blob: aa9e0fe8379240f6ad8398c940554beb9b75aa8c [file] [log] [blame]
Jamie Madill9e54b5a2016-05-25 12:57:39 -04001//
2// Copyright 2016 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6// RendererVk.cpp:
7// Implements the class methods for RendererVk.
8//
9
10#include "libANGLE/renderer/vulkan/RendererVk.h"
11
Jamie Madill4d0bf552016-12-28 15:45:24 -050012// Placing this first seems to solve an intellisense bug.
13#include "libANGLE/renderer/vulkan/renderervk_utils.h"
14
Jamie Madille09bd5d2016-11-29 16:20:35 -050015#include <EGL/eglext.h>
16
Jamie Madill9e54b5a2016-05-25 12:57:39 -040017#include "common/debug.h"
Jamie Madilla66779f2017-01-06 10:43:44 -050018#include "common/system_utils.h"
Jamie Madill4d0bf552016-12-28 15:45:24 -050019#include "libANGLE/renderer/driver_utils.h"
Jamie Madille09bd5d2016-11-29 16:20:35 -050020#include "libANGLE/renderer/vulkan/CompilerVk.h"
21#include "libANGLE/renderer/vulkan/FramebufferVk.h"
Jamie Madill8ecf7f92017-01-13 17:29:52 -050022#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
Jamie Madille09bd5d2016-11-29 16:20:35 -050023#include "libANGLE/renderer/vulkan/TextureVk.h"
24#include "libANGLE/renderer/vulkan/VertexArrayVk.h"
Jamie Madill7b57b9d2017-01-13 09:33:38 -050025#include "libANGLE/renderer/vulkan/formatutilsvk.h"
Jamie Madille09bd5d2016-11-29 16:20:35 -050026#include "platform/Platform.h"
Jamie Madill9e54b5a2016-05-25 12:57:39 -040027
28namespace rx
29{
30
Jamie Madille09bd5d2016-11-29 16:20:35 -050031namespace
32{
33
34VkResult VerifyExtensionsPresent(const std::vector<VkExtensionProperties> &extensionProps,
35 const std::vector<const char *> &enabledExtensionNames)
36{
37 // Compile the extensions names into a set.
38 std::set<std::string> extensionNames;
39 for (const auto &extensionProp : extensionProps)
40 {
41 extensionNames.insert(extensionProp.extensionName);
42 }
43
44 for (const auto &extensionName : enabledExtensionNames)
45 {
46 if (extensionNames.count(extensionName) == 0)
47 {
48 return VK_ERROR_EXTENSION_NOT_PRESENT;
49 }
50 }
51
52 return VK_SUCCESS;
53}
54
Jamie Madill0448ec82016-12-23 13:41:47 -050055VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
56 VkDebugReportObjectTypeEXT objectType,
57 uint64_t object,
58 size_t location,
59 int32_t messageCode,
60 const char *layerPrefix,
61 const char *message,
62 void *userData)
63{
64 if ((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0)
65 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -050066 ERR() << message;
Jamie Madill0448ec82016-12-23 13:41:47 -050067#if !defined(NDEBUG)
68 // Abort the call in Debug builds.
69 return VK_TRUE;
70#endif
71 }
72 else if ((flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0)
73 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -050074 WARN() << message;
Jamie Madill0448ec82016-12-23 13:41:47 -050075 }
76 else
77 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -050078 // Uncomment this if you want Vulkan spam.
79 // WARN() << message;
Jamie Madill0448ec82016-12-23 13:41:47 -050080 }
81
82 return VK_FALSE;
83}
84
Jamie Madille09bd5d2016-11-29 16:20:35 -050085} // anonymous namespace
86
Jamie Madill0448ec82016-12-23 13:41:47 -050087RendererVk::RendererVk()
88 : mCapsInitialized(false),
89 mInstance(VK_NULL_HANDLE),
90 mEnableValidationLayers(false),
Jamie Madill4d0bf552016-12-28 15:45:24 -050091 mDebugReportCallback(VK_NULL_HANDLE),
92 mPhysicalDevice(VK_NULL_HANDLE),
93 mQueue(VK_NULL_HANDLE),
94 mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
95 mDevice(VK_NULL_HANDLE),
Jamie Madill8ecf7f92017-01-13 17:29:52 -050096 mHostVisibleMemoryIndex(std::numeric_limits<uint32_t>::max()),
97 mGlslangWrapper(nullptr)
Jamie Madill9e54b5a2016-05-25 12:57:39 -040098{
99}
100
101RendererVk::~RendererVk()
102{
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500103 if (mGlslangWrapper)
104 {
105 GlslangWrapper::ReleaseReference();
106 mGlslangWrapper = nullptr;
107 }
108
Jamie Madill5deea722017-02-16 10:44:46 -0500109 if (mCommandBuffer.valid())
110 {
111 mCommandBuffer.destroy(mDevice);
112 }
113
114 if (mCommandPool.valid())
115 {
116 mCommandPool.destroy(mDevice);
117 }
Jamie Madill4d0bf552016-12-28 15:45:24 -0500118
119 if (mDevice)
120 {
121 vkDestroyDevice(mDevice, nullptr);
122 mDevice = VK_NULL_HANDLE;
123 }
124
Jamie Madill0448ec82016-12-23 13:41:47 -0500125 if (mDebugReportCallback)
126 {
127 ASSERT(mInstance);
128 auto destroyDebugReportCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
129 vkGetInstanceProcAddr(mInstance, "vkDestroyDebugReportCallbackEXT"));
130 ASSERT(destroyDebugReportCallback);
131 destroyDebugReportCallback(mInstance, mDebugReportCallback, nullptr);
132 }
133
Jamie Madill4d0bf552016-12-28 15:45:24 -0500134 if (mInstance)
135 {
136 vkDestroyInstance(mInstance, nullptr);
137 mInstance = VK_NULL_HANDLE;
138 }
139
140 mPhysicalDevice = VK_NULL_HANDLE;
Jamie Madill327ba852016-11-30 12:38:28 -0500141}
142
Jamie Madille09bd5d2016-11-29 16:20:35 -0500143vk::Error RendererVk::initialize(const egl::AttributeMap &attribs)
Jamie Madill327ba852016-11-30 12:38:28 -0500144{
Jamie Madilla66779f2017-01-06 10:43:44 -0500145#if !defined(NDEBUG)
146 // Validation layers enabled by default in Debug.
147 mEnableValidationLayers = true;
148#endif
149
150 // If specified in the attributes, override the default.
151 if (attribs.contains(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE))
152 {
153 mEnableValidationLayers =
154 (attribs.get(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE, EGL_FALSE) == EGL_TRUE);
155 }
156
157 // If we're loading the validation layers, we could be running from any random directory.
158 // Change to the executable directory so we can find the layers, then change back to the
159 // previous directory to be safe we don't disrupt the application.
160 std::string previousCWD;
161
162 if (mEnableValidationLayers)
163 {
164 const auto &cwd = angle::GetCWD();
165 if (!cwd.valid())
166 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500167 ERR() << "Error getting CWD for Vulkan layers init.";
Jamie Madilla66779f2017-01-06 10:43:44 -0500168 mEnableValidationLayers = false;
169 }
170 else
171 {
172 previousCWD = cwd.value();
173 }
174 const char *exeDir = angle::GetExecutableDirectory();
175 angle::SetCWD(exeDir);
176 }
177
Jamie Madill0448ec82016-12-23 13:41:47 -0500178 // Gather global layer properties.
179 uint32_t instanceLayerCount = 0;
180 ANGLE_VK_TRY(vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr));
181
182 std::vector<VkLayerProperties> instanceLayerProps(instanceLayerCount);
183 if (instanceLayerCount > 0)
184 {
185 ANGLE_VK_TRY(
186 vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayerProps.data()));
187 }
188
Jamie Madille09bd5d2016-11-29 16:20:35 -0500189 uint32_t instanceExtensionCount = 0;
190 ANGLE_VK_TRY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount, nullptr));
191
192 std::vector<VkExtensionProperties> instanceExtensionProps(instanceExtensionCount);
193 if (instanceExtensionCount > 0)
194 {
195 ANGLE_VK_TRY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount,
196 instanceExtensionProps.data()));
197 }
198
Jamie Madill0448ec82016-12-23 13:41:47 -0500199 if (mEnableValidationLayers)
200 {
201 // Verify the standard validation layers are available.
202 if (!HasStandardValidationLayer(instanceLayerProps))
203 {
204 // Generate an error if the attribute was requested, warning otherwise.
205 if (attribs.contains(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE))
206 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500207 ERR() << "Vulkan standard validation layers are missing.";
Jamie Madill0448ec82016-12-23 13:41:47 -0500208 }
209 else
210 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500211 WARN() << "Vulkan standard validation layers are missing.";
Jamie Madill0448ec82016-12-23 13:41:47 -0500212 }
213 mEnableValidationLayers = false;
214 }
215 }
216
Jamie Madille09bd5d2016-11-29 16:20:35 -0500217 std::vector<const char *> enabledInstanceExtensions;
218 enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
219#if defined(ANGLE_PLATFORM_WINDOWS)
220 enabledInstanceExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
221#else
222#error Unsupported Vulkan platform.
223#endif // defined(ANGLE_PLATFORM_WINDOWS)
224
Jamie Madill0448ec82016-12-23 13:41:47 -0500225 // TODO(jmadill): Should be able to continue initialization if debug report ext missing.
226 if (mEnableValidationLayers)
227 {
228 enabledInstanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
229 }
230
Jamie Madille09bd5d2016-11-29 16:20:35 -0500231 // Verify the required extensions are in the extension names set. Fail if not.
232 ANGLE_VK_TRY(VerifyExtensionsPresent(instanceExtensionProps, enabledInstanceExtensions));
233
Jamie Madill327ba852016-11-30 12:38:28 -0500234 VkApplicationInfo applicationInfo;
235 applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
236 applicationInfo.pNext = nullptr;
237 applicationInfo.pApplicationName = "ANGLE";
238 applicationInfo.applicationVersion = 1;
239 applicationInfo.pEngineName = "ANGLE";
240 applicationInfo.engineVersion = 1;
241 applicationInfo.apiVersion = VK_API_VERSION_1_0;
242
243 VkInstanceCreateInfo instanceInfo;
244 instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
245 instanceInfo.pNext = nullptr;
246 instanceInfo.flags = 0;
247 instanceInfo.pApplicationInfo = &applicationInfo;
248
Jamie Madille09bd5d2016-11-29 16:20:35 -0500249 // Enable requested layers and extensions.
250 instanceInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
251 instanceInfo.ppEnabledExtensionNames =
252 enabledInstanceExtensions.empty() ? nullptr : enabledInstanceExtensions.data();
Jamie Madill0448ec82016-12-23 13:41:47 -0500253 instanceInfo.enabledLayerCount = mEnableValidationLayers ? 1u : 0u;
254 instanceInfo.ppEnabledLayerNames =
255 mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
Jamie Madill327ba852016-11-30 12:38:28 -0500256
257 ANGLE_VK_TRY(vkCreateInstance(&instanceInfo, nullptr, &mInstance));
258
Jamie Madill0448ec82016-12-23 13:41:47 -0500259 if (mEnableValidationLayers)
260 {
Jamie Madilla66779f2017-01-06 10:43:44 -0500261 // Change back to the previous working directory now that we've loaded the instance -
262 // the validation layers should be loaded at this point.
263 angle::SetCWD(previousCWD.c_str());
264
Jamie Madill0448ec82016-12-23 13:41:47 -0500265 VkDebugReportCallbackCreateInfoEXT debugReportInfo;
266
267 debugReportInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
268 debugReportInfo.pNext = nullptr;
269 debugReportInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT |
270 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
271 VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT;
272 debugReportInfo.pfnCallback = &DebugReportCallback;
273 debugReportInfo.pUserData = this;
274
275 auto createDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
276 vkGetInstanceProcAddr(mInstance, "vkCreateDebugReportCallbackEXT"));
277 ASSERT(createDebugReportCallback);
278 ANGLE_VK_TRY(
279 createDebugReportCallback(mInstance, &debugReportInfo, nullptr, &mDebugReportCallback));
280 }
281
Jamie Madill4d0bf552016-12-28 15:45:24 -0500282 uint32_t physicalDeviceCount = 0;
283 ANGLE_VK_TRY(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, nullptr));
284 ANGLE_VK_CHECK(physicalDeviceCount > 0, VK_ERROR_INITIALIZATION_FAILED);
285
286 // TODO(jmadill): Handle multiple physical devices. For now, use the first device.
287 physicalDeviceCount = 1;
288 ANGLE_VK_TRY(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, &mPhysicalDevice));
289
290 vkGetPhysicalDeviceProperties(mPhysicalDevice, &mPhysicalDeviceProperties);
291
292 // Ensure we can find a graphics queue family.
293 uint32_t queueCount = 0;
294 vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, nullptr);
295
296 ANGLE_VK_CHECK(queueCount > 0, VK_ERROR_INITIALIZATION_FAILED);
297
298 mQueueFamilyProperties.resize(queueCount);
299 vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount,
300 mQueueFamilyProperties.data());
301
302 size_t graphicsQueueFamilyCount = false;
303 uint32_t firstGraphicsQueueFamily = 0;
304 for (uint32_t familyIndex = 0; familyIndex < queueCount; ++familyIndex)
305 {
306 const auto &queueInfo = mQueueFamilyProperties[familyIndex];
307 if ((queueInfo.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
308 {
309 ASSERT(queueInfo.queueCount > 0);
310 graphicsQueueFamilyCount++;
311 if (firstGraphicsQueueFamily == 0)
312 {
313 firstGraphicsQueueFamily = familyIndex;
314 }
315 break;
316 }
317 }
318
319 ANGLE_VK_CHECK(graphicsQueueFamilyCount > 0, VK_ERROR_INITIALIZATION_FAILED);
320
321 // If only one queue family, go ahead and initialize the device. If there is more than one
322 // queue, we'll have to wait until we see a WindowSurface to know which supports present.
323 if (graphicsQueueFamilyCount == 1)
324 {
325 ANGLE_TRY(initializeDevice(firstGraphicsQueueFamily));
326 }
327
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500328 VkPhysicalDeviceMemoryProperties memoryProperties;
329 vkGetPhysicalDeviceMemoryProperties(mPhysicalDevice, &memoryProperties);
330
331 for (uint32_t memoryIndex = 0; memoryIndex < memoryProperties.memoryTypeCount; ++memoryIndex)
332 {
333 if ((memoryProperties.memoryTypes[memoryIndex].propertyFlags &
334 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
335 {
336 mHostVisibleMemoryIndex = memoryIndex;
337 break;
338 }
339 }
340
341 ANGLE_VK_CHECK(mHostVisibleMemoryIndex < std::numeric_limits<uint32_t>::max(),
342 VK_ERROR_INITIALIZATION_FAILED);
343
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500344 mGlslangWrapper = GlslangWrapper::GetReference();
345
Jamie Madill327ba852016-11-30 12:38:28 -0500346 return vk::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400347}
348
Jamie Madill4d0bf552016-12-28 15:45:24 -0500349vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex)
350{
351 uint32_t deviceLayerCount = 0;
352 ANGLE_VK_TRY(vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount, nullptr));
353
354 std::vector<VkLayerProperties> deviceLayerProps(deviceLayerCount);
355 if (deviceLayerCount > 0)
356 {
357 ANGLE_VK_TRY(vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount,
358 deviceLayerProps.data()));
359 }
360
361 uint32_t deviceExtensionCount = 0;
362 ANGLE_VK_TRY(vkEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr,
363 &deviceExtensionCount, nullptr));
364
365 std::vector<VkExtensionProperties> deviceExtensionProps(deviceExtensionCount);
366 if (deviceExtensionCount > 0)
367 {
368 ANGLE_VK_TRY(vkEnumerateDeviceExtensionProperties(
369 mPhysicalDevice, nullptr, &deviceExtensionCount, deviceExtensionProps.data()));
370 }
371
372 if (mEnableValidationLayers)
373 {
374 if (!HasStandardValidationLayer(deviceLayerProps))
375 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500376 WARN() << "Vulkan standard validation layer is missing.";
Jamie Madill4d0bf552016-12-28 15:45:24 -0500377 mEnableValidationLayers = false;
378 }
379 }
380
381 std::vector<const char *> enabledDeviceExtensions;
382 enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
383
384 ANGLE_VK_TRY(VerifyExtensionsPresent(deviceExtensionProps, enabledDeviceExtensions));
385
386 VkDeviceQueueCreateInfo queueCreateInfo;
387
388 float zeroPriority = 0.0f;
389
390 queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
391 queueCreateInfo.pNext = nullptr;
392 queueCreateInfo.flags = 0;
393 queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
394 queueCreateInfo.queueCount = 1;
395 queueCreateInfo.pQueuePriorities = &zeroPriority;
396
397 // Initialize the device
398 VkDeviceCreateInfo createInfo;
399
400 createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
401 createInfo.pNext = nullptr;
402 createInfo.flags = 0;
403 createInfo.queueCreateInfoCount = 1;
404 createInfo.pQueueCreateInfos = &queueCreateInfo;
405 createInfo.enabledLayerCount = mEnableValidationLayers ? 1u : 0u;
406 createInfo.ppEnabledLayerNames =
407 mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
408 createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size());
409 createInfo.ppEnabledExtensionNames =
410 enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
411 createInfo.pEnabledFeatures = nullptr; // TODO(jmadill): features
412
413 ANGLE_VK_TRY(vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
414
415 mCurrentQueueFamilyIndex = queueFamilyIndex;
416
417 vkGetDeviceQueue(mDevice, mCurrentQueueFamilyIndex, 0, &mQueue);
418
419 // Initialize the command pool now that we know the queue family index.
420 VkCommandPoolCreateInfo commandPoolInfo;
421 commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
422 commandPoolInfo.pNext = nullptr;
423 // TODO(jmadill): Investigate transient command buffers.
424 commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
425 commandPoolInfo.queueFamilyIndex = mCurrentQueueFamilyIndex;
426
Jamie Madill5deea722017-02-16 10:44:46 -0500427 ANGLE_TRY(mCommandPool.init(mDevice, commandPoolInfo));
Jamie Madill4d0bf552016-12-28 15:45:24 -0500428
Jamie Madill5deea722017-02-16 10:44:46 -0500429 mCommandBuffer.setCommandPool(&mCommandPool);
Jamie Madill4d0bf552016-12-28 15:45:24 -0500430
431 return vk::NoError();
432}
433
434vk::ErrorOrResult<uint32_t> RendererVk::selectPresentQueueForSurface(VkSurfaceKHR surface)
435{
436 // We've already initialized a device, and can't re-create it unless it's never been used.
437 // TODO(jmadill): Handle the re-creation case if necessary.
438 if (mDevice != VK_NULL_HANDLE)
439 {
440 ASSERT(mCurrentQueueFamilyIndex != std::numeric_limits<uint32_t>::max());
441
442 // Check if the current device supports present on this surface.
443 VkBool32 supportsPresent = VK_FALSE;
444 ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceSupportKHR(mPhysicalDevice, mCurrentQueueFamilyIndex,
445 surface, &supportsPresent));
446
447 return (supportsPresent == VK_TRUE);
448 }
449
450 // Find a graphics and present queue.
451 Optional<uint32_t> newPresentQueue;
452 uint32_t queueCount = static_cast<uint32_t>(mQueueFamilyProperties.size());
453 for (uint32_t queueIndex = 0; queueIndex < queueCount; ++queueIndex)
454 {
455 const auto &queueInfo = mQueueFamilyProperties[queueIndex];
456 if ((queueInfo.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
457 {
458 VkBool32 supportsPresent = VK_FALSE;
459 ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceSupportKHR(mPhysicalDevice, queueIndex, surface,
460 &supportsPresent));
461
462 if (supportsPresent == VK_TRUE)
463 {
464 newPresentQueue = queueIndex;
465 break;
466 }
467 }
468 }
469
470 ANGLE_VK_CHECK(newPresentQueue.valid(), VK_ERROR_INITIALIZATION_FAILED);
471 ANGLE_TRY(initializeDevice(newPresentQueue.value()));
472
473 return newPresentQueue.value();
474}
475
476std::string RendererVk::getVendorString() const
477{
478 switch (mPhysicalDeviceProperties.vendorID)
479 {
480 case VENDOR_ID_AMD:
481 return "Advanced Micro Devices";
482 case VENDOR_ID_NVIDIA:
483 return "NVIDIA";
484 case VENDOR_ID_INTEL:
485 return "Intel";
486 default:
487 {
488 // TODO(jmadill): More vendor IDs.
489 std::stringstream strstr;
490 strstr << "Vendor ID: " << mPhysicalDeviceProperties.vendorID;
491 return strstr.str();
492 }
493 }
494}
495
Jamie Madille09bd5d2016-11-29 16:20:35 -0500496std::string RendererVk::getRendererDescription() const
497{
Jamie Madill4d0bf552016-12-28 15:45:24 -0500498 std::stringstream strstr;
499
500 uint32_t apiVersion = mPhysicalDeviceProperties.apiVersion;
501
502 strstr << "Vulkan ";
503 strstr << VK_VERSION_MAJOR(apiVersion) << ".";
504 strstr << VK_VERSION_MINOR(apiVersion) << ".";
505 strstr << VK_VERSION_PATCH(apiVersion);
506
507 strstr << "(" << mPhysicalDeviceProperties.deviceName << ")";
508
509 return strstr.str();
Jamie Madille09bd5d2016-11-29 16:20:35 -0500510}
511
Jamie Madillacccc6c2016-05-03 17:22:10 -0400512void RendererVk::ensureCapsInitialized() const
513{
514 if (!mCapsInitialized)
515 {
516 generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
517 mCapsInitialized = true;
518 }
519}
520
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500521void RendererVk::generateCaps(gl::Caps *outCaps,
Jamie Madillacccc6c2016-05-03 17:22:10 -0400522 gl::TextureCapsMap * /*outTextureCaps*/,
Jamie Madillb8353b02017-01-25 12:57:21 -0800523 gl::Extensions *outExtensions,
Jamie Madillacccc6c2016-05-03 17:22:10 -0400524 gl::Limitations * /* outLimitations */) const
525{
Jamie Madill327ba852016-11-30 12:38:28 -0500526 // TODO(jmadill): Caps.
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500527 outCaps->maxDrawBuffers = 1;
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800528 outCaps->maxVertexAttributes = gl::MAX_VERTEX_ATTRIBS;
529 outCaps->maxVertexAttribBindings = gl::MAX_VERTEX_ATTRIB_BINDINGS;
Jamie Madillb8353b02017-01-25 12:57:21 -0800530
531 // Enable this for simple buffer readback testing, but some functionality is missing.
532 // TODO(jmadill): Support full mapBufferRange extension.
533 outExtensions->mapBuffer = true;
534 outExtensions->mapBufferRange = true;
Jamie Madillacccc6c2016-05-03 17:22:10 -0400535}
536
537const gl::Caps &RendererVk::getNativeCaps() const
538{
539 ensureCapsInitialized();
540 return mNativeCaps;
541}
542
543const gl::TextureCapsMap &RendererVk::getNativeTextureCaps() const
544{
545 ensureCapsInitialized();
546 return mNativeTextureCaps;
547}
548
549const gl::Extensions &RendererVk::getNativeExtensions() const
550{
551 ensureCapsInitialized();
552 return mNativeExtensions;
553}
554
555const gl::Limitations &RendererVk::getNativeLimitations() const
556{
557 ensureCapsInitialized();
558 return mNativeLimitations;
559}
560
Jamie Madill4d0bf552016-12-28 15:45:24 -0500561vk::CommandBuffer *RendererVk::getCommandBuffer()
562{
Jamie Madill5deea722017-02-16 10:44:46 -0500563 return &mCommandBuffer;
Jamie Madill4d0bf552016-12-28 15:45:24 -0500564}
565
566vk::Error RendererVk::submitAndFinishCommandBuffer(const vk::CommandBuffer &commandBuffer)
567{
568 VkFenceCreateInfo fenceInfo;
569 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
570 fenceInfo.pNext = nullptr;
571 fenceInfo.flags = 0;
572
573 VkCommandBuffer commandBufferHandle = commandBuffer.getHandle();
574
575 VkSubmitInfo submitInfo;
576 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
577 submitInfo.pNext = nullptr;
578 submitInfo.waitSemaphoreCount = 0;
579 submitInfo.pWaitSemaphores = nullptr;
580 submitInfo.pWaitDstStageMask = nullptr;
581 submitInfo.commandBufferCount = 1;
582 submitInfo.pCommandBuffers = &commandBufferHandle;
583 submitInfo.signalSemaphoreCount = 0;
584 submitInfo.pSignalSemaphores = nullptr;
585
586 // TODO(jmadill): Investigate how to properly submit command buffers.
587 ANGLE_VK_TRY(vkQueueSubmit(mQueue, 1, &submitInfo, VK_NULL_HANDLE));
588
589 // Wait indefinitely for the queue to finish.
590 ANGLE_VK_TRY(vkQueueWaitIdle(mQueue));
591
592 return vk::NoError();
593}
594
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500595vk::Error RendererVk::waitThenFinishCommandBuffer(const vk::CommandBuffer &commandBuffer,
596 const vk::Semaphore &waitSemaphore)
597{
598 VkCommandBuffer commandBufferHandle = commandBuffer.getHandle();
599 VkSemaphore waitHandle = waitSemaphore.getHandle();
600 VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
601
602 VkSubmitInfo submitInfo;
603 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
604 submitInfo.pNext = nullptr;
605 submitInfo.waitSemaphoreCount = 1;
606 submitInfo.pWaitSemaphores = &waitHandle;
607 submitInfo.pWaitDstStageMask = &waitStageMask;
608 submitInfo.commandBufferCount = 1;
609 submitInfo.pCommandBuffers = &commandBufferHandle;
610 submitInfo.signalSemaphoreCount = 0;
611 submitInfo.pSignalSemaphores = nullptr;
612
613 // TODO(jmadill): Investigate how to properly queue command buffer work.
614 ANGLE_VK_TRY(vkQueueSubmit(mQueue, 1, &submitInfo, VK_NULL_HANDLE));
615
616 // Wait indefinitely for the queue to finish.
617 ANGLE_VK_TRY(vkQueueWaitIdle(mQueue));
618
619 return vk::NoError();
620}
621
Jamie Madill5deea722017-02-16 10:44:46 -0500622vk::Error RendererVk::createStagingImage(TextureDimension dimension,
623 const vk::Format &format,
624 const gl::Extents &extent,
625 vk::StagingImage *imageOut)
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500626{
627 ASSERT(mHostVisibleMemoryIndex != std::numeric_limits<uint32_t>::max());
628
Jamie Madill5deea722017-02-16 10:44:46 -0500629 ANGLE_TRY(imageOut->init(mDevice, mCurrentQueueFamilyIndex, mHostVisibleMemoryIndex, dimension,
630 format.native, extent));
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500631
Jamie Madill5deea722017-02-16 10:44:46 -0500632 return vk::NoError();
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500633}
634
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500635GlslangWrapper *RendererVk::getGlslangWrapper()
636{
637 return mGlslangWrapper;
638}
639
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400640} // namespace rx