eric_ch

Untitled

Jul 26th, 2018
363
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 82.49 KB | None | 0 0
  1. #include "vengine.h"
  2. #include "vtool.h"
  3.  
  4. #define STB_IMAGE_IMPLEMENTATION
  5. #include <stb_image.h>
  6.  
  7. #define TINYOBJLOADER_IMPLEMENTATION
  8. #include <tiny_obj_loader.h>
  9.  
  10. #define SHADOWMAP_FILTER VK_FILTER_LINEAR
  11.  
  12. #include <vector>
  13.  
  14.  
  15. namespace std {
  16. template<> struct hash<ve::VEngine::Vertex> {
  17. size_t operator()(ve::VEngine::Vertex const& vertex) const {
  18. return ((hash<glm::vec3>()(vertex.pos) ^ (hash<glm::vec3>()(vertex.normal) << 1)) >> 1) ^ (hash<glm::vec2>()(vertex.texCoord) << 1);
  19. }
  20. };
  21.  
  22. }
  23.  
  24. static void onWindowResized(GLFWwindow* window, int width, int height) {
  25. if (width == 0 || height == 0) return;
  26.  
  27. ve::VEngine* app = reinterpret_cast<ve::VEngine*>(glfwGetWindowUserPointer(window));
  28. app->recreateSwapChain();
  29. }
  30.  
  31. namespace ve {
  32. VEngine::VEngine()
  33. {
  34. }
  35.  
  36. VEngine::~VEngine()
  37. {
  38.  
  39.  
  40.  
  41. }
  42.  
  43.  
  44. void VEngine::Clear()
  45. {
  46. for (int index = 0; index < uniform_buffers_.size(); index++) {
  47. vkDestroyBuffer(logic_device_, uniform_buffers_[index], nullptr);
  48. vkFreeMemory(logic_device_, uniform_buffer_memorys_[index], nullptr);
  49. }
  50. }
  51.  
  52. void VEngine::CreateTexture(const std::string & texture_path, VkImage& texture, VkDeviceMemory& texture_memory)
  53. {
  54. int texWidth, texHeight, texChannels;
  55. stbi_uc* pixels = stbi_load(texture_path.c_str(), &texWidth, &texHeight, &texChannels, STBI_rgb_alpha);
  56. VkDeviceSize imageSize = texWidth * texHeight * 4;
  57.  
  58. if (!pixels) {
  59. throw std::runtime_error("failed to load texture image!");
  60. }
  61.  
  62. VkBuffer stagingBuffer;
  63. VkDeviceMemory stagingBufferMemory;
  64. createBuffer(imageSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
  65.  
  66. void* data;
  67. vkMapMemory(device, stagingBufferMemory, 0, imageSize, 0, &data);
  68. memcpy(data, pixels, static_cast<size_t>(imageSize));
  69. vkUnmapMemory(device, stagingBufferMemory);
  70.  
  71. stbi_image_free(pixels);
  72.  
  73. createImage(texWidth, texHeight, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, texture, texture_memory);
  74.  
  75. transitionImageLayout(texture, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
  76. copyBufferToImage(stagingBuffer, texture, static_cast<uint32_t>(texWidth), static_cast<uint32_t>(texHeight));
  77. transitionImageLayout(texture, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
  78.  
  79. vkDestroyBuffer(device, stagingBuffer, nullptr);
  80. vkFreeMemory(device, stagingBufferMemory, nullptr);
  81. }
  82.  
  83. void VEngine::CreateTextureView(VkImageView & view, VkImage & texture)
  84. {
  85. view = createImageView(texture, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
  86. }
  87.  
  88. void VEngine::CreateTextureSampler(VkSampler & sampler)
  89. {
  90. VkSamplerCreateInfo samplerInfo = {};
  91. samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
  92. samplerInfo.magFilter = VK_FILTER_LINEAR;
  93. samplerInfo.minFilter = VK_FILTER_LINEAR;
  94. samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  95. samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  96. samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT;
  97. samplerInfo.anisotropyEnable = VK_TRUE;
  98. samplerInfo.maxAnisotropy = 16;
  99. samplerInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
  100. samplerInfo.unnormalizedCoordinates = VK_FALSE;
  101. samplerInfo.compareEnable = VK_FALSE;
  102. samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
  103. samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
  104.  
  105. if (vkCreateSampler(device, &samplerInfo, nullptr, &sampler) != VK_SUCCESS) {
  106. throw std::runtime_error("failed to create texture sampler!");
  107. }
  108. }
  109.  
  110. void VEngine::AddScene(const ve::VScene & scene)
  111. {
  112. std::cout << "add a scene to engine!\n";
  113.  
  114. std::array<VkWriteDescriptorSet, 7> descriptorWrites = {};
  115.  
  116. }
  117.  
  118. const VkDevice VEngine::get_logic_device()
  119. {
  120. return logic_device_;
  121. }
  122.  
  123. void VEngine::AddUniformBufferAndMemory(const VkBuffer & uniform_buffer, const VkDeviceMemory & uniform_buffer_memory)
  124. {
  125. uniform_buffers_.push_back(uniform_buffer);
  126. uniform_buffer_memorys_.push_back(uniform_buffer_memory);
  127. }
  128.  
  129.  
  130. void VEngine::cleanup() {
  131. cleanupSwapChain();
  132.  
  133. vkDestroyBuffer(device, indexBuffer, nullptr);
  134. vkFreeMemory(device, indexBufferMemory, nullptr);
  135.  
  136. vkDestroyBuffer(device, vertexBuffer, nullptr);
  137. vkFreeMemory(device, vertexBufferMemory, nullptr);
  138.  
  139. vkDestroyBuffer(device, uniformMatrixBuffer, nullptr);
  140. vkFreeMemory(device, uniformMatrixBufferMemory, nullptr);
  141.  
  142. vkDestroySemaphore(device, renderFinishedSemaphore, nullptr);
  143. vkDestroySemaphore(device, imageAvailableSemaphore, nullptr);
  144.  
  145. vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
  146. vkDestroyDescriptorPool(device, descriptorPool, nullptr);
  147.  
  148. vkDestroyCommandPool(device, commandPool, nullptr);
  149.  
  150. vkDestroyDevice(device, nullptr);
  151. vkDestroySurfaceKHR(instance, surface, nullptr);
  152. vkDestroyInstance(instance, nullptr);
  153.  
  154. glfwDestroyWindow(window);
  155.  
  156. glfwTerminate();
  157. }
  158.  
  159. void VEngine::Run()
  160. {
  161. loadModel();
  162. initWindow();
  163. initVulkan();
  164. mainLoop();
  165. cleanup();
  166. }
  167.  
  168. void VEngine::initWindow() {
  169. glfwInit();
  170.  
  171. glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
  172.  
  173. window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
  174.  
  175. glfwSetWindowUserPointer(window, this);
  176. glfwSetWindowSizeCallback(window, onWindowResized);
  177. }
  178.  
  179. void VEngine::initVulkan() {
  180. createInstance();
  181. createSurface();
  182. pickPhysicalDevice();
  183. createLogicalDevice();
  184. createSemaphores();
  185. findDepthFormat(physicalDevice, &depthFormat);
  186. createSwapChain();
  187. createImageViews();
  188. createCommandPool();
  189. createRenderPass();
  190. createFramebuffers();
  191.  
  192. createDescriptorSetLayout();
  193. createGraphicsPipeline();
  194. createVertexBuffer();
  195. createIndexBuffer();
  196. createUniformBuffer();
  197. createDescriptorPool();
  198. createDescriptorSet();
  199. createCommandBuffers();
  200.  
  201. }
  202.  
  203. void VEngine::mainLoop() {
  204. while (!glfwWindowShouldClose(window) && glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS) {
  205. glfwPollEvents();
  206.  
  207. updateUniformBuffer();
  208.  
  209.  
  210. drawFrame();
  211. }
  212.  
  213. vkDeviceWaitIdle(device);
  214. }
  215.  
  216. void VEngine::cleanupSwapChain() {
  217. vkDestroyImageView(device, depthImageView, nullptr);
  218. vkDestroyImage(device, depthImage, nullptr);
  219. vkFreeMemory(device, depthImageMemory, nullptr);
  220.  
  221. for (size_t i = 0; i < swapChainFramebuffers.size(); i++) {
  222. vkDestroyFramebuffer(device, swapChainFramebuffers[i], nullptr);
  223. }
  224.  
  225. vkFreeCommandBuffers(device, commandPool, static_cast<uint32_t>(commandBuffers.size()), commandBuffers.data());
  226.  
  227. vkDestroyPipeline(device, graphicsPipeline, nullptr);
  228. vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
  229. vkDestroyRenderPass(device, renderPass, nullptr);
  230.  
  231. for (size_t i = 0; i < swapChainImageViews.size(); i++) {
  232. vkDestroyImageView(device, swapChainImageViews[i], nullptr);
  233. }
  234.  
  235. vkDestroySwapchainKHR(device, swapChain, nullptr);
  236. }
  237.  
  238. void VEngine::recreateSwapChain() {
  239. vkDeviceWaitIdle(device);
  240.  
  241. cleanupSwapChain();
  242.  
  243. createSwapChain();
  244. createImageViews();
  245. createRenderPass();
  246. createGraphicsPipeline();
  247. createFramebuffers();
  248.  
  249. createCommandBuffers();
  250.  
  251. }
  252.  
  253. void VEngine::createInstance() {
  254. if (enableValidationLayers && !checkValidationLayerSupport()) {
  255. throw std::runtime_error("validation layers requested, but not available!");
  256. }
  257.  
  258. VkApplicationInfo appInfo = {};
  259. appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  260. appInfo.pApplicationName = "Hello Vulkan";
  261. appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
  262. appInfo.pEngineName = "Vulkan Engine";
  263. appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
  264. appInfo.apiVersion = VK_API_VERSION_1_0;
  265.  
  266. VkInstanceCreateInfo createInfo = {};
  267. createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  268. createInfo.pApplicationInfo = &appInfo;
  269.  
  270. auto extensions = getRequiredExtensions();
  271. createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
  272. createInfo.ppEnabledExtensionNames = extensions.data();
  273.  
  274. if (enableValidationLayers) {
  275. createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  276. createInfo.ppEnabledLayerNames = validationLayers.data();
  277. }
  278. else {
  279. createInfo.enabledLayerCount = 0;
  280. }
  281.  
  282. if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
  283. throw std::runtime_error("failed to create instance!");
  284. }
  285. }
  286.  
  287.  
  288.  
  289. void VEngine::createSurface() {
  290. if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) {
  291. throw std::runtime_error("failed to create window surface!");
  292. }
  293. }
  294.  
  295. void VEngine::pickPhysicalDevice() {
  296. uint32_t deviceCount = 0;
  297. vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
  298.  
  299. if (deviceCount == 0) {
  300. throw std::runtime_error("failed to find GPUs with Vulkan support!");
  301. }
  302.  
  303. std::vector<VkPhysicalDevice> devices(deviceCount);
  304. vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
  305.  
  306. for (const auto& device : devices) {
  307. if (isDeviceSuitable(device)) {
  308. physicalDevice = device;
  309. break;
  310. }
  311. }
  312.  
  313. if (physicalDevice == VK_NULL_HANDLE) {
  314. throw std::runtime_error("failed to find a suitable GPU!");
  315. }
  316. }
  317.  
  318. void VEngine::createLogicalDevice() {
  319. QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
  320.  
  321. std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
  322. std::set<int> uniqueQueueFamilies = { indices.graphicsFamily, indices.presentFamily };
  323.  
  324. float queuePriority = 1.0f;
  325. for (int queueFamily : uniqueQueueFamilies) {
  326. VkDeviceQueueCreateInfo queueCreateInfo = {};
  327. queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  328. queueCreateInfo.queueFamilyIndex = queueFamily;
  329. queueCreateInfo.queueCount = 1;
  330. queueCreateInfo.pQueuePriorities = &queuePriority;
  331. queueCreateInfos.push_back(queueCreateInfo);
  332. }
  333.  
  334. VkPhysicalDeviceFeatures deviceFeatures = {};
  335. deviceFeatures.samplerAnisotropy = VK_TRUE;
  336. deviceFeatures.sampleRateShading = VK_TRUE;
  337.  
  338.  
  339. VkDeviceCreateInfo createInfo = {};
  340. createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  341.  
  342. createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
  343. createInfo.pQueueCreateInfos = queueCreateInfos.data();
  344.  
  345. createInfo.pEnabledFeatures = &deviceFeatures;
  346.  
  347. createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
  348. createInfo.ppEnabledExtensionNames = deviceExtensions.data();
  349.  
  350. if (enableValidationLayers) {
  351. createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
  352. createInfo.ppEnabledLayerNames = validationLayers.data();
  353. }
  354. else {
  355. createInfo.enabledLayerCount = 0;
  356. }
  357.  
  358. if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
  359. throw std::runtime_error("failed to create logical device!");
  360. }
  361.  
  362. //vkGetDeviceQueue(device, indices.graphicsFamily, 0, &graphicsQueue);
  363. vkGetDeviceQueue(device, indices.presentFamily, 0, &presentQueue);
  364. }
  365.  
  366.  
  367. void VEngine::createSwapChain() {
  368. SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);
  369.  
  370. VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
  371. VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
  372. VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);
  373.  
  374. uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
  375. if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {
  376. imageCount = swapChainSupport.capabilities.maxImageCount;
  377. }
  378.  
  379. VkSwapchainCreateInfoKHR createInfo = {};
  380. createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  381. createInfo.surface = surface;
  382.  
  383. createInfo.minImageCount = imageCount;
  384. createInfo.imageFormat = surfaceFormat.format;
  385. createInfo.imageColorSpace = surfaceFormat.colorSpace;
  386. createInfo.imageExtent = extent;
  387. createInfo.imageArrayLayers = 1;
  388. createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  389.  
  390. QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
  391. uint32_t queueFamilyIndices[] = { (uint32_t)indices.graphicsFamily, (uint32_t)indices.presentFamily };
  392.  
  393. if (indices.graphicsFamily != indices.presentFamily) {
  394. createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
  395. createInfo.queueFamilyIndexCount = 2;
  396. createInfo.pQueueFamilyIndices = queueFamilyIndices;
  397. }
  398. else {
  399. createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  400. }
  401.  
  402. createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
  403. createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  404. createInfo.presentMode = presentMode;
  405. createInfo.clipped = VK_TRUE;
  406.  
  407. if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) {
  408. throw std::runtime_error("failed to create swap chain!");
  409. }
  410.  
  411. vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);
  412. swapChainImages.resize(imageCount);
  413. vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());
  414.  
  415. swapChainImageFormat = surfaceFormat.format;
  416. swapChainExtent = extent;
  417. }
  418.  
  419. void VEngine::createImageViews() {
  420. swapChainImageViews.resize(swapChainImages.size());
  421.  
  422. for (uint32_t i = 0; i < swapChainImages.size(); i++) {
  423. swapChainImageViews[i] = createImageView(swapChainImages[i], swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT);
  424. }
  425. }
  426.  
  427. void VEngine::createRenderPass() {
  428. std::array<VkAttachmentDescription, 2> attachments{};
  429. attachments[0].format = swapChainImageFormat;
  430. attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
  431. attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  432. attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  433. attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  434. attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  435. attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  436. attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  437.  
  438. attachments[1].format = depthFormat;
  439. attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
  440. attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  441. attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  442. attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  443. attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  444. attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  445. attachments[1].finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  446.  
  447. VkAttachmentReference colorAttachmentRef[1];
  448. colorAttachmentRef[0] = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
  449.  
  450. VkAttachmentReference depthAttachmentRef = {};
  451. depthAttachmentRef.attachment = 1;
  452. depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  453.  
  454. VkSubpassDescription subpass = {};
  455. subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  456. subpass.colorAttachmentCount = 1;
  457. subpass.pColorAttachments = colorAttachmentRef;
  458. subpass.pDepthStencilAttachment = &depthAttachmentRef;
  459.  
  460. VkSubpassDependency dependency[2] = {};
  461.  
  462. dependency[0].srcSubpass = VK_SUBPASS_EXTERNAL;
  463. dependency[0].dstSubpass = 0;
  464. dependency[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  465. dependency[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  466. dependency[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
  467. dependency[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  468. dependency[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
  469.  
  470. dependency[1].srcSubpass = 0;
  471. dependency[1].dstSubpass = VK_SUBPASS_EXTERNAL;
  472. dependency[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  473. dependency[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  474. dependency[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  475. dependency[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
  476. dependency[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
  477.  
  478.  
  479. VkRenderPassCreateInfo renderPassInfo = {};
  480. renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  481. renderPassInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
  482. renderPassInfo.pAttachments = attachments.data();
  483. renderPassInfo.subpassCount = 1;
  484. renderPassInfo.pSubpasses = &subpass;
  485. renderPassInfo.dependencyCount = 2;
  486. renderPassInfo.pDependencies = dependency;
  487.  
  488. if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) {
  489. throw std::runtime_error("failed to create render pass!");
  490. }
  491. }
  492.  
  493. void VEngine::createDescriptorSetLayout() {
  494. VkDescriptorSetLayoutBinding uboLayoutBinding = {};
  495. uboLayoutBinding.binding = 0;
  496. uboLayoutBinding.descriptorCount = 1;
  497. uboLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  498. uboLayoutBinding.pImmutableSamplers = nullptr;
  499. uboLayoutBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
  500.  
  501. VkDescriptorSetLayoutBinding usvLayoutBinding = {};
  502. usvLayoutBinding.binding = 1;
  503. usvLayoutBinding.descriptorCount = 1;
  504. usvLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  505. usvLayoutBinding.pImmutableSamplers = nullptr;
  506. usvLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  507.  
  508. VkDescriptorSetLayoutBinding usfLayoutBinding = {};
  509. usfLayoutBinding.binding = 2;
  510. usfLayoutBinding.descriptorCount = 1;
  511. usfLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  512. usfLayoutBinding.pImmutableSamplers = nullptr;
  513. usfLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  514.  
  515. VkDescriptorSetLayoutBinding specialLayoutBinding = {};
  516. specialLayoutBinding.binding = 6;
  517. specialLayoutBinding.descriptorCount = 1;
  518. specialLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  519. specialLayoutBinding.pImmutableSamplers = nullptr;
  520. specialLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  521.  
  522. VkDescriptorSetLayoutBinding specialTextureLayoutBinding = {};
  523. specialTextureLayoutBinding.binding = 7;
  524. specialTextureLayoutBinding.descriptorCount = 1;
  525. specialTextureLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  526. specialTextureLayoutBinding.pImmutableSamplers = nullptr;
  527. specialTextureLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  528.  
  529. VkDescriptorSetLayoutBinding samplerLayoutBinding = {};
  530. samplerLayoutBinding.binding = 3;
  531. samplerLayoutBinding.descriptorCount = 1;
  532. samplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  533. samplerLayoutBinding.pImmutableSamplers = nullptr;
  534. samplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  535.  
  536. VkDescriptorSetLayoutBinding specularSamplerLayoutBinding = {};
  537. specularSamplerLayoutBinding.binding = 4;
  538. specularSamplerLayoutBinding.descriptorCount = 1;
  539. specularSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  540. specularSamplerLayoutBinding.pImmutableSamplers = nullptr;
  541. specularSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  542.  
  543. VkDescriptorSetLayoutBinding bumpSamplerLayoutBinding = {};
  544. bumpSamplerLayoutBinding.binding = 5;
  545. bumpSamplerLayoutBinding.descriptorCount = 1;
  546. bumpSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  547. bumpSamplerLayoutBinding.pImmutableSamplers = nullptr;
  548. bumpSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  549.  
  550. VkDescriptorSetLayoutBinding cutoffSamplerLayoutBinding = {};
  551. cutoffSamplerLayoutBinding.binding = 8;
  552. cutoffSamplerLayoutBinding.descriptorCount = 1;
  553. cutoffSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  554. cutoffSamplerLayoutBinding.pImmutableSamplers = nullptr;
  555. cutoffSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  556.  
  557. VkDescriptorSetLayoutBinding shadowMapSamplerLayoutBinding = {};
  558. shadowMapSamplerLayoutBinding.binding = 9;
  559. shadowMapSamplerLayoutBinding.descriptorCount = 1;
  560. shadowMapSamplerLayoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
  561. shadowMapSamplerLayoutBinding.pImmutableSamplers = nullptr;
  562. shadowMapSamplerLayoutBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  563.  
  564. std::array<VkDescriptorSetLayoutBinding, 10> bindings = {
  565. uboLayoutBinding, usvLayoutBinding, usfLayoutBinding, specialLayoutBinding, specialTextureLayoutBinding,
  566. samplerLayoutBinding, specularSamplerLayoutBinding, bumpSamplerLayoutBinding, cutoffSamplerLayoutBinding,
  567. shadowMapSamplerLayoutBinding};
  568.  
  569. VkDescriptorSetLayoutCreateInfo layoutInfo = {};
  570. layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  571. layoutInfo.bindingCount = static_cast<uint32_t>(bindings.size());
  572. layoutInfo.pBindings = bindings.data();
  573.  
  574. if (vkCreateDescriptorSetLayout(device, &layoutInfo, nullptr, &descriptorSetLayout) != VK_SUCCESS) {
  575. throw std::runtime_error("failed to create descriptor set layout!");
  576. }
  577. }
  578.  
  579. void VEngine::createGraphicsPipeline() {
  580. auto vertShaderCode = readFile("D:/project/vulkan_engine/media/shaders/shadow.vert.spv");
  581. auto fragShaderCode = readFile("D:/project/vulkan_engine/media/shaders/shadow.frag.spv");
  582.  
  583. VkShaderModule vertShaderModule = createShaderModule(vertShaderCode);
  584. VkShaderModule fragShaderModule = createShaderModule(fragShaderCode);
  585.  
  586. VkPipelineShaderStageCreateInfo vertShaderStageInfo = {};
  587. vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  588. vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
  589. vertShaderStageInfo.module = vertShaderModule;
  590. vertShaderStageInfo.pName = "main";
  591.  
  592. VkPipelineShaderStageCreateInfo fragShaderStageInfo = {};
  593. fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  594. fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
  595. fragShaderStageInfo.module = fragShaderModule;
  596. fragShaderStageInfo.pName = "main";
  597.  
  598. VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo };
  599.  
  600. VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
  601. vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  602.  
  603. auto bindingDescription = Vertex::getBindingDescription();
  604. auto attributeDescriptions = Vertex::getAttributeDescriptions();
  605.  
  606. vertexInputInfo.vertexBindingDescriptionCount = 1;
  607. vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
  608. vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
  609. vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
  610.  
  611. VkPipelineInputAssemblyStateCreateInfo inputAssembly = {};
  612. inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  613. inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  614. inputAssembly.primitiveRestartEnable = VK_FALSE;
  615.  
  616. VkViewport viewport = {};
  617. viewport.x = 0.0f;
  618. viewport.y = 0.0f;
  619. viewport.width = (float)swapChainExtent.width;
  620. viewport.height = (float)swapChainExtent.height;
  621. viewport.minDepth = 0.0f;
  622. viewport.maxDepth = 1.0f;
  623.  
  624. VkRect2D scissor = {};
  625. scissor.offset = { 0, 0 };
  626. scissor.extent = swapChainExtent;
  627.  
  628. VkPipelineViewportStateCreateInfo viewportState = {};
  629. viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  630. viewportState.viewportCount = 1;
  631. viewportState.pViewports = &viewport;
  632. viewportState.scissorCount = 1;
  633. viewportState.pScissors = &scissor;
  634.  
  635. VkPipelineRasterizationStateCreateInfo rasterizer = {};
  636. rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  637. rasterizer.depthClampEnable = VK_FALSE;
  638. rasterizer.rasterizerDiscardEnable = VK_FALSE;
  639. rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
  640. rasterizer.lineWidth = 1.0f;
  641. rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
  642. rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
  643. rasterizer.depthBiasEnable = VK_FALSE;
  644.  
  645. VkPipelineMultisampleStateCreateInfo multisampling = {};
  646. multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  647. multisampling.sampleShadingEnable = VK_TRUE;
  648. multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
  649.  
  650.  
  651. VkPipelineDepthStencilStateCreateInfo depthStencil = {};
  652. depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
  653. depthStencil.depthTestEnable = VK_TRUE;
  654. depthStencil.depthWriteEnable = VK_TRUE;
  655. depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
  656. depthStencil.depthBoundsTestEnable = VK_FALSE;
  657. depthStencil.stencilTestEnable = VK_FALSE;
  658.  
  659. std::array<VkPipelineColorBlendAttachmentState, 1> colorBlendAttachment = {};
  660. colorBlendAttachment[0].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
  661. colorBlendAttachment[0].blendEnable = VK_FALSE;
  662. /*colorBlendAttachment[0].colorBlendOp = VK_BLEND_OP_ADD;
  663. colorBlendAttachment[0].srcColorBlendFactor = VK_BLEND_FACTOR_SRC_COLOR;
  664. colorBlendAttachment[0].dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
  665. colorBlendAttachment[0].alphaBlendOp = VK_BLEND_OP_ADD;
  666. colorBlendAttachment[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
  667. colorBlendAttachment[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;*/
  668.  
  669. VkPipelineColorBlendStateCreateInfo colorBlending = {};
  670. colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  671. colorBlending.logicOpEnable = VK_FALSE;
  672. colorBlending.logicOp = VK_LOGIC_OP_COPY;
  673. colorBlending.attachmentCount = 1;
  674. colorBlending.pAttachments = colorBlendAttachment.data();
  675. colorBlending.blendConstants[0] = 0.0f;
  676. colorBlending.blendConstants[1] = 0.0f;
  677. colorBlending.blendConstants[2] = 0.0f;
  678. colorBlending.blendConstants[3] = 0.0f;
  679.  
  680. // Push constants for model matrices
  681. VkPushConstantRange pushConstantRange = {};
  682. pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
  683. pushConstantRange.offset = 0;
  684. pushConstantRange.size = sizeof(ConstantMatrixModel);
  685.  
  686. VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
  687. pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  688. pipelineLayoutInfo.setLayoutCount = 1;
  689. pipelineLayoutInfo.pSetLayouts = &descriptorSetLayout;
  690. pipelineLayoutInfo.pushConstantRangeCount = 1;
  691. pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
  692.  
  693. if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) {
  694. throw std::runtime_error("failed to create pipeline layout!");
  695. }
  696.  
  697. VkGraphicsPipelineCreateInfo pipelineInfo = {};
  698. pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  699. pipelineInfo.stageCount = 2;
  700. pipelineInfo.pStages = shaderStages;
  701. pipelineInfo.pVertexInputState = &vertexInputInfo;
  702. pipelineInfo.pInputAssemblyState = &inputAssembly;
  703. pipelineInfo.pViewportState = &viewportState;
  704. pipelineInfo.pRasterizationState = &rasterizer;
  705. pipelineInfo.pMultisampleState = &multisampling;
  706. pipelineInfo.pDepthStencilState = &depthStencil;
  707. pipelineInfo.pColorBlendState = &colorBlending;
  708. pipelineInfo.layout = pipelineLayout;
  709. pipelineInfo.renderPass = renderPass;
  710. pipelineInfo.subpass = 0;
  711. pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
  712.  
  713. if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) {
  714. throw std::runtime_error("failed to create graphics pipeline!");
  715. }
  716.  
  717. vkDestroyShaderModule(device, fragShaderModule, nullptr);
  718. vkDestroyShaderModule(device, vertShaderModule, nullptr);
  719. }
  720.  
  721. void VEngine::createFramebuffers() {
  722. swapChainFramebuffers.resize(swapChainImageViews.size());
  723.  
  724. createImage(
  725. swapChainExtent.width,
  726. swapChainExtent.height,
  727. depthFormat,
  728. VK_IMAGE_TILING_OPTIMAL,
  729. VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
  730. VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
  731. depthImage,
  732. depthImageMemory);
  733.  
  734. depthImageView = createImageView(depthImage, depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
  735.  
  736. for (size_t i = 0; i < swapChainImageViews.size(); i++) {
  737. std::array<VkImageView, 2> attachments = {
  738. swapChainImageViews[i],
  739. depthImageView
  740. };
  741.  
  742. VkFramebufferCreateInfo framebufferInfo = {};
  743. framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  744. framebufferInfo.renderPass = renderPass;
  745. framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
  746. framebufferInfo.pAttachments = attachments.data();
  747. framebufferInfo.width = swapChainExtent.width;
  748. framebufferInfo.height = swapChainExtent.height;
  749. framebufferInfo.layers = 1;
  750.  
  751. if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) {
  752. throw std::runtime_error("failed to create framebuffer!");
  753. }
  754. }
  755. }
  756.  
  757. void VEngine::createCommandBuffers()
  758. {
  759.  
  760. commandBuffers.resize(swapChainFramebuffers.size());
  761.  
  762. VkCommandBufferAllocateInfo allocInfo = {};
  763. allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  764. allocInfo.commandPool = commandPool;
  765. allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  766. allocInfo.commandBufferCount = (uint32_t)commandBuffers.size();
  767.  
  768. if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) {
  769. throw std::runtime_error("failed to allocate command buffers!");
  770. }
  771.  
  772. for (size_t i = 0; i < commandBuffers.size(); i++) {
  773. VkCommandBufferBeginInfo beginInfo = {};
  774. beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  775. beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
  776.  
  777. vkBeginCommandBuffer(commandBuffers[i], &beginInfo);
  778.  
  779. VkRenderPassBeginInfo renderPassInfo = {};
  780. renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  781. renderPassInfo.renderPass = renderPass;
  782. renderPassInfo.framebuffer = swapChainFramebuffers[i];
  783. renderPassInfo.renderArea.offset = { 0, 0 };
  784. renderPassInfo.renderArea.extent = swapChainExtent;
  785.  
  786. std::array<VkClearValue, 2> clearValues = {};
  787. clearValues[0].color = { 0.2f, 0.2f, 0.2f, 1.0f };
  788. clearValues[1].depthStencil = { 1.0f, 0 };
  789.  
  790. renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
  791. renderPassInfo.pClearValues = clearValues.data();
  792.  
  793. vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
  794.  
  795. vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline);
  796.  
  797. VkBuffer vertexBuffers[] = { vertexBuffer };
  798. VkDeviceSize offsets[] = { 0 };
  799. vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets);
  800.  
  801. vkCmdBindIndexBuffer(commandBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT32);
  802.  
  803. vkCmdBindDescriptorSets(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
  804.  
  805. glm::mat4 model = glm::mat4(1.0f);
  806.  
  807. vkCmdPushConstants(commandBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(ConstantMatrixModel), &model);
  808.  
  809. vkCmdDrawIndexed(commandBuffers[i], static_cast<uint32_t>(indices.size()), 1, 0, 0, 0);
  810.  
  811. vkCmdEndRenderPass(commandBuffers[i]);
  812.  
  813. if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) {
  814. throw std::runtime_error("failed to record command buffer!");
  815. }
  816. }
  817. }
  818.  
  819. void VEngine::createCommandPool() {
  820. QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice);
  821.  
  822. VkCommandPoolCreateInfo poolInfo = {};
  823. poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  824. poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily;
  825.  
  826. if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) {
  827. throw std::runtime_error("failed to create graphics command pool!");
  828. }
  829. }
  830.  
  831. VkBool32 VEngine::findDepthFormat(VkPhysicalDevice physicalDevice, VkFormat *depthFormat) {
  832. // Since all depth formats may be optional, we need to find a suitable depth format to use
  833. // Start with the highest precision packed format
  834. std::vector<VkFormat> depthFormats = {
  835. VK_FORMAT_D32_SFLOAT_S8_UINT,
  836. VK_FORMAT_D32_SFLOAT,
  837. VK_FORMAT_D24_UNORM_S8_UINT,
  838. VK_FORMAT_D16_UNORM_S8_UINT,
  839. VK_FORMAT_D16_UNORM
  840. };
  841.  
  842. for (auto& format : depthFormats)
  843. {
  844. VkFormatProperties formatProps;
  845. vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProps);
  846. // Format must support depth stencil attachment for optimal tiling
  847. if (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
  848. {
  849. *depthFormat = format;
  850. return true;
  851. }
  852. }
  853.  
  854. return false;
  855. }
  856.  
  857. bool VEngine::hasStencilComponent(VkFormat format) {
  858. return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
  859. }
  860.  
  861. VkImageView VEngine::createImageView(VkImage image, VkFormat format, VkImageAspectFlags aspectFlags) {
  862. VkImageViewCreateInfo viewInfo = {};
  863. viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  864. viewInfo.image = image;
  865. viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  866. viewInfo.format = format;
  867. viewInfo.subresourceRange.aspectMask = aspectFlags;
  868. viewInfo.subresourceRange.baseMipLevel = 0;
  869. viewInfo.subresourceRange.levelCount = 1;
  870. viewInfo.subresourceRange.baseArrayLayer = 0;
  871. viewInfo.subresourceRange.layerCount = 1;
  872.  
  873. VkImageView imageView;
  874. if (vkCreateImageView(device, &viewInfo, nullptr, &imageView) != VK_SUCCESS) {
  875. throw std::runtime_error("failed to create texture image view!");
  876. }
  877.  
  878. return imageView;
  879. }
  880.  
  881. void VEngine::createImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {
  882. VkImageCreateInfo imageInfo = {};
  883. imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  884. imageInfo.imageType = VK_IMAGE_TYPE_2D;
  885. imageInfo.extent.width = width;
  886. imageInfo.extent.height = height;
  887. imageInfo.extent.depth = 1;
  888. imageInfo.mipLevels = 1;
  889. imageInfo.arrayLayers = 1;
  890. imageInfo.format = format;
  891. imageInfo.tiling = tiling;
  892. imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
  893. imageInfo.usage = usage;
  894. imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
  895. imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  896.  
  897. if (vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
  898. throw std::runtime_error("failed to create image!");
  899. }
  900.  
  901. VkMemoryRequirements memRequirements;
  902. vkGetImageMemoryRequirements(device, image, &memRequirements);
  903.  
  904. VkMemoryAllocateInfo allocInfo = {};
  905. allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  906. allocInfo.allocationSize = memRequirements.size;
  907. allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
  908.  
  909. if (vkAllocateMemory(device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) {
  910. throw std::runtime_error("failed to allocate image memory!");
  911. }
  912.  
  913. vkBindImageMemory(device, image, imageMemory, 0);
  914. }
  915.  
  916. void VEngine::createTestImage(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage& image, VkDeviceMemory& imageMemory) {
  917. VkImageCreateInfo imageInfo = {};
  918. imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  919. imageInfo.imageType = VK_IMAGE_TYPE_2D;
  920. imageInfo.extent.width = width;
  921. imageInfo.extent.height = height;
  922. imageInfo.extent.depth = 1;
  923. imageInfo.mipLevels = 1;
  924. imageInfo.arrayLayers = 1;
  925. imageInfo.format = format;
  926. imageInfo.tiling = tiling;
  927. imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
  928. imageInfo.usage = usage;
  929. imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
  930. imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  931.  
  932. if (vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
  933. throw std::runtime_error("failed to create image!");
  934. }
  935.  
  936. VkMemoryRequirements memRequirements;
  937. vkGetImageMemoryRequirements(device, image, &memRequirements);
  938.  
  939. VkMemoryAllocateInfo allocInfo = {};
  940. allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  941. allocInfo.allocationSize = memRequirements.size;
  942. allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
  943.  
  944. if (vkAllocateMemory(device, &allocInfo, nullptr, &imageMemory) != VK_SUCCESS) {
  945. throw std::runtime_error("failed to allocate image memory!");
  946. }
  947.  
  948. vkBindImageMemory(device, image, imageMemory, 0);
  949. }
  950.  
  951. void VEngine::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout) {
  952. VkCommandBuffer commandBuffer = beginSingleTimeCommands();
  953.  
  954. VkImageMemoryBarrier barrier = {};
  955. barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  956. barrier.oldLayout = oldLayout;
  957. barrier.newLayout = newLayout;
  958. barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  959. barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  960. barrier.image = image;
  961.  
  962. if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
  963. barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
  964.  
  965. if (hasStencilComponent(format)) {
  966. barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
  967. }
  968. }
  969. else {
  970. barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  971. }
  972.  
  973. barrier.subresourceRange.baseMipLevel = 0;
  974. barrier.subresourceRange.levelCount = 1;
  975. barrier.subresourceRange.baseArrayLayer = 0;
  976. barrier.subresourceRange.layerCount = 1;
  977.  
  978. if (oldLayout == VK_IMAGE_LAYOUT_PREINITIALIZED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
  979. barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
  980. barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  981. }
  982. else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
  983. barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  984. barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
  985. }
  986. else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
  987. barrier.srcAccessMask = 0;
  988. barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  989. }
  990. else {
  991. throw std::invalid_argument("unsupported layout transition!");
  992. }
  993.  
  994. vkCmdPipelineBarrier(
  995. commandBuffer,
  996. VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
  997. 0,
  998. 0, nullptr,
  999. 0, nullptr,
  1000. 1, &barrier
  1001. );
  1002.  
  1003. endSingleTimeCommands(commandBuffer);
  1004. }
  1005.  
  1006. void VEngine::copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height) {
  1007. VkCommandBuffer commandBuffer = beginSingleTimeCommands();
  1008.  
  1009. VkBufferImageCopy region = {};
  1010. region.bufferOffset = 0;
  1011. region.bufferRowLength = 0;
  1012. region.bufferImageHeight = 0;
  1013. region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1014. region.imageSubresource.mipLevel = 0;
  1015. region.imageSubresource.baseArrayLayer = 0;
  1016. region.imageSubresource.layerCount = 1;
  1017. region.imageOffset = { 0, 0, 0 };
  1018. region.imageExtent = {
  1019. width,
  1020. height,
  1021. 1
  1022. };
  1023.  
  1024. vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
  1025.  
  1026. endSingleTimeCommands(commandBuffer);
  1027. }
  1028.  
  1029. void VEngine::loadModel() {
  1030. tinyobj::attrib_t attrib;
  1031. std::vector<tinyobj::shape_t> shapes;
  1032. std::vector<tinyobj::material_t> materials;
  1033. std::string err;
  1034.  
  1035. if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, MODEL_PATH.c_str())) {
  1036. throw std::runtime_error(err);
  1037. }
  1038.  
  1039. std::unordered_map<Vertex, uint32_t> uniqueVertices = {};
  1040.  
  1041. for (const auto& shape : shapes) {
  1042. for (const auto& index : shape.mesh.indices) {
  1043. Vertex vertex = {};
  1044.  
  1045. vertex.pos = {
  1046. attrib.vertices[3 * index.vertex_index + 0],
  1047. attrib.vertices[3 * index.vertex_index + 1],
  1048. attrib.vertices[3 * index.vertex_index + 2]
  1049. };
  1050.  
  1051. vertex.normal = {
  1052. attrib.normals[3 * index.normal_index + 0],
  1053. attrib.normals[3 * index.normal_index + 1],
  1054. attrib.normals[3 * index.normal_index + 2]
  1055. };
  1056.  
  1057. vertex.texCoord = {
  1058. attrib.texcoords[2 * index.texcoord_index + 0],
  1059. 1.0f - attrib.texcoords[2 * index.texcoord_index + 1]
  1060. };
  1061.  
  1062. if (uniqueVertices.count(vertex) == 0) {
  1063. uniqueVertices[vertex] = static_cast<uint32_t>(vertices.size());
  1064. vertices.push_back(vertex);
  1065. }
  1066.  
  1067. indices.push_back(uniqueVertices[vertex]);
  1068. }
  1069. }
  1070. }
  1071.  
  1072. void VEngine::createVertexBuffer() {
  1073. VkDeviceSize bufferSize = sizeof(vertices[0]) * vertices.size();
  1074.  
  1075. VkBuffer stagingBuffer;
  1076. VkDeviceMemory stagingBufferMemory;
  1077. createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
  1078.  
  1079. void* data;
  1080. vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
  1081. memcpy(data, vertices.data(), (size_t)bufferSize);
  1082. vkUnmapMemory(device, stagingBufferMemory);
  1083.  
  1084. createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexBuffer, vertexBufferMemory);
  1085.  
  1086. copyBuffer(stagingBuffer, vertexBuffer, bufferSize);
  1087.  
  1088. vkDestroyBuffer(device, stagingBuffer, nullptr);
  1089. vkFreeMemory(device, stagingBufferMemory, nullptr);
  1090.  
  1091. }
  1092.  
  1093. void VEngine::createIndexBuffer() {
  1094. VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size();
  1095.  
  1096. VkBuffer stagingBuffer;
  1097. VkDeviceMemory stagingBufferMemory;
  1098. createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory);
  1099.  
  1100. void* data;
  1101. vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data);
  1102. memcpy(data, indices.data(), (size_t)bufferSize);
  1103. vkUnmapMemory(device, stagingBufferMemory);
  1104.  
  1105. createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory);
  1106.  
  1107. copyBuffer(stagingBuffer, indexBuffer, bufferSize);
  1108.  
  1109. vkDestroyBuffer(device, stagingBuffer, nullptr);
  1110. vkFreeMemory(device, stagingBufferMemory, nullptr);
  1111.  
  1112. }
  1113.  
  1114. void VEngine::createUniformBuffer() {
  1115. createBuffer(sizeof(UniformMatrixBufferObject), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, uniformMatrixBuffer, uniformMatrixBufferMemory);
  1116. }
  1117.  
  1118. void VEngine::createDescriptorPool() {
  1119. std::array<VkDescriptorPoolSize, 1> poolSizes = {};
  1120. poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  1121. poolSizes[0].descriptorCount = 1;
  1122.  
  1123. VkDescriptorPoolCreateInfo poolInfo = {};
  1124. poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  1125. poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
  1126. poolInfo.pPoolSizes = poolSizes.data();
  1127. poolInfo.maxSets = 1;
  1128.  
  1129. if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) {
  1130. throw std::runtime_error("failed to create descriptor pool!");
  1131. }
  1132. }
  1133.  
  1134. void VEngine::createDescriptorSet() {
  1135. VkDescriptorSetLayout layouts[] = { descriptorSetLayout };
  1136. VkDescriptorSetAllocateInfo allocInfo = {};
  1137. allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  1138. allocInfo.descriptorPool = descriptorPool;
  1139. allocInfo.descriptorSetCount = 1;
  1140. allocInfo.pSetLayouts = layouts;
  1141.  
  1142. if (vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet) != VK_SUCCESS) {
  1143. throw std::runtime_error("failed to allocate descriptor set!");
  1144. }
  1145.  
  1146. VkDescriptorBufferInfo matrixBufferInfo = {};
  1147. matrixBufferInfo.buffer = uniformMatrixBuffer;
  1148. matrixBufferInfo.offset = 0;
  1149. matrixBufferInfo.range = sizeof(UniformMatrixBufferObject);
  1150.  
  1151.  
  1152. std::array<VkWriteDescriptorSet, 1> descriptorWrites = {};
  1153.  
  1154. descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
  1155. descriptorWrites[0].dstSet = descriptorSet;
  1156. descriptorWrites[0].dstBinding = 0;
  1157. descriptorWrites[0].dstArrayElement = 0;
  1158. descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  1159. descriptorWrites[0].descriptorCount = 1;
  1160. descriptorWrites[0].pBufferInfo = &matrixBufferInfo;
  1161.  
  1162.  
  1163. vkUpdateDescriptorSets(device, static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
  1164. }
  1165.  
  1166. void VEngine::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
  1167. VkBufferCreateInfo bufferInfo = {};
  1168. bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  1169. bufferInfo.size = size;
  1170. bufferInfo.usage = usage;
  1171. bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  1172.  
  1173. if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
  1174. throw std::runtime_error("failed to create buffer!");
  1175. }
  1176.  
  1177. VkMemoryRequirements memRequirements;
  1178. vkGetBufferMemoryRequirements(device, buffer, &memRequirements);
  1179.  
  1180. VkMemoryAllocateInfo allocInfo = {};
  1181. allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  1182. allocInfo.allocationSize = memRequirements.size;
  1183. allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
  1184.  
  1185. if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {
  1186. throw std::runtime_error("failed to allocate buffer memory!");
  1187. }
  1188.  
  1189. vkBindBufferMemory(device, buffer, bufferMemory, 0);
  1190. }
  1191.  
  1192. VkCommandBuffer VEngine::beginSingleTimeCommands() {
  1193. VkCommandBufferAllocateInfo allocInfo = {};
  1194. allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  1195. allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  1196. allocInfo.commandPool = commandPool;
  1197. allocInfo.commandBufferCount = 1;
  1198.  
  1199. VkCommandBuffer commandBuffer;
  1200. vkAllocateCommandBuffers(device, &allocInfo, &commandBuffer);
  1201.  
  1202. VkCommandBufferBeginInfo beginInfo = {};
  1203. beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  1204. beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  1205.  
  1206. vkBeginCommandBuffer(commandBuffer, &beginInfo);
  1207.  
  1208. return commandBuffer;
  1209. }
  1210.  
  1211. void VEngine::endSingleTimeCommands(VkCommandBuffer commandBuffer) {
  1212. vkEndCommandBuffer(commandBuffer);
  1213.  
  1214. VkSubmitInfo submitInfo = {};
  1215. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  1216. submitInfo.commandBufferCount = 1;
  1217. submitInfo.pCommandBuffers = &commandBuffer;
  1218.  
  1219. /* vkQueueSubmit(presentQueue, 1, &submitInfo, VK_NULL_HANDLE);
  1220. vkQueueWaitIdle(presentQueue);*/
  1221.  
  1222. // Create fence to ensure that the command buffer has finished executing
  1223. VkFenceCreateInfo fenceInfo = {};
  1224. fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  1225.  
  1226. VkFence fence;
  1227. vkCreateFence(device, &fenceInfo, nullptr, &fence);
  1228.  
  1229. vkQueueSubmit(presentQueue, 1, &submitInfo, fence);
  1230. vkWaitForFences(device, 1, &fence, VK_TRUE, 100000000000);
  1231.  
  1232. vkDestroyFence(device, fence, nullptr);
  1233.  
  1234. vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
  1235. }
  1236.  
  1237. void VEngine::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) {
  1238. VkCommandBuffer commandBuffer = beginSingleTimeCommands();
  1239.  
  1240. VkBufferCopy copyRegion = {};
  1241. copyRegion.size = size;
  1242. vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
  1243.  
  1244. endSingleTimeCommands(commandBuffer);
  1245. }
  1246.  
  1247. uint32_t VEngine::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
  1248. VkPhysicalDeviceMemoryProperties memProperties;
  1249. vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
  1250.  
  1251. for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
  1252. if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
  1253. return i;
  1254. }
  1255. }
  1256.  
  1257. throw std::runtime_error("failed to find suitable memory type!");
  1258. }
  1259.  
  1260. void VEngine::createSemaphores() {
  1261. VkSemaphoreCreateInfo semaphoreInfo = {};
  1262. semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  1263.  
  1264. VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphore));
  1265. VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore));
  1266.  
  1267. }
  1268.  
  1269. void VEngine::updateUniformBuffer() {
  1270.  
  1271. camera_control();
  1272.  
  1273. if (glfwGetKey(window, GLFW_KEY_F4) == GLFW_PRESS) {
  1274.  
  1275. auto color_file_name = "D:/project/vulkan_engine/build/color.ppm";
  1276. auto depth_file_name = "D:/project/vulkan_engine/build/depth.ppm";
  1277.  
  1278. SaveOutputColorTexture(color_file_name);
  1279. SaveOutputDepthTexture(depth_file_name);
  1280. }
  1281.  
  1282. }
  1283.  
  1284. void VEngine::camera_control()
  1285. {
  1286.  
  1287. // glfwGetTime is called only once, the first time this function is called
  1288. static double lastTime = glfwGetTime();
  1289.  
  1290. // Compute time difference between current and last frame
  1291. double currentTime = glfwGetTime();
  1292. float deltaTime = float(currentTime - lastTime);
  1293.  
  1294. // Get mouse position
  1295. double xpos, ypos;
  1296.  
  1297.  
  1298. if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS) {
  1299. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
  1300.  
  1301. if (kFirstPress) {
  1302. glfwGetCursorPos(window, &xpos, &ypos);
  1303.  
  1304. last_xpos_ = xpos;
  1305. last_ypos_ = ypos;
  1306.  
  1307. kFirstPress = false;
  1308. return;
  1309. }
  1310.  
  1311. glfwGetCursorPos(window, &xpos, &ypos);
  1312.  
  1313. // Compute new orientation
  1314. horizontalAngle += mouseSpeed * float(last_xpos_ - xpos);
  1315. verticalAngle += mouseSpeed * float(last_ypos_ - ypos);
  1316.  
  1317. last_xpos_ = xpos;
  1318. last_ypos_ = ypos;
  1319. }
  1320. else {
  1321. glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
  1322. kFirstPress = true;
  1323. }
  1324.  
  1325. // Direction : Spherical coordinates to Cartesian coordinates conversion
  1326. glm::vec3 direction(
  1327. cos(verticalAngle) * sin(horizontalAngle),
  1328. sin(verticalAngle),
  1329. cos(verticalAngle) * cos(horizontalAngle)
  1330. );
  1331.  
  1332. // Right vector
  1333. glm::vec3 right = glm::vec3(
  1334. sin(horizontalAngle - 3.14f / 2.0f),
  1335. 0,
  1336. cos(horizontalAngle - 3.14f / 2.0f)
  1337. );
  1338.  
  1339. // Up vector
  1340. glm::vec3 up = glm::cross(right, direction);
  1341.  
  1342. // Move forward
  1343. if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
  1344. position += direction * deltaTime * speed;
  1345. }
  1346. // Move backward
  1347. if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
  1348. position -= direction * deltaTime * speed;
  1349. }
  1350. // Strafe right
  1351. if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
  1352. position += right * deltaTime * speed;
  1353. }
  1354. // Strafe left
  1355. if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
  1356. position -= right * deltaTime * speed;
  1357. }
  1358. // Strafe up
  1359. if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) {
  1360. position.y += 2 * deltaTime * speed;
  1361. }
  1362. // Strafe down
  1363. if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) {
  1364. position.y -= 2 * deltaTime * speed;
  1365. }
  1366.  
  1367. // Strafe down
  1368. if (glfwGetKey(window, GLFW_KEY_M) == GLFW_PRESS) {
  1369. RecreateBufer();
  1370. }
  1371.  
  1372.  
  1373. float FoV = initialFoV;// - 5 * glfwGetMouseWheel(); // Now GLFW 3 requires setting up a callback for this. It's a bit too complicated for this beginner's tutorial, so it's disabled instead.
  1374.  
  1375.  
  1376. UniformMatrixBufferObject umo = {};
  1377.  
  1378. // Projection matrix : 45?Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
  1379. umo.proj = clip * glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 1000.0f);
  1380. //ubo.proj[1][1] *= -1;
  1381.  
  1382.  
  1383. auto camera_point = position + direction;
  1384.  
  1385. // Camera matrix
  1386. umo.view = glm::lookAt(
  1387. position, // Camera is here
  1388. camera_point, // and looks here : at the same position, plus "direction"
  1389. up // Head is up (set to 0,-1,0 to look upside-down)
  1390. );
  1391.  
  1392. // direction light
  1393.  
  1394. umo.lightPos = lightPos;
  1395.  
  1396. // For the next frame, the "last time" will be "now"
  1397. lastTime = currentTime;
  1398.  
  1399. void* data;
  1400. vkMapMemory(device, uniformMatrixBufferMemory, 0, sizeof(umo), 0, &data);
  1401. memcpy(data, &umo, sizeof(umo));
  1402. vkUnmapMemory(device, uniformMatrixBufferMemory);
  1403.  
  1404. }
  1405.  
  1406.  
  1407. void VEngine::drawFrame() {
  1408. VkResult result = vkAcquireNextImageKHR(device, swapChain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
  1409.  
  1410. /*if (result == VK_ERROR_OUT_OF_DATE_KHR) {
  1411. recreateSwapChain();
  1412. return;
  1413. }
  1414. else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
  1415. throw std::runtime_error("failed to acquire swap chain image!");
  1416. }*/
  1417.  
  1418. VkSubmitInfo shadowSubmitInfo = {};
  1419. shadowSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  1420.  
  1421. VkSubmitInfo submitInfo = {};
  1422. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  1423.  
  1424. VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_ALL_COMMANDS_BIT };
  1425. submitInfo.waitSemaphoreCount = 1;
  1426. submitInfo.pWaitSemaphores = &imageAvailableSemaphore;
  1427. submitInfo.pWaitDstStageMask = waitStages;
  1428.  
  1429. submitInfo.commandBufferCount = 1;
  1430. submitInfo.pCommandBuffers = &commandBuffers[imageIndex];
  1431.  
  1432. submitInfo.signalSemaphoreCount = 1;
  1433. submitInfo.pSignalSemaphores = &renderFinishedSemaphore;
  1434.  
  1435. VK_CHECK_RESULT(vkQueueSubmit(presentQueue, 1, &submitInfo, VK_NULL_HANDLE));
  1436.  
  1437. VkPresentInfoKHR presentInfo = {};
  1438. presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  1439.  
  1440. presentInfo.waitSemaphoreCount = 1;
  1441. presentInfo.pWaitSemaphores = &renderFinishedSemaphore;
  1442.  
  1443. VkSwapchainKHR swapChains[] = { swapChain };
  1444. presentInfo.swapchainCount = 1;
  1445. presentInfo.pSwapchains = swapChains;
  1446.  
  1447. presentInfo.pImageIndices = &imageIndex;
  1448.  
  1449. VK_CHECK_RESULT(vkQueuePresentKHR(presentQueue, &presentInfo));
  1450.  
  1451. /*if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
  1452. recreateSwapChain();
  1453. }
  1454. else if (result != VK_SUCCESS) {
  1455. throw std::runtime_error("failed to present swap chain image!");
  1456. }*/
  1457.  
  1458. VK_CHECK_RESULT(vkQueueWaitIdle(presentQueue));
  1459. }
  1460.  
  1461. void VEngine::RecreateBufer()
  1462. {
  1463. createVertexBuffer();
  1464. createIndexBuffer();
  1465. createUniformBuffer();
  1466. createDescriptorPool();
  1467. createDescriptorSet();
  1468. createCommandBuffers();
  1469.  
  1470. }
  1471.  
  1472. void VEngine::SaveOutputColorTexture(const std::string& path)
  1473. {
  1474.  
  1475. bool supportsBlit = true;
  1476.  
  1477. // Check blit support for source and destination
  1478. VkFormatProperties formatProps;
  1479.  
  1480. // Check if the device supports blitting from optimal images (the swapchain images are in optimal format)
  1481. vkGetPhysicalDeviceFormatProperties(physicalDevice, swapChainImageFormat, &formatProps);
  1482. if (!(formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT)) {
  1483. std::cerr << "Device does not support blitting from optimal tiled images, using copy instead of blit!" << std::endl;
  1484. supportsBlit = false;
  1485. }
  1486.  
  1487. // Check if the device supports blitting to linear images
  1488. vkGetPhysicalDeviceFormatProperties(physicalDevice, swapChainImageFormat, &formatProps);
  1489. if (!(formatProps.linearTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT)) {
  1490. std::cerr << "Device does not support blitting to linear tiled images, using copy instead of blit!" << std::endl;
  1491. supportsBlit = false;
  1492. }
  1493.  
  1494. // Source for the copy is the last rendered swapchain image
  1495. VkImage srcImage = swapChainImages[imageIndex];
  1496.  
  1497. // Create the linear tiled destination image to copy to and to read the memory from
  1498. VkImageCreateInfo imageCreateCI = {};
  1499. imageCreateCI.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  1500.  
  1501.  
  1502. imageCreateCI.imageType = VK_IMAGE_TYPE_2D;
  1503. // Note that vkCmdBlitImage (if supported) will also do format conversions if the swapchain color format would differ
  1504. imageCreateCI.format = swapChainImageFormat;
  1505. imageCreateCI.extent.width = WIDTH;
  1506. imageCreateCI.extent.height = HEIGHT;
  1507. imageCreateCI.extent.depth = 1;
  1508. imageCreateCI.arrayLayers = 1;
  1509. imageCreateCI.mipLevels = 1;
  1510. imageCreateCI.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  1511. imageCreateCI.samples = VK_SAMPLE_COUNT_1_BIT;
  1512. imageCreateCI.tiling = VK_IMAGE_TILING_LINEAR;
  1513. imageCreateCI.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
  1514. // Create the image
  1515. VkImage dstImage;
  1516. VK_CHECK_RESULT(vkCreateImage(device, &imageCreateCI, nullptr, &dstImage));
  1517. // Create memory to back up the image
  1518. VkMemoryRequirements memRequirements;
  1519.  
  1520. VkMemoryAllocateInfo memAllocInfo{};
  1521. memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  1522.  
  1523.  
  1524. VkDeviceMemory dstImageMemory;
  1525. vkGetImageMemoryRequirements(device, dstImage, &memRequirements);
  1526. memAllocInfo.allocationSize = memRequirements.size;
  1527. // Memory must be host visible to copy from
  1528.  
  1529. memAllocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
  1530.  
  1531. VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &dstImageMemory));
  1532. VK_CHECK_RESULT(vkBindImageMemory(device, dstImage, dstImageMemory, 0));
  1533.  
  1534. // Do the actual blit from the swapchain image to our host visible destination image
  1535.  
  1536. VkCommandBufferAllocateInfo cmdBufAllocateInfo{};
  1537. cmdBufAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  1538. cmdBufAllocateInfo.commandPool = commandPool;
  1539. cmdBufAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  1540. cmdBufAllocateInfo.commandBufferCount = 1;
  1541.  
  1542.  
  1543. VkCommandBuffer copyCmd;
  1544. VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, &copyCmd));
  1545.  
  1546. VkCommandBufferBeginInfo cmdBufInfo{};
  1547. cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  1548.  
  1549. VK_CHECK_RESULT(vkBeginCommandBuffer(copyCmd, &cmdBufInfo));
  1550.  
  1551.  
  1552. VkImageMemoryBarrier imageMemoryBarrier{};
  1553. imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  1554. imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  1555. imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  1556.  
  1557.  
  1558. // Transition destination image to transfer destination layout
  1559. insertImageMemoryBarrier(
  1560. copyCmd,
  1561. dstImage,
  1562. 0,
  1563. VK_ACCESS_TRANSFER_WRITE_BIT,
  1564. VK_IMAGE_LAYOUT_UNDEFINED,
  1565. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  1566. VK_PIPELINE_STAGE_TRANSFER_BIT,
  1567. VK_PIPELINE_STAGE_TRANSFER_BIT,
  1568. VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
  1569.  
  1570. // Transition swapchain image from present to transfer source layout
  1571. insertImageMemoryBarrier(
  1572. copyCmd,
  1573. srcImage,
  1574. VK_ACCESS_MEMORY_READ_BIT,
  1575. VK_ACCESS_TRANSFER_READ_BIT,
  1576. VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
  1577. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  1578. VK_PIPELINE_STAGE_TRANSFER_BIT,
  1579. VK_PIPELINE_STAGE_TRANSFER_BIT,
  1580. VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
  1581.  
  1582. // If source and destination support blit we'll blit as this also does automatic format conversion (e.g. from BGR to RGB)
  1583. if (supportsBlit)
  1584. {
  1585. // Define the region to blit (we will blit the whole swapchain image)
  1586. VkOffset3D blitSize;
  1587. blitSize.x = WIDTH;
  1588. blitSize.y = HEIGHT;
  1589. blitSize.z = 1;
  1590. VkImageBlit imageBlitRegion{};
  1591. imageBlitRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1592. imageBlitRegion.srcSubresource.layerCount = 1;
  1593. imageBlitRegion.srcOffsets[1] = blitSize;
  1594. imageBlitRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1595. imageBlitRegion.dstSubresource.layerCount = 1;
  1596. imageBlitRegion.dstOffsets[1] = blitSize;
  1597.  
  1598. // Issue the blit command
  1599. vkCmdBlitImage(
  1600. copyCmd,
  1601. srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  1602. dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  1603. 1,
  1604. &imageBlitRegion,
  1605. VK_FILTER_NEAREST);
  1606. }
  1607. else
  1608. {
  1609. // Otherwise use image copy (requires us to manually flip components)
  1610. VkImageCopy imageCopyRegion{};
  1611. imageCopyRegion.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1612. imageCopyRegion.srcSubresource.layerCount = 1;
  1613. imageCopyRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  1614. imageCopyRegion.dstSubresource.layerCount = 1;
  1615. imageCopyRegion.extent.width = WIDTH;
  1616. imageCopyRegion.extent.height = HEIGHT;
  1617. imageCopyRegion.extent.depth = 1;
  1618.  
  1619. // Issue the copy command
  1620. vkCmdCopyImage(
  1621. copyCmd,
  1622. srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  1623. dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  1624. 1,
  1625. &imageCopyRegion);
  1626. }
  1627.  
  1628. // Transition destination image to general layout, which is the required layout for mapping the image memory later on
  1629. insertImageMemoryBarrier(
  1630. copyCmd,
  1631. dstImage,
  1632. VK_ACCESS_TRANSFER_WRITE_BIT,
  1633. VK_ACCESS_MEMORY_READ_BIT,
  1634. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
  1635. VK_IMAGE_LAYOUT_GENERAL,
  1636. VK_PIPELINE_STAGE_TRANSFER_BIT,
  1637. VK_PIPELINE_STAGE_TRANSFER_BIT,
  1638. VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
  1639.  
  1640. // Transition back the swap chain image after the blit is done
  1641. insertImageMemoryBarrier(
  1642. copyCmd,
  1643. srcImage,
  1644. VK_ACCESS_TRANSFER_READ_BIT,
  1645. VK_ACCESS_MEMORY_READ_BIT,
  1646. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  1647. VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
  1648. VK_PIPELINE_STAGE_TRANSFER_BIT,
  1649. VK_PIPELINE_STAGE_TRANSFER_BIT,
  1650. VkImageSubresourceRange{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
  1651.  
  1652.  
  1653. endSingleTimeCommands(copyCmd);
  1654.  
  1655.  
  1656. // Get layout of the image (including row pitch)
  1657. VkImageSubresource subResource{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 };
  1658. VkSubresourceLayout subResourceLayout;
  1659. vkGetImageSubresourceLayout(device, dstImage, &subResource, &subResourceLayout);
  1660.  
  1661. // Map image memory so we can start copying from it
  1662. const char* data;
  1663. vkMapMemory(device, dstImageMemory, 0, VK_WHOLE_SIZE, 0, (void**)&data);
  1664. data += subResourceLayout.offset;
  1665.  
  1666. std::ofstream file(path, std::ios::out | std::ios::binary);
  1667.  
  1668. // ppm header
  1669. file << "P6\n" << WIDTH << "\n" << HEIGHT << "\n" << 255 << "\n";
  1670.  
  1671. // If source is BGR (destination is always RGB) and we can't use blit (which does automatic conversion), we'll have to manually swizzle color components
  1672. bool colorSwizzle = false;
  1673. // Check if source is BGR
  1674. // Note: Not complete, only contains most common and basic BGR surface formats for demonstation purposes
  1675. if (!supportsBlit)
  1676. {
  1677. std::vector<VkFormat> formatsBGR = { VK_FORMAT_B8G8R8A8_SRGB, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_B8G8R8A8_SNORM };
  1678. colorSwizzle = (std::find(formatsBGR.begin(), formatsBGR.end(), swapChainImageFormat) != formatsBGR.end());
  1679. }
  1680.  
  1681. auto image_size = HEIGHT * WIDTH;
  1682.  
  1683.  
  1684. for (uint32_t y = 0; y < HEIGHT; y++)
  1685. {
  1686. unsigned int *row = (unsigned int*)data;
  1687. for (uint32_t x = 0; x < WIDTH; x++)
  1688. {
  1689. if (colorSwizzle)
  1690. {
  1691. file.write((char*)row + 2, 1);
  1692. file.write((char*)row + 1, 1);
  1693. file.write((char*)row, 1);
  1694. }
  1695. else
  1696. {
  1697. file.write((char*)row, 3);
  1698. }
  1699. row++;
  1700. }
  1701. data += subResourceLayout.rowPitch;
  1702. }
  1703.  
  1704. file.close();
  1705.  
  1706. std::cout << "Screenshot saved to disk" << std::endl;
  1707.  
  1708. // Clean up resources
  1709. vkUnmapMemory(device, dstImageMemory);
  1710. vkFreeMemory(device, dstImageMemory, nullptr);
  1711. vkDestroyImage(device, dstImage, nullptr);
  1712.  
  1713. }
  1714.  
  1715. void VEngine::SaveOutputDepthTexture(const std::string& path)
  1716. {
  1717.  
  1718. VkDeviceSize size = WIDTH * HEIGHT * 4;
  1719. VkBuffer dstBuffer;
  1720. VkDeviceMemory dstMemory;
  1721.  
  1722. createBuffer(
  1723. size,
  1724. VK_BUFFER_USAGE_TRANSFER_DST_BIT,
  1725. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
  1726. dstBuffer,
  1727. dstMemory);
  1728.  
  1729. VkCommandBuffer copyCmd = beginSingleTimeCommands();
  1730.  
  1731. // depth format -> VK_FORMAT_D32_SFLOAT_S8_UINT
  1732. VkBufferImageCopy region = {};
  1733. region.bufferOffset = 0;
  1734. region.bufferImageHeight = 0;
  1735. region.bufferRowLength = 0;
  1736. region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
  1737. region.imageSubresource.mipLevel = 0;
  1738. region.imageSubresource.baseArrayLayer = 0;
  1739. region.imageSubresource.layerCount = 1;
  1740. region.imageOffset = VkOffset3D{ 0, 0, 0 };
  1741. region.imageExtent = VkExtent3D{ swapChainExtent.width, swapChainExtent.height, 1};
  1742.  
  1743.  
  1744. vkCmdCopyImageToBuffer(
  1745. copyCmd,
  1746. depthImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
  1747. dstBuffer,
  1748. 1,
  1749. &region
  1750. );
  1751.  
  1752. endSingleTimeCommands(copyCmd);
  1753.  
  1754.  
  1755. // Map image memory so we can start copying from it
  1756. void *data;
  1757. vkMapMemory(device, dstMemory, 0, size, 0, &data);
  1758.  
  1759.  
  1760. std::ofstream file(path, std::ios::out | std::ios::binary);
  1761.  
  1762. // ppm header
  1763. file << "P6\n" << WIDTH << "\n" << HEIGHT << "\n" << 255 << "\n";
  1764.  
  1765. float *row = (float*)data;
  1766.  
  1767. auto size_v = WIDTH * HEIGHT;
  1768.  
  1769. for (uint32_t y = 0; y < size_v; y++) {
  1770.  
  1771. file.write((char*)row + 1, 1);
  1772. file.write((char*)row + 1, 1);
  1773. file.write((char*)row + 1, 1);
  1774.  
  1775. row++;
  1776.  
  1777. }
  1778.  
  1779. file.close();
  1780.  
  1781. // Clean up resources
  1782. vkUnmapMemory(device, dstMemory);
  1783. vkFreeMemory(device, dstMemory, nullptr);
  1784. vkDestroyBuffer(device, dstBuffer, nullptr);
  1785.  
  1786. }
  1787.  
  1788. VkShaderModule VEngine::createShaderModule(const std::vector<char>& code) {
  1789. VkShaderModuleCreateInfo createInfo = {};
  1790. createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  1791. createInfo.codeSize = code.size();
  1792. createInfo.pCode = reinterpret_cast<const uint32_t*>(code.data());
  1793.  
  1794. VkShaderModule shaderModule;
  1795. if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
  1796. throw std::runtime_error("failed to create shader module!");
  1797. }
  1798.  
  1799. return shaderModule;
  1800. }
  1801.  
  1802. VkSurfaceFormatKHR VEngine::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) {
  1803. if (availableFormats.size() == 1 && availableFormats[0].format == VK_FORMAT_UNDEFINED) {
  1804. return{ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
  1805. }
  1806.  
  1807. for (const auto& availableFormat : availableFormats) {
  1808. if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
  1809. return availableFormat;
  1810. }
  1811. }
  1812.  
  1813. return availableFormats[0];
  1814. }
  1815.  
  1816. VkPresentModeKHR VEngine::chooseSwapPresentMode(const std::vector<VkPresentModeKHR> availablePresentModes) {
  1817. VkPresentModeKHR bestMode = VK_PRESENT_MODE_FIFO_KHR;
  1818.  
  1819. for (const auto& availablePresentMode : availablePresentModes) {
  1820. if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
  1821. return availablePresentMode;
  1822. }
  1823. else if (availablePresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) {
  1824. bestMode = availablePresentMode;
  1825. }
  1826. }
  1827.  
  1828. return bestMode;
  1829. }
  1830.  
  1831. VkExtent2D VEngine::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) {
  1832. if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
  1833. return capabilities.currentExtent;
  1834. }
  1835. else {
  1836. int width, height;
  1837. glfwGetWindowSize(window, &width, &height);
  1838.  
  1839. VkExtent2D actualExtent = {
  1840. static_cast<uint32_t>(width),
  1841. static_cast<uint32_t>(height)
  1842. };
  1843.  
  1844. actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width));
  1845. actualExtent.height = std::max(capabilities.minImageExtent.height, std::min(capabilities.maxImageExtent.height, actualExtent.height));
  1846.  
  1847. return actualExtent;
  1848. }
  1849. }
  1850.  
  1851. VEngine::SwapChainSupportDetails VEngine::querySwapChainSupport(VkPhysicalDevice device) {
  1852. SwapChainSupportDetails details;
  1853.  
  1854. vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities);
  1855.  
  1856. uint32_t formatCount;
  1857. vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
  1858.  
  1859. if (formatCount != 0) {
  1860. details.formats.resize(formatCount);
  1861. vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data());
  1862. }
  1863.  
  1864. uint32_t presentModeCount;
  1865. vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr);
  1866.  
  1867. if (presentModeCount != 0) {
  1868. details.presentModes.resize(presentModeCount);
  1869. vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data());
  1870. }
  1871.  
  1872. return details;
  1873. }
  1874.  
  1875. bool VEngine::isDeviceSuitable(VkPhysicalDevice device) {
  1876. QueueFamilyIndices indices = findQueueFamilies(device);
  1877.  
  1878. bool extensionsSupported = checkDeviceExtensionSupport(device);
  1879.  
  1880. bool swapChainAdequate = false;
  1881. if (extensionsSupported) {
  1882. SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device);
  1883. swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
  1884. }
  1885.  
  1886. VkPhysicalDeviceFeatures supportedFeatures;
  1887. vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
  1888.  
  1889. return indices.isComplete() && extensionsSupported && supportedFeatures.samplerAnisotropy;
  1890. }
  1891.  
  1892. bool VEngine::checkDeviceExtensionSupport(VkPhysicalDevice device) {
  1893. uint32_t extensionCount;
  1894. vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
  1895.  
  1896. std::vector<VkExtensionProperties> availableExtensions(extensionCount);
  1897. vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());
  1898.  
  1899. std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
  1900.  
  1901. for (const auto& extension : availableExtensions) {
  1902. requiredExtensions.erase(extension.extensionName);
  1903. }
  1904.  
  1905. return requiredExtensions.empty();
  1906. }
  1907.  
  1908. VEngine::QueueFamilyIndices VEngine::findQueueFamilies(VkPhysicalDevice device) {
  1909. QueueFamilyIndices indices;
  1910.  
  1911. uint32_t queueFamilyCount = 0;
  1912. vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
  1913.  
  1914. std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
  1915. vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
  1916.  
  1917. int i = 0;
  1918. for (const auto& queueFamily : queueFamilies) {
  1919. if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
  1920. indices.graphicsFamily = i;
  1921. }
  1922.  
  1923. VkBool32 presentSupport = false;
  1924. vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
  1925.  
  1926. if (queueFamily.queueCount > 0 && presentSupport) {
  1927. indices.presentFamily = i;
  1928. }
  1929.  
  1930. if (indices.isComplete()) {
  1931. break;
  1932. }
  1933.  
  1934. i++;
  1935. }
  1936.  
  1937. return indices;
  1938. }
  1939.  
  1940. std::vector<const char*> VEngine::getRequiredExtensions() {
  1941. std::vector<const char*> extensions;
  1942.  
  1943. unsigned int glfwExtensionCount = 0;
  1944. const char** glfwExtensions;
  1945. glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
  1946.  
  1947. for (unsigned int i = 0; i < glfwExtensionCount; i++) {
  1948. extensions.push_back(glfwExtensions[i]);
  1949. }
  1950.  
  1951. if (enableValidationLayers) {
  1952. extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
  1953. }
  1954.  
  1955. return extensions;
  1956. }
  1957.  
  1958. bool VEngine::checkValidationLayerSupport() {
  1959. uint32_t layerCount;
  1960. vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
  1961.  
  1962. std::vector<VkLayerProperties> availableLayers(layerCount);
  1963. vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
  1964.  
  1965. for (const char* layerName : validationLayers) {
  1966. bool layerFound = false;
  1967.  
  1968. for (const auto& layerProperties : availableLayers) {
  1969. if (strcmp(layerName, layerProperties.layerName) == 0) {
  1970. layerFound = true;
  1971. break;
  1972. }
  1973. }
  1974.  
  1975. if (!layerFound) {
  1976. return false;
  1977. }
  1978. }
  1979.  
  1980. return true;
  1981. }
  1982.  
  1983. std::vector<char> VEngine::readFile(const std::string& filename) {
  1984. std::ifstream file(filename, std::ios::ate | std::ios::binary);
  1985.  
  1986. if (!file.is_open()) {
  1987. throw std::runtime_error("failed to open file!");
  1988. }
  1989.  
  1990. size_t fileSize = (size_t)file.tellg();
  1991. std::vector<char> buffer(fileSize);
  1992.  
  1993. file.seekg(0);
  1994. file.read(buffer.data(), fileSize);
  1995.  
  1996. file.close();
  1997.  
  1998. return buffer;
  1999. }
  2000.  
  2001. glm::mat4 VEngine::GetOrthoMatrix(float left, float right, float bottom, float top, float near, float far)
  2002. {
  2003. glm::mat4 ortho = glm::mat4{
  2004. 2.0f / (right - left), 0.0f, 0.0f, 0.0f,
  2005. 0.0f, 2.0f / (bottom - top), 0.0f, 0.0f,
  2006. 0.0f, 0.0f, 1.0f / (near - far), 0.0f,
  2007.  
  2008. -(right + left) / (right - left),
  2009. -(bottom + top) / (bottom - top),
  2010. near / (near - far),
  2011. 1.0f
  2012. };
  2013.  
  2014. return ortho;
  2015. }
  2016.  
  2017. void VEngine::insertImageMemoryBarrier(
  2018. VkCommandBuffer cmdbuffer,
  2019. VkImage image,
  2020. VkAccessFlags srcAccessMask,
  2021. VkAccessFlags dstAccessMask,
  2022. VkImageLayout oldImageLayout,
  2023. VkImageLayout newImageLayout,
  2024. VkPipelineStageFlags srcStageMask,
  2025. VkPipelineStageFlags dstStageMask,
  2026. VkImageSubresourceRange subresourceRange)
  2027. {
  2028. VkImageMemoryBarrier imageMemoryBarrier{};
  2029. imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  2030. imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  2031. imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  2032. imageMemoryBarrier.srcAccessMask = srcAccessMask;
  2033. imageMemoryBarrier.dstAccessMask = dstAccessMask;
  2034. imageMemoryBarrier.oldLayout = oldImageLayout;
  2035. imageMemoryBarrier.newLayout = newImageLayout;
  2036. imageMemoryBarrier.image = image;
  2037. imageMemoryBarrier.subresourceRange = subresourceRange;
  2038.  
  2039. vkCmdPipelineBarrier(
  2040. cmdbuffer,
  2041. srcStageMask,
  2042. dstStageMask,
  2043. 0,
  2044. 0, nullptr,
  2045. 0, nullptr,
  2046. 1, &imageMemoryBarrier);
  2047. }
  2048.  
  2049.  
  2050.  
  2051.  
  2052.  
  2053. }
Add Comment
Please, Sign In to add comment