Cogs.Core
GraphicsDeviceVK.cpp
1#include "GraphicsDeviceVK.h"
2
3#include "Foundation/StringView.h"
4#include "Foundation/Platform/WindowData.h"
5
6#include <vector>
7#include <cassert>
8
9namespace
10{
11 HMODULE moduleHandle;
12}
13
14namespace
15{
16 Cogs::Logging::Log logger = Cogs::Logging::getLogger("GraphicsDeviceVK");
17
18 VkBool32 DebugCallback(VkDebugReportFlagsEXT flags,
19 VkDebugReportObjectTypeEXT objectType,
20 uint64_t object,
21 size_t location,
22 int32_t messageCode,
23 const char * pLayerPrefix,
24 const char * pMessage,
25 void * pUserData)
26 {
27 const auto format = "[%s] %s";
28
29 if (pMessage) {
30 if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
31 LOG_ERROR(logger, format, pLayerPrefix, pMessage);
32 } else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
33 LOG_WARNING(logger, format, pLayerPrefix, pMessage);
34 } else if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
35 LOG_INFO(logger, format, pLayerPrefix, pMessage);
36 } else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
37 LOG_DEBUG(logger, format, pLayerPrefix, pMessage);
38 }
39 }
40
41 return true;
42 }
43}
44
45bool Cogs::GraphicsDeviceVK::initializeInstance()
46{
47 loaderInit();
48
49 uint32_t layerCount = 0;
50 vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
51
52 std::vector<VkLayerProperties> layers(layerCount);
53 vkEnumerateInstanceLayerProperties(&layerCount, layers.data());
54
55 uint32_t extensionCount = 0;
56 vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
57
58 std::vector<VkExtensionProperties> extensions(extensionCount);
59 vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
60
61 VkApplicationInfo applicationInfo = {
62 VK_STRUCTURE_TYPE_APPLICATION_INFO,
63 nullptr,
64 "Cogs",
65 2,
66 "Cogs",
67 2,
68 VK_API_VERSION_1_0
69 };
70
71 std::vector<const char *> activeExtensions;
72 std::vector<const char *> activeLayers;
73
74 std::vector<StringView> desiredLayers = {
75#ifdef _DEBUG
76 //"VK_LAYER_LUNARG_standard_validation", // Performs SPIR-V validation.
77 "VK_LAYER_LUNARG_threading",
78 "VK_LAYER_LUNARG_mem_tracker",
79 //"VK_LAYER_LUNARG_object_tracker",
80 "VK_LAYER_LUNARG_draw_state",
81 "VK_LAYER_LUNARG_param_checker",
82 "VK_LAYER_LUNARG_swapchain",
83 "VK_LAYER_LUNARG_device_limits",
84 "VK_LAYER_LUNARG_image",
85 "VK_LAYER_GOOGLE_unique_objects",
86#endif
87 };
88
89 for (auto & layer : layers) {
90 for (auto desiredLayer : desiredLayers) {
91 if (desiredLayer == layer.layerName) {
92 activeLayers.push_back(layer.layerName);
93 }
94 }
95 }
96
97 std::vector<StringView> desiredExtensions = {
98 VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
99 VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
100 VK_KHR_SURFACE_EXTENSION_NAME
101 };
102
103 for (auto & extension : extensions) {
104 for (auto & desiredExtension : desiredExtensions) {
105 if (desiredExtension == extension.extensionName) {
106 activeExtensions.push_back(extension.extensionName);
107 }
108 }
109 }
110
111 if (activeExtensions.size() != desiredExtensions.size()) {
112 LOG_WARNING(logger, "Could not find all desired extensions.");
113 }
114
115 VkInstanceCreateInfo instanceInfo = {
116 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr, 0,
117 &applicationInfo,
118 static_cast<uint32_t>(activeLayers.size()),
119 activeLayers.data(),
120 static_cast<uint32_t>(activeExtensions.size()),
121 activeExtensions.data()
122 };
123
124 auto result = vkCreateInstance(&instanceInfo, nullptr, &instance);
125
126 if (VK_FAILED(result) || !instance) {
127 LOG_ERROR(logger, "Could not create Vulkan API instance.");
128 return false;
129 }
130
131#ifndef COGS_USE_VK_SDK
132 LOAD_INSTANCE_FUNCTION(vkCreateDebugReportCallbackEXT);
133 LOAD_INSTANCE_FUNCTION(vkDebugReportMessageEXT);
134
135 if (vkCreateDebugReportCallbackEXT) {
136 VkDebugReportCallbackCreateInfoEXT reportCallbackInfo = {};
137 reportCallbackInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
138 reportCallbackInfo.pNext = nullptr;
139 reportCallbackInfo.pfnCallback = DebugCallback;
140 reportCallbackInfo.pUserData = this;
141 reportCallbackInfo.flags = VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
142 VK_DEBUG_REPORT_WARNING_BIT_EXT |
143 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
144 VK_DEBUG_REPORT_ERROR_BIT_EXT |
145 VK_DEBUG_REPORT_DEBUG_BIT_EXT;
146
147 VkDebugReportCallbackEXT reportCallback;
148 result = vkCreateDebugReportCallbackEXT(instance, &reportCallbackInfo, nullptr, &reportCallback);
149
150 if (result != VK_SUCCESS) {
151 return false;
152 }
153
154 vkDebugReportMessageEXT(instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, 0, 0, "Cogs", "Initialized debug callbacks.");
155 }
156#else
157 instanceAssign(CreateDebugReportCallbackEXT, instance, "vkCreateDebugReportCallbackEXT");
158 instanceAssign(DebugReportMessageEXT, instance, "vkDebugReportMessageEXT");
159
160 if (CreateDebugReportCallbackEXT) {
161 VkDebugReportCallbackCreateInfoEXT reportCallbackInfo = {};
162 reportCallbackInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
163 reportCallbackInfo.pNext = nullptr;
164 reportCallbackInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)DebugCallback;
165 reportCallbackInfo.pUserData = this;
166 reportCallbackInfo.flags = VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
167 VK_DEBUG_REPORT_WARNING_BIT_EXT |
168 VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
169 VK_DEBUG_REPORT_ERROR_BIT_EXT |
170 VK_DEBUG_REPORT_DEBUG_BIT_EXT;
171
172 VkDebugReportCallbackEXT reportCallback;
173 result = CreateDebugReportCallbackEXT(instance, &reportCallbackInfo, nullptr, &reportCallback);
174
175 if (result != VK_SUCCESS) {
176 return false;
177 }
178
179 DebugReportMessageEXT(instance, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, 0, 0, "Cogs", "Initialized debug callbacks.");
180 }
181#endif
182
183 loaderInitInstance(instance);
184
185 return true;
186}
187
188bool Cogs::GraphicsDeviceVK::initializeDevice()
189{
190 uint32_t physicalDeviceCount = 0;
191 vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, nullptr);
192
193 std::vector<VkPhysicalDevice> physicalDevices(physicalDeviceCount);
194 auto result = vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices.data());
195
196 if (VK_FAILED(result)) {
197 VK_LOG_ERROR(result, "Failed to enumerate physical devices.");
198 return false;
199 }
200
201 if (!physicalDeviceCount) {
202 LOG_ERROR(logger, "No physical devices available.");
203 return false;
204 }
205
206 uint32_t queueFamilyIndex = 0;
207
208 for (auto & physicalDevice : physicalDevices) {
209 VkPhysicalDeviceFeatures features;
210 vkGetPhysicalDeviceFeatures(physicalDevice, &features);
211
212 uint32_t queueFamilyCount = 0;
213 vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr);
214
215 std::vector<VkQueueFamilyProperties> queueFamilyProperties(queueFamilyCount);
216 vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilyProperties.data());
217
218 for (size_t i = 0; i < queueFamilyProperties.size(); ++i) {
219 if (queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
220 queueFamilyIndex = static_cast<uint32_t>(i);
221 break;
222 }
223 }
224
225 VkBool32 supported = 0;
226 vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, 0, surface, &supported);
227
228 if (!supported) {
229 continue;
230 }
231
232 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities.surfaceCapabilities);
233
234 uint32_t presentModeCount = 0;
235 vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, nullptr);
236
237 capabilities.presentModes.resize(presentModeCount);
238 vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, capabilities.presentModes.data());
239
240 uint32_t surfaceFormatCount = 0;
241 vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &surfaceFormatCount, nullptr);
242
243 capabilities.surfaceFormats.resize(surfaceFormatCount);
244 vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &surfaceFormatCount, capabilities.surfaceFormats.data());
245
246 if (true) { // Check if features are OK
247 this->physicalDevice = physicalDevice;
248 physicalDeviceFeatures = features;
249 break;
250 }
251 }
252
253 vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
254
255 VkPhysicalDeviceProperties deviceProperties;
256 vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
257
258 uint32_t layerCount = 0;
259 vkEnumerateDeviceLayerProperties(physicalDevice, &layerCount, nullptr);
260
261 std::vector<VkLayerProperties> layers;
262 vkEnumerateDeviceLayerProperties(physicalDevice, &layerCount, layers.data());
263
264 uint32_t extensionCount = 0;
265 vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr);
266
267 std::vector<VkExtensionProperties> deviceExtensions(extensionCount);
268 vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, deviceExtensions.data());
269
270 std::vector<const char *> activeLayers;
271 std::vector<const char *> activeExtensions;
272
273 for (auto & layer : layers) {
274 activeLayers.push_back(layer.layerName);
275 }
276
277 bool foundKHRSwapchain = false;
278 bool foundNVGLSL = false;
279 for (auto & extension : deviceExtensions) {
280 if (StringView(VK_KHR_SWAPCHAIN_EXTENSION_NAME) == extension.extensionName) {
281 foundKHRSwapchain = true;
282 } else if (StringView("VK_NV_glsl_shader") == extension.extensionName) {
283 foundNVGLSL = true;
284 }
285
286 activeExtensions.push_back(extension.extensionName);
287 }
288
289 if (!foundKHRSwapchain) {
290 LOG_ERROR(logger, "Could not find VK_KHR_SWAPCHAIN_EXTENSION.");
291 return false;
292 }
293
294 if (!foundNVGLSL) {
295 LOG_WARNING(logger, "Could not find VK_NV_glsl_shader. GLSL usage may fail.");
296 }
297
298 float priority = 1.0f;
299
300 VkDeviceQueueCreateInfo queueCreateInfo = {
301 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
302 nullptr,
303 0,
304 queueFamilyIndex,
305 1,
306 &priority
307 };
308
309 VkDeviceCreateInfo createInfo = {
310 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
311 nullptr,
312 0,
313 1,
314 &queueCreateInfo,
315 static_cast<uint32_t>(activeLayers.size()),
316 activeLayers.data(),
317 static_cast<uint32_t>(activeExtensions.size()),
318 activeExtensions.data(),
319 &physicalDeviceFeatures
320 };
321
322 VkAllocationCallbacks allocator = {
323 0
324 };
325
326 result = vkCreateDevice(physicalDevice, &createInfo, nullptr, &device);
327
328 if (VK_FAILED(result)) {
329 VK_LOG_ERROR(result, "Could not create Vulkan device.");
330 return false;
331 }
332
333 vkGetDeviceQueue(device, 0, 0, &queue);
334
335 loaderInitDevice(instance, device);
336
337 return true;
338}
339
340bool Cogs::GraphicsDeviceVK::initializeSwapChain()
341{
342 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &capabilities.surfaceCapabilities);
343
344 VkExtent2D swapchainExtent;
345 swapchainExtent.width = std::min((uint32_t)width, capabilities.surfaceCapabilities.currentExtent.width);
346 swapchainExtent.height = std::min((uint32_t)height, capabilities.surfaceCapabilities.currentExtent.height);;
347
348 VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
349
350 uint32_t desiredNumberOfSwapchainImages = 3;
351
352 auto oldSwapchain = swapChain;
353
354 VkSwapchainCreateInfoKHR swapChainInfo = {};
355 swapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
356 swapChainInfo.pNext = nullptr;
357 swapChainInfo.surface = surface;
358 swapChainInfo.minImageCount = desiredNumberOfSwapchainImages;
359 swapChainInfo.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
360 swapChainInfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
361 swapChainInfo.imageExtent = swapchainExtent;
362 swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
363 swapChainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
364 swapChainInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
365 swapChainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
366 swapChainInfo.imageArrayLayers = 1;
367 swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
368 swapChainInfo.queueFamilyIndexCount = 0;
369 swapChainInfo.pQueueFamilyIndices = nullptr;
370 swapChainInfo.presentMode = swapchainPresentMode;
371 swapChainInfo.oldSwapchain = oldSwapchain;
372 swapChainInfo.clipped = true;
373
374 auto result = vkCreateSwapchainKHR(device, &swapChainInfo, nullptr, &swapChain);
375
376 if (VK_FAILED(result)) {
377 VK_LOG_ERROR(result, "Could not create swap chain.");
378 return false;
379 }
380
381 uint32_t numSwapChainImages = 0;
382 vkGetSwapchainImagesKHR(device, swapChain, &numSwapChainImages, nullptr);
383
384 swapChainImages.resize(numSwapChainImages);
385 vkGetSwapchainImagesKHR(device, swapChain, &numSwapChainImages, swapChainImages.data());
386
387 backBuffers.resize(numSwapChainImages);
388
389 if (settings.numSamples > 1) {
390 backBuffersMS.resize(numSwapChainImages);
391 }
392
393 for (uint32_t i = 0; i < numSwapChainImages; ++i) {
394 backBuffers[i] = textures.loadTexture((uint8_t *)swapChainImages[i], width, height, TextureFormat::B8G8R8A8, TextureFlags::ExternalTexture | TextureFlags::RenderTarget);
395
396 if (settings.numSamples > 1) {
397 backBuffersMS[i] = textures.loadTexture(nullptr, width, height, TextureFormat::R8G8B8A8_UNORM, settings.numSamples, TextureFlags::RenderTarget);
398 }
399
400 if (!HandleIsValid(backBuffers[i])) {
401 LOG_ERROR(logger, "Failed creating back buffer texture wrappers.");
402 }
403 }
404
405 return true;
406}
407
408bool Cogs::GraphicsDeviceVK::initializeCommandPool()
409{
410 const VkCommandPoolCreateInfo commandPoolInfo = {
411 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
412 nullptr,
413 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
414 0,
415 };
416
417 auto result = vkCreateCommandPool(device, &commandPoolInfo, nullptr, &commandPool);
418
419 if (VK_FAILED(result)) {
420 VK_LOG_ERROR(result, "Could not create command pool.");
421 return false;
422 }
423
424 return true;
425}
426
427Cogs::GraphicsDeviceVK::GraphicsDeviceVK(RenderingAllocatorInfo * allocator)
428{
429}
430
432{
433 if (!initializeInstance()) {
434 LOG_ERROR(logger, "Could not initialize instance.");
435 return false;
436 }
437
438 VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {};
439 surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
440 surfaceCreateInfo.pNext = nullptr;
441 surfaceCreateInfo.flags = 0;
442 surfaceCreateInfo.hinstance = ::GetModuleHandle(0);
443 surfaceCreateInfo.hwnd = settings.windowData->windowHandle;
444
445 auto result = vkCreateWin32SurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
446
447 if (VK_FAILED(result)) {
448 VK_LOG_ERROR(result, "Could not create surface.");
449 return false;
450 }
451
452 if (!initializeDevice()) {
453 LOG_ERROR(logger, "Could not initialize device.");
454 return false;
455 }
456
457 buffers.initialize(this);
458 textures.initialize(this);
459 renderTargets.initialize(this);
460
461 if (!initializeSwapChain()) {
462 LOG_ERROR(logger, "Could not initialize swap chain.");
463 return false;
464 }
465
466 if (!initializeCommandPool()) {
467 LOG_ERROR(logger, "Could not initialize command pool.");
468 return false;
469 }
470
471 context.initialize(this);
472 buffers.graphicsDevice = this;
473 effects.initialize(this);
474
475 if (settings.ioHandler) effects.setIOHandler(settings.ioHandler);
476
477 if (!initializeDepth()) {
478 return false;
479 }
480
481 if (!initializeFramebuffers()) {
482 return false;
483 }
484
485 return true;
486}
487
488bool Cogs::GraphicsDeviceVK::initializeDepth()
489{
490 depthTextureHandle = textures.loadTexture(nullptr, width, height, settings.depthFormat, settings.numSamples, TextureFlags::DepthBuffer);
491
492 return true;
493}
494
495void Cogs::GraphicsDeviceVK::flushSetup()
496{
497 if (setupCommands == VK_NULL_HANDLE) {
498 return;
499 }
500
501 auto result = vkEndCommandBuffer(setupCommands);
502 assert(!result);
503
504 const VkCommandBuffer commandBuffers[] = { setupCommands };
505
506 VkSubmitInfo submitInfo = {};
507 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
508 submitInfo.commandBufferCount = 1;
509 submitInfo.pCommandBuffers = commandBuffers;
510
511 result = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
512 assert(!result);
513
514 result = vkQueueWaitIdle(queue);
515 assert(!result);
516
517 vkFreeCommandBuffers(device, commandPool, 1, commandBuffers);
518
519 setupCommands = VK_NULL_HANDLE;
520}
521
522bool Cogs::GraphicsDeviceVK::initializeFramebuffers()
523{
524 framebuffers.resize(swapChainImages.size());
525
526 for (size_t i = 0; i < swapChainImages.size(); i++) {
527 if (settings.numSamples == 1) {
528 framebuffers[i] = renderTargets.createRenderTarget(backBuffers[i]);
529 } else {
530 framebuffers[i] = renderTargets.createRenderTarget(backBuffersMS[i]);
531 }
532
533 auto dsv = renderTargets.createDepthStencilTarget(framebuffers[i], depthTextureHandle);
534
535 if (!HandleIsValid(framebuffers[i]) || !HandleIsValid(dsv)) {
536 LOG_ERROR(logger, "Failed creating render targets.");
537 }
538 }
539
540 return true;
541}
542
543bool Cogs::GraphicsDeviceVK::getMemoryType(uint32_t typeBits, VkFlags requirementsMask, uint32_t * typeIndex)
544{
545 for (uint32_t i = 0; i < 32; i++) {
546 if ((typeBits & 1) == 1) {
547 // Type is available, does it match user properties?
548 if ((memoryProperties.memoryTypes[i].propertyFlags &
549 requirementsMask) == requirementsMask) {
550 *typeIndex = i;
551 return true;
552 }
553 }
554 typeBits >>= 1;
555 }
556
557 return false;
558}
559
560void Cogs::GraphicsDeviceVK::setSize(int width, int height)
561{
562 if (width == this->width && height == this->height) return;
563
564 this->width = width;
565 this->height = height;
566
567 needsResize = true;
568}
569
570bool Cogs::GraphicsDeviceVK::getSize(int& width, int& height) const
571{
572 width = this->width;
573 height = this->height;
574 return true;
575}
576
578{
579 VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {
580 VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
581 nullptr,
582 0,
583 };
584
585 auto err = vkCreateSemaphore(device, &presentCompleteSemaphoreCreateInfo, nullptr, &presentCompleteSemaphore);
586
587 assert(!err);
588
589 if (needsResize) {
590 resize();
591 }
592
593 err = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, presentCompleteSemaphore,
594 (VkFence)0,
595 &currentFrameBuffer);
596
597 context.defaultRenderTarget = framebuffers[currentFrameBuffer];
598
599 flushSetup();
600
601 context.beginFrame();
602
603 if (context.currentFrameResources->presentSemaphore) {
604 vkDestroySemaphore(device, context.currentFrameResources->presentSemaphore, nullptr);
605 }
606
607 context.currentFrameResources->presentSemaphore = presentCompleteSemaphore;
608}
609
610void Cogs::GraphicsDeviceVK::endFrame(uint32_t syncInterval, uint32_t presentFlags)
611{
612 flushSetup();
613
614 context.endFrame();
615
616 VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
617
618 VkSubmitInfo submitInfo = {};
619 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
620 submitInfo.pNext = nullptr;
621 submitInfo.waitSemaphoreCount = 1;
622 submitInfo.pWaitSemaphores = &presentCompleteSemaphore;
623 submitInfo.pWaitDstStageMask = &stageFlags;
624 submitInfo.commandBufferCount = 1;
625 submitInfo.pCommandBuffers = &context.currentFrameResources->commandBuffer;
626 submitInfo.signalSemaphoreCount = 0;
627 submitInfo.pSignalSemaphores = nullptr;
628
629 auto err = vkQueueSubmit(queue, 1, &submitInfo, context.currentFrameResources->fence);
630
631 if (VK_FAILED(err)) {
632 VK_LOG_ERROR(err, "Queue submit failed.");
633 }
634
635 context.currentFrameResources = nullptr;
636
637 VkPresentInfoKHR presentInfo = {
638 VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
639 nullptr,
640 0,
641 nullptr,
642 1,
643 &swapChain,
644 &currentFrameBuffer,
645 nullptr
646 };
647
648 vkQueuePresentKHR(queue, &presentInfo);
649
650 ++currentFrameBuffer;
651 if (currentFrameBuffer > 1) currentFrameBuffer = 0;
652}
653
655{
656 assert(false);
657}
658
660{
661}
662
664{
665 assert(false);
666 return nullptr;
667}
668
669VkCommandBuffer Cogs::GraphicsDeviceVK::getCommandBuffer()
670{
671 if (context.currentFrameResources) {
672 return context.currentFrameResources->commandBuffer;
673 } else {
674 if (setupCommands == VK_NULL_HANDLE) {
675 VkCommandBufferAllocateInfo cmd = {};
676 cmd.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
677 cmd.pNext = nullptr;
678 cmd.commandPool = commandPool;
679 cmd.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
680 cmd.commandBufferCount = 1;
681
682 auto result = vkAllocateCommandBuffers(device, &cmd, &setupCommands);
683
684 if (VK_FAILED(result)) {
685 VK_LOG_ERROR(result, "Failed to allocate setup command buffer.");
686 return VK_NULL_HANDLE;
687 }
688
689 VkCommandBufferBeginInfo commandBufferInfo = {};
690 commandBufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
691 commandBufferInfo.pNext = nullptr;
692 commandBufferInfo.flags = 0;
693 commandBufferInfo.pInheritanceInfo = nullptr;
694
695 result = vkBeginCommandBuffer(setupCommands, &commandBufferInfo);
696 }
697
698 return setupCommands;
699 }
700}
701
702void Cogs::GraphicsDeviceVK::resize()
703{
704 vkDeviceWaitIdle(device);
705
706 for (auto & frameBuffer : framebuffers) {
707 renderTargets.releaseRenderTarget(frameBuffer);
708 }
709
710 framebuffers.clear();
711
712 for (auto & t : backBuffers) {
713 textures.releaseTexture(t);
714 }
715
716 backBuffers.clear();
717
718 textures.releaseTexture(depthTextureHandle);
719
720 initializeSwapChain();
721 initializeDepth();
722 initializeFramebuffers();
723
724 needsResize = false;
725}
void releaseResources() override
Release all resources allocated.
bool initialize() override
Initializes the graphics device with the settings previous set through calling setSettings.
bool getSize(int &width, int &height) const override
Retrieve the size previously set by setSize.
void beginFrame() override
Signal the beginning of a new frame to the graphics device.
void waitForCommandSync() override
Wait for any GPU commands on the current device to finish before returning.
void setSize(int width, int height) override
Set the size of the main drawing buffer used by the graphics device in pixels.
void endFrame(uint32_t syncInterval=0, uint32_t presentFlags=PresentFlags::None) override
Signal the end of a frame to the graphics device.
ISwapChain * getDefaultSwapChain() override
Get a pointer to the default swap chain for this graphics device.
Log implementation class.
Definition: LogManager.h:139
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
@ DepthBuffer
The texture can be used as a depth target and have depth buffer values written into.
Definition: Flags.h:122
@ RenderTarget
The texture can be used as a render target and drawn into.
Definition: Flags.h:120