add possibility to link wgpu library from extern (#4272)
This commit is contained in:
@@ -205,6 +205,18 @@
|
||||
"MLN_WITH_X11": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "linux-webgpu-ffi",
|
||||
"binaryDir": "${sourceDir}/build-linux-webgpu-wgpu-ffi",
|
||||
"inherits": "linux",
|
||||
"cacheVariables": {
|
||||
"MLN_WITH_WEBGPU": "ON",
|
||||
"MLN_WEBGPU_IMPL_WGPU": "ON",
|
||||
"MLN_WEBGPU_IMPL_FFI": "ON",
|
||||
"MLN_WITH_WAYLAND": "OFF",
|
||||
"MLN_WITH_X11": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "android-webgpu-dawn",
|
||||
"displayName": "Android WebGPU (Dawn)",
|
||||
|
||||
@@ -115,7 +115,7 @@ if(MLN_WEBGPU_IMPL_DAWN)
|
||||
if(TARGET mbgl-vendor-dawn)
|
||||
target_link_libraries(mbgl-core PRIVATE mbgl-vendor-dawn)
|
||||
endif()
|
||||
elseif(MLN_WEBGPU_IMPL_WGPU)
|
||||
elseif(MLN_WEBGPU_IMPL_WGPU OR MLN_WEBGPU_IMPL_FFI)
|
||||
# Include wgpu-native integration
|
||||
include(${PROJECT_SOURCE_DIR}/vendor/wgpu.cmake)
|
||||
if(TARGET mbgl-vendor-wgpu)
|
||||
|
||||
@@ -16,6 +16,7 @@ public:
|
||||
bool isRenderable() override;
|
||||
PremultipliedImage readStillImage() override;
|
||||
const gfx::Texture2DPtr& getTexture() override;
|
||||
gfx::Texture2DPtr takeTexture();
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
|
||||
@@ -38,11 +38,11 @@ public:
|
||||
|
||||
// WebGPU-specific methods
|
||||
void setInstance(void* instance);
|
||||
void setDevice(void* device);
|
||||
void setQueue(void* queue);
|
||||
void setDevice(WGPUDevice device);
|
||||
void setQueue(WGPUQueue queue);
|
||||
void* getInstance() const;
|
||||
void* getDevice() const;
|
||||
void* getQueue() const;
|
||||
WGPUDevice getDevice() const;
|
||||
WGPUQueue getQueue() const;
|
||||
void* getSurface() const;
|
||||
|
||||
// Surface texture access - can be overridden by platform backends
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <mbgl/gfx/headless_backend.hpp>
|
||||
#include <mbgl/webgpu/renderer_backend.hpp>
|
||||
#include "mbgl/gfx/offscreen_texture.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
@@ -17,6 +18,12 @@ public:
|
||||
gfx::Renderable& getDefaultRenderable() override;
|
||||
PremultipliedImage readStillImage() override;
|
||||
RendererBackend* getRendererBackend() override;
|
||||
/*!
|
||||
* \brief takeTexture
|
||||
* Take ownership of the current texture
|
||||
* \return
|
||||
*/
|
||||
gfx::Texture2DPtr takeTexture();
|
||||
|
||||
// Override WebGPU-specific methods
|
||||
void* getCurrentTextureView() override;
|
||||
|
||||
@@ -30,6 +30,11 @@ const GeoJSONSource::Impl& GeoJSONSource::impl() const {
|
||||
return static_cast<const Impl&>(*baseImpl);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief GeoJSONSource::setURL
|
||||
* Set the url to a geojson file which can be fetched
|
||||
* \param url_
|
||||
*/
|
||||
void GeoJSONSource::setURL(const std::string& url_) {
|
||||
url = url_;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <mbgl/webgpu/offscreen_texture.hpp>
|
||||
#include <mbgl/util/logging.hpp>
|
||||
#include <mbgl/webgpu/wgpu_cpp_compat.hpp>
|
||||
#include <mbgl/webgpu/texture2d.hpp>
|
||||
|
||||
#if MLN_WEBGPU_IMPL_DAWN
|
||||
#include <dawn/native/DawnNative.h>
|
||||
@@ -84,6 +85,8 @@ public:
|
||||
return PremultipliedImage(size);
|
||||
}
|
||||
|
||||
gfx::Texture2DPtr takeTexture() { return static_cast<OffscreenTexture*>(offscreenTexture.get())->takeTexture(); }
|
||||
|
||||
private:
|
||||
webgpu::Context& context;
|
||||
Size size;
|
||||
@@ -153,7 +156,7 @@ HeadlessBackend::HeadlessBackend(Size size_, SwapBehaviour swapBehaviour_, gfx::
|
||||
setDevice(impl->device.Get());
|
||||
setQueue(impl->queue.Get());
|
||||
setInstance(impl->instance->Get());
|
||||
#elif MLN_WEBGPU_IMPL_WGPU
|
||||
#elif MLN_WEBGPU_IMPL_WGPU && !MLN_WEBGPU_IMPL_FFI
|
||||
// wgpu-native backend initialization
|
||||
wgpu::InstanceDescriptor instanceDesc = {};
|
||||
impl->instance = wgpu::createInstance(instanceDesc);
|
||||
@@ -332,6 +335,13 @@ PremultipliedImage HeadlessBackend::readStillImage() {
|
||||
return PremultipliedImage(getSize());
|
||||
}
|
||||
|
||||
gfx::Texture2DPtr HeadlessBackend::takeTexture() {
|
||||
if (hasResource()) {
|
||||
return getResource<HeadlessRenderableResource>().takeTexture();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RendererBackend* HeadlessBackend::getRendererBackend() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -28,16 +28,7 @@ public:
|
||||
assert(!size.isEmpty());
|
||||
|
||||
// Create color texture
|
||||
colorTexture = context.createTexture2D();
|
||||
colorTexture->setSize(size);
|
||||
colorTexture->setFormat(gfx::TexturePixelType::RGBA, type);
|
||||
if (auto* webgpuTexture = static_cast<Texture2D*>(colorTexture.get())) {
|
||||
webgpuTexture->setUsage(WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst |
|
||||
WGPUTextureUsage_CopySrc | WGPUTextureUsage_RenderAttachment);
|
||||
webgpuTexture->setSizeChangedCallback([this](const Size& newSize) { handleResize(newSize); });
|
||||
}
|
||||
colorTexture->setSamplerConfiguration(
|
||||
{gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
|
||||
colorTexture = createColorTexture();
|
||||
|
||||
// Create depth/stencil texture if needed
|
||||
// WebGPU requires a combined depth-stencil texture when both are needed
|
||||
@@ -304,9 +295,33 @@ public:
|
||||
return colorTexture;
|
||||
}
|
||||
|
||||
gfx::Texture2DPtr takeTexture() {
|
||||
if (!colorTexture) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto taken = std::move(colorTexture);
|
||||
colorTexture = createColorTexture();
|
||||
return taken;
|
||||
}
|
||||
|
||||
void setSizeListener(std::function<void(const Size&)> listener) { sizeListener = std::move(listener); }
|
||||
|
||||
private:
|
||||
gfx::Texture2DPtr createColorTexture() {
|
||||
auto texture = context.createTexture2D();
|
||||
texture->setSize(size);
|
||||
texture->setFormat(gfx::TexturePixelType::RGBA, type);
|
||||
if (auto* webgpuTexture = static_cast<Texture2D*>(texture.get())) {
|
||||
webgpuTexture->setUsage(WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst |
|
||||
WGPUTextureUsage_CopySrc | WGPUTextureUsage_RenderAttachment);
|
||||
webgpuTexture->setSizeChangedCallback([this](const Size& newSize) { handleResize(newSize); });
|
||||
}
|
||||
texture->setSamplerConfiguration(
|
||||
{gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
|
||||
return texture;
|
||||
}
|
||||
|
||||
void handleResize(const Size& newSize) {
|
||||
if (newSize == size || newSize.isEmpty()) {
|
||||
return;
|
||||
@@ -360,5 +375,9 @@ const gfx::Texture2DPtr& OffscreenTexture::getTexture() {
|
||||
return getResource<OffscreenTextureResource>().getTexture();
|
||||
}
|
||||
|
||||
gfx::Texture2DPtr OffscreenTexture::takeTexture() {
|
||||
return getResource<OffscreenTextureResource>().takeTexture();
|
||||
}
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -25,7 +25,9 @@ public:
|
||||
WGPURenderPassEncoder encoder = nullptr;
|
||||
WGPUCommandEncoder commandEncoder = nullptr;
|
||||
const gfx::UniformBufferArray* globalUniformBuffers = nullptr;
|
||||
// Required here because it must life as long as the render pass
|
||||
wgpu::TextureView colorView;
|
||||
// Required here because it must life as long as the render pass
|
||||
wgpu::TextureView depthStencilView;
|
||||
wgpu::TextureFormat previousColorFormat = wgpu::TextureFormat::Undefined;
|
||||
wgpu::TextureFormat previousDepthStencilFormat = wgpu::TextureFormat::Undefined;
|
||||
@@ -183,6 +185,10 @@ RenderPass::RenderPass(CommandEncoder& commandEncoder_, const char* name, const
|
||||
wgpuRenderPassEncoderSetScissorRect(impl->encoder, 0, 0, size.width, size.height);
|
||||
} else {
|
||||
mbgl::Log::Error(mbgl::Event::Render, "WebGPU: Failed to begin render pass");
|
||||
#if MLN_WEBGPU_IMPL_WGPU
|
||||
wgpuTextureViewRelease(impl->colorView);
|
||||
wgpuTextureViewRelease(impl->depthStencilView);
|
||||
#endif
|
||||
impl->colorView = nullptr;
|
||||
impl->depthStencilView = nullptr;
|
||||
}
|
||||
@@ -199,6 +205,15 @@ RenderPass::~RenderPass() {
|
||||
wgpuRenderPassEncoderRelease(impl->encoder);
|
||||
}
|
||||
|
||||
#if MLN_WEBGPU_IMPL_WGPU
|
||||
if (impl->colorView) {
|
||||
wgpuTextureViewRelease(impl->colorView);
|
||||
}
|
||||
if (impl->depthStencilView) {
|
||||
wgpuTextureViewRelease(impl->depthStencilView);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto& backend = static_cast<RendererBackend&>(commandEncoder.getContext().getBackend());
|
||||
if (impl->colorFormatUpdated) {
|
||||
backend.setColorFormat(impl->previousColorFormat);
|
||||
|
||||
@@ -35,8 +35,8 @@ namespace webgpu {
|
||||
class RendererBackend::Impl {
|
||||
public:
|
||||
void* instance = nullptr;
|
||||
void* device = nullptr;
|
||||
void* queue = nullptr;
|
||||
WGPUDevice device = nullptr;
|
||||
WGPUQueue queue = nullptr;
|
||||
void* surface = nullptr;
|
||||
wgpu::TextureFormat depthStencilFormat = wgpu::TextureFormat::Undefined;
|
||||
wgpu::TextureFormat colorFormat = wgpu::TextureFormat::Undefined;
|
||||
@@ -134,11 +134,11 @@ void RendererBackend::setInstance(void* instance) {
|
||||
impl->instance = instance;
|
||||
}
|
||||
|
||||
void RendererBackend::setDevice(void* device) {
|
||||
void RendererBackend::setDevice(WGPUDevice device) {
|
||||
impl->device = device;
|
||||
}
|
||||
|
||||
void RendererBackend::setQueue(void* queue) {
|
||||
void RendererBackend::setQueue(WGPUQueue queue) {
|
||||
impl->queue = queue;
|
||||
}
|
||||
|
||||
@@ -146,11 +146,11 @@ void* RendererBackend::getInstance() const {
|
||||
return impl->instance;
|
||||
}
|
||||
|
||||
void* RendererBackend::getDevice() const {
|
||||
WGPUDevice RendererBackend::getDevice() const {
|
||||
return impl->device;
|
||||
}
|
||||
|
||||
void* RendererBackend::getQueue() const {
|
||||
WGPUQueue RendererBackend::getQueue() const {
|
||||
return impl->queue;
|
||||
}
|
||||
|
||||
|
||||
6
vendor/webgpu.cmake
vendored
6
vendor/webgpu.cmake
vendored
@@ -3,6 +3,8 @@
|
||||
|
||||
set(MLN_WEBGPU_IMPL_DAWN OFF CACHE STRING "WebGPU with Dawn implementation")
|
||||
set(MLN_WEBGPU_IMPL_WGPU OFF CACHE STRING "WebGPU with wgpu implementation")
|
||||
set(MLN_WEBGPU_IMPL_FFI OFF CACHE STRING "WebGPU with ffi interface")
|
||||
set(MLN_WEBGPU_IMPL_WEBGPU_HEADER_DIR "" CACHE STRING "If not empty use this path to the webgpu.h file")
|
||||
|
||||
if(MLN_WITH_WEBGPU)
|
||||
if(MLN_WEBGPU_IMPL_DAWN)
|
||||
@@ -12,9 +14,11 @@ if(MLN_WITH_WEBGPU)
|
||||
elseif(MLN_WEBGPU_IMPL_WGPU)
|
||||
message(STATUS "Using wgpu as WebGPU backend")
|
||||
add_compile_definitions(MLN_WEBGPU_IMPL_WGPU)
|
||||
|
||||
else()
|
||||
message(FATAL_ERROR "MLN_WEBGPU_IMPL_DAWN or MLN_WEBGPU_IMPL_WGPU must be set")
|
||||
endif()
|
||||
|
||||
if (MLN_WEBGPU_IMPL_FFI)
|
||||
add_compile_definitions(MLN_WEBGPU_IMPL_FFI)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
49
vendor/wgpu.cmake
vendored
49
vendor/wgpu.cmake
vendored
@@ -11,9 +11,14 @@ endif()
|
||||
message(STATUS "Configuring wgpu-native WebGPU implementation")
|
||||
|
||||
set(_mln_wgpu_source_dir "${PROJECT_SOURCE_DIR}/vendor/wgpu-native")
|
||||
if ("${MLN_WEBGPU_IMPL_FFI_BUNDLED_WEBGPU_HEADER}" STREQUAL "")
|
||||
set(WEBGPU_H_DIR ${_mln_wgpu_source_dir}/ffi/webgpu-headers)
|
||||
else()
|
||||
set(WEBGPU_H_DIR ${MLN_WEBGPU_IMPL_WEBGPU_HEADER_DIR})
|
||||
endif()
|
||||
|
||||
# Check if wgpu-native exists
|
||||
if(NOT EXISTS "${_mln_wgpu_source_dir}/ffi/webgpu-headers/webgpu.h")
|
||||
if(NOT EXISTS "${WEBGPU_H_DIR}/webgpu.h")
|
||||
message(FATAL_ERROR
|
||||
"wgpu-native not found at ${_mln_wgpu_source_dir}. "
|
||||
"Please ensure the wgpu-native submodule is initialized: "
|
||||
@@ -78,7 +83,8 @@ macro(mln_wgpu_find_exact_library out_var out_description)
|
||||
endmacro()
|
||||
|
||||
# On Android/iOS, use manual path search since find_library may not work with cross-compilation toolchains
|
||||
macro(mln_wgpu_find_library)
|
||||
if (NOT MLN_WEBGPU_IMPL_FFI)
|
||||
macro(mln_wgpu_find_library)
|
||||
if(ANDROID OR CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||
mln_wgpu_find_exact_library(WGPU_LIBRARY "wgpu-native library")
|
||||
else()
|
||||
@@ -89,12 +95,13 @@ macro(mln_wgpu_find_library)
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
)
|
||||
endif()
|
||||
endmacro()
|
||||
endmacro()
|
||||
|
||||
mln_wgpu_find_library()
|
||||
mln_wgpu_find_exact_library(WGPU_STATIC_LIBRARY "wgpu-native static library")
|
||||
mln_wgpu_find_library()
|
||||
mln_wgpu_find_exact_library(WGPU_STATIC_LIBRARY "wgpu-native static library")
|
||||
endif()
|
||||
|
||||
if(NOT WGPU_LIBRARY OR MLN_WGPU_NATIVE_VERSION)
|
||||
if(NOT MLN_WEBGPU_IMPL_FFI AND (NOT WGPU_LIBRARY OR MLN_WGPU_NATIVE_VERSION))
|
||||
# Use a specific version of WGPU. This is required when to a rust application
|
||||
# which uses wgpu directly instead of wgpu-native
|
||||
if (MLN_WGPU_NATIVE_VERSION)
|
||||
@@ -204,7 +211,7 @@ if(NOT EXISTS "${_webgpu_cpp_header}")
|
||||
execute_process(
|
||||
COMMAND ${PYTHON_EXECUTABLE} generate.py
|
||||
--use-init-macros
|
||||
--header ${_mln_wgpu_source_dir}/ffi/webgpu-headers/webgpu.h
|
||||
--header ${WEBGPU_H_DIR}/webgpu.h
|
||||
--output ${_webgpu_cpp_header}
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/vendor/webgpu-cpp"
|
||||
RESULT_VARIABLE _gen_result
|
||||
@@ -278,24 +285,26 @@ endif()
|
||||
# Create interface library
|
||||
add_library(mbgl-vendor-wgpu INTERFACE)
|
||||
|
||||
# For the ffi we don't link the wgpu library, because we link in the final stage with the rust wgpu version
|
||||
target_link_libraries(mbgl-vendor-wgpu INTERFACE ${WGPU_LIBRARY})
|
||||
|
||||
# Add include directories for webgpu.h, wgpu.h, and C++ wrapper
|
||||
target_include_directories(mbgl-vendor-wgpu
|
||||
SYSTEM INTERFACE
|
||||
${_webgpu-cpp-output_dir} # For webgpu.hpp webgpu/webgpu_cpp.h compatibility shim
|
||||
${_mln_wgpu_source_dir}/ffi/webgpu-headers # webgpu.h
|
||||
${WEBGPU_H_DIR}
|
||||
${_mln_wgpu_source_dir}/ffi # wgpu.h
|
||||
)
|
||||
|
||||
# Platform-specific system libraries that wgpu-native needs
|
||||
if(APPLE)
|
||||
if (NOT MLN_WEBGPU_IMPL_FFI)
|
||||
if(APPLE)
|
||||
target_link_libraries(mbgl-vendor-wgpu INTERFACE
|
||||
"-framework Foundation"
|
||||
"-framework QuartzCore"
|
||||
"-framework Metal"
|
||||
)
|
||||
elseif(WIN32)
|
||||
elseif(WIN32)
|
||||
target_link_libraries(mbgl-vendor-wgpu INTERFACE
|
||||
d3d12
|
||||
dxgi
|
||||
@@ -305,15 +314,16 @@ elseif(WIN32)
|
||||
bcrypt
|
||||
ntdll
|
||||
)
|
||||
elseif(ANDROID)
|
||||
elseif(ANDROID)
|
||||
mln_wgpu_android_link_library(mbgl-vendor-wgpu)
|
||||
else() # Linux
|
||||
else() # Linux
|
||||
# wgpu-native on Linux might need these depending on the build configuration
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(mbgl-vendor-wgpu INTERFACE
|
||||
Threads::Threads
|
||||
${CMAKE_DL_LIBS}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Suppress warnings from wgpu headers
|
||||
@@ -324,11 +334,22 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(
|
||||
if (NOT MLN_WEBGPU_IMPL_FFI)
|
||||
set_target_properties(
|
||||
mbgl-vendor-wgpu
|
||||
PROPERTIES
|
||||
INTERFACE_MAPLIBRE_NAME "wgpu-native"
|
||||
INTERFACE_MAPLIBRE_URL "https://github.com/gfx-rs/wgpu-native"
|
||||
INTERFACE_MAPLIBRE_AUTHOR "gfx-rs developers"
|
||||
INTERFACE_MAPLIBRE_LICENSE "${PROJECT_SOURCE_DIR}/vendor/wgpu-native/LICENSE.MIT"
|
||||
)
|
||||
)
|
||||
else()
|
||||
set_target_properties(
|
||||
mbgl-vendor-wgpu
|
||||
PROPERTIES
|
||||
INTERFACE_MAPLIBRE_NAME "wgpu-ffi"
|
||||
INTERFACE_MAPLIBRE_URL "https://github.com/maplibre/maplibre-native"
|
||||
INTERFACE_MAPLIBRE_AUTHOR "Maplibre Contributors"
|
||||
INTERFACE_MAPLIBRE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE.md"
|
||||
)
|
||||
endif()
|
||||
|
||||
Reference in New Issue
Block a user