Refactor bindings to allow for eliminating duplicates... (#1831)
Co-authored-by: Bart Louwers <bart@emeel.net>
This commit is contained in:
@@ -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&&);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user