blob: e859b19ae5560c10c7d9d74d5903b88176ec3d9f [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
8#include "vk/GrVkBackendContext.h"
jvanverthfd7bd452016-03-25 06:29:52 -07009#include "vk/GrVkExtensions.h"
jvanverth633b3562016-03-23 11:01:22 -070010#include "vk/GrVkInterface.h"
11#include "vk/GrVkUtil.h"
12
13////////////////////////////////////////////////////////////////////////////////
14// Helper code to set up Vulkan context objects
15
16#ifdef ENABLE_VK_LAYERS
jvanverthfd7bd452016-03-25 06:29:52 -070017const char* kDebugLayerNames[] = {
jvanverth633b3562016-03-23 11:01:22 -070018 // elements of VK_LAYER_LUNARG_standard_validation
egdaniel58a8d922016-04-21 08:03:10 -070019 "VK_LAYER_GOOGLE_threading",
20 "VK_LAYER_LUNARG_parameter_validation",
jvanverth633b3562016-03-23 11:01:22 -070021 "VK_LAYER_LUNARG_device_limits",
22 "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
jvanverth633b3562016-03-23 11:01:22 -070041// Create the base Vulkan objects needed by the GrVkGpu object
jvanverthb0d43522016-04-21 11:46:23 -070042const GrVkBackendContext* GrVkBackendContext::Create(uint32_t* presentQueueIndexPtr,
bsalomond1bdd1f2016-07-26 12:02:50 -070043 CanPresentFn canPresent) {
jvanverth633b3562016-03-23 11:01:22 -070044 VkPhysicalDevice physDev;
45 VkDevice device;
46 VkInstance inst;
47 VkResult err;
48
49 const VkApplicationInfo app_info = {
50 VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
51 nullptr, // pNext
52 "vktest", // pApplicationName
53 0, // applicationVersion
54 "vktest", // pEngineName
55 0, // engineVerison
56 kGrVkMinimumVersion, // apiVersion
57 };
58
jvanverthfd7bd452016-03-25 06:29:52 -070059 GrVkExtensions extensions;
60 extensions.initInstance(kGrVkMinimumVersion);
61
62 SkTArray<const char*> instanceLayerNames;
63 SkTArray<const char*> instanceExtensionNames;
64 uint32_t extensionFlags = 0;
jvanverth633b3562016-03-23 11:01:22 -070065#ifdef ENABLE_VK_LAYERS
ethannicholas384b5e92016-03-25 11:04:06 -070066 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
jvanverthfd7bd452016-03-25 06:29:52 -070067 if (extensions.hasInstanceLayer(kDebugLayerNames[i])) {
68 instanceLayerNames.push_back(kDebugLayerNames[i]);
69 }
70 }
71 if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
72 instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
73 extensionFlags |= kEXT_debug_report_GrVkExtensionFlag;
jvanverth633b3562016-03-23 11:01:22 -070074 }
jvanverth9f372462016-04-06 06:08:59 -070075#endif
76
jvanverthe50f3e72016-03-28 07:03:06 -070077 if (extensions.hasInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME)) {
78 instanceExtensionNames.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
79 extensionFlags |= kKHR_surface_GrVkExtensionFlag;
80 }
81 if (extensions.hasInstanceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
82 instanceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
83 extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
84 }
85#ifdef SK_BUILD_FOR_WIN
86 if (extensions.hasInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) {
87 instanceExtensionNames.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
88 extensionFlags |= kKHR_win32_surface_GrVkExtensionFlag;
89 }
djsollen7e731082016-06-09 13:07:13 -070090#elif defined(SK_BUILD_FOR_ANDROID)
jvanverthe50f3e72016-03-28 07:03:06 -070091 if (extensions.hasInstanceExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
92 instanceExtensionNames.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
93 extensionFlags |= kKHR_android_surface_GrVkExtensionFlag;
jvanverth1d155962016-05-23 13:13:36 -070094 }
djsollen7e731082016-06-09 13:07:13 -070095#elif defined(SK_BUILD_FOR_UNIX)
jvanverth1d155962016-05-23 13:13:36 -070096 if (extensions.hasInstanceExtension(VK_KHR_XCB_SURFACE_EXTENSION_NAME)) {
97 instanceExtensionNames.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
98 extensionFlags |= kKHR_xcb_surface_GrVkExtensionFlag;
jvanverthe50f3e72016-03-28 07:03:06 -070099 }
100#endif
jvanverth633b3562016-03-23 11:01:22 -0700101
102 const VkInstanceCreateInfo instance_create = {
ethannicholas384b5e92016-03-25 11:04:06 -0700103 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
104 nullptr, // pNext
105 0, // flags
106 &app_info, // pApplicationInfo
107 (uint32_t) instanceLayerNames.count(), // enabledLayerNameCount
108 instanceLayerNames.begin(), // ppEnabledLayerNames
109 (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
110 instanceExtensionNames.begin(), // ppEnabledExtensionNames
jvanverth633b3562016-03-23 11:01:22 -0700111 };
112
113 err = vkCreateInstance(&instance_create, nullptr, &inst);
114 if (err < 0) {
115 SkDebugf("vkCreateInstance failed: %d\n", err);
bsalomondc0fcd42016-04-11 14:21:33 -0700116 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700117 }
118
119 uint32_t gpuCount;
120 err = vkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
121 if (err) {
122 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
egdaniel8af936d2016-04-07 10:17:47 -0700123 vkDestroyInstance(inst, nullptr);
bsalomondc0fcd42016-04-11 14:21:33 -0700124 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700125 }
126 SkASSERT(gpuCount > 0);
127 // Just returning the first physical device instead of getting the whole array.
128 // TODO: find best match for our needs
129 gpuCount = 1;
130 err = vkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
131 if (err) {
132 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
egdaniel8af936d2016-04-07 10:17:47 -0700133 vkDestroyInstance(inst, nullptr);
bsalomondc0fcd42016-04-11 14:21:33 -0700134 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700135 }
136
137 // query to get the initial queue props size
138 uint32_t queueCount;
139 vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
140 SkASSERT(queueCount >= 1);
141
142 SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
143 // now get the actual queue props
144 VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
145
146 vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
147
148 // iterate to find the graphics queue
jvanverthb0d43522016-04-21 11:46:23 -0700149 uint32_t graphicsQueueIndex = queueCount;
jvanverth633b3562016-03-23 11:01:22 -0700150 for (uint32_t i = 0; i < queueCount; i++) {
151 if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
152 graphicsQueueIndex = i;
153 break;
154 }
155 }
156 SkASSERT(graphicsQueueIndex < queueCount);
157
jvanverthb0d43522016-04-21 11:46:23 -0700158 // iterate to find the present queue, if needed
159 uint32_t presentQueueIndex = graphicsQueueIndex;
160 if (presentQueueIndexPtr && canPresent) {
161 for (uint32_t i = 0; i < queueCount; i++) {
bsalomond1bdd1f2016-07-26 12:02:50 -0700162 if (canPresent(inst, physDev, i)) {
jvanverthb0d43522016-04-21 11:46:23 -0700163 presentQueueIndex = i;
164 break;
165 }
166 }
167 SkASSERT(presentQueueIndex < queueCount);
168 *presentQueueIndexPtr = presentQueueIndex;
169 }
170
jvanverthfd7bd452016-03-25 06:29:52 -0700171 extensions.initDevice(kGrVkMinimumVersion, inst, physDev);
172
173 SkTArray<const char*> deviceLayerNames;
174 SkTArray<const char*> deviceExtensionNames;
jvanverth633b3562016-03-23 11:01:22 -0700175#ifdef ENABLE_VK_LAYERS
ethannicholas384b5e92016-03-25 11:04:06 -0700176 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
jvanverthfd7bd452016-03-25 06:29:52 -0700177 if (extensions.hasDeviceLayer(kDebugLayerNames[i])) {
178 deviceLayerNames.push_back(kDebugLayerNames[i]);
179 }
jvanverth633b3562016-03-23 11:01:22 -0700180 }
181#endif
jvanverth9f372462016-04-06 06:08:59 -0700182 if (extensions.hasDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
183 deviceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
184 extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
185 }
jvanverthfd7bd452016-03-25 06:29:52 -0700186 if (extensions.hasDeviceExtension("VK_NV_glsl_shader")) {
187 deviceExtensionNames.push_back("VK_NV_glsl_shader");
188 extensionFlags |= kNV_glsl_shader_GrVkExtensionFlag;
189 }
190
191 // query to get the physical device properties
192 VkPhysicalDeviceFeatures deviceFeatures;
193 vkGetPhysicalDeviceFeatures(physDev, &deviceFeatures);
halcanary9d524f22016-03-29 09:03:52 -0700194 // this looks like it would slow things down,
jvanverthfd7bd452016-03-25 06:29:52 -0700195 // and we can't depend on it on all platforms
196 deviceFeatures.robustBufferAccess = VK_FALSE;
197
198 uint32_t featureFlags = 0;
199 if (deviceFeatures.geometryShader) {
200 featureFlags |= kGeometryShader_GrVkFeatureFlag;
201 }
202 if (deviceFeatures.dualSrcBlend) {
203 featureFlags |= kDualSrcBlend_GrVkFeatureFlag;
204 }
205 if (deviceFeatures.sampleRateShading) {
206 featureFlags |= kSampleRateShading_GrVkFeatureFlag;
207 }
jvanverth633b3562016-03-23 11:01:22 -0700208
209 float queuePriorities[1] = { 0.0 };
210 // Here we assume no need for swapchain queue
211 // If one is needed, the client will need its own setup code
jvanverthb0d43522016-04-21 11:46:23 -0700212 const VkDeviceQueueCreateInfo queueInfo[2] = {
213 {
214 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
215 nullptr, // pNext
216 0, // VkDeviceQueueCreateFlags
217 graphicsQueueIndex, // queueFamilyIndex
218 1, // queueCount
219 queuePriorities, // pQueuePriorities
220 },
221 {
222 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
223 nullptr, // pNext
224 0, // VkDeviceQueueCreateFlags
225 presentQueueIndex, // queueFamilyIndex
226 1, // queueCount
227 queuePriorities, // pQueuePriorities
228 }
jvanverth633b3562016-03-23 11:01:22 -0700229 };
jvanverthb0d43522016-04-21 11:46:23 -0700230 uint32_t queueInfoCount = (presentQueueIndex != graphicsQueueIndex) ? 2 : 1;
231
jvanverth633b3562016-03-23 11:01:22 -0700232 const VkDeviceCreateInfo deviceInfo = {
ethannicholas384b5e92016-03-25 11:04:06 -0700233 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
234 nullptr, // pNext
235 0, // VkDeviceCreateFlags
jvanverthb0d43522016-04-21 11:46:23 -0700236 queueInfoCount, // queueCreateInfoCount
237 queueInfo, // pQueueCreateInfos
ethannicholas384b5e92016-03-25 11:04:06 -0700238 (uint32_t) deviceLayerNames.count(), // layerCount
239 deviceLayerNames.begin(), // ppEnabledLayerNames
240 (uint32_t) deviceExtensionNames.count(), // extensionCount
241 deviceExtensionNames.begin(), // ppEnabledExtensionNames
242 &deviceFeatures // ppEnabledFeatures
jvanverth633b3562016-03-23 11:01:22 -0700243 };
244
245 err = vkCreateDevice(physDev, &deviceInfo, nullptr, &device);
246 if (err) {
247 SkDebugf("CreateDevice failed: %d\n", err);
egdaniel8af936d2016-04-07 10:17:47 -0700248 vkDestroyInstance(inst, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700249 return nullptr;
250 }
251
252 VkQueue queue;
253 vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
254
255 GrVkBackendContext* ctx = new GrVkBackendContext();
256 ctx->fInstance = inst;
257 ctx->fPhysicalDevice = physDev;
258 ctx->fDevice = device;
259 ctx->fQueue = queue;
jvanverthb0d43522016-04-21 11:46:23 -0700260 ctx->fGraphicsQueueIndex = graphicsQueueIndex;
jvanverthfd7bd452016-03-25 06:29:52 -0700261 ctx->fMinAPIVersion = kGrVkMinimumVersion;
262 ctx->fExtensions = extensionFlags;
263 ctx->fFeatures = featureFlags;
264 ctx->fInterface.reset(GrVkCreateInterface(inst, device, extensionFlags));
halcanary9d524f22016-03-29 09:03:52 -0700265
jvanverth633b3562016-03-23 11:01:22 -0700266 return ctx;
267}
268
269GrVkBackendContext::~GrVkBackendContext() {
egdanielf4ace412016-04-11 13:41:51 -0700270 vkDeviceWaitIdle(fDevice);
jvanverth633b3562016-03-23 11:01:22 -0700271 vkDestroyDevice(fDevice, nullptr);
272 fDevice = VK_NULL_HANDLE;
273 vkDestroyInstance(fInstance, nullptr);
274 fInstance = VK_NULL_HANDLE;
275}