Refactor bindings to allow for eliminating duplicates... (#1831)

Co-authored-by: Bart Louwers <bart@emeel.net>
This commit is contained in:
Tim Sylvester
2023-11-06 10:12:34 -08:00
committed by GitHub
parent 1670b2c3ee
commit ef69472f56
29 changed files with 441 additions and 244 deletions

View File

@@ -68,13 +68,18 @@ public:
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&&);

View File

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

View File

@@ -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:
@@ -44,7 +46,15 @@ public:
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,
@@ -64,7 +74,7 @@ public:
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;
@@ -94,10 +104,6 @@ public:
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;
@@ -110,7 +116,10 @@ public:
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();
@@ -119,7 +128,7 @@ public:
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,
@@ -132,7 +141,7 @@ private:
std::optional<BufferResource> tileVertexBuffer;
std::optional<BufferResource> tileIndexBuffer;
gfx::UniqueVertexBufferResource emptyVertexBuffer;
UniqueVertexBufferResource emptyVertexBuffer;
gfx::ShaderProgramBasePtr clipMaskShader;
MTLDepthStencilStatePtr clipMaskDepthStencilState;

View File

@@ -66,16 +66,16 @@ protected:
// 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;

View File

@@ -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;

View File

@@ -12,6 +12,7 @@
namespace mbgl {
namespace mtl {
class BufferResource;
class CommandEncoder;
class Context;
@@ -27,6 +28,10 @@ public:
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;
@@ -36,6 +41,15 @@ private:
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

View File

@@ -44,12 +44,14 @@ public:
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);

View File

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