blob: 20e57522f7e720f69eff39c212c3b1802b72e9dd [file] [log] [blame]
jvanverth9f372462016-04-06 06:08:59 -07001
2/*
3 * Copyright 2015 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
Greg Daniel54bfb182018-11-20 17:12:36 -05009#include "VulkanWindowContext.h"
10
Greg Danielcb324152019-02-25 11:36:53 -050011#include "GrBackendSemaphore.h"
Greg Daniele79b4732017-04-20 14:07:46 -040012#include "GrBackendSurface.h"
jvanverth9f372462016-04-06 06:08:59 -070013#include "GrContext.h"
Hal Canary95e3c052017-01-11 12:44:43 -050014#include "SkAutoMalloc.h"
jvanverth9f372462016-04-06 06:08:59 -070015#include "SkSurface.h"
jvanverth9f372462016-04-06 06:08:59 -070016
Greg Daniel98bffae2018-08-01 13:25:41 -040017#include "vk/GrVkExtensions.h"
Greg Daniel6ddbafc2018-05-24 12:34:29 -040018#include "vk/GrVkImage.h"
jvanverth9f372462016-04-06 06:08:59 -070019#include "vk/GrVkTypes.h"
Greg Daniela31f4e52018-08-01 16:48:52 -040020#include "vk/GrVkUtil.h"
jvanverth9f372462016-04-06 06:08:59 -070021
22#ifdef VK_USE_PLATFORM_WIN32_KHR
23// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
24#undef CreateSemaphore
25#endif
26
Greg Danielf730c182018-07-02 20:15:37 +000027#define GET_PROC(F) f ## F = (PFN_vk ## F) fGetInstanceProcAddr(fInstance, "vk" #F)
28#define GET_DEV_PROC(F) f ## F = (PFN_vk ## F) fGetDeviceProcAddr(fDevice, "vk" #F)
jvanverthb0d43522016-04-21 11:46:23 -070029
jvanvertha8d0d6c2016-05-05 12:32:03 -070030namespace sk_app {
31
bsalomond1bdd1f2016-07-26 12:02:50 -070032VulkanWindowContext::VulkanWindowContext(const DisplayParams& params,
33 CreateVkSurfaceFn createVkSurface,
Greg Daniel35970ec2017-11-10 10:03:05 -050034 CanPresentFn canPresent,
35 PFN_vkGetInstanceProcAddr instProc,
36 PFN_vkGetDeviceProcAddr devProc)
Jim Van Verthfbdc0802017-05-02 16:15:53 -040037 : WindowContext(params)
38 , fCreateVkSurfaceFn(createVkSurface)
39 , fCanPresentFn(canPresent)
jvanverthaf236b52016-05-20 06:01:06 -070040 , fSurface(VK_NULL_HANDLE)
jvanvertha8d0d6c2016-05-05 12:32:03 -070041 , fSwapchain(VK_NULL_HANDLE)
jvanverthaf236b52016-05-20 06:01:06 -070042 , fImages(nullptr)
43 , fImageLayouts(nullptr)
44 , fSurfaces(nullptr)
jvanvertha8d0d6c2016-05-05 12:32:03 -070045 , fBackbuffers(nullptr) {
Greg Daniel35970ec2017-11-10 10:03:05 -050046 fGetInstanceProcAddr = instProc;
47 fGetDeviceProcAddr = devProc;
Jim Van Verthfbdc0802017-05-02 16:15:53 -040048 this->initializeContext();
49}
jvanverth9f372462016-04-06 06:08:59 -070050
Jim Van Verthfbdc0802017-05-02 16:15:53 -040051void VulkanWindowContext::initializeContext() {
jvanverth9f372462016-04-06 06:08:59 -070052 // any config code here (particularly for msaa)?
jvanverth9f372462016-04-06 06:08:59 -070053
Greg Danield3e65aa2018-08-01 09:19:45 -040054 PFN_vkGetInstanceProcAddr getInstanceProc = fGetInstanceProcAddr;
55 PFN_vkGetDeviceProcAddr getDeviceProc = fGetDeviceProcAddr;
56 auto getProc = [getInstanceProc, getDeviceProc](const char* proc_name,
57 VkInstance instance, VkDevice device) {
58 if (device != VK_NULL_HANDLE) {
59 return getDeviceProc(device, proc_name);
60 }
61 return getInstanceProc(instance, proc_name);
62 };
Greg Danielf730c182018-07-02 20:15:37 +000063 GrVkBackendContext backendContext;
Greg Daniel98bffae2018-08-01 13:25:41 -040064 GrVkExtensions extensions;
Greg Daniela0651ac2018-08-08 09:23:18 -040065 VkPhysicalDeviceFeatures2 features;
66 if (!sk_gpu_test::CreateVkBackendContext(getProc, &backendContext, &extensions, &features,
67 &fDebugCallback, &fPresentQueueIndex, fCanPresentFn)) {
68 sk_gpu_test::FreeVulkanFeaturesStructs(&features);
jvanverthb0d43522016-04-21 11:46:23 -070069 return;
70 }
71
Greg Daniela31f4e52018-08-01 16:48:52 -040072 if (!extensions.hasExtension(VK_KHR_SURFACE_EXTENSION_NAME, 25) ||
73 !extensions.hasExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, 68)) {
Greg Daniela0651ac2018-08-08 09:23:18 -040074 sk_gpu_test::FreeVulkanFeaturesStructs(&features);
Greg Danielf730c182018-07-02 20:15:37 +000075 return;
76 }
77
78 fInstance = backendContext.fInstance;
79 fPhysicalDevice = backendContext.fPhysicalDevice;
80 fDevice = backendContext.fDevice;
81 fGraphicsQueueIndex = backendContext.fGraphicsQueueIndex;
82 fGraphicsQueue = backendContext.fQueue;
Greg Danielc0b03d82018-08-03 14:41:15 -040083
84 PFN_vkGetPhysicalDeviceProperties localGetPhysicalDeviceProperties =
85 reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(
86 backendContext.fGetProc("vkGetPhysicalDeviceProperties",
87 backendContext.fInstance,
88 VK_NULL_HANDLE));
89 if (!localGetPhysicalDeviceProperties) {
Greg Daniela0651ac2018-08-08 09:23:18 -040090 sk_gpu_test::FreeVulkanFeaturesStructs(&features);
Greg Danielc0b03d82018-08-03 14:41:15 -040091 return;
92 }
93 VkPhysicalDeviceProperties physDeviceProperties;
94 localGetPhysicalDeviceProperties(backendContext.fPhysicalDevice, &physDeviceProperties);
95 uint32_t physDevVersion = physDeviceProperties.apiVersion;
96
Greg Danielc8cd45a2018-07-12 10:02:37 -040097 fInterface.reset(new GrVkInterface(backendContext.fGetProc, fInstance, fDevice,
Greg Danielc0b03d82018-08-03 14:41:15 -040098 backendContext.fInstanceVersion, physDevVersion,
Greg Daniel98bffae2018-08-01 13:25:41 -040099 &extensions));
Greg Danielf730c182018-07-02 20:15:37 +0000100
101 GET_PROC(DestroyInstance);
Greg Daniela31f4e52018-08-01 16:48:52 -0400102 if (fDebugCallback != VK_NULL_HANDLE) {
103 GET_PROC(DestroyDebugReportCallbackEXT);
104 }
jvanverthb0d43522016-04-21 11:46:23 -0700105 GET_PROC(DestroySurfaceKHR);
106 GET_PROC(GetPhysicalDeviceSurfaceSupportKHR);
107 GET_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
108 GET_PROC(GetPhysicalDeviceSurfaceFormatsKHR);
109 GET_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
Greg Danielf730c182018-07-02 20:15:37 +0000110 GET_DEV_PROC(DeviceWaitIdle);
111 GET_DEV_PROC(QueueWaitIdle);
112 GET_DEV_PROC(DestroyDevice);
jvanverthb0d43522016-04-21 11:46:23 -0700113 GET_DEV_PROC(CreateSwapchainKHR);
114 GET_DEV_PROC(DestroySwapchainKHR);
115 GET_DEV_PROC(GetSwapchainImagesKHR);
116 GET_DEV_PROC(AcquireNextImageKHR);
117 GET_DEV_PROC(QueuePresentKHR);
Greg Daniel35970ec2017-11-10 10:03:05 -0500118 GET_DEV_PROC(GetDeviceQueue);
jvanverth9f372462016-04-06 06:08:59 -0700119
Greg Danielf730c182018-07-02 20:15:37 +0000120 fContext = GrContext::MakeVulkan(backendContext, fDisplayParams.fGrContextOptions);
jvanverth9f372462016-04-06 06:08:59 -0700121
Greg Danielf730c182018-07-02 20:15:37 +0000122 fSurface = fCreateVkSurfaceFn(fInstance);
jvanverth9f372462016-04-06 06:08:59 -0700123 if (VK_NULL_HANDLE == fSurface) {
Greg Danielf730c182018-07-02 20:15:37 +0000124 this->destroyContext();
Greg Daniela0651ac2018-08-08 09:23:18 -0400125 sk_gpu_test::FreeVulkanFeaturesStructs(&features);
jvanverth9f372462016-04-06 06:08:59 -0700126 return;
127 }
128
jvanverth9f372462016-04-06 06:08:59 -0700129 VkBool32 supported;
Greg Danielf730c182018-07-02 20:15:37 +0000130 VkResult res = fGetPhysicalDeviceSurfaceSupportKHR(fPhysicalDevice, fPresentQueueIndex,
131 fSurface, &supported);
jvanverth9f372462016-04-06 06:08:59 -0700132 if (VK_SUCCESS != res) {
133 this->destroyContext();
Greg Daniela0651ac2018-08-08 09:23:18 -0400134 sk_gpu_test::FreeVulkanFeaturesStructs(&features);
jvanverth9f372462016-04-06 06:08:59 -0700135 return;
136 }
137
Jim Van Verthfbdc0802017-05-02 16:15:53 -0400138 if (!this->createSwapchain(-1, -1, fDisplayParams)) {
jvanverth9f372462016-04-06 06:08:59 -0700139 this->destroyContext();
Greg Daniela0651ac2018-08-08 09:23:18 -0400140 sk_gpu_test::FreeVulkanFeaturesStructs(&features);
jvanverth9f372462016-04-06 06:08:59 -0700141 return;
142 }
143
144 // create presentQueue
Greg Danielf730c182018-07-02 20:15:37 +0000145 fGetDeviceQueue(fDevice, fPresentQueueIndex, 0, &fPresentQueue);
Greg Daniela0651ac2018-08-08 09:23:18 -0400146 sk_gpu_test::FreeVulkanFeaturesStructs(&features);
jvanverth9f372462016-04-06 06:08:59 -0700147}
148
bsalomonccde4ab2016-07-27 08:50:12 -0700149bool VulkanWindowContext::createSwapchain(int width, int height,
brianosman05de2162016-05-06 13:28:57 -0700150 const DisplayParams& params) {
jvanverth9f372462016-04-06 06:08:59 -0700151 // check for capabilities
152 VkSurfaceCapabilitiesKHR caps;
Greg Danielf730c182018-07-02 20:15:37 +0000153 VkResult res = fGetPhysicalDeviceSurfaceCapabilitiesKHR(fPhysicalDevice, fSurface, &caps);
jvanverth9f372462016-04-06 06:08:59 -0700154 if (VK_SUCCESS != res) {
155 return false;
156 }
157
158 uint32_t surfaceFormatCount;
Greg Danielf730c182018-07-02 20:15:37 +0000159 res = fGetPhysicalDeviceSurfaceFormatsKHR(fPhysicalDevice, fSurface, &surfaceFormatCount,
160 nullptr);
jvanverth9f372462016-04-06 06:08:59 -0700161 if (VK_SUCCESS != res) {
162 return false;
163 }
164
165 SkAutoMalloc surfaceFormatAlloc(surfaceFormatCount * sizeof(VkSurfaceFormatKHR));
166 VkSurfaceFormatKHR* surfaceFormats = (VkSurfaceFormatKHR*)surfaceFormatAlloc.get();
Greg Danielf730c182018-07-02 20:15:37 +0000167 res = fGetPhysicalDeviceSurfaceFormatsKHR(fPhysicalDevice, fSurface, &surfaceFormatCount,
168 surfaceFormats);
jvanverth9f372462016-04-06 06:08:59 -0700169 if (VK_SUCCESS != res) {
170 return false;
171 }
172
173 uint32_t presentModeCount;
Greg Danielf730c182018-07-02 20:15:37 +0000174 res = fGetPhysicalDeviceSurfacePresentModesKHR(fPhysicalDevice, fSurface, &presentModeCount,
175 nullptr);
jvanverth9f372462016-04-06 06:08:59 -0700176 if (VK_SUCCESS != res) {
177 return false;
178 }
179
180 SkAutoMalloc presentModeAlloc(presentModeCount * sizeof(VkPresentModeKHR));
181 VkPresentModeKHR* presentModes = (VkPresentModeKHR*)presentModeAlloc.get();
Greg Danielf730c182018-07-02 20:15:37 +0000182 res = fGetPhysicalDeviceSurfacePresentModesKHR(fPhysicalDevice, fSurface, &presentModeCount,
183 presentModes);
jvanverth9f372462016-04-06 06:08:59 -0700184 if (VK_SUCCESS != res) {
185 return false;
186 }
187
188 VkExtent2D extent = caps.currentExtent;
189 // use the hints
190 if (extent.width == (uint32_t)-1) {
191 extent.width = width;
192 extent.height = height;
193 }
194
jvanverth9fab59d2016-04-06 12:08:51 -0700195 // clamp width; to protect us from broken hints
jvanverth9f372462016-04-06 06:08:59 -0700196 if (extent.width < caps.minImageExtent.width) {
197 extent.width = caps.minImageExtent.width;
198 } else if (extent.width > caps.maxImageExtent.width) {
199 extent.width = caps.maxImageExtent.width;
200 }
201 // clamp height
202 if (extent.height < caps.minImageExtent.height) {
203 extent.height = caps.minImageExtent.height;
204 } else if (extent.height > caps.maxImageExtent.height) {
205 extent.height = caps.maxImageExtent.height;
206 }
jvanverth1d155962016-05-23 13:13:36 -0700207
jvanverth9f372462016-04-06 06:08:59 -0700208 fWidth = (int)extent.width;
209 fHeight = (int)extent.height;
210
211 uint32_t imageCount = caps.minImageCount + 2;
212 if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
213 // Application must settle for fewer images than desired:
214 imageCount = caps.maxImageCount;
215 }
216
217 VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
218 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
219 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
220 SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
221 SkASSERT(caps.supportedTransforms & caps.currentTransform);
222 SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
223 VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
224 VkCompositeAlphaFlagBitsKHR composite_alpha =
225 (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ?
226 VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR :
227 VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
228
Brian Osman294fe292018-07-09 10:23:19 -0400229 // Pick our surface format.
brianosman05de2162016-05-06 13:28:57 -0700230 VkFormat surfaceFormat = VK_FORMAT_UNDEFINED;
231 VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
brianosman05de2162016-05-06 13:28:57 -0700232 for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
Greg Daniel81b80592017-12-13 10:20:04 -0500233 VkFormat localFormat = surfaceFormats[i].format;
Brian Osman2b23c4b2018-06-01 12:25:08 -0400234 if (GrVkFormatIsSupported(localFormat)) {
Greg Daniel81b80592017-12-13 10:20:04 -0500235 surfaceFormat = localFormat;
brianosman05de2162016-05-06 13:28:57 -0700236 colorSpace = surfaceFormats[i].colorSpace;
237 break;
238 }
239 }
240 fDisplayParams = params;
csmartdalton578f0642017-02-24 16:04:47 -0700241 fSampleCount = params.fMSAASampleCount;
242 fStencilBits = 8;
brianosman05de2162016-05-06 13:28:57 -0700243
244 if (VK_FORMAT_UNDEFINED == surfaceFormat) {
245 return false;
246 }
jvanvertha4b0fed2016-04-27 11:42:21 -0700247
Greg Danielfaa095e2017-12-19 13:15:02 -0500248 SkColorType colorType;
249 switch (surfaceFormat) {
250 case VK_FORMAT_R8G8B8A8_UNORM: // fall through
251 case VK_FORMAT_R8G8B8A8_SRGB:
252 colorType = kRGBA_8888_SkColorType;
253 break;
254 case VK_FORMAT_B8G8R8A8_UNORM: // fall through
255 case VK_FORMAT_B8G8R8A8_SRGB:
256 colorType = kBGRA_8888_SkColorType;
257 break;
258 default:
259 return false;
260 }
261
jvanverth3d6ed3a2016-04-07 11:09:51 -0700262 // If mailbox mode is available, use it, as it is the lowest-latency non-
263 // tearing mode. If not, fall back to FIFO which is always available.
jvanverth9f372462016-04-06 06:08:59 -0700264 VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
Greg Danielbb792aa2019-03-25 13:42:33 -0400265 bool hasImmediate = false;
jvanverth9f372462016-04-06 06:08:59 -0700266 for (uint32_t i = 0; i < presentModeCount; ++i) {
jvanverth3d6ed3a2016-04-07 11:09:51 -0700267 // use mailbox
268 if (VK_PRESENT_MODE_MAILBOX_KHR == presentModes[i]) {
Greg Danielbb792aa2019-03-25 13:42:33 -0400269 mode = VK_PRESENT_MODE_MAILBOX_KHR;
jvanverth9f372462016-04-06 06:08:59 -0700270 }
Greg Danielbb792aa2019-03-25 13:42:33 -0400271 if (VK_PRESENT_MODE_IMMEDIATE_KHR == presentModes[i]) {
272 hasImmediate = true;
273 }
274 }
275 if (params.fDisableVsync && hasImmediate) {
276 mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
jvanverth9f372462016-04-06 06:08:59 -0700277 }
278
279 VkSwapchainCreateInfoKHR swapchainCreateInfo;
280 memset(&swapchainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR));
281 swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
282 swapchainCreateInfo.surface = fSurface;
283 swapchainCreateInfo.minImageCount = imageCount;
jvanvertha4b0fed2016-04-27 11:42:21 -0700284 swapchainCreateInfo.imageFormat = surfaceFormat;
285 swapchainCreateInfo.imageColorSpace = colorSpace;
jvanverth9f372462016-04-06 06:08:59 -0700286 swapchainCreateInfo.imageExtent = extent;
287 swapchainCreateInfo.imageArrayLayers = 1;
288 swapchainCreateInfo.imageUsage = usageFlags;
289
Greg Danielf730c182018-07-02 20:15:37 +0000290 uint32_t queueFamilies[] = { fGraphicsQueueIndex, fPresentQueueIndex };
291 if (fGraphicsQueueIndex != fPresentQueueIndex) {
jvanverth9f372462016-04-06 06:08:59 -0700292 swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
293 swapchainCreateInfo.queueFamilyIndexCount = 2;
294 swapchainCreateInfo.pQueueFamilyIndices = queueFamilies;
295 } else {
296 swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
297 swapchainCreateInfo.queueFamilyIndexCount = 0;
298 swapchainCreateInfo.pQueueFamilyIndices = nullptr;
299 }
300
Greg Daniele897b972016-10-06 13:57:57 -0400301 swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
jvanverth9f372462016-04-06 06:08:59 -0700302 swapchainCreateInfo.compositeAlpha = composite_alpha;
303 swapchainCreateInfo.presentMode = mode;
304 swapchainCreateInfo.clipped = true;
305 swapchainCreateInfo.oldSwapchain = fSwapchain;
306
Greg Danielf730c182018-07-02 20:15:37 +0000307 res = fCreateSwapchainKHR(fDevice, &swapchainCreateInfo, nullptr, &fSwapchain);
jvanverth9f372462016-04-06 06:08:59 -0700308 if (VK_SUCCESS != res) {
309 return false;
310 }
311
312 // destroy the old swapchain
313 if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
Greg Danielf730c182018-07-02 20:15:37 +0000314 fDeviceWaitIdle(fDevice);
jvanverth9f372462016-04-06 06:08:59 -0700315
316 this->destroyBuffers();
317
Greg Danielf730c182018-07-02 20:15:37 +0000318 fDestroySwapchainKHR(fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
jvanverth9f372462016-04-06 06:08:59 -0700319 }
320
Greg Danielfaa095e2017-12-19 13:15:02 -0500321 this->createBuffers(swapchainCreateInfo.imageFormat, colorType);
jvanverth9f372462016-04-06 06:08:59 -0700322
323 return true;
324}
325
Greg Danielfaa095e2017-12-19 13:15:02 -0500326void VulkanWindowContext::createBuffers(VkFormat format, SkColorType colorType) {
Greg Danielf730c182018-07-02 20:15:37 +0000327 fGetSwapchainImagesKHR(fDevice, fSwapchain, &fImageCount, nullptr);
jvanverth9f372462016-04-06 06:08:59 -0700328 SkASSERT(fImageCount);
329 fImages = new VkImage[fImageCount];
Greg Danielf730c182018-07-02 20:15:37 +0000330 fGetSwapchainImagesKHR(fDevice, fSwapchain, &fImageCount, fImages);
jvanverth9f372462016-04-06 06:08:59 -0700331
332 // set up initial image layouts and create surfaces
333 fImageLayouts = new VkImageLayout[fImageCount];
334 fSurfaces = new sk_sp<SkSurface>[fImageCount];
335 for (uint32_t i = 0; i < fImageCount; ++i) {
336 fImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
337
egdanielb2df0c22016-05-13 11:30:37 -0700338 GrVkImageInfo info;
jvanverth9f372462016-04-06 06:08:59 -0700339 info.fImage = fImages[i];
Greg Daniel8385a8a2018-02-26 13:29:37 -0500340 info.fAlloc = GrVkAlloc();
egdaniel580fa592016-08-31 11:03:50 -0700341 info.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
jvanverth9f372462016-04-06 06:08:59 -0700342 info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
egdaniel58a8d922016-04-21 08:03:10 -0700343 info.fFormat = format;
jvanverth3622a172016-05-10 06:42:18 -0700344 info.fLevelCount = 1;
Greg Danielbae71212019-03-01 15:24:35 -0500345 info.fCurrentQueueFamily = fPresentQueueIndex;
jvanverthaf236b52016-05-20 06:01:06 -0700346
Brian Salomonafdc6b12018-03-09 12:02:32 -0500347 GrBackendRenderTarget backendRT(fWidth, fHeight, fSampleCount, info);
Greg Daniele79b4732017-04-20 14:07:46 -0400348
Brian Salomonafdc6b12018-03-09 12:02:32 -0500349 fSurfaces[i] = SkSurface::MakeFromBackendRenderTarget(fContext.get(),
350 backendRT,
351 kTopLeft_GrSurfaceOrigin,
352 colorType,
353 fDisplayParams.fColorSpace,
Ben Wagner37c54032018-04-13 14:30:23 -0400354 &fDisplayParams.fSurfaceProps);
jvanverth9f372462016-04-06 06:08:59 -0700355 }
356
jvanverth9f372462016-04-06 06:08:59 -0700357 // set up the backbuffers
358 VkSemaphoreCreateInfo semaphoreInfo;
359 memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
360 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
361 semaphoreInfo.pNext = nullptr;
362 semaphoreInfo.flags = 0;
jvanverth9f372462016-04-06 06:08:59 -0700363
Greg Daniel1f05f442016-10-27 16:37:17 -0400364 // we create one additional backbuffer structure here, because we want to
jvanverth9f372462016-04-06 06:08:59 -0700365 // give the command buffers they contain a chance to finish before we cycle back
366 fBackbuffers = new BackbufferInfo[fImageCount + 1];
367 for (uint32_t i = 0; i < fImageCount + 1; ++i) {
368 fBackbuffers[i].fImageIndex = -1;
Greg Danielf730c182018-07-02 20:15:37 +0000369 GR_VK_CALL_ERRCHECK(fInterface,
370 CreateSemaphore(fDevice, &semaphoreInfo,
jvanverth9f372462016-04-06 06:08:59 -0700371 nullptr, &fBackbuffers[i].fRenderSemaphore));
jvanverth9f372462016-04-06 06:08:59 -0700372 }
373 fCurrentBackbufferIndex = fImageCount;
374}
375
jvanvertha8d0d6c2016-05-05 12:32:03 -0700376void VulkanWindowContext::destroyBuffers() {
jvanverth9f372462016-04-06 06:08:59 -0700377
378 if (fBackbuffers) {
379 for (uint32_t i = 0; i < fImageCount + 1; ++i) {
jvanverth9f372462016-04-06 06:08:59 -0700380 fBackbuffers[i].fImageIndex = -1;
Greg Danielf730c182018-07-02 20:15:37 +0000381 GR_VK_CALL(fInterface,
382 DestroySemaphore(fDevice,
jvanverth9f372462016-04-06 06:08:59 -0700383 fBackbuffers[i].fRenderSemaphore,
384 nullptr));
jvanverth9f372462016-04-06 06:08:59 -0700385 }
386 }
387
388 delete[] fBackbuffers;
389 fBackbuffers = nullptr;
390
jvanverthaf236b52016-05-20 06:01:06 -0700391 // Does this actually free the surfaces?
jvanverth9f372462016-04-06 06:08:59 -0700392 delete[] fSurfaces;
393 fSurfaces = nullptr;
394 delete[] fImageLayouts;
395 fImageLayouts = nullptr;
396 delete[] fImages;
397 fImages = nullptr;
398}
399
jvanvertha8d0d6c2016-05-05 12:32:03 -0700400VulkanWindowContext::~VulkanWindowContext() {
jvanverth9f372462016-04-06 06:08:59 -0700401 this->destroyContext();
402}
403
jvanvertha8d0d6c2016-05-05 12:32:03 -0700404void VulkanWindowContext::destroyContext() {
Greg Daniel37329b32018-07-02 20:16:44 +0000405 if (this->isValid()) {
406 fQueueWaitIdle(fPresentQueue);
407 fDeviceWaitIdle(fDevice);
jvanverth9f372462016-04-06 06:08:59 -0700408
Greg Daniel37329b32018-07-02 20:16:44 +0000409 this->destroyBuffers();
jvanverth9f372462016-04-06 06:08:59 -0700410
Greg Daniel37329b32018-07-02 20:16:44 +0000411 if (VK_NULL_HANDLE != fSwapchain) {
412 fDestroySwapchainKHR(fDevice, fSwapchain, nullptr);
413 fSwapchain = VK_NULL_HANDLE;
414 }
jvanverth9f372462016-04-06 06:08:59 -0700415
Greg Daniel37329b32018-07-02 20:16:44 +0000416 if (VK_NULL_HANDLE != fSurface) {
417 fDestroySurfaceKHR(fInstance, fSurface, nullptr);
418 fSurface = VK_NULL_HANDLE;
419 }
jvanverth9f372462016-04-06 06:08:59 -0700420 }
421
Greg Daniel02611d92017-07-25 10:05:01 -0400422 fContext.reset();
Greg Danielf730c182018-07-02 20:15:37 +0000423 fInterface.reset();
jvanverth9f372462016-04-06 06:08:59 -0700424
Greg Danielf730c182018-07-02 20:15:37 +0000425 if (VK_NULL_HANDLE != fDevice) {
426 fDestroyDevice(fDevice, nullptr);
427 fDevice = VK_NULL_HANDLE;
428 }
Greg Daniel37329b32018-07-02 20:16:44 +0000429
430#ifdef SK_ENABLE_VK_LAYERS
431 if (fDebugCallback != VK_NULL_HANDLE) {
Greg Daniela31f4e52018-08-01 16:48:52 -0400432 fDestroyDebugReportCallbackEXT(fInstance, fDebugCallback, nullptr);
Greg Daniel37329b32018-07-02 20:16:44 +0000433 }
434#endif
435
Greg Danielf730c182018-07-02 20:15:37 +0000436 fPhysicalDevice = VK_NULL_HANDLE;
437
438 if (VK_NULL_HANDLE != fInstance) {
439 fDestroyInstance(fInstance, nullptr);
440 fInstance = VK_NULL_HANDLE;
441 }
jvanverth9f372462016-04-06 06:08:59 -0700442}
443
jvanvertha8d0d6c2016-05-05 12:32:03 -0700444VulkanWindowContext::BackbufferInfo* VulkanWindowContext::getAvailableBackbuffer() {
jvanverth9f372462016-04-06 06:08:59 -0700445 SkASSERT(fBackbuffers);
446
447 ++fCurrentBackbufferIndex;
egdaniel804af7d2016-09-26 12:30:46 -0700448 if (fCurrentBackbufferIndex > fImageCount) {
jvanverth9f372462016-04-06 06:08:59 -0700449 fCurrentBackbufferIndex = 0;
450 }
451
452 BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
jvanverth9f372462016-04-06 06:08:59 -0700453 return backbuffer;
454}
455
jvanverthaf236b52016-05-20 06:01:06 -0700456sk_sp<SkSurface> VulkanWindowContext::getBackbufferSurface() {
jvanverth9f372462016-04-06 06:08:59 -0700457 BackbufferInfo* backbuffer = this->getAvailableBackbuffer();
458 SkASSERT(backbuffer);
459
jvanverth9f372462016-04-06 06:08:59 -0700460 // semaphores should be in unsignaled state
Greg Danielcb324152019-02-25 11:36:53 -0500461 VkSemaphoreCreateInfo semaphoreInfo;
462 memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
463 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
464 semaphoreInfo.pNext = nullptr;
465 semaphoreInfo.flags = 0;
466 VkSemaphore semaphore;
467 GR_VK_CALL_ERRCHECK(fInterface, CreateSemaphore(fDevice, &semaphoreInfo,
468 nullptr, &semaphore));
469
jvanverth9f372462016-04-06 06:08:59 -0700470 // acquire the image
Greg Danielf730c182018-07-02 20:15:37 +0000471 VkResult res = fAcquireNextImageKHR(fDevice, fSwapchain, UINT64_MAX,
Greg Danielcb324152019-02-25 11:36:53 -0500472 semaphore, VK_NULL_HANDLE,
jvanverthb0d43522016-04-21 11:46:23 -0700473 &backbuffer->fImageIndex);
jvanverth9f372462016-04-06 06:08:59 -0700474 if (VK_ERROR_SURFACE_LOST_KHR == res) {
475 // need to figure out how to create a new vkSurface without the platformData*
jvanverth3d6ed3a2016-04-07 11:09:51 -0700476 // maybe use attach somehow? but need a Window
Greg Danielcb324152019-02-25 11:36:53 -0500477 GR_VK_CALL(fInterface, DestroySemaphore(fDevice, semaphore, nullptr));
jvanverth9f372462016-04-06 06:08:59 -0700478 return nullptr;
479 }
jvanverth3d6ed3a2016-04-07 11:09:51 -0700480 if (VK_ERROR_OUT_OF_DATE_KHR == res) {
jvanverth9f372462016-04-06 06:08:59 -0700481 // tear swapchain down and try again
Greg Daniel1f05f442016-10-27 16:37:17 -0400482 if (!this->createSwapchain(-1, -1, fDisplayParams)) {
Greg Danielcb324152019-02-25 11:36:53 -0500483 GR_VK_CALL(fInterface, DestroySemaphore(fDevice, semaphore, nullptr));
jvanverth9f372462016-04-06 06:08:59 -0700484 return nullptr;
485 }
Jim Van Verthd63c1022017-01-05 13:50:49 -0500486 backbuffer = this->getAvailableBackbuffer();
jvanverth9f372462016-04-06 06:08:59 -0700487
488 // acquire the image
Greg Danielf730c182018-07-02 20:15:37 +0000489 res = fAcquireNextImageKHR(fDevice, fSwapchain, UINT64_MAX,
Greg Danielcb324152019-02-25 11:36:53 -0500490 semaphore, VK_NULL_HANDLE,
jvanverthb0d43522016-04-21 11:46:23 -0700491 &backbuffer->fImageIndex);
jvanverth9f372462016-04-06 06:08:59 -0700492
493 if (VK_SUCCESS != res) {
Greg Danielcb324152019-02-25 11:36:53 -0500494 GR_VK_CALL(fInterface, DestroySemaphore(fDevice, semaphore, nullptr));
jvanverth9f372462016-04-06 06:08:59 -0700495 return nullptr;
496 }
497 }
498
egdaniel580fa592016-08-31 11:03:50 -0700499 SkSurface* surface = fSurfaces[backbuffer->fImageIndex].get();
Robert Phillipsba375a82018-04-11 10:08:06 -0400500
Greg Danielcb324152019-02-25 11:36:53 -0500501 GrBackendSemaphore beSemaphore;
502 beSemaphore.initVulkan(semaphore);
503
504 surface->wait(1, &beSemaphore);
egdaniel580fa592016-08-31 11:03:50 -0700505
506 return sk_ref_sp(surface);
jvanverth9f372462016-04-06 06:08:59 -0700507}
508
jvanvertha8d0d6c2016-05-05 12:32:03 -0700509void VulkanWindowContext::swapBuffers() {
jvanverth9f372462016-04-06 06:08:59 -0700510
511 BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
egdaniel580fa592016-08-31 11:03:50 -0700512 SkSurface* surface = fSurfaces[backbuffer->fImageIndex].get();
jvanverth9f372462016-04-06 06:08:59 -0700513
Greg Danielbae71212019-03-01 15:24:35 -0500514 GrBackendSemaphore beSemaphore;
515 beSemaphore.initVulkan(backbuffer->fRenderSemaphore);
Robert Phillipsba375a82018-04-11 10:08:06 -0400516
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400517 GrFlushInfo info;
518 info.fNumSemaphores = 1;
519 info.fSignalSemaphores = &beSemaphore;
520 surface->flush(SkSurface::BackendSurfaceAccess::kPresent, info);
jvanverth9f372462016-04-06 06:08:59 -0700521
522 // Submit present operation to present queue
523 const VkPresentInfoKHR presentInfo =
524 {
525 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
526 NULL, // pNext
527 1, // waitSemaphoreCount
528 &backbuffer->fRenderSemaphore, // pWaitSemaphores
529 1, // swapchainCount
530 &fSwapchain, // pSwapchains
531 &backbuffer->fImageIndex, // pImageIndices
532 NULL // pResults
533 };
534
jvanverthb0d43522016-04-21 11:46:23 -0700535 fQueuePresentKHR(fPresentQueue, &presentInfo);
jvanverth9f372462016-04-06 06:08:59 -0700536}
jvanvertha8d0d6c2016-05-05 12:32:03 -0700537
538} //namespace sk_app