Skip to content

Commit

Permalink
Make RenderBuffer mappable
Browse files Browse the repository at this point in the history
Adds map() and unmap() functions to RenderBuffer, and changes Mesh::draw() to map and update the vertex buffer instead of making a new one.

Also refactors RenderBuffer to just be a blob of data as opposed to an array of elements of fixed size and type. Removes the type-specific factory methods for creating RenderBuffers in favor of a single one that just takes a buffer type and buffer size.

Diffs=
06a187288 Make RenderBuffer mappable (#5907)

Co-authored-by: Chris Dalton <99840794+csmartdalton@users.noreply.github.com>
  • Loading branch information
csmartdalton and csmartdalton committed Aug 31, 2023
1 parent 50777ba commit a1f5e03
Show file tree
Hide file tree
Showing 23 changed files with 233 additions and 169 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
654d4488e936ac8c63930253b83229ef1c82618b
06a1872884b3b7cf2be58673e5f5246c57c3d39c
6 changes: 3 additions & 3 deletions include/rive/factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ class Factory
Factory() {}
virtual ~Factory() {}

virtual rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>) = 0;
virtual rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) = 0;
virtual rcp<RenderBuffer> makeBufferF32(Span<const float>) = 0;
virtual rcp<RenderBuffer> makeRenderBuffer(RenderBufferType,
RenderBufferFlags,
size_t sizeInBytes) = 0;

virtual rcp<RenderShader> makeLinearGradient(float sx,
float sy,
Expand Down
40 changes: 35 additions & 5 deletions include/rive/renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef _RIVE_RENDERER_HPP_
#define _RIVE_RENDERER_HPP_

#include "rive/enum_bitset.hpp"
#include "rive/shapes/paint/color.hpp"
#include "rive/command_path.hpp"
#include "rive/layout.hpp"
Expand All @@ -27,16 +28,43 @@ class Vec2D;
// Helper that computes a matrix to "align" content (source) to fit inside frame (destination).
Mat2D computeAlignment(Fit, Alignment, const AABB& frame, const AABB& content);

// A render buffer holds an immutable array of values
class RenderBuffer : public RefCnt<RenderBuffer>
enum class RenderBufferType
{
const size_t m_Count;
index,
vertex,
};

enum class RenderBufferFlags
{
none = 0,
mappedOnceAtInitialization = 1 << 0, // The client will map the buffer exactly one time, before
// rendering, and will never update it again.
};
RIVE_MAKE_ENUM_BITSET(RenderBufferFlags)

class RenderBuffer : public RefCnt<RenderBuffer>
{
public:
RenderBuffer(size_t count);
RenderBuffer(RenderBufferType, RenderBufferFlags, size_t sizeInBytes);
virtual ~RenderBuffer();

size_t count() const { return m_Count; }
RenderBufferType type() const { return m_type; }
RenderBufferFlags flags() const { return m_flags; }
size_t sizeInBytes() const { return m_sizeInBytes; }

void* map();
void unmap();

protected:
virtual void* onMap() = 0;
virtual void onUnmap() = 0;

private:
const RenderBufferType m_type;
const RenderBufferFlags m_flags;
const size_t m_sizeInBytes;
RIVE_DEBUG_CODE(size_t m_mapCount = 0;)
RIVE_DEBUG_CODE(size_t m_unmapCount = 0;)
};

enum class RenderPaintStyle
Expand Down Expand Up @@ -122,6 +150,8 @@ class Renderer
rcp<RenderBuffer> vertices_f32,
rcp<RenderBuffer> uvCoords_f32,
rcp<RenderBuffer> indices_u16,
uint32_t vertexCount,
uint32_t indexCount,
BlendMode,
float opacity) = 0;

Expand Down
1 change: 1 addition & 0 deletions include/rive/shapes/mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Mesh : public MeshBase, public Skinnable
{};
std::vector<MeshVertex*> m_Vertices;
rcp<IndexBuffer> m_IndexBuffer;
bool m_VertexRenderBufferDirty = true;

rcp<RenderBuffer> m_IndexRenderBuffer;
rcp<RenderBuffer> m_VertexRenderBuffer;
Expand Down
37 changes: 13 additions & 24 deletions include/utils/factory_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,32 @@ namespace rive
//
class DataRenderBuffer : public RenderBuffer
{
const size_t m_elemSize;
std::vector<uint32_t> m_storage; // store 32bits for alignment

public:
DataRenderBuffer(const void* src, size_t count, size_t elemSize) :
RenderBuffer(count), m_elemSize(elemSize)
DataRenderBuffer(RenderBufferType type, RenderBufferFlags flags, size_t sizeInBytes) :
RenderBuffer(type, flags, sizeInBytes)
{
const size_t bytes = count * elemSize;
m_storage.resize((bytes + 3) >> 2); // round up to next 32bit count
memcpy(m_storage.data(), src, bytes);
m_storage = malloc(sizeInBytes);
}

const float* f32s() const
{
assert(m_elemSize == sizeof(float));
return reinterpret_cast<const float*>(m_storage.data());
}
~DataRenderBuffer() { free(m_storage); }

const uint16_t* u16s() const
{
assert(m_elemSize == sizeof(uint16_t));
return reinterpret_cast<const uint16_t*>(m_storage.data());
}
const float* f32s() const { return reinterpret_cast<const float*>(m_storage); }

const Vec2D* vecs() const { return reinterpret_cast<const Vec2D*>(this->f32s()); }
const uint16_t* u16s() const { return reinterpret_cast<const uint16_t*>(m_storage); }

size_t elemSize() const { return m_elemSize; }
const Vec2D* vecs() const { return reinterpret_cast<const Vec2D*>(f32s()); }

static const DataRenderBuffer* Cast(const RenderBuffer* buffer)
{
return static_cast<const DataRenderBuffer*>(buffer);
}

template <typename T> static rcp<RenderBuffer> Make(Span<T> span)
{
return rcp<RenderBuffer>(new DataRenderBuffer(span.data(), span.size(), sizeof(T)));
}
protected:
void* onMap() override { return m_storage; }
void onUnmap() override {}

private:
void* m_storage;
};

} // namespace rive
Expand Down
4 changes: 1 addition & 3 deletions include/utils/no_op_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ namespace rive

class NoOpFactory : public Factory
{
rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>) override;
rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) override;
rcp<RenderBuffer> makeBufferF32(Span<const float>) override;
rcp<RenderBuffer> makeRenderBuffer(RenderBufferType, RenderBufferFlags, size_t) override;

rcp<RenderShader> makeLinearGradient(float sx,
float sy,
Expand Down
2 changes: 2 additions & 0 deletions include/utils/no_op_renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class NoOpRenderer : public Renderer
rcp<RenderBuffer>,
rcp<RenderBuffer>,
rcp<RenderBuffer>,
uint32_t vertexCount,
uint32_t indexCount,
BlendMode,
float) override
{}
Expand Down
4 changes: 1 addition & 3 deletions skia/renderer/include/cg_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ namespace rive
class CGFactory : public Factory
{
public:
rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>) override;
rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) override;
rcp<RenderBuffer> makeBufferF32(Span<const float>) override;
rcp<RenderBuffer> makeRenderBuffer(RenderBufferType, RenderBufferFlags, size_t) override;

rcp<RenderShader> makeLinearGradient(float sx,
float sy,
Expand Down
2 changes: 2 additions & 0 deletions skia/renderer/include/cg_renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class CGRenderer : public Renderer
rcp<RenderBuffer> vertices_f32,
rcp<RenderBuffer> uvCoords_f32,
rcp<RenderBuffer> indices_u16,
uint32_t vertexCount,
uint32_t indexCount,
BlendMode,
float opacity) override;
};
Expand Down
4 changes: 1 addition & 3 deletions skia/renderer/include/skia_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ namespace rive
class SkiaFactory : public Factory
{
public:
rcp<RenderBuffer> makeBufferU16(Span<const uint16_t>) override;
rcp<RenderBuffer> makeBufferU32(Span<const uint32_t>) override;
rcp<RenderBuffer> makeBufferF32(Span<const float>) override;
rcp<RenderBuffer> makeRenderBuffer(RenderBufferType, RenderBufferFlags, size_t) override;

rcp<RenderShader> makeLinearGradient(float sx,
float sy,
Expand Down
2 changes: 2 additions & 0 deletions skia/renderer/include/skia_renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class SkiaRenderer : public Renderer
rcp<RenderBuffer> vertices_f32,
rcp<RenderBuffer> uvCoords_f32,
rcp<RenderBuffer> indices_u16,
uint32_t vertexCount,
uint32_t indexCount,
BlendMode,
float opacity) override;
};
Expand Down
20 changes: 7 additions & 13 deletions skia/renderer/src/cg_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,8 @@ void CGRenderer::drawImageMesh(const RenderImage* image,
rcp<RenderBuffer> vertices,
rcp<RenderBuffer> uvCoords,
rcp<RenderBuffer> indices,
uint32_t vertexCount,
uint32_t indexCount,
BlendMode blendMode,
float opacity)
{
Expand All @@ -432,7 +434,7 @@ void CGRenderer::drawImageMesh(const RenderImage* image,

auto scale = [sx, sy](Vec2D v) { return Vec2D{v.x * sx, v.y * sy}; };

auto triangles = indices->count() / 3;
auto triangles = indexCount / 3;
auto ndx = DataRenderBuffer::Cast(indices.get())->u16s();
auto pts = DataRenderBuffer::Cast(vertices.get())->vecs();
auto uvs = DataRenderBuffer::Cast(uvCoords.get())->vecs();
Expand Down Expand Up @@ -479,19 +481,11 @@ void CGRenderer::drawImageMesh(const RenderImage* image,

// Factory

rcp<RenderBuffer> CGFactory::makeBufferU16(Span<const uint16_t> data)
rcp<RenderBuffer> CGFactory::makeRenderBuffer(RenderBufferType type,
RenderBufferFlags flags,
size_t sizeInBytes)
{
return DataRenderBuffer::Make(data);
}

rcp<RenderBuffer> CGFactory::makeBufferU32(Span<const uint32_t> data)
{
return DataRenderBuffer::Make(data);
}

rcp<RenderBuffer> CGFactory::makeBufferF32(Span<const float> data)
{
return DataRenderBuffer::Make(data);
return make_rcp<DataRenderBuffer>(type, flags, sizeInBytes);
}

rcp<RenderShader> CGFactory::makeLinearGradient(float sx,
Expand Down
35 changes: 12 additions & 23 deletions skia/renderer/src/skia_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,15 @@ void SkiaRenderer::drawImageMesh(const RenderImage* image,
rcp<RenderBuffer> vertices,
rcp<RenderBuffer> uvCoords,
rcp<RenderBuffer> indices,
uint32_t vertexCount,
uint32_t indexCount,
BlendMode blendMode,
float opacity)
{
// need our vertices and uvs to agree
assert(vertices->count() == uvCoords->count());
// vertices and uvs are arrays of floats, so we need their counts to be
// even, since we treat them as arrays of points
assert((vertices->count() & 1) == 0);

const int vertexCount = vertices->count() >> 1;
// need our buffers and counts to agree
assert(vertices->sizeInBytes() == vertexCount * sizeof(Vec2D));
assert(uvCoords->sizeInBytes() == vertexCount * sizeof(Vec2D));
assert(indices->sizeInBytes() == indexCount * sizeof(uint16_t));

SkMatrix scaleM;

Expand All @@ -177,7 +176,7 @@ void SkiaRenderer::drawImageMesh(const RenderImage* image,
// The local matrix is ignored for drawVertices, so we have to manually scale
// the UVs to match Skia's convention...
std::vector<SkPoint> scaledUVs(vertexCount);
for (int i = 0; i < vertexCount; ++i)
for (uint32_t i = 0; i < vertexCount; ++i)
{
scaledUVs[i] = {uvs[i].fX * image->width(), uvs[i].fY * image->height()};
}
Expand All @@ -200,15 +199,13 @@ void SkiaRenderer::drawImageMesh(const RenderImage* image,

const SkColor* no_colors = nullptr;
auto vertexMode = SkVertices::kTriangles_VertexMode;
// clang-format off
auto vt = SkVertices::MakeCopy(vertexMode,
vertexCount,
(const SkPoint*)DataRenderBuffer::Cast(vertices.get())->vecs(),
uvs,
no_colors,
indices->count(),
indexCount,
DataRenderBuffer::Cast(indices.get())->u16s());
// clang-format on

// The blend mode is ignored if we don't have colors && uvs
m_Canvas->drawVertices(vt, SkBlendMode::kModulate, paint);
Expand All @@ -222,19 +219,11 @@ SkiaRenderImage::SkiaRenderImage(sk_sp<SkImage> image) : m_SkImage(std::move(ima

// Factory

rcp<RenderBuffer> SkiaFactory::makeBufferU16(Span<const uint16_t> data)
{
return DataRenderBuffer::Make(data);
}

rcp<RenderBuffer> SkiaFactory::makeBufferU32(Span<const uint32_t> data)
{
return DataRenderBuffer::Make(data);
}

rcp<RenderBuffer> SkiaFactory::makeBufferF32(Span<const float> data)
rcp<RenderBuffer> SkiaFactory::makeRenderBuffer(RenderBufferType type,
RenderBufferFlags flags,
size_t sizeInBytes)
{
return DataRenderBuffer::Make(data);
return make_rcp<DataRenderBuffer>(type, flags, sizeInBytes);
}

rcp<RenderShader> SkiaFactory::makeLinearGradient(float sx,
Expand Down
21 changes: 20 additions & 1 deletion src/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,29 @@ void Renderer::rotate(float radians)
this->transform(Mat2D(c, s, -s, c, 0, 0));
}

RenderBuffer::RenderBuffer(size_t count) : m_Count(count) { Counter::update(Counter::kBuffer, 1); }
RenderBuffer::RenderBuffer(RenderBufferType type, RenderBufferFlags flags, size_t sizeInBytes) :
m_type(type), m_flags(flags), m_sizeInBytes(sizeInBytes)
{
Counter::update(Counter::kBuffer, 1);
}

RenderBuffer::~RenderBuffer() { Counter::update(Counter::kBuffer, -1); }

void* RenderBuffer::map()
{
assert(m_mapCount == 0 || !(m_flags & RenderBufferFlags::mappedOnceAtInitialization));
assert(m_mapCount == m_unmapCount);
RIVE_DEBUG_CODE(++m_mapCount;)
return onMap();
}

void RenderBuffer::unmap()
{
assert(m_unmapCount + 1 == m_mapCount);
RIVE_DEBUG_CODE(++m_unmapCount;)
onUnmap();
}

RenderShader::RenderShader() { Counter::update(Counter::kShader, 1); }
RenderShader::~RenderShader() { Counter::update(Counter::kShader, -1); }

Expand Down
Loading

0 comments on commit a1f5e03

Please sign in to comment.