1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2023 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "tools/window/GraphiteNativeVulkanWindowContext.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/MutableTextureState.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/BackendSemaphore.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/BackendTexture.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Context.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/ContextOptions.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/GraphiteTypes.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Recorder.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/Surface.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/TextureInfo.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/vk/VulkanGraphiteUtils.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanExtensions.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanMutableTextureState.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/vk/VulkanTypes.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkAutoMalloc.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextOptionsPriv.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/vk/VulkanGraphiteUtilsPriv.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/VulkanInterface.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/vk/vulkanmemoryallocator/VulkanAMDMemoryAllocator.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "tools/graphite/GraphiteToolUtils.h"
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker #ifdef VK_USE_PLATFORM_WIN32_KHR
34*c8dee2aaSAndroid Build Coastguard Worker // windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
35*c8dee2aaSAndroid Build Coastguard Worker #undef CreateSemaphore
36*c8dee2aaSAndroid Build Coastguard Worker #endif
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker #define GET_PROC(F) f##F = (PFN_vk##F)backendContext.fGetProc("vk" #F, fInstance, VK_NULL_HANDLE)
39*c8dee2aaSAndroid Build Coastguard Worker #define GET_DEV_PROC(F) f##F = (PFN_vk##F)backendContext.fGetProc("vk" #F, VK_NULL_HANDLE, fDevice)
40*c8dee2aaSAndroid Build Coastguard Worker
41*c8dee2aaSAndroid Build Coastguard Worker namespace skwindow::internal {
42*c8dee2aaSAndroid Build Coastguard Worker
GraphiteVulkanWindowContext(std::unique_ptr<const DisplayParams> params,CreateVkSurfaceFn createVkSurface,CanPresentFn canPresent,PFN_vkGetInstanceProcAddr instProc)43*c8dee2aaSAndroid Build Coastguard Worker GraphiteVulkanWindowContext::GraphiteVulkanWindowContext(
44*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<const DisplayParams> params,
45*c8dee2aaSAndroid Build Coastguard Worker CreateVkSurfaceFn createVkSurface,
46*c8dee2aaSAndroid Build Coastguard Worker CanPresentFn canPresent,
47*c8dee2aaSAndroid Build Coastguard Worker PFN_vkGetInstanceProcAddr instProc)
48*c8dee2aaSAndroid Build Coastguard Worker : WindowContext(std::move(params))
49*c8dee2aaSAndroid Build Coastguard Worker , fCreateVkSurfaceFn(std::move(createVkSurface))
50*c8dee2aaSAndroid Build Coastguard Worker , fCanPresentFn(std::move(canPresent))
51*c8dee2aaSAndroid Build Coastguard Worker , fSurface(VK_NULL_HANDLE)
52*c8dee2aaSAndroid Build Coastguard Worker , fSwapchain(VK_NULL_HANDLE)
53*c8dee2aaSAndroid Build Coastguard Worker , fImages(nullptr)
54*c8dee2aaSAndroid Build Coastguard Worker , fImageLayouts(nullptr)
55*c8dee2aaSAndroid Build Coastguard Worker , fSurfaces(nullptr)
56*c8dee2aaSAndroid Build Coastguard Worker , fBackbuffers(nullptr) {
57*c8dee2aaSAndroid Build Coastguard Worker fGetInstanceProcAddr = instProc;
58*c8dee2aaSAndroid Build Coastguard Worker this->initializeContext();
59*c8dee2aaSAndroid Build Coastguard Worker }
60*c8dee2aaSAndroid Build Coastguard Worker
initializeContext()61*c8dee2aaSAndroid Build Coastguard Worker void GraphiteVulkanWindowContext::initializeContext() {
62*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fGraphiteContext && !fGraphiteRecorder);
63*c8dee2aaSAndroid Build Coastguard Worker // any config code here (particularly for msaa)?
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker PFN_vkGetInstanceProcAddr getInstanceProc = fGetInstanceProcAddr;
66*c8dee2aaSAndroid Build Coastguard Worker skgpu::VulkanBackendContext backendContext;
67*c8dee2aaSAndroid Build Coastguard Worker skgpu::VulkanExtensions extensions;
68*c8dee2aaSAndroid Build Coastguard Worker VkPhysicalDeviceFeatures2 features;
69*c8dee2aaSAndroid Build Coastguard Worker if (!sk_gpu_test::CreateVkBackendContext(getInstanceProc,
70*c8dee2aaSAndroid Build Coastguard Worker &backendContext,
71*c8dee2aaSAndroid Build Coastguard Worker &extensions,
72*c8dee2aaSAndroid Build Coastguard Worker &features,
73*c8dee2aaSAndroid Build Coastguard Worker &fDebugCallback,
74*c8dee2aaSAndroid Build Coastguard Worker &fPresentQueueIndex,
75*c8dee2aaSAndroid Build Coastguard Worker fCanPresentFn,
76*c8dee2aaSAndroid Build Coastguard Worker fDisplayParams->createProtectedNativeBackend())) {
77*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::FreeVulkanFeaturesStructs(&features);
78*c8dee2aaSAndroid Build Coastguard Worker return;
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker
81*c8dee2aaSAndroid Build Coastguard Worker if (!extensions.hasExtension(VK_KHR_SURFACE_EXTENSION_NAME, 25) ||
82*c8dee2aaSAndroid Build Coastguard Worker !extensions.hasExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME, 68)) {
83*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::FreeVulkanFeaturesStructs(&features);
84*c8dee2aaSAndroid Build Coastguard Worker return;
85*c8dee2aaSAndroid Build Coastguard Worker }
86*c8dee2aaSAndroid Build Coastguard Worker
87*c8dee2aaSAndroid Build Coastguard Worker fInstance = backendContext.fInstance;
88*c8dee2aaSAndroid Build Coastguard Worker fPhysicalDevice = backendContext.fPhysicalDevice;
89*c8dee2aaSAndroid Build Coastguard Worker fDevice = backendContext.fDevice;
90*c8dee2aaSAndroid Build Coastguard Worker fGraphicsQueueIndex = backendContext.fGraphicsQueueIndex;
91*c8dee2aaSAndroid Build Coastguard Worker fGraphicsQueue = backendContext.fQueue;
92*c8dee2aaSAndroid Build Coastguard Worker
93*c8dee2aaSAndroid Build Coastguard Worker PFN_vkGetPhysicalDeviceProperties localGetPhysicalDeviceProperties =
94*c8dee2aaSAndroid Build Coastguard Worker reinterpret_cast<PFN_vkGetPhysicalDeviceProperties>(backendContext.fGetProc(
95*c8dee2aaSAndroid Build Coastguard Worker "vkGetPhysicalDeviceProperties", backendContext.fInstance, VK_NULL_HANDLE));
96*c8dee2aaSAndroid Build Coastguard Worker if (!localGetPhysicalDeviceProperties) {
97*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::FreeVulkanFeaturesStructs(&features);
98*c8dee2aaSAndroid Build Coastguard Worker return;
99*c8dee2aaSAndroid Build Coastguard Worker }
100*c8dee2aaSAndroid Build Coastguard Worker VkPhysicalDeviceProperties physDeviceProperties;
101*c8dee2aaSAndroid Build Coastguard Worker localGetPhysicalDeviceProperties(backendContext.fPhysicalDevice, &physDeviceProperties);
102*c8dee2aaSAndroid Build Coastguard Worker uint32_t physDevVersion = physDeviceProperties.apiVersion;
103*c8dee2aaSAndroid Build Coastguard Worker
104*c8dee2aaSAndroid Build Coastguard Worker fInterface.reset(new skgpu::VulkanInterface(backendContext.fGetProc,
105*c8dee2aaSAndroid Build Coastguard Worker fInstance,
106*c8dee2aaSAndroid Build Coastguard Worker fDevice,
107*c8dee2aaSAndroid Build Coastguard Worker backendContext.fMaxAPIVersion,
108*c8dee2aaSAndroid Build Coastguard Worker physDevVersion,
109*c8dee2aaSAndroid Build Coastguard Worker &extensions));
110*c8dee2aaSAndroid Build Coastguard Worker
111*c8dee2aaSAndroid Build Coastguard Worker GET_PROC(DestroyInstance);
112*c8dee2aaSAndroid Build Coastguard Worker if (fDebugCallback != VK_NULL_HANDLE) {
113*c8dee2aaSAndroid Build Coastguard Worker GET_PROC(DestroyDebugReportCallbackEXT);
114*c8dee2aaSAndroid Build Coastguard Worker }
115*c8dee2aaSAndroid Build Coastguard Worker GET_PROC(DestroySurfaceKHR);
116*c8dee2aaSAndroid Build Coastguard Worker GET_PROC(GetPhysicalDeviceSurfaceSupportKHR);
117*c8dee2aaSAndroid Build Coastguard Worker GET_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR);
118*c8dee2aaSAndroid Build Coastguard Worker GET_PROC(GetPhysicalDeviceSurfaceFormatsKHR);
119*c8dee2aaSAndroid Build Coastguard Worker GET_PROC(GetPhysicalDeviceSurfacePresentModesKHR);
120*c8dee2aaSAndroid Build Coastguard Worker GET_DEV_PROC(DeviceWaitIdle);
121*c8dee2aaSAndroid Build Coastguard Worker GET_DEV_PROC(QueueWaitIdle);
122*c8dee2aaSAndroid Build Coastguard Worker GET_DEV_PROC(DestroyDevice);
123*c8dee2aaSAndroid Build Coastguard Worker GET_DEV_PROC(CreateSwapchainKHR);
124*c8dee2aaSAndroid Build Coastguard Worker GET_DEV_PROC(DestroySwapchainKHR);
125*c8dee2aaSAndroid Build Coastguard Worker GET_DEV_PROC(GetSwapchainImagesKHR);
126*c8dee2aaSAndroid Build Coastguard Worker GET_DEV_PROC(AcquireNextImageKHR);
127*c8dee2aaSAndroid Build Coastguard Worker GET_DEV_PROC(QueuePresentKHR);
128*c8dee2aaSAndroid Build Coastguard Worker GET_DEV_PROC(GetDeviceQueue);
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::ContextOptions contextOptions;
131*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::ContextOptionsPriv contextOptionsPriv;
132*c8dee2aaSAndroid Build Coastguard Worker // Needed to make synchronous readPixels work
133*c8dee2aaSAndroid Build Coastguard Worker contextOptionsPriv.fStoreContextRefInRecorder = true;
134*c8dee2aaSAndroid Build Coastguard Worker contextOptions.fOptionsPriv = &contextOptionsPriv;
135*c8dee2aaSAndroid Build Coastguard Worker fGraphiteContext = skgpu::graphite::ContextFactory::MakeVulkan(backendContext, contextOptions);
136*c8dee2aaSAndroid Build Coastguard Worker fGraphiteRecorder = fGraphiteContext->makeRecorder(ToolUtils::CreateTestingRecorderOptions());
137*c8dee2aaSAndroid Build Coastguard Worker
138*c8dee2aaSAndroid Build Coastguard Worker fSurface = fCreateVkSurfaceFn(fInstance);
139*c8dee2aaSAndroid Build Coastguard Worker if (VK_NULL_HANDLE == fSurface) {
140*c8dee2aaSAndroid Build Coastguard Worker this->destroyContext();
141*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::FreeVulkanFeaturesStructs(&features);
142*c8dee2aaSAndroid Build Coastguard Worker return;
143*c8dee2aaSAndroid Build Coastguard Worker }
144*c8dee2aaSAndroid Build Coastguard Worker
145*c8dee2aaSAndroid Build Coastguard Worker VkBool32 supported;
146*c8dee2aaSAndroid Build Coastguard Worker VkResult res = fGetPhysicalDeviceSurfaceSupportKHR(
147*c8dee2aaSAndroid Build Coastguard Worker fPhysicalDevice, fPresentQueueIndex, fSurface, &supported);
148*c8dee2aaSAndroid Build Coastguard Worker if (VK_SUCCESS != res) {
149*c8dee2aaSAndroid Build Coastguard Worker this->destroyContext();
150*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::FreeVulkanFeaturesStructs(&features);
151*c8dee2aaSAndroid Build Coastguard Worker return;
152*c8dee2aaSAndroid Build Coastguard Worker }
153*c8dee2aaSAndroid Build Coastguard Worker
154*c8dee2aaSAndroid Build Coastguard Worker if (!this->createSwapchain(-1, -1)) {
155*c8dee2aaSAndroid Build Coastguard Worker this->destroyContext();
156*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::FreeVulkanFeaturesStructs(&features);
157*c8dee2aaSAndroid Build Coastguard Worker return;
158*c8dee2aaSAndroid Build Coastguard Worker }
159*c8dee2aaSAndroid Build Coastguard Worker
160*c8dee2aaSAndroid Build Coastguard Worker // create presentQueue
161*c8dee2aaSAndroid Build Coastguard Worker fGetDeviceQueue(fDevice, fPresentQueueIndex, 0, &fPresentQueue);
162*c8dee2aaSAndroid Build Coastguard Worker sk_gpu_test::FreeVulkanFeaturesStructs(&features);
163*c8dee2aaSAndroid Build Coastguard Worker }
164*c8dee2aaSAndroid Build Coastguard Worker
createSwapchain(int width,int height)165*c8dee2aaSAndroid Build Coastguard Worker bool GraphiteVulkanWindowContext::createSwapchain(int width, int height) {
166*c8dee2aaSAndroid Build Coastguard Worker // check for capabilities
167*c8dee2aaSAndroid Build Coastguard Worker VkSurfaceCapabilitiesKHR caps;
168*c8dee2aaSAndroid Build Coastguard Worker VkResult res = fGetPhysicalDeviceSurfaceCapabilitiesKHR(fPhysicalDevice, fSurface, &caps);
169*c8dee2aaSAndroid Build Coastguard Worker if (VK_SUCCESS != res) {
170*c8dee2aaSAndroid Build Coastguard Worker return false;
171*c8dee2aaSAndroid Build Coastguard Worker }
172*c8dee2aaSAndroid Build Coastguard Worker
173*c8dee2aaSAndroid Build Coastguard Worker uint32_t surfaceFormatCount;
174*c8dee2aaSAndroid Build Coastguard Worker res = fGetPhysicalDeviceSurfaceFormatsKHR(
175*c8dee2aaSAndroid Build Coastguard Worker fPhysicalDevice, fSurface, &surfaceFormatCount, nullptr);
176*c8dee2aaSAndroid Build Coastguard Worker if (VK_SUCCESS != res) {
177*c8dee2aaSAndroid Build Coastguard Worker return false;
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker SkAutoMalloc surfaceFormatAlloc(surfaceFormatCount * sizeof(VkSurfaceFormatKHR));
181*c8dee2aaSAndroid Build Coastguard Worker VkSurfaceFormatKHR* surfaceFormats = (VkSurfaceFormatKHR*)surfaceFormatAlloc.get();
182*c8dee2aaSAndroid Build Coastguard Worker res = fGetPhysicalDeviceSurfaceFormatsKHR(
183*c8dee2aaSAndroid Build Coastguard Worker fPhysicalDevice, fSurface, &surfaceFormatCount, surfaceFormats);
184*c8dee2aaSAndroid Build Coastguard Worker if (VK_SUCCESS != res) {
185*c8dee2aaSAndroid Build Coastguard Worker return false;
186*c8dee2aaSAndroid Build Coastguard Worker }
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker uint32_t presentModeCount;
189*c8dee2aaSAndroid Build Coastguard Worker res = fGetPhysicalDeviceSurfacePresentModesKHR(
190*c8dee2aaSAndroid Build Coastguard Worker fPhysicalDevice, fSurface, &presentModeCount, nullptr);
191*c8dee2aaSAndroid Build Coastguard Worker if (VK_SUCCESS != res) {
192*c8dee2aaSAndroid Build Coastguard Worker return false;
193*c8dee2aaSAndroid Build Coastguard Worker }
194*c8dee2aaSAndroid Build Coastguard Worker
195*c8dee2aaSAndroid Build Coastguard Worker SkAutoMalloc presentModeAlloc(presentModeCount * sizeof(VkPresentModeKHR));
196*c8dee2aaSAndroid Build Coastguard Worker VkPresentModeKHR* presentModes = (VkPresentModeKHR*)presentModeAlloc.get();
197*c8dee2aaSAndroid Build Coastguard Worker res = fGetPhysicalDeviceSurfacePresentModesKHR(
198*c8dee2aaSAndroid Build Coastguard Worker fPhysicalDevice, fSurface, &presentModeCount, presentModes);
199*c8dee2aaSAndroid Build Coastguard Worker if (VK_SUCCESS != res) {
200*c8dee2aaSAndroid Build Coastguard Worker return false;
201*c8dee2aaSAndroid Build Coastguard Worker }
202*c8dee2aaSAndroid Build Coastguard Worker
203*c8dee2aaSAndroid Build Coastguard Worker VkExtent2D extent = caps.currentExtent;
204*c8dee2aaSAndroid Build Coastguard Worker // use the hints
205*c8dee2aaSAndroid Build Coastguard Worker if (extent.width == (uint32_t)-1) {
206*c8dee2aaSAndroid Build Coastguard Worker extent.width = width;
207*c8dee2aaSAndroid Build Coastguard Worker extent.height = height;
208*c8dee2aaSAndroid Build Coastguard Worker }
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker // clamp width; to protect us from broken hints
211*c8dee2aaSAndroid Build Coastguard Worker if (extent.width < caps.minImageExtent.width) {
212*c8dee2aaSAndroid Build Coastguard Worker extent.width = caps.minImageExtent.width;
213*c8dee2aaSAndroid Build Coastguard Worker } else if (extent.width > caps.maxImageExtent.width) {
214*c8dee2aaSAndroid Build Coastguard Worker extent.width = caps.maxImageExtent.width;
215*c8dee2aaSAndroid Build Coastguard Worker }
216*c8dee2aaSAndroid Build Coastguard Worker // clamp height
217*c8dee2aaSAndroid Build Coastguard Worker if (extent.height < caps.minImageExtent.height) {
218*c8dee2aaSAndroid Build Coastguard Worker extent.height = caps.minImageExtent.height;
219*c8dee2aaSAndroid Build Coastguard Worker } else if (extent.height > caps.maxImageExtent.height) {
220*c8dee2aaSAndroid Build Coastguard Worker extent.height = caps.maxImageExtent.height;
221*c8dee2aaSAndroid Build Coastguard Worker }
222*c8dee2aaSAndroid Build Coastguard Worker
223*c8dee2aaSAndroid Build Coastguard Worker fWidth = (int)extent.width;
224*c8dee2aaSAndroid Build Coastguard Worker fHeight = (int)extent.height;
225*c8dee2aaSAndroid Build Coastguard Worker
226*c8dee2aaSAndroid Build Coastguard Worker uint32_t imageCount = caps.minImageCount + 2;
227*c8dee2aaSAndroid Build Coastguard Worker if (caps.maxImageCount > 0 && imageCount > caps.maxImageCount) {
228*c8dee2aaSAndroid Build Coastguard Worker // Application must settle for fewer images than desired:
229*c8dee2aaSAndroid Build Coastguard Worker imageCount = caps.maxImageCount;
230*c8dee2aaSAndroid Build Coastguard Worker }
231*c8dee2aaSAndroid Build Coastguard Worker
232*c8dee2aaSAndroid Build Coastguard Worker VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
233*c8dee2aaSAndroid Build Coastguard Worker VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
234*c8dee2aaSAndroid Build Coastguard Worker VK_IMAGE_USAGE_TRANSFER_DST_BIT;
235*c8dee2aaSAndroid Build Coastguard Worker SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags);
236*c8dee2aaSAndroid Build Coastguard Worker if (caps.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
237*c8dee2aaSAndroid Build Coastguard Worker usageFlags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
238*c8dee2aaSAndroid Build Coastguard Worker }
239*c8dee2aaSAndroid Build Coastguard Worker if (caps.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
240*c8dee2aaSAndroid Build Coastguard Worker usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
241*c8dee2aaSAndroid Build Coastguard Worker }
242*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(caps.supportedTransforms & caps.currentTransform);
243*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(caps.supportedCompositeAlpha &
244*c8dee2aaSAndroid Build Coastguard Worker (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR));
245*c8dee2aaSAndroid Build Coastguard Worker VkCompositeAlphaFlagBitsKHR composite_alpha =
246*c8dee2aaSAndroid Build Coastguard Worker (caps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
247*c8dee2aaSAndroid Build Coastguard Worker ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
248*c8dee2aaSAndroid Build Coastguard Worker : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
249*c8dee2aaSAndroid Build Coastguard Worker
250*c8dee2aaSAndroid Build Coastguard Worker // Pick our surface format.
251*c8dee2aaSAndroid Build Coastguard Worker VkFormat surfaceFormat = VK_FORMAT_UNDEFINED;
252*c8dee2aaSAndroid Build Coastguard Worker VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
253*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
254*c8dee2aaSAndroid Build Coastguard Worker VkFormat localFormat = surfaceFormats[i].format;
255*c8dee2aaSAndroid Build Coastguard Worker if (skgpu::graphite::vkFormatIsSupported(localFormat)) {
256*c8dee2aaSAndroid Build Coastguard Worker surfaceFormat = localFormat;
257*c8dee2aaSAndroid Build Coastguard Worker colorSpace = surfaceFormats[i].colorSpace;
258*c8dee2aaSAndroid Build Coastguard Worker break;
259*c8dee2aaSAndroid Build Coastguard Worker }
260*c8dee2aaSAndroid Build Coastguard Worker }
261*c8dee2aaSAndroid Build Coastguard Worker fSampleCount = std::max(1, fDisplayParams->msaaSampleCount());
262*c8dee2aaSAndroid Build Coastguard Worker fStencilBits = 8;
263*c8dee2aaSAndroid Build Coastguard Worker
264*c8dee2aaSAndroid Build Coastguard Worker if (VK_FORMAT_UNDEFINED == surfaceFormat) {
265*c8dee2aaSAndroid Build Coastguard Worker return false;
266*c8dee2aaSAndroid Build Coastguard Worker }
267*c8dee2aaSAndroid Build Coastguard Worker
268*c8dee2aaSAndroid Build Coastguard Worker SkColorType colorType;
269*c8dee2aaSAndroid Build Coastguard Worker switch (surfaceFormat) {
270*c8dee2aaSAndroid Build Coastguard Worker case VK_FORMAT_R8G8B8A8_UNORM: // fall through
271*c8dee2aaSAndroid Build Coastguard Worker case VK_FORMAT_R8G8B8A8_SRGB:
272*c8dee2aaSAndroid Build Coastguard Worker colorType = kRGBA_8888_SkColorType;
273*c8dee2aaSAndroid Build Coastguard Worker break;
274*c8dee2aaSAndroid Build Coastguard Worker case VK_FORMAT_B8G8R8A8_UNORM: // fall through
275*c8dee2aaSAndroid Build Coastguard Worker colorType = kBGRA_8888_SkColorType;
276*c8dee2aaSAndroid Build Coastguard Worker break;
277*c8dee2aaSAndroid Build Coastguard Worker default:
278*c8dee2aaSAndroid Build Coastguard Worker return false;
279*c8dee2aaSAndroid Build Coastguard Worker }
280*c8dee2aaSAndroid Build Coastguard Worker
281*c8dee2aaSAndroid Build Coastguard Worker // If mailbox mode is available, use it, as it is the lowest-latency non-
282*c8dee2aaSAndroid Build Coastguard Worker // tearing mode. If not, fall back to FIFO which is always available.
283*c8dee2aaSAndroid Build Coastguard Worker VkPresentModeKHR mode = VK_PRESENT_MODE_FIFO_KHR;
284*c8dee2aaSAndroid Build Coastguard Worker bool hasImmediate = false;
285*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t i = 0; i < presentModeCount; ++i) {
286*c8dee2aaSAndroid Build Coastguard Worker // use mailbox
287*c8dee2aaSAndroid Build Coastguard Worker if (VK_PRESENT_MODE_MAILBOX_KHR == presentModes[i]) {
288*c8dee2aaSAndroid Build Coastguard Worker mode = VK_PRESENT_MODE_MAILBOX_KHR;
289*c8dee2aaSAndroid Build Coastguard Worker }
290*c8dee2aaSAndroid Build Coastguard Worker if (VK_PRESENT_MODE_IMMEDIATE_KHR == presentModes[i]) {
291*c8dee2aaSAndroid Build Coastguard Worker hasImmediate = true;
292*c8dee2aaSAndroid Build Coastguard Worker }
293*c8dee2aaSAndroid Build Coastguard Worker }
294*c8dee2aaSAndroid Build Coastguard Worker if (fDisplayParams->disableVsync() && hasImmediate) {
295*c8dee2aaSAndroid Build Coastguard Worker mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
296*c8dee2aaSAndroid Build Coastguard Worker }
297*c8dee2aaSAndroid Build Coastguard Worker
298*c8dee2aaSAndroid Build Coastguard Worker VkSwapchainCreateInfoKHR swapchainCreateInfo;
299*c8dee2aaSAndroid Build Coastguard Worker memset(&swapchainCreateInfo, 0, sizeof(VkSwapchainCreateInfoKHR));
300*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
301*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.flags = fDisplayParams->createProtectedNativeBackend()
302*c8dee2aaSAndroid Build Coastguard Worker ? VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR
303*c8dee2aaSAndroid Build Coastguard Worker : 0;
304*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.surface = fSurface;
305*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.minImageCount = imageCount;
306*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.imageFormat = surfaceFormat;
307*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.imageColorSpace = colorSpace;
308*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.imageExtent = extent;
309*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.imageArrayLayers = 1;
310*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.imageUsage = usageFlags;
311*c8dee2aaSAndroid Build Coastguard Worker
312*c8dee2aaSAndroid Build Coastguard Worker uint32_t queueFamilies[] = {fGraphicsQueueIndex, fPresentQueueIndex};
313*c8dee2aaSAndroid Build Coastguard Worker if (fGraphicsQueueIndex != fPresentQueueIndex) {
314*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
315*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.queueFamilyIndexCount = 2;
316*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.pQueueFamilyIndices = queueFamilies;
317*c8dee2aaSAndroid Build Coastguard Worker } else {
318*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
319*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.queueFamilyIndexCount = 0;
320*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.pQueueFamilyIndices = nullptr;
321*c8dee2aaSAndroid Build Coastguard Worker }
322*c8dee2aaSAndroid Build Coastguard Worker
323*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
324*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.compositeAlpha = composite_alpha;
325*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.presentMode = mode;
326*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.clipped = true;
327*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.oldSwapchain = fSwapchain;
328*c8dee2aaSAndroid Build Coastguard Worker
329*c8dee2aaSAndroid Build Coastguard Worker res = fCreateSwapchainKHR(fDevice, &swapchainCreateInfo, nullptr, &fSwapchain);
330*c8dee2aaSAndroid Build Coastguard Worker if (VK_SUCCESS != res) {
331*c8dee2aaSAndroid Build Coastguard Worker return false;
332*c8dee2aaSAndroid Build Coastguard Worker }
333*c8dee2aaSAndroid Build Coastguard Worker
334*c8dee2aaSAndroid Build Coastguard Worker // destroy the old swapchain
335*c8dee2aaSAndroid Build Coastguard Worker if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) {
336*c8dee2aaSAndroid Build Coastguard Worker fDeviceWaitIdle(fDevice);
337*c8dee2aaSAndroid Build Coastguard Worker
338*c8dee2aaSAndroid Build Coastguard Worker this->destroyBuffers();
339*c8dee2aaSAndroid Build Coastguard Worker
340*c8dee2aaSAndroid Build Coastguard Worker fDestroySwapchainKHR(fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
341*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
342*c8dee2aaSAndroid Build Coastguard Worker }
343*c8dee2aaSAndroid Build Coastguard Worker
344*c8dee2aaSAndroid Build Coastguard Worker if (!this->createBuffers(swapchainCreateInfo.imageFormat,
345*c8dee2aaSAndroid Build Coastguard Worker usageFlags,
346*c8dee2aaSAndroid Build Coastguard Worker colorType,
347*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.imageSharingMode)) {
348*c8dee2aaSAndroid Build Coastguard Worker fDeviceWaitIdle(fDevice);
349*c8dee2aaSAndroid Build Coastguard Worker
350*c8dee2aaSAndroid Build Coastguard Worker this->destroyBuffers();
351*c8dee2aaSAndroid Build Coastguard Worker
352*c8dee2aaSAndroid Build Coastguard Worker fDestroySwapchainKHR(fDevice, swapchainCreateInfo.oldSwapchain, nullptr);
353*c8dee2aaSAndroid Build Coastguard Worker swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
354*c8dee2aaSAndroid Build Coastguard Worker }
355*c8dee2aaSAndroid Build Coastguard Worker
356*c8dee2aaSAndroid Build Coastguard Worker return true;
357*c8dee2aaSAndroid Build Coastguard Worker }
358*c8dee2aaSAndroid Build Coastguard Worker
createBuffers(VkFormat format,VkImageUsageFlags usageFlags,SkColorType colorType,VkSharingMode sharingMode)359*c8dee2aaSAndroid Build Coastguard Worker bool GraphiteVulkanWindowContext::createBuffers(VkFormat format,
360*c8dee2aaSAndroid Build Coastguard Worker VkImageUsageFlags usageFlags,
361*c8dee2aaSAndroid Build Coastguard Worker SkColorType colorType,
362*c8dee2aaSAndroid Build Coastguard Worker VkSharingMode sharingMode) {
363*c8dee2aaSAndroid Build Coastguard Worker fGetSwapchainImagesKHR(fDevice, fSwapchain, &fImageCount, nullptr);
364*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fImageCount);
365*c8dee2aaSAndroid Build Coastguard Worker fImages = new VkImage[fImageCount];
366*c8dee2aaSAndroid Build Coastguard Worker fGetSwapchainImagesKHR(fDevice, fSwapchain, &fImageCount, fImages);
367*c8dee2aaSAndroid Build Coastguard Worker
368*c8dee2aaSAndroid Build Coastguard Worker // set up initial image layouts and create surfaces
369*c8dee2aaSAndroid Build Coastguard Worker fImageLayouts = new VkImageLayout[fImageCount];
370*c8dee2aaSAndroid Build Coastguard Worker fSurfaces = new sk_sp<SkSurface>[fImageCount];
371*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t i = 0; i < fImageCount; ++i) {
372*c8dee2aaSAndroid Build Coastguard Worker fImageLayouts[i] = VK_IMAGE_LAYOUT_UNDEFINED;
373*c8dee2aaSAndroid Build Coastguard Worker
374*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::VulkanTextureInfo info;
375*c8dee2aaSAndroid Build Coastguard Worker info.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
376*c8dee2aaSAndroid Build Coastguard Worker info.fFormat = format;
377*c8dee2aaSAndroid Build Coastguard Worker info.fImageUsageFlags = usageFlags;
378*c8dee2aaSAndroid Build Coastguard Worker info.fSharingMode = sharingMode;
379*c8dee2aaSAndroid Build Coastguard Worker info.fFlags =
380*c8dee2aaSAndroid Build Coastguard Worker fDisplayParams->createProtectedNativeBackend() ? VK_IMAGE_CREATE_PROTECTED_BIT : 0;
381*c8dee2aaSAndroid Build Coastguard Worker
382*c8dee2aaSAndroid Build Coastguard Worker auto backendTex = skgpu::graphite::BackendTextures::MakeVulkan(this->dimensions(),
383*c8dee2aaSAndroid Build Coastguard Worker info,
384*c8dee2aaSAndroid Build Coastguard Worker VK_IMAGE_LAYOUT_UNDEFINED,
385*c8dee2aaSAndroid Build Coastguard Worker fPresentQueueIndex,
386*c8dee2aaSAndroid Build Coastguard Worker fImages[i],
387*c8dee2aaSAndroid Build Coastguard Worker skgpu::VulkanAlloc());
388*c8dee2aaSAndroid Build Coastguard Worker
389*c8dee2aaSAndroid Build Coastguard Worker fSurfaces[i] = SkSurfaces::WrapBackendTexture(this->graphiteRecorder(),
390*c8dee2aaSAndroid Build Coastguard Worker backendTex,
391*c8dee2aaSAndroid Build Coastguard Worker colorType,
392*c8dee2aaSAndroid Build Coastguard Worker fDisplayParams->colorSpace(),
393*c8dee2aaSAndroid Build Coastguard Worker &fDisplayParams->surfaceProps());
394*c8dee2aaSAndroid Build Coastguard Worker
395*c8dee2aaSAndroid Build Coastguard Worker if (!fSurfaces[i]) {
396*c8dee2aaSAndroid Build Coastguard Worker return false;
397*c8dee2aaSAndroid Build Coastguard Worker }
398*c8dee2aaSAndroid Build Coastguard Worker }
399*c8dee2aaSAndroid Build Coastguard Worker
400*c8dee2aaSAndroid Build Coastguard Worker // set up the backbuffers
401*c8dee2aaSAndroid Build Coastguard Worker VkSemaphoreCreateInfo semaphoreInfo;
402*c8dee2aaSAndroid Build Coastguard Worker memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
403*c8dee2aaSAndroid Build Coastguard Worker semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
404*c8dee2aaSAndroid Build Coastguard Worker semaphoreInfo.pNext = nullptr;
405*c8dee2aaSAndroid Build Coastguard Worker semaphoreInfo.flags = 0;
406*c8dee2aaSAndroid Build Coastguard Worker
407*c8dee2aaSAndroid Build Coastguard Worker // we create one additional backbuffer structure here, because we want to
408*c8dee2aaSAndroid Build Coastguard Worker // give the command buffers they contain a chance to finish before we cycle back
409*c8dee2aaSAndroid Build Coastguard Worker fBackbuffers = new BackbufferInfo[fImageCount + 1];
410*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t i = 0; i < fImageCount + 1; ++i) {
411*c8dee2aaSAndroid Build Coastguard Worker fBackbuffers[i].fImageIndex = -1;
412*c8dee2aaSAndroid Build Coastguard Worker VkResult result;
413*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL_RESULT_NOCHECK(
414*c8dee2aaSAndroid Build Coastguard Worker fInterface,
415*c8dee2aaSAndroid Build Coastguard Worker result,
416*c8dee2aaSAndroid Build Coastguard Worker CreateSemaphore(
417*c8dee2aaSAndroid Build Coastguard Worker fDevice, &semaphoreInfo, nullptr, &fBackbuffers[i].fRenderSemaphore));
418*c8dee2aaSAndroid Build Coastguard Worker }
419*c8dee2aaSAndroid Build Coastguard Worker fCurrentBackbufferIndex = fImageCount;
420*c8dee2aaSAndroid Build Coastguard Worker
421*c8dee2aaSAndroid Build Coastguard Worker return true;
422*c8dee2aaSAndroid Build Coastguard Worker }
423*c8dee2aaSAndroid Build Coastguard Worker
destroyBuffers()424*c8dee2aaSAndroid Build Coastguard Worker void GraphiteVulkanWindowContext::destroyBuffers() {
425*c8dee2aaSAndroid Build Coastguard Worker if (fBackbuffers) {
426*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t i = 0; i < fImageCount + 1; ++i) {
427*c8dee2aaSAndroid Build Coastguard Worker fBackbuffers[i].fImageIndex = -1;
428*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(fInterface,
429*c8dee2aaSAndroid Build Coastguard Worker DestroySemaphore(fDevice, fBackbuffers[i].fRenderSemaphore, nullptr));
430*c8dee2aaSAndroid Build Coastguard Worker }
431*c8dee2aaSAndroid Build Coastguard Worker }
432*c8dee2aaSAndroid Build Coastguard Worker
433*c8dee2aaSAndroid Build Coastguard Worker delete[] fBackbuffers;
434*c8dee2aaSAndroid Build Coastguard Worker fBackbuffers = nullptr;
435*c8dee2aaSAndroid Build Coastguard Worker
436*c8dee2aaSAndroid Build Coastguard Worker // Does this actually free the surfaces?
437*c8dee2aaSAndroid Build Coastguard Worker delete[] fSurfaces;
438*c8dee2aaSAndroid Build Coastguard Worker fSurfaces = nullptr;
439*c8dee2aaSAndroid Build Coastguard Worker delete[] fImageLayouts;
440*c8dee2aaSAndroid Build Coastguard Worker fImageLayouts = nullptr;
441*c8dee2aaSAndroid Build Coastguard Worker delete[] fImages;
442*c8dee2aaSAndroid Build Coastguard Worker fImages = nullptr;
443*c8dee2aaSAndroid Build Coastguard Worker }
444*c8dee2aaSAndroid Build Coastguard Worker
~GraphiteVulkanWindowContext()445*c8dee2aaSAndroid Build Coastguard Worker GraphiteVulkanWindowContext::~GraphiteVulkanWindowContext() { this->destroyContext(); }
446*c8dee2aaSAndroid Build Coastguard Worker
destroyContext()447*c8dee2aaSAndroid Build Coastguard Worker void GraphiteVulkanWindowContext::destroyContext() {
448*c8dee2aaSAndroid Build Coastguard Worker if (this->isValid()) {
449*c8dee2aaSAndroid Build Coastguard Worker fQueueWaitIdle(fPresentQueue);
450*c8dee2aaSAndroid Build Coastguard Worker fDeviceWaitIdle(fDevice);
451*c8dee2aaSAndroid Build Coastguard Worker
452*c8dee2aaSAndroid Build Coastguard Worker if (fWaitSemaphore != VK_NULL_HANDLE) {
453*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(fInterface, DestroySemaphore(fDevice, fWaitSemaphore, nullptr));
454*c8dee2aaSAndroid Build Coastguard Worker fWaitSemaphore = VK_NULL_HANDLE;
455*c8dee2aaSAndroid Build Coastguard Worker }
456*c8dee2aaSAndroid Build Coastguard Worker
457*c8dee2aaSAndroid Build Coastguard Worker this->destroyBuffers();
458*c8dee2aaSAndroid Build Coastguard Worker
459*c8dee2aaSAndroid Build Coastguard Worker if (fSwapchain != VK_NULL_HANDLE) {
460*c8dee2aaSAndroid Build Coastguard Worker fDestroySwapchainKHR(fDevice, fSwapchain, nullptr);
461*c8dee2aaSAndroid Build Coastguard Worker fSwapchain = VK_NULL_HANDLE;
462*c8dee2aaSAndroid Build Coastguard Worker }
463*c8dee2aaSAndroid Build Coastguard Worker
464*c8dee2aaSAndroid Build Coastguard Worker if (fSurface != VK_NULL_HANDLE) {
465*c8dee2aaSAndroid Build Coastguard Worker fDestroySurfaceKHR(fInstance, fSurface, nullptr);
466*c8dee2aaSAndroid Build Coastguard Worker fSurface = VK_NULL_HANDLE;
467*c8dee2aaSAndroid Build Coastguard Worker }
468*c8dee2aaSAndroid Build Coastguard Worker }
469*c8dee2aaSAndroid Build Coastguard Worker
470*c8dee2aaSAndroid Build Coastguard Worker if (fGraphiteContext) {
471*c8dee2aaSAndroid Build Coastguard Worker fGraphiteRecorder.reset();
472*c8dee2aaSAndroid Build Coastguard Worker fGraphiteContext.reset();
473*c8dee2aaSAndroid Build Coastguard Worker }
474*c8dee2aaSAndroid Build Coastguard Worker fInterface.reset();
475*c8dee2aaSAndroid Build Coastguard Worker
476*c8dee2aaSAndroid Build Coastguard Worker if (fDevice != VK_NULL_HANDLE) {
477*c8dee2aaSAndroid Build Coastguard Worker fDestroyDevice(fDevice, nullptr);
478*c8dee2aaSAndroid Build Coastguard Worker fDevice = VK_NULL_HANDLE;
479*c8dee2aaSAndroid Build Coastguard Worker }
480*c8dee2aaSAndroid Build Coastguard Worker
481*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_ENABLE_VK_LAYERS
482*c8dee2aaSAndroid Build Coastguard Worker if (fDebugCallback != VK_NULL_HANDLE) {
483*c8dee2aaSAndroid Build Coastguard Worker fDestroyDebugReportCallbackEXT(fInstance, fDebugCallback, nullptr);
484*c8dee2aaSAndroid Build Coastguard Worker }
485*c8dee2aaSAndroid Build Coastguard Worker #endif
486*c8dee2aaSAndroid Build Coastguard Worker
487*c8dee2aaSAndroid Build Coastguard Worker fPhysicalDevice = VK_NULL_HANDLE;
488*c8dee2aaSAndroid Build Coastguard Worker
489*c8dee2aaSAndroid Build Coastguard Worker if (fInstance != VK_NULL_HANDLE) {
490*c8dee2aaSAndroid Build Coastguard Worker fDestroyInstance(fInstance, nullptr);
491*c8dee2aaSAndroid Build Coastguard Worker fInstance = VK_NULL_HANDLE;
492*c8dee2aaSAndroid Build Coastguard Worker }
493*c8dee2aaSAndroid Build Coastguard Worker }
494*c8dee2aaSAndroid Build Coastguard Worker
getAvailableBackbuffer()495*c8dee2aaSAndroid Build Coastguard Worker GraphiteVulkanWindowContext::BackbufferInfo* GraphiteVulkanWindowContext::getAvailableBackbuffer() {
496*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fBackbuffers);
497*c8dee2aaSAndroid Build Coastguard Worker
498*c8dee2aaSAndroid Build Coastguard Worker ++fCurrentBackbufferIndex;
499*c8dee2aaSAndroid Build Coastguard Worker if (fCurrentBackbufferIndex > fImageCount) {
500*c8dee2aaSAndroid Build Coastguard Worker fCurrentBackbufferIndex = 0;
501*c8dee2aaSAndroid Build Coastguard Worker }
502*c8dee2aaSAndroid Build Coastguard Worker
503*c8dee2aaSAndroid Build Coastguard Worker BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
504*c8dee2aaSAndroid Build Coastguard Worker return backbuffer;
505*c8dee2aaSAndroid Build Coastguard Worker }
506*c8dee2aaSAndroid Build Coastguard Worker
getBackbufferSurface()507*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> GraphiteVulkanWindowContext::getBackbufferSurface() {
508*c8dee2aaSAndroid Build Coastguard Worker BackbufferInfo* backbuffer = this->getAvailableBackbuffer();
509*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(backbuffer);
510*c8dee2aaSAndroid Build Coastguard Worker
511*c8dee2aaSAndroid Build Coastguard Worker // semaphores should be in unsignaled state
512*c8dee2aaSAndroid Build Coastguard Worker VkSemaphoreCreateInfo semaphoreInfo;
513*c8dee2aaSAndroid Build Coastguard Worker memset(&semaphoreInfo, 0, sizeof(VkSemaphoreCreateInfo));
514*c8dee2aaSAndroid Build Coastguard Worker semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
515*c8dee2aaSAndroid Build Coastguard Worker semaphoreInfo.pNext = nullptr;
516*c8dee2aaSAndroid Build Coastguard Worker semaphoreInfo.flags = 0;
517*c8dee2aaSAndroid Build Coastguard Worker VkResult result;
518*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL_RESULT_NOCHECK(
519*c8dee2aaSAndroid Build Coastguard Worker fInterface, result, CreateSemaphore(fDevice, &semaphoreInfo, nullptr, &fWaitSemaphore));
520*c8dee2aaSAndroid Build Coastguard Worker
521*c8dee2aaSAndroid Build Coastguard Worker // acquire the image
522*c8dee2aaSAndroid Build Coastguard Worker VkResult res = fAcquireNextImageKHR(fDevice,
523*c8dee2aaSAndroid Build Coastguard Worker fSwapchain,
524*c8dee2aaSAndroid Build Coastguard Worker UINT64_MAX,
525*c8dee2aaSAndroid Build Coastguard Worker fWaitSemaphore,
526*c8dee2aaSAndroid Build Coastguard Worker VK_NULL_HANDLE,
527*c8dee2aaSAndroid Build Coastguard Worker &backbuffer->fImageIndex);
528*c8dee2aaSAndroid Build Coastguard Worker if (VK_ERROR_SURFACE_LOST_KHR == res) {
529*c8dee2aaSAndroid Build Coastguard Worker // TODO: Recreate fSurface using fCreateVkSurfaceFn, and then rebuild the swapchain
530*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(fInterface, DestroySemaphore(fDevice, fWaitSemaphore, nullptr));
531*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
532*c8dee2aaSAndroid Build Coastguard Worker }
533*c8dee2aaSAndroid Build Coastguard Worker if (VK_ERROR_OUT_OF_DATE_KHR == res) {
534*c8dee2aaSAndroid Build Coastguard Worker // tear swapchain down and try again
535*c8dee2aaSAndroid Build Coastguard Worker if (!this->createSwapchain(-1, -1)) {
536*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(fInterface, DestroySemaphore(fDevice, fWaitSemaphore, nullptr));
537*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
538*c8dee2aaSAndroid Build Coastguard Worker }
539*c8dee2aaSAndroid Build Coastguard Worker backbuffer = this->getAvailableBackbuffer();
540*c8dee2aaSAndroid Build Coastguard Worker
541*c8dee2aaSAndroid Build Coastguard Worker // acquire the image
542*c8dee2aaSAndroid Build Coastguard Worker res = fAcquireNextImageKHR(fDevice,
543*c8dee2aaSAndroid Build Coastguard Worker fSwapchain,
544*c8dee2aaSAndroid Build Coastguard Worker UINT64_MAX,
545*c8dee2aaSAndroid Build Coastguard Worker fWaitSemaphore,
546*c8dee2aaSAndroid Build Coastguard Worker VK_NULL_HANDLE,
547*c8dee2aaSAndroid Build Coastguard Worker &backbuffer->fImageIndex);
548*c8dee2aaSAndroid Build Coastguard Worker
549*c8dee2aaSAndroid Build Coastguard Worker if (VK_SUCCESS != res) {
550*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(fInterface, DestroySemaphore(fDevice, fWaitSemaphore, nullptr));
551*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
552*c8dee2aaSAndroid Build Coastguard Worker }
553*c8dee2aaSAndroid Build Coastguard Worker }
554*c8dee2aaSAndroid Build Coastguard Worker
555*c8dee2aaSAndroid Build Coastguard Worker SkSurface* surface = fSurfaces[backbuffer->fImageIndex].get();
556*c8dee2aaSAndroid Build Coastguard Worker
557*c8dee2aaSAndroid Build Coastguard Worker return sk_ref_sp(surface);
558*c8dee2aaSAndroid Build Coastguard Worker }
559*c8dee2aaSAndroid Build Coastguard Worker
onSwapBuffers()560*c8dee2aaSAndroid Build Coastguard Worker void GraphiteVulkanWindowContext::onSwapBuffers() {
561*c8dee2aaSAndroid Build Coastguard Worker if (!fGraphiteContext) {
562*c8dee2aaSAndroid Build Coastguard Worker return;
563*c8dee2aaSAndroid Build Coastguard Worker }
564*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fGraphiteRecorder);
565*c8dee2aaSAndroid Build Coastguard Worker
566*c8dee2aaSAndroid Build Coastguard Worker BackbufferInfo* backbuffer = fBackbuffers + fCurrentBackbufferIndex;
567*c8dee2aaSAndroid Build Coastguard Worker
568*c8dee2aaSAndroid Build Coastguard Worker // Rather than using submitToGpu we explicitly do that work here
569*c8dee2aaSAndroid Build Coastguard Worker // so we can set up the swapchain semaphores.
570*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<skgpu::graphite::Recording> recording = fGraphiteRecorder->snap();
571*c8dee2aaSAndroid Build Coastguard Worker if (recording) {
572*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::InsertRecordingInfo info;
573*c8dee2aaSAndroid Build Coastguard Worker info.fRecording = recording.get();
574*c8dee2aaSAndroid Build Coastguard Worker
575*c8dee2aaSAndroid Build Coastguard Worker // set up surface for layout transition
576*c8dee2aaSAndroid Build Coastguard Worker info.fTargetSurface = fSurfaces[backbuffer->fImageIndex].get();
577*c8dee2aaSAndroid Build Coastguard Worker skgpu::MutableTextureState presentState = skgpu::MutableTextureStates::MakeVulkan(
578*c8dee2aaSAndroid Build Coastguard Worker VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, fPresentQueueIndex);
579*c8dee2aaSAndroid Build Coastguard Worker info.fTargetTextureState = &presentState;
580*c8dee2aaSAndroid Build Coastguard Worker
581*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fWaitSemaphore != VK_NULL_HANDLE);
582*c8dee2aaSAndroid Build Coastguard Worker auto beWaitSemaphore = skgpu::graphite::BackendSemaphores::MakeVulkan(fWaitSemaphore);
583*c8dee2aaSAndroid Build Coastguard Worker info.fNumWaitSemaphores = 1;
584*c8dee2aaSAndroid Build Coastguard Worker info.fWaitSemaphores = &beWaitSemaphore;
585*c8dee2aaSAndroid Build Coastguard Worker auto beSignalSemaphore =
586*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::BackendSemaphores::MakeVulkan(backbuffer->fRenderSemaphore);
587*c8dee2aaSAndroid Build Coastguard Worker info.fNumSignalSemaphores = 1;
588*c8dee2aaSAndroid Build Coastguard Worker info.fSignalSemaphores = &beSignalSemaphore;
589*c8dee2aaSAndroid Build Coastguard Worker
590*c8dee2aaSAndroid Build Coastguard Worker // Insert finishedProc to delete waitSemaphore when done
591*c8dee2aaSAndroid Build Coastguard Worker struct FinishContext {
592*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const skgpu::VulkanInterface> interface;
593*c8dee2aaSAndroid Build Coastguard Worker VkDevice device;
594*c8dee2aaSAndroid Build Coastguard Worker VkSemaphore waitSemaphore;
595*c8dee2aaSAndroid Build Coastguard Worker };
596*c8dee2aaSAndroid Build Coastguard Worker auto* finishContext = new FinishContext{fInterface, fDevice, fWaitSemaphore};
597*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::GpuFinishedProc finishCallback = [](skgpu::graphite::GpuFinishedContext c,
598*c8dee2aaSAndroid Build Coastguard Worker skgpu::CallbackResult status) {
599*c8dee2aaSAndroid Build Coastguard Worker // regardless of the status we need to destroy the semaphore
600*c8dee2aaSAndroid Build Coastguard Worker const auto* context = reinterpret_cast<const FinishContext*>(c);
601*c8dee2aaSAndroid Build Coastguard Worker VULKAN_CALL(context->interface,
602*c8dee2aaSAndroid Build Coastguard Worker DestroySemaphore(context->device, context->waitSemaphore, nullptr));
603*c8dee2aaSAndroid Build Coastguard Worker };
604*c8dee2aaSAndroid Build Coastguard Worker info.fFinishedContext = finishContext;
605*c8dee2aaSAndroid Build Coastguard Worker info.fFinishedProc = finishCallback;
606*c8dee2aaSAndroid Build Coastguard Worker
607*c8dee2aaSAndroid Build Coastguard Worker fGraphiteContext->insertRecording(info);
608*c8dee2aaSAndroid Build Coastguard Worker fGraphiteContext->submit(skgpu::graphite::SyncToCpu::kNo);
609*c8dee2aaSAndroid Build Coastguard Worker fWaitSemaphore = VK_NULL_HANDLE; // FinishCallback will destroy this
610*c8dee2aaSAndroid Build Coastguard Worker }
611*c8dee2aaSAndroid Build Coastguard Worker
612*c8dee2aaSAndroid Build Coastguard Worker // Submit present operation to present queue
613*c8dee2aaSAndroid Build Coastguard Worker const VkPresentInfoKHR presentInfo = {
614*c8dee2aaSAndroid Build Coastguard Worker VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, // sType
615*c8dee2aaSAndroid Build Coastguard Worker nullptr, // pNext
616*c8dee2aaSAndroid Build Coastguard Worker 1, // waitSemaphoreCount
617*c8dee2aaSAndroid Build Coastguard Worker &backbuffer->fRenderSemaphore, // pWaitSemaphores
618*c8dee2aaSAndroid Build Coastguard Worker 1, // swapchainCount
619*c8dee2aaSAndroid Build Coastguard Worker &fSwapchain, // pSwapchains
620*c8dee2aaSAndroid Build Coastguard Worker &backbuffer->fImageIndex, // pImageIndices
621*c8dee2aaSAndroid Build Coastguard Worker nullptr // pResults
622*c8dee2aaSAndroid Build Coastguard Worker };
623*c8dee2aaSAndroid Build Coastguard Worker
624*c8dee2aaSAndroid Build Coastguard Worker fQueuePresentKHR(fPresentQueue, &presentInfo);
625*c8dee2aaSAndroid Build Coastguard Worker }
626*c8dee2aaSAndroid Build Coastguard Worker
627*c8dee2aaSAndroid Build Coastguard Worker } // namespace skwindow::internal
628