Add Android Vulkan backend (#2711)

Co-authored-by: Bart Louwers <bart.louwers@gmail.com>
This commit is contained in:
Adrian Cojocaru
2024-09-06 17:40:57 +03:00
committed by GitHub
parent 4b5d06d908
commit ea09bdf2b6
79 changed files with 2580 additions and 1400 deletions

View File

@@ -135,7 +135,8 @@ void Context::submitOneTimeCommand(const std::function<void(const vk::UniqueComm
const vk::CommandBufferAllocateInfo allocateInfo(
backend.getCommandPool().get(), vk::CommandBufferLevel::ePrimary, 1);
const auto& commandBuffers = backend.getDevice()->allocateCommandBuffersUnique(allocateInfo);
const auto& device = backend.getDevice();
const auto& commandBuffers = device->allocateCommandBuffersUnique(allocateInfo);
auto& commandBuffer = commandBuffers.front();
backend.setDebugName(commandBuffer.get(), "OneTimeSubmitCommandBuffer");
@@ -146,8 +147,14 @@ void Context::submitOneTimeCommand(const std::function<void(const vk::UniqueComm
const auto submitInfo = vk::SubmitInfo().setCommandBuffers(commandBuffer.get());
backend.getGraphicsQueue().submit(submitInfo);
backend.getDevice()->waitIdle();
const auto& fence = device->createFenceUnique(vk::FenceCreateInfo(vk::FenceCreateFlags()));
backend.getGraphicsQueue().submit(submitInfo, fence.get());
constexpr uint64_t timeout = std::numeric_limits<uint64_t>::max();
const vk::Result waitFenceResult = device->waitForFences(1, &fence.get(), VK_TRUE, timeout);
if (waitFenceResult != vk::Result::eSuccess) {
mbgl::Log::Error(mbgl::Event::Render, "OneTimeCommand - Wait fence failed");
}
}
void Context::waitFrame() const {
@@ -161,10 +168,27 @@ void Context::waitFrame() const {
}
}
void Context::beginFrame() {
backend.startFrameCapture();
const auto& device = backend.getDevice();
auto& renderableResource = backend.getDefaultRenderable().getResource<SurfaceRenderableResource>();
const auto& platformSurface = renderableResource.getPlatformSurface();
if (platformSurface && surfaceUpdateRequested) {
renderableResource.recreateSwapchain();
// we wait for an idle device to recreate the swapchain
// so it's a good opportunity to delete all queued items
for (auto& frame : frameResources) {
device->resetDescriptorPool(frame.descriptorPool.get());
frame.runDeletionQueue(*this);
}
// sync resources with swapchain
frameResourceIndex = 0;
surfaceUpdateRequested = false;
}
backend.startFrameCapture();
auto& frame = frameResources[frameResourceIndex];
constexpr uint64_t timeout = std::numeric_limits<uint64_t>::max();
@@ -173,18 +197,26 @@ void Context::beginFrame() {
device->resetDescriptorPool(getCurrentDescriptorPool().get());
frame.runDeletionQueue(*this);
if (renderableResource.getPlatformSurface()) {
if (platformSurface) {
try {
const vk::ResultValue acquireImageResult = device->acquireNextImageKHR(
renderableResource.getSwapchain().get(), timeout, frame.surfaceSemaphore.get(), nullptr);
if (acquireImageResult.result == vk::Result::eSuccess)
if (acquireImageResult.result == vk::Result::eSuccess) {
renderableResource.setAcquiredImageIndex(acquireImageResult.value);
else if (acquireImageResult.result == vk::Result::eSuboptimalKHR)
renderableResource.recreateSwapchain();
} else if (acquireImageResult.result == vk::Result::eSuboptimalKHR) {
renderableResource.setAcquiredImageIndex(acquireImageResult.value);
// TODO implement pre-rotation transform for surface orientation
// requestSurfaceUpdate();
// beginFrame();
// return;
}
} catch (const vk::OutOfDateKHRError& e) {
renderableResource.recreateSwapchain();
// request an update and restart frame
requestSurfaceUpdate();
beginFrame();
return;
}
} else {
renderableResource.setAcquiredImageIndex(frameResourceIndex);
@@ -197,18 +229,23 @@ void Context::beginFrame() {
}
void Context::endFrame() {
frameResourceIndex = (frameResourceIndex + 1) % frameResources.size();
}
void Context::submitFrame() {
const auto& frame = frameResources[frameResourceIndex];
frame.commandBuffer->end();
const auto& device = backend.getDevice();
const auto& graphicsQueue = backend.getGraphicsQueue();
auto& renderableResource = backend.getDefaultRenderable().getResource<SurfaceRenderableResource>();
const auto& platformSurface = renderableResource.getPlatformSurface();
// submit frame commands
const vk::PipelineStageFlags waitStageMask[] = {vk::PipelineStageFlagBits::eColorAttachmentOutput};
auto submitInfo = vk::SubmitInfo().setCommandBuffers(frame.commandBuffer.get());
if (renderableResource.getPlatformSurface()) {
if (platformSurface) {
submitInfo.setSignalSemaphores(frame.frameSemaphore.get())
.setWaitSemaphores(frame.surfaceSemaphore.get())
.setWaitDstStageMask(waitStageMask);
@@ -222,7 +259,7 @@ void Context::endFrame() {
graphicsQueue.submit(submitInfo, frame.flightFrameFence.get());
// present rendered frame
if (renderableResource.getPlatformSurface()) {
if (platformSurface) {
const auto acquiredImage = renderableResource.getAcquiredImageIndex();
const auto presentInfo = vk::PresentInfoKHR()
.setSwapchains(renderableResource.getSwapchain().get())
@@ -232,14 +269,15 @@ void Context::endFrame() {
try {
const auto& presentQueue = backend.getPresentQueue();
const vk::Result presentResult = presentQueue.presentKHR(presentInfo);
if (presentResult == vk::Result::eSuboptimalKHR) renderableResource.recreateSwapchain();
if (presentResult == vk::Result::eSuboptimalKHR) {
// TODO implement pre-rotation transform for surface orientation
// requestSurfaceUpdate();
}
} catch (const vk::OutOfDateKHRError& e) {
renderableResource.recreateSwapchain();
requestSurfaceUpdate();
}
}
frameResourceIndex = (frameResourceIndex + 1) % frameResources.size();
backend.endFrameCapture();
}
@@ -419,7 +457,7 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,
const auto& pipeline = shaderImpl.getPipeline(clipping.pipelineInfo);
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.get());
clipping.pipelineInfo.setDynamicValues(commandBuffer);
clipping.pipelineInfo.setDynamicValues(backend, commandBuffer);
const std::array<vk::Buffer, 1> vertexBuffers = {clipping.vertexBuffer->getVulkanBuffer()};
const std::array<vk::DeviceSize, 1> offset = {0};