Skip to content

Commit

Permalink
Merge branch 'main' into compile-time-string
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcristici authored Jan 10, 2025
2 parents fe552fc + 57f42d9 commit ee238c7
Show file tree
Hide file tree
Showing 15 changed files with 243 additions and 104 deletions.
14 changes: 9 additions & 5 deletions include/mbgl/vulkan/buffer_resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,18 @@ class BufferResource {
void update(const void* data, std::size_t size, std::size_t offset) noexcept;

std::size_t getSizeInBytes() const noexcept { return size; }
const void* contents() const noexcept { return (raw.empty() ? nullptr : raw.data()); }
const void* contents() const noexcept;
const void* contents(uint8_t resourceIndex) const noexcept;

Context& getContext() const noexcept { return context; }
const vk::Buffer& getVulkanBuffer() const noexcept { return bufferAllocation->buffer; }
std::size_t getVulkanBufferOffset() const noexcept;
std::size_t getVulkanBufferSize() const noexcept;
std::size_t getVulkanBufferOffset(uint8_t resourceIndex) const noexcept;
// update the current sub-buffer with the latest data
void updateVulkanBuffer();
void updateVulkanBuffer(const int8_t destination, const uint8_t source);

bool isValid() const noexcept { return !raw.empty(); }
bool isValid() const noexcept { return !!bufferAllocation; }
operator bool() const noexcept { return isValid(); }
bool operator!() const noexcept { return !isValid(); }

Expand All @@ -69,14 +73,14 @@ class BufferResource {

protected:
Context& context;
std::vector<std::uint8_t> raw;
std::size_t size;
std::uint32_t usage;
std::uint16_t version = 0;
VersionType version = 0;
bool persistent;

SharedBufferAllocation bufferAllocation;
size_t bufferWindowSize = 0;
std::vector<VersionType> bufferWindowVersions;
};

} // namespace vulkan
Expand Down
8 changes: 2 additions & 6 deletions include/mbgl/vulkan/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,7 @@ class Context final : public gfx::Context {
RenderStaticData& staticData,
const std::vector<shaders::ClipUBO>& tileUBOs);

const std::unique_ptr<BufferResource>& getDummyVertexBuffer();
const std::unique_ptr<BufferResource>& getDummyUniformBuffer();
const std::unique_ptr<BufferResource>& getDummyStorageBuffer();
const std::unique_ptr<BufferResource>& getDummyBuffer();
const std::unique_ptr<Texture2D>& getDummyTexture();

const vk::DescriptorSetLayout& getDescriptorSetLayout(DescriptorSetType type);
Expand Down Expand Up @@ -190,9 +188,7 @@ class Context final : public gfx::Context {
vulkan::UniformBufferArray globalUniformBuffers;
std::unordered_map<DescriptorSetType, DescriptorPoolGrowable> descriptorPoolMap;

std::unique_ptr<BufferResource> dummyVertexBuffer;
std::unique_ptr<BufferResource> dummyUniformBuffer;
std::unique_ptr<BufferResource> dummyStorageBuffer;
std::unique_ptr<BufferResource> dummyBuffer;
std::unique_ptr<Texture2D> dummyTexture2D;
vk::UniqueDescriptorSetLayout globalUniformDescriptorSetLayout;
vk::UniqueDescriptorSetLayout layerUniformDescriptorSetLayout;
Expand Down
2 changes: 2 additions & 0 deletions include/mbgl/vulkan/renderer_backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ class RendererBackend : public gfx::RendererBackend {

void startFrameCapture();
void endFrameCapture();
void setFrameCaptureLoop(bool value);
void triggerFrameCapture(uint32_t frameCount = 1, uint32_t frameDelay = 0);

protected:
std::unique_ptr<gfx::Context> createContext() override;
Expand Down
14 changes: 11 additions & 3 deletions include/mbgl/vulkan/uniform_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class UniformBuffer final : public gfx::UniformBuffer {
~UniformBuffer() override;

const BufferResource& getBufferResource() const { return buffer; }
BufferResource& mutableBufferResource() { return buffer; }

UniformBuffer clone() const { return {buffer.clone()}; }

Expand All @@ -37,14 +38,21 @@ class UniformBufferArray final : public gfx::UniformBufferArray {
descriptorStorageCount(descriptorStorageCount_),
descriptorUniformCount(descriptorUniformCount_) {}

UniformBufferArray(UniformBufferArray&& other)
: gfx::UniformBufferArray(std::move(other)) {}
UniformBufferArray(UniformBufferArray&& other) noexcept
: gfx::UniformBufferArray(std::move(other)),
descriptorSetType(other.descriptorSetType),
descriptorStartIndex(other.descriptorStartIndex),
descriptorStorageCount(other.descriptorStorageCount),
descriptorUniformCount(other.descriptorUniformCount),
descriptorSet(std::move(other.descriptorSet)) {}

UniformBufferArray(const UniformBufferArray&) = delete;

UniformBufferArray& operator=(UniformBufferArray&& other) {
UniformBufferArray& operator=(UniformBufferArray&& other) noexcept {
gfx::UniformBufferArray::operator=(std::move(other));
return *this;
}

UniformBufferArray& operator=(const UniformBufferArray& other) {
gfx::UniformBufferArray::operator=(other);
return *this;
Expand Down
16 changes: 16 additions & 0 deletions platform/android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Changelog MapLibre Native for Android

## 11.8.0

> [!NOTE]
> We are now releasing OpenGL ES and Vulkan variants of MapLibre Android. See the [11.7.0 release notes](https://github.com/maplibre/maplibre-native/releases/tag/android-v11.7.0) for details.
### ✨ Features and improvements

- Add PMTiles support ([#2882](https://github.com/maplibre/maplibre-native/pull/2882)).
- Consolidate UBOs ([#3089](https://github.com/maplibre/maplibre-native/pull/3089)).

### 🐞 Bug fixes

- (Vulkan) Fix in-flight frame update Vulkan ([#3122](https://github.com/maplibre/maplibre-native/pull/3122)). Fixes jittery labels and some similar issues.

We have a new feature in the C++ Core to constrain the screen (instead of the center of the camera) to some bounds ([#2475](https://github.com/maplibre/maplibre-native/pull/2475)). This functionality still has to be exposed to Android. If you are interested in implementing this, see [this issue](https://github.com/maplibre/maplibre-native/issues/3128).

## 11.7.1

> [!NOTE]
Expand Down
2 changes: 1 addition & 1 deletion platform/android/MapLibreAndroid/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION_NAME=11.7.1
VERSION_NAME=11.8.0

# Only build native dependencies for the current ABI
# See https://code.google.com/p/android/issues/detail?id=221098#c20
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void HTTPRequest::onResponse(jni::JNIEnv& env,
response.expires = util::parseTimestamp(jni::Make<std::string>(env, expires).c_str());
}

if (code == 200) {
if (code == 200 || code == 206) {
if (body) {
auto data = std::make_shared<std::string>(body.Length(env), char());
jni::GetArrayRegion(env, *body, 0, data->size(), reinterpret_cast<jbyte*>(&(*data)[0]));
Expand Down
15 changes: 15 additions & 0 deletions platform/android/docs/data/PMTiles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# PMTiles

Starting MapLibre Android 11.7.0, using [PMTiles](https://docs.protomaps.com/pmtiles/) as a data source is supported. You can prefix your vector tile source with `pmtiles://` to load a PMTiles file. The rest of the URL continue with be `https://` to load a remote PMTiles file, `asset://` to load an asset or `file://` to load a local PMTiles file.

Oliver Wipfli has made a style available that combines a [Protomaps]() basemap togehter with Foursquare's POI dataset. It is available in the [wipfli/foursquare-os-places-pmtiles](https://github.com/wipfli/foursquare-os-places-pmtiles) repository on GitHub. The style to use is

```
https://raw.githubusercontent.com/wipfli/foursquare-os-places-pmtiles/refs/heads/main/style.json
```

The neat thing about this style is that it only uses PMTiles vector sources. PMTiles can be hosted with a relatively simple file server (or file hosting service) instead of a more complex specialized tile server.

<figure markdown="span">
![Screenshot of PMTiles based style using Protomaps basemap with Foursquare POIs]({{ s3_url("pmtiles-demo.png") }}){ width="300" }
</figure>
85 changes: 70 additions & 15 deletions src/mbgl/vulkan/buffer_resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <mbgl/util/instrumentation.hpp>

#include <algorithm>
#include <numeric>

namespace mbgl {
namespace vulkan {
Expand Down Expand Up @@ -59,12 +60,25 @@ BufferResource::BufferResource(
if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT || usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) {
const auto& backend = context.getBackend();
const auto& deviceProps = backend.getDeviceProperties();
const auto& align = deviceProps.limits.minUniformBufferOffsetAlignment;

vk::DeviceSize align = 0;
if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) {
align = deviceProps.limits.minUniformBufferOffsetAlignment;
}

if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) {
align = align ? std::lcm(align, deviceProps.limits.minStorageBufferOffsetAlignment)
: deviceProps.limits.minStorageBufferOffsetAlignment;
}

bufferWindowSize = (size + align - 1) & ~(align - 1);

assert(bufferWindowSize != 0);

totalSize = bufferWindowSize * backend.getMaxFrames();
const auto frameCount = backend.getMaxFrames();
totalSize = bufferWindowSize * frameCount;

bufferWindowVersions = std::vector<std::uint16_t>(frameCount, 0);
}

const auto bufferInfo = vk::BufferCreateInfo()
Expand All @@ -87,9 +101,7 @@ BufferResource::BufferResource(
vmaMapMemory(allocator, bufferAllocation->allocation, &bufferAllocation->mappedBuffer);

if (data) {
raw.resize(size);
std::memcpy(raw.data(), data, size);
std::memcpy(static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset(), data, size);
update(data, size, 0);
}

if (isValid()) {
Expand All @@ -104,12 +116,13 @@ BufferResource::BufferResource(

BufferResource::BufferResource(BufferResource&& other) noexcept
: context(other.context),
raw(std::move(other.raw)),
size(other.size),
usage(other.usage),
version(other.version),
persistent(other.persistent),
bufferAllocation(std::move(other.bufferAllocation)),
bufferWindowSize(other.bufferWindowSize) {
bufferWindowSize(other.bufferWindowSize),
bufferWindowVersions(std::move(other.bufferWindowVersions)) {
other.bufferAllocation = nullptr;
}

Expand All @@ -134,7 +147,7 @@ BufferResource& BufferResource::operator=(BufferResource&& other) noexcept {
context.renderingStats().numBuffers--;
context.renderingStats().memBuffers -= size;
};
raw = std::move(other.raw);

size = other.size;
usage = other.usage;
persistent = other.persistent;
Expand All @@ -152,21 +165,63 @@ void BufferResource::update(const void* newData, std::size_t updateSize, std::si
return;
}

auto& stats = context.renderingStats();
uint8_t* data = static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset() + offset;
std::memcpy(data, newData, updateSize);

std::memcpy(raw.data() + offset, newData, updateSize);
std::memcpy(
static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset() + offset, newData, updateSize);
auto& stats = context.renderingStats();
stats.bufferUpdateBytes += updateSize;

stats.bufferUpdates++;
version++;

if (bufferWindowSize) {
const auto frameIndex = context.getCurrentFrameResourceIndex();
bufferWindowVersions[frameIndex] = version;
}
}

const void* BufferResource::contents() const noexcept {
return contents(context.getCurrentFrameResourceIndex());
}

const void* BufferResource::contents(uint8_t resourceIndex) const noexcept {
if (!isValid()) {
return nullptr;
}

return static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + getVulkanBufferOffset(resourceIndex);
}

std::size_t BufferResource::getVulkanBufferOffset() const noexcept {
if (bufferWindowSize > 0) return 0;
return getVulkanBufferOffset(context.getCurrentFrameResourceIndex());
}

std::size_t BufferResource::getVulkanBufferOffset(std::uint8_t resourceIndex) const noexcept {
assert(context.getBackend().getMaxFrames() >= resourceIndex);
return bufferWindowSize ? resourceIndex * bufferWindowSize : 0;
}

void BufferResource::updateVulkanBuffer() {
const auto frameCount = context.getBackend().getMaxFrames();

const int8_t currentIndex = context.getCurrentFrameResourceIndex();
const int8_t prevIndex = currentIndex == 0 ? frameCount - 1 : currentIndex - 1;

updateVulkanBuffer(currentIndex, prevIndex);
}

void BufferResource::updateVulkanBuffer(const int8_t destination, const uint8_t source) {
if (!bufferWindowSize) {
return;
}

return context.getCurrentFrameResourceIndex() * bufferWindowSize;
if (bufferWindowVersions[destination] < bufferWindowVersions[source]) {
uint8_t* dstData = static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + bufferWindowSize * destination;
uint8_t* srcData = static_cast<uint8_t*>(bufferAllocation->mappedBuffer) + bufferWindowSize * source;

std::memcpy(dstData, srcData, size);

bufferWindowVersions[destination] = bufferWindowVersions[source];
}
}

} // namespace vulkan
Expand Down
25 changes: 7 additions & 18 deletions src/mbgl/vulkan/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,25 +563,14 @@ bool Context::renderTileClippingMasks(gfx::RenderPass& renderPass,
return true;
}

const std::unique_ptr<BufferResource>& Context::getDummyVertexBuffer() {
if (!dummyVertexBuffer)
dummyVertexBuffer = std::make_unique<BufferResource>(
*this, nullptr, 16, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, false);
return dummyVertexBuffer;
}

const std::unique_ptr<BufferResource>& Context::getDummyUniformBuffer() {
if (!dummyUniformBuffer)
dummyUniformBuffer = std::make_unique<BufferResource>(
*this, nullptr, 16, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, false);
return dummyUniformBuffer;
}
const std::unique_ptr<BufferResource>& Context::getDummyBuffer() {
if (!dummyBuffer) {
const uint32_t usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
dummyBuffer = std::make_unique<BufferResource>(*this, nullptr, 16, usage, false);
}

const std::unique_ptr<BufferResource>& Context::getDummyStorageBuffer() {
if (!dummyStorageBuffer)
dummyStorageBuffer = std::make_unique<BufferResource>(
*this, nullptr, 16, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, false);
return dummyStorageBuffer;
return dummyBuffer;
}

const std::unique_ptr<Texture2D>& Context::getDummyTexture() {
Expand Down
3 changes: 1 addition & 2 deletions src/mbgl/vulkan/descriptor_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ void UniformDescriptorSet::update(const gfx::UniformBufferArray& uniforms,
.setOffset(bufferResource.getVulkanBufferOffset())
.setRange(bufferResource.getSizeInBytes());
} else {
const auto& dummyBuffer = index < descriptorStorageCount ? context.getDummyStorageBuffer()
: context.getDummyUniformBuffer();
const auto& dummyBuffer = context.getDummyBuffer();
descriptorBufferInfo.setBuffer(dummyBuffer->getVulkanBuffer()).setOffset(0).setRange(VK_WHOLE_SIZE);
}

Expand Down
Loading

0 comments on commit ee238c7

Please sign in to comment.