Skip to content

Commit

Permalink
Refactor bindings to allow for eliminating duplicates... (#1831)
Browse files Browse the repository at this point in the history
Co-authored-by: Bart Louwers <[email protected]>
  • Loading branch information
TimSylvester and louwers authored Nov 6, 2023
1 parent 1670b2c commit ef69472
Show file tree
Hide file tree
Showing 29 changed files with 442 additions and 245 deletions.
13 changes: 9 additions & 4 deletions include/mbgl/gfx/uniform_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,18 @@ class UniformBufferArray {
std::shared_ptr<UniformBuffer> uniformBuffer);

/// Create and add a new buffer or update an existing one
void createOrUpdate(const StringIdentity id, const std::vector<uint8_t>& data, gfx::Context&);
void createOrUpdate(const StringIdentity id, const void* data, std::size_t size, gfx::Context&);
void createOrUpdate(const StringIdentity id,
const std::vector<uint8_t>& data,
gfx::Context&,
bool persistent = false);
void createOrUpdate(
const StringIdentity id, const void* data, std::size_t size, gfx::Context&, bool persistent = false);
template <typename T>
std::enable_if_t<!std::is_pointer_v<T>> createOrUpdate(const StringIdentity id,
const T* data,
gfx::Context& context) {
createOrUpdate(id, data, sizeof(T), context);
gfx::Context& context,
bool persistent = false) {
createOrUpdate(id, data, sizeof(T), context, persistent);
}

UniformBufferArray& operator=(UniformBufferArray&&);
Expand Down
66 changes: 54 additions & 12 deletions include/mbgl/mtl/buffer_resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,79 @@ class Context;

class BufferResource {
public:
BufferResource() = delete;
BufferResource() noexcept = delete;
/** @brief Create a new Metal buffer
@param device The Metal device on which to create the buffer.
@param raw Data to use for the contents of the new buffer. May be null.
@param size The minimum size of the new buffer. Must be non-zero.
@param usage A `MTL::ResourceOptions` value. Currently, only `ResourceStorageModeShared` is supported.
@param isIndexBuffer True if the buffer will be used for indexes. The Metal API only accepts `MTLBuffer`
objects for drawing indexed primitives, so this constrains how the buffer can be managed.
@param persistent Performance hint, assume this buffer will be reused many times.
*/
BufferResource(Context& context_, const void* raw, std::size_t size, MTL::ResourceOptions usage);
BufferResource(BufferResource&&);
virtual ~BufferResource();
BufferResource(Context& context_,
const void* raw,
std::size_t size,
MTL::ResourceOptions usage,
bool isIndexBuffer,
bool persistent);
BufferResource(BufferResource&&) noexcept;
virtual ~BufferResource() noexcept;

BufferResource& operator=(BufferResource&&);
BufferResource& operator=(BufferResource&&) noexcept;

BufferResource clone() const;

void update(const void* data, std::size_t size, std::size_t offset);
void update(const void* data, std::size_t size, std::size_t offset) noexcept;

std::size_t getSizeInBytes() const { return buffer ? buffer->length() : 0; }
void* contents() const { return buffer ? buffer->contents() : nullptr; }
std::size_t getSizeInBytes() const noexcept { return size; }
const void* contents() const noexcept { return buffer ? buffer->contents() : (raw.empty() ? nullptr : raw.data()); }

Context& getContext() const { return context; }
const MTLBufferPtr& getMetalBuffer() const { return buffer; }
Context& getContext() const noexcept { return context; }
const MTLBufferPtr& getMetalBuffer() const noexcept { return buffer; }

operator bool() const { return buffer.operator bool(); }
bool operator!() const { return !buffer.operator bool(); }
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;

/// Bind this buffer to the specified vertex buffer index
void bindVertex(const MTLRenderCommandEncoderPtr&,
std::size_t offset,
std::size_t index,
std::size_t size) const noexcept;
/// Bind this buffer to the specified fragment buffer index
void bindFragment(const MTLRenderCommandEncoderPtr&,
std::size_t offset,
std::size_t index,
std::size_t size) const noexcept;

/// Update the offset, when this buffer is alread bound to the specified index (unchecked).
void updateVertexBindOffset(const MTLRenderCommandEncoderPtr&,
std::size_t offset,
std::size_t index,
std::size_t size) const noexcept;
void updateFragmentBindOffset(const MTLRenderCommandEncoderPtr&,
std::size_t offset,
std::size_t index,
std::size_t size) const noexcept;

protected:
Context& context;
MTLBufferPtr buffer;
std::vector<std::uint8_t> raw;
NS::UInteger size;
NS::UInteger usage;
std::uint16_t version = 0;
bool isIndexBuffer;
bool persistent;
};

} // namespace mtl
Expand Down
27 changes: 18 additions & 9 deletions include/mbgl/mtl/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ namespace mtl {
class RenderPass;
class RendererBackend;
class ShaderProgram;
class VertexBufferResource;

using UniqueShaderProgram = std::unique_ptr<ShaderProgram>;
using UniqueVertexBufferResource = std::unique_ptr<VertexBufferResource>;

class Context final : public gfx::Context {
public:
Expand All @@ -44,7 +46,15 @@ class Context final : public gfx::Context {

std::unique_ptr<gfx::CommandEncoder> createCommandEncoder() override;

BufferResource createBuffer(const void* data, std::size_t size, gfx::BufferUsageType) const;
/// Create a new buffer object
/// @param data The raw data to copy, may be `nullptr`
/// @param size The size of the buffer
/// @param usage Not currently used
/// @param isIndexBuffer True if the buffer will be used for indexes. The Metal API only accepts `MTLBuffer`
/// objects for drawing indexed primitives, so this constrains how the buffer can be managed.
/// @param persistent Performance hint, assume this buffer will be reused many times.
BufferResource createBuffer(
const void* data, std::size_t size, gfx::BufferUsageType usage, bool isIndexBuffer, bool persistent) const;

UniqueShaderProgram createProgram(std::string name,
std::string_view source,
Expand All @@ -64,7 +74,7 @@ class Context final : public gfx::Context {
void reduceMemoryUsage() override {}

gfx::UniqueDrawableBuilder createDrawableBuilder(std::string name) override;
gfx::UniformBufferPtr createUniformBuffer(const void* data, std::size_t size) override;
gfx::UniformBufferPtr createUniformBuffer(const void* data, std::size_t size, bool persistent) override;

gfx::ShaderProgramBasePtr getGenericShader(gfx::ShaderRegistry&, const std::string& name) override;

Expand Down Expand Up @@ -94,10 +104,6 @@ class Context final : public gfx::Context {
Size size) override;

std::unique_ptr<gfx::DrawScopeResource> createDrawScopeResource() override;
/*
UniqueFramebuffer createFramebuffer();
std::unique_ptr<uint8_t[]> readFramebuffer(Size, gfx::TexturePixelType, bool flip);
*/

#if !defined(NDEBUG)
void visualizeStencilBuffer() override;
Expand All @@ -110,7 +116,10 @@ class Context final : public gfx::Context {
const gfx::StencilMode&,
const gfx::Renderable&) const;

virtual bool emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr&, const void* data, std::size_t size);
virtual bool emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr&,
const void* data,
std::size_t size,
bool persistent);

/// Get a reusable buffer containing the standard fixed tile vertices (+/- `util::EXTENT`)
const BufferResource& getTileVertexBuffer();
Expand All @@ -119,7 +128,7 @@ class Context final : public gfx::Context {
const BufferResource& getTileIndexBuffer();

/// Get a buffer to be bound to unused vertex buffers
const gfx::UniqueVertexBufferResource& getEmptyVertexBuffer();
const UniqueVertexBufferResource& getEmptyVertexBuffer();

bool renderTileClippingMasks(gfx::RenderPass& renderPass,
RenderStaticData& staticData,
Expand All @@ -132,7 +141,7 @@ class Context final : public gfx::Context {
std::optional<BufferResource> tileVertexBuffer;
std::optional<BufferResource> tileIndexBuffer;

gfx::UniqueVertexBufferResource emptyVertexBuffer;
UniqueVertexBufferResource emptyVertexBuffer;

gfx::ShaderProgramBasePtr clipMaskShader;
MTLDepthStencilStatePtr clipMaskDepthStencilState;
Expand Down
14 changes: 7 additions & 7 deletions include/mbgl/mtl/drawable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,16 @@ class Drawable : public gfx::Drawable {
// For testing only.
Drawable(std::unique_ptr<Impl>);

void bindAttributes(const RenderPass& renderPass) const;
void unbindAttributes(const RenderPass& renderPass) const;
void bindAttributes(RenderPass&) const noexcept;
void unbindAttributes(RenderPass&) const noexcept {}

void bindUniformBuffers(const RenderPass& renderPass) const;
void unbindUniformBuffers(const RenderPass& renderPass) const;
void bindUniformBuffers(RenderPass&) const noexcept;
void unbindUniformBuffers(RenderPass&) const noexcept {}

void bindTextures(const RenderPass& renderPass) const;
void unbindTextures(const RenderPass& renderPass) const;
void bindTextures(RenderPass&) const noexcept;
void unbindTextures(RenderPass&) const noexcept;

void uploadTextures() const;
void uploadTextures(UploadPass&) const noexcept;

class Impl;
const std::unique_ptr<Impl> impl;
Expand Down
16 changes: 8 additions & 8 deletions include/mbgl/mtl/index_buffer_resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ namespace mtl {

class IndexBufferResource : public gfx::IndexBufferResource {
public:
IndexBufferResource() = default;
IndexBufferResource(BufferResource&&);
IndexBufferResource(IndexBufferResource&& other)
IndexBufferResource() noexcept = default;
IndexBufferResource(BufferResource&&) noexcept;
IndexBufferResource(IndexBufferResource&& other) noexcept
: buffer(std::move(other.buffer)) {}
~IndexBufferResource() override;
~IndexBufferResource() noexcept override;

std::size_t getSizeInBytes() const { return buffer.getSizeInBytes(); }
void* contents() const { return buffer.contents(); }
std::size_t getSizeInBytes() const noexcept { return buffer.getSizeInBytes(); }
const void* contents() const noexcept { return buffer.contents(); }

BufferResource& get() { return buffer; }
const BufferResource& get() const { return buffer; }
BufferResource& get() noexcept { return buffer; }
const BufferResource& get() const noexcept { return buffer; }

protected:
BufferResource buffer;
Expand Down
14 changes: 14 additions & 0 deletions include/mbgl/mtl/render_pass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace mbgl {
namespace mtl {

class BufferResource;
class CommandEncoder;
class Context;

Expand All @@ -27,6 +28,10 @@ class RenderPass final : public gfx::RenderPass {

void addDebugSignpost(const char* name) override;

void bindVertex(const BufferResource&, std::size_t offset, std::size_t index, std::size_t size = 0);

void bindFragment(const BufferResource&, std::size_t offset, std::size_t index, std::size_t size = 0);

private:
void pushDebugGroup(const char* name) override;
void popDebugGroup() override;
Expand All @@ -36,6 +41,15 @@ class RenderPass final : public gfx::RenderPass {
mtl::CommandEncoder& commandEncoder;
MTLRenderCommandEncoderPtr encoder;
std::vector<gfx::DebugGroup<gfx::RenderPass>> debugGroups;

struct BindInfo {
const BufferResource* buf = nullptr;
NS::UInteger offset = 0;
std::uint16_t version = 0;
};
static constexpr auto maxBinds = 32;
std::array<std::optional<BindInfo>, maxBinds> vertexBinds;
std::array<std::optional<BindInfo>, maxBinds> fragmentBinds;
};

} // namespace mtl
Expand Down
6 changes: 4 additions & 2 deletions include/mbgl/mtl/upload_pass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ class UploadPass final : public gfx::UploadPass {

std::unique_ptr<gfx::VertexBufferResource> createVertexBufferResource(const void* data,
std::size_t size,
gfx::BufferUsageType) override;
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) override;
gfx::BufferUsageType,
bool persistent) override;
void updateIndexBufferResource(gfx::IndexBufferResource&, const void* data, std::size_t size) override;

void updateResource(BufferResource&, const void* data, std::size_t size);
Expand Down
20 changes: 12 additions & 8 deletions include/mbgl/mtl/vertex_buffer_resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,30 @@

#include <mbgl/mtl/buffer_resource.hpp>

#include <memory>

namespace mbgl {
namespace mtl {

class VertexBufferResource : public gfx::VertexBufferResource {
public:
VertexBufferResource() = default;
VertexBufferResource(BufferResource&&);
VertexBufferResource(VertexBufferResource&& other)
VertexBufferResource() noexcept = default;
VertexBufferResource(BufferResource&&) noexcept;
VertexBufferResource(VertexBufferResource&& other) noexcept
: buffer(std::move(other.buffer)) {}
~VertexBufferResource() override;
~VertexBufferResource() noexcept override;

std::size_t getSizeInBytes() const { return buffer.getSizeInBytes(); }
void* contents() const { return buffer.contents(); }
std::size_t getSizeInBytes() const noexcept { return buffer.getSizeInBytes(); }
const void* contents() const noexcept { return buffer.contents(); }

BufferResource& get() { return buffer; }
const BufferResource& get() const { return buffer; }
BufferResource& get() noexcept { return buffer; }
const BufferResource& get() const noexcept { return buffer; }

protected:
BufferResource buffer;
};

using UniqueVertexBufferResource = std::unique_ptr<VertexBufferResource>;

} // namespace mtl
} // namespace mbgl
15 changes: 11 additions & 4 deletions src/mbgl/gfx/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ class Context {
virtual UniqueDrawableBuilder createDrawableBuilder(std::string name) = 0;

/// Create a new uniform buffer
virtual UniformBufferPtr createUniformBuffer(const void* data, std::size_t size) = 0;
/// @param data The data to copy, may be `nullptr`
/// @param size The size of the buffer
/// @param persistent Performance hint, optimize for few or many uses
virtual UniformBufferPtr createUniformBuffer(const void* data, std::size_t size, bool persistent = false) = 0;

/// Get the generic shader with the specified name
virtual gfx::ShaderProgramBasePtr getGenericShader(gfx::ShaderRegistry&, const std::string& name) = 0;
Expand All @@ -147,13 +150,17 @@ class Context {

/// Update the uniform buffer with the provided data if it already exists, otherwise create it.
/// @return True if the buffer was created, false if it was updated
virtual bool emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr&, const void* data, std::size_t size) = 0;
virtual bool emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr&,
const void* data,
std::size_t size,
bool persistent = false) = 0;

/// `emplaceOrUpdateUniformBuffer` with type inference
template <typename T>
std::enable_if_t<!std::is_pointer_v<T>, bool> emplaceOrUpdateUniformBuffer(gfx::UniformBufferPtr& ptr,
const T* data) {
return emplaceOrUpdateUniformBuffer(ptr, data, sizeof(T));
const T* data,
bool persistent = false) {
return emplaceOrUpdateUniformBuffer(ptr, data, sizeof(T), persistent);
}

#endif
Expand Down
4 changes: 2 additions & 2 deletions src/mbgl/gfx/index_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ namespace gfx {

class IndexBufferResource {
protected:
IndexBufferResource() = default;
IndexBufferResource() noexcept = default;

public:
virtual ~IndexBufferResource() = default;
virtual ~IndexBufferResource() noexcept = default;
};

class IndexBuffer {
Expand Down
Loading

0 comments on commit ef69472

Please sign in to comment.