blob: d189840adbed7bddf58a66c40a0400b4c7ce2e4b [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
19 "VK_LAYER_LUNARG_threading",
20 "VK_LAYER_LUNARG_param_checker",
21 "VK_LAYER_LUNARG_device_limits",
22 "VK_LAYER_LUNARG_object_tracker",
23 "VK_LAYER_LUNARG_image",
24 "VK_LAYER_LUNARG_mem_tracker",
25 "VK_LAYER_LUNARG_draw_state",
26 "VK_LAYER_LUNARG_swapchain",
jvanverth9f372462016-04-06 06:08:59 -070027 //"VK_LAYER_GOOGLE_unique_objects",
jvanverth633b3562016-03-23 11:01:22 -070028 // not included in standard_validation
29 //"VK_LAYER_LUNARG_api_dump",
jvanverthfd7bd452016-03-25 06:29:52 -070030 //"VK_LAYER_LUNARG_vktrace",
31 //"VK_LAYER_LUNARG_screenshot",
jvanverth633b3562016-03-23 11:01:22 -070032};
jvanverth633b3562016-03-23 11:01:22 -070033#endif
34
jvanverthfd7bd452016-03-25 06:29:52 -070035// the minimum version of Vulkan supported
36const uint32_t kGrVkMinimumVersion = VK_MAKE_VERSION(1, 0, 3);
37
jvanverth633b3562016-03-23 11:01:22 -070038// Create the base Vulkan objects needed by the GrVkGpu object
39const GrVkBackendContext* GrVkBackendContext::Create() {
40 VkPhysicalDevice physDev;
41 VkDevice device;
42 VkInstance inst;
43 VkResult err;
44
45 const VkApplicationInfo app_info = {
46 VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType
47 nullptr, // pNext
48 "vktest", // pApplicationName
49 0, // applicationVersion
50 "vktest", // pEngineName
51 0, // engineVerison
52 kGrVkMinimumVersion, // apiVersion
53 };
54
jvanverthfd7bd452016-03-25 06:29:52 -070055 GrVkExtensions extensions;
56 extensions.initInstance(kGrVkMinimumVersion);
57
58 SkTArray<const char*> instanceLayerNames;
59 SkTArray<const char*> instanceExtensionNames;
60 uint32_t extensionFlags = 0;
jvanverth633b3562016-03-23 11:01:22 -070061#ifdef ENABLE_VK_LAYERS
ethannicholas384b5e92016-03-25 11:04:06 -070062 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
jvanverthfd7bd452016-03-25 06:29:52 -070063 if (extensions.hasInstanceLayer(kDebugLayerNames[i])) {
64 instanceLayerNames.push_back(kDebugLayerNames[i]);
65 }
66 }
67 if (extensions.hasInstanceExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
68 instanceExtensionNames.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
69 extensionFlags |= kEXT_debug_report_GrVkExtensionFlag;
jvanverth633b3562016-03-23 11:01:22 -070070 }
jvanverth9f372462016-04-06 06:08:59 -070071#endif
72
jvanverthe50f3e72016-03-28 07:03:06 -070073 if (extensions.hasInstanceExtension(VK_KHR_SURFACE_EXTENSION_NAME)) {
74 instanceExtensionNames.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
75 extensionFlags |= kKHR_surface_GrVkExtensionFlag;
76 }
77 if (extensions.hasInstanceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
78 instanceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
79 extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
80 }
81#ifdef SK_BUILD_FOR_WIN
82 if (extensions.hasInstanceExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME)) {
83 instanceExtensionNames.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
84 extensionFlags |= kKHR_win32_surface_GrVkExtensionFlag;
85 }
86#elif SK_BUILD_FOR_ANDROID
87 if (extensions.hasInstanceExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME)) {
88 instanceExtensionNames.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
89 extensionFlags |= kKHR_android_surface_GrVkExtensionFlag;
90}
91#elif SK_BUILD_FOR_UNIX
92 if (extensions.hasInstanceExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) {
93 instanceExtensionNames.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
94 extensionFlags |= kKHR_xlib_surface_GrVkExtensionFlag;
95 }
96#endif
jvanverth633b3562016-03-23 11:01:22 -070097
98 const VkInstanceCreateInfo instance_create = {
ethannicholas384b5e92016-03-25 11:04:06 -070099 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
100 nullptr, // pNext
101 0, // flags
102 &app_info, // pApplicationInfo
103 (uint32_t) instanceLayerNames.count(), // enabledLayerNameCount
104 instanceLayerNames.begin(), // ppEnabledLayerNames
105 (uint32_t) instanceExtensionNames.count(), // enabledExtensionNameCount
106 instanceExtensionNames.begin(), // ppEnabledExtensionNames
jvanverth633b3562016-03-23 11:01:22 -0700107 };
108
109 err = vkCreateInstance(&instance_create, nullptr, &inst);
110 if (err < 0) {
111 SkDebugf("vkCreateInstance failed: %d\n", err);
bsalomondc0fcd42016-04-11 14:21:33 -0700112 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700113 }
114
115 uint32_t gpuCount;
116 err = vkEnumeratePhysicalDevices(inst, &gpuCount, nullptr);
117 if (err) {
118 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
egdaniel8af936d2016-04-07 10:17:47 -0700119 vkDestroyInstance(inst, nullptr);
bsalomondc0fcd42016-04-11 14:21:33 -0700120 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700121 }
122 SkASSERT(gpuCount > 0);
123 // Just returning the first physical device instead of getting the whole array.
124 // TODO: find best match for our needs
125 gpuCount = 1;
126 err = vkEnumeratePhysicalDevices(inst, &gpuCount, &physDev);
127 if (err) {
128 SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err);
egdaniel8af936d2016-04-07 10:17:47 -0700129 vkDestroyInstance(inst, nullptr);
bsalomondc0fcd42016-04-11 14:21:33 -0700130 return nullptr;
jvanverth633b3562016-03-23 11:01:22 -0700131 }
132
133 // query to get the initial queue props size
134 uint32_t queueCount;
135 vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
136 SkASSERT(queueCount >= 1);
137
138 SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties));
139 // now get the actual queue props
140 VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get();
141
142 vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps);
143
144 // iterate to find the graphics queue
145 uint32_t graphicsQueueIndex = -1;
146 for (uint32_t i = 0; i < queueCount; i++) {
147 if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
148 graphicsQueueIndex = i;
149 break;
150 }
151 }
152 SkASSERT(graphicsQueueIndex < queueCount);
153
jvanverthfd7bd452016-03-25 06:29:52 -0700154 extensions.initDevice(kGrVkMinimumVersion, inst, physDev);
155
156 SkTArray<const char*> deviceLayerNames;
157 SkTArray<const char*> deviceExtensionNames;
jvanverth633b3562016-03-23 11:01:22 -0700158#ifdef ENABLE_VK_LAYERS
ethannicholas384b5e92016-03-25 11:04:06 -0700159 for (size_t i = 0; i < SK_ARRAY_COUNT(kDebugLayerNames); ++i) {
jvanverthfd7bd452016-03-25 06:29:52 -0700160 if (extensions.hasDeviceLayer(kDebugLayerNames[i])) {
161 deviceLayerNames.push_back(kDebugLayerNames[i]);
162 }
jvanverth633b3562016-03-23 11:01:22 -0700163 }
164#endif
jvanverth9f372462016-04-06 06:08:59 -0700165 if (extensions.hasDeviceExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)) {
166 deviceExtensionNames.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
167 extensionFlags |= kKHR_swapchain_GrVkExtensionFlag;
168 }
jvanverthfd7bd452016-03-25 06:29:52 -0700169 if (extensions.hasDeviceExtension("VK_NV_glsl_shader")) {
170 deviceExtensionNames.push_back("VK_NV_glsl_shader");
171 extensionFlags |= kNV_glsl_shader_GrVkExtensionFlag;
172 }
173
174 // query to get the physical device properties
175 VkPhysicalDeviceFeatures deviceFeatures;
176 vkGetPhysicalDeviceFeatures(physDev, &deviceFeatures);
halcanary9d524f22016-03-29 09:03:52 -0700177 // this looks like it would slow things down,
jvanverthfd7bd452016-03-25 06:29:52 -0700178 // and we can't depend on it on all platforms
179 deviceFeatures.robustBufferAccess = VK_FALSE;
180
181 uint32_t featureFlags = 0;
182 if (deviceFeatures.geometryShader) {
183 featureFlags |= kGeometryShader_GrVkFeatureFlag;
184 }
185 if (deviceFeatures.dualSrcBlend) {
186 featureFlags |= kDualSrcBlend_GrVkFeatureFlag;
187 }
188 if (deviceFeatures.sampleRateShading) {
189 featureFlags |= kSampleRateShading_GrVkFeatureFlag;
190 }
jvanverth633b3562016-03-23 11:01:22 -0700191
192 float queuePriorities[1] = { 0.0 };
193 // Here we assume no need for swapchain queue
194 // If one is needed, the client will need its own setup code
195 const VkDeviceQueueCreateInfo queueInfo = {
196 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
197 nullptr, // pNext
198 0, // VkDeviceQueueCreateFlags
199 graphicsQueueIndex, // queueFamilyIndex
200 1, // queueCount
201 queuePriorities, // pQueuePriorities
202 };
203 const VkDeviceCreateInfo deviceInfo = {
ethannicholas384b5e92016-03-25 11:04:06 -0700204 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
205 nullptr, // pNext
206 0, // VkDeviceCreateFlags
207 1, // queueCreateInfoCount
208 &queueInfo, // pQueueCreateInfos
209 (uint32_t) deviceLayerNames.count(), // layerCount
210 deviceLayerNames.begin(), // ppEnabledLayerNames
211 (uint32_t) deviceExtensionNames.count(), // extensionCount
212 deviceExtensionNames.begin(), // ppEnabledExtensionNames
213 &deviceFeatures // ppEnabledFeatures
jvanverth633b3562016-03-23 11:01:22 -0700214 };
215
216 err = vkCreateDevice(physDev, &deviceInfo, nullptr, &device);
217 if (err) {
218 SkDebugf("CreateDevice failed: %d\n", err);
egdaniel8af936d2016-04-07 10:17:47 -0700219 vkDestroyInstance(inst, nullptr);
jvanverth633b3562016-03-23 11:01:22 -0700220 return nullptr;
221 }
222
223 VkQueue queue;
224 vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
225
226 GrVkBackendContext* ctx = new GrVkBackendContext();
227 ctx->fInstance = inst;
228 ctx->fPhysicalDevice = physDev;
229 ctx->fDevice = device;
230 ctx->fQueue = queue;
231 ctx->fQueueFamilyIndex = graphicsQueueIndex;
jvanverthfd7bd452016-03-25 06:29:52 -0700232 ctx->fMinAPIVersion = kGrVkMinimumVersion;
233 ctx->fExtensions = extensionFlags;
234 ctx->fFeatures = featureFlags;
235 ctx->fInterface.reset(GrVkCreateInterface(inst, device, extensionFlags));
halcanary9d524f22016-03-29 09:03:52 -0700236
jvanverth633b3562016-03-23 11:01:22 -0700237 return ctx;
238}
239
240GrVkBackendContext::~GrVkBackendContext() {
egdanielf4ace412016-04-11 13:41:51 -0700241 vkDeviceWaitIdle(fDevice);
jvanverth633b3562016-03-23 11:01:22 -0700242 vkDestroyDevice(fDevice, nullptr);
243 fDevice = VK_NULL_HANDLE;
244 vkDestroyInstance(fInstance, nullptr);
245 fInstance = VK_NULL_HANDLE;
246}