blob: 107c7dee27fcc911110b5de9ccaca63d082033dd [file] [log] [blame]
David Pinedofb5b5382015-06-18 17:03:14 -06001/*
David Pinedofb5b5382015-06-18 17:03:14 -06002 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06003 * Copyright (C) 2015 Valve Corporation
David Pinedofb5b5382015-06-18 17:03:14 -06004 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060022 *
23 * Author: Cody Northrop <cody@lunarg.com>
24 * Author: David Pinedo <david@lunarg.com>
Jon Ashburn0f1a5332016-01-20 08:52:40 -070025 * Author: Jon Ashburn <jon@lunarg.com>
David Pinedofb5b5382015-06-18 17:03:14 -060026 */
27
28#include <inttypes.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <assert.h>
33#include <unordered_map>
34#include <iostream>
35#include <algorithm>
36#include <list>
37#include <map>
38#include <vector>
39#include <fstream>
40
41using namespace std;
42
Tobin Ehlisb835d1b2015-07-03 10:34:49 -060043#include "vk_loader_platform.h"
David Pinedofb5b5382015-06-18 17:03:14 -060044#include "vk_dispatch_table_helper.h"
45#include "vk_struct_string_helper_cpp.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060046#include "vk_layer_config.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060047#include "vk_layer_table.h"
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -060048#include "vk_layer_extension_utils.h"
David Pinedofb5b5382015-06-18 17:03:14 -060049
David Pinedobcd0e792015-06-19 13:48:18 -060050
51struct devExts {
Ian Elliott1064fe32015-07-06 14:31:32 -060052 bool wsi_enabled;
David Pinedobcd0e792015-06-19 13:48:18 -060053};
54static std::unordered_map<void *, struct devExts> deviceExtMap;
David Pinedofb5b5382015-06-18 17:03:14 -060055static device_table_map screenshot_device_table_map;
Jon Ashburn0f1a5332016-01-20 08:52:40 -070056//TODO convert over to the new interface using locally defiend maps
57//static instance_table_map screenshot_instance_table_map;
David Pinedofb5b5382015-06-18 17:03:14 -060058
59static int globalLockInitialized = 0;
60static loader_platform_thread_mutex globalLock;
61
Cody Northrop49f885c2015-09-01 10:18:45 -060062// unordered map: associates a swap chain with a device, image extent, format, and
David Pinedo8897e192015-07-31 10:56:20 -060063// list of images
David Pinedofb5b5382015-06-18 17:03:14 -060064typedef struct
65{
66 VkDevice device;
67 VkExtent2D imageExtent;
68 VkFormat format;
David Pinedo8897e192015-07-31 10:56:20 -060069 VkImage *imageList;
David Pinedofb5b5382015-06-18 17:03:14 -060070} SwapchainMapStruct;
Chia-I Wue2fc5522015-10-26 20:04:44 +080071static unordered_map<VkSwapchainKHR, SwapchainMapStruct *> swapchainMap;
David Pinedofb5b5382015-06-18 17:03:14 -060072
Cody Northrop49f885c2015-09-01 10:18:45 -060073// unordered map: associates an image with a device, image extent, and format
David Pinedofb5b5382015-06-18 17:03:14 -060074typedef struct
75{
76 VkDevice device;
77 VkExtent2D imageExtent;
78 VkFormat format;
79} ImageMapStruct;
Chia-I Wue2fc5522015-10-26 20:04:44 +080080static unordered_map<VkImage, ImageMapStruct *> imageMap;
David Pinedofb5b5382015-06-18 17:03:14 -060081
Chia-I Wu3432a0c2015-10-27 18:04:07 +080082// unordered map: associates a device with a queue, commandPool, and physical device
David Pinedofb5b5382015-06-18 17:03:14 -060083typedef struct
84{
85 VkQueue queue;
Chia-I Wu3432a0c2015-10-27 18:04:07 +080086 VkCommandPool commandPool;
Cody Northrop49f885c2015-09-01 10:18:45 -060087 VkPhysicalDevice physicalDevice;
David Pinedofb5b5382015-06-18 17:03:14 -060088} DeviceMapStruct;
89static unordered_map<VkDevice, DeviceMapStruct *> deviceMap;
90
Cody Northrop49f885c2015-09-01 10:18:45 -060091// unordered map: associates a physical device with an instance
92typedef struct
93{
94 VkInstance instance;
95} PhysDeviceMapStruct;
96static unordered_map<VkPhysicalDevice, PhysDeviceMapStruct *> physDeviceMap;
97
David Pinedofb5b5382015-06-18 17:03:14 -060098// List of frames to we will get a screenshot of
99static vector<int> screenshotFrames;
100
101// Flag indicating we have queried _VK_SCREENSHOT env var
102static bool screenshotEnvQueried = false;
103
Courtney Goeltzenleuchter1d2f0dd2015-10-22 11:03:31 -0600104static bool memory_type_from_properties(
Cody Northrop49f885c2015-09-01 10:18:45 -0600105 VkPhysicalDeviceMemoryProperties *memory_properties,
106 uint32_t typeBits,
Tony Barbouraf392d02015-10-15 12:42:56 -0600107 VkFlags requirements_mask,
Cody Northrop49f885c2015-09-01 10:18:45 -0600108 uint32_t *typeIndex)
109{
110 // Search memtypes to find first index with those properties
111 for (uint32_t i = 0; i < 32; i++) {
112 if ((typeBits & 1) == 1) {
113 // Type is available, does it match user properties?
Tony Barbouraf392d02015-10-15 12:42:56 -0600114 if ((memory_properties->memoryTypes[i].propertyFlags & requirements_mask) == requirements_mask) {
Cody Northrop49f885c2015-09-01 10:18:45 -0600115 *typeIndex = i;
Courtney Goeltzenleuchter1d2f0dd2015-10-22 11:03:31 -0600116 return true;
Cody Northrop49f885c2015-09-01 10:18:45 -0600117 }
118 }
119 typeBits >>= 1;
120 }
121 // No memory types matched, return failure
Courtney Goeltzenleuchter1d2f0dd2015-10-22 11:03:31 -0600122 return false;
Cody Northrop49f885c2015-09-01 10:18:45 -0600123}
124
David Pinedofb5b5382015-06-18 17:03:14 -0600125static void init_screenshot()
126{
David Pinedofb5b5382015-06-18 17:03:14 -0600127 if (!globalLockInitialized)
128 {
129 // TODO/TBD: Need to delete this mutex sometime. How??? One
130 // suggestion is to call this during vkCreateInstance(), and then we
131 // can clean it up during vkDestroyInstance(). However, that requires
132 // that the layer have per-instance locks. We need to come back and
133 // address this soon.
134 loader_platform_thread_create_mutex(&globalLock);
135 globalLockInitialized = 1;
136 }
137}
138
139static void writePPM( const char *filename, VkImage image1)
140{
141 VkImage image2;
142 VkResult err;
Courtney Goeltzenleuchter1d2f0dd2015-10-22 11:03:31 -0600143 bool pass;
Mark Young93ecb1d2016-01-13 13:47:16 -0700144 uint32_t x, y;
David Pinedofb5b5382015-06-18 17:03:14 -0600145 const char *ptr;
146 VkDeviceMemory mem2;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800147 VkCommandBuffer commandBuffer;
Karl Schultzc643fb42016-01-19 09:56:56 -0700148
149 if (imageMap.empty() || imageMap.find(image1) == imageMap.end())
150 return;
151
Chia-I Wue2fc5522015-10-26 20:04:44 +0800152 VkDevice device = imageMap[image1]->device;
Cody Northrop49f885c2015-09-01 10:18:45 -0600153 VkPhysicalDevice physicalDevice = deviceMap[device]->physicalDevice;
154 VkInstance instance = physDeviceMap[physicalDevice]->instance;
David Pinedofb5b5382015-06-18 17:03:14 -0600155 VkQueue queue = deviceMap[device]->queue;
Jon Ashburnf19916e2016-01-11 13:12:43 -0700156 uint32_t width = imageMap[image1]->imageExtent.width;
157 uint32_t height = imageMap[image1]->imageExtent.height;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800158 VkFormat format = imageMap[image1]->format;
Courtney Goeltzenleuchter908e7672015-10-21 17:00:51 -0600159 const VkImageSubresource sr = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0};
David Pinedofb5b5382015-06-18 17:03:14 -0600160 VkSubresourceLayout sr_layout;
David Pinedofb5b5382015-06-18 17:03:14 -0600161 const VkImageCreateInfo imgCreateInfo = {
162 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
163 NULL,
Chia-I Wu439c0772015-10-26 17:00:46 +0800164 0,
David Pinedofb5b5382015-06-18 17:03:14 -0600165 VK_IMAGE_TYPE_2D,
166 format,
167 {width, height, 1},
168 1,
169 1,
Chia-I Wu5c17c962015-10-31 00:31:16 +0800170 VK_SAMPLE_COUNT_1_BIT,
David Pinedofb5b5382015-06-18 17:03:14 -0600171 VK_IMAGE_TILING_LINEAR,
Karl Schultzc643fb42016-01-19 09:56:56 -0700172 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
173 VK_SHARING_MODE_EXCLUSIVE,
174 0,
175 NULL,
176 VK_IMAGE_LAYOUT_UNDEFINED,
David Pinedofb5b5382015-06-18 17:03:14 -0600177 };
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800178 VkMemoryAllocateInfo memAllocInfo = {
Chia-I Wu00ce5402015-11-10 16:21:09 +0800179 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
David Pinedofb5b5382015-06-18 17:03:14 -0600180 NULL,
181 0, // allocationSize, queried later
Cody Northrop488f5472015-09-01 11:47:50 -0600182 0 // memoryTypeIndex, queried later
David Pinedofb5b5382015-06-18 17:03:14 -0600183 };
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800184 const VkCommandBufferAllocateInfo allocCommandBufferInfo = {
Chia-I Wu00ce5402015-11-10 16:21:09 +0800185 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
David Pinedofb5b5382015-06-18 17:03:14 -0600186 NULL,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800187 deviceMap[device]->commandPool,
188 VK_COMMAND_BUFFER_LEVEL_PRIMARY,
Courtney Goeltzenleuchterbee18a92015-10-23 14:21:05 -0600189 1
David Pinedofb5b5382015-06-18 17:03:14 -0600190 };
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800191 const VkCommandBufferBeginInfo commandBufferBeginInfo = {
192 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
David Pinedofb5b5382015-06-18 17:03:14 -0600193 NULL,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800194 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
David Pinedofb5b5382015-06-18 17:03:14 -0600195 };
196 const VkImageCopy imageCopyRegion = {
Karl Schultzc643fb42016-01-19 09:56:56 -0700197 {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
David Pinedofb5b5382015-06-18 17:03:14 -0600198 {0, 0, 0},
Karl Schultzc643fb42016-01-19 09:56:56 -0700199 {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
David Pinedofb5b5382015-06-18 17:03:14 -0600200 {0, 0, 0},
201 {width, height, 1}
202 };
203 VkMemoryRequirements memRequirements;
David Pinedo68295872015-06-30 13:08:37 -0600204 VkLayerDispatchTable* pTableDevice = get_dispatch_table(screenshot_device_table_map, device);
205 VkLayerDispatchTable* pTableQueue = get_dispatch_table(screenshot_device_table_map, queue);
Cody Northrop49f885c2015-09-01 10:18:45 -0600206 VkLayerInstanceDispatchTable* pInstanceTable;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800207 VkLayerDispatchTable* pTableCommandBuffer;
Cody Northrop49f885c2015-09-01 10:18:45 -0600208 VkPhysicalDeviceMemoryProperties memory_properties;
David Pinedofb5b5382015-06-18 17:03:14 -0600209
David Pinedofb5b5382015-06-18 17:03:14 -0600210 // The VkImage image1 we are going to dump may not be mappable,
211 // and/or it may have a tiling mode of optimal rather than linear.
212 // To make sure we have an image that we can map and read linearly, we:
213 // create image2 that is mappable and linear
214 // copy image1 to image2
215 // map image2
Karl Schultzc643fb42016-01-19 09:56:56 -0700216 // read from image2's mapped memory.
David Pinedofb5b5382015-06-18 17:03:14 -0600217
Chia-I Wuf7458c52015-10-26 21:10:41 +0800218 err = pTableDevice->CreateImage(device, &imgCreateInfo, NULL, &image2);
David Pinedofb5b5382015-06-18 17:03:14 -0600219 assert(!err);
220
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600221 pTableDevice->GetImageMemoryRequirements(device, image2, &memRequirements);
David Pinedofb5b5382015-06-18 17:03:14 -0600222
223 memAllocInfo.allocationSize = memRequirements.size;
Cody Northrop49f885c2015-09-01 10:18:45 -0600224 pInstanceTable = instance_dispatch_table(instance);
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600225 pInstanceTable->GetPhysicalDeviceMemoryProperties(physicalDevice, &memory_properties);
Cody Northrop49f885c2015-09-01 10:18:45 -0600226
Courtney Goeltzenleuchter1d2f0dd2015-10-22 11:03:31 -0600227 pass = memory_type_from_properties(&memory_properties,
Karl Schultzc643fb42016-01-19 09:56:56 -0700228 memRequirements.memoryTypeBits,
229 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
230 &memAllocInfo.memoryTypeIndex);
Courtney Goeltzenleuchter1d2f0dd2015-10-22 11:03:31 -0600231 assert(pass);
Cody Northrop49f885c2015-09-01 10:18:45 -0600232
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800233 err = pTableDevice->AllocateMemory(device, &memAllocInfo, NULL, &mem2);
David Pinedofb5b5382015-06-18 17:03:14 -0600234 assert(!err);
235
David Pinedo8897e192015-07-31 10:56:20 -0600236 err = pTableQueue->BindImageMemory(device, image2, mem2, 0);
David Pinedofb5b5382015-06-18 17:03:14 -0600237 assert(!err);
238
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800239 err = pTableDevice->AllocateCommandBuffers(device, &allocCommandBufferInfo, &commandBuffer);
David Pinedofb5b5382015-06-18 17:03:14 -0600240 assert(!err);
241
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800242 screenshot_device_table_map.emplace(commandBuffer, pTableDevice);
243 pTableCommandBuffer = screenshot_device_table_map[commandBuffer];
David Pinedofb5b5382015-06-18 17:03:14 -0600244
Karl Schultzc643fb42016-01-19 09:56:56 -0700245 // We have just created a dispatchable object, but the dispatch table has not been placed
246 // in the object yet. When a "normal" application creates a command buffer, the dispatch
247 // table is installed by the top-level api binding (trampoline.c).
248 // But here, we have to do it ourselves.
249 *((const void**)commandBuffer) = *(void**)device;
250
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800251 err = pTableCommandBuffer->BeginCommandBuffer(commandBuffer, &commandBufferBeginInfo);
David Pinedofb5b5382015-06-18 17:03:14 -0600252 assert(!err);
253
Karl Schultzc643fb42016-01-19 09:56:56 -0700254 // Transition the source image layout to prepare it for the copy.
255
256 VkImageMemoryBarrier image1_memory_barrier = {
257 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
258 NULL,
259 0,
260 VK_ACCESS_TRANSFER_READ_BIT,
261 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
262 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
263 0,
264 0,
265 image1,
266 { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
267 };
268
269 VkImageMemoryBarrier image2_memory_barrier = {
270 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
271 NULL,
272 0,
273 VK_ACCESS_TRANSFER_READ_BIT,
274 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
275 VK_IMAGE_LAYOUT_GENERAL,
276 0,
277 0,
278 image2,
279 { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
280 };
281
282 VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
283 VkPipelineStageFlags dst_stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
284
285 pTableCommandBuffer->CmdPipelineBarrier(commandBuffer, src_stages, dst_stages,
286 0, 0, NULL, 0, NULL, 1, &image1_memory_barrier);
287
288 pTableCommandBuffer->CmdCopyImage(commandBuffer,
289 image1, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
290 image2, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
291 1, &imageCopyRegion);
292
293 pTableCommandBuffer->CmdPipelineBarrier(commandBuffer, src_stages, dst_stages,
294 0, 0, NULL, 0, NULL, 1, &image2_memory_barrier);
David Pinedofb5b5382015-06-18 17:03:14 -0600295
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800296 err = pTableCommandBuffer->EndCommandBuffer(commandBuffer);
David Pinedofb5b5382015-06-18 17:03:14 -0600297 assert(!err);
298
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600299 VkFence nullFence = { VK_NULL_HANDLE };
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600300 VkSubmitInfo submit_info;
Chia-I Wuf9be13c2015-10-26 20:37:06 +0800301 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
302 submit_info.pNext = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800303 submit_info.waitSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600304 submit_info.pWaitSemaphores = NULL;
Jon Ashburn7f9716c2015-12-30 16:42:50 -0700305 submit_info.pWaitDstStageMask = NULL;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800306 submit_info.commandBufferCount = 1;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800307 submit_info.pCommandBuffers = &commandBuffer;
Chia-I Wud50a7d72015-10-26 20:48:51 +0800308 submit_info.signalSemaphoreCount = 0;
Courtney Goeltzenleuchter806c7002015-10-27 11:22:14 -0600309 submit_info.pSignalSemaphores = NULL;
Courtney Goeltzenleuchter646b9072015-10-20 18:04:07 -0600310
311 err = pTableQueue->QueueSubmit(queue, 1, &submit_info, nullFence);
David Pinedofb5b5382015-06-18 17:03:14 -0600312 assert(!err);
313
314 err = pTableQueue->QueueWaitIdle(queue);
315 assert(!err);
316
317 err = pTableDevice->DeviceWaitIdle(device);
318 assert(!err);
319
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600320 pTableDevice->GetImageSubresourceLayout(device, image2, &sr, &sr_layout);
David Pinedofb5b5382015-06-18 17:03:14 -0600321
322 err = pTableDevice->MapMemory(device, mem2, 0, 0, 0, (void **) &ptr );
323 assert(!err);
324
325 ptr += sr_layout.offset;
326
327 ofstream file(filename, ios::binary);
328
329 file << "P6\n";
330 file << width << "\n";
331 file << height << "\n";
332 file << 255 << "\n";
333
334 for (y = 0; y < height; y++) {
335 const unsigned int *row = (const unsigned int*) ptr;
336 if (format == VK_FORMAT_B8G8R8A8_UNORM)
337 {
338 for (x = 0; x < width; x++) {
339 unsigned int swapped;
340 swapped = (*row & 0xff00ff00) | (*row & 0x000000ff) << 16 | (*row & 0x00ff0000) >> 16;
341 file.write((char *)&swapped, 3);
342 row++;
343 }
344 }
345 else if (format == VK_FORMAT_R8G8B8A8_UNORM)
346 {
347 for (x = 0; x < width; x++) {
348 file.write((char *)row, 3);
349 row++;
350 }
351 }
352 else
353 {
David Pinedo8897e192015-07-31 10:56:20 -0600354 // TODO: add support for additional formats
David Pinedofb5b5382015-06-18 17:03:14 -0600355 printf("Unrecognized image format\n");
356 break;
357 }
358 ptr += sr_layout.rowPitch;
359 }
360 file.close();
Karl Schultzc643fb42016-01-19 09:56:56 -0700361 pTableDevice->UnmapMemory(device, mem2);
362
363 // Restore the swap chain image layout to what it was before.
364 // This may not be strictly needed, but it is generally good to restore things to original state.
365 err = pTableCommandBuffer->BeginCommandBuffer(commandBuffer, &commandBufferBeginInfo);
366 assert(!err);
367 image1_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
368 image1_memory_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
369
370 pTableCommandBuffer->CmdPipelineBarrier(commandBuffer, src_stages, dst_stages,
371 0, 0, NULL, 0, NULL, 1, &image1_memory_barrier);
372 err = pTableCommandBuffer->EndCommandBuffer(commandBuffer);
373 assert(!err);
374
375 err = pTableQueue->QueueSubmit(queue, 1, &submit_info, nullFence);
376 assert(!err);
377
378 err = pTableQueue->QueueWaitIdle(queue);
379 assert(!err);
380
381 err = pTableDevice->DeviceWaitIdle(device);
382 assert(!err);
David Pinedofb5b5382015-06-18 17:03:14 -0600383
384 // Clean up
Chia-I Wuf7458c52015-10-26 21:10:41 +0800385 pTableDevice->FreeMemory(device, mem2, NULL);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800386 pTableDevice->FreeCommandBuffers(device, deviceMap[device]->commandPool, 1, &commandBuffer);
David Pinedofb5b5382015-06-18 17:03:14 -0600387}
388
Jon Ashburn0f1a5332016-01-20 08:52:40 -0700389VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
390 const VkInstanceCreateInfo* pCreateInfo,
391 const VkAllocationCallbacks* pAllocator,
392 VkInstance* pInstance)
393{
394 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
395
396 assert(chain_info->u.pLayerInfo);
397 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
398 assert(fpGetInstanceProcAddr);
399 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(*pInstance, "vkCreateInstance");
400 if (fpCreateInstance == NULL) {
401 return VK_ERROR_INITIALIZATION_FAILED;
402 }
403
404 // Advance the link info for the next element on the chain
405 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
406
407 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
408 if (result != VK_SUCCESS)
409 return result;
410
411 initInstanceTable(*pInstance, fpGetInstanceProcAddr);
412
413 init_screenshot();
414
415 return result;
416}
417
418//TODO hook DestroyInstance to cleanup
David Pinedofb5b5382015-06-18 17:03:14 -0600419
David Pinedobcd0e792015-06-19 13:48:18 -0600420static void createDeviceRegisterExtensions(const VkDeviceCreateInfo* pCreateInfo, VkDevice device)
421{
Cody Northropd2ad0342015-08-05 11:15:02 -0600422 uint32_t i;
David Pinedobcd0e792015-06-19 13:48:18 -0600423 VkLayerDispatchTable *pDisp = get_dispatch_table(screenshot_device_table_map, device);
Jon Ashburn8acd2332015-09-16 18:08:32 -0600424 PFN_vkGetDeviceProcAddr gpa = pDisp->GetDeviceProcAddr;
Jon Ashburn8acd2332015-09-16 18:08:32 -0600425 pDisp->CreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) gpa(device, "vkCreateSwapchainKHR");
Jon Ashburn8acd2332015-09-16 18:08:32 -0600426 pDisp->GetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) gpa(device, "vkGetSwapchainImagesKHR");
427 pDisp->AcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) gpa(device, "vkAcquireNextImageKHR");
428 pDisp->QueuePresentKHR = (PFN_vkQueuePresentKHR) gpa(device, "vkQueuePresentKHR");
Ian Elliott1064fe32015-07-06 14:31:32 -0600429 deviceExtMap[pDisp].wsi_enabled = false;
Jon Ashburnf19916e2016-01-11 13:12:43 -0700430 for (i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
Ian Elliott05846062015-11-20 14:13:17 -0700431 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0)
Ian Elliott1064fe32015-07-06 14:31:32 -0600432 deviceExtMap[pDisp].wsi_enabled = true;
David Pinedobcd0e792015-06-19 13:48:18 -0600433 }
434}
435
Chia-I Wu9ab61502015-11-06 06:42:02 +0800436VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(
David Pinedofb5b5382015-06-18 17:03:14 -0600437 VkPhysicalDevice gpu,
438 const VkDeviceCreateInfo *pCreateInfo,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800439 const VkAllocationCallbacks* pAllocator,
David Pinedofb5b5382015-06-18 17:03:14 -0600440 VkDevice *pDevice)
441{
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700442 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
David Pinedofb5b5382015-06-18 17:03:14 -0600443
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700444 assert(chain_info->u.pLayerInfo);
445 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
446 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
447 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
448 if (fpCreateDevice == NULL) {
449 return VK_ERROR_INITIALIZATION_FAILED;
David Pinedobcd0e792015-06-19 13:48:18 -0600450 }
451
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700452 // Advance the link info for the next element on the chain
453 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
454
455 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
456 if (result != VK_SUCCESS) {
457 return result;
458 }
459
460 initDeviceTable(*pDevice, fpGetDeviceProcAddr, screenshot_device_table_map);
461
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700462 createDeviceRegisterExtensions(pCreateInfo, *pDevice);
463 // Create a mapping from a device to a physicalDevice
464 if (deviceMap[*pDevice] == NULL)
465 {
466 DeviceMapStruct *deviceMapElem = new DeviceMapStruct;
467 deviceMap[*pDevice] = deviceMapElem;
468 }
469 deviceMap[*pDevice]->physicalDevice = gpu;
470
David Pinedofb5b5382015-06-18 17:03:14 -0600471 return result;
472}
473
Chia-I Wu9ab61502015-11-06 06:42:02 +0800474VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(
Cody Northrop49f885c2015-09-01 10:18:45 -0600475 VkInstance instance,
476 uint32_t* pPhysicalDeviceCount,
477 VkPhysicalDevice* pPhysicalDevices)
478{
479 VkResult result;
480
481 VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);
482 result = pTable->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
Tobin Ehlisbe427742015-09-08 08:59:48 -0600483 if (result==VK_SUCCESS && *pPhysicalDeviceCount > 0 && pPhysicalDevices)
Cody Northrop49f885c2015-09-01 10:18:45 -0600484 {
485 for (uint32_t i=0; i<*pPhysicalDeviceCount ; i++)
486 {
487 // Create a mapping from a physicalDevice to an instance
488 if (physDeviceMap[pPhysicalDevices[i]] == NULL)
489 {
490 PhysDeviceMapStruct *physDeviceMapElem = new PhysDeviceMapStruct;
491 physDeviceMap[pPhysicalDevices[i]] = physDeviceMapElem;
492 }
493 physDeviceMap[pPhysicalDevices[i]]->instance = instance;
494 }
495 }
496 return result;
497}
498
Courtney Goeltzenleuchterca173b82015-06-25 18:01:43 -0600499/* TODO: Probably need a DestroyDevice as well */
500
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600501static const VkLayerProperties ss_device_layers[] = {
David Pinedofb5b5382015-06-18 17:03:14 -0600502 {
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700503 "screenshot",
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600504 VK_API_VERSION,
505 VK_MAKE_VERSION(0, 1, 0),
Mark Lobodzinski0d054fe2015-12-30 08:16:12 -0700506 "Layer: screenshot",
David Pinedobcd0e792015-06-19 13:48:18 -0600507 }
David Pinedofb5b5382015-06-18 17:03:14 -0600508};
David Pinedofb5b5382015-06-18 17:03:14 -0600509
Chia-I Wu9ab61502015-11-06 06:42:02 +0800510VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600511 const char *pLayerName,
512 uint32_t *pCount,
513 VkExtensionProperties* pProperties)
David Pinedofb5b5382015-06-18 17:03:14 -0600514{
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600515 /* ScreenShot does not have any global extensions */
516 return util_GetExtensionProperties(0, NULL, pCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -0600517}
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600518
Chia-I Wu9ab61502015-11-06 06:42:02 +0800519VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600520 uint32_t *pCount,
521 VkLayerProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -0600522{
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600523 /* ScreenShot does not have any global layers */
524 return util_GetLayerProperties(0, NULL,
525 pCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -0600526}
527
Chia-I Wu9ab61502015-11-06 06:42:02 +0800528VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600529 VkPhysicalDevice physicalDevice,
530 const char* pLayerName,
531 uint32_t* pCount,
532 VkExtensionProperties* pProperties)
Tony Barbour59a47322015-06-24 16:06:58 -0600533{
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600534 /* ScreenShot does not have any physical device extensions */
Jon Ashburn751c4842015-11-02 17:37:20 -0700535 if (pLayerName == NULL) {
536 VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(physicalDevice);
537 return pTable->EnumerateDeviceExtensionProperties(
538 physicalDevice,
539 NULL,
540 pCount,
541 pProperties);
542 } else {
543 return util_GetExtensionProperties(0, NULL, pCount, pProperties);
544 }
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600545}
Tony Barbour59a47322015-06-24 16:06:58 -0600546
Chia-I Wu9ab61502015-11-06 06:42:02 +0800547VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(
Courtney Goeltzenleuchtera6db3462015-07-07 11:25:43 -0600548 VkPhysicalDevice physicalDevice,
549 uint32_t* pCount,
550 VkLayerProperties* pProperties)
551{
552 return util_GetLayerProperties(ARRAY_SIZE(ss_device_layers),
553 ss_device_layers,
554 pCount, pProperties);
David Pinedofb5b5382015-06-18 17:03:14 -0600555}
556
Chia-I Wu9ab61502015-11-06 06:42:02 +0800557VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(
David Pinedofb5b5382015-06-18 17:03:14 -0600558 VkDevice device,
559 uint32_t queueNodeIndex,
560 uint32_t queueIndex,
561 VkQueue *pQueue)
562{
563 VkLayerDispatchTable* pTable = screenshot_device_table_map[device];
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600564 get_dispatch_table(screenshot_device_table_map, device)->GetDeviceQueue(device, queueNodeIndex, queueIndex, pQueue);
David Pinedofb5b5382015-06-18 17:03:14 -0600565
566 loader_platform_thread_lock_mutex(&globalLock);
567 if (screenshotEnvQueried && screenshotFrames.empty()) {
568 // We are all done taking screenshots, so don't do anything else
569 loader_platform_thread_unlock_mutex(&globalLock);
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600570 return;
David Pinedofb5b5382015-06-18 17:03:14 -0600571 }
572
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600573 screenshot_device_table_map.emplace(*pQueue, pTable);
David Pinedofb5b5382015-06-18 17:03:14 -0600574
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600575 // Create a mapping from a device to a queue
576 if (deviceMap[device] == NULL)
577 {
578 DeviceMapStruct *deviceMapElem = new DeviceMapStruct;
579 deviceMap[device] = deviceMapElem;
David Pinedofb5b5382015-06-18 17:03:14 -0600580 }
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600581 deviceMap[device]->queue = *pQueue;
David Pinedofb5b5382015-06-18 17:03:14 -0600582 loader_platform_thread_unlock_mutex(&globalLock);
David Pinedofb5b5382015-06-18 17:03:14 -0600583}
584
Chia-I Wu9ab61502015-11-06 06:42:02 +0800585VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(
David Pinedo8897e192015-07-31 10:56:20 -0600586 VkDevice device,
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800587 const VkCommandPoolCreateInfo *pCreateInfo,
588 const VkAllocationCallbacks* pAllocator,
589 VkCommandPool *pCommandPool)
David Pinedo8897e192015-07-31 10:56:20 -0600590{
591 VkLayerDispatchTable* pTable = screenshot_device_table_map[device];
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800592 VkResult result = get_dispatch_table(screenshot_device_table_map, device)->CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
David Pinedo8897e192015-07-31 10:56:20 -0600593
594 loader_platform_thread_lock_mutex(&globalLock);
595 if (screenshotEnvQueried && screenshotFrames.empty()) {
596 // We are all done taking screenshots, so don't do anything else
597 loader_platform_thread_unlock_mutex(&globalLock);
598 return result;
599 }
600
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800601 // Create a mapping from a device to a commandPool
Cody Northrop49f885c2015-09-01 10:18:45 -0600602 if (deviceMap[device] == NULL)
603 {
604 DeviceMapStruct *deviceMapElem = new DeviceMapStruct;
605 deviceMap[device] = deviceMapElem;
606 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800607 deviceMap[device]->commandPool = *pCommandPool;
David Pinedo8897e192015-07-31 10:56:20 -0600608 loader_platform_thread_unlock_mutex(&globalLock);
609 return result;
610}
611
Chia-I Wu9ab61502015-11-06 06:42:02 +0800612VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
David Pinedofb5b5382015-06-18 17:03:14 -0600613 VkDevice device,
Ian Elliott7e40db92015-08-21 15:09:33 -0600614 const VkSwapchainCreateInfoKHR *pCreateInfo,
Ian Elliott05846062015-11-20 14:13:17 -0700615 const VkAllocationCallbacks *pAllocator,
Ian Elliott7e40db92015-08-21 15:09:33 -0600616 VkSwapchainKHR *pSwapchain)
David Pinedofb5b5382015-06-18 17:03:14 -0600617{
618 VkLayerDispatchTable* pTable = screenshot_device_table_map[device];
Ian Elliott05846062015-11-20 14:13:17 -0700619 VkResult result = get_dispatch_table(screenshot_device_table_map, device)->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
David Pinedofb5b5382015-06-18 17:03:14 -0600620
621 loader_platform_thread_lock_mutex(&globalLock);
622 if (screenshotEnvQueried && screenshotFrames.empty()) {
623 // We are all done taking screenshots, so don't do anything else
624 loader_platform_thread_unlock_mutex(&globalLock);
625 return result;
626 }
627
628 if (result == VK_SUCCESS)
629 {
630 // Create a mapping for a swapchain to a device, image extent, and format
631 SwapchainMapStruct *swapchainMapElem = new SwapchainMapStruct;
632 swapchainMapElem->device = device;
633 swapchainMapElem->imageExtent = pCreateInfo->imageExtent;
634 swapchainMapElem->format = pCreateInfo->imageFormat;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800635 swapchainMap.insert(make_pair(*pSwapchain, swapchainMapElem));
David Pinedofb5b5382015-06-18 17:03:14 -0600636
637 // Create a mapping for the swapchain object into the dispatch table
Chia-I Wue2fc5522015-10-26 20:04:44 +0800638 screenshot_device_table_map.emplace((void *)pSwapchain, pTable);
David Pinedofb5b5382015-06-18 17:03:14 -0600639 }
640 loader_platform_thread_unlock_mutex(&globalLock);
641
642 return result;
643}
644
Chia-I Wu9ab61502015-11-06 06:42:02 +0800645VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(
Ian Elliott1064fe32015-07-06 14:31:32 -0600646 VkDevice device,
Ian Elliott7e40db92015-08-21 15:09:33 -0600647 VkSwapchainKHR swapchain,
Ian Elliott2b6b68a2015-08-07 14:11:14 -0600648 uint32_t* pCount,
Ian Elliott7e40db92015-08-21 15:09:33 -0600649 VkImage* pSwapchainImages)
David Pinedofb5b5382015-06-18 17:03:14 -0600650{
Ian Elliott7e40db92015-08-21 15:09:33 -0600651 VkResult result = get_dispatch_table(screenshot_device_table_map, device)->GetSwapchainImagesKHR(device, swapchain, pCount, pSwapchainImages);
David Pinedofb5b5382015-06-18 17:03:14 -0600652
653 loader_platform_thread_lock_mutex(&globalLock);
654 if (screenshotEnvQueried && screenshotFrames.empty()) {
655 // We are all done taking screenshots, so don't do anything else
656 loader_platform_thread_unlock_mutex(&globalLock);
657 return result;
658 }
659
660 if (result == VK_SUCCESS &&
Ian Elliott7e40db92015-08-21 15:09:33 -0600661 pSwapchainImages &&
Chia-I Wue2fc5522015-10-26 20:04:44 +0800662 !swapchainMap.empty() && swapchainMap.find(swapchain) != swapchainMap.end())
Ian Elliott2b6b68a2015-08-07 14:11:14 -0600663 {
Cody Northropbf065822015-09-01 11:48:13 -0600664 unsigned i;
David Pinedo8897e192015-07-31 10:56:20 -0600665
Ian Elliott2b6b68a2015-08-07 14:11:14 -0600666 for (i=0; i<*pCount; i++)
David Pinedofb5b5382015-06-18 17:03:14 -0600667 {
668 // Create a mapping for an image to a device, image extent, and format
Chia-I Wue2fc5522015-10-26 20:04:44 +0800669 if (imageMap[pSwapchainImages[i]] == NULL)
Cody Northrop49f885c2015-09-01 10:18:45 -0600670 {
671 ImageMapStruct *imageMapElem = new ImageMapStruct;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800672 imageMap[pSwapchainImages[i]] = imageMapElem;
Cody Northrop49f885c2015-09-01 10:18:45 -0600673 }
Chia-I Wue2fc5522015-10-26 20:04:44 +0800674 imageMap[pSwapchainImages[i]]->device = swapchainMap[swapchain]->device;
675 imageMap[pSwapchainImages[i]]->imageExtent = swapchainMap[swapchain]->imageExtent;
676 imageMap[pSwapchainImages[i]]->format = swapchainMap[swapchain]->format;
David Pinedofb5b5382015-06-18 17:03:14 -0600677 }
David Pinedo8897e192015-07-31 10:56:20 -0600678
679 // Add list of images to swapchain to image map
Chia-I Wue2fc5522015-10-26 20:04:44 +0800680 SwapchainMapStruct *swapchainMapElem = swapchainMap[swapchain];
David Pinedo8897e192015-07-31 10:56:20 -0600681 if (i >= 1 && swapchainMapElem)
682 {
683 VkImage *imageList = new VkImage[i];
684 swapchainMapElem->imageList = imageList;
Cody Northropbf065822015-09-01 11:48:13 -0600685 for (unsigned j=0; j<i; j++)
David Pinedo8897e192015-07-31 10:56:20 -0600686 {
Chia-I Wue2fc5522015-10-26 20:04:44 +0800687 swapchainMapElem->imageList[j] = pSwapchainImages[j];
David Pinedo8897e192015-07-31 10:56:20 -0600688 }
689 }
690
David Pinedofb5b5382015-06-18 17:03:14 -0600691 }
692 loader_platform_thread_unlock_mutex(&globalLock);
693 return result;
694}
695
Ian Elliott05846062015-11-20 14:13:17 -0700696VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo)
David Pinedofb5b5382015-06-18 17:03:14 -0600697{
698 static int frameNumber = 0;
David Pinedo8897e192015-07-31 10:56:20 -0600699 if (frameNumber == 10) {fflush(stdout); /* *((int*)0)=0; */ }
Ian Elliott7e40db92015-08-21 15:09:33 -0600700 VkResult result = get_dispatch_table(screenshot_device_table_map, queue)->QueuePresentKHR(queue, pPresentInfo);
David Pinedofb5b5382015-06-18 17:03:14 -0600701
702 loader_platform_thread_lock_mutex(&globalLock);
703
704 if (!screenshotEnvQueried)
705 {
Jon Ashburn38a497f2016-01-04 14:01:38 -0700706 const char *_vk_screenshot = loader_getenv("_VK_SCREENSHOT");
David Pinedofb5b5382015-06-18 17:03:14 -0600707 if (_vk_screenshot && *_vk_screenshot)
708 {
709 string spec(_vk_screenshot), word;
710 size_t start = 0, comma = 0;
711
712 while (start < spec.size()) {
713 int frameToAdd;
714 comma = spec.find(',', start);
715 if (comma == string::npos)
716 word = string(spec, start);
717 else
718 word = string(spec, start, comma - start);
719 frameToAdd=atoi(word.c_str());
720 // Add the frame number to list, but only do it if the word started with a digit and if
721 // it's not already in the list
722 if (*(word.c_str()) >= '0' && *(word.c_str()) <= '9' &&
723 find(screenshotFrames.begin(), screenshotFrames.end(), frameToAdd) == screenshotFrames.end())
724 {
725 screenshotFrames.push_back(frameToAdd);
726 }
727 if (comma == string::npos)
728 break;
729 start = comma + 1;
730 }
731 }
Jon Ashburn38a497f2016-01-04 14:01:38 -0700732 loader_free_getenv(_vk_screenshot);
David Pinedofb5b5382015-06-18 17:03:14 -0600733 screenshotEnvQueried = true;
734 }
735
736
737 if (result == VK_SUCCESS && !screenshotFrames.empty())
738 {
739 vector<int>::iterator it;
740 it = find(screenshotFrames.begin(), screenshotFrames.end(), frameNumber);
741 if (it != screenshotFrames.end())
742 {
743 string fileName;
744 fileName = to_string(frameNumber) + ".ppm";
David Pinedo8897e192015-07-31 10:56:20 -0600745
746 VkImage image;
Chia-I Wue2fc5522015-10-26 20:04:44 +0800747 VkSwapchainKHR swapchain;
David Pinedo8897e192015-07-31 10:56:20 -0600748 // We'll dump only one image: the first
Ian Elliott05846062015-11-20 14:13:17 -0700749 swapchain = pPresentInfo->pSwapchains[0];
750 image = swapchainMap[swapchain]->imageList[pPresentInfo->pImageIndices[0]];
David Pinedo8897e192015-07-31 10:56:20 -0600751 writePPM(fileName.c_str(), image);
David Pinedofb5b5382015-06-18 17:03:14 -0600752 screenshotFrames.erase(it);
753
754 if (screenshotFrames.empty())
755 {
David Pinedo8897e192015-07-31 10:56:20 -0600756 // Free all our maps since we are done with them.
David Pinedofb5b5382015-06-18 17:03:14 -0600757 for (auto it = swapchainMap.begin(); it != swapchainMap.end(); it++)
758 {
759 SwapchainMapStruct *swapchainMapElem = it->second;
760 delete swapchainMapElem;
761 }
762 for (auto it = imageMap.begin(); it != imageMap.end(); it++)
763 {
764 ImageMapStruct *imageMapElem = it->second;
765 delete imageMapElem;
766 }
767 for (auto it = deviceMap.begin(); it != deviceMap.end(); it++)
768 {
769 DeviceMapStruct *deviceMapElem = it->second;
770 delete deviceMapElem;
771 }
Cody Northrop49f885c2015-09-01 10:18:45 -0600772 for (auto it = physDeviceMap.begin(); it != physDeviceMap.end(); it++)
773 {
774 PhysDeviceMapStruct *physDeviceMapElem = it->second;
775 delete physDeviceMapElem;
776 }
David Pinedofb5b5382015-06-18 17:03:14 -0600777 swapchainMap.clear();
778 imageMap.clear();
779 deviceMap.clear();
Cody Northrop49f885c2015-09-01 10:18:45 -0600780 physDeviceMap.clear();
David Pinedofb5b5382015-06-18 17:03:14 -0600781 }
782 }
783 }
784 frameNumber++;
785 loader_platform_thread_unlock_mutex(&globalLock);
786 return result;
787}
788
Chia-I Wu9ab61502015-11-06 06:42:02 +0800789VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(
David Pinedofb5b5382015-06-18 17:03:14 -0600790 VkDevice dev,
791 const char *funcName)
792{
Jon Ashburn0f1a5332016-01-20 08:52:40 -0700793 if (!strcmp(funcName, "vkGetDeviceProcAddr"))
David Pinedo8897e192015-07-31 10:56:20 -0600794 return (PFN_vkVoidFunction)vkGetDeviceProcAddr;
David Pinedofb5b5382015-06-18 17:03:14 -0600795 if (!strcmp(funcName, "vkGetDeviceQueue"))
David Pinedo8897e192015-07-31 10:56:20 -0600796 return (PFN_vkVoidFunction) vkGetDeviceQueue;
David Pinedo8897e192015-07-31 10:56:20 -0600797 if (!strcmp(funcName, "vkCreateCommandPool"))
798 return (PFN_vkVoidFunction) vkCreateCommandPool;
David Pinedofb5b5382015-06-18 17:03:14 -0600799
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700800 if (dev == NULL) {
801 return NULL;
802 }
803
David Pinedobcd0e792015-06-19 13:48:18 -0600804 VkLayerDispatchTable *pDisp = get_dispatch_table(screenshot_device_table_map, dev);
Jon Ashburn8acd2332015-09-16 18:08:32 -0600805 if (deviceExtMap.size() != 0 && deviceExtMap[pDisp].wsi_enabled)
David Pinedobcd0e792015-06-19 13:48:18 -0600806 {
Ian Elliott7e40db92015-08-21 15:09:33 -0600807 if (!strcmp(funcName, "vkCreateSwapchainKHR"))
808 return (PFN_vkVoidFunction) vkCreateSwapchainKHR;
809 if (!strcmp(funcName, "vkGetSwapchainImagesKHR"))
810 return (PFN_vkVoidFunction) vkGetSwapchainImagesKHR;
811 if (!strcmp(funcName, "vkQueuePresentKHR"))
812 return (PFN_vkVoidFunction) vkQueuePresentKHR;
David Pinedobcd0e792015-06-19 13:48:18 -0600813 }
814
815 if (pDisp->GetDeviceProcAddr == NULL)
David Pinedofb5b5382015-06-18 17:03:14 -0600816 return NULL;
David Pinedobcd0e792015-06-19 13:48:18 -0600817 return pDisp->GetDeviceProcAddr(dev, funcName);
David Pinedofb5b5382015-06-18 17:03:14 -0600818}
David Pinedo38310942015-07-09 16:23:44 -0600819
820
Chia-I Wu9ab61502015-11-06 06:42:02 +0800821VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
David Pinedo38310942015-07-09 16:23:44 -0600822{
Jon Ashburn0f1a5332016-01-20 08:52:40 -0700823
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700824 if (!strcmp("vkGetInstanceProcAddr", funcName))
David Pinedo8897e192015-07-31 10:56:20 -0600825 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
Jon Ashburn0f1a5332016-01-20 08:52:40 -0700826 if (!strcmp(funcName, "vkCreateInstance"))
827 return (PFN_vkVoidFunction) vkCreateInstance;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700828 if (!strcmp(funcName, "vkCreateDevice"))
829 return (PFN_vkVoidFunction) vkCreateDevice;
Cody Northrop49f885c2015-09-01 10:18:45 -0600830 if (!strcmp(funcName, "vkEnumeratePhysicalDevices"))
831 return (PFN_vkVoidFunction)vkEnumeratePhysicalDevices;
Jon Ashburn751c4842015-11-02 17:37:20 -0700832 if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
833 return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties;
Cody Northrop49f885c2015-09-01 10:18:45 -0600834
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700835 if (instance == VK_NULL_HANDLE) {
836 return NULL;
837 }
David Pinedo38310942015-07-09 16:23:44 -0600838 VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);
839 if (pTable->GetInstanceProcAddr == NULL)
840 return NULL;
841 return pTable->GetInstanceProcAddr(instance, funcName);
David Pinedo38310942015-07-09 16:23:44 -0600842}