blob: 283e43193e208235c37cdceacc365570f108e2dc [file] [log] [blame]
Jeremy Hayesb707aa52015-06-18 10:12:39 -06001/*
2 * Vulkan
3 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <iostream>
30#include <string>
31#include <sstream>
32#include <unordered_map>
Tobin Ehlis65380532015-09-21 15:20:28 -060033#include <memory>
Courtney Goeltzenleuchter9fac1572015-10-05 15:59:11 -060034#include <vector>
Jeremy Hayesb707aa52015-06-18 10:12:39 -060035
Tobin Ehlis65380532015-09-21 15:20:28 -060036#include "image.h"
Tobin Ehlis7a51d902015-07-03 10:34:49 -060037#include "vk_loader_platform.h"
Tobin Ehlis2d1d9702015-07-03 09:42:57 -060038#include "vk_layer.h"
Jeremy Hayesb707aa52015-06-18 10:12:39 -060039#include "vk_enum_validate_helper.h"
40#include "vk_struct_validate_helper.h"
41//The following is #included again to catch certain OS-specific functions being used:
Tobin Ehlis7a51d902015-07-03 10:34:49 -060042#include "vk_loader_platform.h"
Jeremy Hayesb707aa52015-06-18 10:12:39 -060043
Tobin Ehlis56d204a2015-07-03 10:15:26 -060044#include "vk_layer_table.h"
45#include "vk_layer_data.h"
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -060046#include "vk_layer_extension_utils.h"
Mike Stroyan43909d82015-09-25 13:39:21 -060047#include "vk_layer_utils.h"
Jeremy Hayesb707aa52015-06-18 10:12:39 -060048
Tobin Ehlis65380532015-09-21 15:20:28 -060049using namespace std;
50
Cody Northrop73bb6572015-09-28 15:09:32 -060051struct layer_data {
Jeremy Hayesb707aa52015-06-18 10:12:39 -060052 debug_report_data *report_data;
Courtney Goeltzenleuchter9fac1572015-10-05 15:59:11 -060053 std::vector<VkDbgMsgCallback> logging_callback;
Chris Forbesd7576302015-06-21 22:55:02 +120054 VkPhysicalDevice physicalDevice;
Tobin Ehlis342b9bf2015-09-22 10:11:37 -060055 unordered_map<uint64_t, unique_ptr<IMAGE_STATE>> imageMap;
Cody Northrop73bb6572015-09-28 15:09:32 -060056
57 layer_data() :
58 report_data(nullptr),
Cody Northrop73bb6572015-09-28 15:09:32 -060059 physicalDevice(0)
60 {};
61};
Jeremy Hayesb707aa52015-06-18 10:12:39 -060062
Tobin Ehlis65380532015-09-21 15:20:28 -060063static unordered_map<void*, layer_data*> layer_data_map;
Jeremy Hayesb707aa52015-06-18 10:12:39 -060064static device_table_map image_device_table_map;
65static instance_table_map image_instance_table_map;
66
67// "my device data"
Tony Barbour2a199c12015-07-09 17:31:46 -060068debug_report_data *mdd(const void* object)
Jeremy Hayesb707aa52015-06-18 10:12:39 -060069{
70 dispatch_key key = get_dispatch_key(object);
71 layer_data *data = get_my_data_ptr(key, layer_data_map);
72#if DISPATCH_MAP_DEBUG
73 fprintf(stderr, "MDD: map: %p, object: %p, key: %p, data: %p\n", &layer_data_map, object, key, data);
74#endif
Jeremy Hayesb707aa52015-06-18 10:12:39 -060075 return data->report_data;
76}
77
78// "my instance data"
79debug_report_data *mid(VkInstance object)
80{
81 dispatch_key key = get_dispatch_key(object);
Courtney Goeltzenleuchter07199212015-06-22 16:19:14 -060082 layer_data *data = get_my_data_ptr(key, layer_data_map);
Jeremy Hayesb707aa52015-06-18 10:12:39 -060083#if DISPATCH_MAP_DEBUG
84 fprintf(stderr, "MID: map: %p, object: %p, key: %p, data: %p\n", &layer_data_map, object, key, data);
85#endif
Jeremy Hayesb707aa52015-06-18 10:12:39 -060086 return data->report_data;
87}
88
89static void InitImage(layer_data *data)
90{
Courtney Goeltzenleuchter9fac1572015-10-05 15:59:11 -060091 VkDbgMsgCallback callback;
Jeremy Hayesb707aa52015-06-18 10:12:39 -060092 uint32_t report_flags = getLayerOptionFlags("ImageReportFlags", 0);
93
94 uint32_t debug_action = 0;
95 getLayerOptionEnum("ImageDebugAction", (uint32_t *) &debug_action);
96 if(debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
97 {
98 FILE *log_output = NULL;
99 const char* option_str = getLayerOption("ImageLogFilename");
Tobin Ehlisb4b6e7c2015-09-15 09:55:54 -0600100 log_output = getLayerLogOutput(option_str, "Image");
Courtney Goeltzenleuchter9fac1572015-10-05 15:59:11 -0600101 layer_create_msg_callback(data->report_data, report_flags, log_callback, (void *) log_output, &callback);
102 data->logging_callback.push_back(callback);
103 }
104
105 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
106 layer_create_msg_callback(data->report_data, report_flags, win32_debug_output_msg, NULL, &callback);
107 data->logging_callback.push_back(callback);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600108 }
109}
110
111VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(
112 VkInstance instance,
113 VkFlags msgFlags,
114 const PFN_vkDbgMsgCallback pfnMsgCallback,
115 void* pUserData,
116 VkDbgMsgCallback* pMsgCallback)
117{
118 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, instance);
119 VkResult res = pTable->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
120 if (res == VK_SUCCESS) {
121 layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
122
123 res = layer_create_msg_callback(data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
124 }
125 return res;
126}
127
128VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(
129 VkInstance instance,
130 VkDbgMsgCallback msgCallback)
131{
132 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, instance);
133 VkResult res = pTable->DbgDestroyMsgCallback(instance, msgCallback);
134
135 layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
136 layer_destroy_msg_callback(data->report_data, msgCallback);
137
138 return res;
139}
140
141VK_LAYER_EXPORT VkResult VKAPI vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance)
142{
143 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, *pInstance);
144 VkResult result = pTable->CreateInstance(pCreateInfo, pInstance);
145
146 if (result == VK_SUCCESS) {
147 layer_data *data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
148 data->report_data = debug_report_create_instance(pTable, *pInstance, pCreateInfo->extensionCount,
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -0600149 pCreateInfo->ppEnabledExtensionNames);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600150
151 InitImage(data);
152 }
153
154 return result;
155}
156
Mark Lobodzinski67b42b72015-09-07 13:59:43 -0600157VK_LAYER_EXPORT void VKAPI vkDestroyInstance(VkInstance instance)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600158{
159 // Grab the key before the instance is destroyed.
160 dispatch_key key = get_dispatch_key(instance);
161 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, instance);
Mark Lobodzinski67b42b72015-09-07 13:59:43 -0600162 pTable->DestroyInstance(instance);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600163
164 // Clean up logging callback, if any
Courtney Goeltzenleuchter9fac1572015-10-05 15:59:11 -0600165 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
166 while (my_data->logging_callback.size() > 0) {
167 VkDbgMsgCallback callback = my_data->logging_callback.back();
168 layer_destroy_msg_callback(my_data->report_data, callback);
169 my_data->logging_callback.pop_back();
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600170 }
171
172 layer_debug_report_destroy_instance(mid(instance));
173 layer_data_map.erase(pTable);
174
175 image_instance_table_map.erase(key);
176 assert(image_instance_table_map.size() == 0 && "Should not have any instance mappings hanging around");
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600177}
178
179VK_LAYER_EXPORT VkResult VKAPI vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice* pDevice)
180{
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -0600181 VkLayerDispatchTable *pTable = get_dispatch_table(image_device_table_map, *pDevice);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600182 VkResult result = pTable->CreateDevice(physicalDevice, pCreateInfo, pDevice);
183 if(result == VK_SUCCESS)
184 {
185 layer_data *instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
186 layer_data *device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
187 device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice);
Chris Forbesd7576302015-06-21 22:55:02 +1200188 device_data->physicalDevice = physicalDevice;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600189 }
190
191 return result;
192}
193
Mark Lobodzinski67b42b72015-09-07 13:59:43 -0600194VK_LAYER_EXPORT void VKAPI vkDestroyDevice(VkDevice device)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600195{
196 layer_debug_report_destroy_device(device);
197
198 dispatch_key key = get_dispatch_key(device);
199#if DISPATCH_MAP_DEBUG
200 fprintf(stderr, "Device: %p, key: %p\n", device, key);
201#endif
202
Mark Lobodzinski67b42b72015-09-07 13:59:43 -0600203 get_dispatch_table(image_device_table_map, device)->DestroyDevice(device);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600204 image_device_table_map.erase(key);
205 assert(image_device_table_map.size() == 0 && "Should not have any instance mappings hanging around");
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600206}
207
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -0600208static const VkLayerProperties pc_global_layers[] = {
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600209 {
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600210 "Image",
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -0600211 VK_API_VERSION,
212 VK_MAKE_VERSION(0, 1, 0),
213 "Validation layer: Image ParamChecker",
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600214 }
215};
216
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600217VK_LAYER_EXPORT VkResult VKAPI vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -0600218 const char *pLayerName,
219 uint32_t *pCount,
220 VkExtensionProperties* pProperties)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600221{
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -0600222 /* ParamChecker does not have any global extensions */
223 return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600224}
225
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600226VK_LAYER_EXPORT VkResult VKAPI vkEnumerateInstanceLayerProperties(
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -0600227 uint32_t *pCount,
228 VkLayerProperties* pProperties)
Tony Barbour426b9052015-06-24 16:06:58 -0600229{
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -0600230 return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers),
231 pc_global_layers,
232 pCount, pProperties);
Tony Barbour426b9052015-06-24 16:06:58 -0600233}
234
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600235VK_LAYER_EXPORT VkResult VKAPI vkEnumerateDeviceExtensionProperties(
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -0600236 VkPhysicalDevice physicalDevice,
237 const char* pLayerName,
238 uint32_t* pCount,
239 VkExtensionProperties* pProperties)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600240{
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -0600241 /* ParamChecker does not have any physical device extensions */
242 return util_GetExtensionProperties(0, NULL, pCount, pProperties);
243}
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600244
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600245VK_LAYER_EXPORT VkResult VKAPI vkEnumerateDeviceLayerProperties(
Courtney Goeltzenleuchtereb1ddb02015-07-07 11:18:30 -0600246 VkPhysicalDevice physicalDevice,
247 uint32_t* pCount,
248 VkLayerProperties* pProperties)
249{
250 /* ParamChecker's physical device layers are the same as global */
251 return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers), pc_global_layers,
252 pCount, pProperties);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600253}
254
Mark Lobodzinski9cce7832015-07-29 09:21:22 -0600255// Start of the Image layer proper
256
257// Returns TRUE if a format is a depth-compatible format
258bool is_depth_format(VkFormat format)
259{
260 bool result = VK_FALSE;
261 switch (format) {
262 case VK_FORMAT_D16_UNORM:
Courtney Goeltzenleuchter7ed10592015-09-10 17:17:43 -0600263 case VK_FORMAT_D24_UNORM_X8:
Mark Lobodzinski9cce7832015-07-29 09:21:22 -0600264 case VK_FORMAT_D32_SFLOAT:
265 case VK_FORMAT_S8_UINT:
266 case VK_FORMAT_D16_UNORM_S8_UINT:
267 case VK_FORMAT_D24_UNORM_S8_UINT:
268 case VK_FORMAT_D32_SFLOAT_S8_UINT:
269 result = VK_TRUE;
270 break;
271 default:
272 break;
273 }
274 return result;
275}
276
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600277VK_LAYER_EXPORT VkResult VKAPI vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, VkImage* pImage)
278{
Tobin Ehlis35613802015-09-22 08:40:52 -0600279 VkBool32 skipCall = VK_FALSE;
Tobin Ehlis65380532015-09-21 15:20:28 -0600280 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600281 if(pCreateInfo->format != VK_FORMAT_UNDEFINED)
282 {
283 VkFormatProperties properties;
Courtney Goeltzenleuchterab36aa62015-07-12 12:40:29 -0600284 VkResult result = get_dispatch_table(image_instance_table_map, device_data->physicalDevice)->GetPhysicalDeviceFormatProperties(
Chris Forbesd7576302015-06-21 22:55:02 +1200285 device_data->physicalDevice, pCreateInfo->format, &properties);
Tobin Ehlis65380532015-09-21 15:20:28 -0600286 if(result != VK_SUCCESS) {
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600287 char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, cannot be validated";
Tobin Ehlis35613802015-09-22 08:40:52 -0600288 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_WARN_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_FORMAT_UNSUPPORTED, "IMAGE", str);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600289 }
290
291 if((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
292 {
293 char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, contains unsupported format";
Tobin Ehlis35613802015-09-22 08:40:52 -0600294 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_WARN_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_FORMAT_UNSUPPORTED, "IMAGE", str);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600295 }
296 }
Tobin Ehlis35613802015-09-22 08:40:52 -0600297 if (skipCall)
298 return VK_ERROR_VALIDATION_FAILED;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600299
300 VkResult result = get_dispatch_table(image_device_table_map, device)->CreateImage(device, pCreateInfo, pImage);
301
Tobin Ehlis65380532015-09-21 15:20:28 -0600302 if(result == VK_SUCCESS) {
Tobin Ehlis342b9bf2015-09-22 10:11:37 -0600303 device_data->imageMap[pImage->handle] = unique_ptr<IMAGE_STATE>(new IMAGE_STATE(pCreateInfo));
Tobin Ehlis65380532015-09-21 15:20:28 -0600304 }
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600305 return result;
306}
307
Tobin Ehlis65380532015-09-21 15:20:28 -0600308VK_LAYER_EXPORT void VKAPI vkDestroyImage(VkDevice device, VkImage image)
309{
310 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
311 device_data->imageMap.erase(image.handle);
312 get_dispatch_table(image_device_table_map, device)->DestroyImage(device, image);
313}
314
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600315VK_LAYER_EXPORT VkResult VKAPI vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, VkRenderPass* pRenderPass)
316{
Tobin Ehlis35613802015-09-22 08:40:52 -0600317 VkBool32 skipCall = VK_FALSE;
Chia-I Wuc278df82015-07-07 11:50:03 +0800318 for(uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600319 {
Chia-I Wuc278df82015-07-07 11:50:03 +0800320 if(pCreateInfo->pAttachments[i].format != VK_FORMAT_UNDEFINED)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600321 {
Courtney Goeltzenleuchter07199212015-06-22 16:19:14 -0600322 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600323 VkFormatProperties properties;
Courtney Goeltzenleuchterab36aa62015-07-12 12:40:29 -0600324 VkResult result = get_dispatch_table(image_instance_table_map, device_data->physicalDevice)->GetPhysicalDeviceFormatProperties(
Chia-I Wuc278df82015-07-07 11:50:03 +0800325 device_data->physicalDevice, pCreateInfo->pAttachments[i].format, &properties);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600326 if(result != VK_SUCCESS)
327 {
328 std::stringstream ss;
Chia-I Wuc278df82015-07-07 11:50:03 +0800329 ss << "vkCreateRenderPass parameter, VkFormat in pCreateInfo->pAttachments[" << i << "], cannot be validated";
Tobin Ehlis35613802015-09-22 08:40:52 -0600330 skipCall |= log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_FORMAT_UNSUPPORTED, "IMAGE", ss.str().c_str());
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600331 continue;
332 }
333
334 if((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
335 {
336 std::stringstream ss;
Chia-I Wuc278df82015-07-07 11:50:03 +0800337 ss << "vkCreateRenderPass parameter, VkFormat in pCreateInfo->pAttachments[" << i << "], contains unsupported format";
Tobin Ehlis35613802015-09-22 08:40:52 -0600338 skipCall |= log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_FORMAT_UNSUPPORTED, "IMAGE", ss.str().c_str());
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600339 }
340 }
341 }
342
Chia-I Wuc278df82015-07-07 11:50:03 +0800343 for(uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600344 {
Chia-I Wuc278df82015-07-07 11:50:03 +0800345 if(!validate_VkImageLayout(pCreateInfo->pAttachments[i].initialLayout) ||
346 !validate_VkImageLayout(pCreateInfo->pAttachments[i].finalLayout))
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600347 {
348 std::stringstream ss;
Chia-I Wuc278df82015-07-07 11:50:03 +0800349 ss << "vkCreateRenderPass parameter, VkImageLayout in pCreateInfo->pAttachments[" << i << "], is unrecognized";
Tobin Ehlis35613802015-09-22 08:40:52 -0600350 skipCall |= log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", ss.str().c_str());
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600351 }
352 }
353
Chia-I Wuc278df82015-07-07 11:50:03 +0800354 for(uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600355 {
Chia-I Wuc278df82015-07-07 11:50:03 +0800356 if(!validate_VkAttachmentLoadOp(pCreateInfo->pAttachments[i].loadOp))
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600357 {
358 std::stringstream ss;
Chia-I Wuc278df82015-07-07 11:50:03 +0800359 ss << "vkCreateRenderPass parameter, VkAttachmentLoadOp in pCreateInfo->pAttachments[" << i << "], is unrecognized";
Tobin Ehlis35613802015-09-22 08:40:52 -0600360 skipCall |= log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", ss.str().c_str());
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600361 }
362 }
363
Chia-I Wuc278df82015-07-07 11:50:03 +0800364 for(uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600365 {
Chia-I Wuc278df82015-07-07 11:50:03 +0800366 if(!validate_VkAttachmentStoreOp(pCreateInfo->pAttachments[i].storeOp))
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600367 {
368 std::stringstream ss;
Chia-I Wuc278df82015-07-07 11:50:03 +0800369 ss << "vkCreateRenderPass parameter, VkAttachmentStoreOp in pCreateInfo->pAttachments[" << i << "], is unrecognized";
Tobin Ehlis35613802015-09-22 08:40:52 -0600370 skipCall |= log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", ss.str().c_str());
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600371 }
372 }
373
Mark Lobodzinski9cce7832015-07-29 09:21:22 -0600374 // Any depth buffers specified as attachments?
375 bool depthFormatPresent = VK_FALSE;
376 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
377 {
378 depthFormatPresent |= is_depth_format(pCreateInfo->pAttachments[i].format);
379 }
380
381 if (depthFormatPresent == VK_FALSE) {
382 // No depth attachment is present, validate that subpasses set depthStencilAttachment to VK_ATTACHMENT_UNUSED;
383 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
384 if (pCreateInfo->pSubpasses[i].depthStencilAttachment.attachment != VK_ATTACHMENT_UNUSED) {
385 std::stringstream ss;
386 ss << "vkCreateRenderPass has no depth/stencil attachment, yet subpass[" << i << "] has VkSubpassDescription::depthStencilAttachment value that is not VK_ATTACHMENT_UNUSED";
Tobin Ehlis35613802015-09-22 08:40:52 -0600387 skipCall |= log_msg(mdd(device), VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_RENDERPASS_INVALID_DS_ATTACHMENT, "IMAGE", ss.str().c_str());
Mark Lobodzinski9cce7832015-07-29 09:21:22 -0600388 }
389 }
390 }
Tobin Ehlis35613802015-09-22 08:40:52 -0600391 if (skipCall)
392 return VK_ERROR_VALIDATION_FAILED;
Mark Lobodzinski9cce7832015-07-29 09:21:22 -0600393
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600394 VkResult result = get_dispatch_table(image_device_table_map, device)->CreateRenderPass(device, pCreateInfo, pRenderPass);
395
396 return result;
397}
398
Tobin Ehlis65380532015-09-21 15:20:28 -0600399VK_LAYER_EXPORT VkResult VKAPI vkCreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, VkImageView* pView)
400{
401 VkBool32 skipCall = VK_FALSE;
402 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
403 auto imageEntry = device_data->imageMap.find(pCreateInfo->image.handle);
404 if (imageEntry != device_data->imageMap.end()) {
405 if (pCreateInfo->subresourceRange.baseMipLevel >= imageEntry->second->mipLevels) {
406 std::stringstream ss;
407 ss << "vkCreateImageView called with baseMipLevel " << pCreateInfo->subresourceRange.baseMipLevel << " for image " << pCreateInfo->image.handle << " that only has " << imageEntry->second->mipLevels << " mip levels.";
408 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_VIEW_CREATE_ERROR, "IMAGE", ss.str().c_str());
409 }
410 if (pCreateInfo->subresourceRange.baseArrayLayer >= imageEntry->second->arraySize) {
411 std::stringstream ss;
412 ss << "vkCreateImageView called with baseArrayLayer " << pCreateInfo->subresourceRange.baseArrayLayer << " for image " << pCreateInfo->image.handle << " that only has " << imageEntry->second->arraySize << " mip levels.";
413 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_VIEW_CREATE_ERROR, "IMAGE", ss.str().c_str());
414 }
415 if (!pCreateInfo->subresourceRange.mipLevels) {
416 std::stringstream ss;
417 ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.mipLevels.";
418 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_VIEW_CREATE_ERROR, "IMAGE", ss.str().c_str());
419 }
420 if (!pCreateInfo->subresourceRange.arraySize) {
421 std::stringstream ss;
422 ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.arraySize.";
423 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, (VkDbgObjectType)0, 0, 0, IMAGE_VIEW_CREATE_ERROR, "IMAGE", ss.str().c_str());
424 }
425 }
Mark Lobodzinski6f3403c2015-10-05 17:16:05 -0600426
427 // TODO: Image aspect mask must be only VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT
428 // if the format is a color, depth-only or stencil-only format respectively. If using a depth/stencil format,
429 // aspectMask must include at least one of VK_IMAGE_ASPECT_DEPTH_BIT and VK_IMAGE_ASPECT_STENCIL_BIT, and may include both.
430 // Add after image/buffer state tracking is implemented.
431
Tobin Ehlis65380532015-09-21 15:20:28 -0600432 if (skipCall)
433 return VK_ERROR_VALIDATION_FAILED;
Tobin Ehlis35613802015-09-22 08:40:52 -0600434
Tobin Ehlis65380532015-09-21 15:20:28 -0600435 VkResult result = get_dispatch_table(image_device_table_map, device)->CreateImageView(device, pCreateInfo, pView);
436 return result;
437}
438
Mark Lobodzinski6f3403c2015-10-05 17:16:05 -0600439VK_LAYER_EXPORT void VKAPI vkCmdClearColorImage(
440 VkCmdBuffer cmdBuffer,
441 VkImage image,
442 VkImageLayout imageLayout,
443 const VkClearColorValue *pColor,
444 uint32_t rangeCount,
445 const VkImageSubresourceRange *pRanges)
446{
447 VkBool32 skipCall = VK_FALSE;
448
449 // For each range, image aspect must be color only
450 for (uint32_t i = 0; i < rangeCount; i++) {
451 if (pRanges[i].aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
452 layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
453 char const str[] = "vkCmdClearColorImage aspectMasks for all subresource ranges must be set to VK_IMAGE_ASPECT_COLOR_BIT";
454 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
455 (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
456 }
457 }
458
459 if (VK_FALSE == skipCall) {
460 get_dispatch_table(image_device_table_map, cmdBuffer)->CmdClearColorImage(cmdBuffer, image, imageLayout,
461 pColor, rangeCount, pRanges);
462 }
463}
464
465VK_LAYER_EXPORT void VKAPI vkCmdClearDepthStencilImage(
466 VkCmdBuffer cmdBuffer,
467 VkImage image,
468 VkImageLayout imageLayout,
469 const VkClearDepthStencilValue *pDepthStencil,
470 uint32_t rangeCount,
471 const VkImageSubresourceRange *pRanges)
472{
473 VkBool32 skipCall = VK_FALSE;
474
475 // For each range, Image aspect must be depth or stencil or both
476 for (uint32_t i = 0; i < rangeCount; i++) {
477 if (((pRanges[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
478 ((pRanges[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT))
479 {
480 layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
481 char const str[] = "vkCmdClearDepthStencilImage aspectMasks for all subresource ranges must be "
482 "set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
483 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
484 (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
485 }
486 }
487
488 if (VK_FALSE == skipCall) {
489 get_dispatch_table(image_device_table_map, cmdBuffer)->CmdClearDepthStencilImage(cmdBuffer,
490 image, imageLayout, pDepthStencil, rangeCount, pRanges);
491 }
492}
493
494VK_LAYER_EXPORT void VKAPI vkCmdClearDepthStencilAttachment(
495 VkCmdBuffer cmdBuffer,
496 VkImageAspectFlags imageAspectMask,
497 VkImageLayout imageLayout,
498 const VkClearDepthStencilValue *pDepthStencil,
499 uint32_t rectCount,
500 const VkRect3D *pRects)
501{
502 VkBool32 skipCall = VK_FALSE;
503
504 // Image aspect must be depth or stencil or both
505 if (((imageAspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
506 ((imageAspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT))
507 {
508 layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
509 char const str[] = "vkCmdClearDepthStencilAttachment aspectMask must be set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
510 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
511 (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
512 }
513
514 if (VK_FALSE == skipCall) {
515 get_dispatch_table(image_device_table_map, cmdBuffer)->CmdClearDepthStencilAttachment(cmdBuffer,
516 imageAspectMask, imageLayout, pDepthStencil, rectCount, pRects);
517 }
518}
519
520VK_LAYER_EXPORT void VKAPI vkCmdCopyImage(
521 VkCmdBuffer cmdBuffer,
522 VkImage srcImage,
523 VkImageLayout srcImageLayout,
524 VkImage destImage,
525 VkImageLayout destImageLayout,
526 uint32_t regionCount,
527 const VkImageCopy *pRegions)
528{
529 VkBool32 skipCall = VK_FALSE;
Mike Stroyan43909d82015-09-25 13:39:21 -0600530 layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
531 auto srcImageEntry = device_data->imageMap.find(srcImage.handle);
532 auto destImageEntry = device_data->imageMap.find(destImage.handle);
Mark Lobodzinski6f3403c2015-10-05 17:16:05 -0600533
534 // For each region, src aspect mask must match dest aspect mask
535 // For each region, color aspects cannot be mixed with depth/stencil aspects
536 for (uint32_t i = 0; i < regionCount; i++) {
537 if (pRegions[i].srcSubresource.aspect != pRegions[i].destSubresource.aspect) {
Mark Lobodzinski6f3403c2015-10-05 17:16:05 -0600538 char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match";
539 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
540 (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
541 }
542 if ((pRegions[i].srcSubresource.aspect & VK_IMAGE_ASPECT_COLOR) &&
543 (pRegions[i].srcSubresource.aspect & (VK_IMAGE_ASPECT_DEPTH | VK_IMAGE_ASPECT_STENCIL))) {
Mark Lobodzinski6f3403c2015-10-05 17:16:05 -0600544 char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects";
545 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
546 (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
547 }
548 }
549
Mike Stroyan43909d82015-09-25 13:39:21 -0600550 if ((srcImageEntry != device_data->imageMap.end())
551 && (destImageEntry != device_data->imageMap.end())) {
552 if (srcImageEntry->second->imageType != destImageEntry->second->imageType) {
553 char const str[] = "vkCmdCopyImage called with unmatched source and dest image types.";
554 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
555 (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str);
556 }
557 // Check that format is same size or exact stencil/depth
558 if (is_depth_format(srcImageEntry->second->format)) {
559 if (srcImageEntry->second->format != destImageEntry->second->format) {
560 char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats.";
561 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
562 (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
563 }
564 } else {
565 size_t srcSize = vk_format_get_size(srcImageEntry->second->format);
566 size_t destSize = vk_format_get_size(destImageEntry->second->format);
567 if (srcSize != destSize) {
568 char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes.";
569 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
570 (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
571 }
572 }
573 }
574
Mark Lobodzinski6f3403c2015-10-05 17:16:05 -0600575 if (VK_FALSE == skipCall) {
576 get_dispatch_table(image_device_table_map, cmdBuffer)->CmdCopyImage(cmdBuffer, srcImage,
577 srcImageLayout, destImage, destImageLayout, regionCount, pRegions);
578 }
579}
580
581VK_LAYER_EXPORT void VKAPI vkCmdCopyImageToBuffer(
582 VkCmdBuffer cmdBuffer,
583 VkImage srcImage,
584 VkImageLayout srcImageLayout,
585 VkBuffer destBuffer,
586 uint32_t regionCount,
587 const VkBufferImageCopy *pRegions)
588{
589 VkBool32 skipCall = VK_FALSE;
590
591 // Image aspect must be ONE OF color, depth, stencil
592 for (uint32_t i = 0; i < regionCount; i++) {
593 VkImageAspect aspect = pRegions[i].imageSubresource.aspect;
594 if ((aspect != VK_IMAGE_ASPECT_COLOR) &&
595 (aspect != VK_IMAGE_ASPECT_DEPTH) &&
596 (aspect != VK_IMAGE_ASPECT_STENCIL)) {
597 layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
598 char const str[] = "vkCmdCopyImageToBuffer: aspectMasks for each region must specify only COLOR or DEPTH or STENCIL";
599 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
600 (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
601 }
602 }
603
604 if (VK_FALSE == skipCall) {
605 get_dispatch_table(image_device_table_map, cmdBuffer)->CmdCopyImageToBuffer(cmdBuffer,
606 srcImage, srcImageLayout, destBuffer, regionCount, pRegions);
607 }
608}
609
610
611VK_LAYER_EXPORT void VKAPI vkCmdCopyBufferToImage(
612 VkCmdBuffer cmdBuffer,
613 VkBuffer srcBuffer,
614 VkImage destImage,
615 VkImageLayout destImageLayout,
616 uint32_t regionCount,
617 const VkBufferImageCopy *pRegions)
618{
619 VkBool32 skipCall = VK_FALSE;
620
621 // Image aspect must be ONE OF color, depth, stencil
622 for (uint32_t i = 0; i < regionCount; i++) {
623 VkImageAspect aspect = pRegions[i].imageSubresource.aspect;
624 if ((aspect != VK_IMAGE_ASPECT_COLOR) &&
625 (aspect != VK_IMAGE_ASPECT_DEPTH) &&
626 (aspect != VK_IMAGE_ASPECT_STENCIL)) {
627 layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
628 char const str[] = "vkCmdCopyBufferToImage: aspectMasks for each region must specify only COLOR or DEPTH or STENCIL";
629 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
630 (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
631 }
632 }
633
634 if (VK_FALSE == skipCall) {
635 get_dispatch_table(image_device_table_map, cmdBuffer)->CmdCopyBufferToImage(cmdBuffer,
636 srcBuffer, destImage, destImageLayout, regionCount, pRegions);
637 }
638}
639
640VK_LAYER_EXPORT void VKAPI vkCmdBlitImage(
641 VkCmdBuffer cmdBuffer,
642 VkImage srcImage,
643 VkImageLayout srcImageLayout,
644 VkImage destImage,
645 VkImageLayout destImageLayout,
646 uint32_t regionCount,
647 const VkImageBlit *pRegions,
648 VkTexFilter filter)
649{
650 // TODO: From the spec -- these validation items will require the image layer to maintain image/buffer state.
651 // If one of srcImage and destImage images has signed integer format, the other one must also have be signed integer format.
652 // If one of srcImage and destImage images has unsigned integer format, the other one must also have be an unsigned integer format.
653 // If the format of srcImage is a depth, stencil, depth stencil or integer-based format then filter must be VK_TEX_FILTER_NEAREST.
654 // If one of srcImage and destImage images has a format of depth, stencil or depth stencil, the other one must have exactly the same format.
655 // Additionally the allowed aspect bits in srcSubresource and destSubresource are only VK_IMAGE_ASPECT_DEPTH_BIT and
656 // VK_IMAGE_ASPECT_STENCIL_BIT and the given aspect must exist in the format of both srcImage and destImage images.
657
658 get_dispatch_table(image_device_table_map, cmdBuffer)->CmdBlitImage(cmdBuffer, srcImage,
659 srcImageLayout, destImage, destImageLayout, regionCount, pRegions, filter);
660}
661
662VK_LAYER_EXPORT void VKAPI vkCmdResolveImage(
663 VkCmdBuffer cmdBuffer,
664 VkImage srcImage,
665 VkImageLayout srcImageLayout,
666 VkImage destImage,
667 VkImageLayout destImageLayout,
668 uint32_t regionCount,
669 const VkImageResolve *pRegions)
670{
671 VkBool32 skipCall = VK_FALSE;
Mike Stroyan43909d82015-09-25 13:39:21 -0600672 layer_data *device_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
673 auto srcImageEntry = device_data->imageMap.find(srcImage.handle);
674 auto destImageEntry = device_data->imageMap.find(destImage.handle);
Mark Lobodzinski6f3403c2015-10-05 17:16:05 -0600675
676 // For each region, src and dest image aspect must be color only
677 for (uint32_t i = 0; i < regionCount; i++) {
678 if ((pRegions[i].srcSubresource.aspect != VK_IMAGE_ASPECT_COLOR) ||
679 (pRegions[i].destSubresource.aspect != VK_IMAGE_ASPECT_COLOR)) {
Mark Lobodzinski6f3403c2015-10-05 17:16:05 -0600680 char const str[] = "vkCmdResolveImage: src and dest aspectMasks for each region must specify only VK_IMAGE_ASPECT_COLOR_BIT";
681 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
682 (uint64_t)cmdBuffer, 0, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
683 }
684 }
685
Mike Stroyan43909d82015-09-25 13:39:21 -0600686 if ((srcImageEntry != device_data->imageMap.end())
687 && (destImageEntry != device_data->imageMap.end())) {
688 if (srcImageEntry->second->format != destImageEntry->second->format) {
689 char const str[] = "vkCmdResolveImage called with unmatched source and dest formats.";
690 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
691 (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
692 }
693 if (srcImageEntry->second->imageType != destImageEntry->second->imageType) {
694 char const str[] = "vkCmdResolveImage called with unmatched source and dest image types.";
695 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
696 (uint64_t)cmdBuffer, 0, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str);
697 }
698 if (srcImageEntry->second->samples <= 1) {
699 char const str[] = "vkCmdResolveImage called with source sample count less than 2.";
700 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
701 (uint64_t)cmdBuffer, 0, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
702 }
703 if (destImageEntry->second->samples > 1) {
704 char const str[] = "vkCmdResolveImage called with dest sample count greater than 1.";
705 skipCall |= log_msg(device_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER,
706 (uint64_t)cmdBuffer, 0, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
707 }
708 }
709
Mark Lobodzinski6f3403c2015-10-05 17:16:05 -0600710 if (VK_FALSE == skipCall) {
711 get_dispatch_table(image_device_table_map, cmdBuffer)->CmdResolveImage(cmdBuffer, srcImage,
712 srcImageLayout, destImage, destImageLayout, regionCount, pRegions);
713 }
714}
715
716VK_LAYER_EXPORT VkResult VKAPI vkGetImageSubresourceLayout(
717 VkDevice device,
718 VkImage image,
719 const VkImageSubresource *pSubresource,
720 VkSubresourceLayout *pLayout)
721{
722 VkResult result = get_dispatch_table(image_device_table_map, device)->GetImageSubresourceLayout(device,
723 image, pSubresource, pLayout);
724
725 // TODO: After state tracking for images/buffers is implemented, validate that returned aspects match
726 // the created formats -- color for color formats, depth|stencil for ds formats
727
728 return result;
729}
730
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600731VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600732{
733 if (device == NULL) {
734 return NULL;
735 }
736
737 /* loader uses this to force layer initialization; device object is wrapped */
738 if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
739 initDeviceTable(image_device_table_map, (const VkBaseLayerObject *) device);
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600740 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600741 }
742
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -0600743 if (!strcmp(funcName, "vkCreateDevice"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600744 return (PFN_vkVoidFunction) vkCreateDevice;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600745 if (!strcmp(funcName, "vkDestroyDevice"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600746 return (PFN_vkVoidFunction) vkDestroyDevice;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600747 if (!strcmp(funcName, "vkCreateImage"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600748 return (PFN_vkVoidFunction) vkCreateImage;
Tobin Ehlis342b9bf2015-09-22 10:11:37 -0600749 if (!strcmp(funcName, "vkCreateImageView"))
750 return (PFN_vkVoidFunction) vkCreateImageView;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600751 if (!strcmp(funcName, "vkCreateRenderPass"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600752 return (PFN_vkVoidFunction) vkCreateRenderPass;
Mark Lobodzinski6f3403c2015-10-05 17:16:05 -0600753 if (!strcmp(funcName, "vkCmdClearColorImage"))
754 return (PFN_vkVoidFunction) vkCmdClearColorImage;
755 if (!strcmp(funcName, "vkCmdClearDepthStencilImage"))
756 return (PFN_vkVoidFunction) vkCmdClearDepthStencilImage;
757 if (!strcmp(funcName, "vkCmdClearDepthStencilAttachment"))
758 return (PFN_vkVoidFunction) vkCmdClearDepthStencilAttachment;
759 if (!strcmp(funcName, "vkCmdCopyImage"))
760 return (PFN_vkVoidFunction) vkCmdCopyImage;
761 if (!strcmp(funcName, "vkCmdCopyImageToBuffer"))
762 return (PFN_vkVoidFunction) vkCmdCopyImageToBuffer;
763 if (!strcmp(funcName, "vkCmdCopyBufferToImage"))
764 return (PFN_vkVoidFunction) vkCmdCopyBufferToImage;
765 if (!strcmp(funcName, "vkCmdBlitImage"))
766 return (PFN_vkVoidFunction) vkCmdBlitImage;
767 if (!strcmp(funcName, "vkCmdResolveImage"))
768 return (PFN_vkVoidFunction) vkCmdResolveImage;
769 if (!strcmp(funcName, "vkGetImageSubresourceLayout"))
770 return (PFN_vkVoidFunction) vkGetImageSubresourceLayout;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600771 {
772 if (get_dispatch_table(image_device_table_map, device)->GetDeviceProcAddr == NULL)
773 return NULL;
774 return get_dispatch_table(image_device_table_map, device)->GetDeviceProcAddr(device, funcName);
775 }
776}
777
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600778VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600779{
780 if (instance == NULL) {
781 return NULL;
782 }
783
784 /* loader uses this to force layer initialization; instance object is wrapped */
785 if (!strcmp(funcName, "vkGetInstanceProcAddr")) {
786 initInstanceTable(image_instance_table_map, (const VkBaseLayerObject *) instance);
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600787 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600788 }
789
790 if (!strcmp(funcName, "vkCreateInstance"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600791 return (PFN_vkVoidFunction) vkCreateInstance;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600792 if (!strcmp(funcName, "vkDestroyInstance"))
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600793 return (PFN_vkVoidFunction) vkDestroyInstance;
Courtney Goeltzenleuchter74c4ce92015-09-14 17:22:16 -0600794 if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
795 return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
796 if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
797 return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties;
798 if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
799 return (PFN_vkVoidFunction) vkEnumerateDeviceLayerProperties;
800 if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
801 return (PFN_vkVoidFunction) vkEnumerateDeviceExtensionProperties;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600802
803 layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchtera4c8c712015-07-12 14:35:22 -0600804 PFN_vkVoidFunction fptr = debug_report_get_instance_proc_addr(data->report_data, funcName);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600805 if(fptr)
806 return fptr;
807
808 {
809 if (get_dispatch_table(image_instance_table_map, instance)->GetInstanceProcAddr == NULL)
810 return NULL;
811 return get_dispatch_table(image_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);
812 }
813}