feat(android): Vulkan graphics backend support for Android custom layers (#4348)
Co-authored-by: Vladyslav Odobesku <VladyslavOdobesku@intellias.com> Co-authored-by: Claude Opus 4 <noreply@anthropic.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
9f6f8e3f1b
commit
aa90185d42
@@ -358,6 +358,8 @@ list(APPEND INCLUDE_FILES
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/background_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/circle_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/custom_layer_host.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/custom_layer_init_parameters.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/custom_layer_render_parameters.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/custom_layer.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/fill_extrusion_layer.hpp
|
||||
|
||||
@@ -771,6 +771,8 @@ MLN_CORE_HEADERS = [
|
||||
"include/mbgl/style/layer.hpp",
|
||||
"include/mbgl/style/layer_properties.hpp",
|
||||
"include/mbgl/style/layers/custom_layer.hpp",
|
||||
"include/mbgl/style/layers/custom_layer_host.hpp",
|
||||
"include/mbgl/style/layers/custom_layer_init_parameters.hpp",
|
||||
"include/mbgl/style/layers/custom_layer_render_parameters.hpp",
|
||||
"include/mbgl/style/position.hpp",
|
||||
"include/mbgl/style/property_expression.hpp",
|
||||
|
||||
@@ -12,6 +12,8 @@ target_compile_definitions(
|
||||
|
||||
list(APPEND
|
||||
INCLUDE_FILES
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/vulkan/custom_layer_init_parameters.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/style/layers/vulkan/custom_layer_render_parameters.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/buffer_resource.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/command_encoder.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/mbgl/vulkan/context.hpp
|
||||
@@ -57,6 +59,7 @@ list(APPEND
|
||||
|
||||
list(APPEND
|
||||
SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/style/layers/vulkan/custom_layer_render_parameters.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/buffer_resource.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/command_encoder.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/vulkan/context.cpp
|
||||
|
||||
@@ -1,59 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/layer.hpp>
|
||||
#include <mbgl/style/layers/custom_layer_render_parameters.hpp>
|
||||
#include <mbgl/style/layers/custom_layer_host.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
namespace style {
|
||||
|
||||
class CustomLayerHost {
|
||||
public:
|
||||
virtual ~CustomLayerHost() = default;
|
||||
/**
|
||||
* Initialize any GL/Metal state needed by the custom layer. This method is called
|
||||
* once, from the main thread, at a point when the GL context is active but
|
||||
* before rendering for the first time.
|
||||
*
|
||||
* Resources that are acquired in this method must be released in the
|
||||
* `deinitialize` function.
|
||||
*/
|
||||
virtual void initialize() = 0;
|
||||
|
||||
/**
|
||||
* Render the layer. This method is called once per frame. The
|
||||
* implementation should not make any assumptions about the GL/Metal state (other
|
||||
* than that the correct context is active). It may make changes to the
|
||||
* state, and is not required to reset values such as the depth mask,
|
||||
* stencil mask, and corresponding test flags to their original values. Make
|
||||
* sure that you are drawing your fragments with a z value of 1 to take
|
||||
* advantage of the opaque fragment culling in case there are opaque layers
|
||||
* above your custom layer.
|
||||
*/
|
||||
virtual void render(const mbgl::style::CustomLayerRenderParameters&) = 0;
|
||||
|
||||
/**
|
||||
* Called when the system has destroyed the underlying GL/Metal context. The
|
||||
* `deinitialize` function will not be called in this case, however
|
||||
* `initialize` will be called instead to prepare for a new render.
|
||||
*
|
||||
*/
|
||||
virtual void contextLost() = 0;
|
||||
|
||||
/**
|
||||
* Destroy any GL/Metal state needed by the custom layer, and deallocate context,
|
||||
* if necessary. This method is called once, from the main thread, at a
|
||||
* point when the GL/Metal context is active.
|
||||
*
|
||||
* Note that it may be called even when the `initialize` function has not
|
||||
* been called.
|
||||
*/
|
||||
virtual void deinitialize() = 0;
|
||||
};
|
||||
|
||||
class CustomLayer final : public Layer {
|
||||
public:
|
||||
CustomLayer(const std::string& id, std::unique_ptr<CustomLayerHost> host);
|
||||
|
||||
59
include/mbgl/style/layers/custom_layer_host.hpp
Normal file
59
include/mbgl/style/layers/custom_layer_host.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/layers/custom_layer_init_parameters.hpp>
|
||||
#include <mbgl/style/layers/custom_layer_render_parameters.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
class CustomLayerHost {
|
||||
public:
|
||||
virtual ~CustomLayerHost() = default;
|
||||
/**
|
||||
* Initialize any GL/Metal/Vulkan state needed by the custom layer. This method
|
||||
* is called once, from the main thread, at a point when the graphics context
|
||||
* is active but before rendering for the first time.
|
||||
*
|
||||
* The parameters argument provides backend-specific device handles:
|
||||
* - Vulkan: cast to mbgl::style::vulkan::CustomLayerInitParameters for
|
||||
* access to vk::Device, vk::PhysicalDevice, and the dispatcher.
|
||||
* - Metal/GL: base CustomLayerInitParameters (no extra handles currently).
|
||||
*
|
||||
* Resources that are acquired in this method must be released in the
|
||||
* `deinitialize` function.
|
||||
*/
|
||||
virtual void initialize(const CustomLayerInitParameters&) = 0;
|
||||
|
||||
/**
|
||||
* Render the layer. This method is called once per frame. The
|
||||
* implementation should not make any assumptions about the GL/Metal state (other
|
||||
* than that the correct context is active). It may make changes to the
|
||||
* state, and is not required to reset values such as the depth mask,
|
||||
* stencil mask, and corresponding test flags to their original values. Make
|
||||
* sure that you are drawing your fragments with a z value of 1 to take
|
||||
* advantage of the opaque fragment culling in case there are opaque layers
|
||||
* above your custom layer.
|
||||
*/
|
||||
virtual void render(const mbgl::style::CustomLayerRenderParameters&) = 0;
|
||||
|
||||
/**
|
||||
* Called when the system has destroyed the underlying GL/Metal context. The
|
||||
* `deinitialize` function will not be called in this case, however
|
||||
* `initialize` will be called instead to prepare for a new render.
|
||||
*
|
||||
*/
|
||||
virtual void contextLost() = 0;
|
||||
|
||||
/**
|
||||
* Destroy any GL/Metal state needed by the custom layer, and deallocate context,
|
||||
* if necessary. This method is called once, from the main thread, at a
|
||||
* point when the GL/Metal context is active.
|
||||
*
|
||||
* Note that it may be called even when the `initialize` function has not
|
||||
* been called.
|
||||
*/
|
||||
virtual void deinitialize() = 0;
|
||||
};
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
16
include/mbgl/style/layers/custom_layer_init_parameters.hpp
Normal file
16
include/mbgl/style/layers/custom_layer_init_parameters.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
/**
|
||||
* Base parameters passed to CustomLayerHost::initialize().
|
||||
* Backend-specific subclasses provide device handles needed for
|
||||
* resource creation (pipelines, buffers, etc.).
|
||||
*/
|
||||
struct CustomLayerInitParameters {
|
||||
virtual ~CustomLayerInitParameters() = default;
|
||||
};
|
||||
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/layers/custom_layer_init_parameters.hpp>
|
||||
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
namespace vulkan {
|
||||
|
||||
/**
|
||||
* Vulkan-specific initialization parameters.
|
||||
* Provides device handles so that custom layers can create pipelines,
|
||||
* allocate buffers, and compile shaders during initialize().
|
||||
*
|
||||
* Note: vk::RenderPass is NOT available here because it depends on the
|
||||
* active framebuffer which may not exist yet. Use the render pass from
|
||||
* CustomLayerRenderParameters during the first render() call if needed
|
||||
* for pipeline creation.
|
||||
*/
|
||||
struct CustomLayerInitParameters : mbgl::style::CustomLayerInitParameters {
|
||||
/// Dynamic dispatcher for Vulkan function calls.
|
||||
const vk::detail::DispatchLoaderDynamic& dispatcher;
|
||||
/// Logical device handle.
|
||||
vk::Device device;
|
||||
/// Physical device handle — useful for querying memory properties, limits, etc.
|
||||
vk::PhysicalDevice physicalDevice;
|
||||
|
||||
CustomLayerInitParameters(const vk::detail::DispatchLoaderDynamic& dispatcher_,
|
||||
vk::Device device_,
|
||||
vk::PhysicalDevice physicalDevice_)
|
||||
: dispatcher(dispatcher_),
|
||||
device(device_),
|
||||
physicalDevice(physicalDevice_) {}
|
||||
};
|
||||
|
||||
} // namespace vulkan
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/style/layers/custom_layer_render_parameters.hpp>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class PaintParameters;
|
||||
|
||||
namespace style {
|
||||
namespace vulkan {
|
||||
|
||||
struct CustomLayerRenderParameters : mbgl::style::CustomLayerRenderParameters {
|
||||
/// Dynamic dispatcher.
|
||||
const vk::detail::DispatchLoaderDynamic& dispatcher;
|
||||
|
||||
/// Vulkan device
|
||||
vk::Device device;
|
||||
|
||||
/// Compatible render pass handle — use when creating VkPipeline.
|
||||
vk::RenderPass renderPass;
|
||||
|
||||
/// Active command buffer for the current render pass — record all draw calls here.
|
||||
vk::CommandBuffer commandBuffer;
|
||||
|
||||
/// @brief Screen pre-rotation related to VkSurfaceTransformFlagBitsKHR.
|
||||
/// This field is going to be non 0.0 when renderer decides to do the rotation inside the rendering pipeline instead
|
||||
/// of relying on compositor. Custom layers must use this parameter to do the rotation in clip space.
|
||||
///
|
||||
/// @code{.cpp}
|
||||
/// if(screenPreRotationRadiansClockwise != 0.0)
|
||||
/// {
|
||||
/// glm::vec3 rotation_axis = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
/// glm::mat4 pre_rotate_mat = glm::rotate(screenPreRotationRadiansClockwise, rotation_axis);
|
||||
/// MVP = pre_rotate_mat * MVP;
|
||||
/// }
|
||||
/// @endcode
|
||||
///
|
||||
/// @note For more info see https://developer.android.com/games/optimize/vulkan-prerotation.
|
||||
/// @attention dFdx, dFdy in shaders also need adjustments if used.
|
||||
float screenPreRotationRadiansClockwise = 0.0f;
|
||||
|
||||
explicit CustomLayerRenderParameters(const PaintParameters&);
|
||||
};
|
||||
|
||||
} // namespace vulkan
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
~RenderPass() override;
|
||||
|
||||
vulkan::CommandEncoder& getEncoder() { return commandEncoder; }
|
||||
const gfx::RenderPassDescriptor& getDescriptor() { return descriptor; }
|
||||
const gfx::RenderPassDescriptor& getDescriptor() const { return descriptor; }
|
||||
void endEncoding();
|
||||
|
||||
void clearStencil(uint32_t value = 0) const;
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
const vk::Extent2D& getExtent() const { return extent; }
|
||||
const vk::UniqueRenderPass& getRenderPass() const { return renderPass; }
|
||||
virtual const vk::UniqueFramebuffer& getFramebuffer() const = 0;
|
||||
virtual float getRotation() const { return 0.0f; }
|
||||
|
||||
protected:
|
||||
RendererBackend& backend;
|
||||
@@ -70,7 +71,7 @@ public:
|
||||
bool didSurfaceTransformUpdate() const;
|
||||
|
||||
// rotation needed to align framebuffer contents with device surface
|
||||
float getRotation();
|
||||
float getRotation() const override;
|
||||
|
||||
void setSurfaceTransformPollingInterval(int32_t value) { surfaceTransformPollingInterval = value; }
|
||||
int32_t getSurfaceTransformPollingInterval() const { return surfaceTransformPollingInterval; }
|
||||
|
||||
1
platform/android/.gitignore
vendored
1
platform/android/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
MapLibreAndroid/src/vulkanDebug
|
||||
prefab-headers/
|
||||
|
||||
@@ -177,6 +177,14 @@ android {
|
||||
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
prefabPublishing = project.findProperty("maplibre.abis") != "none"
|
||||
}
|
||||
|
||||
prefab {
|
||||
create("maplibre") {
|
||||
headers = "../prefab-headers"
|
||||
libraryName = "libmaplibre"
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
@@ -192,6 +200,25 @@ fun getGitRevision(shortRev: Boolean = true): String {
|
||||
return proc.inputStream.bufferedReader().readText().trim()
|
||||
}
|
||||
|
||||
val syncPrefabHeaders by tasks.registering(Sync::class) {
|
||||
val nativeRoot = rootProject.rootDir.resolve("../..")
|
||||
from(nativeRoot.resolve("include")) {
|
||||
include("mbgl/style/layers/custom_layer_host.hpp")
|
||||
include("mbgl/style/layers/custom_layer_init_parameters.hpp")
|
||||
include("mbgl/style/layers/custom_layer_render_parameters.hpp")
|
||||
include("mbgl/style/layers/vulkan/custom_layer_init_parameters.hpp")
|
||||
include("mbgl/style/layers/vulkan/custom_layer_render_parameters.hpp")
|
||||
}
|
||||
into(project.rootDir.resolve("prefab-headers"))
|
||||
}
|
||||
|
||||
tasks.configureEach {
|
||||
if (name == "syncPrefabHeaders") return@configureEach
|
||||
if (name.contains("Prefab", ignoreCase = true) || name.contains("bundleLibRuntimeTo", ignoreCase = true)) {
|
||||
dependsOn(syncPrefabHeaders)
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
getByName("implementation") {
|
||||
exclude(group = "commons-logging", module = "commons-logging")
|
||||
|
||||
@@ -34,7 +34,7 @@ android {
|
||||
manifestPlaceholders["SENTRY_ENV"] = ""
|
||||
}
|
||||
|
||||
nativeBuild(listOf("example-custom-layer"))
|
||||
nativeBuild(emptyList())
|
||||
|
||||
packaging {
|
||||
resources.excludes += listOf("META-INF/LICENSE.txt", "META-INF/NOTICE.txt", "LICENSE.txt")
|
||||
@@ -82,7 +82,8 @@ android {
|
||||
dimension = "renderer"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments("-DMLN_WITH_OPENGL=ON")
|
||||
arguments += "-DMLN_WITH_OPENGL=ON"
|
||||
targets += "example-custom-layer"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,7 +91,8 @@ android {
|
||||
dimension = "renderer"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments("-DMLN_WITH_VULKAN=ON")
|
||||
arguments += "-DMLN_WITH_VULKAN=ON"
|
||||
targets += "example-vulkan-custom-layer"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,10 @@ import org.maplibre.android.maps.MapView
|
||||
import org.maplibre.android.maps.MapLibreMap
|
||||
import org.maplibre.android.maps.Style
|
||||
import org.maplibre.android.style.layers.CustomLayer
|
||||
import org.maplibre.android.testapp.BuildConfig
|
||||
import org.maplibre.android.testapp.R
|
||||
import org.maplibre.android.testapp.model.customlayer.ExampleCustomLayer
|
||||
import org.maplibre.android.testapp.model.customlayer.ExampleVulkanCustomLayer
|
||||
import org.maplibre.android.testapp.styles.TestStyles
|
||||
|
||||
/**
|
||||
@@ -29,6 +31,9 @@ class CustomLayerActivity : AppCompatActivity() {
|
||||
private lateinit var mapView: MapView
|
||||
private var customLayer: CustomLayer? = null
|
||||
private lateinit var fab: FloatingActionButton
|
||||
|
||||
private var isVulkan = BuildConfig.FLAVOR.contains("vulkan")
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_custom_layer)
|
||||
@@ -65,7 +70,7 @@ class CustomLayerActivity : AppCompatActivity() {
|
||||
} else {
|
||||
customLayer = CustomLayer(
|
||||
"custom",
|
||||
ExampleCustomLayer.createContext()
|
||||
if (!isVulkan) ExampleCustomLayer.createContext() else ExampleVulkanCustomLayer.createContext()
|
||||
)
|
||||
style!!.addLayerBelow(customLayer!!, "building")
|
||||
fab.setImageResource(R.drawable.ic_layers_clear)
|
||||
@@ -124,18 +129,34 @@ class CustomLayerActivity : AppCompatActivity() {
|
||||
updateLayer()
|
||||
true
|
||||
}
|
||||
|
||||
R.id.action_set_color_red -> {
|
||||
ExampleCustomLayer.setColor(1f, 0f, 0f, 1f)
|
||||
if (!isVulkan) {
|
||||
ExampleCustomLayer.setColor(1f, 0f, 0f, 1f)
|
||||
} else {
|
||||
ExampleVulkanCustomLayer.setColor(1f, 0f, 0f, 1f)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
R.id.action_set_color_green -> {
|
||||
ExampleCustomLayer.setColor(0f, 1f, 0f, 1f)
|
||||
if (!isVulkan) {
|
||||
ExampleCustomLayer.setColor(0f, 1f, 0f, 1f)
|
||||
} else {
|
||||
ExampleVulkanCustomLayer.setColor(0f, 1f, 0f, 1f)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
R.id.action_set_color_blue -> {
|
||||
ExampleCustomLayer.setColor(0f, 0f, 1f, 1f)
|
||||
if (!isVulkan) {
|
||||
ExampleCustomLayer.setColor(0f, 0f, 1f, 1f)
|
||||
} else {
|
||||
ExampleVulkanCustomLayer.setColor(0f, 0f, 1f, 1f)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.maplibre.android.testapp.model.customlayer
|
||||
|
||||
import androidx.annotation.Keep
|
||||
|
||||
@Keep
|
||||
object ExampleVulkanCustomLayer {
|
||||
init {
|
||||
System.loadLibrary("example-vulkan-custom-layer")
|
||||
}
|
||||
|
||||
external fun createContext(): Long
|
||||
external fun setColor(red: Float, green: Float, blue: Float, alpha: Float)
|
||||
var InitializeFunction: Long = 0
|
||||
var RenderFunction: Long = 0
|
||||
var ContextLostFunction: Long = 0
|
||||
var DeinitializeFunction: Long = 0
|
||||
}
|
||||
@@ -142,6 +142,27 @@ target_link_libraries(
|
||||
mbgl-compiler-options
|
||||
)
|
||||
|
||||
if(MLN_WITH_VULKAN)
|
||||
add_library(
|
||||
example-vulkan-custom-layer MODULE
|
||||
${PROJECT_SOURCE_DIR}/platform/android/src/example_vulkan_custom_layer.cpp
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
example-vulkan-custom-layer
|
||||
PRIVATE ${PROJECT_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
example-vulkan-custom-layer
|
||||
PRIVATE
|
||||
MapLibreNative::Base
|
||||
log
|
||||
mbgl-compiler-options
|
||||
mbgl-vendor-vulkan-headers
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
mbgl-test-runner SHARED
|
||||
${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c
|
||||
|
||||
@@ -131,7 +131,7 @@ class ExampleCustomLayer : mbgl::style::CustomLayerHost {
|
||||
public:
|
||||
~ExampleCustomLayer() {}
|
||||
|
||||
void initialize() {
|
||||
void initialize(const mbgl::style::CustomLayerInitParameters &) override {
|
||||
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "Initialize");
|
||||
|
||||
// Debug info
|
||||
@@ -163,7 +163,7 @@ public:
|
||||
GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), background, GL_STATIC_DRAW));
|
||||
}
|
||||
|
||||
void render(const mbgl::style::CustomLayerRenderParameters &) {
|
||||
void render(const mbgl::style::CustomLayerRenderParameters &) override {
|
||||
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "Render");
|
||||
glUseProgram(program);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
@@ -183,12 +183,12 @@ public:
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
|
||||
void contextLost() {
|
||||
void contextLost() override {
|
||||
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "ContextLost");
|
||||
program = 0;
|
||||
}
|
||||
|
||||
void deinitialize() {
|
||||
void deinitialize() override {
|
||||
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "DeInitialize");
|
||||
if (program) {
|
||||
glDeleteBuffers(1, &buffer);
|
||||
|
||||
450
platform/android/src/example_vulkan_custom_layer.cpp
Normal file
450
platform/android/src/example_vulkan_custom_layer.cpp
Normal file
@@ -0,0 +1,450 @@
|
||||
#include <android/log.h>
|
||||
#include <jni.h>
|
||||
|
||||
#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS
|
||||
|
||||
#include <mbgl/style/layers/custom_layer_host.hpp>
|
||||
#include <mbgl/style/layers/vulkan/custom_layer_init_parameters.hpp>
|
||||
#include <mbgl/style/layers/vulkan/custom_layer_render_parameters.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
const char *VK_LOG_TAG = "VulkanCustomLayer";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Minimal SPIR-V shaders
|
||||
//
|
||||
// Vertex shader: generates a full-screen quad from gl_VertexIndex (no VBO).
|
||||
// index 0 → (-1,-1) index 1 → ( 3,-1) index 2 → (-1, 3)
|
||||
// This covers the NDC clip space with a single triangle.
|
||||
//
|
||||
// Fragment shader: outputs a push-constant RGBA color.
|
||||
//
|
||||
// Generated from:
|
||||
// vert: #version 450
|
||||
// void main() {
|
||||
// vec2 pos[3] = vec2[](vec2(-1,-1), vec2(3,-1), vec2(-1,3));
|
||||
// gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);
|
||||
// }
|
||||
// frag: #version 450
|
||||
// layout(push_constant) uniform PC { vec4 color; } pc;
|
||||
// layout(location = 0) out vec4 outColor;
|
||||
// void main() { outColor = pc.color; }
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// clang-format off
|
||||
static const unsigned char kVertSpirv[] = {
|
||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00,
|
||||
0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x18, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00,
|
||||
0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70,
|
||||
0x70, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65,
|
||||
0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00,
|
||||
0x04, 0x00, 0x08, 0x00, 0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c,
|
||||
0x45, 0x5f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69,
|
||||
0x72, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x73, 0x00,
|
||||
0x05, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50,
|
||||
0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00,
|
||||
0x06, 0x00, 0x07, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65,
|
||||
0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43, 0x6c, 0x69, 0x70, 0x44,
|
||||
0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x06, 0x00, 0x07, 0x00,
|
||||
0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43,
|
||||
0x75, 0x6c, 0x6c, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00,
|
||||
0x05, 0x00, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x06, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x56,
|
||||
0x65, 0x72, 0x74, 0x65, 0x78, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x00, 0x00,
|
||||
0x47, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x48, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
|
||||
0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x48, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
|
||||
0x1c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xbf, 0x2c, 0x00, 0x05, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
|
||||
0x0d, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x2c, 0x00, 0x05, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
|
||||
0x0d, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x11, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
|
||||
0x2c, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
|
||||
0x17, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
|
||||
0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x16, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
|
||||
0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
|
||||
0x19, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x2b, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
|
||||
0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
|
||||
0x20, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
|
||||
0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x3e, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0x3d, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
|
||||
0x1c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x1e, 0x00, 0x00, 0x00,
|
||||
0x1f, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
|
||||
0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
|
||||
0x1f, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
|
||||
0x23, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
|
||||
0x13, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
|
||||
0x24, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
|
||||
0x41, 0x00, 0x05, 0x00, 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
|
||||
0x18, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
|
||||
0x27, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
|
||||
0x38, 0x00, 0x01, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char kFragSpirv[] = {
|
||||
0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x0d, 0x00,
|
||||
0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
|
||||
0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0xc2, 0x01, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x47, 0x4c, 0x5f, 0x47,
|
||||
0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x74,
|
||||
0x79, 0x6c, 0x65, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x64, 0x69, 0x72,
|
||||
0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
|
||||
0x47, 0x4c, 0x5f, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x5f, 0x69, 0x6e,
|
||||
0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
|
||||
0x69, 0x76, 0x65, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
|
||||
0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x50, 0x43, 0x00, 0x00, 0x06, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x70, 0x63, 0x00, 0x00,
|
||||
0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
|
||||
0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00,
|
||||
0x0a, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
|
||||
0x0b, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x3b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
|
||||
0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
|
||||
0x07, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
|
||||
0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
|
||||
0x0f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x0e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
|
||||
0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00,
|
||||
0x38, 0x00, 0x01, 0x00
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class ExampleVulkanCustomLayer : public mbgl::style::CustomLayerHost {
|
||||
public:
|
||||
~ExampleVulkanCustomLayer() = default;
|
||||
|
||||
void initialize(const mbgl::style::CustomLayerInitParameters &baseParams) override {
|
||||
const auto ¶ms = static_cast<const mbgl::style::vulkan::CustomLayerInitParameters &>(baseParams);
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO,
|
||||
VK_LOG_TAG,
|
||||
"initialize: device=%p, physicalDevice=%p",
|
||||
static_cast<VkDevice>(params.device),
|
||||
static_cast<VkPhysicalDevice>(params.physicalDevice));
|
||||
|
||||
vulkanDevice = params.device;
|
||||
vulkanDispatcher = ¶ms.dispatcher;
|
||||
|
||||
createShaders(vulkanDevice, *vulkanDispatcher);
|
||||
createPipelineLayout(vulkanDevice, *vulkanDispatcher);
|
||||
}
|
||||
|
||||
void render(const mbgl::style::CustomLayerRenderParameters &baseParams) override {
|
||||
const auto ¶ms = static_cast<const mbgl::style::vulkan::CustomLayerRenderParameters &>(baseParams);
|
||||
|
||||
const auto &dispatcher = params.dispatcher;
|
||||
const auto &cmd = params.commandBuffer;
|
||||
|
||||
if (!pipeline) {
|
||||
createPipeline(params.device, dispatcher, params.renderPass);
|
||||
}
|
||||
|
||||
if (!pipeline) return;
|
||||
|
||||
cmd.pushConstants(
|
||||
*pipelineLayout, vk::ShaderStageFlagBits::eFragment, 0, sizeof(color), color.data(), dispatcher);
|
||||
|
||||
cmd.bindPipeline(vk::PipelineBindPoint::eGraphics, *pipeline, dispatcher);
|
||||
|
||||
cmd.draw(3, 1, 0, 0, dispatcher);
|
||||
|
||||
__android_log_write(ANDROID_LOG_VERBOSE, VK_LOG_TAG, "render");
|
||||
}
|
||||
|
||||
void contextLost() override {
|
||||
__android_log_write(ANDROID_LOG_INFO, VK_LOG_TAG, "contextLost");
|
||||
pipeline.reset();
|
||||
pipelineLayout.reset();
|
||||
vertexModule.reset();
|
||||
fragmentModule.reset();
|
||||
}
|
||||
|
||||
void deinitialize() override {
|
||||
__android_log_write(ANDROID_LOG_INFO, VK_LOG_TAG, "deinitialize");
|
||||
pipeline.reset();
|
||||
pipelineLayout.reset();
|
||||
vertexModule.reset();
|
||||
fragmentModule.reset();
|
||||
}
|
||||
|
||||
static std::array<float, 4> color;
|
||||
|
||||
private:
|
||||
void createShaders(const vk::Device &device, const vk::detail::DispatchLoaderDynamic &dispatcher) {
|
||||
try {
|
||||
vertexModule = device.createShaderModuleUnique(
|
||||
vk::ShaderModuleCreateInfo{.codeSize = sizeof(kVertSpirv),
|
||||
.pCode = reinterpret_cast<const std::uint32_t *>(kVertSpirv)},
|
||||
nullptr,
|
||||
dispatcher);
|
||||
} catch (const std::exception &) {
|
||||
__android_log_write(ANDROID_LOG_ERROR, VK_LOG_TAG, "Failed to create vertex shader module.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
fragmentModule = device.createShaderModuleUnique(
|
||||
vk::ShaderModuleCreateInfo{.codeSize = sizeof(kFragSpirv),
|
||||
.pCode = reinterpret_cast<const std::uint32_t *>(kFragSpirv)},
|
||||
nullptr,
|
||||
dispatcher);
|
||||
} catch (const std::exception &) {
|
||||
__android_log_write(ANDROID_LOG_ERROR, VK_LOG_TAG, "Failed to create fragment shader module.");
|
||||
return;
|
||||
}
|
||||
|
||||
__android_log_write(ANDROID_LOG_INFO, VK_LOG_TAG, "Shader modules created");
|
||||
}
|
||||
|
||||
void createPipelineLayout(const vk::Device &device, const vk::detail::DispatchLoaderDynamic &dispatcher) {
|
||||
const vk::PushConstantRange pushRange{
|
||||
.stageFlags = vk::ShaderStageFlagBits::eFragment,
|
||||
.offset = 0,
|
||||
.size = sizeof(float) * 4,
|
||||
};
|
||||
|
||||
try {
|
||||
pipelineLayout = device.createPipelineLayoutUnique(
|
||||
vk::PipelineLayoutCreateInfo{
|
||||
.pushConstantRangeCount = 1,
|
||||
.pPushConstantRanges = &pushRange,
|
||||
},
|
||||
nullptr,
|
||||
dispatcher);
|
||||
} catch (const std::exception &) {
|
||||
__android_log_write(ANDROID_LOG_ERROR, VK_LOG_TAG, "Failed to create pipeline layout.");
|
||||
return;
|
||||
}
|
||||
|
||||
__android_log_write(ANDROID_LOG_INFO, VK_LOG_TAG, "Pipeline layout created");
|
||||
}
|
||||
|
||||
void createPipeline(const vk::Device &device,
|
||||
const vk::detail::DispatchLoaderDynamic &dispatcher,
|
||||
vk::RenderPass renderPass) {
|
||||
if (!vertexModule || !fragmentModule || !pipelineLayout) return;
|
||||
|
||||
const std::array<vk::PipelineShaderStageCreateInfo, 2> stages = {{
|
||||
{
|
||||
.stage = vk::ShaderStageFlagBits::eVertex,
|
||||
.module = *vertexModule,
|
||||
.pName = "main",
|
||||
},
|
||||
{
|
||||
.stage = vk::ShaderStageFlagBits::eFragment,
|
||||
.module = *fragmentModule,
|
||||
.pName = "main",
|
||||
},
|
||||
}};
|
||||
|
||||
const vk::PipelineVertexInputStateCreateInfo vertexInput{};
|
||||
|
||||
const vk::PipelineInputAssemblyStateCreateInfo inputAssembly{
|
||||
.topology = vk::PrimitiveTopology::eTriangleList,
|
||||
};
|
||||
|
||||
const std::array<vk::DynamicState, 2> dynamicStates = {
|
||||
vk::DynamicState::eViewport,
|
||||
vk::DynamicState::eScissor,
|
||||
};
|
||||
const vk::PipelineDynamicStateCreateInfo dynamicState{
|
||||
.dynamicStateCount = static_cast<uint32_t>(dynamicStates.size()),
|
||||
.pDynamicStates = dynamicStates.data(),
|
||||
};
|
||||
|
||||
const vk::PipelineViewportStateCreateInfo viewportState{
|
||||
.viewportCount = 1,
|
||||
.scissorCount = 1,
|
||||
};
|
||||
|
||||
const vk::PipelineRasterizationStateCreateInfo rasterizer{
|
||||
.polygonMode = vk::PolygonMode::eFill,
|
||||
.cullMode = vk::CullModeFlagBits::eNone,
|
||||
.frontFace = vk::FrontFace::eClockwise,
|
||||
.lineWidth = 1.0f,
|
||||
};
|
||||
|
||||
const vk::PipelineMultisampleStateCreateInfo multisampling{
|
||||
.rasterizationSamples = vk::SampleCountFlagBits::e1,
|
||||
};
|
||||
|
||||
const vk::PipelineColorBlendAttachmentState blendAttachment{
|
||||
.blendEnable = VK_TRUE,
|
||||
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
|
||||
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
|
||||
.colorBlendOp = vk::BlendOp::eAdd,
|
||||
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
|
||||
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
|
||||
.alphaBlendOp = vk::BlendOp::eAdd,
|
||||
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |
|
||||
vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
|
||||
};
|
||||
|
||||
const vk::PipelineColorBlendStateCreateInfo colorBlend{
|
||||
.attachmentCount = 1,
|
||||
.pAttachments = &blendAttachment,
|
||||
};
|
||||
|
||||
const vk::PipelineDepthStencilStateCreateInfo depthStencil{
|
||||
.depthTestEnable = VK_FALSE,
|
||||
.depthWriteEnable = VK_FALSE,
|
||||
};
|
||||
|
||||
const vk::GraphicsPipelineCreateInfo pipelineInfo{
|
||||
.stageCount = static_cast<uint32_t>(stages.size()),
|
||||
.pStages = stages.data(),
|
||||
.pVertexInputState = &vertexInput,
|
||||
.pInputAssemblyState = &inputAssembly,
|
||||
.pViewportState = &viewportState,
|
||||
.pRasterizationState = &rasterizer,
|
||||
.pMultisampleState = &multisampling,
|
||||
.pDepthStencilState = &depthStencil,
|
||||
.pColorBlendState = &colorBlend,
|
||||
.pDynamicState = &dynamicState,
|
||||
.layout = *pipelineLayout,
|
||||
.renderPass = renderPass,
|
||||
.subpass = 0,
|
||||
};
|
||||
|
||||
auto result = device.createGraphicsPipelineUnique(nullptr, pipelineInfo, nullptr, dispatcher);
|
||||
if (result.result != vk::Result::eSuccess) {
|
||||
__android_log_write(ANDROID_LOG_ERROR, VK_LOG_TAG, "Failed to create graphics pipeline");
|
||||
return;
|
||||
}
|
||||
pipeline = std::move(result.value);
|
||||
__android_log_write(ANDROID_LOG_INFO, VK_LOG_TAG, "Pipeline created");
|
||||
}
|
||||
|
||||
vk::Device vulkanDevice;
|
||||
const vk::detail::DispatchLoaderDynamic *vulkanDispatcher = nullptr;
|
||||
|
||||
vk::UniqueHandle<vk::ShaderModule, vk::detail::DispatchLoaderDynamic> vertexModule;
|
||||
vk::UniqueHandle<vk::ShaderModule, vk::detail::DispatchLoaderDynamic> fragmentModule;
|
||||
|
||||
vk::UniqueHandle<vk::Pipeline, vk::detail::DispatchLoaderDynamic> pipeline;
|
||||
vk::UniqueHandle<vk::PipelineLayout, vk::detail::DispatchLoaderDynamic> pipelineLayout;
|
||||
};
|
||||
|
||||
std::array<float, 4> ExampleVulkanCustomLayer::color = {0.0f, 1.0f, 0.0f, 0.5f};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// JNI entry points
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
jlong JNICALL nativeCreateContext(JNIEnv *, jobject) {
|
||||
__android_log_write(ANDROID_LOG_INFO, VK_LOG_TAG, "nativeCreateContext");
|
||||
return reinterpret_cast<jlong>(new ExampleVulkanCustomLayer());
|
||||
}
|
||||
|
||||
void JNICALL nativeSetColor(JNIEnv *, jobject, jfloat red, jfloat green, jfloat blue, jfloat alpha) {
|
||||
__android_log_print(ANDROID_LOG_INFO,
|
||||
VK_LOG_TAG,
|
||||
"ExampleVulkanCustomLayer.nativeSetColor: %.2f, %.2f, %.2f, %.2f",
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
alpha);
|
||||
ExampleVulkanCustomLayer::color = {red, green, blue, alpha};
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
|
||||
__android_log_write(ANDROID_LOG_INFO, VK_LOG_TAG, "JNI_OnLoad");
|
||||
|
||||
JNIEnv *env = nullptr;
|
||||
vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
|
||||
|
||||
jclass cls = env->FindClass("org/maplibre/android/testapp/model/customlayer/ExampleVulkanCustomLayer");
|
||||
|
||||
const JNINativeMethod methods[] = {
|
||||
{"createContext", "()J", reinterpret_cast<void *>(&nativeCreateContext)},
|
||||
{"setColor", "(FFFF)V", reinterpret_cast<void *>(&nativeSetColor)},
|
||||
};
|
||||
|
||||
if (env->RegisterNatives(cls, methods, 2) < 0) {
|
||||
env->ExceptionDescribe();
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *, void *) {}
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
layer = nil;
|
||||
}
|
||||
|
||||
void initialize() {
|
||||
void initialize(const mbgl::style::CustomLayerInitParameters &) override {
|
||||
if (layerRef == nil)
|
||||
return;
|
||||
else if (layer == nil)
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void render(const mbgl::style::CustomLayerRenderParameters ¶meters) {
|
||||
void render(const mbgl::style::CustomLayerRenderParameters ¶meters) override {
|
||||
if (!layer) return;
|
||||
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
@@ -124,9 +124,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void contextLost() {}
|
||||
void contextLost() override {}
|
||||
|
||||
void deinitialize() {
|
||||
void deinitialize() override {
|
||||
if (layer == nil) return;
|
||||
|
||||
if (layer.mapView) {
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#if MLN_RENDER_BACKEND_METAL
|
||||
#include <mbgl/style/layers/mtl/custom_layer_render_parameters.hpp>
|
||||
#include <mbgl/mtl/render_pass.hpp>
|
||||
#elif MLN_RENDER_BACKEND_VULKAN
|
||||
#include <mbgl/style/layers/vulkan/custom_layer_render_parameters.hpp>
|
||||
#include <mbgl/vulkan/render_pass.hpp>
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
@@ -28,6 +31,8 @@ void DrawableCustomLayerHostTweaker::execute([[maybe_unused]] gfx::Drawable& dra
|
||||
mtlRenderPass->resetState();
|
||||
|
||||
style::mtl::CustomLayerRenderParameters parameters(paintParameters);
|
||||
#elif MLN_RENDER_BACKEND_VULKAN
|
||||
style::vulkan::CustomLayerRenderParameters parameters(paintParameters);
|
||||
#else
|
||||
style::CustomLayerRenderParameters parameters(paintParameters);
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
#include <mbgl/gfx/drawable_custom_layer_host_tweaker.hpp>
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
|
||||
#if MLN_RENDER_BACKEND_VULKAN
|
||||
#include <mbgl/vulkan/context.hpp>
|
||||
#include <mbgl/vulkan/renderer_backend.hpp>
|
||||
#include <mbgl/style/layers/vulkan/custom_layer_init_parameters.hpp>
|
||||
#endif
|
||||
|
||||
// TODO: platform agnostic error checks
|
||||
#define MBGL_CHECK_ERROR(cmd) (cmd)
|
||||
|
||||
@@ -27,13 +33,27 @@ inline const CustomLayer::Impl& impl(const Immutable<style::Layer::Impl>& impl)
|
||||
return static_cast<const CustomLayer::Impl&>(*impl);
|
||||
}
|
||||
|
||||
void initializeHost(const std::shared_ptr<style::CustomLayerHost>& host, [[maybe_unused]] gfx::Context& context) {
|
||||
#if MLN_RENDER_BACKEND_VULKAN
|
||||
{
|
||||
auto& vkBackend = static_cast<mbgl::vulkan::Context&>(context).getBackend();
|
||||
style::vulkan::CustomLayerInitParameters params(
|
||||
vkBackend.getDispatcher(), vkBackend.getDevice().get(), vkBackend.getPhysicalDevice());
|
||||
host->initialize(params);
|
||||
}
|
||||
#else
|
||||
{
|
||||
style::CustomLayerInitParameters params;
|
||||
host->initialize(params);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
RenderCustomLayer::RenderCustomLayer(Immutable<style::CustomLayer::Impl> _impl)
|
||||
: RenderLayer(makeMutable<CustomLayerProperties>(std::move(_impl))),
|
||||
host(impl(baseImpl).host) {
|
||||
assert(gfx::BackendScope::exists());
|
||||
MBGL_CHECK_ERROR(host->initialize());
|
||||
}
|
||||
|
||||
RenderCustomLayer::~RenderCustomLayer() {
|
||||
@@ -86,7 +106,12 @@ void RenderCustomLayer::update([[maybe_unused]] gfx::ShaderRegistry& shaders,
|
||||
MBGL_CHECK_ERROR(host->deinitialize());
|
||||
}
|
||||
host = impl(baseImpl).host;
|
||||
MBGL_CHECK_ERROR(host->initialize());
|
||||
needsInitialize = true;
|
||||
}
|
||||
|
||||
if (needsInitialize) {
|
||||
MBGL_CHECK_ERROR(initializeHost(host, context));
|
||||
needsInitialize = false;
|
||||
}
|
||||
|
||||
// create drawable
|
||||
|
||||
@@ -27,6 +27,7 @@ private:
|
||||
void prepare(const LayerPrepareParameters&) override;
|
||||
|
||||
bool contextDestroyed = false;
|
||||
bool needsInitialize = true;
|
||||
std::shared_ptr<style::CustomLayerHost> host;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Include this before including custom_layer_render_parameters as custom_layer_render_parameters needs to be
|
||||
// "lightweight". It shouldn't touch the full <mbgl/vulkan/renderer_backend.hpp> as it brings the whole new big
|
||||
#include <mbgl/vulkan/renderer_backend.hpp>
|
||||
#include <mbgl/style/layers/vulkan/custom_layer_render_parameters.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/vulkan/command_encoder.hpp>
|
||||
#include <mbgl/vulkan/render_pass.hpp>
|
||||
#include <mbgl/vulkan/renderable_resource.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
namespace vulkan {
|
||||
|
||||
CustomLayerRenderParameters::CustomLayerRenderParameters(const mbgl::PaintParameters& paintParameters)
|
||||
: mbgl::style::CustomLayerRenderParameters(paintParameters),
|
||||
dispatcher(static_cast<mbgl::vulkan::RendererBackend&>(paintParameters.backend).getDispatcher()) {
|
||||
device = static_cast<mbgl::vulkan::RendererBackend&>(paintParameters.backend).getDevice().get();
|
||||
auto& vulkanRenderPass = static_cast<mbgl::vulkan::RenderPass&>(*paintParameters.renderPass);
|
||||
commandBuffer = vulkanRenderPass.getEncoder().getCommandBuffer().get();
|
||||
|
||||
const auto& renderable = paintParameters.backend.getDefaultRenderable();
|
||||
const auto& resource = renderable.getResource<mbgl::vulkan::RenderableResource>();
|
||||
renderPass = resource.getRenderPass().get();
|
||||
screenPreRotationRadiansClockwise = resource.getRotation();
|
||||
}
|
||||
|
||||
} // namespace vulkan
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
@@ -389,7 +389,7 @@ bool SurfaceRenderableResource::didSurfaceTransformUpdate() const {
|
||||
return capabilities.currentTransform != updatedCapabilities.currentTransform;
|
||||
}
|
||||
|
||||
float SurfaceRenderableResource::getRotation() {
|
||||
float SurfaceRenderableResource::getRotation() const {
|
||||
switch (capabilities.currentTransform) {
|
||||
default:
|
||||
case vk::SurfaceTransformFlagBitsKHR::eIdentity:
|
||||
|
||||
@@ -42,7 +42,7 @@ void main() {
|
||||
|
||||
class TestLayer : public mbgl::style::CustomLayerHost {
|
||||
public:
|
||||
void initialize() override {
|
||||
void initialize(const mbgl::style::CustomLayerInitParameters&) override {
|
||||
program = MBGL_CHECK_ERROR(glCreateProgram());
|
||||
vertexShader = MBGL_CHECK_ERROR(glCreateShader(GL_VERTEX_SHADER));
|
||||
fragmentShader = MBGL_CHECK_ERROR(glCreateShader(GL_FRAGMENT_SHADER));
|
||||
|
||||
Reference in New Issue
Block a user