Add Android Vulkan backend (#2711)
Co-authored-by: Bart Louwers <bart.louwers@gmail.com>
This commit is contained in:
@@ -15,11 +15,8 @@
|
||||
#include <mbgl/geometry/feature_index.hpp>
|
||||
#include <mbgl/gfx/backend_scope.hpp>
|
||||
#include <mbgl/gfx/renderer_backend.hpp>
|
||||
#include <mbgl/gl/context.hpp>
|
||||
#include <mbgl/gl/renderable_resource.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
#include <mbgl/math/angles.hpp>
|
||||
#include <mbgl/platform/gl_functions.hpp>
|
||||
#include <mbgl/renderer/bucket.hpp>
|
||||
#include <mbgl/renderer/layers/render_location_indicator_layer.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
@@ -29,11 +26,25 @@
|
||||
#include <mbgl/util/mat4.hpp>
|
||||
|
||||
#include <mapbox/eternal.hpp>
|
||||
#include <mbgl/renderer/image_manager.hpp>
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
|
||||
#include <mbgl/platform/gl_functions.hpp>
|
||||
#include <mbgl/gl/context.hpp>
|
||||
#include <mbgl/gl/renderable_resource.hpp>
|
||||
#include <mbgl/gl/defines.hpp>
|
||||
#include <mbgl/gl/texture.hpp>
|
||||
#include <mbgl/gl/texture_resource.hpp>
|
||||
#include <mbgl/gl/types.hpp>
|
||||
#include <mbgl/renderer/image_manager.hpp>
|
||||
|
||||
#else
|
||||
|
||||
#define MBGL_CHECK_ERROR(x) \
|
||||
while (0) { \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#include <numbers>
|
||||
|
||||
@@ -75,6 +86,7 @@ struct LocationIndicatorRenderParameters {
|
||||
std::string puckHatImagePath;
|
||||
};
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
class RenderLocationIndicatorImpl {
|
||||
protected:
|
||||
struct vec2 {
|
||||
@@ -756,6 +768,25 @@ public:
|
||||
};
|
||||
|
||||
bool RenderLocationIndicatorImpl::anisotropicFilteringAvailable = false;
|
||||
#else
|
||||
|
||||
class RenderLocationIndicatorImpl {
|
||||
public:
|
||||
RenderLocationIndicatorImpl(std::string) {}
|
||||
|
||||
void release() {}
|
||||
void updateFeature() {}
|
||||
void updatePuckGeometry([[maybe_unused]] const mbgl::LocationIndicatorRenderParameters& params) {}
|
||||
|
||||
public:
|
||||
mbgl::LocationIndicatorRenderParameters parameters;
|
||||
std::shared_ptr<mbgl::Feature> feature;
|
||||
std::shared_ptr<mapbox::geometry::polygon<int64_t>> featureEnvelope;
|
||||
static bool anisotropicFilteringAvailable;
|
||||
};
|
||||
|
||||
bool RenderLocationIndicatorImpl::anisotropicFilteringAvailable = false;
|
||||
#endif
|
||||
|
||||
using namespace style;
|
||||
namespace {
|
||||
@@ -845,6 +876,7 @@ void RenderLocationIndicatorLayer::prepare(const LayerPrepareParameters& p) {
|
||||
renderImpl->updatePuckGeometry(renderImpl->parameters);
|
||||
}
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
void RenderLocationIndicatorLayer::render(PaintParameters& paintParameters) {
|
||||
auto& glContext = static_cast<gl::Context&>(paintParameters.context);
|
||||
|
||||
@@ -863,6 +895,8 @@ void RenderLocationIndicatorLayer::render(PaintParameters& paintParameters) {
|
||||
glContext.setDirtyState();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void RenderLocationIndicatorLayer::populateDynamicRenderFeatureIndex(DynamicFeatureIndex& index) const {
|
||||
renderImpl->updateFeature();
|
||||
if (!renderImpl->featureEnvelope->empty()) index.insert(renderImpl->feature, renderImpl->featureEnvelope);
|
||||
|
||||
@@ -20,7 +20,10 @@ private:
|
||||
void markContextDestroyed() override;
|
||||
void prepare(const LayerPrepareParameters &) override;
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
void render(PaintParameters &) override;
|
||||
#endif
|
||||
|
||||
void populateDynamicRenderFeatureIndex(DynamicFeatureIndex &) const override;
|
||||
|
||||
bool contextDestroyed = false;
|
||||
|
||||
@@ -28,6 +28,13 @@
|
||||
#include <mbgl/renderer/layer_tweaker.hpp>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL || (MLN_RENDER_BACKEND_VULKAN && defined(__ANDROID__))
|
||||
#define MLN_ENABLE_POLYLINE_DRAWABLES 1
|
||||
#else
|
||||
#define MLN_ENABLE_POLYLINE_DRAWABLES 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
namespace mbgl {
|
||||
@@ -81,7 +88,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr
|
||||
return builder;
|
||||
}();
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
#if MLN_ENABLE_POLYLINE_DRAWABLES
|
||||
// initialize polyline builder
|
||||
gfx::ShaderPtr polylineShader;
|
||||
const auto createPolylineShader = [&]() -> gfx::ShaderPtr {
|
||||
@@ -185,7 +192,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr
|
||||
}
|
||||
};
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
#if MLN_ENABLE_POLYLINE_DRAWABLES
|
||||
// function to add polylines drawable
|
||||
const auto addPolylineDrawable = [&](TileLayerGroup* tileLayerGroup, const RenderTile& tile) {
|
||||
class PolylineDrawableTweaker : public gfx::DrawableTweaker {
|
||||
@@ -364,7 +371,7 @@ void TileSourceRenderItem::updateDebugDrawables(DebugLayerGroupMap& debugLayerGr
|
||||
0,
|
||||
0};
|
||||
if (0 == updateDrawables(tileLayerGroup, tileID, debugUBO) && tile.getNeedsRendering()) {
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
#if MLN_ENABLE_POLYLINE_DRAWABLES
|
||||
addPolylineDrawable(tileLayerGroup, tile);
|
||||
#else
|
||||
addDrawable(tileLayerGroup,
|
||||
|
||||
@@ -8,7 +8,7 @@ const std::array<UniformBlockInfo, 2> ShaderSource<BuiltIn::BackgroundShader, gf
|
||||
UniformBlockInfo{false, true, sizeof(BackgroundLayerUBO), idBackgroundLayerUBO},
|
||||
};
|
||||
const std::array<AttributeInfo, 1> ShaderSource<BuiltIn::BackgroundShader, gfx::Backend::Type::Vulkan>::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Float3, idBackgroundPosVertexAttribute},
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, idBackgroundPosVertexAttribute},
|
||||
};
|
||||
|
||||
const std::array<UniformBlockInfo, 3>
|
||||
@@ -19,7 +19,7 @@ const std::array<UniformBlockInfo, 3>
|
||||
};
|
||||
const std::array<AttributeInfo, 1>
|
||||
ShaderSource<BuiltIn::BackgroundPatternShader, gfx::Backend::Type::Vulkan>::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Float3, idBackgroundPosVertexAttribute},
|
||||
AttributeInfo{0, gfx::AttributeDataType::Short2, idBackgroundPosVertexAttribute},
|
||||
};
|
||||
const std::array<TextureInfo, 1> ShaderSource<BuiltIn::BackgroundPatternShader, gfx::Backend::Type::Vulkan>::textures =
|
||||
{TextureInfo{0, idBackgroundImageTexture}};
|
||||
|
||||
@@ -185,7 +185,7 @@ const vk::UniquePipeline& ShaderProgram::getPipeline(const PipelineInfo& pipelin
|
||||
// vk::DynamicState::eDepthBias,
|
||||
// vk::DynamicState::eDepthBounds,
|
||||
|
||||
const auto& dynamicValues = pipelineInfo.getDynamicStates();
|
||||
const auto& dynamicValues = pipelineInfo.getDynamicStates(backend);
|
||||
const vk::PipelineDynamicStateCreateInfo dynamicState({}, dynamicValues);
|
||||
|
||||
const auto& device = backend.getDevice();
|
||||
|
||||
22
src/mbgl/shaders/vulkan/widevector.cpp
Normal file
22
src/mbgl/shaders/vulkan/widevector.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <mbgl/shaders/vulkan/widevector.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace shaders {
|
||||
|
||||
const std::array<UniformBlockInfo, 2> ShaderSource<BuiltIn::WideVectorShader, gfx::Backend::Type::Vulkan>::uniforms = {
|
||||
UniformBlockInfo{true, false, sizeof(WideVectorUniformsUBO), idWideVectorUniformsUBO},
|
||||
UniformBlockInfo{true, false, sizeof(WideVectorUniformWideVecUBO), idWideVectorUniformWideVecUBO},
|
||||
};
|
||||
const std::array<AttributeInfo, 3> ShaderSource<BuiltIn::WideVectorShader, gfx::Backend::Type::Vulkan>::attributes = {
|
||||
AttributeInfo{0, gfx::AttributeDataType::Float3, idWideVectorScreenPos},
|
||||
AttributeInfo{1, gfx::AttributeDataType::Float4, idWideVectorColor},
|
||||
AttributeInfo{2, gfx::AttributeDataType::Int, idWideVectorIndex}};
|
||||
const std::array<AttributeInfo, 4>
|
||||
ShaderSource<BuiltIn::WideVectorShader, gfx::Backend::Type::Vulkan>::instanceAttributes = {
|
||||
AttributeInfo{3, gfx::AttributeDataType::Float3, idWideVectorInstanceCenter},
|
||||
AttributeInfo{4, gfx::AttributeDataType::Float4, idWideVectorInstanceColor},
|
||||
AttributeInfo{5, gfx::AttributeDataType::Int, idWideVectorInstancePrevious},
|
||||
AttributeInfo{6, gfx::AttributeDataType::Int, idWideVectorInstanceNext}};
|
||||
|
||||
} // namespace shaders
|
||||
} // namespace mbgl
|
||||
@@ -10,19 +10,27 @@ namespace mbgl {
|
||||
namespace vulkan {
|
||||
|
||||
bool BufferAllocation::create(const VmaAllocationCreateInfo& allocInfo, const vk::BufferCreateInfo& bufferInfo) {
|
||||
VkResult result = vmaCreateBuffer(
|
||||
allocator, reinterpret_cast<const VkBufferCreateInfo*>(&bufferInfo), &allocInfo, &buffer, &allocation, nullptr);
|
||||
VkBuffer buffer_;
|
||||
VkResult result = vmaCreateBuffer(allocator,
|
||||
reinterpret_cast<const VkBufferCreateInfo*>(&bufferInfo),
|
||||
&allocInfo,
|
||||
&buffer_,
|
||||
&allocation,
|
||||
nullptr);
|
||||
|
||||
if (result != VK_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer = vk::Buffer(buffer_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BufferAllocation::destroy() {
|
||||
if (mappedBuffer) vmaUnmapMemory(allocator, allocation);
|
||||
vmaDestroyBuffer(allocator, buffer, allocation);
|
||||
vmaDestroyBuffer(allocator, VkBuffer(buffer), allocation);
|
||||
|
||||
buffer = nullptr;
|
||||
mappedBuffer = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,9 @@ std::unique_ptr<gfx::RenderPass> CommandEncoder::createRenderPass(const char* na
|
||||
return std::make_unique<RenderPass>(*this, name, descriptor);
|
||||
}
|
||||
|
||||
void CommandEncoder::present(gfx::Renderable&) {}
|
||||
void CommandEncoder::present(gfx::Renderable& renderable) {
|
||||
renderable.getResource<RenderableResource>().swap();
|
||||
}
|
||||
|
||||
void CommandEncoder::pushDebugGroup(const char* name) {
|
||||
pushDebugGroup(name, {});
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -247,7 +247,7 @@ void Drawable::draw(PaintParameters& parameters) const {
|
||||
// update pipeline info with per segment modifiers
|
||||
impl->pipelineInfo.setDrawMode(seg->getMode());
|
||||
|
||||
impl->pipelineInfo.setDynamicValues(commandBuffer);
|
||||
impl->pipelineInfo.setDynamicValues(context.getBackend(), commandBuffer);
|
||||
|
||||
const auto& pipeline = shaderImpl.getPipeline(impl->pipelineInfo);
|
||||
commandBuffer->bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline.get());
|
||||
|
||||
@@ -9,37 +9,37 @@ namespace vulkan {
|
||||
vk::Format PipelineInfo::vulkanFormat(const gfx::AttributeDataType& value) {
|
||||
switch (value) {
|
||||
case gfx::AttributeDataType::Byte:
|
||||
return vk::Format::eR8Sscaled;
|
||||
return vk::Format::eR8Sint;
|
||||
case gfx::AttributeDataType::Byte2:
|
||||
return vk::Format::eR8G8Sscaled;
|
||||
return vk::Format::eR8G8Sint;
|
||||
case gfx::AttributeDataType::Byte3:
|
||||
return vk::Format::eR8G8B8Sscaled;
|
||||
return vk::Format::eR8G8B8Sint;
|
||||
case gfx::AttributeDataType::Byte4:
|
||||
return vk::Format::eR8G8B8A8Sscaled;
|
||||
return vk::Format::eR8G8B8A8Sint;
|
||||
case gfx::AttributeDataType::UByte:
|
||||
return vk::Format::eR8Uscaled;
|
||||
return vk::Format::eR8Uint;
|
||||
case gfx::AttributeDataType::UByte2:
|
||||
return vk::Format::eR8G8Uscaled;
|
||||
return vk::Format::eR8G8Uint;
|
||||
case gfx::AttributeDataType::UByte3:
|
||||
return vk::Format::eR8G8B8Uscaled;
|
||||
return vk::Format::eR8G8B8Uint;
|
||||
case gfx::AttributeDataType::UByte4:
|
||||
return vk::Format::eR8G8B8A8Uscaled;
|
||||
return vk::Format::eR8G8B8A8Uint;
|
||||
case gfx::AttributeDataType::Short:
|
||||
return vk::Format::eR16Sscaled;
|
||||
return vk::Format::eR16Sint;
|
||||
case gfx::AttributeDataType::Short2:
|
||||
return vk::Format::eR16G16Sscaled;
|
||||
return vk::Format::eR16G16Sint;
|
||||
case gfx::AttributeDataType::Short3:
|
||||
return vk::Format::eR16G16B16Sscaled;
|
||||
return vk::Format::eR16G16B16Sint;
|
||||
case gfx::AttributeDataType::Short4:
|
||||
return vk::Format::eR16G16B16A16Sscaled;
|
||||
return vk::Format::eR16G16B16A16Sint;
|
||||
case gfx::AttributeDataType::UShort:
|
||||
return vk::Format::eR16Uscaled;
|
||||
return vk::Format::eR16Uint;
|
||||
case gfx::AttributeDataType::UShort2:
|
||||
return vk::Format::eR16G16Uscaled;
|
||||
return vk::Format::eR16G16Uint;
|
||||
case gfx::AttributeDataType::UShort3:
|
||||
return vk::Format::eR16G16B16Uscaled;
|
||||
return vk::Format::eR16G16B16Uint;
|
||||
case gfx::AttributeDataType::UShort4:
|
||||
return vk::Format::eR16G16B16A16Uscaled;
|
||||
return vk::Format::eR16G16B16A16Uint;
|
||||
case gfx::AttributeDataType::Int:
|
||||
return vk::Format::eR32Sint;
|
||||
case gfx::AttributeDataType::Int2:
|
||||
@@ -401,7 +401,7 @@ std::size_t PipelineInfo::hash() const {
|
||||
vertexInputHash);
|
||||
}
|
||||
|
||||
void PipelineInfo::setDynamicValues(const vk::UniqueCommandBuffer& buffer) const {
|
||||
void PipelineInfo::setDynamicValues(const RendererBackend& backend, const vk::UniqueCommandBuffer& buffer) const {
|
||||
if (dynamicValues.blendConstants.has_value()) {
|
||||
buffer->setBlendConstants(dynamicValues.blendConstants.value().data());
|
||||
}
|
||||
@@ -412,12 +412,12 @@ void PipelineInfo::setDynamicValues(const vk::UniqueCommandBuffer& buffer) const
|
||||
buffer->setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack, dynamicValues.stencilRef);
|
||||
}
|
||||
|
||||
if (wideLines) {
|
||||
if (backend.getDeviceFeatures().wideLines && wideLines) {
|
||||
buffer->setLineWidth(dynamicValues.lineWidth);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<vk::DynamicState> PipelineInfo::getDynamicStates() const {
|
||||
std::vector<vk::DynamicState> PipelineInfo::getDynamicStates(const RendererBackend& backend) const {
|
||||
std::vector<vk::DynamicState> dynamicStates;
|
||||
|
||||
if (usesBlendConstants()) {
|
||||
@@ -430,7 +430,7 @@ std::vector<vk::DynamicState> PipelineInfo::getDynamicStates() const {
|
||||
dynamicStates.push_back(vk::DynamicState::eStencilReference);
|
||||
}
|
||||
|
||||
if (wideLines) {
|
||||
if (backend.getDeviceFeatures().wideLines && wideLines) {
|
||||
dynamicStates.push_back(vk::DynamicState::eLineWidth);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ void SurfaceRenderableResource::initColor(uint32_t w, uint32_t h) {
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceRenderableResource::initSwapchain(uint32_t w, uint32_t h) {
|
||||
void SurfaceRenderableResource::initSwapchain(uint32_t w, uint32_t h, vk::PresentModeKHR presentMode) {
|
||||
const auto& physicalDevice = backend.getPhysicalDevice();
|
||||
const auto& device = backend.getDevice();
|
||||
|
||||
@@ -83,7 +83,16 @@ void SurfaceRenderableResource::initSwapchain(uint32_t w, uint32_t h) {
|
||||
if (formatIt == formats.end()) throw std::runtime_error("No suitable swapchain format found");
|
||||
|
||||
// only vk::PresentModeKHR::eFifo (vsync on) is guaranteed
|
||||
// TODO check for vk::PresentModeKHR::eImmediate when uncapped
|
||||
if (presentMode != vk::PresentModeKHR::eFifo) {
|
||||
const std::vector<vk::PresentModeKHR>& presentModes = physicalDevice.getSurfacePresentModesKHR(surface.get());
|
||||
if (std::find(presentModes.begin(), presentModes.end(), presentMode) == presentModes.end()) {
|
||||
mbgl::Log::Error(
|
||||
mbgl::Event::Render,
|
||||
"Requested PresentModeKHR not available (" + std::to_string(static_cast<int>(presentMode)) + ")");
|
||||
|
||||
presentMode = vk::PresentModeKHR::eFifo;
|
||||
}
|
||||
}
|
||||
|
||||
// pick surface size
|
||||
const vk::SurfaceCapabilitiesKHR& capabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface.get());
|
||||
@@ -105,7 +114,7 @@ void SurfaceRenderableResource::initSwapchain(uint32_t w, uint32_t h) {
|
||||
.setMinImageCount(swapchainImageCount)
|
||||
.setImageFormat(formatIt->format)
|
||||
.setImageColorSpace(formatIt->colorSpace)
|
||||
.setPresentMode(vk::PresentModeKHR::eFifo)
|
||||
.setPresentMode(presentMode)
|
||||
.setImageExtent(extent)
|
||||
.setImageArrayLayers(1)
|
||||
.setImageUsage(vk::ImageUsageFlagBits::eColorAttachment);
|
||||
@@ -114,7 +123,7 @@ void SurfaceRenderableResource::initSwapchain(uint32_t w, uint32_t h) {
|
||||
int32_t presentQueueIndex = backend.getPresentQueueIndex();
|
||||
|
||||
if (graphicsQueueIndex != presentQueueIndex) {
|
||||
// TODO if this scenario is widespred and performance is a problem (shouldn't be the case on most hardware)
|
||||
// TODO if this scenario is widespread and performance is a problem (shouldn't be the case on most hardware)
|
||||
// rework to vk::SharingMode::eExclusive + queue ownership
|
||||
swapchainCreateInfo.setImageSharingMode(vk::SharingMode::eConcurrent);
|
||||
const std::array<uint32_t, 2> queueIndices = {static_cast<uint32_t>(graphicsQueueIndex),
|
||||
@@ -124,7 +133,7 @@ void SurfaceRenderableResource::initSwapchain(uint32_t w, uint32_t h) {
|
||||
swapchainCreateInfo.setImageSharingMode(vk::SharingMode::eExclusive);
|
||||
}
|
||||
|
||||
swapchainCreateInfo.setPreTransform(capabilities.currentTransform);
|
||||
swapchainCreateInfo.setPreTransform(vk::SurfaceTransformFlagBitsKHR::eIdentity);
|
||||
swapchainCreateInfo.setClipped(VK_TRUE);
|
||||
|
||||
if (capabilities.supportedCompositeAlpha & vk::CompositeAlphaFlagBitsKHR::eInherit) {
|
||||
@@ -209,6 +218,11 @@ void SurfaceRenderableResource::initDepthStencil() {
|
||||
backend.setDebugName(depthAllocation->imageView.get(), "SwapchainDepthImageView");
|
||||
}
|
||||
|
||||
void SurfaceRenderableResource::swap() {
|
||||
auto& context = static_cast<Context&>(backend.getContext());
|
||||
context.submitFrame();
|
||||
}
|
||||
|
||||
const vk::Image SurfaceRenderableResource::getAcquiredImage() const {
|
||||
if (surface) {
|
||||
return swapchainImages[acquiredImageIndex];
|
||||
@@ -233,8 +247,7 @@ void SurfaceRenderableResource::init(uint32_t w, uint32_t h) {
|
||||
.setViewType(vk::ImageViewType::e2D)
|
||||
.setFormat(colorFormat)
|
||||
.setComponents(vk::ComponentMapping()) // defaults to vk::ComponentSwizzle::eIdentity
|
||||
.setSubresourceRange(
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1));
|
||||
.setSubresourceRange({vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1});
|
||||
|
||||
for (const auto& image : swapchainImages) {
|
||||
imageViewCreateInfo.setImage(image);
|
||||
@@ -267,7 +280,7 @@ void SurfaceRenderableResource::init(uint32_t w, uint32_t h) {
|
||||
.setSamples(vk::SampleCountFlagBits::e1)
|
||||
.setLoadOp(vk::AttachmentLoadOp::eClear)
|
||||
.setStoreOp(vk::AttachmentStoreOp::eDontCare)
|
||||
.setStencilLoadOp(vk::AttachmentLoadOp::eDontCare)
|
||||
.setStencilLoadOp(vk::AttachmentLoadOp::eClear)
|
||||
.setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)
|
||||
.setInitialLayout(vk::ImageLayout::eUndefined)
|
||||
.setFinalLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal);
|
||||
@@ -337,7 +350,7 @@ void SurfaceRenderableResource::recreateSwapchain() {
|
||||
}
|
||||
|
||||
const vk::UniqueFramebuffer& SurfaceRenderableResource::getFramebuffer() const {
|
||||
return swapchainFramebuffers[backend.getContext<Context&>().getCurrentFrameResourceIndex()];
|
||||
return swapchainFramebuffers[acquiredImageIndex];
|
||||
}
|
||||
|
||||
} // namespace vulkan
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <mbgl/shaders/vulkan/line.hpp>
|
||||
#include <mbgl/shaders/vulkan/raster.hpp>
|
||||
#include <mbgl/shaders/vulkan/symbol.hpp>
|
||||
#include <mbgl/shaders/vulkan/widevector.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
@@ -443,13 +444,15 @@ void RendererBackend::initDevice() {
|
||||
|
||||
const auto& queues = candidate.getQueueFamilyProperties();
|
||||
|
||||
// Use to test on specific GPU type (if multiple)
|
||||
// if (candidate.getProperties().deviceType != vk::PhysicalDeviceType::eIntegratedGpu) return false;
|
||||
|
||||
for (auto i = 0u; i < queues.size(); ++i) {
|
||||
const auto& queue = queues[i];
|
||||
|
||||
if (queue.queueCount == 0) continue;
|
||||
|
||||
if (queue.queueFlags & vk::QueueFlagBits::eGraphics) graphicsQueueIndex = i;
|
||||
|
||||
if (surface && candidate.getSurfaceSupportKHR(i, surface)) presentQueueIndex = i;
|
||||
|
||||
if (graphicsQueueIndex != -1 && (!surface || presentQueueIndex != -1)) break;
|
||||
@@ -476,9 +479,9 @@ void RendererBackend::initDevice() {
|
||||
}
|
||||
}
|
||||
|
||||
physicalDeviceProperties = physicalDevice.getProperties();
|
||||
|
||||
if (!physicalDevice) throw std::runtime_error("No suitable GPU found");
|
||||
|
||||
physicalDeviceProperties = physicalDevice.getProperties();
|
||||
};
|
||||
|
||||
pickPhysicalDevice();
|
||||
@@ -492,12 +495,15 @@ void RendererBackend::initDevice() {
|
||||
if (surface && graphicsQueueIndex != presentQueueIndex)
|
||||
queueCreateInfos.emplace_back(vk::DeviceQueueCreateFlags(), presentQueueIndex, 1, &queuePriority);
|
||||
|
||||
const auto& supportedDeviceFeatures = physicalDevice.getFeatures();
|
||||
|
||||
vk::PhysicalDeviceFeatures enabledDeviceFeatures;
|
||||
[[maybe_unused]] const auto& supportedDeviceFeatures = physicalDevice.getFeatures();
|
||||
physicalDeviceFeatures = vk::PhysicalDeviceFeatures();
|
||||
|
||||
// TODO
|
||||
// - WideLines disabled on Android (20.77% device coverage https://vulkan.gpuinfo.org/listfeaturescore10.php)
|
||||
// - Rework this to a dynamic toggle based on MLN_TRIANGULATE_FILL_OUTLINES/MLN_ENABLE_POLYLINE_DRAWABLES
|
||||
#if !defined(__ANDROID__) && !defined(__apple__)
|
||||
if (supportedDeviceFeatures.wideLines) {
|
||||
enabledDeviceFeatures.setWideLines(true);
|
||||
physicalDeviceFeatures.setWideLines(true);
|
||||
|
||||
// more wideLines info
|
||||
// physicalDeviceProperties.limits.lineWidthRange;
|
||||
@@ -505,12 +511,13 @@ void RendererBackend::initDevice() {
|
||||
} else {
|
||||
mbgl::Log::Error(mbgl::Event::Render, "Wide line support not available");
|
||||
}
|
||||
#endif
|
||||
|
||||
auto createInfo = vk::DeviceCreateInfo()
|
||||
.setQueueCreateInfos(queueCreateInfos)
|
||||
.setEnabledExtensionCount(static_cast<uint32_t>(extensions.size()))
|
||||
.setPpEnabledExtensionNames(extensions.data())
|
||||
.setPEnabledFeatures(&enabledDeviceFeatures);
|
||||
.setPEnabledFeatures(&physicalDeviceFeatures);
|
||||
|
||||
// this is not needed for newer implementations
|
||||
createInfo.setPEnabledLayerNames(layers);
|
||||
@@ -528,11 +535,12 @@ void RendererBackend::initSwapchain() {
|
||||
const auto& renderable = getDefaultRenderable();
|
||||
auto& renderableResource = renderable.getResource<SurfaceRenderableResource>();
|
||||
const auto& size = renderable.getSize();
|
||||
renderableResource.init(size.width, size.height);
|
||||
|
||||
if (renderableResource.getPlatformSurface()) {
|
||||
maxFrames = renderableResource.getImageCount();
|
||||
}
|
||||
// use triple buffering if rendering to a surface
|
||||
// no buffering when using headless
|
||||
maxFrames = renderableResource.getPlatformSurface() ? 3 : 1;
|
||||
|
||||
renderableResource.init(size.width, size.height);
|
||||
}
|
||||
|
||||
void RendererBackend::initCommandPool() {
|
||||
|
||||
@@ -10,19 +10,22 @@ namespace mbgl {
|
||||
namespace vulkan {
|
||||
|
||||
bool ImageAllocation::create(const VmaAllocationCreateInfo& allocInfo, const vk::ImageCreateInfo& imageInfo) {
|
||||
VkImage image_;
|
||||
VkResult result = vmaCreateImage(
|
||||
allocator, reinterpret_cast<const VkImageCreateInfo*>(&imageInfo), &allocInfo, &image, &allocation, nullptr);
|
||||
allocator, reinterpret_cast<const VkImageCreateInfo*>(&imageInfo), &allocInfo, &image_, &allocation, nullptr);
|
||||
|
||||
if (result != VK_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
image = vk::Image(image_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImageAllocation::destroy() {
|
||||
imageView.reset();
|
||||
vmaDestroyImage(allocator, image, allocation);
|
||||
vmaDestroyImage(allocator, VkImage(image), allocation);
|
||||
image = nullptr;
|
||||
}
|
||||
|
||||
void ImageAllocation::setName([[maybe_unused]] const std::string& name) const {
|
||||
|
||||
Reference in New Issue
Block a user