blob: 53a6f9e0dd25eb5c25d8f2dac9a6e69291720323 [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"
22#include "libANGLE/renderer/vulkan/TextureVk.h"
23#include "libANGLE/renderer/vulkan/VertexArrayVk.h"
Jamie Madill7b57b9d2017-01-13 09:33:38 -050024#include "libANGLE/renderer/vulkan/formatutilsvk.h"
Jamie Madille09bd5d2016-11-29 16:20:35 -050025#include "platform/Platform.h"
Jamie Madill9e54b5a2016-05-25 12:57:39 -040026
27namespace rx
28{
29
Jamie Madille09bd5d2016-11-29 16:20:35 -050030namespace
31{
32
33VkResult VerifyExtensionsPresent(const std::vector<VkExtensionProperties> &extensionProps,
34 const std::vector<const char *> &enabledExtensionNames)
35{
36 // Compile the extensions names into a set.
37 std::set<std::string> extensionNames;
38 for (const auto &extensionProp : extensionProps)
39 {
40 extensionNames.insert(extensionProp.extensionName);
41 }
42
43 for (const auto &extensionName : enabledExtensionNames)
44 {
45 if (extensionNames.count(extensionName) == 0)
46 {
47 return VK_ERROR_EXTENSION_NOT_PRESENT;
48 }
49 }
50
51 return VK_SUCCESS;
52}
53
Jamie Madill0448ec82016-12-23 13:41:47 -050054VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
55 VkDebugReportObjectTypeEXT objectType,
56 uint64_t object,
57 size_t location,
58 int32_t messageCode,
59 const char *layerPrefix,
60 const char *message,
61 void *userData)
62{
63 if ((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0)
64 {
65 ANGLEPlatformCurrent()->logError(message);
66#if !defined(NDEBUG)
67 // Abort the call in Debug builds.
68 return VK_TRUE;
69#endif
70 }
71 else if ((flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0)
72 {
73 ANGLEPlatformCurrent()->logWarning(message);
74 }
75 else
76 {
77 ANGLEPlatformCurrent()->logInfo(message);
78 }
79
80 return VK_FALSE;
81}
82
Jamie Madille09bd5d2016-11-29 16:20:35 -050083} // anonymous namespace
84
Jamie Madill0448ec82016-12-23 13:41:47 -050085RendererVk::RendererVk()
86 : mCapsInitialized(false),
87 mInstance(VK_NULL_HANDLE),
88 mEnableValidationLayers(false),
Jamie Madill4d0bf552016-12-28 15:45:24 -050089 mDebugReportCallback(VK_NULL_HANDLE),
90 mPhysicalDevice(VK_NULL_HANDLE),
91 mQueue(VK_NULL_HANDLE),
92 mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
93 mDevice(VK_NULL_HANDLE),
Jamie Madill7b57b9d2017-01-13 09:33:38 -050094 mCommandPool(VK_NULL_HANDLE),
95 mHostVisibleMemoryIndex(std::numeric_limits<uint32_t>::max())
Jamie Madill9e54b5a2016-05-25 12:57:39 -040096{
97}
98
99RendererVk::~RendererVk()
100{
Jamie Madill4d0bf552016-12-28 15:45:24 -0500101 mCommandBuffer.reset(nullptr);
102
103 if (mCommandPool)
104 {
105 vkDestroyCommandPool(mDevice, mCommandPool, nullptr);
106 mCommandPool = VK_NULL_HANDLE;
107 }
108
109 if (mDevice)
110 {
111 vkDestroyDevice(mDevice, nullptr);
112 mDevice = VK_NULL_HANDLE;
113 }
114
Jamie Madill0448ec82016-12-23 13:41:47 -0500115 if (mDebugReportCallback)
116 {
117 ASSERT(mInstance);
118 auto destroyDebugReportCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
119 vkGetInstanceProcAddr(mInstance, "vkDestroyDebugReportCallbackEXT"));
120 ASSERT(destroyDebugReportCallback);
121 destroyDebugReportCallback(mInstance, mDebugReportCallback, nullptr);
122 }
123
Jamie Madill4d0bf552016-12-28 15:45:24 -0500124 if (mInstance)
125 {
126 vkDestroyInstance(mInstance, nullptr);
127 mInstance = VK_NULL_HANDLE;
128 }
129
130 mPhysicalDevice = VK_NULL_HANDLE;
Jamie Madill327ba852016-11-30 12:38:28 -0500131}
132
Jamie Madille09bd5d2016-11-29 16:20:35 -0500133vk::Error RendererVk::initialize(const egl::AttributeMap &attribs)
Jamie Madill327ba852016-11-30 12:38:28 -0500134{
Jamie Madilla66779f2017-01-06 10:43:44 -0500135#if !defined(NDEBUG)
136 // Validation layers enabled by default in Debug.
137 mEnableValidationLayers = true;
138#endif
139
140 // If specified in the attributes, override the default.
141 if (attribs.contains(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE))
142 {
143 mEnableValidationLayers =
144 (attribs.get(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE, EGL_FALSE) == EGL_TRUE);
145 }
146
147 // If we're loading the validation layers, we could be running from any random directory.
148 // Change to the executable directory so we can find the layers, then change back to the
149 // previous directory to be safe we don't disrupt the application.
150 std::string previousCWD;
151
152 if (mEnableValidationLayers)
153 {
154 const auto &cwd = angle::GetCWD();
155 if (!cwd.valid())
156 {
157 ANGLEPlatformCurrent()->logError("Error getting CWD for Vulkan layers init.");
158 mEnableValidationLayers = false;
159 }
160 else
161 {
162 previousCWD = cwd.value();
163 }
164 const char *exeDir = angle::GetExecutableDirectory();
165 angle::SetCWD(exeDir);
166 }
167
Jamie Madill0448ec82016-12-23 13:41:47 -0500168 // Gather global layer properties.
169 uint32_t instanceLayerCount = 0;
170 ANGLE_VK_TRY(vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr));
171
172 std::vector<VkLayerProperties> instanceLayerProps(instanceLayerCount);
173 if (instanceLayerCount > 0)
174 {
175 ANGLE_VK_TRY(
176 vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayerProps.data()));
177 }
178
Jamie Madille09bd5d2016-11-29 16:20:35 -0500179 uint32_t instanceExtensionCount = 0;
180 ANGLE_VK_TRY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount, nullptr));
181
182 std::vector<VkExtensionProperties> instanceExtensionProps(instanceExtensionCount);
183 if (instanceExtensionCount > 0)
184 {
185 ANGLE_VK_TRY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount,
186 instanceExtensionProps.data()));
187 }
188
Jamie Madill0448ec82016-12-23 13:41:47 -0500189 if (mEnableValidationLayers)
190 {
191 // Verify the standard validation layers are available.
192 if (!HasStandardValidationLayer(instanceLayerProps))
193 {
194 // Generate an error if the attribute was requested, warning otherwise.
195 if (attribs.contains(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE))
196 {
197 ANGLEPlatformCurrent()->logError("Vulkan standard validation layers are missing.");
198 }
199 else
200 {
201 ANGLEPlatformCurrent()->logWarning(
202 "Vulkan standard validation layers are missing.");
203 }
204 mEnableValidationLayers = false;
205 }
206 }
207
Jamie Madille09bd5d2016-11-29 16:20:35 -0500208 std::vector<const char *> enabledInstanceExtensions;
209 enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
210#if defined(ANGLE_PLATFORM_WINDOWS)
211 enabledInstanceExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
212#else
213#error Unsupported Vulkan platform.
214#endif // defined(ANGLE_PLATFORM_WINDOWS)
215
Jamie Madill0448ec82016-12-23 13:41:47 -0500216 // TODO(jmadill): Should be able to continue initialization if debug report ext missing.
217 if (mEnableValidationLayers)
218 {
219 enabledInstanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
220 }
221
Jamie Madille09bd5d2016-11-29 16:20:35 -0500222 // Verify the required extensions are in the extension names set. Fail if not.
223 ANGLE_VK_TRY(VerifyExtensionsPresent(instanceExtensionProps, enabledInstanceExtensions));
224
Jamie Madill327ba852016-11-30 12:38:28 -0500225 VkApplicationInfo applicationInfo;
226 applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
227 applicationInfo.pNext = nullptr;
228 applicationInfo.pApplicationName = "ANGLE";
229 applicationInfo.applicationVersion = 1;
230 applicationInfo.pEngineName = "ANGLE";
231 applicationInfo.engineVersion = 1;
232 applicationInfo.apiVersion = VK_API_VERSION_1_0;
233
234 VkInstanceCreateInfo instanceInfo;
235 instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
236 instanceInfo.pNext = nullptr;
237 instanceInfo.flags = 0;
238 instanceInfo.pApplicationInfo = &applicationInfo;
239
Jamie Madille09bd5d2016-11-29 16:20:35 -0500240 // Enable requested layers and extensions.
241 instanceInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
242 instanceInfo.ppEnabledExtensionNames =
243 enabledInstanceExtensions.empty() ? nullptr : enabledInstanceExtensions.data();
Jamie Madill0448ec82016-12-23 13:41:47 -0500244 instanceInfo.enabledLayerCount = mEnableValidationLayers ? 1u : 0u;
245 instanceInfo.ppEnabledLayerNames =
246 mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
Jamie Madill327ba852016-11-30 12:38:28 -0500247
248 ANGLE_VK_TRY(vkCreateInstance(&instanceInfo, nullptr, &mInstance));
249
Jamie Madill0448ec82016-12-23 13:41:47 -0500250 if (mEnableValidationLayers)
251 {
Jamie Madilla66779f2017-01-06 10:43:44 -0500252 // Change back to the previous working directory now that we've loaded the instance -
253 // the validation layers should be loaded at this point.
254 angle::SetCWD(previousCWD.c_str());
255
Jamie Madill0448ec82016-12-23 13:41:47 -0500256 VkDebugReportCallbackCreateInfoEXT debugReportInfo;
257
258 debugReportInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
259 debugReportInfo.pNext = nullptr;
260 debugReportInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT |
261 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
262 VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT;
263 debugReportInfo.pfnCallback = &DebugReportCallback;
264 debugReportInfo.pUserData = this;
265
266 auto createDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
267 vkGetInstanceProcAddr(mInstance, "vkCreateDebugReportCallbackEXT"));
268 ASSERT(createDebugReportCallback);
269 ANGLE_VK_TRY(
270 createDebugReportCallback(mInstance, &debugReportInfo, nullptr, &mDebugReportCallback));
271 }
272
Jamie Madill4d0bf552016-12-28 15:45:24 -0500273 uint32_t physicalDeviceCount = 0;
274 ANGLE_VK_TRY(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, nullptr));
275 ANGLE_VK_CHECK(physicalDeviceCount > 0, VK_ERROR_INITIALIZATION_FAILED);
276
277 // TODO(jmadill): Handle multiple physical devices. For now, use the first device.
278 physicalDeviceCount = 1;
279 ANGLE_VK_TRY(vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, &mPhysicalDevice));
280
281 vkGetPhysicalDeviceProperties(mPhysicalDevice, &mPhysicalDeviceProperties);
282
283 // Ensure we can find a graphics queue family.
284 uint32_t queueCount = 0;
285 vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, nullptr);
286
287 ANGLE_VK_CHECK(queueCount > 0, VK_ERROR_INITIALIZATION_FAILED);
288
289 mQueueFamilyProperties.resize(queueCount);
290 vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount,
291 mQueueFamilyProperties.data());
292
293 size_t graphicsQueueFamilyCount = false;
294 uint32_t firstGraphicsQueueFamily = 0;
295 for (uint32_t familyIndex = 0; familyIndex < queueCount; ++familyIndex)
296 {
297 const auto &queueInfo = mQueueFamilyProperties[familyIndex];
298 if ((queueInfo.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
299 {
300 ASSERT(queueInfo.queueCount > 0);
301 graphicsQueueFamilyCount++;
302 if (firstGraphicsQueueFamily == 0)
303 {
304 firstGraphicsQueueFamily = familyIndex;
305 }
306 break;
307 }
308 }
309
310 ANGLE_VK_CHECK(graphicsQueueFamilyCount > 0, VK_ERROR_INITIALIZATION_FAILED);
311
312 // If only one queue family, go ahead and initialize the device. If there is more than one
313 // queue, we'll have to wait until we see a WindowSurface to know which supports present.
314 if (graphicsQueueFamilyCount == 1)
315 {
316 ANGLE_TRY(initializeDevice(firstGraphicsQueueFamily));
317 }
318
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500319 VkPhysicalDeviceMemoryProperties memoryProperties;
320 vkGetPhysicalDeviceMemoryProperties(mPhysicalDevice, &memoryProperties);
321
322 for (uint32_t memoryIndex = 0; memoryIndex < memoryProperties.memoryTypeCount; ++memoryIndex)
323 {
324 if ((memoryProperties.memoryTypes[memoryIndex].propertyFlags &
325 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
326 {
327 mHostVisibleMemoryIndex = memoryIndex;
328 break;
329 }
330 }
331
332 ANGLE_VK_CHECK(mHostVisibleMemoryIndex < std::numeric_limits<uint32_t>::max(),
333 VK_ERROR_INITIALIZATION_FAILED);
334
Jamie Madill327ba852016-11-30 12:38:28 -0500335 return vk::NoError();
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400336}
337
Jamie Madill4d0bf552016-12-28 15:45:24 -0500338vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex)
339{
340 uint32_t deviceLayerCount = 0;
341 ANGLE_VK_TRY(vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount, nullptr));
342
343 std::vector<VkLayerProperties> deviceLayerProps(deviceLayerCount);
344 if (deviceLayerCount > 0)
345 {
346 ANGLE_VK_TRY(vkEnumerateDeviceLayerProperties(mPhysicalDevice, &deviceLayerCount,
347 deviceLayerProps.data()));
348 }
349
350 uint32_t deviceExtensionCount = 0;
351 ANGLE_VK_TRY(vkEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr,
352 &deviceExtensionCount, nullptr));
353
354 std::vector<VkExtensionProperties> deviceExtensionProps(deviceExtensionCount);
355 if (deviceExtensionCount > 0)
356 {
357 ANGLE_VK_TRY(vkEnumerateDeviceExtensionProperties(
358 mPhysicalDevice, nullptr, &deviceExtensionCount, deviceExtensionProps.data()));
359 }
360
361 if (mEnableValidationLayers)
362 {
363 if (!HasStandardValidationLayer(deviceLayerProps))
364 {
365 ANGLEPlatformCurrent()->logWarning("Vulkan standard validation layer is missing.");
366 mEnableValidationLayers = false;
367 }
368 }
369
370 std::vector<const char *> enabledDeviceExtensions;
371 enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
372
373 ANGLE_VK_TRY(VerifyExtensionsPresent(deviceExtensionProps, enabledDeviceExtensions));
374
375 VkDeviceQueueCreateInfo queueCreateInfo;
376
377 float zeroPriority = 0.0f;
378
379 queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
380 queueCreateInfo.pNext = nullptr;
381 queueCreateInfo.flags = 0;
382 queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
383 queueCreateInfo.queueCount = 1;
384 queueCreateInfo.pQueuePriorities = &zeroPriority;
385
386 // Initialize the device
387 VkDeviceCreateInfo createInfo;
388
389 createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
390 createInfo.pNext = nullptr;
391 createInfo.flags = 0;
392 createInfo.queueCreateInfoCount = 1;
393 createInfo.pQueueCreateInfos = &queueCreateInfo;
394 createInfo.enabledLayerCount = mEnableValidationLayers ? 1u : 0u;
395 createInfo.ppEnabledLayerNames =
396 mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
397 createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size());
398 createInfo.ppEnabledExtensionNames =
399 enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
400 createInfo.pEnabledFeatures = nullptr; // TODO(jmadill): features
401
402 ANGLE_VK_TRY(vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
403
404 mCurrentQueueFamilyIndex = queueFamilyIndex;
405
406 vkGetDeviceQueue(mDevice, mCurrentQueueFamilyIndex, 0, &mQueue);
407
408 // Initialize the command pool now that we know the queue family index.
409 VkCommandPoolCreateInfo commandPoolInfo;
410 commandPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
411 commandPoolInfo.pNext = nullptr;
412 // TODO(jmadill): Investigate transient command buffers.
413 commandPoolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
414 commandPoolInfo.queueFamilyIndex = mCurrentQueueFamilyIndex;
415
416 ANGLE_VK_TRY(vkCreateCommandPool(mDevice, &commandPoolInfo, nullptr, &mCommandPool));
417
418 mCommandBuffer.reset(new vk::CommandBuffer(mDevice, mCommandPool));
419
420 return vk::NoError();
421}
422
423vk::ErrorOrResult<uint32_t> RendererVk::selectPresentQueueForSurface(VkSurfaceKHR surface)
424{
425 // We've already initialized a device, and can't re-create it unless it's never been used.
426 // TODO(jmadill): Handle the re-creation case if necessary.
427 if (mDevice != VK_NULL_HANDLE)
428 {
429 ASSERT(mCurrentQueueFamilyIndex != std::numeric_limits<uint32_t>::max());
430
431 // Check if the current device supports present on this surface.
432 VkBool32 supportsPresent = VK_FALSE;
433 ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceSupportKHR(mPhysicalDevice, mCurrentQueueFamilyIndex,
434 surface, &supportsPresent));
435
436 return (supportsPresent == VK_TRUE);
437 }
438
439 // Find a graphics and present queue.
440 Optional<uint32_t> newPresentQueue;
441 uint32_t queueCount = static_cast<uint32_t>(mQueueFamilyProperties.size());
442 for (uint32_t queueIndex = 0; queueIndex < queueCount; ++queueIndex)
443 {
444 const auto &queueInfo = mQueueFamilyProperties[queueIndex];
445 if ((queueInfo.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
446 {
447 VkBool32 supportsPresent = VK_FALSE;
448 ANGLE_VK_TRY(vkGetPhysicalDeviceSurfaceSupportKHR(mPhysicalDevice, queueIndex, surface,
449 &supportsPresent));
450
451 if (supportsPresent == VK_TRUE)
452 {
453 newPresentQueue = queueIndex;
454 break;
455 }
456 }
457 }
458
459 ANGLE_VK_CHECK(newPresentQueue.valid(), VK_ERROR_INITIALIZATION_FAILED);
460 ANGLE_TRY(initializeDevice(newPresentQueue.value()));
461
462 return newPresentQueue.value();
463}
464
465std::string RendererVk::getVendorString() const
466{
467 switch (mPhysicalDeviceProperties.vendorID)
468 {
469 case VENDOR_ID_AMD:
470 return "Advanced Micro Devices";
471 case VENDOR_ID_NVIDIA:
472 return "NVIDIA";
473 case VENDOR_ID_INTEL:
474 return "Intel";
475 default:
476 {
477 // TODO(jmadill): More vendor IDs.
478 std::stringstream strstr;
479 strstr << "Vendor ID: " << mPhysicalDeviceProperties.vendorID;
480 return strstr.str();
481 }
482 }
483}
484
Jamie Madille09bd5d2016-11-29 16:20:35 -0500485std::string RendererVk::getRendererDescription() const
486{
Jamie Madill4d0bf552016-12-28 15:45:24 -0500487 std::stringstream strstr;
488
489 uint32_t apiVersion = mPhysicalDeviceProperties.apiVersion;
490
491 strstr << "Vulkan ";
492 strstr << VK_VERSION_MAJOR(apiVersion) << ".";
493 strstr << VK_VERSION_MINOR(apiVersion) << ".";
494 strstr << VK_VERSION_PATCH(apiVersion);
495
496 strstr << "(" << mPhysicalDeviceProperties.deviceName << ")";
497
498 return strstr.str();
Jamie Madille09bd5d2016-11-29 16:20:35 -0500499}
500
Jamie Madillacccc6c2016-05-03 17:22:10 -0400501void RendererVk::ensureCapsInitialized() const
502{
503 if (!mCapsInitialized)
504 {
505 generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
506 mCapsInitialized = true;
507 }
508}
509
510void RendererVk::generateCaps(gl::Caps * /*outCaps*/,
511 gl::TextureCapsMap * /*outTextureCaps*/,
Jamie Madillb8353b02017-01-25 12:57:21 -0800512 gl::Extensions *outExtensions,
Jamie Madillacccc6c2016-05-03 17:22:10 -0400513 gl::Limitations * /* outLimitations */) const
514{
Jamie Madill327ba852016-11-30 12:38:28 -0500515 // TODO(jmadill): Caps.
Jamie Madillb8353b02017-01-25 12:57:21 -0800516
517 // Enable this for simple buffer readback testing, but some functionality is missing.
518 // TODO(jmadill): Support full mapBufferRange extension.
519 outExtensions->mapBuffer = true;
520 outExtensions->mapBufferRange = true;
Jamie Madillacccc6c2016-05-03 17:22:10 -0400521}
522
523const gl::Caps &RendererVk::getNativeCaps() const
524{
525 ensureCapsInitialized();
526 return mNativeCaps;
527}
528
529const gl::TextureCapsMap &RendererVk::getNativeTextureCaps() const
530{
531 ensureCapsInitialized();
532 return mNativeTextureCaps;
533}
534
535const gl::Extensions &RendererVk::getNativeExtensions() const
536{
537 ensureCapsInitialized();
538 return mNativeExtensions;
539}
540
541const gl::Limitations &RendererVk::getNativeLimitations() const
542{
543 ensureCapsInitialized();
544 return mNativeLimitations;
545}
546
Jamie Madill4d0bf552016-12-28 15:45:24 -0500547vk::CommandBuffer *RendererVk::getCommandBuffer()
548{
549 return mCommandBuffer.get();
550}
551
552vk::Error RendererVk::submitAndFinishCommandBuffer(const vk::CommandBuffer &commandBuffer)
553{
554 VkFenceCreateInfo fenceInfo;
555 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
556 fenceInfo.pNext = nullptr;
557 fenceInfo.flags = 0;
558
559 VkCommandBuffer commandBufferHandle = commandBuffer.getHandle();
560
561 VkSubmitInfo submitInfo;
562 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
563 submitInfo.pNext = nullptr;
564 submitInfo.waitSemaphoreCount = 0;
565 submitInfo.pWaitSemaphores = nullptr;
566 submitInfo.pWaitDstStageMask = nullptr;
567 submitInfo.commandBufferCount = 1;
568 submitInfo.pCommandBuffers = &commandBufferHandle;
569 submitInfo.signalSemaphoreCount = 0;
570 submitInfo.pSignalSemaphores = nullptr;
571
572 // TODO(jmadill): Investigate how to properly submit command buffers.
573 ANGLE_VK_TRY(vkQueueSubmit(mQueue, 1, &submitInfo, VK_NULL_HANDLE));
574
575 // Wait indefinitely for the queue to finish.
576 ANGLE_VK_TRY(vkQueueWaitIdle(mQueue));
577
578 return vk::NoError();
579}
580
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500581vk::Error RendererVk::waitThenFinishCommandBuffer(const vk::CommandBuffer &commandBuffer,
582 const vk::Semaphore &waitSemaphore)
583{
584 VkCommandBuffer commandBufferHandle = commandBuffer.getHandle();
585 VkSemaphore waitHandle = waitSemaphore.getHandle();
586 VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
587
588 VkSubmitInfo submitInfo;
589 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
590 submitInfo.pNext = nullptr;
591 submitInfo.waitSemaphoreCount = 1;
592 submitInfo.pWaitSemaphores = &waitHandle;
593 submitInfo.pWaitDstStageMask = &waitStageMask;
594 submitInfo.commandBufferCount = 1;
595 submitInfo.pCommandBuffers = &commandBufferHandle;
596 submitInfo.signalSemaphoreCount = 0;
597 submitInfo.pSignalSemaphores = nullptr;
598
599 // TODO(jmadill): Investigate how to properly queue command buffer work.
600 ANGLE_VK_TRY(vkQueueSubmit(mQueue, 1, &submitInfo, VK_NULL_HANDLE));
601
602 // Wait indefinitely for the queue to finish.
603 ANGLE_VK_TRY(vkQueueWaitIdle(mQueue));
604
605 return vk::NoError();
606}
607
608vk::ErrorOrResult<vk::StagingImage> RendererVk::createStagingImage(TextureDimension dimension,
609 const vk::Format &format,
610 const gl::Extents &extent)
611{
612 ASSERT(mHostVisibleMemoryIndex != std::numeric_limits<uint32_t>::max());
613
614 vk::StagingImage stagingImage(mDevice);
615 ANGLE_TRY(stagingImage.init(mCurrentQueueFamilyIndex, mHostVisibleMemoryIndex, dimension,
616 format.native, extent));
617
618 return std::move(stagingImage);
619}
620
Jamie Madill9e54b5a2016-05-25 12:57:39 -0400621} // namespace rx