Index: src/gpu/vk/GrVkBackendContext.cpp |
diff --git a/src/gpu/vk/GrVkBackendContext.cpp b/src/gpu/vk/GrVkBackendContext.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c169c620a133787fe022420ccdc788e8942d7bc0 |
--- /dev/null |
+++ b/src/gpu/vk/GrVkBackendContext.cpp |
@@ -0,0 +1,252 @@ |
+/* |
+ * Copyright 2015 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "vk/GrVkBackendContext.h" |
+#include "vk/GrVkInterface.h" |
+#include "vk/GrVkUtil.h" |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Helper code to set up Vulkan context objects |
+ |
+#ifdef ENABLE_VK_LAYERS |
+const char* kEnabledLayerNames[] = { |
+ // elements of VK_LAYER_LUNARG_standard_validation |
+ "VK_LAYER_LUNARG_threading", |
+ "VK_LAYER_LUNARG_param_checker", |
+ "VK_LAYER_LUNARG_device_limits", |
+ "VK_LAYER_LUNARG_object_tracker", |
+ "VK_LAYER_LUNARG_image", |
+ "VK_LAYER_LUNARG_mem_tracker", |
+ "VK_LAYER_LUNARG_draw_state", |
+ "VK_LAYER_LUNARG_swapchain", |
+ "VK_LAYER_GOOGLE_unique_objects", |
+ // not included in standard_validation |
+ //"VK_LAYER_LUNARG_api_dump", |
+}; |
+const char* kEnabledInstanceExtensionNames[] = { |
+ VK_EXT_DEBUG_REPORT_EXTENSION_NAME |
+}; |
+ |
+bool verify_instance_layers() { |
+ // make sure we can actually use the extensions and layers above |
+ uint32_t extensionCount; |
+ VkResult res = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); |
+ if (VK_SUCCESS != res) { |
+ return false; |
+ } |
+ VkExtensionProperties* extensions = new VkExtensionProperties[extensionCount]; |
+ res = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions); |
+ if (VK_SUCCESS != res) { |
+ return false; |
+ } |
+ int instanceExtensionsFound = 0; |
+ for (uint32_t j = 0; j < ARRAYSIZE(kEnabledInstanceExtensionNames); ++j) { |
+ for (uint32_t i = 0; i < extensionCount; ++i) { |
+ if (!strncmp(extensions[i].extensionName, kEnabledInstanceExtensionNames[j], |
+ strlen(kEnabledInstanceExtensionNames[j]))) { |
+ ++instanceExtensionsFound; |
+ break; |
+ } |
+ } |
+ } |
+ delete[] extensions; |
+ |
+ uint32_t layerCount; |
+ res = vkEnumerateInstanceLayerProperties(&layerCount, nullptr); |
+ if (VK_SUCCESS != res) { |
+ return false; |
+ } |
+ VkLayerProperties* layers = new VkLayerProperties[layerCount]; |
+ res = vkEnumerateInstanceLayerProperties(&layerCount, layers); |
+ if (VK_SUCCESS != res) { |
+ return false; |
+ } |
+ int instanceLayersFound = 0; |
+ for (uint32_t j = 0; j < ARRAYSIZE(kEnabledLayerNames); ++j) { |
+ for (uint32_t i = 0; i < layerCount; ++i) { |
+ if (!strncmp(layers[i].layerName, kEnabledLayerNames[j], |
+ strlen(kEnabledLayerNames[j]))) { |
+ ++instanceLayersFound; |
+ break; |
+ } |
+ } |
+ } |
+ delete[] layers; |
+ |
+ return instanceExtensionsFound == ARRAYSIZE(kEnabledInstanceExtensionNames) && |
+ instanceLayersFound == ARRAYSIZE(kEnabledLayerNames); |
+} |
+ |
+bool verify_device_layers(VkPhysicalDevice physDev) { |
+ uint32_t layerCount; |
+ VkResult res = vkEnumerateDeviceLayerProperties(physDev, &layerCount, nullptr); |
+ if (VK_SUCCESS != res) { |
+ return false; |
+ } |
+ VkLayerProperties* layers = new VkLayerProperties[layerCount]; |
+ res = vkEnumerateDeviceLayerProperties(physDev, &layerCount, layers); |
+ if (VK_SUCCESS != res) { |
+ return false; |
+ } |
+ int deviceLayersFound = 0; |
+ for (uint32_t j = 0; j < ARRAYSIZE(kEnabledLayerNames); ++j) { |
+ for (uint32_t i = 0; i < layerCount; ++i) { |
+ if (!strncmp(layers[i].layerName, kEnabledLayerNames[j], |
+ strlen(kEnabledLayerNames[j]))) { |
+ ++deviceLayersFound; |
+ break; |
+ } |
+ } |
+ } |
+ delete[] layers; |
+ |
+ return deviceLayersFound == ARRAYSIZE(kEnabledLayerNames); |
+} |
+#endif |
+ |
+// Create the base Vulkan objects needed by the GrVkGpu object |
+const GrVkBackendContext* GrVkBackendContext::Create() { |
+ VkPhysicalDevice physDev; |
+ VkDevice device; |
+ VkInstance inst; |
+ VkResult err; |
+ |
+ const VkApplicationInfo app_info = { |
+ VK_STRUCTURE_TYPE_APPLICATION_INFO, // sType |
+ nullptr, // pNext |
+ "vktest", // pApplicationName |
+ 0, // applicationVersion |
+ "vktest", // pEngineName |
+ 0, // engineVerison |
+ kGrVkMinimumVersion, // apiVersion |
+ }; |
+ |
+ const char** enabledLayerNames = nullptr; |
+ int enabledLayerCount = 0; |
+ const char** enabledInstanceExtensionNames = nullptr; |
+ int enabledInstanceExtensionCount = 0; |
+#ifdef ENABLE_VK_LAYERS |
+ if (verify_instance_layers()) { |
+ enabledLayerNames = kEnabledLayerNames; |
+ enabledLayerCount = ARRAYSIZE(kEnabledLayerNames); |
+ enabledInstanceExtensionNames = kEnabledInstanceExtensionNames; |
+ enabledInstanceExtensionCount = ARRAYSIZE(kEnabledInstanceExtensionNames); |
+ } |
+#endif |
+ |
+ const VkInstanceCreateInfo instance_create = { |
+ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType |
+ nullptr, // pNext |
+ 0, // flags |
+ &app_info, // pApplicationInfo |
+ enabledLayerCount, // enabledLayerNameCount |
+ enabledLayerNames, // ppEnabledLayerNames |
+ enabledInstanceExtensionCount, // enabledExtensionNameCount |
+ enabledInstanceExtensionNames, // ppEnabledExtensionNames |
+ }; |
+ |
+ err = vkCreateInstance(&instance_create, nullptr, &inst); |
+ if (err < 0) { |
+ SkDebugf("vkCreateInstance failed: %d\n", err); |
+ SkFAIL("failing"); |
+ } |
+ |
+ uint32_t gpuCount; |
+ err = vkEnumeratePhysicalDevices(inst, &gpuCount, nullptr); |
+ if (err) { |
+ SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err); |
+ SkFAIL("failing"); |
+ } |
+ SkASSERT(gpuCount > 0); |
+ // Just returning the first physical device instead of getting the whole array. |
+ // TODO: find best match for our needs |
+ gpuCount = 1; |
+ err = vkEnumeratePhysicalDevices(inst, &gpuCount, &physDev); |
+ if (err) { |
+ SkDebugf("vkEnumeratePhysicalDevices failed: %d\n", err); |
+ SkFAIL("failing"); |
+ } |
+ |
+ // query to get the initial queue props size |
+ uint32_t queueCount; |
+ vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr); |
+ SkASSERT(queueCount >= 1); |
+ |
+ SkAutoMalloc queuePropsAlloc(queueCount * sizeof(VkQueueFamilyProperties)); |
+ // now get the actual queue props |
+ VkQueueFamilyProperties* queueProps = (VkQueueFamilyProperties*)queuePropsAlloc.get(); |
+ |
+ vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueProps); |
+ |
+ // iterate to find the graphics queue |
+ uint32_t graphicsQueueIndex = -1; |
+ for (uint32_t i = 0; i < queueCount; i++) { |
+ if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { |
+ graphicsQueueIndex = i; |
+ break; |
+ } |
+ } |
+ SkASSERT(graphicsQueueIndex < queueCount); |
+ |
+#ifdef ENABLE_VK_LAYERS |
+ // unlikely that the device will have different layers than the instance, but good to check |
+ if (!verify_device_layers(physDev)) { |
+ enabledLayerNames = nullptr; |
+ enabledLayerCount = 0; |
+ } |
+#endif |
+ |
+ float queuePriorities[1] = { 0.0 }; |
+ // Here we assume no need for swapchain queue |
+ // If one is needed, the client will need its own setup code |
+ const VkDeviceQueueCreateInfo queueInfo = { |
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType |
+ nullptr, // pNext |
+ 0, // VkDeviceQueueCreateFlags |
+ graphicsQueueIndex, // queueFamilyIndex |
+ 1, // queueCount |
+ queuePriorities, // pQueuePriorities |
+ }; |
+ const VkDeviceCreateInfo deviceInfo = { |
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType |
+ nullptr, // pNext |
+ 0, // VkDeviceCreateFlags |
+ 1, // queueCreateInfoCount |
+ &queueInfo, // pQueueCreateInfos |
+ enabledLayerCount, // layerCount |
+ enabledLayerNames, // ppEnabledLayerNames |
+ 0, // extensionCount |
+ nullptr, // ppEnabledExtensionNames |
+ nullptr // ppEnabledFeatures |
+ }; |
+ |
+ err = vkCreateDevice(physDev, &deviceInfo, nullptr, &device); |
+ if (err) { |
+ SkDebugf("CreateDevice failed: %d\n", err); |
+ return nullptr; |
+ } |
+ |
+ VkQueue queue; |
+ vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue); |
+ |
+ GrVkBackendContext* ctx = new GrVkBackendContext(); |
+ ctx->fInstance = inst; |
+ ctx->fPhysicalDevice = physDev; |
+ ctx->fDevice = device; |
+ ctx->fQueue = queue; |
+ ctx->fQueueFamilyIndex = graphicsQueueIndex; |
+ ctx->fInterface.reset(GrVkCreateInterface(inst, physDev, device)); |
+ |
+ return ctx; |
+} |
+ |
+GrVkBackendContext::~GrVkBackendContext() { |
+ vkDestroyDevice(fDevice, nullptr); |
+ fDevice = VK_NULL_HANDLE; |
+ vkDestroyInstance(fInstance, nullptr); |
+ fInstance = VK_NULL_HANDLE; |
+} |