Add WebGPU Backend w/ Dawn Support (#3838)
This commit is contained in:
65
include/mbgl/webgpu/buffer_resource.hpp
Normal file
65
include/mbgl/webgpu/buffer_resource.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <webgpu/webgpu.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
namespace webgpu {
|
||||
|
||||
class Context;
|
||||
|
||||
class BufferResource {
|
||||
public:
|
||||
BufferResource() noexcept = delete;
|
||||
BufferResource(Context& context,
|
||||
const void* data,
|
||||
std::size_t size,
|
||||
uint32_t usage,
|
||||
bool isIndexBuffer = false,
|
||||
bool persistent = false);
|
||||
BufferResource(BufferResource&&) noexcept;
|
||||
virtual ~BufferResource() noexcept;
|
||||
|
||||
BufferResource& operator=(BufferResource&&) noexcept;
|
||||
|
||||
BufferResource clone() const;
|
||||
|
||||
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(); }
|
||||
|
||||
Context& getContext() const noexcept { return context; }
|
||||
WGPUBuffer getBuffer() const noexcept { return buffer; }
|
||||
|
||||
bool isValid() const noexcept { return buffer || !raw.empty(); }
|
||||
operator bool() const noexcept { return isValid(); }
|
||||
bool operator!() const noexcept { return !isValid(); }
|
||||
|
||||
using VersionType = std::uint16_t;
|
||||
|
||||
/// Used to detect whether buffer contents have changed
|
||||
VersionType getVersion() const noexcept { return version; }
|
||||
|
||||
/// Indicates whether this buffer needs to be re-bound from a previous binding at the given version
|
||||
bool needReBind(VersionType version) const noexcept;
|
||||
|
||||
uint32_t getUsage() const { return usage; }
|
||||
bool isPersistent() const { return persistent; }
|
||||
|
||||
protected:
|
||||
Context& context;
|
||||
WGPUBuffer buffer = nullptr;
|
||||
std::vector<std::uint8_t> raw;
|
||||
std::size_t size = 0;
|
||||
uint32_t usage = 0;
|
||||
std::uint16_t version = 0;
|
||||
bool isIndexBuffer = false;
|
||||
bool persistent = false;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
84
include/mbgl/webgpu/command_encoder.hpp
Normal file
84
include/mbgl/webgpu/command_encoder.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/command_encoder.hpp>
|
||||
#include <mbgl/util/containers.hpp>
|
||||
#include <webgpu/webgpu.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
class Renderable;
|
||||
} // namespace gfx
|
||||
|
||||
namespace webgpu {
|
||||
|
||||
class Context;
|
||||
class RenderPass;
|
||||
class UploadPass;
|
||||
|
||||
class CommandEncoder final : public gfx::CommandEncoder {
|
||||
public:
|
||||
explicit CommandEncoder(Context& context_);
|
||||
~CommandEncoder() override;
|
||||
|
||||
webgpu::Context& getContext() { return context; }
|
||||
const webgpu::Context& getContext() const { return context; }
|
||||
WGPUCommandEncoder getEncoder() const { return encoder; }
|
||||
|
||||
std::unique_ptr<gfx::UploadPass> createUploadPass(const char* name, gfx::Renderable&) override;
|
||||
std::unique_ptr<gfx::RenderPass> createRenderPass(const char* name, const gfx::RenderPassDescriptor&) override;
|
||||
|
||||
void present(gfx::Renderable&) override;
|
||||
|
||||
// WebGPU-specific: submit command buffer directly
|
||||
void submitCommandBuffer();
|
||||
|
||||
template <typename TFunc>
|
||||
void visitDebugGroups(TFunc f) {
|
||||
for (const auto& item : debugGroupNames) {
|
||||
f(item.name);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class RenderPass;
|
||||
friend class UploadPass;
|
||||
|
||||
// Track a RenderPass, propagating debug groups to it
|
||||
void trackRenderPass(RenderPass*);
|
||||
// Stop tracking a RenderPass
|
||||
void forgetRenderPass(RenderPass*);
|
||||
|
||||
// Track an UploadPass, propagating debug groups to it
|
||||
void trackUploadPass(UploadPass*);
|
||||
// Stop tracking a RenderPass
|
||||
void forgetUploadPass(UploadPass*);
|
||||
|
||||
void pushDebugGroup(const char* name) override;
|
||||
void popDebugGroup() override;
|
||||
|
||||
protected:
|
||||
struct GroupEntry {
|
||||
std::string name;
|
||||
std::size_t renderGroups;
|
||||
std::size_t uploadGroups;
|
||||
};
|
||||
|
||||
protected:
|
||||
webgpu::Context& context;
|
||||
WGPUCommandEncoder encoder = nullptr;
|
||||
std::vector<GroupEntry> debugGroupNames;
|
||||
std::vector<gfx::DebugGroup<gfx::RenderPass>> renderDebugGroups;
|
||||
std::vector<gfx::DebugGroup<gfx::UploadPass>> uploadDebugGroups;
|
||||
mbgl::unordered_set<RenderPass*> renderPasses;
|
||||
mbgl::unordered_set<UploadPass*> uploadPasses;
|
||||
UploadPass* currentUploadPass = nullptr;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
132
include/mbgl/webgpu/context.hpp
Normal file
132
include/mbgl/webgpu/context.hpp
Normal file
@@ -0,0 +1,132 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/context.hpp>
|
||||
#include <mbgl/gfx/vertex_buffer.hpp>
|
||||
#include <mbgl/webgpu/renderer_backend.hpp>
|
||||
#include <mbgl/webgpu/buffer_resource.hpp>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace mbgl {
|
||||
class RenderStaticData;
|
||||
namespace gfx {
|
||||
// Forward declaration
|
||||
class AttributeBinding;
|
||||
using AttributeBindingArray = std::vector<std::optional<AttributeBinding>>;
|
||||
class RenderPass;
|
||||
class Renderable;
|
||||
class ShaderProgramBase;
|
||||
} // namespace gfx
|
||||
|
||||
namespace shaders {
|
||||
struct ClipUBO;
|
||||
} // namespace shaders
|
||||
|
||||
namespace webgpu {
|
||||
|
||||
// Forward declaration
|
||||
class VertexBufferResource;
|
||||
|
||||
class Context : public gfx::Context {
|
||||
public:
|
||||
explicit Context(RendererBackend& backend);
|
||||
~Context() override;
|
||||
|
||||
RendererBackend& getBackend() { return backend; }
|
||||
const RendererBackend& getBackend() const { return backend; }
|
||||
|
||||
// Frame management
|
||||
void beginFrame() override;
|
||||
void endFrame() override;
|
||||
void performCleanup() override;
|
||||
void reduceMemoryUsage() override;
|
||||
|
||||
// Resource creation
|
||||
std::unique_ptr<gfx::OffscreenTexture> createOffscreenTexture(Size, gfx::TextureChannelDataType, bool, bool);
|
||||
std::unique_ptr<gfx::OffscreenTexture> createOffscreenTexture(Size, gfx::TextureChannelDataType) override;
|
||||
std::unique_ptr<gfx::CommandEncoder> createCommandEncoder() override;
|
||||
gfx::VertexAttributeArrayPtr createVertexAttributeArray() const override;
|
||||
gfx::UniqueDrawableBuilder createDrawableBuilder(std::string name) override;
|
||||
gfx::UniformBufferPtr createUniformBuffer(const void* data,
|
||||
std::size_t size,
|
||||
bool persistent = false,
|
||||
bool ssbo = false) override;
|
||||
gfx::UniqueUniformBufferArray createLayerUniformBufferArray() override;
|
||||
gfx::ShaderProgramBasePtr getGenericShader(gfx::ShaderRegistry&, const std::string& name) override;
|
||||
TileLayerGroupPtr createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) override;
|
||||
LayerGroupPtr createLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) override;
|
||||
gfx::Texture2DPtr createTexture2D() override;
|
||||
RenderTargetPtr createRenderTarget(const Size size, const gfx::TextureChannelDataType type) override;
|
||||
|
||||
// State management
|
||||
void resetState(gfx::DepthMode depthMode, gfx::ColorMode colorMode) override;
|
||||
void setDirtyState() override;
|
||||
void clearStencilBuffer(int32_t) override;
|
||||
|
||||
// Uniform buffer management
|
||||
bool emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr&,
|
||||
const void* data,
|
||||
std::size_t size,
|
||||
bool persistent = false) override;
|
||||
const gfx::UniformBufferArray& getGlobalUniformBuffers() const override;
|
||||
gfx::UniformBufferArray& mutableGlobalUniformBuffers() override;
|
||||
void bindGlobalUniformBuffers(gfx::RenderPass&) const noexcept override;
|
||||
void unbindGlobalUniformBuffers(gfx::RenderPass&) const noexcept override;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
void visualizeStencilBuffer() override;
|
||||
void visualizeDepthBuffer(float depthRangeSize) override;
|
||||
#endif
|
||||
|
||||
// Buffer creation (aligned with Metal)
|
||||
BufferResource createBuffer(
|
||||
const void* data, std::size_t size, uint32_t usage, bool isIndexBuffer, bool persistent) const;
|
||||
|
||||
// Get reusable buffers (aligned with Metal)
|
||||
const BufferResource& getTileVertexBuffer();
|
||||
const BufferResource& getTileIndexBuffer();
|
||||
|
||||
// Tile clipping mask rendering
|
||||
bool renderTileClippingMasks(gfx::RenderPass& renderPass,
|
||||
RenderStaticData& staticData,
|
||||
const std::vector<shaders::ClipUBO>& tileUBOs);
|
||||
|
||||
// Command encoder tracking
|
||||
class CommandEncoder* getCurrentCommandEncoder() const { return currentCommandEncoder; }
|
||||
void setCurrentCommandEncoder(class CommandEncoder* encoder) { currentCommandEncoder = encoder; }
|
||||
|
||||
// Vertex binding creation - needed for drawable geometry
|
||||
gfx::AttributeBindingArray getOrCreateVertexBindings(gfx::Context&,
|
||||
const gfx::AttributeDataType vertexType,
|
||||
const size_t vertexAttributeIndex,
|
||||
const std::vector<uint8_t>& vertexData,
|
||||
const gfx::VertexAttributeArray& defaults,
|
||||
const gfx::VertexAttributeArray& overrides,
|
||||
gfx::BufferUsageType,
|
||||
const std::optional<std::chrono::duration<double>>&,
|
||||
std::shared_ptr<webgpu::VertexBufferResource>&) noexcept;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<gfx::RenderbufferResource> createRenderbufferResource(gfx::RenderbufferPixelType, Size) override;
|
||||
std::unique_ptr<gfx::DrawScopeResource> createDrawScopeResource() override;
|
||||
|
||||
private:
|
||||
RendererBackend& backend;
|
||||
std::unique_ptr<gfx::UniformBufferArray> globalUniformBuffers;
|
||||
class CommandEncoder* currentCommandEncoder = nullptr;
|
||||
|
||||
// Cached buffers (aligned with Metal)
|
||||
std::optional<BufferResource> tileVertexBuffer;
|
||||
std::optional<BufferResource> tileIndexBuffer;
|
||||
|
||||
// Cached clipping resources
|
||||
gfx::ShaderProgramBasePtr clipMaskShader;
|
||||
const gfx::Renderable* clipMaskRenderable = nullptr;
|
||||
std::optional<std::size_t> clipMaskPipelineHash;
|
||||
std::vector<BufferResource> clipMaskUniformBuffers;
|
||||
std::vector<WGPUBindGroup> clipMaskActiveBindGroups;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
20
include/mbgl/webgpu/draw_scope_resource.hpp
Normal file
20
include/mbgl/webgpu/draw_scope_resource.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/draw_scope.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace webgpu {
|
||||
|
||||
class Context;
|
||||
|
||||
class DrawScopeResource : public gfx::DrawScopeResource {
|
||||
public:
|
||||
explicit DrawScopeResource(Context& context);
|
||||
~DrawScopeResource() override = default;
|
||||
|
||||
private:
|
||||
Context& context;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
64
include/mbgl/webgpu/drawable.hpp
Normal file
64
include/mbgl/webgpu/drawable.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/drawable.hpp>
|
||||
#include <mbgl/gfx/draw_mode.hpp>
|
||||
#include <webgpu/webgpu.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// Forward declare WebGPU types
|
||||
typedef struct WGPUBindGroupLayoutImpl* WGPUBindGroupLayout;
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
class UploadPass;
|
||||
class DepthMode;
|
||||
class StencilMode;
|
||||
} // namespace gfx
|
||||
|
||||
namespace webgpu {
|
||||
|
||||
class CommandEncoder;
|
||||
class UploadPass;
|
||||
class RenderPipeline;
|
||||
|
||||
class Drawable : public gfx::Drawable {
|
||||
public:
|
||||
Drawable(std::string name);
|
||||
~Drawable() override;
|
||||
|
||||
void upload(gfx::UploadPass&);
|
||||
void draw(PaintParameters&) const override;
|
||||
|
||||
void setIndexData(gfx::IndexVectorBasePtr, std::vector<UniqueDrawSegment> segments) override;
|
||||
void setVertices(std::vector<uint8_t>&&, std::size_t, gfx::AttributeDataType) override;
|
||||
|
||||
const gfx::UniformBufferArray& getUniformBuffers() const override;
|
||||
gfx::UniformBufferArray& mutableUniformBuffers() override;
|
||||
|
||||
void setColorMode(const gfx::ColorMode&) override;
|
||||
|
||||
void setShader(gfx::ShaderProgramBasePtr) override;
|
||||
|
||||
void setEnableStencil(bool) override;
|
||||
void setEnableDepth(bool) override;
|
||||
void setSubLayerIndex(int32_t) override;
|
||||
void setDepthType(gfx::DepthMaskType) override;
|
||||
void setDepthModeFor3D(const gfx::DepthMode&);
|
||||
void setStencilModeFor3D(const gfx::StencilMode&);
|
||||
|
||||
void setVertexAttrId(const size_t);
|
||||
|
||||
void updateVertexAttributes(gfx::VertexAttributeArrayPtr,
|
||||
std::size_t vertexCount,
|
||||
gfx::DrawMode,
|
||||
gfx::IndexVectorBasePtr,
|
||||
const SegmentBase* segments,
|
||||
std::size_t segmentCount) override;
|
||||
|
||||
class Impl;
|
||||
const std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
29
include/mbgl/webgpu/drawable_builder.hpp
Normal file
29
include/mbgl/webgpu/drawable_builder.hpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/drawable_builder.hpp>
|
||||
#include <mbgl/webgpu/drawable.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
namespace webgpu {
|
||||
|
||||
class Context;
|
||||
|
||||
class DrawableBuilder : public gfx::DrawableBuilder {
|
||||
public:
|
||||
explicit DrawableBuilder(std::string name);
|
||||
~DrawableBuilder() override;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<gfx::Drawable> createDrawable() const override;
|
||||
std::unique_ptr<gfx::Drawable::DrawSegment> createSegment(gfx::DrawMode, SegmentBase&&) override;
|
||||
void init() override;
|
||||
|
||||
private:
|
||||
// WebGPU-specific drawable configuration is handled in the drawable implementation
|
||||
// Pipeline, buffers, and textures are managed by the Context and Drawable classes
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
33
include/mbgl/webgpu/index_buffer_resource.hpp
Normal file
33
include/mbgl/webgpu/index_buffer_resource.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/index_buffer.hpp>
|
||||
#include <mbgl/webgpu/buffer_resource.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace webgpu {
|
||||
|
||||
class IndexBufferResource : public gfx::IndexBufferResource {
|
||||
public:
|
||||
IndexBufferResource(BufferResource&&) noexcept;
|
||||
IndexBufferResource(IndexBufferResource&& other) noexcept
|
||||
: buffer(std::move(other.buffer)) {}
|
||||
~IndexBufferResource() noexcept override;
|
||||
|
||||
std::size_t getSizeInBytes() const noexcept { return buffer.getSizeInBytes(); }
|
||||
const void* contents() const noexcept { return buffer.contents(); }
|
||||
|
||||
BufferResource& get() noexcept { return buffer; }
|
||||
const BufferResource& get() const noexcept { return buffer; }
|
||||
|
||||
// Compatibility with existing code
|
||||
const BufferResource& getBuffer() const { return buffer; }
|
||||
BufferResource& getBuffer() { return buffer; }
|
||||
|
||||
void update(const void* data, std::size_t size) { buffer.update(data, size, 0); }
|
||||
|
||||
protected:
|
||||
BufferResource buffer;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
31
include/mbgl/webgpu/layer_group.hpp
Normal file
31
include/mbgl/webgpu/layer_group.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/webgpu/uniform_buffer.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class PaintParameters;
|
||||
|
||||
namespace webgpu {
|
||||
|
||||
/**
|
||||
* A layer group for non-tile-based drawables
|
||||
*/
|
||||
class LayerGroup : public mbgl::LayerGroup {
|
||||
public:
|
||||
LayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name);
|
||||
~LayerGroup() override {}
|
||||
|
||||
void upload(gfx::UploadPass&) override;
|
||||
void render(RenderOrchestrator&, PaintParameters&) override;
|
||||
|
||||
const gfx::UniformBufferArray& getUniformBuffers() const override { return uniformBuffers; }
|
||||
gfx::UniformBufferArray& mutableUniformBuffers() override { return uniformBuffers; }
|
||||
|
||||
protected:
|
||||
webgpu::UniformBufferArray uniformBuffers;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
22
include/mbgl/webgpu/offscreen_texture.hpp
Normal file
22
include/mbgl/webgpu/offscreen_texture.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/offscreen_texture.hpp>
|
||||
#include <mbgl/gfx/types.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace webgpu {
|
||||
|
||||
class Context;
|
||||
class Texture2D;
|
||||
|
||||
class OffscreenTexture final : public gfx::OffscreenTexture {
|
||||
public:
|
||||
OffscreenTexture(Context&, Size size, gfx::TextureChannelDataType type, bool depth, bool stencil);
|
||||
|
||||
bool isRenderable() override;
|
||||
PremultipliedImage readStillImage() override;
|
||||
const gfx::Texture2DPtr& getTexture() override;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
52
include/mbgl/webgpu/render_pass.hpp
Normal file
52
include/mbgl/webgpu/render_pass.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/render_pass.hpp>
|
||||
#include <memory>
|
||||
|
||||
// Forward declare WebGPU types
|
||||
typedef struct WGPURenderPassEncoderImpl* WGPURenderPassEncoder;
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
class CommandEncoder;
|
||||
class UniformBufferArray;
|
||||
} // namespace gfx
|
||||
|
||||
namespace webgpu {
|
||||
|
||||
class CommandEncoder;
|
||||
|
||||
class RenderPass final : public gfx::RenderPass {
|
||||
public:
|
||||
RenderPass(CommandEncoder& commandEncoder, const char* name, const gfx::RenderPassDescriptor& descriptor);
|
||||
~RenderPass() override;
|
||||
|
||||
// Match Metal's interface
|
||||
CommandEncoder& getCommandEncoder() { return commandEncoder; }
|
||||
const CommandEncoder& getCommandEncoder() const { return commandEncoder; }
|
||||
|
||||
// Get the WebGPU render pass encoder (similar to Metal's getMetalEncoder)
|
||||
WGPURenderPassEncoder getEncoder() const;
|
||||
const gfx::RenderPassDescriptor& getDescriptor() const { return descriptor; }
|
||||
|
||||
// Set/get global uniform buffers for drawables to access
|
||||
void setGlobalUniformBuffers(const gfx::UniformBufferArray* buffers);
|
||||
const gfx::UniformBufferArray* getGlobalUniformBuffers() const;
|
||||
|
||||
private:
|
||||
void pushDebugGroup(const char* name) override;
|
||||
void popDebugGroup() override;
|
||||
void addDebugSignpost(const char* name) override;
|
||||
|
||||
private:
|
||||
gfx::RenderPassDescriptor descriptor;
|
||||
CommandEncoder& commandEncoder;
|
||||
const gfx::DebugGroup<gfx::CommandEncoder> debugGroup;
|
||||
|
||||
// Implementation details
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
54
include/mbgl/webgpu/renderable_resource.hpp
Normal file
54
include/mbgl/webgpu/renderable_resource.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/renderable.hpp>
|
||||
#include <mbgl/webgpu/wgpu_cpp_compat.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <optional>
|
||||
|
||||
namespace mbgl {
|
||||
namespace webgpu {
|
||||
|
||||
class RendererBackend;
|
||||
|
||||
class RenderableResource : public gfx::RenderableResource {
|
||||
protected:
|
||||
explicit RenderableResource() = default;
|
||||
|
||||
public:
|
||||
void bind() override {
|
||||
// WebGPU binding happens at the command encoder level
|
||||
// This is a no-op for now
|
||||
}
|
||||
|
||||
virtual void swap() {
|
||||
// Renderable resources that require a swap function to be called
|
||||
// explicitly can override this method.
|
||||
}
|
||||
|
||||
virtual const mbgl::webgpu::RendererBackend& getBackend() const = 0;
|
||||
virtual const WGPUCommandEncoder& getCommandEncoder() const = 0;
|
||||
virtual WGPURenderPassEncoder getRenderPassEncoder() const = 0;
|
||||
|
||||
/**
|
||||
* Obtain a texture view that should be bound as the color attachment for
|
||||
* the render pass targeting this resource. Implementations should return a
|
||||
* valid `WGPUTextureView` or `nullptr` if the resource relies on the
|
||||
* backend to supply the swapchain view (e.g. default framebuffer).
|
||||
*/
|
||||
virtual WGPUTextureView getColorTextureView() { return nullptr; }
|
||||
|
||||
virtual std::optional<wgpu::TextureFormat> getColorTextureFormat() const { return std::nullopt; }
|
||||
|
||||
/**
|
||||
* Obtain a depth/stencil texture view for the render pass if the resource
|
||||
* manages one. Returning `nullptr` indicates that the backend-provided
|
||||
* depth/stencil view (if any) should be used instead.
|
||||
*/
|
||||
virtual WGPUTextureView getDepthStencilTextureView() { return nullptr; }
|
||||
|
||||
virtual std::optional<wgpu::TextureFormat> getDepthStencilTextureFormat() const { return std::nullopt; }
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
62
include/mbgl/webgpu/renderer_backend.hpp
Normal file
62
include/mbgl/webgpu/renderer_backend.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/renderer_backend.hpp>
|
||||
#include <mbgl/util/size.hpp>
|
||||
#include <mbgl/webgpu/wgpu_cpp_compat.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class ProgramParameters;
|
||||
|
||||
namespace gfx {
|
||||
class ShaderRegistry;
|
||||
}
|
||||
|
||||
namespace webgpu {
|
||||
|
||||
class Context;
|
||||
|
||||
class RendererBackend : public gfx::RendererBackend {
|
||||
public:
|
||||
explicit RendererBackend(gfx::ContextMode);
|
||||
~RendererBackend() override;
|
||||
|
||||
// getDefaultRenderable() is pure virtual - must be implemented by platform backends
|
||||
// Platform backends typically inherit from gfx::Renderable and return *this
|
||||
void initShaders(gfx::ShaderRegistry&, const ProgramParameters&) override;
|
||||
|
||||
// Platform-specific surface creation
|
||||
void setSurface(void* nativeWindow);
|
||||
|
||||
// WebGPU-specific methods
|
||||
void setInstance(void* instance);
|
||||
void setDevice(void* device);
|
||||
void setQueue(void* queue);
|
||||
void* getInstance() const;
|
||||
void* getDevice() const;
|
||||
void* getQueue() const;
|
||||
void* getSurface() const;
|
||||
|
||||
// Surface texture access - can be overridden by platform backends
|
||||
virtual void* getCurrentTextureView();
|
||||
virtual void* getDepthStencilView();
|
||||
virtual mbgl::Size getFramebufferSize() const;
|
||||
|
||||
void setDepthStencilFormat(wgpu::TextureFormat);
|
||||
wgpu::TextureFormat getDepthStencilFormat() const;
|
||||
void setColorFormat(wgpu::TextureFormat);
|
||||
wgpu::TextureFormat getColorFormat() const;
|
||||
|
||||
protected:
|
||||
std::unique_ptr<gfx::Context> createContext() override;
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
64
include/mbgl/webgpu/texture2d.hpp
Normal file
64
include/mbgl/webgpu/texture2d.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/texture2d.hpp>
|
||||
#include <webgpu/webgpu.h>
|
||||
#include <mbgl/util/image.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
namespace webgpu {
|
||||
|
||||
class Context;
|
||||
class RenderPass;
|
||||
|
||||
class Texture2D : public gfx::Texture2D {
|
||||
public:
|
||||
Texture2D(Context& context_);
|
||||
~Texture2D() override;
|
||||
|
||||
gfx::Texture2D& setSamplerConfiguration(const SamplerState&) noexcept override;
|
||||
gfx::Texture2D& setFormat(gfx::TexturePixelType, gfx::TextureChannelDataType) noexcept override;
|
||||
gfx::Texture2D& setSize(Size size_) noexcept override;
|
||||
gfx::Texture2D& setImage(std::shared_ptr<PremultipliedImage>) noexcept override;
|
||||
Texture2D& setUsage(uint32_t usageFlags_) noexcept;
|
||||
void setSizeChangedCallback(std::function<void(const Size&)>) noexcept;
|
||||
WGPUTextureFormat getNativeFormat() const noexcept { return nativeFormat; }
|
||||
|
||||
gfx::TexturePixelType getFormat() const noexcept override { return pixelFormat; }
|
||||
Size getSize() const noexcept override { return size; }
|
||||
size_t getDataSize() const noexcept override;
|
||||
size_t getPixelStride() const noexcept override;
|
||||
size_t numChannels() const noexcept override;
|
||||
|
||||
void create() noexcept override;
|
||||
void upload(const void* pixelData, const Size& size) noexcept override;
|
||||
void upload() noexcept override;
|
||||
void uploadSubRegion(const void* pixelData, const Size& size, uint16_t xOffset, uint16_t yOffset) noexcept override;
|
||||
bool needsUpload() const noexcept override { return dirty; }
|
||||
|
||||
WGPUTexture getTexture() const { return texture; }
|
||||
WGPUTextureView getTextureView() const { return textureView; }
|
||||
WGPUSampler getSampler() const { return sampler; }
|
||||
const SamplerState& getSamplerState() const noexcept { return samplerState; }
|
||||
|
||||
protected:
|
||||
Context& context;
|
||||
WGPUTexture texture = nullptr;
|
||||
WGPUTextureView textureView = nullptr;
|
||||
WGPUSampler sampler = nullptr;
|
||||
uint32_t usageFlags = WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst | WGPUTextureUsage_CopySrc;
|
||||
WGPUTextureFormat nativeFormat = WGPUTextureFormat_Undefined;
|
||||
|
||||
Size size{0, 0};
|
||||
gfx::TexturePixelType pixelFormat = gfx::TexturePixelType::RGBA;
|
||||
gfx::TextureChannelDataType channelType = gfx::TextureChannelDataType::UnsignedByte;
|
||||
SamplerState samplerState;
|
||||
std::shared_ptr<PremultipliedImage> image;
|
||||
bool dirty = false;
|
||||
std::function<void(const Size&)> sizeChangedCallback;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
#include <functional>
|
||||
31
include/mbgl/webgpu/tile_layer_group.hpp
Normal file
31
include/mbgl/webgpu/tile_layer_group.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/renderer/layer_group.hpp>
|
||||
#include <mbgl/webgpu/uniform_buffer.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class PaintParameters;
|
||||
|
||||
namespace webgpu {
|
||||
|
||||
/**
|
||||
* A layer group for tile-based drawables
|
||||
*/
|
||||
class TileLayerGroup : public mbgl::TileLayerGroup {
|
||||
public:
|
||||
TileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name);
|
||||
~TileLayerGroup() override {}
|
||||
|
||||
void upload(gfx::UploadPass&) override;
|
||||
void render(RenderOrchestrator&, PaintParameters&) override;
|
||||
|
||||
const gfx::UniformBufferArray& getUniformBuffers() const override { return uniformBuffers; }
|
||||
gfx::UniformBufferArray& mutableUniformBuffers() override { return uniformBuffers; }
|
||||
|
||||
protected:
|
||||
webgpu::UniformBufferArray uniformBuffers;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
60
include/mbgl/webgpu/uniform_buffer.hpp
Normal file
60
include/mbgl/webgpu/uniform_buffer.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/uniform_buffer.hpp>
|
||||
#include <webgpu/webgpu.h>
|
||||
|
||||
namespace mbgl {
|
||||
namespace webgpu {
|
||||
|
||||
class Context;
|
||||
class RenderPass;
|
||||
|
||||
class UniformBuffer final : public gfx::UniformBuffer {
|
||||
public:
|
||||
UniformBuffer(Context& context, const void* data, std::size_t size);
|
||||
~UniformBuffer() override;
|
||||
|
||||
UniformBuffer(const UniformBuffer&) = delete;
|
||||
UniformBuffer(UniformBuffer&& other) noexcept;
|
||||
UniformBuffer& operator=(const UniformBuffer&) = delete;
|
||||
UniformBuffer& operator=(UniformBuffer&&) = delete;
|
||||
|
||||
UniformBuffer clone() const;
|
||||
|
||||
void update(const void* data, std::size_t dataSize) override;
|
||||
|
||||
WGPUBuffer getBuffer() const { return buffer; }
|
||||
|
||||
private:
|
||||
Context& context;
|
||||
WGPUBuffer buffer = nullptr;
|
||||
};
|
||||
|
||||
/// Stores a collection of uniform buffers by name
|
||||
class UniformBufferArray final : public gfx::UniformBufferArray {
|
||||
public:
|
||||
UniformBufferArray() = default;
|
||||
UniformBufferArray(UniformBufferArray&& other)
|
||||
: gfx::UniformBufferArray(std::move(other)) {}
|
||||
UniformBufferArray(const UniformBufferArray&) = delete;
|
||||
|
||||
UniformBufferArray& operator=(UniformBufferArray&& other) {
|
||||
gfx::UniformBufferArray::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
UniformBufferArray& operator=(const UniformBufferArray& other) {
|
||||
gfx::UniformBufferArray::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void bindWebgpu(RenderPass&) const noexcept;
|
||||
void bind(gfx::RenderPass& renderPass) override;
|
||||
|
||||
private:
|
||||
gfx::UniqueUniformBuffer copy(const gfx::UniformBuffer& buffer) override {
|
||||
return std::make_unique<UniformBuffer>(static_cast<const UniformBuffer&>(buffer).clone());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
70
include/mbgl/webgpu/upload_pass.hpp
Normal file
70
include/mbgl/webgpu/upload_pass.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/index_buffer.hpp>
|
||||
#include <mbgl/gfx/vertex_buffer.hpp>
|
||||
|
||||
#include <mbgl/gfx/upload_pass.hpp>
|
||||
#include <mbgl/gfx/renderbuffer.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
class CommandEncoder;
|
||||
class Renderable;
|
||||
} // namespace gfx
|
||||
|
||||
namespace webgpu {
|
||||
|
||||
class CommandEncoder;
|
||||
|
||||
class RenderbufferResource : public gfx::RenderbufferResource {
|
||||
public:
|
||||
RenderbufferResource() = default;
|
||||
};
|
||||
|
||||
class UploadPass final : public gfx::UploadPass {
|
||||
public:
|
||||
UploadPass(gfx::Renderable& renderable, CommandEncoder& commandEncoder, const char* name);
|
||||
~UploadPass() override;
|
||||
|
||||
private:
|
||||
void pushDebugGroup(const char* name) override;
|
||||
void popDebugGroup() override;
|
||||
|
||||
public:
|
||||
gfx::Context& getContext() override;
|
||||
const gfx::Context& getContext() const override;
|
||||
|
||||
std::unique_ptr<gfx::VertexBufferResource> createVertexBufferResource(const void* data,
|
||||
std::size_t size,
|
||||
gfx::BufferUsageType,
|
||||
bool persistent) override;
|
||||
void updateVertexBufferResource(gfx::VertexBufferResource&, const void* data, std::size_t size) override;
|
||||
|
||||
std::unique_ptr<gfx::IndexBufferResource> createIndexBufferResource(const void* data,
|
||||
std::size_t size,
|
||||
gfx::BufferUsageType,
|
||||
bool persistent) override;
|
||||
void updateIndexBufferResource(gfx::IndexBufferResource&, const void* data, std::size_t size) override;
|
||||
|
||||
gfx::AttributeBindingArray buildAttributeBindings(
|
||||
const std::size_t vertexCount,
|
||||
const gfx::AttributeDataType vertexType,
|
||||
const std::size_t vertexAttributeIndex,
|
||||
const std::vector<std::uint8_t>& vertexData,
|
||||
const gfx::VertexAttributeArray& defaults,
|
||||
const gfx::VertexAttributeArray& overrides,
|
||||
gfx::BufferUsageType,
|
||||
const std::optional<std::chrono::duration<double>> lastUpdate,
|
||||
/*out*/ std::vector<std::unique_ptr<gfx::VertexBufferResource>>& outBuffers) override;
|
||||
|
||||
const gfx::UniqueVertexBufferResource& getBuffer(const gfx::VertexVectorBasePtr&,
|
||||
gfx::BufferUsageType,
|
||||
bool forceUpdate);
|
||||
|
||||
private:
|
||||
CommandEncoder& commandEncoder;
|
||||
std::vector<gfx::DebugGroup<gfx::UploadPass>> debugGroups;
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
52
include/mbgl/webgpu/vertex_attribute.hpp
Normal file
52
include/mbgl/webgpu/vertex_attribute.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/types.hpp>
|
||||
#include <mbgl/gfx/vertex_attribute.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace gfx {
|
||||
class VertexBufferResource;
|
||||
} // namespace gfx
|
||||
namespace webgpu {
|
||||
|
||||
class UploadPass;
|
||||
|
||||
class VertexAttribute final : public gfx::VertexAttribute {
|
||||
public:
|
||||
VertexAttribute(int index_, gfx::AttributeDataType dataType_, std::size_t count_)
|
||||
: gfx::VertexAttribute(index_, dataType_, count_) {}
|
||||
VertexAttribute(const VertexAttribute& other) = delete;
|
||||
VertexAttribute(VertexAttribute&& other)
|
||||
: gfx::VertexAttribute(std::move(other)) {}
|
||||
~VertexAttribute() override = default;
|
||||
|
||||
static const gfx::UniqueVertexBufferResource& getBuffer(gfx::VertexAttribute&,
|
||||
UploadPass&,
|
||||
const gfx::BufferUsageType,
|
||||
bool forceUpdate);
|
||||
};
|
||||
|
||||
/// Stores a collection of vertex attributes by name
|
||||
class VertexAttributeArray final : public gfx::VertexAttributeArray {
|
||||
public:
|
||||
VertexAttributeArray() = default;
|
||||
VertexAttributeArray(VertexAttributeArray&& other)
|
||||
: gfx::VertexAttributeArray(std::move(other)) {}
|
||||
|
||||
VertexAttributeArray& operator=(VertexAttributeArray&& other) {
|
||||
gfx::VertexAttributeArray::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
VertexAttributeArray& operator=(const VertexAttributeArray& other) = delete;
|
||||
|
||||
/// Indicates whether any values have changed
|
||||
bool isModifiedAfter(std::chrono::duration<double> time) const;
|
||||
|
||||
private:
|
||||
gfx::UniqueVertexAttribute create(int index, gfx::AttributeDataType dataType, std::size_t count) const override {
|
||||
return std::make_unique<VertexAttribute>(index, dataType, count);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
44
include/mbgl/webgpu/vertex_buffer_resource.hpp
Normal file
44
include/mbgl/webgpu/vertex_buffer_resource.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gfx/vertex_buffer.hpp>
|
||||
#include <mbgl/webgpu/buffer_resource.hpp>
|
||||
#include <mbgl/util/monotonic_timer.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
namespace webgpu {
|
||||
|
||||
class Context;
|
||||
|
||||
class VertexBufferResource : public gfx::VertexBufferResource {
|
||||
public:
|
||||
VertexBufferResource(BufferResource&&) noexcept;
|
||||
VertexBufferResource(VertexBufferResource&& other) noexcept
|
||||
: buffer(std::move(other.buffer)) {}
|
||||
~VertexBufferResource() noexcept override;
|
||||
|
||||
std::size_t getSizeInBytes() const noexcept { return buffer.getSizeInBytes(); }
|
||||
const void* contents() const noexcept { return buffer.contents(); }
|
||||
|
||||
BufferResource& get() noexcept { return buffer; }
|
||||
const BufferResource& get() const noexcept { return buffer; }
|
||||
|
||||
// Compatibility with existing code
|
||||
const BufferResource& getBuffer() const { return buffer; }
|
||||
BufferResource& getBuffer() { return buffer; }
|
||||
|
||||
std::chrono::duration<double> getLastUpdated() const { return lastUpdated; }
|
||||
void setLastUpdated(std::chrono::duration<double> time) { lastUpdated = time; }
|
||||
|
||||
void update(const void* data, std::size_t size) { buffer.update(data, size, 0); }
|
||||
|
||||
protected:
|
||||
BufferResource buffer;
|
||||
std::chrono::duration<double> lastUpdated;
|
||||
};
|
||||
|
||||
using UniqueVertexBufferResource = std::unique_ptr<VertexBufferResource>;
|
||||
|
||||
} // namespace webgpu
|
||||
} // namespace mbgl
|
||||
19
include/mbgl/webgpu/wgpu_cpp_compat.hpp
Normal file
19
include/mbgl/webgpu/wgpu_cpp_compat.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wshadow"
|
||||
#pragma clang diagnostic ignored "-Wstrict-aliasing"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wshadow"
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif
|
||||
|
||||
#include <webgpu/webgpu_cpp.h>
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
Reference in New Issue
Block a user