diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index f30a015c..871858de 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -881,7 +881,7 @@ bool VulkanExampleBase::initVulkan() { char* endptr; uint32_t index = strtol(args[i + 1], &endptr, 10); - if (endptr != args[i + 1]) + if (endptr != args[i + 1]) { if (index > gpuCount - 1) { @@ -900,11 +900,11 @@ bool VulkanExampleBase::initVulkan() { uint32_t gpuCount = 0; VK_CHECK_RESULT(vkEnumeratePhysicalDevices(instance, &gpuCount, nullptr)); - if (gpuCount == 0) + if (gpuCount == 0) { std::cerr << "No Vulkan devices found!" << std::endl; } - else + else { // Enumerate devices std::cout << "Available Vulkan devices" << std::endl; @@ -984,7 +984,7 @@ bool VulkanExampleBase::initVulkan() androidProduct += std::string(prop); }; LOGD("androidProduct = %s", androidProduct.c_str()); -#endif +#endif return true; } @@ -1329,13 +1329,13 @@ int32_t VulkanExampleBase::handleAppInput(struct android_app* app, AInputEvent* vulkanExample->mousePos.x = AMotionEvent_getX(event, 0); vulkanExample->mousePos.y = AMotionEvent_getY(event, 0); break; - } + } case AMOTION_EVENT_ACTION_MOVE: { bool handled = false; if (vulkanExample->settings.overlay) { ImGuiIO& io = ImGui::GetIO(); handled = io.WantCaptureMouse; - } + } if (!handled) { int32_t eventX = AMotionEvent_getX(event, 0); int32_t eventY = AMotionEvent_getY(event, 0); @@ -1940,7 +1940,7 @@ void VulkanExampleBase::handleEvent(const xcb_generic_event_t *event) if (settings.overlay) { settings.overlay = !settings.overlay; } - break; + break; } } break; @@ -1960,7 +1960,7 @@ void VulkanExampleBase::handleEvent(const xcb_generic_event_t *event) break; case KEY_D: camera.keys.right = false; - break; + break; case KEY_ESCAPE: quit = true; break; diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index f821d93e..e28efb10 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -56,7 +56,7 @@ class VulkanExampleBase { -private: +private: // Get window title with example name, device, et. std::string getWindowTitle(); /** brief Indicates that the view (position, rotation) has changed and buffers containing camera matrices need to be updated */ @@ -182,8 +182,7 @@ public: std::string name = "vulkanExample"; uint32_t apiVersion = VK_API_VERSION_1_0; - struct - { + struct { VkImage image; VkDeviceMemory mem; VkImageView view; diff --git a/examples/triangle/triangle.cpp b/examples/triangle/triangle.cpp index 2a2ffda6..4a91d0c8 100644 --- a/examples/triangle/triangle.cpp +++ b/examples/triangle/triangle.cpp @@ -44,22 +44,21 @@ public: // Vertex buffer and attributes struct { - VkDeviceMemory memory; // Handle to the device memory for this buffer - VkBuffer buffer; // Handle to the Vulkan buffer object that the memory is bound to + VkDeviceMemory memory; // Handle to the device memory for this buffer + VkBuffer buffer; // Handle to the Vulkan buffer object that the memory is bound to } vertices; // Index buffer - struct - { - VkDeviceMemory memory; - VkBuffer buffer; + struct { + VkDeviceMemory memory; + VkBuffer buffer; uint32_t count; } indices; // Uniform buffer block object struct { - VkDeviceMemory memory; - VkBuffer buffer; + VkDeviceMemory memory; + VkBuffer buffer; VkDescriptorBufferInfo descriptor; } uniformBufferVS; @@ -159,7 +158,7 @@ public: if ((typeBits & 1) == 1) { if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) - { + { return i; } } @@ -341,17 +340,17 @@ public: // The submit info structure specifices a command buffer queue submission batch VkSubmitInfo submitInfo = {}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at - submitInfo.pWaitSemaphores = &presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing - submitInfo.waitSemaphoreCount = 1; // One wait semaphore - submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed - submitInfo.signalSemaphoreCount = 1; // One signal semaphore - submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; // Command buffers(s) to execute in this batch (submission) - submitInfo.commandBufferCount = 1; // One command buffer + submitInfo.pWaitDstStageMask = &waitStageMask; // Pointer to the list of pipeline stages that the semaphore waits will occur at + submitInfo.pWaitSemaphores = &presentCompleteSemaphore; // Semaphore(s) to wait upon before the submitted command buffer starts executing + submitInfo.waitSemaphoreCount = 1; // One wait semaphore + submitInfo.pSignalSemaphores = &renderCompleteSemaphore; // Semaphore(s) to be signaled when command buffers have completed + submitInfo.signalSemaphoreCount = 1; // One signal semaphore + submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; // Command buffers(s) to execute in this batch (submission) + submitInfo.commandBufferCount = 1; // One command buffer // Submit to the graphics queue passing a wait fence VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, waitFences[currentBuffer])); - + // Present the current buffer to the swap chain // Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation // This ensures that the image is not presented to the windowing system until all commands have been submitted @@ -673,9 +672,9 @@ public: frameBuffers.resize(swapChain.imageCount); for (size_t i = 0; i < frameBuffers.size(); i++) { - std::array attachments; - attachments[0] = swapChain.buffers[i].view; // Color attachment is the view of the swapchain image - attachments[1] = depthStencil.view; // Depth/Stencil attachment is the same for all frame buffers + std::array attachments; + attachments[0] = swapChain.buffers[i].view; // Color attachment is the view of the swapchain image + attachments[1] = depthStencil.view; // Depth/Stencil attachment is the same for all frame buffers VkFramebufferCreateInfo frameBufferCreateInfo = {}; frameBufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; @@ -704,83 +703,84 @@ public: std::array attachments = {}; // Color attachment - attachments[0].format = swapChain.colorFormat; // Use the color format selected by the swapchain - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; // We don't use multi sampling in this example - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear this attachment at the start of the render pass - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // Keep its contents after the render pass is finished (for displaying it) - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // We don't use stencil, so don't care for load - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // Same for store - attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Layout at render pass start. Initial doesn't matter, so we use undefined - attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; // Layout to which the attachment is transitioned when the render pass is finished - // As we want to present the color buffer to the swapchain, we transition to PRESENT_KHR + attachments[0].format = swapChain.colorFormat; // Use the color format selected by the swapchain + attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; // We don't use multi sampling in this example + attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear this attachment at the start of the render pass + attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // Keep its contents after the render pass is finished (for displaying it) + attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // We don't use stencil, so don't care for load + attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // Same for store + attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Layout at render pass start. Initial doesn't matter, so we use undefined + attachments[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; // Layout to which the attachment is transitioned when the render pass is finished + // As we want to present the color buffer to the swapchain, we transition to PRESENT_KHR // Depth attachment - attachments[1].format = depthFormat; // A proper depth format is selected in the example base - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at start of first subpass - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // We don't need depth after render pass has finished (DONT_CARE may result in better performance) - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // No stencil - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // No Stencil - attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Layout at render pass start. Initial doesn't matter, so we use undefined - attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Transition to depth/stencil attachment + attachments[1].format = depthFormat; // A proper depth format is selected in the example base + attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // Clear depth at start of first subpass + attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // We don't need depth after render pass has finished (DONT_CARE may result in better performance) + attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // No stencil + attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // No Stencil + attachments[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; // Layout at render pass start. Initial doesn't matter, so we use undefined + attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Transition to depth/stencil attachment // Setup attachment references VkAttachmentReference colorReference = {}; - colorReference.attachment = 0; // Attachment 0 is color - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // Attachment layout used as color during the subpass + colorReference.attachment = 0; // Attachment 0 is color + colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // Attachment layout used as color during the subpass VkAttachmentReference depthReference = {}; - depthReference.attachment = 1; // Attachment 1 is color - depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Attachment used as depth/stemcil used during the subpass + depthReference.attachment = 1; // Attachment 1 is color + depthReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; // Attachment used as depth/stemcil used during the subpass // Setup a single subpass reference VkSubpassDescription subpassDescription = {}; - subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpassDescription.colorAttachmentCount = 1; // Subpass uses one color attachment - subpassDescription.pColorAttachments = &colorReference; // Reference to the color attachment in slot 0 - subpassDescription.pDepthStencilAttachment = &depthReference; // Reference to the depth attachment in slot 1 - subpassDescription.inputAttachmentCount = 0; // Input attachments can be used to sample from contents of a previous subpass - subpassDescription.pInputAttachments = nullptr; // (Input attachments not used by this example) - subpassDescription.preserveAttachmentCount = 0; // Preserved attachments can be used to loop (and preserve) attachments through subpasses - subpassDescription.pPreserveAttachments = nullptr; // (Preserve attachments not used by this example) - subpassDescription.pResolveAttachments = nullptr; // Resolve attachments are resolved at the end of a sub pass and can be used for e.g. multi sampling + subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpassDescription.colorAttachmentCount = 1; // Subpass uses one color attachment + subpassDescription.pColorAttachments = &colorReference; // Reference to the color attachment in slot 0 + subpassDescription.pDepthStencilAttachment = &depthReference; // Reference to the depth attachment in slot 1 + subpassDescription.inputAttachmentCount = 0; // Input attachments can be used to sample from contents of a previous subpass + subpassDescription.pInputAttachments = nullptr; // (Input attachments not used by this example) + subpassDescription.preserveAttachmentCount = 0; // Preserved attachments can be used to loop (and preserve) attachments through subpasses + subpassDescription.pPreserveAttachments = nullptr; // (Preserve attachments not used by this example) + subpassDescription.pResolveAttachments = nullptr; // Resolve attachments are resolved at the end of a sub pass and can be used for e.g. multi sampling // Setup subpass dependencies // These will add the implicit ttachment layout transitionss specified by the attachment descriptions - // The actual usage layout is preserved through the layout specified in the attachment reference + // The actual usage layout is preserved through the layout specified in the attachment reference // Each subpass dependency will introduce a memory and execution dependency between the source and dest subpass described by // srcStageMask, dstStageMask, srcAccessMask, dstAccessMask (and dependencyFlags is set) // Note: VK_SUBPASS_EXTERNAL is a special constant that refers to all commands executed outside of the actual renderpass) std::array dependencies; // First dependency at the start of the renderpass - // Does the transition from final to initial layout - dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; // Producer of the dependency - dependencies[0].dstSubpass = 0; // Consumer is our single subpass that will wait for the execution depdendency - dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; - dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + // Does the transition from final to initial layout + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; // Producer of the dependency + dependencies[0].dstSubpass = 0; // Consumer is our single subpass that will wait for the execution depdendency + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // Match our pWaitDstStageMask when we vkQueueSubmit + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // is a loadOp stage for color attachments + dependencies[0].srcAccessMask = 0; // semaphore wait already does memory dependency for us + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; // is a loadOp CLEAR access mask for color attachments dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; // Second dependency at the end the renderpass // Does the transition from the initial to the final layout - dependencies[1].srcSubpass = 0; // Producer of the dependency is our single subpass - dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; // Consumer are all commands outside of the renderpass - dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + // Technically this is the same as the implicit subpass dependency, but we are gonna state it explicitly here + dependencies[1].srcSubpass = 0; // Producer of the dependency is our single subpass + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; // Consumer are all commands outside of the renderpass + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // is a storeOp stage for color attachments + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; // Do not block any subsequent work + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; // is a storeOp `STORE` access mask for color attachments + dependencies[1].dstAccessMask = 0; dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; // Create the actual renderpass VkRenderPassCreateInfo renderPassInfo = {}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attachments.size()); // Number of attachments used by this render pass - renderPassInfo.pAttachments = attachments.data(); // Descriptions of the attachments used by the render pass - renderPassInfo.subpassCount = 1; // We only use one subpass in this example - renderPassInfo.pSubpasses = &subpassDescription; // Description of that subpass - renderPassInfo.dependencyCount = static_cast(dependencies.size()); // Number of subpass dependencies - renderPassInfo.pDependencies = dependencies.data(); // Subpass dependencies used by the render pass + renderPassInfo.attachmentCount = static_cast(attachments.size()); // Number of attachments used by this render pass + renderPassInfo.pAttachments = attachments.data(); // Descriptions of the attachments used by the render pass + renderPassInfo.subpassCount = 1; // We only use one subpass in this example + renderPassInfo.pSubpasses = &subpassDescription; // Description of that subpass + renderPassInfo.dependencyCount = static_cast(dependencies.size()); // Number of subpass dependencies + renderPassInfo.pDependencies = dependencies.data(); // Subpass dependencies used by the render pass VK_CHECK_RESULT(vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass)); } @@ -873,7 +873,7 @@ public: rasterizationState.lineWidth = 1.0f; // Color blend state describes how blend factors are calculated (if used) - // We need one blend attachment state per color attachment (even if blending is not used + // We need one blend attachment state per color attachment (even if blending is not used) VkPipelineColorBlendAttachmentState blendAttachmentState[1] = {}; blendAttachmentState[0].colorWriteMask = 0xf; blendAttachmentState[0].blendEnable = VK_FALSE;