blob: 97cd3933aff3c0bbf0c29d9763db9a4c4920f13f [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 Madill4d0bf552016-12-28 15:45:24 -0500109 mCommandBuffer.reset(nullptr);
Jamie Madill294a5602017-02-15 10:41:32 -0500110 mCommandPool.reset(nullptr);
Jamie Madill4d0bf552016-12-28 15:45:24 -0500111
112 if (mDevice)
113 {
114 vkDestroyDevice(mDevice, nullptr);
115 mDevice = VK_NULL_HANDLE;
116 }
117
Jamie Madill0448ec82016-12-23 13:41:47 -0500118 if (mDebugReportCallback)
119 {
120 ASSERT(mInstance);
121 auto destroyDebugReportCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
122 vkGetInstanceProcAddr(mInstance, "vkDestroyDebugReportCallbackEXT"));
123 ASSERT(destroyDebugReportCallback);
124 destroyDebugReportCallback(mInstance, mDebugReportCallback, nullptr);
125 }
126
Jamie Madill4d0bf552016-12-28 15:45:24 -0500127 if (mInstance)
128 {
129 vkDestroyInstance(mInstance, nullptr);
130 mInstance = VK_NULL_HANDLE;
131 }
132
133 mPhysicalDevice = VK_NULL_HANDLE;
Jamie Madill327ba852016-11-30 12:38:28 -0500134}
135
Jamie Madille09bd5d2016-11-29 16:20:35 -0500136vk::Error RendererVk::initialize(const egl::AttributeMap &attribs)
Jamie Madill327ba852016-11-30 12:38:28 -0500137{
Jamie Madilla66779f2017-01-06 10:43:44 -0500138#if !defined(NDEBUG)
139 // Validation layers enabled by default in Debug.
140 mEnableValidationLayers = true;
141#endif
142
143 // If specified in the attributes, override the default.
144 if (attribs.contains(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE))
145 {
146 mEnableValidationLayers =
147 (attribs.get(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE, EGL_FALSE) == EGL_TRUE);
148 }
149
150 // If we're loading the validation layers, we could be running from any random directory.
151 // Change to the executable directory so we can find the layers, then change back to the
152 // previous directory to be safe we don't disrupt the application.
153 std::string previousCWD;
154
155 if (mEnableValidationLayers)
156 {
157 const auto &cwd = angle::GetCWD();
158 if (!cwd.valid())
159 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500160 ERR() << "Error getting CWD for Vulkan layers init.";
Jamie Madilla66779f2017-01-06 10:43:44 -0500161 mEnableValidationLayers = false;
162 }
163 else
164 {
165 previousCWD = cwd.value();
166 }
167 const char *exeDir = angle::GetExecutableDirectory();
168 angle::SetCWD(exeDir);
169 }
170
Jamie Madill0448ec82016-12-23 13:41:47 -0500171 // Gather global layer properties.
172 uint32_t instanceLayerCount = 0;
173 ANGLE_VK_TRY(vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr));
174
175 std::vector<VkLayerProperties> instanceLayerProps(instanceLayerCount);
176 if (instanceLayerCount > 0)
177 {
178 ANGLE_VK_TRY(
179 vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayerProps.data()));
180 }
181
Jamie Madille09bd5d2016-11-29 16:20:35 -0500182 uint32_t instanceExtensionCount = 0;
183 ANGLE_VK_TRY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount, nullptr));
184
185 std::vector<VkExtensionProperties> instanceExtensionProps(instanceExtensionCount);
186 if (instanceExtensionCount > 0)
187 {
188 ANGLE_VK_TRY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount,
189 instanceExtensionProps.data()));
190 }
191
Jamie Madill0448ec82016-12-23 13:41:47 -0500192 if (mEnableValidationLayers)
193 {
194 // Verify the standard validation layers are available.
195 if (!HasStandardValidationLayer(instanceLayerProps))
196 {
197 // Generate an error if the attribute was requested, warning otherwise.
198 if (attribs.contains(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE))
199 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500200 ERR() << "Vulkan standard validation layers are missing.";
Jamie Madill0448ec82016-12-23 13:41:47 -0500201 }
202 else
203 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500204 WARN() << "Vulkan standard validation layers are missing.";
Jamie Madill0448ec82016-12-23 13:41:47 -0500205 }
206 mEnableValidationLayers = false;
207 }
208 }
209
Jamie Madille09bd5d2016-11-29 16:20:35 -0500210 std::vector<const char *> enabledInstanceExtensions;
211 enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
212#if defined(ANGLE_PLATFORM_WINDOWS)
213 enabledInstanceExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
214#else
215#error Unsupported Vulkan platform.
216#endif // defined(ANGLE_PLATFORM_WINDOWS)
217
Jamie Madill0448ec82016-12-23 13:41:47 -0500218 // TODO(jmadill): Should be able to continue initialization if debug report ext missing.
219 if (mEnableValidationLayers)
220 {
221 enabledInstanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
222 }
223
Jamie Madille09bd5d2016-11-29 16:20:35 -0500224 // Verify the required extensions are in the extension names set. Fail if not.
225 ANGLE_VK_TRY(VerifyExtensionsPresent(instanceExtensionProps, enabledInstanceExtensions));
226
Jamie Madill327ba852016-11-30 12:38:28 -0500227 VkApplicationInfo applicationInfo;
228 applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
229 applicationInfo.pNext = nullptr;
230 applicationInfo.pApplicationName = "ANGLE";
231 applicationInfo.applicationVersion = 1;
232 applicationInfo.pEngineName = "ANGLE";
233 applicationInfo.engineVersion = 1;
234 applicationInfo.apiVersion = VK_API_VERSION_1_0;
235
236 VkInstanceCreateInfo instanceInfo;
237 instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
238 instanceInfo.pNext = nullptr;
239 instanceInfo.flags = 0;
240 instanceInfo.pApplicationInfo = &applicationInfo;
241
Jamie Madille09bd5d2016-11-29 16:20:35 -0500242 // Enable requested layers and extensions.
243 instanceInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
244 instanceInfo.ppEnabledExtensionNames =
245 enabledInstanceExtensions.empty() ? nullptr : enabledInstanceExtensions.data();
Jamie Madill0448ec82016-12-23 13:41:47 -0500246 instanceInfo.enabledLayerCount = mEnableValidationLayers ? 1u : 0u;
247 instanceInfo.ppEnabledLayerNames =
248 mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
Jamie Madill327ba852016-11-30 12:38:28 -0500249
250 ANGLE_VK_TRY(vkCreateInstance(&instanceInfo, nullptr, &mInstance));
251
Jamie Madill0448ec82016-12-23 13:41:47 -0500252 if (mEnableValidationLayers)
253 {
Jamie Madilla66779f2017-01-06 10:43:44 -0500254 // Change back to the previous working directory now that we've loaded the instance -
255 // the validation layers should be loaded at this point.
256 angle::SetCWD(previousCWD.c_str());
257
Jamie Madill0448ec82016-12-23 13:41:47 -0500258 VkDebugReportCallbackCreateInfoEXT debugReportInfo;
259
260 debugReportInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
261 debugReportInfo.pNext = nullptr;
262 debugReportInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT |
263 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
264 VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT;
265 debugReportInfo.pfnCallback = &DebugReportCallback;
266 debugReportInfo.pUserData = this;
267
268 auto createDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
269 vkGetInstanceProcAddr(mInstance, "vkCreateDebugReportCallbackEXT"));
270 ASSERT(createDebugReportCallback);
271 ANGLE_VK_TRY(
272 createDebugReportCallback(mInstance, &debugReportInfo, nullptr, &mDebugReportCallback));
273 }
274
Jamie Madill4d0bf552016-12-28 15:45:24 -0500275 uint32_t physicalDeviceCount = 0;
276 ANGLE_VK_TRY(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, nullptr));
277 ANGLE_VK_CHECK(physicalDeviceCount > 0, VK_ERROR_INITIALIZATION_FAILED);
278
279 // TODO(jmadill): Handle multiple physical devices. For now, use the first device.
280 physicalDeviceCount = 1;
281 ANGLE_VK_TRY(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, &mPhysicalDevice));
282
283 vkGetPhysicalDeviceProperties(mPhysicalDevice, &mPhysicalDeviceProperties);
284
285 // Ensure we can find a graphics queue family.
286 uint32_t queueCount = 0;
287 vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, nullptr);
288
289 ANGLE_VK_CHECK(queueCount > 0, VK_ERROR_INITIALIZATION_FAILED);
290
291 mQueueFamilyProperties.resize(queueCount);
292 vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount,
293 mQueueFamilyProperties.data());
294
295 size_t graphicsQueueFamilyCount = false;
296 uint32_t firstGraphicsQueueFamily = 0;
297 for (uint32_t familyIndex = 0; familyIndex < queueCount; ++familyIndex)
298 {
299 const auto &queueInfo = mQueueFamilyProperties[familyIndex];
300 if ((queueInfo.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
301 {
302 ASSERT(queueInfo.queueCount > 0);
303 graphicsQueueFamilyCount++;
304 if (firstGraphicsQueueFamily == 0)
305 {
306 firstGraphicsQueueFamily = familyIndex;
307 }
308 break;
309 }
310 }
311
312 ANGLE_VK_CHECK(graphicsQueueFamilyCount > 0, VK_ERROR_INITIALIZATION_FAILED);
313
314 // If only one queue family, go ahead and initialize the device. If there is more than one
315 // queue, we'll have to wait until we see a WindowSurface to know which supports present.
316 if (graphicsQueueFamilyCount == 1)
317 {
318 ANGLE_TRY(initializeDevice(firstGraphicsQueueFamily));
319 }
320
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500321 VkPhysicalDeviceMemoryProperties memoryProperties;
322 vkGetPhysicalDeviceMemoryProperties(mPhysicalDevice, &memoryProperties);
323
324 for (uint32_t memoryIndex = 0; memoryIndex < memoryProperties.memoryTypeCount; ++memoryIndex)
325 {
326 if ((memoryProperties.memoryTypes[memoryIndex].propertyFlags &
327 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
328 {
329 mHostVisibleMemoryIndex = memoryIndex;
330 break;
331 }
332 }
333
334 ANGLE_VK_CHECK(mHostVisibleMemoryIndex < std::numeric_limits<uint32_t>::max(),
335 VK_ERROR_INITIALIZATION_FAILED);
336
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500337 mGlslangWrapper = GlslangWrapper::GetReference();
338
Jamie Madill327ba852016-11-30 12:38:28 -0500339 return vk::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400340}
341
Jamie Madill4d0bf552016-12-28 15:45:24 -0500342vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex)
343{
344 uint32_t deviceLayerCount = 0;
345 ANGLE_VK_TRY(vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount, nullptr));
346
347 std::vector<VkLayerProperties> deviceLayerProps(deviceLayerCount);
348 if (deviceLayerCount > 0)
349 {
350 ANGLE_VK_TRY(vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount,
351 deviceLayerProps.data()));
352 }
353
354 uint32_t deviceExtensionCount = 0;
355 ANGLE_VK_TRY(vkEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr,
356 &deviceExtensionCount, nullptr));
357
358 std::vector<VkExtensionProperties> deviceExtensionProps(deviceExtensionCount);
359 if (deviceExtensionCount > 0)
360 {
361 ANGLE_VK_TRY(vkEnumerateDeviceExtensionProperties(
362 mPhysicalDevice, nullptr, &deviceExtensionCount, deviceExtensionProps.data()));
363 }
364
365 if (mEnableValidationLayers)
366 {
367 if (!HasStandardValidationLayer(deviceLayerProps))
368 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500369 WARN() << "Vulkan standard validation layer is missing.";
Jamie Madill4d0bf552016-12-28 15:45:24 -0500370 mEnableValidationLayers = false;
371 }
372 }
373
374 std::vector<const char *> enabledDeviceExtensions;
375 enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
376
377 ANGLE_VK_TRY(VerifyExtensionsPresent(deviceExtensionProps, enabledDeviceExtensions));
378
379 VkDeviceQueueCreateInfo queueCreateInfo;
380
381 float zeroPriority = 0.0f;
382
383 queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
384 queueCreateInfo.pNext = nullptr;
385 queueCreateInfo.flags = 0;
386 queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
387 queueCreateInfo.queueCount = 1;
388 queueCreateInfo.pQueuePriorities = &zeroPriority;
389
390 // Initialize the device
391 VkDeviceCreateInfo createInfo;
392
393 createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
394 createInfo.pNext = nullptr;
395 createInfo.flags = 0;
396 createInfo.queueCreateInfoCount = 1;
397 createInfo.pQueueCreateInfos = &queueCreateInfo;
398 createInfo.enabledLayerCount = mEnableValidationLayers ? 1u : 0u;
399 createInfo.ppEnabledLayerNames =
400 mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
401 createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size());
402 createInfo.ppEnabledExtensionNames =
403 enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
404 createInfo.pEnabledFeatures = nullptr; // TODO(jmadill): features
405
406 ANGLE_VK_TRY(vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
407
408 mCurrentQueueFamilyIndex = queueFamilyIndex;
409
410 vkGetDeviceQueue(mDevice, mCurrentQueueFamilyIndex, 0, &mQueue);
411
412 // Initialize the command pool now that we know the queue family index.
413 VkCommandPoolCreateInfo commandPoolInfo;
414 commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
415 commandPoolInfo.pNext = nullptr;
416 // TODO(jmadill): Investigate transient command buffers.
417 commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
418 commandPoolInfo.queueFamilyIndex = mCurrentQueueFamilyIndex;
419
Jamie Madill294a5602017-02-15 10:41:32 -0500420 mCommandPool.reset(new vk::CommandPool(mDevice));
421 ANGLE_TRY(mCommandPool->init(commandPoolInfo));
Jamie Madill4d0bf552016-12-28 15:45:24 -0500422
Jamie Madill294a5602017-02-15 10:41:32 -0500423 mCommandBuffer.reset(new vk::CommandBuffer(mDevice, mCommandPool.get()));
Jamie Madill4d0bf552016-12-28 15:45:24 -0500424
425 return vk::NoError();
426}
427
428vk::ErrorOrResult<uint32_t> RendererVk::selectPresentQueueForSurface(VkSurfaceKHR surface)
429{
430 // We've already initialized a device, and can't re-create it unless it's never been used.
431 // TODO(jmadill): Handle the re-creation case if necessary.
432 if (mDevice != VK_NULL_HANDLE)
433 {
434 ASSERT(mCurrentQueueFamilyIndex != std::numeric_limits<uint32_t>::max());
435
436 // Check if the current device supports present on this surface.
437 VkBool32 supportsPresent = VK_FALSE;
438 ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceSupportKHR(mPhysicalDevice, mCurrentQueueFamilyIndex,
439 surface, &supportsPresent));
440
441 return (supportsPresent == VK_TRUE);
442 }
443
444 // Find a graphics and present queue.
445 Optional<uint32_t> newPresentQueue;
446 uint32_t queueCount = static_cast<uint32_t>(mQueueFamilyProperties.size());
447 for (uint32_t queueIndex = 0; queueIndex < queueCount; ++queueIndex)
448 {
449 const auto &queueInfo = mQueueFamilyProperties[queueIndex];
450 if ((queueInfo.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
451 {
452 VkBool32 supportsPresent = VK_FALSE;
453 ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceSupportKHR(mPhysicalDevice, queueIndex, surface,
454 &supportsPresent));
455
456 if (supportsPresent == VK_TRUE)
457 {
458 newPresentQueue = queueIndex;
459 break;
460 }
461 }
462 }
463
464 ANGLE_VK_CHECK(newPresentQueue.valid(), VK_ERROR_INITIALIZATION_FAILED);
465 ANGLE_TRY(initializeDevice(newPresentQueue.value()));
466
467 return newPresentQueue.value();
468}
469
470std::string RendererVk::getVendorString() const
471{
472 switch (mPhysicalDeviceProperties.vendorID)
473 {
474 case VENDOR_ID_AMD:
475 return "Advanced Micro Devices";
476 case VENDOR_ID_NVIDIA:
477 return "NVIDIA";
478 case VENDOR_ID_INTEL:
479 return "Intel";
480 default:
481 {
482 // TODO(jmadill): More vendor IDs.
483 std::stringstream strstr;
484 strstr << "Vendor ID: " << mPhysicalDeviceProperties.vendorID;
485 return strstr.str();
486 }
487 }
488}
489
Jamie Madille09bd5d2016-11-29 16:20:35 -0500490std::string RendererVk::getRendererDescription() const
491{
Jamie Madill4d0bf552016-12-28 15:45:24 -0500492 std::stringstream strstr;
493
494 uint32_t apiVersion = mPhysicalDeviceProperties.apiVersion;
495
496 strstr << "Vulkan ";
497 strstr << VK_VERSION_MAJOR(apiVersion) << ".";
498 strstr << VK_VERSION_MINOR(apiVersion) << ".";
499 strstr << VK_VERSION_PATCH(apiVersion);
500
501 strstr << "(" << mPhysicalDeviceProperties.deviceName << ")";
502
503 return strstr.str();
Jamie Madille09bd5d2016-11-29 16:20:35 -0500504}
505
Jamie Madillacccc6c2016-05-03 17:22:10 -0400506void RendererVk::ensureCapsInitialized() const
507{
508 if (!mCapsInitialized)
509 {
510 generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
511 mCapsInitialized = true;
512 }
513}
514
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500515void RendererVk::generateCaps(gl::Caps *outCaps,
Jamie Madillacccc6c2016-05-03 17:22:10 -0400516 gl::TextureCapsMap * /*outTextureCaps*/,
Jamie Madillb8353b02017-01-25 12:57:21 -0800517 gl::Extensions *outExtensions,
Jamie Madillacccc6c2016-05-03 17:22:10 -0400518 gl::Limitations * /* outLimitations */) const
519{
Jamie Madill327ba852016-11-30 12:38:28 -0500520 // TODO(jmadill): Caps.
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500521 outCaps->maxDrawBuffers = 1;
522 outCaps->maxVertexAttributes = 1;
Jamie Madillb8353b02017-01-25 12:57:21 -0800523
524 // Enable this for simple buffer readback testing, but some functionality is missing.
525 // TODO(jmadill): Support full mapBufferRange extension.
526 outExtensions->mapBuffer = true;
527 outExtensions->mapBufferRange = true;
Jamie Madillacccc6c2016-05-03 17:22:10 -0400528}
529
530const gl::Caps &RendererVk::getNativeCaps() const
531{
532 ensureCapsInitialized();
533 return mNativeCaps;
534}
535
536const gl::TextureCapsMap &RendererVk::getNativeTextureCaps() const
537{
538 ensureCapsInitialized();
539 return mNativeTextureCaps;
540}
541
542const gl::Extensions &RendererVk::getNativeExtensions() const
543{
544 ensureCapsInitialized();
545 return mNativeExtensions;
546}
547
548const gl::Limitations &RendererVk::getNativeLimitations() const
549{
550 ensureCapsInitialized();
551 return mNativeLimitations;
552}
553
Jamie Madill4d0bf552016-12-28 15:45:24 -0500554vk::CommandBuffer *RendererVk::getCommandBuffer()
555{
556 return mCommandBuffer.get();
557}
558
559vk::Error RendererVk::submitAndFinishCommandBuffer(const vk::CommandBuffer &commandBuffer)
560{
561 VkFenceCreateInfo fenceInfo;
562 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
563 fenceInfo.pNext = nullptr;
564 fenceInfo.flags = 0;
565
566 VkCommandBuffer commandBufferHandle = commandBuffer.getHandle();
567
568 VkSubmitInfo submitInfo;
569 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
570 submitInfo.pNext = nullptr;
571 submitInfo.waitSemaphoreCount = 0;
572 submitInfo.pWaitSemaphores = nullptr;
573 submitInfo.pWaitDstStageMask = nullptr;
574 submitInfo.commandBufferCount = 1;
575 submitInfo.pCommandBuffers = &commandBufferHandle;
576 submitInfo.signalSemaphoreCount = 0;
577 submitInfo.pSignalSemaphores = nullptr;
578
579 // TODO(jmadill): Investigate how to properly submit command buffers.
580 ANGLE_VK_TRY(vkQueueSubmit(mQueue, 1, &submitInfo, VK_NULL_HANDLE));
581
582 // Wait indefinitely for the queue to finish.
583 ANGLE_VK_TRY(vkQueueWaitIdle(mQueue));
584
585 return vk::NoError();
586}
587
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500588vk::Error RendererVk::waitThenFinishCommandBuffer(const vk::CommandBuffer &commandBuffer,
589 const vk::Semaphore &waitSemaphore)
590{
591 VkCommandBuffer commandBufferHandle = commandBuffer.getHandle();
592 VkSemaphore waitHandle = waitSemaphore.getHandle();
593 VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
594
595 VkSubmitInfo submitInfo;
596 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
597 submitInfo.pNext = nullptr;
598 submitInfo.waitSemaphoreCount = 1;
599 submitInfo.pWaitSemaphores = &waitHandle;
600 submitInfo.pWaitDstStageMask = &waitStageMask;
601 submitInfo.commandBufferCount = 1;
602 submitInfo.pCommandBuffers = &commandBufferHandle;
603 submitInfo.signalSemaphoreCount = 0;
604 submitInfo.pSignalSemaphores = nullptr;
605
606 // TODO(jmadill): Investigate how to properly queue command buffer work.
607 ANGLE_VK_TRY(vkQueueSubmit(mQueue, 1, &submitInfo, VK_NULL_HANDLE));
608
609 // Wait indefinitely for the queue to finish.
610 ANGLE_VK_TRY(vkQueueWaitIdle(mQueue));
611
612 return vk::NoError();
613}
614
615vk::ErrorOrResult<vk::StagingImage> RendererVk::createStagingImage(TextureDimension dimension,
616 const vk::Format &format,
617 const gl::Extents &extent)
618{
619 ASSERT(mHostVisibleMemoryIndex != std::numeric_limits<uint32_t>::max());
620
621 vk::StagingImage stagingImage(mDevice);
622 ANGLE_TRY(stagingImage.init(mCurrentQueueFamilyIndex, mHostVisibleMemoryIndex, dimension,
623 format.native, extent));
624
625 return std::move(stagingImage);
626}
627
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500628GlslangWrapper *RendererVk::getGlslangWrapper()
629{
630 return mGlslangWrapper;
631}
632
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400633} // namespace rx