// // Vulkan update. // VkBool32 Example::update(const vkts::IUpdateThreadContext& updateContext) { for (size_t i = 0; i < allUpdateables.size(); i++) { allUpdateables[i]->update(updateContext.getDeltaTime(), updateContext.getDeltaTicks()); } // VkResult result = VK_SUCCESS; // if (windowDimension != updateContext.getWindowDimension(windowIndex)) { windowDimension = updateContext.getWindowDimension(windowIndex); result = VK_ERROR_OUT_OF_DATE_KHR; } // uint32_t currentBuffer; if (result == VK_SUCCESS) { result = swapchain->acquireNextImage(UINT64_MAX, imageAcquiredSemaphore->getSemaphore(), VK_NULL_HANDLE, currentBuffer); } if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { glm::mat4 projectionMatrix(1.0f); glm::mat4 viewMatrix(1.0f); const auto& dimension = updateContext.getWindowDimension(windowIndex); projectionMatrix = vkts::perspectiveMat4(45.0f, (float) dimension.x / (float) dimension.y, 1.0f, 100.0f); viewMatrix = camera->getViewMatrix(); glm::vec3 lightDirection = glm::mat3(viewMatrix) * glm::vec3(0.0f, 1.0f, 2.0f); lightDirection = glm::normalize(lightDirection); if (!fragmentUniformBuffer->upload(0, 0, lightDirection)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not upload light direction."); return VK_FALSE; } if (!vertexViewProjectionUniformBuffer->upload(0 * sizeof(float) * 16, 0, projectionMatrix)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not upload matrices."); return VK_FALSE; } if (!vertexViewProjectionUniformBuffer->upload(1 * sizeof(float) * 16, 0, viewMatrix)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not upload matrices."); return VK_FALSE; } if (scene.get()) { scene->updateRecursive(updateContext); } // VkSemaphore waitSemaphores = imageAcquiredSemaphore->getSemaphore(); VkSemaphore signalSemaphores = renderingCompleteSemaphore->getSemaphore(); VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; VkSubmitInfo submitInfo; memset(&submitInfo, 0, sizeof(VkSubmitInfo)); submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = &waitSemaphores; submitInfo.pWaitDstStageMask = &waitDstStageMask; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = cmdBuffer[currentBuffer]->getCommandBuffers(); submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = &signalSemaphores; result = initialResources->getQueue()->submit(1, &submitInfo, VK_NULL_HANDLE); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not submit queue."); return VK_FALSE; } waitSemaphores = renderingCompleteSemaphore->getSemaphore(); VkSwapchainKHR swapchains = swapchain->getSwapchain(); result = swapchain->queuePresent(initialResources->getQueue()->getQueue(), 1, &waitSemaphores, 1, &swapchains, ¤tBuffer, nullptr); if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { result = initialResources->getQueue()->waitIdle(); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not wait for idle queue."); return VK_FALSE; } } else { if (result == VK_ERROR_OUT_OF_DATE_KHR) { terminateResources(updateContext); if (!buildResources(updateContext)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build resources."); return VK_FALSE; } } else { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not present queue."); return VK_FALSE; } } } else { if (result == VK_ERROR_OUT_OF_DATE_KHR) { terminateResources(updateContext); if (!buildResources(updateContext)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build resources."); return VK_FALSE; } } else { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not acquire next image."); return VK_FALSE; } } // result = imageAcquiredSemaphore->reset(); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not reset semaphore."); return VK_FALSE; } result = renderingCompleteSemaphore->reset(); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not reset semaphore."); return VK_FALSE; } return VK_TRUE; }
// // Vulkan initialization. // VkBool32 Example::init(const vkts::IUpdateThreadContext& updateContext) { if (!updateContext.isWindowAttached(windowIndex)) { return VK_FALSE; } windowDimension = updateContext.getWindowDimension(windowIndex); // camera = vkts::cameraCreate(glm::vec4(0.0f, 4.0f, 10.0f, 1.0f), glm::vec4(0.0f, 2.0f, 0.0f, 1.0f)); if (!camera.get()) { return VK_FALSE; } allUpdateables.append(camera); inputController = vkts::inputControllerCreate(updateContext, windowIndex, 0, camera); if (!inputController.get()) { return VK_FALSE; } allUpdateables.insert(0, inputController); // commandPool = vkts::commandPoolCreate(initialResources->getDevice()->getDevice(), 0, initialResources->getQueue()->getQueueFamilyIndex()); if (!commandPool.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not get command pool."); return VK_FALSE; } // imageAcquiredSemaphore = vkts::semaphoreCreate(initialResources->getDevice()->getDevice(), 0); if (!imageAcquiredSemaphore.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create semaphore."); return VK_FALSE; } renderingCompleteSemaphore = vkts::semaphoreCreate(initialResources->getDevice()->getDevice(), 0); if (!renderingCompleteSemaphore.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create semaphore."); return VK_FALSE; } // if (!buildUniformBuffers()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build uniform buffers."); return VK_FALSE; } if (!buildShader()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build shader."); return VK_FALSE; } if (!buildDescriptorSetLayout()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build descriptor set layout."); return VK_FALSE; } if (!buildPipelineLayout()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build pipeline cache."); return VK_FALSE; } // if (!buildResources(updateContext)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build resources."); return VK_FALSE; } // glm::vec3 lightDirection = glm::vec3(0.0f, 1.0f, 2.0f); lightDirection = glm::normalize(lightDirection); if (!fragmentUniformBuffer->upload(0, 0, lightDirection)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not upload light direction."); return VK_FALSE; } return VK_TRUE; }
// // Vulkan update. // VkBool32 Example::update(const vkts::IUpdateThreadContext& updateContext) { VkResult result = VK_SUCCESS; // if (windowDimension != updateContext.getWindowDimension(windowIndex)) { windowDimension = updateContext.getWindowDimension(windowIndex); result = VK_ERROR_OUT_OF_DATE_KHR; } // uint32_t currentBuffer; if (result == VK_SUCCESS) { result = swapchain->acquireNextImage(UINT64_MAX, imageAcquiredSemaphore->getSemaphore(), VK_NULL_HANDLE, currentBuffer); } if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { VkSemaphore waitSemaphores = imageAcquiredSemaphore->getSemaphore(); VkSemaphore signalSemaphores = renderingCompleteSemaphore->getSemaphore(); VkPipelineStageFlags waitDstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; VkSubmitInfo submitInfo; memset(&submitInfo, 0, sizeof(VkSubmitInfo)); submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.waitSemaphoreCount = 1; submitInfo.pWaitSemaphores = &waitSemaphores; submitInfo.pWaitDstStageMask = &waitDstStageMask; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = cmdBuffer[currentBuffer]->getCommandBuffers(); submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = &signalSemaphores; result = queue->submit(1, &submitInfo, VK_NULL_HANDLE); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not submit queue."); return VK_FALSE; } waitSemaphores = renderingCompleteSemaphore->getSemaphore(); VkSwapchainKHR swapchains = swapchain->getSwapchain(); result = swapchain->queuePresent(queue->getQueue(), 1, &waitSemaphores, 1, &swapchains, ¤tBuffer, nullptr); if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { result = queue->waitIdle(); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not wait for idle queue."); return VK_FALSE; } } else { if (result == VK_ERROR_OUT_OF_DATE_KHR) { terminateResources(updateContext); if (!buildResources(updateContext)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build resources."); return VK_FALSE; } } else { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not present queue."); return VK_FALSE; } } } else { if (result == VK_ERROR_OUT_OF_DATE_KHR) { terminateResources(updateContext); if (!buildResources(updateContext)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build resources."); return VK_FALSE; } } else { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not acquire next image."); return VK_FALSE; } } // result = imageAcquiredSemaphore->reset(); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not reset semaphore."); return VK_FALSE; } result = renderingCompleteSemaphore->reset(); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not reset semaphore."); return VK_FALSE; } return VK_TRUE; }
// // Vulkan initialization. // VkBool32 Example::init(const vkts::IUpdateThreadContext& updateContext) { if (!updateContext.isDisplayAttached(displayIndex)) { return VK_FALSE; } if (!updateContext.isWindowAttached(windowIndex)) { return VK_FALSE; } windowDimension = updateContext.getWindowDimension(windowIndex); // VkResult result; // if (!vkts::wsiGatherNeededInstanceExtensions()) { vkts::logPrint(VKTS_LOG_WARNING, "Example: Could not gather instance extensions."); return VK_TRUE; } instance = vkts::instanceCreate(VKTS_EXAMPLE_NAME, VK_MAKE_VERSION(1, 0, 0), VK_MAKE_VERSION(1, 0, 0), 0, 0, nullptr, vkts::extensionGetNeededInstanceExtensionCount(), vkts::extensionGetNeededInstanceExtensionNames()); if (!instance.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create instance."); return VK_FALSE; } if (!vkts::wsiInitInstanceExtensions(instance->getInstance())) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not initialize instance extension."); return VK_FALSE; } physicalDevice = vkts::physicalDeviceCreate(instance->getInstance(), 0); if (!physicalDevice.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not get physical device."); return VK_FALSE; } if (!vkts::wsiGatherNeededDeviceExtensions(physicalDevice->getPhysicalDevice())) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not gather device extension."); return VK_FALSE; } // surface = vkts::wsiSurfaceCreate(instance->getInstance(), updateContext.getNativeDisplay(displayIndex), updateContext.getNativeWindow(windowIndex)); if (!surface.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create surface."); return VK_FALSE; } // std::vector<VkBool32> supportFilter; result = vkts::wsiGetPhysicalDeviceSurfaceSupport(physicalDevice->getPhysicalDevice(), surface->getSurface(), (uint32_t) physicalDevice->getAllQueueFamilyProperties().size(), supportFilter); if (result != VK_SUCCESS || supportFilter.size() == 0) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not get physical device surface support."); return VK_FALSE; } // uint32_t queueFamilyIndex; if (!vkts::queueGetFamilyIndex(physicalDevice->getAllQueueFamilyProperties(), VK_QUEUE_GRAPHICS_BIT, 0, &supportFilter, queueFamilyIndex)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not find queue family index."); return VK_FALSE; } // float queuePriorities[1] = {0.0f}; VkDeviceQueueCreateInfo deviceQueueCreateInfo; memset(&deviceQueueCreateInfo, 0, sizeof(VkDeviceQueueCreateInfo)); deviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; deviceQueueCreateInfo.flags = 0; deviceQueueCreateInfo.queueFamilyIndex = 0; deviceQueueCreateInfo.queueCount = 1; deviceQueueCreateInfo.pQueuePriorities = queuePriorities; device = vkts::deviceCreate(physicalDevice->getPhysicalDevice(), 0, 1, &deviceQueueCreateInfo, 0, nullptr, vkts::extensionGetNeededDeviceExtensionCount(), vkts::extensionGetNeededDeviceExtensionNames(), nullptr); if (!device.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Test: Could not create device."); return VK_FALSE; } if (!vkts::wsiInitDeviceExtensions(device->getDevice())) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not initialize device extension."); return VK_FALSE; } // queue = vkts::queueGet(device->getDevice(), queueFamilyIndex, 0); if (!queue.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not get device queue."); return VK_FALSE; } // commandPool = vkts::commandPoolCreate(device->getDevice(), 0, queue->getQueueFamilyIndex()); if (!commandPool.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not get command pool."); return VK_FALSE; } // imageAcquiredSemaphore = vkts::semaphoreCreate(device->getDevice(), 0); if (!imageAcquiredSemaphore.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create semaphore."); return VK_FALSE; } renderingCompleteSemaphore = vkts::semaphoreCreate(device->getDevice(), 0); if (!renderingCompleteSemaphore.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create semaphore."); return VK_FALSE; } // if (!buildVertexBuffer()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build vertex buffer."); return VK_FALSE; } if (!buildShader()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build shader."); return VK_FALSE; } if (!buildPipelineCache()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build pipeline cache."); return VK_FALSE; } if (!buildPipelineLayout()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build pipeline layout."); return VK_FALSE; } // if (!buildResources(updateContext)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build resources."); return VK_FALSE; } return VK_TRUE; }
VkBool32 Example::buildResources( const vkts::IUpdateThreadContext& updateContext) { VkResult result; // glm::uvec2 dimension = updateContext.getWindowDimension(windowIndex); VkExtent2D extent2D = { dimension.x, dimension.y }; // auto lastSwapchain = swapchain; VkSwapchainKHR oldSwapchain = lastSwapchain.get() ? lastSwapchain->getSwapchain() : VK_NULL_HANDLE; swapchain = vkts::wsiSwapchainCreate(physicalDevice->getPhysicalDevice(), device->getDevice(), 0, surface->getSurface(), VKTS_NUMBER_BUFFERS, extent2D, 1, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_SHARING_MODE_EXCLUSIVE, 0, nullptr, VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, VK_TRUE, oldSwapchain); if (!swapchain.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create swap chain."); return VK_FALSE; } // swapchainImagesCount = (uint32_t)swapchain->getAllSwapchainImages().size(); if (swapchainImagesCount == 0) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not get swap chain images count."); return VK_FALSE; } swapchainImageView = vkts::SmartPointerVector<vkts::IImageViewSP>(swapchainImagesCount); framebuffer = vkts::SmartPointerVector<vkts::IFramebufferSP>(swapchainImagesCount); cmdBuffer = vkts::SmartPointerVector<vkts::ICommandBuffersSP>(swapchainImagesCount); // if (lastSwapchain.get()) { lastSwapchain->destroy(); } // if (!buildRenderPass()) { return VK_FALSE; } if (!buildPipeline()) { return VK_FALSE; } // vkts::IImageSP stageImage; vkts::IDeviceMemorySP stageDeviceMemoryImage; vkts::ICommandBuffersSP updateCmdBuffer = vkts::commandBuffersCreate(device->getDevice(), commandPool->getCmdPool(), VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); if (!updateCmdBuffer.get()) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not create command buffer."); return VK_FALSE; } result = updateCmdBuffer->beginCommandBuffer(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, VK_NULL_HANDLE, 0, VK_NULL_HANDLE, VK_FALSE, 0, 0); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not begin command buffer."); return VK_FALSE; } for (uint32_t index = 0; index < swapchain->getMinImageCount(); index++) { swapchain->cmdPipelineBarrier(updateCmdBuffer->getCommandBuffer(), 0, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, index); } VkBool32 doUpdateDescriptorSets = VK_FALSE; if (!image.get()) { if (!buildTexture(updateCmdBuffer, stageImage, stageDeviceMemoryImage)) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not build texture."); return VK_FALSE; } doUpdateDescriptorSets = VK_TRUE; } result = updateCmdBuffer->endCommandBuffer(); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not end command buffer."); return VK_FALSE; } VkSubmitInfo submitInfo; memset(&submitInfo, 0, sizeof(VkSubmitInfo)); submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.waitSemaphoreCount = 0; submitInfo.pWaitSemaphores = nullptr; submitInfo.commandBufferCount = updateCmdBuffer->getCommandBufferCount(); submitInfo.pCommandBuffers = updateCmdBuffer->getCommandBuffers(); submitInfo.signalSemaphoreCount = 0; submitInfo.pSignalSemaphores = nullptr; result = queue->submit(1, &submitInfo, VK_NULL_HANDLE); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not submit queue."); return VK_FALSE; } result = queue->waitIdle(); if (result != VK_SUCCESS) { vkts::logPrint(VKTS_LOG_ERROR, "Example: Could not wait for idle queue."); return VK_FALSE; } updateCmdBuffer->destroy(); if (stageImage.get() || stageDeviceMemoryImage.get()) { destroyTexture(stageImage, stageDeviceMemoryImage); } // if (doUpdateDescriptorSets) { if (!updateDescriptorSets()) { return VK_FALSE; } } for (int32_t i = 0; i < (int32_t)swapchainImagesCount; i++) { if (!buildSwapchainImageView(i)) { return VK_FALSE; } if (!buildFramebuffer(i)) { return VK_FALSE; } if (!buildCmdBuffer(i)) { return VK_FALSE; } } return VK_TRUE; }