Vulkan renderer backend (#2564)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bart Louwers <bart.louwers@gmail.com>
This commit is contained in:
48
platform/default/include/mbgl/vulkan/headless_backend.hpp
Normal file
48
platform/default/include/mbgl/vulkan/headless_backend.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/headless_backend.hpp>
|
||||
#include <mbgl/vulkan/renderer_backend.hpp>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
namespace mbgl {
|
||||
namespace vulkan {
|
||||
|
||||
class Texture2D;
|
||||
|
||||
class HeadlessBackend final : public vulkan::RendererBackend, public gfx::HeadlessBackend {
|
||||
public:
|
||||
HeadlessBackend(Size = {256, 256},
|
||||
SwapBehaviour = SwapBehaviour::NoFlush,
|
||||
gfx::ContextMode = gfx::ContextMode::Unique);
|
||||
~HeadlessBackend() override;
|
||||
gfx::Renderable& getDefaultRenderable() override;
|
||||
PremultipliedImage readStillImage() override;
|
||||
RendererBackend* getRendererBackend() override;
|
||||
|
||||
void swap();
|
||||
|
||||
class Impl {
|
||||
public:
|
||||
virtual ~Impl() = default;
|
||||
virtual bool glNeedsActiveContextOnDestruction() const { return false; }
|
||||
virtual void activateContext() {}
|
||||
virtual void deactivateContext() {}
|
||||
virtual void getContext() {}
|
||||
};
|
||||
|
||||
private:
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
void createImpl();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Impl> impl;
|
||||
bool active = false;
|
||||
|
||||
std::unique_ptr<Texture2D> texture;
|
||||
};
|
||||
|
||||
} // namespace vulkan
|
||||
} // namespace mbgl
|
||||
113
platform/default/src/mbgl/vulkan/headless_backend.cpp
Normal file
113
platform/default/src/mbgl/vulkan/headless_backend.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
#include <mbgl/vulkan/headless_backend.hpp>
|
||||
#include <mbgl/vulkan/renderable_resource.hpp>
|
||||
#include <mbgl/vulkan/context.hpp>
|
||||
#include <mbgl/vulkan/texture2d.hpp>
|
||||
#include <mbgl/gfx/backend_scope.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
namespace mbgl {
|
||||
namespace vulkan {
|
||||
|
||||
class HeadlessRenderableResource final : public vulkan::SurfaceRenderableResource {
|
||||
public:
|
||||
HeadlessRenderableResource(HeadlessBackend& backend_)
|
||||
: SurfaceRenderableResource(backend_) {
|
||||
if (backend_.getDevice() && !renderPass) {
|
||||
init(backend_.getSize().width, backend_.getSize().height);
|
||||
}
|
||||
}
|
||||
|
||||
~HeadlessRenderableResource() noexcept override = default;
|
||||
|
||||
void createPlatformSurface() override {}
|
||||
void bind() override {}
|
||||
};
|
||||
|
||||
HeadlessBackend::HeadlessBackend(const Size size_,
|
||||
gfx::HeadlessBackend::SwapBehaviour,
|
||||
const gfx::ContextMode contextMode_)
|
||||
: mbgl::vulkan::RendererBackend(contextMode_),
|
||||
mbgl::gfx::HeadlessBackend(size_) {
|
||||
init();
|
||||
}
|
||||
|
||||
HeadlessBackend::~HeadlessBackend() {
|
||||
gfx::BackendScope guard{*this, gfx::BackendScope::ScopeType::Implicit};
|
||||
|
||||
texture.reset();
|
||||
|
||||
// Explicitly reset the renderable resource
|
||||
resource.reset();
|
||||
// Explicitly reset the context so that it is destructed and cleaned up
|
||||
// before we destruct the impl object.
|
||||
getThreadPool().runRenderJobs(true /* closeQueue */);
|
||||
context.reset();
|
||||
}
|
||||
|
||||
void HeadlessBackend::activate() {
|
||||
active = true;
|
||||
|
||||
if (!impl) {
|
||||
createImpl();
|
||||
}
|
||||
|
||||
assert(impl);
|
||||
}
|
||||
|
||||
void HeadlessBackend::deactivate() {
|
||||
assert(impl);
|
||||
active = false;
|
||||
}
|
||||
|
||||
gfx::Renderable& HeadlessBackend::getDefaultRenderable() {
|
||||
if (!resource) {
|
||||
resource = std::make_unique<HeadlessRenderableResource>(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void HeadlessBackend::swap() {
|
||||
static_cast<Context&>(*context).waitFrame();
|
||||
}
|
||||
|
||||
PremultipliedImage HeadlessBackend::readStillImage() {
|
||||
auto& contextImpl = static_cast<Context&>(*context);
|
||||
auto& resourceImpl = static_cast<HeadlessRenderableResource&>(*resource);
|
||||
|
||||
if (!texture) {
|
||||
texture = std::make_unique<Texture2D>(contextImpl);
|
||||
texture->setFormat(gfx::TexturePixelType::RGBA, gfx::TextureChannelDataType::UnsignedByte);
|
||||
texture->setSize(size);
|
||||
texture->setUsage(Texture2DUsage::Read);
|
||||
}
|
||||
|
||||
contextImpl.waitFrame();
|
||||
texture->copyImage(resourceImpl.getAcquiredImage());
|
||||
|
||||
return std::move(*texture->readImage());
|
||||
}
|
||||
|
||||
RendererBackend* HeadlessBackend::getRendererBackend() {
|
||||
return this;
|
||||
}
|
||||
|
||||
void HeadlessBackend::createImpl() {
|
||||
assert(!impl);
|
||||
impl = std::make_unique<Impl>();
|
||||
}
|
||||
|
||||
} // namespace vulkan
|
||||
|
||||
namespace gfx {
|
||||
|
||||
template <>
|
||||
std::unique_ptr<gfx::HeadlessBackend> Backend::Create<gfx::Backend::Type::Vulkan>(
|
||||
const Size size, gfx::Renderable::SwapBehaviour swapBehavior, const gfx::ContextMode contextMode) {
|
||||
return std::make_unique<vulkan::HeadlessBackend>(size, swapBehavior, contextMode);
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mbgl
|
||||
Reference in New Issue
Block a user