Example application for subpasses in Vulkan.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

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. }