RendererVK.cpp 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2024 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <TestFramework.h>
  5. #include <Renderer/VK/RendererVK.h>
  6. #include <Renderer/VK/RenderPrimitiveVK.h>
  7. #include <Renderer/VK/RenderInstancesVK.h>
  8. #include <Renderer/VK/PipelineStateVK.h>
  9. #include <Renderer/VK/VertexShaderVK.h>
  10. #include <Renderer/VK/PixelShaderVK.h>
  11. #include <Renderer/VK/TextureVK.h>
  12. #include <Renderer/VK/FatalErrorIfFailedVK.h>
  13. #include <Utils/Log.h>
  14. #include <Utils/ReadData.h>
  15. #include <Jolt/Core/Profiler.h>
  16. #include <Jolt/Core/QuickSort.h>
  17. #include <Jolt/Core/RTTI.h>
  18. #ifdef JPH_PLATFORM_WINDOWS
  19. #include <vulkan/vulkan_win32.h>
  20. #elif defined(JPH_PLATFORM_LINUX)
  21. #include <vulkan/vulkan_xlib.h>
  22. #endif
  23. #ifdef JPH_DEBUG
  24. static VKAPI_ATTR VkBool32 VKAPI_CALL sVulkanDebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT inSeverity, [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT inType, const VkDebugUtilsMessengerCallbackDataEXT *inCallbackData, [[maybe_unused]] void *inUserData)
  25. {
  26. Trace("VK: %s", inCallbackData->pMessage);
  27. JPH_ASSERT((inSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) == 0);
  28. return VK_FALSE;
  29. }
  30. #endif // JPH_DEBUG
  31. RendererVK::~RendererVK()
  32. {
  33. vkDeviceWaitIdle(mDevice);
  34. // Trace allocation stats
  35. Trace("VK: Max allocations: %u, max size: %u MB", mMaxNumAllocations, uint32(mMaxTotalAllocated >> 20));
  36. // Destroy the shadow map
  37. mShadowMap = nullptr;
  38. vkDestroyFramebuffer(mDevice, mShadowFrameBuffer, nullptr);
  39. // Release constant buffers
  40. for (unique_ptr<ConstantBufferVK> &cb : mVertexShaderConstantBufferProjection)
  41. cb = nullptr;
  42. for (unique_ptr<ConstantBufferVK> &cb : mVertexShaderConstantBufferOrtho)
  43. cb = nullptr;
  44. for (unique_ptr<ConstantBufferVK> &cb : mPixelShaderConstantBuffer)
  45. cb = nullptr;
  46. // Free all buffers
  47. for (BufferCache &bc : mFreedBuffers)
  48. for (BufferCache::value_type &vt : bc)
  49. for (BufferVK &bvk : vt.second)
  50. FreeBufferInternal(bvk);
  51. for (BufferCache::value_type &vt : mBufferCache)
  52. for (BufferVK &bvk : vt.second)
  53. FreeBufferInternal(bvk);
  54. // Free all blocks in the memory cache
  55. for (MemoryCache::value_type &mc : mMemoryCache)
  56. for (Memory &m : mc.second)
  57. if (m.mOffset == 0)
  58. vkFreeMemory(mDevice, m.mMemory, nullptr); // Don't care about memory tracking anymore
  59. for (VkFence fence : mInFlightFences)
  60. vkDestroyFence(mDevice, fence, nullptr);
  61. for (VkSemaphore semaphore : mRenderFinishedSemaphores)
  62. vkDestroySemaphore(mDevice, semaphore, nullptr);
  63. for (VkSemaphore semaphore : mImageAvailableSemaphores)
  64. vkDestroySemaphore(mDevice, semaphore, nullptr);
  65. vkDestroyCommandPool(mDevice, mCommandPool, nullptr);
  66. vkDestroyPipelineLayout(mDevice, mPipelineLayout, nullptr);
  67. vkDestroyRenderPass(mDevice, mRenderPassShadow, nullptr);
  68. vkDestroyRenderPass(mDevice, mRenderPass, nullptr);
  69. vkDestroyDescriptorPool(mDevice, mDescriptorPool, nullptr);
  70. vkDestroySampler(mDevice, mTextureSamplerShadow, nullptr);
  71. vkDestroySampler(mDevice, mTextureSamplerRepeat, nullptr);
  72. vkDestroyDescriptorSetLayout(mDevice, mDescriptorSetLayoutUBO, nullptr);
  73. vkDestroyDescriptorSetLayout(mDevice, mDescriptorSetLayoutTexture, nullptr);
  74. DestroySwapChain();
  75. vkDestroySurfaceKHR(mInstance, mSurface, nullptr);
  76. vkDestroyDevice(mDevice, nullptr);
  77. #ifdef JPH_DEBUG
  78. PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = (PFN_vkDestroyDebugUtilsMessengerEXT)(void *)vkGetInstanceProcAddr(mInstance, "vkDestroyDebugUtilsMessengerEXT");
  79. if (vkDestroyDebugUtilsMessengerEXT != nullptr)
  80. vkDestroyDebugUtilsMessengerEXT(mInstance, mDebugMessenger, nullptr);
  81. #endif
  82. vkDestroyInstance(mInstance, nullptr);
  83. }
  84. void RendererVK::Initialize()
  85. {
  86. Renderer::Initialize();
  87. // Flip the sign of the projection matrix
  88. mPerspectiveYSign = -1.0f;
  89. // Required instance extensions
  90. Array<const char *> required_instance_extensions;
  91. required_instance_extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
  92. #ifdef JPH_PLATFORM_WINDOWS
  93. required_instance_extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
  94. #elif defined(JPH_PLATFORM_LINUX)
  95. required_instance_extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
  96. #endif
  97. // Required device extensions
  98. Array<const char *> required_device_extensions;
  99. required_device_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
  100. // Query supported instance extensions
  101. uint32 instance_extension_count = 0;
  102. FatalErrorIfFailed(vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, nullptr));
  103. Array<VkExtensionProperties> instance_extensions;
  104. instance_extensions.resize(instance_extension_count);
  105. FatalErrorIfFailed(vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, instance_extensions.data()));
  106. // Query supported validation layers
  107. uint32 validation_layer_count;
  108. vkEnumerateInstanceLayerProperties(&validation_layer_count, nullptr);
  109. Array<VkLayerProperties> validation_layers(validation_layer_count);
  110. vkEnumerateInstanceLayerProperties(&validation_layer_count, validation_layers.data());
  111. // Create Vulkan instance
  112. VkInstanceCreateInfo instance_create_info = {};
  113. instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  114. #ifdef JPH_DEBUG
  115. // Enable validation layer if supported
  116. const char *desired_validation_layers[] = { "VK_LAYER_KHRONOS_validation" };
  117. for (const VkLayerProperties &p : validation_layers)
  118. if (strcmp(desired_validation_layers[0], p.layerName) == 0)
  119. {
  120. instance_create_info.enabledLayerCount = 1;
  121. instance_create_info.ppEnabledLayerNames = desired_validation_layers;
  122. break;
  123. }
  124. // Setup debug messenger callback if the extension is supported
  125. VkDebugUtilsMessengerCreateInfoEXT messenger_create_info = {};
  126. for (const VkExtensionProperties &ext : instance_extensions)
  127. if (strcmp(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, ext.extensionName) == 0)
  128. {
  129. messenger_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
  130. messenger_create_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
  131. messenger_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT;
  132. messenger_create_info.pfnUserCallback = sVulkanDebugCallback;
  133. instance_create_info.pNext = &messenger_create_info;
  134. required_instance_extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
  135. break;
  136. }
  137. #endif
  138. instance_create_info.enabledExtensionCount = (uint32)required_instance_extensions.size();
  139. instance_create_info.ppEnabledExtensionNames = required_instance_extensions.data();
  140. FatalErrorIfFailed(vkCreateInstance(&instance_create_info, nullptr, &mInstance));
  141. #ifdef JPH_DEBUG
  142. // Finalize debug messenger callback
  143. PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = (PFN_vkCreateDebugUtilsMessengerEXT)(std::uintptr_t)vkGetInstanceProcAddr(mInstance, "vkCreateDebugUtilsMessengerEXT");
  144. if (vkCreateDebugUtilsMessengerEXT != nullptr)
  145. FatalErrorIfFailed(vkCreateDebugUtilsMessengerEXT(mInstance, &messenger_create_info, nullptr, &mDebugMessenger));
  146. #endif
  147. // Create surface
  148. #ifdef JPH_PLATFORM_WINDOWS
  149. VkWin32SurfaceCreateInfoKHR surface_create_info = {};
  150. surface_create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
  151. surface_create_info.hwnd = mhWnd;
  152. surface_create_info.hinstance = GetModuleHandle(nullptr);
  153. FatalErrorIfFailed(vkCreateWin32SurfaceKHR(mInstance, &surface_create_info, nullptr, &mSurface));
  154. #elif defined(JPH_PLATFORM_LINUX)
  155. VkXlibSurfaceCreateInfoKHR surface_create_info = {};
  156. surface_create_info.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
  157. surface_create_info.dpy = mDisplay;
  158. surface_create_info.window = mWindow;
  159. FatalErrorIfFailed(vkCreateXlibSurfaceKHR(mInstance, &surface_create_info, nullptr, &mSurface));
  160. #endif
  161. // Select device
  162. uint32 device_count = 0;
  163. FatalErrorIfFailed(vkEnumeratePhysicalDevices(mInstance, &device_count, nullptr));
  164. Array<VkPhysicalDevice> devices;
  165. devices.resize(device_count);
  166. FatalErrorIfFailed(vkEnumeratePhysicalDevices(mInstance, &device_count, devices.data()));
  167. struct Device
  168. {
  169. VkPhysicalDevice mPhysicalDevice;
  170. String mName;
  171. VkSurfaceFormatKHR mFormat;
  172. uint32 mGraphicsQueueIndex;
  173. uint32 mPresentQueueIndex;
  174. int mScore;
  175. };
  176. Array<Device> available_devices;
  177. for (VkPhysicalDevice device : devices)
  178. {
  179. // Get device properties
  180. VkPhysicalDeviceProperties properties;
  181. vkGetPhysicalDeviceProperties(device, &properties);
  182. // Test if it is an appropriate type
  183. int score = 0;
  184. switch (properties.deviceType)
  185. {
  186. case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
  187. score = 30;
  188. break;
  189. case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
  190. score = 20;
  191. break;
  192. case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
  193. score = 10;
  194. break;
  195. case VK_PHYSICAL_DEVICE_TYPE_CPU:
  196. score = 5;
  197. break;
  198. case VK_PHYSICAL_DEVICE_TYPE_OTHER:
  199. case VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM:
  200. continue;
  201. }
  202. // Check if the device supports all our required extensions
  203. uint32 device_extension_count;
  204. vkEnumerateDeviceExtensionProperties(device, nullptr, &device_extension_count, nullptr);
  205. Array<VkExtensionProperties> available_extensions;
  206. available_extensions.resize(device_extension_count);
  207. vkEnumerateDeviceExtensionProperties(device, nullptr, &device_extension_count, available_extensions.data());
  208. int found_extensions = 0;
  209. for (const char *required_device_extension : required_device_extensions)
  210. for (const VkExtensionProperties &ext : available_extensions)
  211. if (strcmp(required_device_extension, ext.extensionName) == 0)
  212. {
  213. found_extensions++;
  214. break;
  215. }
  216. if (found_extensions != int(required_device_extensions.size()))
  217. continue;
  218. // Find the right queues
  219. uint32 queue_family_count = 0;
  220. vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, nullptr);
  221. Array<VkQueueFamilyProperties> queue_families;
  222. queue_families.resize(queue_family_count);
  223. vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families.data());
  224. uint32 graphics_queue = ~uint32(0);
  225. uint32 present_queue = ~uint32(0);
  226. for (uint32 i = 0; i < uint32(queue_families.size()); ++i)
  227. {
  228. if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
  229. graphics_queue = i;
  230. VkBool32 present_support = false;
  231. vkGetPhysicalDeviceSurfaceSupportKHR(device, i, mSurface, &present_support);
  232. if (present_support)
  233. present_queue = i;
  234. if (graphics_queue != ~uint32(0) && present_queue != ~uint32(0))
  235. break;
  236. }
  237. if (graphics_queue == ~uint32(0) || present_queue == ~uint32(0))
  238. continue;
  239. // Select surface format
  240. VkSurfaceFormatKHR selected_format = SelectFormat(device);
  241. if (selected_format.format == VK_FORMAT_UNDEFINED)
  242. continue;
  243. // Add the device
  244. available_devices.push_back({ device, properties.deviceName, selected_format, graphics_queue, present_queue, score });
  245. }
  246. if (available_devices.empty())
  247. FatalError("No Vulkan device found!");
  248. QuickSort(available_devices.begin(), available_devices.end(), [](const Device &inLHS, const Device &inRHS) {
  249. return inLHS.mScore > inRHS.mScore;
  250. });
  251. const Device &selected_device = available_devices[0];
  252. Trace("Selected device: %s", selected_device.mName.c_str());
  253. mPhysicalDevice = selected_device.mPhysicalDevice;
  254. // Get memory properties
  255. vkGetPhysicalDeviceMemoryProperties(mPhysicalDevice, &mMemoryProperties);
  256. // Get features
  257. VkPhysicalDeviceFeatures physical_device_features = {};
  258. vkGetPhysicalDeviceFeatures(mPhysicalDevice, &physical_device_features);
  259. // Create device
  260. float queue_priority = 1.0f;
  261. VkDeviceQueueCreateInfo queue_create_info[2] = {};
  262. for (size_t i = 0; i < std::size(queue_create_info); ++i)
  263. {
  264. queue_create_info[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  265. queue_create_info[i].queueCount = 1;
  266. queue_create_info[i].pQueuePriorities = &queue_priority;
  267. }
  268. queue_create_info[0].queueFamilyIndex = selected_device.mGraphicsQueueIndex;
  269. queue_create_info[1].queueFamilyIndex = selected_device.mPresentQueueIndex;
  270. VkPhysicalDeviceFeatures device_features = {};
  271. if (!physical_device_features.fillModeNonSolid)
  272. FatalError("fillModeNonSolid not supported!");
  273. device_features.fillModeNonSolid = VK_TRUE;
  274. VkDeviceCreateInfo device_create_info = {};
  275. device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  276. device_create_info.queueCreateInfoCount = selected_device.mGraphicsQueueIndex != selected_device.mPresentQueueIndex? 2 : 1;
  277. device_create_info.pQueueCreateInfos = queue_create_info;
  278. device_create_info.enabledLayerCount = instance_create_info.enabledLayerCount;
  279. device_create_info.ppEnabledLayerNames = instance_create_info.ppEnabledLayerNames;
  280. device_create_info.enabledExtensionCount = uint32(required_device_extensions.size());
  281. device_create_info.ppEnabledExtensionNames = required_device_extensions.data();
  282. device_create_info.pEnabledFeatures = &device_features;
  283. FatalErrorIfFailed(vkCreateDevice(selected_device.mPhysicalDevice, &device_create_info, nullptr, &mDevice));
  284. // Get the queues
  285. mGraphicsQueueIndex = selected_device.mGraphicsQueueIndex;
  286. mPresentQueueIndex = selected_device.mPresentQueueIndex;
  287. vkGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);
  288. vkGetDeviceQueue(mDevice, mPresentQueueIndex, 0, &mPresentQueue);
  289. VkCommandPoolCreateInfo pool_info = {};
  290. pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  291. pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
  292. pool_info.queueFamilyIndex = selected_device.mGraphicsQueueIndex;
  293. FatalErrorIfFailed(vkCreateCommandPool(mDevice, &pool_info, nullptr, &mCommandPool));
  294. VkCommandBufferAllocateInfo command_buffer_info = {};
  295. command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  296. command_buffer_info.commandPool = mCommandPool;
  297. command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  298. command_buffer_info.commandBufferCount = 1;
  299. for (uint32 i = 0; i < cFrameCount; ++i)
  300. FatalErrorIfFailed(vkAllocateCommandBuffers(mDevice, &command_buffer_info, &mCommandBuffers[i]));
  301. VkSemaphoreCreateInfo semaphore_info = {};
  302. semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  303. for (uint32 i = 0; i < cFrameCount; ++i)
  304. {
  305. FatalErrorIfFailed(vkCreateSemaphore(mDevice, &semaphore_info, nullptr, &mImageAvailableSemaphores[i]));
  306. FatalErrorIfFailed(vkCreateSemaphore(mDevice, &semaphore_info, nullptr, &mRenderFinishedSemaphores[i]));
  307. }
  308. VkFenceCreateInfo fence_info = {};
  309. fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  310. fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
  311. for (uint32 i = 0; i < cFrameCount; ++i)
  312. FatalErrorIfFailed(vkCreateFence(mDevice, &fence_info, nullptr, &mInFlightFences[i]));
  313. // Create constant buffer. One per frame to avoid overwriting the constant buffer while the GPU is still using it.
  314. for (uint n = 0; n < cFrameCount; ++n)
  315. {
  316. mVertexShaderConstantBufferProjection[n] = CreateConstantBuffer(sizeof(VertexShaderConstantBuffer));
  317. mVertexShaderConstantBufferOrtho[n] = CreateConstantBuffer(sizeof(VertexShaderConstantBuffer));
  318. mPixelShaderConstantBuffer[n] = CreateConstantBuffer(sizeof(PixelShaderConstantBuffer));
  319. }
  320. // Create descriptor set layout for the uniform buffers
  321. VkDescriptorSetLayoutBinding ubo_layout_binding[2] = {};
  322. ubo_layout_binding[0].binding = 0;
  323. ubo_layout_binding[0].descriptorCount = 1;
  324. ubo_layout_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  325. ubo_layout_binding[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
  326. ubo_layout_binding[1].binding = 1;
  327. ubo_layout_binding[1].descriptorCount = 1;
  328. ubo_layout_binding[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  329. ubo_layout_binding[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  330. VkDescriptorSetLayoutCreateInfo ubo_dsl = {};
  331. ubo_dsl.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  332. ubo_dsl.bindingCount = std::size(ubo_layout_binding);
  333. ubo_dsl.pBindings = ubo_layout_binding;
  334. FatalErrorIfFailed(vkCreateDescriptorSetLayout(mDevice, &ubo_dsl, nullptr, &mDescriptorSetLayoutUBO));
  335. // Create descriptor set layout for the texture binding
  336. VkDescriptorSetLayoutBinding texture_layout_binding = {};
  337. texture_layout_binding.binding = 0;
  338. texture_layout_binding.descriptorCount = 1;
  339. texture_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  340. texture_layout_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  341. VkDescriptorSetLayoutCreateInfo texture_dsl = {};
  342. texture_dsl.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  343. texture_dsl.bindingCount = 1;
  344. texture_dsl.pBindings = &texture_layout_binding;
  345. FatalErrorIfFailed(vkCreateDescriptorSetLayout(mDevice, &texture_dsl, nullptr, &mDescriptorSetLayoutTexture));
  346. // Create pipeline layout
  347. VkPipelineLayoutCreateInfo pipeline_layout = {};
  348. VkDescriptorSetLayout layout_handles[] = { mDescriptorSetLayoutUBO, mDescriptorSetLayoutTexture };
  349. pipeline_layout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  350. pipeline_layout.setLayoutCount = std::size(layout_handles);
  351. pipeline_layout.pSetLayouts = layout_handles;
  352. pipeline_layout.pushConstantRangeCount = 0;
  353. FatalErrorIfFailed(vkCreatePipelineLayout(mDevice, &pipeline_layout, nullptr, &mPipelineLayout));
  354. // Create descriptor pool
  355. VkDescriptorPoolSize descriptor_pool_sizes[] = {
  356. { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 128 },
  357. { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 128 },
  358. };
  359. VkDescriptorPoolCreateInfo descriptor_info = {};
  360. descriptor_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  361. descriptor_info.poolSizeCount = std::size(descriptor_pool_sizes);
  362. descriptor_info.pPoolSizes = descriptor_pool_sizes;
  363. descriptor_info.maxSets = 256;
  364. FatalErrorIfFailed(vkCreateDescriptorPool(mDevice, &descriptor_info, nullptr, &mDescriptorPool));
  365. // Allocate descriptor sets for 3d rendering
  366. Array<VkDescriptorSetLayout> layouts(cFrameCount, mDescriptorSetLayoutUBO);
  367. VkDescriptorSetAllocateInfo descriptor_set_alloc_info = {};
  368. descriptor_set_alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  369. descriptor_set_alloc_info.descriptorPool = mDescriptorPool;
  370. descriptor_set_alloc_info.descriptorSetCount = cFrameCount;
  371. descriptor_set_alloc_info.pSetLayouts = layouts.data();
  372. FatalErrorIfFailed(vkAllocateDescriptorSets(mDevice, &descriptor_set_alloc_info, mDescriptorSets));
  373. for (uint i = 0; i < cFrameCount; i++)
  374. {
  375. VkDescriptorBufferInfo vs_buffer_info = {};
  376. vs_buffer_info.buffer = mVertexShaderConstantBufferProjection[i]->GetBuffer();
  377. vs_buffer_info.range = sizeof(VertexShaderConstantBuffer);
  378. VkDescriptorBufferInfo ps_buffer_info = {};
  379. ps_buffer_info.buffer = mPixelShaderConstantBuffer[i]->GetBuffer();
  380. ps_buffer_info.range = sizeof(PixelShaderConstantBuffer);
  381. VkWriteDescriptorSet descriptor_write[2] = {};
  382. descriptor_write[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  383. descriptor_write[0].dstSet = mDescriptorSets[i];
  384. descriptor_write[0].dstBinding = 0;
  385. descriptor_write[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  386. descriptor_write[0].descriptorCount = 1;
  387. descriptor_write[0].pBufferInfo = &vs_buffer_info;
  388. descriptor_write[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  389. descriptor_write[1].dstSet = mDescriptorSets[i];
  390. descriptor_write[1].dstBinding = 1;
  391. descriptor_write[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  392. descriptor_write[1].descriptorCount = 1;
  393. descriptor_write[1].pBufferInfo = &ps_buffer_info;
  394. vkUpdateDescriptorSets(mDevice, 2, descriptor_write, 0, nullptr);
  395. }
  396. // Allocate descriptor sets for 2d rendering
  397. FatalErrorIfFailed(vkAllocateDescriptorSets(mDevice, &descriptor_set_alloc_info, mDescriptorSetsOrtho));
  398. for (uint i = 0; i < cFrameCount; i++)
  399. {
  400. VkDescriptorBufferInfo vs_buffer_info = {};
  401. vs_buffer_info.buffer = mVertexShaderConstantBufferOrtho[i]->GetBuffer();
  402. vs_buffer_info.range = sizeof(VertexShaderConstantBuffer);
  403. VkWriteDescriptorSet descriptor_write = {};
  404. descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  405. descriptor_write.dstSet = mDescriptorSetsOrtho[i];
  406. descriptor_write.dstBinding = 0;
  407. descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  408. descriptor_write.descriptorCount = 1;
  409. descriptor_write.pBufferInfo = &vs_buffer_info;
  410. vkUpdateDescriptorSets(mDevice, 1, &descriptor_write, 0, nullptr);
  411. }
  412. // Create regular texture sampler
  413. VkSamplerCreateInfo sampler_info = {};
  414. sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
  415. sampler_info.magFilter = VK_FILTER_LINEAR;
  416. sampler_info.minFilter = VK_FILTER_LINEAR;
  417. sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  418. sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  419. sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  420. sampler_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
  421. sampler_info.unnormalizedCoordinates = VK_FALSE;
  422. sampler_info.compareEnable = VK_FALSE;
  423. sampler_info.minLod = 0.0f;
  424. sampler_info.maxLod = VK_LOD_CLAMP_NONE;
  425. sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
  426. FatalErrorIfFailed(vkCreateSampler(mDevice, &sampler_info, nullptr, &mTextureSamplerRepeat));
  427. // Create sampler for shadow maps
  428. sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
  429. sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
  430. sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
  431. sampler_info.compareEnable = VK_TRUE;
  432. sampler_info.compareOp = VK_COMPARE_OP_GREATER_OR_EQUAL;
  433. FatalErrorIfFailed(vkCreateSampler(mDevice, &sampler_info, nullptr, &mTextureSamplerShadow));
  434. {
  435. // Create shadow render pass
  436. VkAttachmentDescription shadowmap_attachment = {};
  437. shadowmap_attachment.format = FindDepthFormat();
  438. shadowmap_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
  439. shadowmap_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  440. shadowmap_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  441. shadowmap_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  442. shadowmap_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  443. shadowmap_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  444. shadowmap_attachment.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  445. VkAttachmentReference shadowmap_attachment_ref = {};
  446. shadowmap_attachment_ref.attachment = 0;
  447. shadowmap_attachment_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  448. VkSubpassDescription subpass_shadow = {};
  449. subpass_shadow.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  450. subpass_shadow.pDepthStencilAttachment = &shadowmap_attachment_ref;
  451. VkSubpassDependency dependencies_shadow = {};
  452. dependencies_shadow.srcSubpass = VK_SUBPASS_EXTERNAL;
  453. dependencies_shadow.dstSubpass = 0;
  454. dependencies_shadow.srcStageMask = VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
  455. dependencies_shadow.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  456. dependencies_shadow.dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
  457. dependencies_shadow.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  458. VkRenderPassCreateInfo render_pass_shadow = {};
  459. render_pass_shadow.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  460. render_pass_shadow.attachmentCount = 1;
  461. render_pass_shadow.pAttachments = &shadowmap_attachment;
  462. render_pass_shadow.subpassCount = 1;
  463. render_pass_shadow.pSubpasses = &subpass_shadow;
  464. render_pass_shadow.dependencyCount = 1;
  465. render_pass_shadow.pDependencies = &dependencies_shadow;
  466. FatalErrorIfFailed(vkCreateRenderPass(mDevice, &render_pass_shadow, nullptr, &mRenderPassShadow));
  467. }
  468. // Create depth only texture (no color buffer, as seen from light)
  469. mShadowMap = new TextureVK(this, cShadowMapSize, cShadowMapSize);
  470. // Create frame buffer for the shadow pass
  471. VkImageView attachments[] = { mShadowMap->GetImageView() };
  472. VkFramebufferCreateInfo frame_buffer_info = {};
  473. frame_buffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  474. frame_buffer_info.renderPass = mRenderPassShadow;
  475. frame_buffer_info.attachmentCount = std::size(attachments);
  476. frame_buffer_info.pAttachments = attachments;
  477. frame_buffer_info.width = cShadowMapSize;
  478. frame_buffer_info.height = cShadowMapSize;
  479. frame_buffer_info.layers = 1;
  480. FatalErrorIfFailed(vkCreateFramebuffer(mDevice, &frame_buffer_info, nullptr, &mShadowFrameBuffer));
  481. {
  482. // Create normal render pass
  483. VkAttachmentDescription attachments_normal[2] = {};
  484. VkAttachmentDescription &color_attachment = attachments_normal[0];
  485. color_attachment.format = selected_device.mFormat.format;
  486. color_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
  487. color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  488. color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  489. color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  490. color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  491. color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  492. color_attachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  493. VkAttachmentReference color_attachment_ref = {};
  494. color_attachment_ref.attachment = 0;
  495. color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  496. VkAttachmentDescription &depth_attachment = attachments_normal[1];
  497. depth_attachment.format = FindDepthFormat();
  498. depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
  499. depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  500. depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  501. depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  502. depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  503. depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  504. depth_attachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  505. VkAttachmentReference depth_attachment_ref = {};
  506. depth_attachment_ref.attachment = 1;
  507. depth_attachment_ref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  508. VkSubpassDescription subpass_normal = {};
  509. subpass_normal.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  510. subpass_normal.colorAttachmentCount = 1;
  511. subpass_normal.pColorAttachments = &color_attachment_ref;
  512. subpass_normal.pDepthStencilAttachment = &depth_attachment_ref;
  513. VkSubpassDependency dependencies_normal = {};
  514. dependencies_normal.srcSubpass = VK_SUBPASS_EXTERNAL;
  515. dependencies_normal.dstSubpass = 0;
  516. dependencies_normal.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
  517. dependencies_normal.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  518. dependencies_normal.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  519. dependencies_normal.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT;
  520. VkRenderPassCreateInfo render_pass_normal = {};
  521. render_pass_normal.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  522. render_pass_normal.attachmentCount = std::size(attachments_normal);
  523. render_pass_normal.pAttachments = attachments_normal;
  524. render_pass_normal.subpassCount = 1;
  525. render_pass_normal.pSubpasses = &subpass_normal;
  526. render_pass_normal.dependencyCount = 1;
  527. render_pass_normal.pDependencies = &dependencies_normal;
  528. FatalErrorIfFailed(vkCreateRenderPass(mDevice, &render_pass_normal, nullptr, &mRenderPass));
  529. }
  530. // Create the swap chain
  531. CreateSwapChain(mPhysicalDevice);
  532. }
  533. VkSurfaceFormatKHR RendererVK::SelectFormat(VkPhysicalDevice inDevice)
  534. {
  535. uint32 format_count;
  536. vkGetPhysicalDeviceSurfaceFormatsKHR(inDevice, mSurface, &format_count, nullptr);
  537. if (format_count == 0)
  538. return { VK_FORMAT_UNDEFINED, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
  539. Array<VkSurfaceFormatKHR> formats;
  540. formats.resize(format_count);
  541. vkGetPhysicalDeviceSurfaceFormatsKHR(inDevice, mSurface, &format_count, formats.data());
  542. // Select BGRA8 UNORM format if available, otherwise the 1st format
  543. for (const VkSurfaceFormatKHR &format : formats)
  544. if (format.format == VK_FORMAT_B8G8R8A8_UNORM && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
  545. return format;
  546. return formats[0];
  547. }
  548. VkFormat RendererVK::FindDepthFormat()
  549. {
  550. VkFormat candidates[] = { VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT };
  551. for (VkFormat format : candidates)
  552. {
  553. VkFormatProperties props;
  554. vkGetPhysicalDeviceFormatProperties(mPhysicalDevice, format, &props);
  555. if ((props.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
  556. return format;
  557. }
  558. FatalError("Failed to find format!");
  559. }
  560. void RendererVK::CreateSwapChain(VkPhysicalDevice inDevice)
  561. {
  562. // Select the format
  563. VkSurfaceFormatKHR format = SelectFormat(inDevice);
  564. mSwapChainImageFormat = format.format;
  565. // Determine swap chain extent
  566. VkSurfaceCapabilitiesKHR capabilities;
  567. vkGetPhysicalDeviceSurfaceCapabilitiesKHR(inDevice, mSurface, &capabilities);
  568. mSwapChainExtent = capabilities.currentExtent;
  569. if (mSwapChainExtent.width == UINT32_MAX || mSwapChainExtent.height == UINT32_MAX)
  570. mSwapChainExtent = { uint32(mWindowWidth), uint32(mWindowHeight) };
  571. mSwapChainExtent.width = Clamp(mSwapChainExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
  572. mSwapChainExtent.height = Clamp(mSwapChainExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
  573. // Early out if our window has been minimized
  574. if (mSwapChainExtent.width == 0 || mSwapChainExtent.height == 0)
  575. return;
  576. // Create the swap chain
  577. uint32 desired_image_count = max(min(capabilities.minImageCount + 1, capabilities.maxImageCount), capabilities.minImageCount);
  578. VkSwapchainCreateInfoKHR swapchain_create_info = {};
  579. swapchain_create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  580. swapchain_create_info.surface = mSurface;
  581. swapchain_create_info.minImageCount = desired_image_count;
  582. swapchain_create_info.imageFormat = format.format;
  583. swapchain_create_info.imageColorSpace = format.colorSpace;
  584. swapchain_create_info.imageExtent = mSwapChainExtent;
  585. swapchain_create_info.imageArrayLayers = 1;
  586. swapchain_create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  587. uint32 queue_family_indices[] = { mGraphicsQueueIndex, mPresentQueueIndex };
  588. if (mGraphicsQueueIndex != mPresentQueueIndex)
  589. {
  590. swapchain_create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
  591. swapchain_create_info.queueFamilyIndexCount = 2;
  592. swapchain_create_info.pQueueFamilyIndices = queue_family_indices;
  593. }
  594. else
  595. {
  596. swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  597. }
  598. swapchain_create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  599. swapchain_create_info.preTransform = capabilities.currentTransform;
  600. swapchain_create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  601. swapchain_create_info.presentMode = VK_PRESENT_MODE_FIFO_KHR;
  602. swapchain_create_info.clipped = VK_TRUE;
  603. FatalErrorIfFailed(vkCreateSwapchainKHR(mDevice, &swapchain_create_info, nullptr, &mSwapChain));
  604. // Get the actual swap chain image count
  605. uint32 image_count;
  606. FatalErrorIfFailed(vkGetSwapchainImagesKHR(mDevice, mSwapChain, &image_count, nullptr));
  607. // Get the swap chain images
  608. mSwapChainImages.resize(image_count);
  609. FatalErrorIfFailed(vkGetSwapchainImagesKHR(mDevice, mSwapChain, &image_count, mSwapChainImages.data()));
  610. // Create image views
  611. mSwapChainImageViews.resize(image_count);
  612. for (uint32 i = 0; i < image_count; ++i)
  613. mSwapChainImageViews[i] = CreateImageView(mSwapChainImages[i], mSwapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT);
  614. // Create depth buffer
  615. VkFormat depth_format = FindDepthFormat();
  616. VkImageUsageFlags depth_usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
  617. VkMemoryPropertyFlags depth_memory_properties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
  618. // Test and utilize support for transient memory for the depth buffer
  619. VkImageFormatProperties depth_transient_properties = {};
  620. VkResult depth_transient_support = vkGetPhysicalDeviceImageFormatProperties(mPhysicalDevice, depth_format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, depth_usage | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, 0, &depth_transient_properties);
  621. if (depth_transient_support == VK_SUCCESS)
  622. {
  623. depth_usage |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
  624. // Test and utilize lazily allocated memory for the depth buffer
  625. for (size_t i = 0; i < mMemoryProperties.memoryTypeCount; i++)
  626. if (mMemoryProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
  627. {
  628. depth_memory_properties = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
  629. break;
  630. }
  631. }
  632. CreateImage(mSwapChainExtent.width, mSwapChainExtent.height, depth_format, VK_IMAGE_TILING_OPTIMAL, depth_usage, depth_memory_properties, mDepthImage, mDepthImageMemory);
  633. mDepthImageView = CreateImageView(mDepthImage, depth_format, VK_IMAGE_ASPECT_DEPTH_BIT);
  634. // Create frame buffers for the normal pass
  635. mSwapChainFramebuffers.resize(image_count);
  636. for (size_t i = 0; i < mSwapChainFramebuffers.size(); i++)
  637. {
  638. VkImageView attachments[] = { mSwapChainImageViews[i], mDepthImageView };
  639. VkFramebufferCreateInfo frame_buffer_info = {};
  640. frame_buffer_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  641. frame_buffer_info.renderPass = mRenderPass;
  642. frame_buffer_info.attachmentCount = std::size(attachments);
  643. frame_buffer_info.pAttachments = attachments;
  644. frame_buffer_info.width = mSwapChainExtent.width;
  645. frame_buffer_info.height = mSwapChainExtent.height;
  646. frame_buffer_info.layers = 1;
  647. FatalErrorIfFailed(vkCreateFramebuffer(mDevice, &frame_buffer_info, nullptr, &mSwapChainFramebuffers[i]));
  648. }
  649. }
  650. void RendererVK::DestroySwapChain()
  651. {
  652. // Destroy depth buffer
  653. if (mDepthImageView != VK_NULL_HANDLE)
  654. {
  655. vkDestroyImageView(mDevice, mDepthImageView, nullptr);
  656. DestroyImage(mDepthImage, mDepthImageMemory);
  657. }
  658. for (VkFramebuffer frame_buffer : mSwapChainFramebuffers)
  659. vkDestroyFramebuffer(mDevice, frame_buffer, nullptr);
  660. mSwapChainFramebuffers.clear();
  661. for (VkImageView view : mSwapChainImageViews)
  662. vkDestroyImageView(mDevice, view, nullptr);
  663. mSwapChainImageViews.clear();
  664. if (mSwapChain != nullptr)
  665. {
  666. vkDestroySwapchainKHR(mDevice, mSwapChain, nullptr);
  667. mSwapChain = nullptr;
  668. }
  669. }
  670. void RendererVK::OnWindowResize()
  671. {
  672. Renderer::OnWindowResize();
  673. vkDeviceWaitIdle(mDevice);
  674. DestroySwapChain();
  675. CreateSwapChain(mPhysicalDevice);
  676. }
  677. void RendererVK::BeginFrame(const CameraState &inCamera, float inWorldScale)
  678. {
  679. JPH_PROFILE_FUNCTION();
  680. Renderer::BeginFrame(inCamera, inWorldScale);
  681. // If we have no swap chain, bail out
  682. if (mSwapChain == nullptr)
  683. return;
  684. // Update frame index
  685. mFrameIndex = (mFrameIndex + 1) % cFrameCount;
  686. // Wait for this frame to complete
  687. vkWaitForFences(mDevice, 1, &mInFlightFences[mFrameIndex], VK_TRUE, UINT64_MAX);
  688. VkResult result = vkAcquireNextImageKHR(mDevice, mSwapChain, UINT64_MAX, mImageAvailableSemaphores[mFrameIndex], VK_NULL_HANDLE, &mImageIndex);
  689. if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR)
  690. {
  691. vkDeviceWaitIdle(mDevice);
  692. DestroySwapChain();
  693. CreateSwapChain(mPhysicalDevice);
  694. if (mSwapChain == nullptr)
  695. return;
  696. result = vkAcquireNextImageKHR(mDevice, mSwapChain, UINT64_MAX, mImageAvailableSemaphores[mFrameIndex], VK_NULL_HANDLE, &mImageIndex);
  697. }
  698. FatalErrorIfFailed(result);
  699. // Free buffers that weren't used this frame
  700. for (BufferCache::value_type &vt : mBufferCache)
  701. for (BufferVK &bvk : vt.second)
  702. FreeBufferInternal(bvk);
  703. mBufferCache.clear();
  704. // Recycle the buffers that were freed
  705. mBufferCache.swap(mFreedBuffers[mFrameIndex]);
  706. vkResetFences(mDevice, 1, &mInFlightFences[mFrameIndex]);
  707. VkCommandBuffer command_buffer = GetCommandBuffer();
  708. FatalErrorIfFailed(vkResetCommandBuffer(command_buffer, 0));
  709. VkCommandBufferBeginInfo command_buffer_begin_info = {};
  710. command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  711. command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  712. FatalErrorIfFailed(vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info));
  713. // Begin the shadow pass
  714. VkClearValue clear_value;
  715. clear_value.depthStencil = { 0.0f, 0 };
  716. VkRenderPassBeginInfo render_pass_begin_info = {};
  717. render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  718. render_pass_begin_info.renderPass = mRenderPassShadow;
  719. render_pass_begin_info.framebuffer = mShadowFrameBuffer;
  720. render_pass_begin_info.renderArea.extent = { cShadowMapSize, cShadowMapSize };
  721. render_pass_begin_info.clearValueCount = 1;
  722. render_pass_begin_info.pClearValues = &clear_value;
  723. vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
  724. // Set constants for vertex shader in projection mode
  725. VertexShaderConstantBuffer *vs = mVertexShaderConstantBufferProjection[mFrameIndex]->Map<VertexShaderConstantBuffer>();
  726. *vs = mVSBuffer;
  727. mVertexShaderConstantBufferProjection[mFrameIndex]->Unmap();
  728. // Set constants for vertex shader in ortho mode
  729. vs = mVertexShaderConstantBufferOrtho[mFrameIndex]->Map<VertexShaderConstantBuffer>();
  730. *vs = mVSBufferOrtho;
  731. mVertexShaderConstantBufferOrtho[mFrameIndex]->Unmap();
  732. // Set constants for pixel shader
  733. PixelShaderConstantBuffer *ps = mPixelShaderConstantBuffer[mFrameIndex]->Map<PixelShaderConstantBuffer>();
  734. *ps = mPSBuffer;
  735. mPixelShaderConstantBuffer[mFrameIndex]->Unmap();
  736. // Set the view port and scissor rect to the shadow map size
  737. UpdateViewPortAndScissorRect(cShadowMapSize, cShadowMapSize);
  738. // Switch to 3d projection mode
  739. SetProjectionMode();
  740. }
  741. void RendererVK::EndShadowPass()
  742. {
  743. VkCommandBuffer command_buffer = GetCommandBuffer();
  744. // End the shadow pass
  745. vkCmdEndRenderPass(command_buffer);
  746. // Begin the normal render pass
  747. VkClearValue clear_values[2];
  748. clear_values[0].color = {{ 0.098f, 0.098f, 0.439f, 1.000f }};
  749. clear_values[1].depthStencil = { 0.0f, 0 }; // Reverse-Z clears to 0
  750. VkRenderPassBeginInfo render_pass_begin_info = {};
  751. render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  752. render_pass_begin_info.renderPass = mRenderPass;
  753. JPH_ASSERT(mImageIndex < mSwapChainFramebuffers.size());
  754. render_pass_begin_info.framebuffer = mSwapChainFramebuffers[mImageIndex];
  755. render_pass_begin_info.renderArea.extent = mSwapChainExtent;
  756. render_pass_begin_info.clearValueCount = std::size(clear_values);
  757. render_pass_begin_info.pClearValues = clear_values;
  758. vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
  759. // Set the view port and scissor rect to the screen size
  760. UpdateViewPortAndScissorRect(mSwapChainExtent.width, mSwapChainExtent.height);
  761. }
  762. void RendererVK::EndFrame()
  763. {
  764. JPH_PROFILE_FUNCTION();
  765. // If we have no swap chain, bail out
  766. if (mSwapChain == nullptr)
  767. {
  768. Renderer::EndFrame();
  769. return;
  770. }
  771. VkCommandBuffer command_buffer = GetCommandBuffer();
  772. vkCmdEndRenderPass(command_buffer);
  773. FatalErrorIfFailed(vkEndCommandBuffer(command_buffer));
  774. VkSemaphore wait_semaphores[] = { mImageAvailableSemaphores[mFrameIndex] };
  775. VkSemaphore signal_semaphores[] = { mRenderFinishedSemaphores[mFrameIndex] };
  776. VkPipelineStageFlags wait_stages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
  777. VkSubmitInfo submit_info = {};
  778. submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  779. submit_info.waitSemaphoreCount = 1;
  780. submit_info.pWaitSemaphores = wait_semaphores;
  781. submit_info.pWaitDstStageMask = wait_stages;
  782. submit_info.commandBufferCount = 1;
  783. submit_info.pCommandBuffers = &command_buffer;
  784. submit_info.signalSemaphoreCount = 1;
  785. submit_info.pSignalSemaphores = signal_semaphores;
  786. FatalErrorIfFailed(vkQueueSubmit(mGraphicsQueue, 1, &submit_info, mInFlightFences[mFrameIndex]));
  787. VkSwapchainKHR swap_chains[] = { mSwapChain };
  788. VkPresentInfoKHR present_info = {};
  789. present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  790. present_info.waitSemaphoreCount = 1;
  791. present_info.pWaitSemaphores = signal_semaphores;
  792. present_info.swapchainCount = 1;
  793. present_info.pSwapchains = swap_chains;
  794. present_info.pImageIndices = &mImageIndex;
  795. vkQueuePresentKHR(mPresentQueue, &present_info);
  796. Renderer::EndFrame();
  797. }
  798. void RendererVK::SetProjectionMode()
  799. {
  800. JPH_ASSERT(mInFrame);
  801. // Bind descriptor set for 3d rendering
  802. vkCmdBindDescriptorSets(GetCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, mPipelineLayout, 0, 1, &mDescriptorSets[mFrameIndex], 0, nullptr);
  803. }
  804. void RendererVK::SetOrthoMode()
  805. {
  806. JPH_ASSERT(mInFrame);
  807. // Bind descriptor set for 2d rendering
  808. vkCmdBindDescriptorSets(GetCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS, mPipelineLayout, 0, 1, &mDescriptorSetsOrtho[mFrameIndex], 0, nullptr);
  809. }
  810. Ref<Texture> RendererVK::CreateTexture(const Surface *inSurface)
  811. {
  812. return new TextureVK(this, inSurface);
  813. }
  814. Ref<VertexShader> RendererVK::CreateVertexShader(const char *inFileName)
  815. {
  816. Array<uint8> data = ReadData((String(inFileName) + ".vert.spv").c_str());
  817. VkShaderModuleCreateInfo create_info = {};
  818. create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  819. create_info.codeSize = data.size();
  820. create_info.pCode = reinterpret_cast<const uint32 *>(data.data());
  821. VkShaderModule shader_module;
  822. FatalErrorIfFailed(vkCreateShaderModule(mDevice, &create_info, nullptr, &shader_module));
  823. return new VertexShaderVK(mDevice, shader_module);
  824. }
  825. Ref<PixelShader> RendererVK::CreatePixelShader(const char *inFileName)
  826. {
  827. Array<uint8> data = ReadData((String(inFileName) + ".frag.spv").c_str());
  828. VkShaderModuleCreateInfo create_info = {};
  829. create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  830. create_info.codeSize = data.size();
  831. create_info.pCode = reinterpret_cast<const uint32 *>(data.data());
  832. VkShaderModule shader_module;
  833. FatalErrorIfFailed(vkCreateShaderModule(mDevice, &create_info, nullptr, &shader_module));
  834. return new PixelShaderVK(mDevice, shader_module);
  835. }
  836. unique_ptr<PipelineState> RendererVK::CreatePipelineState(const VertexShader *inVertexShader, const PipelineState::EInputDescription *inInputDescription, uint inInputDescriptionCount, const PixelShader *inPixelShader, PipelineState::EDrawPass inDrawPass, PipelineState::EFillMode inFillMode, PipelineState::ETopology inTopology, PipelineState::EDepthTest inDepthTest, PipelineState::EBlendMode inBlendMode, PipelineState::ECullMode inCullMode)
  837. {
  838. return make_unique<PipelineStateVK>(this, static_cast<const VertexShaderVK *>(inVertexShader), inInputDescription, inInputDescriptionCount, static_cast<const PixelShaderVK *>(inPixelShader), inDrawPass, inFillMode, inTopology, inDepthTest, inBlendMode, inCullMode);
  839. }
  840. RenderPrimitive *RendererVK::CreateRenderPrimitive(PipelineState::ETopology inType)
  841. {
  842. return new RenderPrimitiveVK(this);
  843. }
  844. RenderInstances *RendererVK::CreateRenderInstances()
  845. {
  846. return new RenderInstancesVK(this);
  847. }
  848. uint32 RendererVK::FindMemoryType(uint32 inTypeFilter, VkMemoryPropertyFlags inProperties)
  849. {
  850. for (uint32 i = 0; i < mMemoryProperties.memoryTypeCount; i++)
  851. if ((inTypeFilter & (1 << i))
  852. && (mMemoryProperties.memoryTypes[i].propertyFlags & inProperties) == inProperties)
  853. return i;
  854. FatalError("Failed to find memory type!");
  855. }
  856. void RendererVK::AllocateMemory(VkDeviceSize inSize, uint32 inMemoryTypeBits, VkMemoryPropertyFlags inProperties, VkDeviceMemory &outMemory)
  857. {
  858. VkMemoryAllocateInfo alloc_info = {};
  859. alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  860. alloc_info.allocationSize = inSize;
  861. alloc_info.memoryTypeIndex = FindMemoryType(inMemoryTypeBits, inProperties);
  862. FatalErrorIfFailed(vkAllocateMemory(mDevice, &alloc_info, nullptr, &outMemory));
  863. // Track allocation
  864. ++mNumAllocations;
  865. mTotalAllocated += inSize;
  866. // Track max usage
  867. mMaxTotalAllocated = max(mMaxTotalAllocated, mTotalAllocated);
  868. mMaxNumAllocations = max(mMaxNumAllocations, mNumAllocations);
  869. }
  870. void RendererVK::FreeMemory(VkDeviceMemory inMemory, VkDeviceSize inSize)
  871. {
  872. vkFreeMemory(mDevice, inMemory, nullptr);
  873. // Track free
  874. --mNumAllocations;
  875. mTotalAllocated -= inSize;
  876. }
  877. void RendererVK::CreateBuffer(VkDeviceSize inSize, VkBufferUsageFlags inUsage, VkMemoryPropertyFlags inProperties, BufferVK &outBuffer)
  878. {
  879. // Check the cache
  880. BufferCache::iterator i = mBufferCache.find({ inSize, inUsage, inProperties });
  881. if (i != mBufferCache.end() && !i->second.empty())
  882. {
  883. outBuffer = i->second.back();
  884. i->second.pop_back();
  885. return;
  886. }
  887. // Create a new buffer
  888. outBuffer.mSize = inSize;
  889. outBuffer.mUsage = inUsage;
  890. outBuffer.mProperties = inProperties;
  891. VkBufferCreateInfo create_info = {};
  892. create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  893. create_info.size = inSize;
  894. create_info.usage = inUsage;
  895. create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  896. FatalErrorIfFailed(vkCreateBuffer(mDevice, &create_info, nullptr, &outBuffer.mBuffer));
  897. VkMemoryRequirements mem_requirements;
  898. vkGetBufferMemoryRequirements(mDevice, outBuffer.mBuffer, &mem_requirements);
  899. if (mem_requirements.size > cMaxAllocSize)
  900. {
  901. // Allocate block directly
  902. AllocateMemory(mem_requirements.size, mem_requirements.memoryTypeBits, inProperties, outBuffer.mMemory);
  903. outBuffer.mAllocatedSize = mem_requirements.size;
  904. outBuffer.mOffset = 0;
  905. }
  906. else
  907. {
  908. // Round allocation to the next power of 2 so that we can use a simple block based allocator
  909. outBuffer.mAllocatedSize = max(VkDeviceSize(GetNextPowerOf2(uint32(mem_requirements.size))), cMinAllocSize);
  910. // Ensure that we have memory available from the right pool
  911. Array<Memory> &mem_array = mMemoryCache[{ outBuffer.mAllocatedSize, outBuffer.mUsage, outBuffer.mProperties }];
  912. if (mem_array.empty())
  913. {
  914. // Allocate a bigger block
  915. VkDeviceMemory device_memory;
  916. AllocateMemory(cBlockSize, mem_requirements.memoryTypeBits, inProperties, device_memory);
  917. // Divide into sub blocks
  918. for (VkDeviceSize offset = 0; offset < cBlockSize; offset += outBuffer.mAllocatedSize)
  919. mem_array.push_back({ device_memory, offset });
  920. }
  921. // Claim memory from the pool
  922. Memory &memory = mem_array.back();
  923. outBuffer.mMemory = memory.mMemory;
  924. outBuffer.mOffset = memory.mOffset;
  925. mem_array.pop_back();
  926. }
  927. // Bind the memory to the buffer
  928. vkBindBufferMemory(mDevice, outBuffer.mBuffer, outBuffer.mMemory, outBuffer.mOffset);
  929. }
  930. VkCommandBuffer RendererVK::StartTempCommandBuffer()
  931. {
  932. VkCommandBufferAllocateInfo alloc_info = {};
  933. alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  934. alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  935. alloc_info.commandPool = mCommandPool;
  936. alloc_info.commandBufferCount = 1;
  937. VkCommandBuffer command_buffer;
  938. vkAllocateCommandBuffers(mDevice, &alloc_info, &command_buffer);
  939. VkCommandBufferBeginInfo begin_info = {};
  940. begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  941. begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  942. vkBeginCommandBuffer(command_buffer, &begin_info);
  943. return command_buffer;
  944. }
  945. void RendererVK::EndTempCommandBuffer(VkCommandBuffer inCommandBuffer)
  946. {
  947. vkEndCommandBuffer(inCommandBuffer);
  948. VkSubmitInfo submit_info = {};
  949. submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  950. submit_info.commandBufferCount = 1;
  951. submit_info.pCommandBuffers = &inCommandBuffer;
  952. vkQueueSubmit(mGraphicsQueue, 1, &submit_info, VK_NULL_HANDLE);
  953. vkQueueWaitIdle(mGraphicsQueue); // Inefficient, but we only use this during initialization
  954. vkFreeCommandBuffers(mDevice, mCommandPool, 1, &inCommandBuffer);
  955. }
  956. void RendererVK::CopyBuffer(VkBuffer inSrc, VkBuffer inDst, VkDeviceSize inSize)
  957. {
  958. VkCommandBuffer command_buffer = StartTempCommandBuffer();
  959. VkBufferCopy region = {};
  960. region.size = inSize;
  961. vkCmdCopyBuffer(command_buffer, inSrc, inDst, 1, &region);
  962. EndTempCommandBuffer(command_buffer);
  963. }
  964. void RendererVK::CreateDeviceLocalBuffer(const void *inData, VkDeviceSize inSize, VkBufferUsageFlags inUsage, BufferVK &outBuffer)
  965. {
  966. BufferVK staging_buffer;
  967. CreateBuffer(inSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, staging_buffer);
  968. void *data;
  969. vkMapMemory(mDevice, staging_buffer.mMemory, staging_buffer.mOffset, inSize, 0, &data);
  970. memcpy(data, inData, (size_t)inSize);
  971. vkUnmapMemory(mDevice, staging_buffer.mMemory);
  972. CreateBuffer(inSize, inUsage | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, outBuffer);
  973. CopyBuffer(staging_buffer.mBuffer, outBuffer.mBuffer, inSize);
  974. FreeBuffer(staging_buffer);
  975. }
  976. void RendererVK::FreeBuffer(BufferVK &ioBuffer)
  977. {
  978. if (ioBuffer.mBuffer != VK_NULL_HANDLE)
  979. {
  980. JPH_ASSERT(mFrameIndex < cFrameCount);
  981. mFreedBuffers[mFrameIndex][{ ioBuffer.mSize, ioBuffer.mUsage, ioBuffer.mProperties }].push_back(ioBuffer);
  982. }
  983. }
  984. void RendererVK::FreeBufferInternal(BufferVK &ioBuffer)
  985. {
  986. // Destroy the buffer
  987. vkDestroyBuffer(mDevice, ioBuffer.mBuffer, nullptr);
  988. ioBuffer.mBuffer = VK_NULL_HANDLE;
  989. if (ioBuffer.mAllocatedSize > cMaxAllocSize)
  990. FreeMemory(ioBuffer.mMemory, ioBuffer.mAllocatedSize);
  991. else
  992. mMemoryCache[{ ioBuffer.mAllocatedSize, ioBuffer.mUsage, ioBuffer.mProperties }].push_back({ ioBuffer.mMemory, ioBuffer.mOffset });
  993. ioBuffer.mMemory = VK_NULL_HANDLE;
  994. }
  995. unique_ptr<ConstantBufferVK> RendererVK::CreateConstantBuffer(VkDeviceSize inBufferSize)
  996. {
  997. return make_unique<ConstantBufferVK>(this, inBufferSize);
  998. }
  999. VkImageView RendererVK::CreateImageView(VkImage inImage, VkFormat inFormat, VkImageAspectFlags inAspectFlags)
  1000. {
  1001. VkImageViewCreateInfo view_info = {};
  1002. view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  1003. view_info.image = inImage;
  1004. view_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
  1005. view_info.format = inFormat;
  1006. view_info.subresourceRange.aspectMask = inAspectFlags;
  1007. view_info.subresourceRange.levelCount = 1;
  1008. view_info.subresourceRange.layerCount = 1;
  1009. VkImageView image_view;
  1010. FatalErrorIfFailed(vkCreateImageView(mDevice, &view_info, nullptr, &image_view));
  1011. return image_view;
  1012. }
  1013. void RendererVK::CreateImage(uint32 inWidth, uint32 inHeight, VkFormat inFormat, VkImageTiling inTiling, VkImageUsageFlags inUsage, VkMemoryPropertyFlags inProperties, VkImage &outImage, VkDeviceMemory &outMemory)
  1014. {
  1015. VkImageCreateInfo image_info = {};
  1016. image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  1017. image_info.imageType = VK_IMAGE_TYPE_2D;
  1018. image_info.extent.width = inWidth;
  1019. image_info.extent.height = inHeight;
  1020. image_info.extent.depth = 1;
  1021. image_info.mipLevels = 1;
  1022. image_info.arrayLayers = 1;
  1023. image_info.format = inFormat;
  1024. image_info.tiling = inTiling;
  1025. image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  1026. image_info.usage = inUsage;
  1027. image_info.samples = VK_SAMPLE_COUNT_1_BIT;
  1028. image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  1029. FatalErrorIfFailed(vkCreateImage(mDevice, &image_info, nullptr, &outImage));
  1030. VkMemoryRequirements mem_requirements;
  1031. vkGetImageMemoryRequirements(mDevice, outImage, &mem_requirements);
  1032. AllocateMemory(mem_requirements.size, mem_requirements.memoryTypeBits, inProperties, outMemory);
  1033. vkBindImageMemory(mDevice, outImage, outMemory, 0);
  1034. }
  1035. void RendererVK::DestroyImage(VkImage inImage, VkDeviceMemory inMemory)
  1036. {
  1037. VkMemoryRequirements mem_requirements;
  1038. vkGetImageMemoryRequirements(mDevice, inImage, &mem_requirements);
  1039. vkDestroyImage(mDevice, inImage, nullptr);
  1040. FreeMemory(inMemory, mem_requirements.size);
  1041. }
  1042. void RendererVK::UpdateViewPortAndScissorRect(uint32 inWidth, uint32 inHeight)
  1043. {
  1044. VkCommandBuffer command_buffer = GetCommandBuffer();
  1045. // Update the view port rect
  1046. VkViewport viewport = {};
  1047. viewport.x = 0.0f;
  1048. viewport.y = 0.0f;
  1049. viewport.width = (float)inWidth;
  1050. viewport.height = (float)inHeight;
  1051. viewport.minDepth = 0.0f;
  1052. viewport.maxDepth = 1.0f;
  1053. vkCmdSetViewport(command_buffer, 0, 1, &viewport);
  1054. // Update the scissor rect
  1055. VkRect2D scissor = {};
  1056. scissor.extent = { inWidth, inHeight };
  1057. vkCmdSetScissor(command_buffer, 0, 1, &scissor);
  1058. }