blob: 479d680f1852f0aea9372ad081ccbc1db19347e3 [file] [log] [blame]
jvanverth633b3562016-03-23 11:01:22 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Hal Canary95e3c052017-01-11 12:44:43 -05008#include "SkAutoMalloc.h"
jvanverth633b3562016-03-23 11:01:22 -07009#include "vk/GrVkBackendContext.h"
jvanverthfd7bd452016-03-25 06:29:52 -070010#include "vk/GrVkExtensions.h"
jvanverth633b3562016-03-23 11:01:22 -070011#include "vk/GrVkInterface.h"
12#include "vk/GrVkUtil.h"
13
14////////////////////////////////////////////////////////////////////////////////
15// Helper code to set up Vulkan context objects
16
egdaniel735109c2016-07-27 08:03:57 -070017#ifdef SK_ENABLE_VK_LAYERS
jvanverthfd7bd452016-03-25 06:29:52 -070018const char* kDebugLayerNames[] = {
jvanverth633b3562016-03-23 11:01:22 -070019 // elements of VK_LAYER_LUNARG_standard_validation
egdaniel58a8d922016-04-21 08:03:10 -070020 "VK_LAYER_GOOGLE_threading",
21 "VK_LAYER_LUNARG_parameter_validation",
jvanverth633b3562016-03-23 11:01:22 -070022 "VK_LAYER_LUNARG_object_tracker",
23 "VK_LAYER_LUNARG_image",
egdaniel58a8d922016-04-21 08:03:10 -070024 "VK_LAYER_LUNARG_core_validation",
jvanverth633b3562016-03-23 11:01:22 -070025 "VK_LAYER_LUNARG_swapchain",
egdaniel58a8d922016-04-21 08:03:10 -070026 "VK_LAYER_GOOGLE_unique_objects",
jvanverth633b3562016-03-23 11:01:22 -070027 // not included in standard_validation
28 //"VK_LAYER_LUNARG_api_dump",
jvanverthfd7bd452016-03-25 06:29:52 -070029 //"VK_LAYER_LUNARG_vktrace",
30 //"VK_LAYER_LUNARG_screenshot",
jvanverth633b3562016-03-23 11:01:22 -070031};
jvanverth633b3562016-03-23 11:01:22 -070032#endif
33
jvanverthfd7bd452016-03-25 06:29:52 -070034// the minimum version of Vulkan supported
liyuqianb138fdc2016-04-29 10:00:26 -070035#ifdef SK_BUILD_FOR_ANDROID
36const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 3);
37#else
egdaniel58a8d922016-04-21 08:03:10 -070038const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 8);
liyuqianb138fdc2016-04-29 10:00:26 -070039#endif
jvanverthfd7bd452016-03-25 06:29:52 -070040
Michael Jurka3251ed82017-04-05 09:52:55 -070041#define ACQUIRE_VK_PROC(name, instance, device) \
42 PFN_vk##name grVk##name = \
43 reinterpret_cast<PFN_vk##name>(getProc("vk" #name, instance, device)); \
44 if (grVk##name == nullptr) { \
45 SkDebugf("Function ptr for vk%s could not be acquired\n", #name); \
46 return nullptr; \
47 }
48
jvanverth633b3562016-03-23 11:01:22 -070049// Create the base Vulkan objects needed by the GrVkGpu object
jvanverthb0d43522016-04-21 11:46:23 -070050const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndexPtr,
Michael Jurka3251ed82017-04-05 09:52:55 -070051 CanPresentFn canPresent,
52 GrVkInterface::GetProc getProc) {
Brian Salomoncc901742017-04-25 13:28:45 -040053 if (!getProc) {
Brian Salomoncc901742017-04-25 13:28:45 -040054 return nullptr;
Brian Salomoncc901742017-04-25 13:28:45 -040055 }
56 SkASSERT(getProc);
Michael Jurka3251ed82017-04-05 09:52:55 -070057
jvanverth633b3562016-03-23 11:01:22 -070058 VkPhysicalDevice physDev;
59 VkDevice device;
60 VkInstance inst;
61 VkResult err;
62
63 const VkApplicationInfo app_info = {
64 VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
65 nullptr, // pNext
66 "vktest", // pApplicationName
67 0, // applicationVersion
68 "vktest", // pEngineName
69 0, // engineVerison
70 kGrVkMinimumVersion, // apiVersion
71 };
72
Michael Jurka3251ed82017-04-05 09:52:55 -070073 GrVkExtensions extensions(getProc);
jvanverthfd7bd452016-03-25 06:29:52 -070074 extensions.initInstance(kGrVkMinimumVersion);
75
76 SkTArray<const char*> instanceLayerNames;
77 SkTArray<const char*> instanceExtensionNames;
78 uint32_t extensionFlags = 0;
egdaniel735109c2016-07-27 08:03:57 -070079#ifdef SK_ENABLE_VK_LAYERS
ethannicholas384b5e92016-03-25 11:04:06 -070080 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
jvanverthfd7bd452016-03-25 06:29:52 -070081 if (extensions.hasInstanceLayer(kDebugLayerNames[i])) {
82 instanceLayerNames.push_back(kDebugLayerNames[i]);
83 }
84 }
85 if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
86 instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
87 extensionFlags |= kEXT_debug_report_GrVkExtensionFlag;
jvanverth633b3562016-03-23 11:01:22 -070088 }
jvanverth9f372462016-04-06 06:08:59 -070089#endif
90
jvanverthe50f3e72016-03-28 07:03:06 -070091 if (extensions.hasInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME)) {
92 instanceExtensionNames.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
93 extensionFlags |= kKHR_surface_GrVkExtensionFlag;
94 }
95 if (extensions.hasInstanceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
96 instanceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
97 extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
98 }
99#ifdef SK_BUILD_FOR_WIN
100 if (extensions.hasInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) {
101 instanceExtensionNames.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
102 extensionFlags |= kKHR_win32_surface_GrVkExtensionFlag;
103 }
djsollen7e731082016-06-09 13:07:13 -0700104#elif defined(SK_BUILD_FOR_ANDROID)
jvanverthe50f3e72016-03-28 07:03:06 -0700105 if (extensions.hasInstanceExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
106 instanceExtensionNames.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
107 extensionFlags |= kKHR_android_surface_GrVkExtensionFlag;
jvanverth1d155962016-05-23 13:13:36 -0700108 }
Michael Jurka3251ed82017-04-05 09:52:55 -0700109#elif defined(SK_BUILD_FOR_UNIX) && !defined(__Fuchsia__)
jvanverth1d155962016-05-23 13:13:36 -0700110 if (extensions.hasInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME)) {
111 instanceExtensionNames.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
112 extensionFlags |= kKHR_xcb_surface_GrVkExtensionFlag;
jvanverthe50f3e72016-03-28 07:03:06 -0700113 }
114#endif
jvanverth633b3562016-03-23 11:01:22 -0700115
116 const VkInstanceCreateInfo instance_create = {
ethannicholas384b5e92016-03-25 11:04:06 -0700117 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
118 nullptr, // pNext
119 0, // flags
120 &app_info, // pApplicationInfo
121 (uint32_t) instanceLayerNames.count(), // enabledLayerNameCount
122 instanceLayerNames.begin(), // ppEnabledLayerNames
123 (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
124 instanceExtensionNames.begin(), // ppEnabledExtensionNames
jvanverth633b3562016-03-23 11:01:22 -0700125 };
126
Michael Jurka3251ed82017-04-05 09:52:55 -0700127 ACQUIRE_VK_PROC(CreateInstance, VK_NULL_HANDLE, VK_NULL_HANDLE);
128 err = grVkCreateInstance(&instance_create, nullptr, &inst);
jvanverth633b3562016-03-23 11:01:22 -0700129 if (err < 0) {
130 SkDebugf("vkCreateInstance failed: %d\n", err);
bsalomondc0fcd42016-04-11 14:21:33 -0700131 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700132 }
133
Michael Jurka3251ed82017-04-05 09:52:55 -0700134 ACQUIRE_VK_PROC(DestroyInstance, inst, VK_NULL_HANDLE);
135 ACQUIRE_VK_PROC(EnumeratePhysicalDevices, inst, VK_NULL_HANDLE);
136 ACQUIRE_VK_PROC(GetPhysicalDeviceQueueFamilyProperties, inst, VK_NULL_HANDLE);
137 ACQUIRE_VK_PROC(GetPhysicalDeviceFeatures, inst, VK_NULL_HANDLE);
138 ACQUIRE_VK_PROC(CreateDevice, inst, VK_NULL_HANDLE);
139 ACQUIRE_VK_PROC(GetDeviceQueue, inst, VK_NULL_HANDLE);
140 ACQUIRE_VK_PROC(DeviceWaitIdle, inst, VK_NULL_HANDLE);
141 ACQUIRE_VK_PROC(DestroyDevice, inst, VK_NULL_HANDLE);
142
jvanverth633b3562016-03-23 11:01:22 -0700143 uint32_t gpuCount;
Michael Jurka3251ed82017-04-05 09:52:55 -0700144 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700145 if (err) {
146 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
Michael Jurka3251ed82017-04-05 09:52:55 -0700147 grVkDestroyInstance(inst, nullptr);
bsalomondc0fcd42016-04-11 14:21:33 -0700148 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700149 }
150 SkASSERT(gpuCount > 0);
151 // Just returning the first physical device instead of getting the whole array.
152 // TODO: find best match for our needs
153 gpuCount = 1;
Michael Jurka3251ed82017-04-05 09:52:55 -0700154 err = grVkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
jvanverth633b3562016-03-23 11:01:22 -0700155 if (err) {
156 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
Michael Jurka3251ed82017-04-05 09:52:55 -0700157 grVkDestroyInstance(inst, nullptr);
bsalomondc0fcd42016-04-11 14:21:33 -0700158 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700159 }
160
161 // query to get the initial queue props size
162 uint32_t queueCount;
Michael Jurka3251ed82017-04-05 09:52:55 -0700163 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700164 SkASSERT(queueCount >= 1);
165
166 SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
167 // now get the actual queue props
168 VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
169
Michael Jurka3251ed82017-04-05 09:52:55 -0700170 grVkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
jvanverth633b3562016-03-23 11:01:22 -0700171
172 // iterate to find the graphics queue
jvanverthb0d43522016-04-21 11:46:23 -0700173 uint32_t graphicsQueueIndex = queueCount;
jvanverth633b3562016-03-23 11:01:22 -0700174 for (uint32_t i = 0; i < queueCount; i++) {
175 if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
176 graphicsQueueIndex = i;
177 break;
178 }
179 }
180 SkASSERT(graphicsQueueIndex < queueCount);
181
jvanverthb0d43522016-04-21 11:46:23 -0700182 // iterate to find the present queue, if needed
183 uint32_t presentQueueIndex = graphicsQueueIndex;
184 if (presentQueueIndexPtr && canPresent) {
185 for (uint32_t i = 0; i < queueCount; i++) {
bsalomond1bdd1f2016-07-26 12:02:50 -0700186 if (canPresent(inst, physDev, i)) {
jvanverthb0d43522016-04-21 11:46:23 -0700187 presentQueueIndex = i;
188 break;
189 }
190 }
191 SkASSERT(presentQueueIndex < queueCount);
192 *presentQueueIndexPtr = presentQueueIndex;
193 }
194
jvanverthfd7bd452016-03-25 06:29:52 -0700195 extensions.initDevice(kGrVkMinimumVersion, inst, physDev);
196
197 SkTArray<const char*> deviceLayerNames;
198 SkTArray<const char*> deviceExtensionNames;
egdaniel735109c2016-07-27 08:03:57 -0700199#ifdef SK_ENABLE_VK_LAYERS
ethannicholas384b5e92016-03-25 11:04:06 -0700200 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
jvanverthfd7bd452016-03-25 06:29:52 -0700201 if (extensions.hasDeviceLayer(kDebugLayerNames[i])) {
202 deviceLayerNames.push_back(kDebugLayerNames[i]);
203 }
jvanverth633b3562016-03-23 11:01:22 -0700204 }
205#endif
jvanverth9f372462016-04-06 06:08:59 -0700206 if (extensions.hasDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
207 deviceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
208 extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
209 }
jvanverthfd7bd452016-03-25 06:29:52 -0700210 if (extensions.hasDeviceExtension("VK_NV_glsl_shader")) {
211 deviceExtensionNames.push_back("VK_NV_glsl_shader");
212 extensionFlags |= kNV_glsl_shader_GrVkExtensionFlag;
213 }
214
215 // query to get the physical device properties
216 VkPhysicalDeviceFeatures deviceFeatures;
Michael Jurka3251ed82017-04-05 09:52:55 -0700217 grVkGetPhysicalDeviceFeatures(physDev, &deviceFeatures);
halcanary9d524f22016-03-29 09:03:52 -0700218 // this looks like it would slow things down,
jvanverthfd7bd452016-03-25 06:29:52 -0700219 // and we can't depend on it on all platforms
220 deviceFeatures.robustBufferAccess = VK_FALSE;
221
222 uint32_t featureFlags = 0;
223 if (deviceFeatures.geometryShader) {
224 featureFlags |= kGeometryShader_GrVkFeatureFlag;
225 }
226 if (deviceFeatures.dualSrcBlend) {
227 featureFlags |= kDualSrcBlend_GrVkFeatureFlag;
228 }
229 if (deviceFeatures.sampleRateShading) {
230 featureFlags |= kSampleRateShading_GrVkFeatureFlag;
231 }
jvanverth633b3562016-03-23 11:01:22 -0700232
233 float queuePriorities[1] = { 0.0 };
234 // Here we assume no need for swapchain queue
235 // If one is needed, the client will need its own setup code
jvanverthb0d43522016-04-21 11:46:23 -0700236 const VkDeviceQueueCreateInfo queueInfo[2] = {
237 {
238 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
239 nullptr, // pNext
240 0, // VkDeviceQueueCreateFlags
241 graphicsQueueIndex, // queueFamilyIndex
242 1, // queueCount
243 queuePriorities, // pQueuePriorities
244 },
245 {
246 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
247 nullptr, // pNext
248 0, // VkDeviceQueueCreateFlags
249 presentQueueIndex, // queueFamilyIndex
250 1, // queueCount
251 queuePriorities, // pQueuePriorities
252 }
jvanverth633b3562016-03-23 11:01:22 -0700253 };
jvanverthb0d43522016-04-21 11:46:23 -0700254 uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;
255
jvanverth633b3562016-03-23 11:01:22 -0700256 const VkDeviceCreateInfo deviceInfo = {
ethannicholas384b5e92016-03-25 11:04:06 -0700257 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
258 nullptr, // pNext
259 0, // VkDeviceCreateFlags
jvanverthb0d43522016-04-21 11:46:23 -0700260 queueInfoCount, // queueCreateInfoCount
261 queueInfo, // pQueueCreateInfos
ethannicholas384b5e92016-03-25 11:04:06 -0700262 (uint32_t) deviceLayerNames.count(), // layerCount
263 deviceLayerNames.begin(), // ppEnabledLayerNames
264 (uint32_t) deviceExtensionNames.count(), // extensionCount
265 deviceExtensionNames.begin(), // ppEnabledExtensionNames
266 &deviceFeatures // ppEnabledFeatures
jvanverth633b3562016-03-23 11:01:22 -0700267 };
268
Michael Jurka3251ed82017-04-05 09:52:55 -0700269 err = grVkCreateDevice(physDev, &deviceInfo, nullptr, &device);
jvanverth633b3562016-03-23 11:01:22 -0700270 if (err) {
271 SkDebugf("CreateDevice failed: %d\n", err);
Michael Jurka3251ed82017-04-05 09:52:55 -0700272 grVkDestroyInstance(inst, nullptr);
273 return nullptr;
274 }
275
276 auto interface =
277 sk_make_sp<GrVkInterface>(getProc, inst, device, extensionFlags);
278 if (!interface->validate(extensionFlags)) {
279 SkDebugf("Vulkan interface validation failed\n");
280 grVkDeviceWaitIdle(device);
281 grVkDestroyDevice(device, nullptr);
282 grVkDestroyInstance(inst, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700283 return nullptr;
284 }
285
286 VkQueue queue;
Michael Jurka3251ed82017-04-05 09:52:55 -0700287 grVkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
jvanverth633b3562016-03-23 11:01:22 -0700288
289 GrVkBackendContext* ctx = new GrVkBackendContext();
290 ctx->fInstance = inst;
291 ctx->fPhysicalDevice = physDev;
292 ctx->fDevice = device;
293 ctx->fQueue = queue;
jvanverthb0d43522016-04-21 11:46:23 -0700294 ctx->fGraphicsQueueIndex = graphicsQueueIndex;
jvanverthfd7bd452016-03-25 06:29:52 -0700295 ctx->fMinAPIVersion = kGrVkMinimumVersion;
296 ctx->fExtensions = extensionFlags;
297 ctx->fFeatures = featureFlags;
Michael Jurka3251ed82017-04-05 09:52:55 -0700298 ctx->fInterface.reset(interface.release());
Brian Salomon290c6902017-04-25 15:03:41 -0400299 ctx->fOwnsInstanceAndDevice = true;
halcanary9d524f22016-03-29 09:03:52 -0700300
jvanverth633b3562016-03-23 11:01:22 -0700301 return ctx;
302}
303
304GrVkBackendContext::~GrVkBackendContext() {
Brian Salomon290c6902017-04-25 15:03:41 -0400305 if (fInterface == nullptr || !fOwnsInstanceAndDevice) {
Michael Jurka3251ed82017-04-05 09:52:55 -0700306 return;
307 }
308
309 fInterface->fFunctions.fDeviceWaitIdle(fDevice);
310 fInterface->fFunctions.fDestroyDevice(fDevice, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700311 fDevice = VK_NULL_HANDLE;
Michael Jurka3251ed82017-04-05 09:52:55 -0700312 fInterface->fFunctions.fDestroyInstance(fInstance, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700313 fInstance = VK_NULL_HANDLE;
314}