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