Add WebGPU Backend w/ Dawn Support (#3838)

This commit is contained in:
Birk Skyum
2025-10-16 20:35:33 +02:00
committed by GitHub
parent cd129e873a
commit 68459732be
119 changed files with 14067 additions and 28 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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>

View 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

View 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

View 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

View 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

View 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

View 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