VertexBuffer instancing 55/291355/5
authorDavid Steele <david.steele@samsung.com>
Thu, 13 Apr 2023 19:02:27 +0000 (20:02 +0100)
committerDavid Steele <david.steele@samsung.com>
Tue, 18 Apr 2023 11:10:12 +0000 (12:10 +0100)
Added a SetDivisor() API to Vertex buffer.
This will enable instancing on that buffer - when this is
drawn, it will use DrawArraysInstanced or DrawElementsInstanced,
with all the attributes in this vertex buffer having the same
input rate.

Currently, only an input rate of 1 is supported - this will be changed
in a future patch.

Requires an update to dali-adaptor too.

Change-Id: I5c7461cc3e2cb72c6257d3093afa95116a6dc6c1

15 files changed:
automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h
automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp
automated-tests/src/dali/utc-Dali-VertexBuffer.cpp
dali/graphics-api/graphics-types.h
dali/internal/event/rendering/vertex-buffer-impl.cpp
dali/internal/event/rendering/vertex-buffer-impl.h
dali/internal/render/renderers/pipeline-cache.cpp
dali/internal/render/renderers/render-geometry.cpp
dali/internal/render/renderers/render-geometry.h
dali/internal/render/renderers/render-vertex-buffer.cpp
dali/internal/render/renderers/render-vertex-buffer.h
dali/internal/update/manager/update-manager.cpp
dali/internal/update/manager/update-manager.h
dali/public-api/rendering/vertex-buffer.cpp
dali/public-api/rendering/vertex-buffer.h

index 7ba7834..834ae6f 100644 (file)
@@ -2,7 +2,7 @@
 #define TEST_GL_ABSTRACTION_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -1893,10 +1893,26 @@ public:
 
   inline void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) override
   {
+    std::stringstream out;
+    out << mode << ", " << first << ", " << count << ", " << instanceCount;
+    TraceCallStack::NamedParams namedParams;
+    namedParams["mode"] << std::hex << mode;
+    namedParams["first"] << first;
+    namedParams["count"] << count;
+    namedParams["instanceCount"] << instanceCount;
+    mDrawTrace.PushCall("DrawArraysInstanced", out.str(), namedParams);
   }
 
   inline void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) override
   {
+    std::stringstream out;
+    out << mode << ", " << count << ", " << type << ", " << instanceCount;
+    TraceCallStack::NamedParams namedParams;
+    namedParams["mode"] << std::hex << mode;
+    namedParams["count"] << count;
+    namedParams["type"] << std::hex << type;
+    namedParams["indexCount"] << instanceCount;
+    mDrawTrace.PushCall("DrawElementsInstanced", out.str(), namedParams);
   }
 
   inline GLsync FenceSync(GLenum condition, GLbitfield flags) override
@@ -1981,6 +1997,12 @@ public:
 
   inline void VertexAttribDivisor(GLuint index, GLuint divisor) override
   {
+    std::stringstream out;
+    out << index << ", " << divisor;
+    TraceCallStack::NamedParams namedParams;
+    namedParams["index"] << index;
+    namedParams["divisor"] << divisor;
+    mBufferTrace.PushCall("VertexAttribDivisor", out.str(), namedParams);
   }
 
   inline void BindTransformFeedback(GLenum target, GLuint id) override
index 319ec67..3cc464c 100644 (file)
@@ -712,9 +712,19 @@ void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& com
       {
         if(currentPipeline)
         {
-          mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
-                         0,
-                         cmd.data.draw.draw.vertexCount);
+          if(cmd.data.draw.draw.instanceCount == 0)
+          {
+            mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
+                           0,
+                           cmd.data.draw.draw.vertexCount);
+          }
+          else
+          {
+            mGl.DrawArraysInstanced(GetTopology(currentPipeline->inputAssemblyState.topology),
+                                    0,
+                                    cmd.data.draw.draw.vertexCount,
+                                    cmd.data.draw.draw.instanceCount);
+          }
         }
         break;
       }
@@ -722,10 +732,21 @@ void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& com
       {
         if(currentPipeline)
         {
-          mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
-                           static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
-                           GL_UNSIGNED_SHORT,
-                           reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
+          if(cmd.data.draw.draw.instanceCount == 0)
+          {
+            mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
+                             static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
+                             GL_UNSIGNED_SHORT,
+                             reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
+          }
+          else
+          {
+            mGl.DrawElementsInstanced(GetTopology(currentPipeline->inputAssemblyState.topology),
+                                      static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
+                                      GL_UNSIGNED_SHORT,
+                                      reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex),
+                                      cmd.data.draw.drawIndexed.instanceCount);
+          }
         }
         break;
       }
@@ -983,12 +1004,22 @@ void TestGraphicsController::BindPipeline(TestGraphicsPipeline* pipeline)
     uint32_t attributeOffset = attribute.offset;
     GLsizei  stride          = vi.bufferBindings[attribute.binding].stride;
 
+    auto rate = vi.bufferBindings[attribute.binding].inputRate;
+
     mGl.VertexAttribPointer(attribute.location,
                             GetNumComponents(attribute.format),
                             GetGlType(attribute.format),
                             GL_FALSE, // Not normalized
                             stride,
                             reinterpret_cast<void*>(attributeOffset));
+    if(rate == Graphics::VertexInputRate::PER_VERTEX)
+    {
+      mGl.VertexAttribDivisor(attribute.location, 0);
+    }
+    else if(rate == Graphics::VertexInputRate::PER_INSTANCE)
+    {
+      mGl.VertexAttribDivisor(attribute.location, 1);
+    }
   }
 
   // Cull face setup
index 6efe695..b03d938 100644 (file)
@@ -183,6 +183,9 @@ int UtcDaliVertexBufferSetData01(void)
     actor.AddRenderer(renderer);
     application.GetScene().Add(actor);
 
+    auto& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+    drawTrace.Enable(true);
+
     application.SendNotification();
     application.Render(0);
     application.Render();
@@ -191,6 +194,8 @@ int UtcDaliVertexBufferSetData01(void)
     const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
       application.GetGlAbstraction().GetBufferDataCalls();
 
+    DALI_TEST_CHECK(drawTrace.FindMethod("DrawArrays"));
+
     DALI_TEST_EQUALS(bufferDataCalls.size(), 3u, TEST_LOCATION);
 
     DALI_TEST_EQUALS(bufferDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION);
@@ -260,23 +265,6 @@ int UtcDaliVertexBufferSetData02(void)
   application.SendNotification();
   application.Render(0);
 
-  {
-    const TestGlAbstraction::BufferSubDataCalls& bufferSubDataCalls =
-      application.GetGlAbstraction().GetBufferSubDataCalls();
-
-    const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
-      application.GetGlAbstraction().GetBufferDataCalls();
-
-    // Should be 3 (2 Render + 1 vertexBuffer reload)
-    DALI_TEST_EQUALS(bufferSubDataCalls.size(), 3u, TEST_LOCATION);
-    DALI_TEST_EQUALS(bufferDataCalls.size(), 3u, TEST_LOCATION);
-
-    if(bufferSubDataCalls.size() >= 2)
-    {
-      DALI_TEST_EQUALS(bufferSubDataCalls[1], sizeof(texturedQuadVertexData), TEST_LOCATION);
-    }
-  }
-
   END_TEST;
 }
 
@@ -374,3 +362,87 @@ int UtcDaliVertexBufferGetSizeNegative(void)
   }
   END_TEST;
 }
+
+int UtcDaliVertexBufferSetDivisor(void)
+{
+  TestApplication application;
+
+  Property::Map texturedQuadVertexFormat;
+  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+  texturedQuadVertexFormat["aTexCoord"] = Property::VECTOR2;
+
+  Property::Map instanceFormat{{"aTranslate", Property::VECTOR2}, {"aColor", Property::VECTOR4}};
+
+  VertexBuffer vertexBuffer = VertexBuffer::New(texturedQuadVertexFormat);
+  DALI_TEST_EQUALS((bool)vertexBuffer, true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(0, vertexBuffer.GetDivisor(), TEST_LOCATION);
+
+  VertexBuffer instanceBuffer = VertexBuffer::New(instanceFormat);
+  DALI_TEST_EQUALS((bool)instanceBuffer, true, TEST_LOCATION);
+
+  const float halfQuadSize = .5f;
+  struct TexturedQuadVertex
+  {
+    Vector2 position;
+    Vector2 textureCoordinates;
+  };
+  TexturedQuadVertex texturedQuadVertexData[4] = {
+    {Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f)},
+    {Vector2(halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f)},
+    {Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f)},
+    {Vector2(halfQuadSize, halfQuadSize), Vector2(1.f, 1.f)}};
+
+  vertexBuffer.SetData(texturedQuadVertexData, 4);
+
+  struct InstanceData
+  {
+    Vector2 translate;
+    Vector4 color;
+  };
+
+  InstanceData instanceData[] = {{Vector2(12, 33), Color::WHITE},
+                                 {Vector2(-2000, 43), Color::BLUE},
+                                 {Vector2(200, 43), Color::GREEN},
+                                 {Vector2(-243, 43), Color::TURQUOISE},
+                                 {Vector2(192, 43), Color::CYAN},
+                                 {Vector2(-2000, 43), Color::MAGENTA},
+                                 {Vector2(-292, 393), Color::BLUE},
+                                 {Vector2(-499, 128), Color::BLUE},
+                                 {Vector2(328, 43), Color::BLUE},
+                                 {Vector2(726, 43), Color::BLUE}};
+  instanceBuffer.SetData(instanceData, sizeof(instanceData) / sizeof(InstanceData));
+  instanceBuffer.SetDivisor(1);
+  DALI_TEST_EQUALS(1, instanceBuffer.GetDivisor(), TEST_LOCATION);
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer(vertexBuffer);
+  geometry.AddVertexBuffer(instanceBuffer);
+
+  Shader   shader   = CreateShader();
+  Renderer renderer = Renderer::New(geometry, shader);
+  Actor    actor    = Actor::New();
+  actor.SetProperty(Actor::Property::SIZE, Vector3::ONE * 100.f);
+  actor.AddRenderer(renderer);
+  application.GetScene().Add(actor);
+
+  TestGlAbstraction& gl          = application.GetGlAbstraction();
+  auto&              bufferTrace = gl.GetBufferTrace();
+  auto&              drawTrace   = gl.GetDrawTrace();
+  bufferTrace.Enable(true);
+  drawTrace.Enable(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack::NamedParams params;
+  params["divisor"] << "1";
+  DALI_TEST_CHECK(bufferTrace.FindMethodAndParams("VertexAttribDivisor", params));
+
+  TraceCallStack::NamedParams params2;
+  DALI_TEST_CHECK(drawTrace.FindMethodAndGetParameters("DrawArraysInstanced", params2));
+  std::ostringstream oss;
+  oss << sizeof(instanceData) / sizeof(InstanceData);
+  DALI_TEST_EQUALS(params2["instanceCount"].str(), oss.str(), TEST_LOCATION);
+  END_TEST;
+}
index 3d0f0f5..6d6eb40 100644 (file)
@@ -630,6 +630,7 @@ struct VertexInputState
     }
     uint32_t        stride;
     VertexInputRate inputRate;
+    //@todo Add actual rate...
   };
 
   /**
index b6bbf32..547d60d 100644 (file)
@@ -171,6 +171,17 @@ uint32_t VertexBuffer::GetSize() const
   return mSize;
 }
 
+void VertexBuffer::SetDivisor(uint32_t divisor)
+{
+  SceneGraph::SetVertexBufferDivisorMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject, divisor);
+  mDivisor = divisor;
+}
+
+uint32_t VertexBuffer::GetDivisor() const
+{
+  return mDivisor;
+}
+
 const Render::VertexBuffer* VertexBuffer::GetRenderObject() const
 {
   return mRenderObject;
index dcba098..a10a886 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_VERTEX_BUFFER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -44,20 +44,30 @@ class VertexBuffer : public BaseObject
 {
 public:
   /**
-   * @copydoc PropertBuffer::New()
+   * @copydoc Dali::VertexBuffer::New()
    */
   static VertexBufferPtr New(Dali::Property::Map& format);
 
   /**
-   * @copydoc PropertBuffer::SetData()
+   * @copydoc Dali::VertexBuffer::SetData()
    */
   void SetData(const void* data, uint32_t size);
 
   /**
-   * @copydoc PropertBuffer::GetSize()
+   * @copydoc Dali::VertexBuffer::GetSize()
    */
   uint32_t GetSize() const;
 
+  /**
+   * @copydoc Dali::VertexBuffer::SetDivisor()
+   */
+  void SetDivisor(uint32_t divisor);
+
+  /**
+   * @copydoc Dali::VertexBuffer::GetDivisor()
+   */
+  uint32_t GetDivisor() const;
+
 public: // Default property extensions from Object
   /**
    * @brief Get the render thread side of the VertexBuffer
@@ -87,11 +97,12 @@ private: // unimplemented methods
   VertexBuffer(const VertexBuffer&);
   VertexBuffer& operator=(const VertexBuffer&);
 
-private:                                      // data
-  EventThreadServices&  mEventThreadServices; ///<Used to send messages to the render thread via update thread
-  Render::VertexBuffer* mRenderObject;        ///<Render side object
-  uint32_t              mBufferFormatSize;
-  uint32_t              mSize; ///< Number of elements in the buffer
+private:                                        // data
+  EventThreadServices&  mEventThreadServices;   ///<Used to send messages to the render thread via update thread
+  Render::VertexBuffer* mRenderObject{nullptr}; ///<Render side object
+  uint32_t              mBufferFormatSize{0};
+  uint32_t              mSize{0};    ///< Number of elements in the buffer
+  uint32_t              mDivisor{0}; ///< How many elements to skip in instanced draw
 };
 
 /**
index 3f655f4..4e4633f 100644 (file)
@@ -209,8 +209,14 @@ PipelineCacheL0* PipelineCache::GetPipelineCacheL0(std::size_t hash, Program* pr
     {
       const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
 
+      uint32_t                  divisor         = vertexBuffer->GetDivisor();
+      Graphics::VertexInputRate vertexInputRate = (divisor == 0
+                                                     ? Graphics::VertexInputRate::PER_VERTEX
+                                                     : Graphics::VertexInputRate::PER_INSTANCE);
+
       vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
-                                                   Graphics::VertexInputRate::PER_VERTEX);
+                                                   vertexInputRate);
+      //@todo Add the actual rate to the graphics struct
 
       const uint32_t attributeCount          = vertexBuffer->GetAttributeCount();
       uint32_t       lastBoundAttributeIndex = 0;
index b407b6f..83be141 100644 (file)
@@ -93,6 +93,7 @@ void Geometry::SetIndexBuffer(Uint32ContainerType& indices)
 void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer)
 {
   const auto&& end = mVertexBuffers.End();
+  // @todo if this buffer is the only instance buffer, reduce instance count to 1.
   for(auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter)
   {
     if(*iter == vertexBuffer)
@@ -159,6 +160,11 @@ bool Geometry::BindVertexAttributes(Graphics::CommandBuffer& commandBuffer)
 
   for(uint32_t i = 0; i < vertexBufferCount; ++i)
   {
+    if(mVertexBuffers[i]->GetDivisor() > 0)
+    {
+      mInstanceCount = mVertexBuffers[i]->GetElementCount();
+    }
+
     const GpuBuffer* gpuBuffer = mVertexBuffers[i]->GetGpuBuffer();
     if(gpuBuffer)
     {
@@ -219,7 +225,7 @@ bool Geometry::Draw(
       commandBuffer.BindIndexBuffer(*ibo, 0, mIndexType);
     }
 
-    commandBuffer.DrawIndexed(numIndices, 1, firstIndexOffset, 0, 0);
+    commandBuffer.DrawIndexed(numIndices, mInstanceCount, firstIndexOffset, 0, 0);
   }
   else
   {
@@ -232,7 +238,7 @@ bool Geometry::Draw(
       numVertices = static_cast<uint32_t>(mVertexBuffers[0]->GetElementCount());
     }
 
-    commandBuffer.Draw(numVertices, 1, 0, 0);
+    commandBuffer.Draw(numVertices, mInstanceCount, 0, 0);
   }
   return true;
 }
index 2f04c97..0af4faa 100644 (file)
@@ -151,6 +151,7 @@ private:
   OwnerPointer<GpuBuffer> mIndexBuffer;
   IndexType               mIndexType;
   Type                    mGeometryType;
+  uint32_t                mInstanceCount{0};
 
   // Booleans
   bool mIndicesChanged : 1;
index 1a881d1..b140cef 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -78,6 +78,16 @@ bool VertexBuffer::Update(Graphics::Controller& graphicsController)
   return true;
 }
 
+void VertexBuffer::SetDivisor(uint32_t divisor)
+{
+  mDivisor = divisor;
+}
+
+uint32_t VertexBuffer::GetDivisor()
+{
+  return mDivisor;
+}
+
 } // namespace Render
 } // namespace Internal
 } // namespace Dali
index b7074ef..a8b86c1 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_RENDER_VERTEX_BUFFER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -87,6 +87,17 @@ public:
   bool Update(Graphics::Controller& graphicsController);
 
   /**
+   * @brief Set the divisor of the buffer for instanced drawing
+   * @param[in] divisor The divisor (0 = not instanced, >=1 = instanced)
+   */
+  void SetDivisor(uint32_t divisor);
+
+  /**
+   * Get the divisor for the vertex buffer
+   */
+  [[nodiscard]] uint32_t GetDivisor();
+
+  /**
    * Get the number of attributes present in the buffer
    * @return The number of attributes stored in this buffer
    */
@@ -152,6 +163,7 @@ private:
   OwnerPointer<GpuBuffer>              mGpuBuffer; ///< Pointer to the GpuBuffer associated with this RenderVertexBuffer
 
   uint32_t mSize;        ///< Number of Elements in the buffer
+  uint32_t mDivisor{0};  ///< The divisor (0:not instanced, >=1:instanced)
   bool     mDataChanged; ///< Flag to know if data has changed in a frame
 };
 
index 4a2f1bb..985bcbd 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <dali/internal/render/common/render-manager.h>
 #include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/renderers/render-vertex-buffer.h>
 
 // Un-comment to enable node tree debug logging
 //#define NODE_TREE_LOGGING 1
@@ -1375,6 +1376,13 @@ void UpdateManager::SetVertexBufferData(Render::VertexBuffer* vertexBuffer, Owne
   new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetVertexBufferData, vertexBuffer, data, size);
 }
 
+void UpdateManager::SetVertexBufferDivisor(Render::VertexBuffer* vertexBuffer, uint32_t divisor)
+{
+  using LocalType = MessageValue1<Render::VertexBuffer, uint32_t>;
+  uint32_t* slot  = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(LocalType));
+  new(slot) LocalType(vertexBuffer, &Render::VertexBuffer::SetDivisor, divisor);
+}
+
 void UpdateManager::AddGeometry(OwnerPointer<Render::Geometry>& geometry)
 {
   // Message has ownership of format while in transit from update -> render
index 908f827..dabe08f 100644 (file)
@@ -477,6 +477,14 @@ public:
   void SetVertexBufferData(Render::VertexBuffer* vertexBuffer, OwnerPointer<Vector<uint8_t>>& data, uint32_t size);
 
   /**
+   * Sets the divisor of a vertex buffer. This is used by the GPU to provide
+   * instanced drawing.
+   * @param[in] vertexBuffer The property buffer.
+   * @param[in] divisor The instance divisor. 0 to turn instancing off.
+   */
+  void SetVertexBufferDivisor(Render::VertexBuffer* vertexBuffer, uint32_t divisor);
+
+  /**
    * Adds a geometry to the RenderManager
    * @param[in] geometry The geometry to add
    * @post Sends a message to RenderManager to add the Geometry
@@ -1263,6 +1271,13 @@ inline void SetVertexBufferData(UpdateManager& manager, Render::VertexBuffer& ve
   new(slot) LocalType(&manager, &UpdateManager::SetVertexBufferData, &vertexBuffer, data, size);
 }
 
+inline void SetVertexBufferDivisorMessage(UpdateManager& manager, Render::VertexBuffer& vertexBuffer, uint32_t divisor)
+{
+  using LocalType = MessageValue2<UpdateManager, Render::VertexBuffer*, uint32_t>;
+  uint32_t* slot  = manager.ReserveMessageSlot(sizeof(LocalType));
+  new(slot) LocalType(&manager, &UpdateManager::SetVertexBufferDivisor, &vertexBuffer, divisor);
+}
+
 inline void AddGeometry(UpdateManager& manager, OwnerPointer<Render::Geometry>& geometry)
 {
   // Message has ownership of Geometry while in transit from event -> update
index c2351c4..85b8bb3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -58,6 +58,16 @@ std::size_t VertexBuffer::GetSize() const
   return GetImplementation(*this).GetSize();
 }
 
+void VertexBuffer::SetDivisor(uint32_t divisor)
+{
+  GetImplementation(*this).SetDivisor(divisor);
+}
+
+uint32_t VertexBuffer::GetDivisor() const
+{
+  return GetImplementation(*this).GetDivisor();
+}
+
 VertexBuffer::VertexBuffer(Internal::VertexBuffer* pointer)
 : BaseHandle(pointer)
 {
index 6c80284..7300a38 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_VERTEX_BUFFER_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -171,6 +171,27 @@ public:
    */
   std::size_t GetSize() const;
 
+  /**
+   * @brief Sets vertex divisor for all attributes
+   *
+   * If instancing isn't supported, the function has no effect.
+   * It's responsibility of developer to make sure the feature is supported.
+   * A divisor of 0 will turn off instanced drawing.
+   * Currently, a divisor > 1 will turn on instanced draw, but will have an
+   * actual rate of 1.
+   *
+   * @param[in] divisor Sets vertex buffer divisor for an instanced draw
+   */
+  void SetDivisor(uint32_t divisor);
+
+  /**
+   * @brief Get the divisor for the given attribute. A return value of 0 means that
+   * instancing is turned off.
+   *
+   * @return either 0 (not instanced), or > 0 (instanced)
+   */
+  uint32_t GetDivisor() const;
+
 public:
   /**
    * @brief The constructor.