+static bool create_renderpass()
+{
+ VkSurfaceFormatKHR sformat;
+ if(!vku_get_surface_format(vk_physical, vk_surface, &sformat)) {
+ fprintf(stderr, "Failed to get surface format.\n");
+ return false;
+ }
+
+ VkAttachmentDescription att[2];
+ memset(&att, 0, (sizeof att[0]) * 2);
+
+ att[0].format = sformat.format;
+ att[0].samples = VK_SAMPLE_COUNT_1_BIT;
+ att[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ att[0].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ att[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ att[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ att[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ att[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ att[1].format = dformat;
+ att[1].samples = VK_SAMPLE_COUNT_1_BIT;
+ att[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ att[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ att[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ att[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ att[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ att[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference cref;
+ memset(&cref, 0, sizeof cref);
+ cref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ VkAttachmentReference dref;
+ memset(&dref, 0, sizeof dref);
+ dref.attachment = 1;
+ dref.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ VkSubpassDescription sd;
+ memset(&sd, 0, sizeof sd);
+ sd.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ sd.colorAttachmentCount = 1;
+ sd.pColorAttachments = &cref;
+ sd.pDepthStencilAttachment = &dref;
+
+ VkRenderPassCreateInfo rinf;
+ memset(&rinf, 0, sizeof rinf);
+ rinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ rinf.attachmentCount = 2;
+ rinf.pAttachments = att;
+ rinf.subpassCount = 1;
+ rinf.pSubpasses = &sd;
+
+ if(vkCreateRenderPass(vk_device, &rinf, 0, &vk_renderpass) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to create render pass.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool create_framebuffers()
+{
+ /* framebuffer attachments */
+ VkImageView fb_att[2];
+ fb_att[1] = dview;
+
+ VkFramebufferCreateInfo fbinf;
+ memset(&fbinf, 0, sizeof fbinf);
+ fbinf.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fbinf.renderPass = vk_renderpass;
+ fbinf.attachmentCount = 2;
+ fbinf.pAttachments = fb_att;
+ fbinf.width = win_w;
+ fbinf.height = win_h;
+ fbinf.layers = 1;
+
+ for(int i=0; i<2; i++) {
+ fb_att[0] = iviews[i];
+ if(vkCreateFramebuffer(vk_device, &fbinf, 0, &fbs[i]) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to create framebuffer %i\n", i);
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool end_init_command_buffer(VkCommandBuffer *cb)
+{
+ if(vkEndCommandBuffer(*cb) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to end command buffer.\n");
+ return false;
+ }
+
+ VkSubmitInfo si;
+ memset(&si, 0, sizeof si);
+ si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ si.commandBufferCount = 1;
+ si.pCommandBuffers = cb;
+
+ if(vkQueueSubmit(vk_queue, 1, &si, VK_NULL_HANDLE) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to submit null queue.\n");
+ return false;
+ }
+
+ if(vkQueueWaitIdle(vk_queue) != VK_SUCCESS) {
+ fprintf(stderr, "QueueWaitIdle failure!\n");
+ return false;
+ }
+
+ vkFreeCommandBuffers(vk_device, vk_pool, 1, cb);
+ *cb = VK_NULL_HANDLE;
+
+ return true;
+}
+
+static bool allocate_rendering_command_buffers(VkCommandBuffer *bufs)
+{
+ return vku_alloc_cmdbufs(vk_pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ 2, bufs);
+}
+
+static void free_rendering_command_buffers(VkCommandBuffer *bufs, int count)
+{
+ for(int i=0; i<count; i++) {
+ vku_free_cmdbuf(vk_pool, bufs[i]);
+ }
+}
+
+static bool begin_rendering_command_buffers(VkCommandBuffer *bufs, int count)
+{
+ VkCommandBufferInheritanceInfo iinf;
+ memset(&iinf, 0, sizeof iinf);
+ iinf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
+ iinf.renderPass = VK_NULL_HANDLE;
+ iinf.framebuffer = VK_NULL_HANDLE;
+
+ VkCommandBufferBeginInfo binf;
+ memset(&binf, 0, sizeof binf);
+ binf.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ binf.pInheritanceInfo = &iinf;
+
+ // setting clear values
+ VkClearValue clvals[2];
+ for(int i=0; i<4; i++) {
+ clvals[0].color.float32[i] = clear_color[i];
+ }
+ clvals[1].depthStencil = {1.0f, 0};
+
+ //build drawing command buffers
+ for(int i=0; i<count; i++) {
+ if(vkBeginCommandBuffer(bufs[i], &binf) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to begin command buffer: %d\n", i);
+ return false;
+ }
+
+ VkImageMemoryBarrier imbarr;
+ memset(&imbarr, 0, sizeof imbarr);
+ imbarr.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ imbarr.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ imbarr.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ imbarr.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ imbarr.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ imbarr.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ imbarr.image = images[i];
+ imbarr.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
+ vkCmdPipelineBarrier(bufs[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &imbarr);
+
+ VkRenderPassBeginInfo rbinf;
+ memset(&rbinf, 0, sizeof rbinf);
+ rbinf.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rbinf.renderPass = vk_renderpass;
+ rbinf.framebuffer = fbs[i];
+ rbinf.renderArea.extent.width = win_w;
+ rbinf.renderArea.extent.height = win_h;
+ rbinf.clearValueCount = count;
+ rbinf.pClearValues = clvals;
+
+ vkCmdBeginRenderPass(bufs[i], &rbinf, VK_SUBPASS_CONTENTS_INLINE);
+ VkViewport viewport;
+ memset(&viewport, 0, sizeof viewport);
+ viewport.width = (float)win_w;
+ viewport.height = (float)win_h;
+ viewport.maxDepth = 1.0f;
+ vkCmdSetViewport(bufs[i], 0, 1, &viewport);
+
+ VkRect2D scissor;
+ memset(&scissor, 0, sizeof scissor);
+ scissor.extent.width = win_w;
+ scissor.extent.height = win_h;
+ vkCmdSetScissor(bufs[i], 0, 1, &scissor);
+ vkCmdEndRenderPass(bufs[i]);
+
+ /* pre-present barrier */
+ VkImageMemoryBarrier ppb;
+ memset(&ppb, 0, sizeof ppb);
+ ppb.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ ppb.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ ppb.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ ppb.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ ppb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ ppb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ ppb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ ppb.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
+ ppb.image = images[i];
+
+ vkCmdPipelineBarrier(bufs[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, 0, 0, 0, 1, &ppb);
+
+ if(vkEndCommandBuffer(bufs[i]) != VK_SUCCESS) {
+ fprintf(stderr, "Failed to end command buffer: %d\n", i);
+ return false;
+ }
+ }
+ return true;
+}
+