Example application for subpasses in Vulkan.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

subpass.cc 38KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. #include <png.h>
  2. #include <vulkan/vulkan.h>
  3. #include <array>
  4. #include <fstream>
  5. #include <iostream>
  6. #include <sstream>
  7. #include <string>
  8. #include <vector>
  9. const uint32_t kWidth = 256;
  10. const uint32_t kHeight = 256;
  11. const VkFormat kVulkanFormat = VK_FORMAT_A8B8G8R8_UNORM_PACK32;
  12. const VkFormat kVulkanDepthFormat = VK_FORMAT_D32_SFLOAT;
  13. const std::string kDrawVertexShaderPath = "draw.vert.spv";
  14. const std::string kDrawFragmentShaderPath = "draw.frag.spv";
  15. const std::string kDarkenVertexShaderPath = "darken.vert.spv";
  16. const std::string kDarkenFragmentShaderPath = "darken.frag.spv";
  17. #define ERROR(message) \
  18. std::cerr << message << std::endl; \
  19. std::exit(EXIT_FAILURE)
  20. VkInstance CreateVkInstance() {
  21. VkApplicationInfo app_info = {};
  22. app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  23. app_info.apiVersion = VK_API_VERSION_1_1;
  24. VkInstanceCreateInfo create_info = {};
  25. create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  26. create_info.pApplicationInfo = &app_info;
  27. create_info.enabledExtensionCount = 0;
  28. create_info.ppEnabledExtensionNames = nullptr;
  29. create_info.enabledLayerCount = 0;
  30. create_info.ppEnabledLayerNames = nullptr;
  31. VkInstance instance;
  32. VkResult result = vkCreateInstance(&create_info, nullptr, &instance);
  33. if (result != VK_SUCCESS) {
  34. ERROR("Error creating VkInstance: " << result);
  35. }
  36. return instance;
  37. }
  38. VkPhysicalDevice ChooseVkPhysicalDevice(VkInstance instance) {
  39. uint32_t device_count = 0;
  40. VkResult result = vkEnumeratePhysicalDevices(instance, &device_count, nullptr);
  41. if (result != VK_SUCCESS) {
  42. ERROR("Error enumerating VkPhysicalDevices: " << result);
  43. }
  44. if (device_count == 0) {
  45. ERROR("No available VkPhysicalDevices");
  46. }
  47. std::vector<VkPhysicalDevice> devices(device_count);
  48. result = vkEnumeratePhysicalDevices(instance, &device_count, devices.data());
  49. if (result != VK_SUCCESS) {
  50. ERROR("Error fetching VkPhysicalDevices: " << result);
  51. }
  52. std::cout << "Found " << device_count << " device(s):" << std::endl;
  53. VkPhysicalDevice chosen_device = VK_NULL_HANDLE;
  54. for (VkPhysicalDevice device : devices) {
  55. VkPhysicalDeviceProperties device_props;
  56. vkGetPhysicalDeviceProperties(device, &device_props);
  57. std::cout << "\t- " << device_props.deviceName << " [V: " <<
  58. VK_VERSION_MAJOR(device_props.apiVersion) << "." <<
  59. VK_VERSION_MINOR(device_props.apiVersion) << "." <<
  60. VK_VERSION_PATCH(device_props.apiVersion) << "]" << std::endl;
  61. // Currently, any device with Vulkan API version 1.1 is fine.
  62. if (chosen_device == VK_NULL_HANDLE && device_props.apiVersion >= VK_API_VERSION_1_1) {
  63. chosen_device = device;
  64. }
  65. }
  66. if (chosen_device == VK_NULL_HANDLE) {
  67. ERROR("Unable to find suitable VkPhysicalDevice");
  68. }
  69. return chosen_device;
  70. }
  71. uint32_t ChooseDeviceQueueFamilyIndex(VkPhysicalDevice physical_device) {
  72. uint32_t props_count;
  73. vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &props_count, nullptr);
  74. std::vector<VkQueueFamilyProperties> props(props_count);
  75. vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &props_count, props.data());
  76. // Simply choose the first graphics queue.
  77. for (size_t i = 0; i < props_count; i++) {
  78. const VkQueueFamilyProperties& prop = props[i];
  79. if ((prop.queueFlags & VK_QUEUE_GRAPHICS_BIT) && prop.queueCount > 0) {
  80. return i;
  81. }
  82. }
  83. ERROR("Unable to find suitable queue family");
  84. }
  85. VkDevice CreateVkDevice(VkPhysicalDevice physical_device, uint32_t device_queue_family_index) {
  86. VkDeviceQueueCreateInfo queue_create_info = {};
  87. queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  88. queue_create_info.queueFamilyIndex = device_queue_family_index;
  89. queue_create_info.queueCount = 1;
  90. float queue_priority = 1.0f;
  91. queue_create_info.pQueuePriorities = &queue_priority;
  92. VkDeviceCreateInfo device_create_info = {};
  93. device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  94. device_create_info.queueCreateInfoCount = 1;
  95. device_create_info.pQueueCreateInfos = &queue_create_info;
  96. // Let's not use any device extensions for now.
  97. device_create_info.enabledExtensionCount = 0;
  98. device_create_info.ppEnabledExtensionNames = nullptr;
  99. VkDevice device;
  100. VkResult result = vkCreateDevice(physical_device, &device_create_info, nullptr, &device);
  101. if (result != VK_SUCCESS) {
  102. ERROR("Unable to create logical device: " << result);
  103. }
  104. return device;
  105. }
  106. void CreateVkBuffer(VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage,
  107. VkBuffer* buffer, VkDeviceMemory* bufferMemory) {
  108. VkBufferCreateInfo bufferInfo = {};
  109. bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
  110. bufferInfo.size = size;
  111. bufferInfo.usage = usage;
  112. bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  113. if (vkCreateBuffer(device, &bufferInfo, nullptr, buffer) != VK_SUCCESS) {
  114. ERROR("Unable to create buffer: ");
  115. }
  116. VkMemoryRequirements memRequirements;
  117. vkGetBufferMemoryRequirements(device, *buffer, &memRequirements);
  118. VkMemoryAllocateInfo allocInfo = {};
  119. allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  120. allocInfo.allocationSize = memRequirements.size;
  121. allocInfo.memoryTypeIndex = 0;
  122. if (vkAllocateMemory(device, &allocInfo, nullptr, bufferMemory) != VK_SUCCESS) {
  123. ERROR("Unable to allocate buffer memory: ");
  124. }
  125. vkBindBufferMemory(device, *buffer, *bufferMemory, 0);
  126. }
  127. VkDescriptorSetLayout CreateVkDescriptorSetLayout(VkDevice device) {
  128. VkDescriptorSetLayoutBinding layout_binding = {};
  129. layout_binding.binding = 0;
  130. layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
  131. layout_binding.descriptorCount = 1;
  132. layout_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
  133. layout_binding.pImmutableSamplers = nullptr;
  134. VkDescriptorSetLayoutCreateInfo layout_info = {};
  135. layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
  136. layout_info.bindingCount = 1;
  137. layout_info.pBindings = &layout_binding;
  138. VkDescriptorSetLayout layout;
  139. VkResult result = vkCreateDescriptorSetLayout(device, &layout_info, nullptr, &layout);
  140. if (result != VK_SUCCESS) {
  141. ERROR("Unable to create descriptor set layout: " << result);
  142. }
  143. return layout;
  144. }
  145. VkDescriptorPool CreateAttachmentVkDescriptorPool(VkDevice device) {
  146. VkDescriptorPoolSize pool_size = {};
  147. pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  148. pool_size.descriptorCount = 1;
  149. VkDescriptorPoolCreateInfo pool_create_info = {};
  150. pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
  151. pool_create_info.poolSizeCount = 1;
  152. pool_create_info.pPoolSizes = &pool_size;
  153. pool_create_info.maxSets = 1;
  154. VkDescriptorPool pool;
  155. VkResult result = vkCreateDescriptorPool(device, &pool_create_info, nullptr, &pool);
  156. if (result != VK_SUCCESS) {
  157. ERROR("Unable to create descriptor pool: " << result);
  158. }
  159. return pool;
  160. }
  161. VkDescriptorSet CreateVkDescriptorSet(VkDevice device, VkDescriptorSetLayout layout,
  162. VkDescriptorPool pool) {
  163. VkDescriptorSetAllocateInfo allocate_info = {};
  164. allocate_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
  165. allocate_info.descriptorPool = pool;
  166. allocate_info.descriptorSetCount = 1;
  167. allocate_info.pSetLayouts = &layout;
  168. VkDescriptorSet descriptor_set;
  169. VkResult result = vkAllocateDescriptorSets(device, &allocate_info, &descriptor_set);
  170. if (result != VK_SUCCESS) {
  171. ERROR("Unable to allocate descriptor set: " << result);
  172. }
  173. return descriptor_set;
  174. }
  175. void UpdateVkDescriptorSet(VkDevice device, VkImageView image_view, VkDescriptorSet set) {
  176. VkDescriptorImageInfo image_info = {};
  177. image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
  178. image_info.imageView = image_view;
  179. image_info.sampler = VK_NULL_HANDLE;
  180. VkWriteDescriptorSet descriptor_write = {};
  181. descriptor_write.dstSet = set;
  182. descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
  183. descriptor_write.descriptorCount = 1;
  184. descriptor_write.dstBinding = 0;
  185. descriptor_write.pImageInfo = &image_info;
  186. descriptor_write.pBufferInfo = nullptr;
  187. descriptor_write.pTexelBufferView = nullptr;
  188. vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, nullptr);
  189. }
  190. VkQueue GetVkQueue(VkDevice device, uint32_t device_queue_family_index) {
  191. VkQueue queue;
  192. vkGetDeviceQueue(device, device_queue_family_index, /*queueIndex*/ 0, &queue);
  193. return queue;
  194. }
  195. VkCommandPool CreateVkCommandPool(VkDevice device, uint32_t device_queue_family_index) {
  196. VkCommandPool command_pool;
  197. VkCommandPoolCreateInfo create_info = {};
  198. create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  199. create_info.flags = 0;
  200. create_info.queueFamilyIndex = device_queue_family_index;
  201. VkResult result = vkCreateCommandPool(device, &create_info, nullptr, &command_pool);
  202. if (result != VK_SUCCESS) {
  203. ERROR("Unable to create command pool: " << result);
  204. }
  205. return command_pool;
  206. }
  207. VkCommandBuffer CreateVkCommandBuffer(VkDevice device, VkCommandPool command_pool) {
  208. VkCommandBufferAllocateInfo allocate_info = {};
  209. allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  210. allocate_info.commandPool = command_pool;
  211. allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  212. allocate_info.commandBufferCount = 1;
  213. VkCommandBuffer command_buffer;
  214. VkResult result = vkAllocateCommandBuffers( device, &allocate_info, &command_buffer);
  215. if (result != VK_SUCCESS) {
  216. ERROR("Unable to create VkCommandBuffer: " << result);
  217. }
  218. return command_buffer;
  219. }
  220. VkRenderPass CreateVkRenderPass(VkDevice device) {
  221. std::array<VkAttachmentDescription, 3> attachment_descriptions = {};
  222. VkAttachmentDescription* color_attachment_description = &attachment_descriptions[0];
  223. color_attachment_description->format = kVulkanFormat;
  224. color_attachment_description->samples = VK_SAMPLE_COUNT_1_BIT;
  225. color_attachment_description->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  226. color_attachment_description->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  227. color_attachment_description->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  228. color_attachment_description->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  229. color_attachment_description->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  230. color_attachment_description->finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  231. VkAttachmentReference color_attachment_reference = {};
  232. color_attachment_reference.attachment = 0;
  233. color_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  234. VkAttachmentDescription* depth_attachment_description = &attachment_descriptions[1];
  235. depth_attachment_description->format = kVulkanDepthFormat;
  236. depth_attachment_description->samples = VK_SAMPLE_COUNT_1_BIT;
  237. depth_attachment_description->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  238. depth_attachment_description->storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  239. depth_attachment_description->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  240. depth_attachment_description->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  241. depth_attachment_description->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  242. depth_attachment_description->finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  243. VkAttachmentReference depth_attachment_reference = {};
  244. depth_attachment_reference.attachment = 1;
  245. depth_attachment_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  246. VkAttachmentDescription* input_attachment_description = &attachment_descriptions[2];
  247. input_attachment_description->format = kVulkanFormat;
  248. input_attachment_description->samples = VK_SAMPLE_COUNT_1_BIT;
  249. input_attachment_description->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  250. input_attachment_description->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  251. input_attachment_description->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  252. input_attachment_description->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  253. input_attachment_description->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  254. input_attachment_description->finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
  255. VkAttachmentReference input_attachment_reference = {};
  256. input_attachment_reference.attachment = 2;
  257. input_attachment_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  258. std::array<VkSubpassDescription, 2> subpass_descriptions = {};
  259. VkSubpassDescription* draw_subpass_description = &subpass_descriptions[0];
  260. draw_subpass_description->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  261. draw_subpass_description->colorAttachmentCount = 1;
  262. draw_subpass_description->pColorAttachments = &input_attachment_reference;
  263. draw_subpass_description->pDepthStencilAttachment = &depth_attachment_reference;
  264. VkSubpassDescription* darken_subpass_description = &subpass_descriptions[1];
  265. darken_subpass_description->pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  266. darken_subpass_description->colorAttachmentCount = 1;
  267. darken_subpass_description->pColorAttachments = &color_attachment_reference;
  268. darken_subpass_description->pDepthStencilAttachment = &depth_attachment_reference;
  269. darken_subpass_description->inputAttachmentCount = 1;
  270. darken_subpass_description->pInputAttachments = &input_attachment_reference;
  271. std::array<VkSubpassDependency, 2> subpass_dependencies = {};
  272. VkSubpassDependency* color_subpass_dependency = &subpass_dependencies[0];
  273. color_subpass_dependency->srcSubpass = VK_SUBPASS_EXTERNAL;
  274. color_subpass_dependency->dstSubpass = 0;
  275. color_subpass_dependency->srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  276. color_subpass_dependency->dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  277. color_subpass_dependency->srcAccessMask = 0;
  278. color_subpass_dependency->dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
  279. VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  280. color_subpass_dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
  281. VkSubpassDependency* darken_subpass_dependency = &subpass_dependencies[1];
  282. darken_subpass_dependency->srcSubpass = 0;
  283. darken_subpass_dependency->dstSubpass = 1;
  284. darken_subpass_dependency->srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  285. darken_subpass_dependency->dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
  286. darken_subpass_dependency->srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  287. darken_subpass_dependency->dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
  288. VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  289. darken_subpass_dependency->dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
  290. VkRenderPassCreateInfo render_pass_info = {};
  291. render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  292. render_pass_info.attachmentCount = attachment_descriptions.size();
  293. render_pass_info.pAttachments = attachment_descriptions.data();
  294. render_pass_info.subpassCount = subpass_descriptions.size();
  295. render_pass_info.pSubpasses = subpass_descriptions.data();
  296. render_pass_info.dependencyCount = subpass_dependencies.size();
  297. render_pass_info.pDependencies = subpass_dependencies.data();
  298. VkRenderPass render_pass;
  299. VkResult result = vkCreateRenderPass(device, &render_pass_info, nullptr, &render_pass);
  300. if (result != VK_SUCCESS) {
  301. ERROR("Unable to create render pass: " << result);
  302. }
  303. return render_pass;
  304. }
  305. VkShaderModule CreateVkShaderModule(VkDevice device, std::string path) {
  306. std::ifstream fstream(path);
  307. if (!fstream) {
  308. ERROR("Unable to open: " << path);
  309. }
  310. std::stringstream buffer;
  311. buffer << fstream.rdbuf();
  312. std::string spirv_source = buffer.str();
  313. VkShaderModuleCreateInfo create_info = {};
  314. create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
  315. create_info.codeSize = spirv_source.length();
  316. create_info.pCode = (const uint32_t*)spirv_source.c_str();
  317. VkShaderModule shader_module;
  318. VkResult result = vkCreateShaderModule(device, &create_info, nullptr, &shader_module);
  319. if (result != VK_SUCCESS) {
  320. ERROR("Unable to create shader module for " << path << ": ");
  321. }
  322. return shader_module;
  323. }
  324. VkPipelineLayout CreateVkPipelineLayout(VkDevice device,
  325. VkDescriptorSetLayout descriptor_set_layout) {
  326. VkPipelineLayoutCreateInfo pipeline_layout_create_info = {};
  327. pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
  328. if (descriptor_set_layout != VK_NULL_HANDLE) {
  329. pipeline_layout_create_info.setLayoutCount = 1;
  330. pipeline_layout_create_info.pSetLayouts = &descriptor_set_layout;
  331. }
  332. VkPipelineLayout pipeline_layout;
  333. VkResult result = vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr,
  334. &pipeline_layout);
  335. if (result != VK_SUCCESS) {
  336. ERROR("Unable to create VkPipelineLayout: " << result);
  337. }
  338. return pipeline_layout;
  339. }
  340. VkPipeline CreateVkPipeline(VkDevice device, VkShaderModule vertex_shader_module,
  341. VkShaderModule fragment_shader_module, VkPipelineLayout pipeline_layout,
  342. VkRenderPass render_pass, uint32_t subpass) {
  343. VkPipelineShaderStageCreateInfo vertex_shader_stage_info = {};
  344. vertex_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  345. vertex_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT;
  346. vertex_shader_stage_info.module = vertex_shader_module;
  347. vertex_shader_stage_info.pName = "main";
  348. VkPipelineShaderStageCreateInfo fragment_shader_stage_info = {};
  349. fragment_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
  350. fragment_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
  351. fragment_shader_stage_info.module = fragment_shader_module;
  352. fragment_shader_stage_info.pName = "main";
  353. std::vector<VkPipelineShaderStageCreateInfo> shader_stages =
  354. {vertex_shader_stage_info, fragment_shader_stage_info};
  355. VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
  356. vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
  357. vertex_input_info.vertexBindingDescriptionCount = 0;
  358. vertex_input_info.pVertexBindingDescriptions = nullptr;
  359. vertex_input_info.vertexAttributeDescriptionCount = 0;
  360. vertex_input_info.pVertexAttributeDescriptions = nullptr;
  361. VkPipelineInputAssemblyStateCreateInfo input_assembly_info = {};
  362. input_assembly_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
  363. input_assembly_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  364. input_assembly_info.primitiveRestartEnable = VK_FALSE;
  365. VkViewport viewport = {};
  366. viewport.x = 0.0f;
  367. viewport.y = 0.0f;
  368. viewport.width = (float)kWidth;
  369. viewport.height = (float)kHeight;
  370. viewport.minDepth = 0.0f;
  371. viewport.maxDepth = 1.0f;
  372. VkExtent2D extent = {};
  373. extent.width = kWidth;
  374. extent.height = kHeight;
  375. VkRect2D scissor = {};
  376. scissor.offset = {0, 0};
  377. scissor.extent = extent;
  378. VkPipelineViewportStateCreateInfo viewport_state_info = {};
  379. viewport_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
  380. viewport_state_info.viewportCount = 1;
  381. viewport_state_info.pViewports = &viewport;
  382. viewport_state_info.scissorCount = 1;
  383. viewport_state_info.pScissors = &scissor;
  384. VkPipelineRasterizationStateCreateInfo rasterization_state_info = {};
  385. rasterization_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
  386. rasterization_state_info.depthClampEnable = VK_FALSE;
  387. rasterization_state_info.rasterizerDiscardEnable = VK_FALSE;
  388. rasterization_state_info.polygonMode = VK_POLYGON_MODE_FILL;
  389. rasterization_state_info.lineWidth = 1.0f;
  390. rasterization_state_info.cullMode = VK_CULL_MODE_BACK_BIT;
  391. rasterization_state_info.frontFace = VK_FRONT_FACE_CLOCKWISE;
  392. rasterization_state_info.depthBiasEnable = VK_FALSE;
  393. VkPipelineMultisampleStateCreateInfo multisampling_state_info = {};
  394. multisampling_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
  395. multisampling_state_info.sampleShadingEnable = VK_FALSE;
  396. multisampling_state_info.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
  397. VkPipelineDepthStencilStateCreateInfo depth_stencil_create_info = {};
  398. depth_stencil_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
  399. depth_stencil_create_info.depthTestEnable = VK_TRUE;
  400. depth_stencil_create_info.depthWriteEnable = VK_TRUE;
  401. depth_stencil_create_info.depthCompareOp = VK_COMPARE_OP_LESS;
  402. // TODO(brkho): Test depth bounds functionality.
  403. depth_stencil_create_info.depthBoundsTestEnable = VK_FALSE;
  404. depth_stencil_create_info.minDepthBounds = 0.0f;
  405. depth_stencil_create_info.maxDepthBounds = 1.0f;
  406. depth_stencil_create_info.stencilTestEnable = VK_FALSE;
  407. VkPipelineColorBlendAttachmentState color_blend_attachment_state = {};
  408. color_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
  409. VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
  410. color_blend_attachment_state.blendEnable = VK_FALSE;
  411. VkPipelineColorBlendStateCreateInfo color_blend_state = {};
  412. color_blend_state.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
  413. color_blend_state.logicOpEnable = VK_FALSE;
  414. color_blend_state.attachmentCount = 1;
  415. color_blend_state.pAttachments = &color_blend_attachment_state;
  416. VkGraphicsPipelineCreateInfo pipeline_create_info = {};
  417. pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
  418. pipeline_create_info.stageCount = 2;
  419. pipeline_create_info.pStages = shader_stages.data();
  420. pipeline_create_info.pVertexInputState = &vertex_input_info;
  421. pipeline_create_info.pInputAssemblyState = &input_assembly_info;
  422. pipeline_create_info.pViewportState = &viewport_state_info;
  423. pipeline_create_info.pRasterizationState = &rasterization_state_info;
  424. pipeline_create_info.pMultisampleState = &multisampling_state_info;
  425. pipeline_create_info.pDepthStencilState = &depth_stencil_create_info;
  426. pipeline_create_info.pColorBlendState = &color_blend_state;
  427. pipeline_create_info.pDynamicState = nullptr;
  428. pipeline_create_info.layout = pipeline_layout;
  429. pipeline_create_info.renderPass = render_pass;
  430. pipeline_create_info.subpass = subpass;
  431. pipeline_create_info.basePipelineHandle = VK_NULL_HANDLE;
  432. pipeline_create_info.basePipelineIndex = -1;
  433. VkPipeline pipeline;
  434. VkResult result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_create_info, nullptr,
  435. &pipeline);
  436. if (result != VK_SUCCESS) {
  437. ERROR("Unable to create VkPipeline: " << result);
  438. }
  439. return pipeline;
  440. }
  441. VkImage CreateVkImage(VkDevice device, VkFormat format, VkImageTiling image_tiling,
  442. VkImageUsageFlags usage) {
  443. VkImageCreateInfo create_info = {};
  444. create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  445. create_info.pNext = nullptr;
  446. create_info.imageType = VK_IMAGE_TYPE_2D;
  447. create_info.format = format;
  448. VkExtent3D extent = {};
  449. extent.width = kWidth;
  450. extent.height = kHeight;
  451. extent.depth = 1;
  452. create_info.extent = extent;
  453. create_info.mipLevels = 1;
  454. create_info.arrayLayers = 1;
  455. create_info.samples = VK_SAMPLE_COUNT_1_BIT;
  456. create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
  457. create_info.tiling = image_tiling;
  458. create_info.usage = usage;
  459. create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  460. VkImage image;
  461. VkResult result = vkCreateImage(device, &create_info, nullptr, &image);
  462. if (result != VK_SUCCESS) {
  463. ERROR("Unable to create VkImage: " << result);
  464. }
  465. return image;
  466. }
  467. inline VkImage CreateRenderVkImage(VkDevice device) {
  468. return CreateVkImage(device, kVulkanFormat, VK_IMAGE_TILING_OPTIMAL,
  469. VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
  470. }
  471. inline VkImage CreateDepthVkImage(VkDevice device) {
  472. return CreateVkImage(device, kVulkanDepthFormat, VK_IMAGE_TILING_OPTIMAL,
  473. VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
  474. }
  475. inline VkImage CreateScanoutVkImage(VkDevice device) {
  476. return CreateVkImage(device, kVulkanFormat, VK_IMAGE_TILING_LINEAR,
  477. VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
  478. }
  479. uint32_t FindMemoryType(uint32_t valid_image_memory_types,
  480. VkPhysicalDeviceMemoryProperties device_memory_properties,
  481. VkMemoryPropertyFlags memory_property_flags) {
  482. for (uint32_t i = 0; i < device_memory_properties.memoryTypeCount; i++) {
  483. // We don't care about performance, so just choose the first mappable memory type.
  484. if ((valid_image_memory_types & (1 << i)) &&
  485. ((device_memory_properties.memoryTypes[i].propertyFlags & memory_property_flags) ==
  486. memory_property_flags)) {
  487. return i;
  488. }
  489. }
  490. ERROR("Unable to find suitable memory type index");
  491. }
  492. VkDeviceMemory AllocateAndBindMemory(VkPhysicalDevice physical_device, VkDevice device,
  493. VkImage image, VkMemoryPropertyFlags memory_property_flags) {
  494. VkMemoryRequirements image_memory_requirements;
  495. vkGetImageMemoryRequirements(device, image, &image_memory_requirements);
  496. VkPhysicalDeviceMemoryProperties device_memory_properties;
  497. vkGetPhysicalDeviceMemoryProperties(physical_device, &device_memory_properties);
  498. VkMemoryAllocateInfo memory_allocate_info = {};
  499. memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  500. memory_allocate_info.allocationSize = image_memory_requirements.size;
  501. memory_allocate_info.memoryTypeIndex = FindMemoryType(
  502. image_memory_requirements.memoryTypeBits, device_memory_properties,
  503. memory_property_flags);
  504. VkDeviceMemory image_memory;
  505. VkResult result = vkAllocateMemory(device, &memory_allocate_info, nullptr, &image_memory);
  506. if (result != VK_SUCCESS) {
  507. ERROR("Unable to allocate image memory: " << result);
  508. }
  509. result = vkBindImageMemory(device, image, image_memory, 0);
  510. if (result != VK_SUCCESS) {
  511. ERROR("Unable to bind image memory: " << result);
  512. }
  513. return image_memory;
  514. }
  515. inline VkDeviceMemory AllocateAndBindRenderMemory(VkPhysicalDevice physical_device,
  516. VkDevice device, VkImage image) {
  517. return AllocateAndBindMemory(physical_device, device, image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
  518. }
  519. inline VkDeviceMemory AllocateAndBindDepthMemory(VkPhysicalDevice physical_device,
  520. VkDevice device, VkImage image) {
  521. return AllocateAndBindMemory(physical_device, device, image, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
  522. }
  523. inline VkDeviceMemory AllocateAndBindScanoutMemory(VkPhysicalDevice physical_device,
  524. VkDevice device, VkImage image) {
  525. return AllocateAndBindMemory(physical_device, device, image, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
  526. }
  527. VkImageView CreateVkImageView(VkDevice device, VkImage image, VkFormat format,
  528. VkImageAspectFlags aspect) {
  529. VkImageViewCreateInfo create_info = {};
  530. create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  531. create_info.image = image;
  532. create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
  533. create_info.format = format;
  534. VkComponentMapping component_mapping = {};
  535. component_mapping.r = VK_COMPONENT_SWIZZLE_IDENTITY;
  536. component_mapping.b = VK_COMPONENT_SWIZZLE_IDENTITY;
  537. component_mapping.g = VK_COMPONENT_SWIZZLE_IDENTITY;
  538. component_mapping.a = VK_COMPONENT_SWIZZLE_IDENTITY;
  539. create_info.components = component_mapping;
  540. VkImageSubresourceRange subresource_range = {};
  541. subresource_range.aspectMask = aspect;
  542. subresource_range.baseMipLevel = 0;
  543. subresource_range.levelCount = 1;
  544. subresource_range.baseArrayLayer = 0;
  545. subresource_range.layerCount = 1;
  546. create_info.subresourceRange = subresource_range;
  547. VkImageView image_view;
  548. VkResult result = vkCreateImageView(device, &create_info, nullptr, &image_view);
  549. if (result != VK_SUCCESS) {
  550. ERROR("Unable to create VkImageView: " << result);
  551. }
  552. return image_view;
  553. }
  554. VkImageView CreateRenderVkImageView(VkDevice device, VkImage image) {
  555. return CreateVkImageView(device, image, kVulkanFormat, VK_IMAGE_ASPECT_COLOR_BIT);
  556. }
  557. VkImageView CreateDepthVkImageView(VkDevice device, VkImage image) {
  558. return CreateVkImageView(device, image, kVulkanDepthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
  559. }
  560. VkFramebuffer CreateVkFramebuffer(VkDevice device, VkRenderPass render_pass,
  561. VkImageView render_image_view, VkImageView depth_image_view, VkImageView input_image_view) {
  562. std::array<VkImageView, 3> attachments =
  563. { render_image_view, depth_image_view, input_image_view };
  564. VkFramebufferCreateInfo create_info = {};
  565. create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  566. create_info.renderPass = render_pass;
  567. create_info.attachmentCount = attachments.size();
  568. create_info.pAttachments = attachments.data();
  569. create_info.width = kWidth;
  570. create_info.height = kHeight;
  571. create_info.layers = 1;
  572. VkFramebuffer framebuffer;
  573. VkResult result = vkCreateFramebuffer(device, &create_info, nullptr, &framebuffer);
  574. if (result != VK_SUCCESS) {
  575. ERROR("Unable to create VkFramebuffer: " << result);
  576. }
  577. return framebuffer;
  578. }
  579. void BeginCommandBuffer(VkCommandBuffer command_buffer) {
  580. VkCommandBufferBeginInfo command_buffer_begin_info = {};
  581. command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  582. command_buffer_begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  583. VkResult result = vkBeginCommandBuffer(command_buffer, &command_buffer_begin_info);
  584. if (result != VK_SUCCESS) {
  585. ERROR("Unable to begin command buffer recording: " << result);
  586. }
  587. }
  588. void EndCommandBufferAndSubmit(VkCommandBuffer command_buffer, VkQueue queue) {
  589. VkResult result = vkEndCommandBuffer(command_buffer);
  590. if (result != VK_SUCCESS) {
  591. ERROR("Unable to end command buffer recording: " << result);
  592. }
  593. VkSubmitInfo submit_info = {};
  594. submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  595. submit_info.commandBufferCount = 1;
  596. submit_info.pCommandBuffers = &command_buffer;
  597. result = vkQueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
  598. if (result != VK_SUCCESS) {
  599. ERROR("Error in submitting command buffer to queue: " << result);
  600. }
  601. }
  602. void WaitForIdle(VkQueue queue) {
  603. // In a real application, we should use real synchronization primitives to figure out when the
  604. // command buffers have been executed. Waiting on an idle queue is simple, but it can cause
  605. // deadlock if we continue to submit to the queue while we wait for idle.
  606. VkResult result = vkQueueWaitIdle(queue);
  607. if (result != VK_SUCCESS) {
  608. ERROR("Error in waiting for graphics queue to reach idle state: " << result);
  609. }
  610. }
  611. void Draw(VkDevice device, VkQueue queue, VkRenderPass render_pass, VkPipeline draw_pipeline,
  612. VkPipeline darken_pipeline, VkPipelineLayout darken_pipeline_layout,
  613. VkDescriptorSet descriptor_set, VkFramebuffer framebuffer, VkCommandBuffer command_buffer) {
  614. BeginCommandBuffer(command_buffer);
  615. VkRenderPassBeginInfo render_pass_begin_info = {};
  616. render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  617. render_pass_begin_info.renderPass = render_pass;
  618. render_pass_begin_info.framebuffer = framebuffer;
  619. VkRect2D render_area = {};
  620. render_area.offset = { 0, 0 };
  621. render_area.extent = { kWidth, kHeight };
  622. render_pass_begin_info.renderArea = render_area;
  623. std::array<VkClearValue, 2> clear_values = {};
  624. clear_values[0].color.float32[0] = 1.0f;
  625. clear_values[0].color.float32[1] = 0.0f;
  626. clear_values[0].color.float32[2] = 0.0f;
  627. clear_values[0].color.float32[3] = 1.0f;
  628. clear_values[1].depthStencil.depth = 1.0f;
  629. clear_values[1].depthStencil.stencil = 0.0f;
  630. clear_values[2].color.float32[0] = 1.0f;
  631. clear_values[2].color.float32[1] = 1.0f;
  632. clear_values[2].color.float32[2] = 1.0f;
  633. clear_values[2].color.float32[3] = 1.0f;
  634. render_pass_begin_info.clearValueCount = clear_values.size();
  635. render_pass_begin_info.pClearValues = clear_values.data();
  636. vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
  637. vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, draw_pipeline);
  638. vkCmdDraw(command_buffer, 3, 1, 0, 0);
  639. vkCmdDraw(command_buffer, 3, 1, 3, 0);
  640. vkCmdNextSubpass(command_buffer, VK_SUBPASS_CONTENTS_INLINE);
  641. vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, darken_pipeline);
  642. vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, darken_pipeline_layout,
  643. 0, 1, &descriptor_set, 0, nullptr);
  644. vkCmdDraw(command_buffer, 6, 1, 0, 0);
  645. vkCmdEndRenderPass(command_buffer);
  646. }
  647. void BlitToScanoutImage(VkQueue queue, VkCommandBuffer command_buffer, VkImage source_image,
  648. VkImage dest_image) {
  649. // We need to make sure the writes of the render pass have executed before actually scanning out
  650. // the rendered image. Also, we need to transition the layout of the scanout image to
  651. // VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
  652. VkImageMemoryBarrier image_memory_barrier = {};
  653. image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
  654. image_memory_barrier.pNext = nullptr;
  655. image_memory_barrier.srcAccessMask = 0;
  656. image_memory_barrier.dstAccessMask = 0;
  657. image_memory_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  658. image_memory_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  659. image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  660. image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  661. image_memory_barrier.image = dest_image;
  662. VkImageSubresourceRange subresource_range = {};
  663. subresource_range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  664. subresource_range.baseMipLevel = 0;
  665. subresource_range.levelCount = 1;
  666. subresource_range.baseArrayLayer = 0;
  667. subresource_range.layerCount = 1;
  668. image_memory_barrier.subresourceRange = subresource_range;
  669. vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
  670. VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
  671. VkOffset3D blit_start = {};
  672. blit_start.x = 0;
  673. blit_start.y = 0;
  674. blit_start.z = 0;
  675. VkOffset3D blit_end = {};
  676. blit_end.x = kWidth;
  677. blit_end.y = kHeight;
  678. blit_end.z = 1;
  679. VkImageSubresourceLayers subresource_layers = {};
  680. subresource_layers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  681. subresource_layers.mipLevel = 0;
  682. subresource_layers.baseArrayLayer = 0;
  683. subresource_layers.layerCount = 1;
  684. VkImageBlit image_blit = {};
  685. image_blit.srcSubresource = subresource_layers;
  686. image_blit.srcOffsets[0] = blit_start;
  687. image_blit.srcOffsets[1] = blit_end;
  688. image_blit.dstSubresource = subresource_layers;
  689. image_blit.dstOffsets[0] = blit_start;
  690. image_blit.dstOffsets[1] = blit_end;
  691. // TODO(brkho): Support multi-planar formats.
  692. vkCmdBlitImage(command_buffer, source_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dest_image,
  693. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &image_blit, VK_FILTER_NEAREST);
  694. EndCommandBufferAndSubmit(command_buffer, queue);
  695. }
  696. uint8_t* MapVkDeviceMemory(VkDevice device, VkDeviceMemory image_memory) {
  697. void* mapped_memory = nullptr;
  698. VkResult result = vkMapMemory(device, image_memory, 0, kWidth * kHeight * 4, 0, &mapped_memory);
  699. if (result != VK_SUCCESS) {
  700. ERROR("Unable to map device memory: " << result);
  701. }
  702. return static_cast<uint8_t*>(mapped_memory);
  703. }
  704. void WriteImage(uint8_t* pixels) {
  705. FILE *f = fopen("subpass.png", "wb");
  706. png_image image_info = {};
  707. image_info.version = PNG_IMAGE_VERSION;
  708. image_info.width = kWidth;
  709. image_info.height = kHeight;
  710. image_info.format = PNG_FORMAT_RGBA;
  711. if (png_image_write_to_stdio(&image_info, f, 0, pixels, kWidth * 4, nullptr) == 0) {
  712. ERROR("Error writing PNG: " << image_info.message);
  713. }
  714. fclose(f);
  715. }
  716. int main() {
  717. VkInstance instance = CreateVkInstance();
  718. VkPhysicalDevice physical_device = ChooseVkPhysicalDevice(instance);
  719. uint32_t device_queue_family_index = ChooseDeviceQueueFamilyIndex(physical_device);
  720. VkDevice device = CreateVkDevice(physical_device, device_queue_family_index);
  721. VkQueue queue = GetVkQueue(device, device_queue_family_index);
  722. VkCommandPool command_pool = CreateVkCommandPool(device, device_queue_family_index);
  723. VkCommandBuffer command_buffer = CreateVkCommandBuffer(device, command_pool);
  724. VkImage render_image = CreateRenderVkImage(device);
  725. AllocateAndBindRenderMemory(physical_device, device, render_image);
  726. VkImageView render_image_view = CreateRenderVkImageView(device, render_image);
  727. VkImage depth_image = CreateDepthVkImage(device);
  728. AllocateAndBindDepthMemory(physical_device, device, depth_image);
  729. VkImageView depth_image_view = CreateDepthVkImageView(device, depth_image);
  730. VkImage input_image = CreateRenderVkImage(device);
  731. AllocateAndBindRenderMemory(physical_device, device, input_image);
  732. VkImageView input_image_view = CreateRenderVkImageView(device, input_image);
  733. VkDescriptorSetLayout descriptor_set_layout = CreateVkDescriptorSetLayout(device);
  734. VkDescriptorPool descriptor_pool = CreateAttachmentVkDescriptorPool(device);
  735. VkDescriptorSet descriptor_set = CreateVkDescriptorSet(device, descriptor_set_layout,
  736. descriptor_pool);
  737. UpdateVkDescriptorSet(device, render_image_view, descriptor_set);
  738. VkRenderPass render_pass = CreateVkRenderPass(device);
  739. VkShaderModule draw_vertex_shader_module =
  740. CreateVkShaderModule(device, kDrawVertexShaderPath);
  741. VkShaderModule draw_fragment_shader_module =
  742. CreateVkShaderModule(device, kDrawFragmentShaderPath);
  743. VkPipelineLayout draw_pipeline_layout = CreateVkPipelineLayout(device, VK_NULL_HANDLE);
  744. VkPipeline draw_pipeline = CreateVkPipeline(device, draw_vertex_shader_module,
  745. draw_fragment_shader_module, draw_pipeline_layout, render_pass, 0 /* subpass */);
  746. VkShaderModule darken_vertex_shader_module =
  747. CreateVkShaderModule(device, kDarkenVertexShaderPath);
  748. VkShaderModule darken_fragment_shader_module =
  749. CreateVkShaderModule(device, kDarkenFragmentShaderPath);
  750. VkPipelineLayout darken_pipeline_layout = CreateVkPipelineLayout(device, descriptor_set_layout);
  751. VkPipeline darken_pipeline = CreateVkPipeline(device, darken_vertex_shader_module,
  752. darken_fragment_shader_module, darken_pipeline_layout, render_pass, 1 /* subpass */);
  753. VkFramebuffer framebuffer = CreateVkFramebuffer(device, render_pass, render_image_view,
  754. depth_image_view, input_image_view);
  755. VkImage scanout_image = CreateScanoutVkImage(device);
  756. VkDeviceMemory scanout_image_memory =
  757. AllocateAndBindScanoutMemory(physical_device, device, scanout_image);
  758. Draw(device, queue, render_pass, draw_pipeline, darken_pipeline, darken_pipeline_layout,
  759. descriptor_set, framebuffer, command_buffer);
  760. // Since the render target is created with VK_IMAGE_TILING_OPTIMAL, we need to copy it to a linear
  761. // format before scanning out.
  762. BlitToScanoutImage(queue, command_buffer, render_image, scanout_image);
  763. WaitForIdle(queue);
  764. uint8_t* pixels = MapVkDeviceMemory(device, scanout_image_memory);
  765. WriteImage(pixels);
  766. return EXIT_SUCCESS;
  767. }