From 4e17bda6fcb0eab26bf8fa551ec536549e103af3 Mon Sep 17 00:00:00 2001 From: Eunki Hong Date: Sat, 18 Feb 2023 20:06:24 +0900 Subject: [PATCH] Allow to load uint32_t indices for geometry Dali's default indices use uint16_t. But if heavy 3D model who need more than 65536 indexes loaded, It will break index. This patch make Scene3D can allow to use uint32_t type indeces load and generete Geometry by it. Change-Id: I020b27642760e6262fb5137a74e59b8da803e859 Signed-off-by: Eunki Hong --- automated-tests/src/dali/utc-Dali-Geometry.cpp | 59 ++++++++++++++++++++++ dali/internal/event/rendering/geometry-impl.cpp | 18 +++++-- dali/internal/event/rendering/geometry-impl.h | 5 ++ .../event/rendering/vertex-buffer-impl.cpp | 2 +- dali/internal/render/common/render-manager.cpp | 7 ++- dali/internal/render/common/render-manager.h | 9 +++- dali/internal/render/renderers/render-geometry.cpp | 45 +++++++++++++++-- dali/internal/render/renderers/render-geometry.h | 20 ++++++-- dali/internal/update/manager/update-manager.cpp | 15 +++++- dali/internal/update/manager/update-manager.h | 34 ++++++++++--- dali/public-api/rendering/geometry.cpp | 5 ++ dali/public-api/rendering/geometry.h | 15 +++++- 12 files changed, 207 insertions(+), 27 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-Geometry.cpp b/automated-tests/src/dali/utc-Dali-Geometry.cpp index 3654fdd..2243872 100644 --- a/automated-tests/src/dali/utc-Dali-Geometry.cpp +++ b/automated-tests/src/dali/utc-Dali-Geometry.cpp @@ -351,6 +351,65 @@ int UtcDaliGeometrySetIndexBuffer(void) END_TEST; } +int UtcDaliGeometrySetIndexBuffer32Bits(void) +{ + TestApplication application; + auto& bufferTrace = application.GetGlAbstraction().GetBufferTrace(); + bufferTrace.Enable(true); + bufferTrace.EnableLogging(true); + + tet_infoline("Test SetIndexBuffer 32Bits"); + + VertexBuffer vertexBuffer = CreateVertexBuffer("aPosition", "aTexCoord"); + + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer(vertexBuffer); + + 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); + + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + + { + const TestGlAbstraction::BufferDataCalls& bufferDataCalls = + application.GetGlAbstraction().GetBufferDataCalls(); + + DALI_TEST_EQUALS(bufferDataCalls.size(), 3u, TEST_LOCATION); + + DALI_TEST_EQUALS(bufferDataCalls[0], 4 * sizeof(TexturedQuadVertex), TEST_LOCATION); + } + + // Set index buffer + application.GetGlAbstraction().ResetBufferDataCalls(); + + const uint32_t indexData32Bits[6] = {0, 3, 1, 0, 2, 3}; + geometry.SetIndexBuffer(indexData32Bits, sizeof(indexData32Bits) / sizeof(indexData32Bits[0])); + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + + { + const TestGlAbstraction::BufferDataCalls& bufferDataCalls = + application.GetGlAbstraction().GetBufferDataCalls(); + + //Only the index buffer should be uploaded + DALI_TEST_EQUALS(bufferDataCalls.size(), 1u, TEST_LOCATION); + + // should be unsigned int instead of unsigned short + DALI_TEST_EQUALS(bufferDataCalls[0], 6 * sizeof(uint32_t), TEST_LOCATION); + } + + END_TEST; +} + int UtcDaliGeometrySetGetGeometryType01(void) { TestApplication application; diff --git a/dali/internal/event/rendering/geometry-impl.cpp b/dali/internal/event/rendering/geometry-impl.cpp index 4b6ee13..3ec6362 100644 --- a/dali/internal/event/rendering/geometry-impl.cpp +++ b/dali/internal/event/rendering/geometry-impl.cpp @@ -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. @@ -56,10 +56,22 @@ void Geometry::RemoveVertexBuffer(uint32_t index) void Geometry::SetIndexBuffer(const uint16_t* indices, uint32_t count) { - Dali::Vector indexData; + Render::Geometry::Uint16ContainerType indexData; if(indices && count) { - indexData.Resize(count); + indexData.ResizeUninitialized(count); + std::copy(indices, indices + count, indexData.Begin()); + } + + SceneGraph::SetIndexBufferMessage(mEventThreadServices.GetUpdateManager(), *mRenderObject, indexData); +} + +void Geometry::SetIndexBuffer(const uint32_t* indices, uint32_t count) +{ + Render::Geometry::Uint32ContainerType indexData; + if(indices && count) + { + indexData.ResizeUninitialized(count); std::copy(indices, indices + count, indexData.Begin()); } diff --git a/dali/internal/event/rendering/geometry-impl.h b/dali/internal/event/rendering/geometry-impl.h index 4663727..261ca3c 100644 --- a/dali/internal/event/rendering/geometry-impl.h +++ b/dali/internal/event/rendering/geometry-impl.h @@ -76,6 +76,11 @@ public: void SetIndexBuffer(const uint16_t* indices, uint32_t count); /** + * @copydoc Dali::Geometry::SetIndexBuffer() + */ + void SetIndexBuffer(const uint32_t* indices, uint32_t count); + + /** * @copydoc Dali::Geometry::SetType() */ void SetType(Dali::Geometry::Type geometryType); diff --git a/dali/internal/event/rendering/vertex-buffer-impl.cpp b/dali/internal/event/rendering/vertex-buffer-impl.cpp index 462fc9c..689d703 100644 --- a/dali/internal/event/rendering/vertex-buffer-impl.cpp +++ b/dali/internal/event/rendering/vertex-buffer-impl.cpp @@ -155,7 +155,7 @@ void VertexBuffer::SetData(const void* data, uint32_t size) // create a new DALi vector to store the buffer data // the heap allocated vector will end up being owned by Render::VertexBuffer OwnerPointer > bufferCopy = new Dali::Vector(); - bufferCopy->Resize(bufferSize); + bufferCopy->ResizeUninitialized(bufferSize); // copy the data const uint8_t* source = static_cast(data); diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index e54741f..b72ec9b 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -369,7 +369,12 @@ void RenderManager::SetVertexBufferData(Render::VertexBuffer* vertexBuffer, Owne vertexBuffer->SetData(data.Release(), size); } -void RenderManager::SetIndexBuffer(Render::Geometry* geometry, Dali::Vector& indices) +void RenderManager::SetIndexBuffer(Render::Geometry* geometry, Render::Geometry::Uint16ContainerType& indices) +{ + geometry->SetIndexBuffer(indices); +} + +void RenderManager::SetIndexBuffer(Render::Geometry* geometry, Render::Geometry::Uint32ContainerType& indices) { geometry->SetIndexBuffer(indices); } diff --git a/dali/internal/render/common/render-manager.h b/dali/internal/render/common/render-manager.h index 7f4843f..cf40117 100644 --- a/dali/internal/render/common/render-manager.h +++ b/dali/internal/render/common/render-manager.h @@ -211,7 +211,14 @@ public: * @param[in] geometry The geometry * @param[in] data A vector containing the indices */ - void SetIndexBuffer(Render::Geometry* geometry, Dali::Vector& data); + void SetIndexBuffer(Render::Geometry* geometry, Render::Geometry::Uint16ContainerType& data); + + /** + * Sets the data for the index buffer of an existing geometry + * @param[in] geometry The geometry + * @param[in] data A vector containing the indices + */ + void SetIndexBuffer(Render::Geometry* geometry, Render::Geometry::Uint32ContainerType& data); /** * Set the geometry type of an existing render geometry diff --git a/dali/internal/render/renderers/render-geometry.cpp b/dali/internal/render/renderers/render-geometry.cpp index e12f37b..feb6244 100644 --- a/dali/internal/render/renderers/render-geometry.cpp +++ b/dali/internal/render/renderers/render-geometry.cpp @@ -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. @@ -28,9 +28,32 @@ namespace Internal { namespace Render { +namespace +{ +inline constexpr size_t GetSizeOfIndexFromIndexType(Dali::Graphics::Format graphicsFormat) +{ + switch(graphicsFormat) + { + case Dali::Graphics::Format::R16_UINT: + { + return sizeof(uint16_t); + } + case Dali::Graphics::Format::R32_UINT: + { + return sizeof(uint32_t); + } + default: + { + // TODO : Not implmeneted. + return sizeof(uint16_t); + } + } +} +} // unnamed namespace Geometry::Geometry() : mIndices(), mIndexBuffer(nullptr), + mIndexType(Dali::Graphics::Format::R16_UINT), mGeometryType(Dali::Geometry::TRIANGLES), mIndicesChanged(false), mHasBeenUpdated(false), @@ -51,10 +74,20 @@ const Vector& Geometry::GetVertexBuffers() const return mVertexBuffers; } -void Geometry::SetIndexBuffer(Dali::Vector& indices) +void Geometry::SetIndexBuffer(Uint16ContainerType& indices) { mIndices.Swap(indices); mIndicesChanged = true; + mIndexType = Graphics::Format::R16_UINT; +} + +void Geometry::SetIndexBuffer(Uint32ContainerType& indices) +{ + // mIndices type is not matched with indices. Copy memory hardly. + mIndices.ResizeUninitialized(indices.Count() * 2); + memcpy(mIndices.Begin(), indices.Begin(), indices.Count() * sizeof(uint32_t)); + mIndicesChanged = true; + mIndexType = Graphics::Format::R32_UINT; } void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer) @@ -154,12 +187,14 @@ bool Geometry::Draw( intptr_t firstIndexOffset(0u); if(mIndexBuffer) { - numIndices = static_cast(mIndices.Size()); + std::size_t sizeOfIndex = GetSizeOfIndexFromIndexType(mIndexType); + + numIndices = static_cast(mIndices.Size() * sizeof(uint16_t) / sizeOfIndex); if(elementBufferOffset != 0u) { elementBufferOffset = (elementBufferOffset >= numIndices) ? numIndices - 1 : elementBufferOffset; - firstIndexOffset = intptr_t(elementBufferOffset * sizeof(uint16_t)); + firstIndexOffset = intptr_t(elementBufferOffset * sizeOfIndex); numIndices -= elementBufferOffset; } @@ -176,7 +211,7 @@ bool Geometry::Draw( const Graphics::Buffer* ibo = mIndexBuffer->GetGraphicsObject(); if(ibo) { - commandBuffer.BindIndexBuffer(*ibo, 0, Graphics::Format::R16_UINT); + commandBuffer.BindIndexBuffer(*ibo, 0, mIndexType); } commandBuffer.DrawIndexed(numIndices, 1, firstIndexOffset, 0, 0); diff --git a/dali/internal/render/renderers/render-geometry.h b/dali/internal/render/renderers/render-geometry.h index 54d9ee4..a23c7a0 100644 --- a/dali/internal/render/renderers/render-geometry.h +++ b/dali/internal/render/renderers/render-geometry.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_RENDER_GEOMETRY_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. @@ -20,6 +20,7 @@ // INTERNAL INCLUDES #include #include +#include #include #include #include @@ -44,7 +45,11 @@ class VertexBuffer; class Geometry { public: - using Type = Dali::Geometry::Type; + using Type = Dali::Geometry::Type; + using IndexType = Dali::Graphics::Format; + + using Uint16ContainerType = Dali::Vector; + using Uint32ContainerType = Dali::Vector; Geometry(); @@ -63,7 +68,13 @@ public: * Set the data for the index buffer to be used by the geometry * @param[in] indices A vector containing the indices */ - void SetIndexBuffer(Dali::Vector& indices); + void SetIndexBuffer(Uint16ContainerType& indices); + + /** + * Set the data for the index buffer to be used by the geometry + * @param[in] indices A vector containing the indices + */ + void SetIndexBuffer(Uint32ContainerType& indices); /** * Removes a VertexBuffer from the geometry @@ -128,8 +139,9 @@ private: // VertexBuffers Vector mVertexBuffers; - Dali::Vector mIndices; + Uint16ContainerType mIndices; OwnerPointer mIndexBuffer; + IndexType mIndexType; Type mGeometryType; // Booleans diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp index 778a758..5b3bf16 100644 --- a/dali/internal/update/manager/update-manager.cpp +++ b/dali/internal/update/manager/update-manager.cpp @@ -1390,9 +1390,20 @@ void UpdateManager::SetGeometryType(Render::Geometry* geometry, uint32_t geometr new(slot) DerivedType(&mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType); } -void UpdateManager::SetIndexBuffer(Render::Geometry* geometry, Dali::Vector& indices) +void UpdateManager::SetIndexBuffer(Render::Geometry* geometry, Render::Geometry::Uint16ContainerType& indices) { - using DerivedType = IndexBufferMessage; + using DerivedType = IndexBufferMessage; + + // Reserve some memory inside the render queue + uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType)); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new(slot) DerivedType(&mImpl->renderManager, geometry, indices); +} + +void UpdateManager::SetIndexBuffer(Render::Geometry* geometry, Render::Geometry::Uint32ContainerType& indices) +{ + using DerivedType = IndexBufferMessage; // Reserve some memory inside the render queue uint32_t* slot = mImpl->renderQueue.ReserveMessageSlot(mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof(DerivedType)); diff --git a/dali/internal/update/manager/update-manager.h b/dali/internal/update/manager/update-manager.h index ee5cf87..aacfe23 100644 --- a/dali/internal/update/manager/update-manager.h +++ b/dali/internal/update/manager/update-manager.h @@ -498,7 +498,14 @@ public: * @param[in] geometry The geometry * @param[in] indices A vector containing the indices for the geometry */ - void SetIndexBuffer(Render::Geometry* geometry, Dali::Vector& indices); + void SetIndexBuffer(Render::Geometry* geometry, Render::Geometry::Uint16ContainerType& indices); + + /** + * Sets the index buffer to be used by a geometry + * @param[in] geometry The geometry + * @param[in] indices A vector containing the indices for the geometry + */ + void SetIndexBuffer(Render::Geometry* geometry, Render::Geometry::Uint32ContainerType& indices); /** * Adds a vertex buffer to a geometry @@ -1297,14 +1304,14 @@ inline void RemoveVertexBufferMessage(UpdateManager& manager, Render::Geometry& } // Custom message type for SetIndexBuffer() used to move data with Vector::Swap() -template +template class IndexBufferMessage : public MessageBase { public: /** * Constructor which does a Vector::Swap() */ - IndexBufferMessage(T* manager, Render::Geometry* geometry, Dali::Vector& indices) + IndexBufferMessage(T* manager, Render::Geometry* geometry, IndexContainerType& indices) : MessageBase(), mManager(manager), mRenderGeometry(geometry) @@ -1327,14 +1334,25 @@ public: } private: - T* mManager; - Render::Geometry* mRenderGeometry; - Dali::Vector mIndices; + T* mManager; + Render::Geometry* mRenderGeometry; + IndexContainerType mIndices; }; -inline void SetIndexBufferMessage(UpdateManager& manager, Render::Geometry& geometry, Dali::Vector& indices) +inline void SetIndexBufferMessage(UpdateManager& manager, Render::Geometry& geometry, Render::Geometry::Uint16ContainerType& indices) +{ + using LocalType = IndexBufferMessage; + + // Reserve some memory inside the message queue + uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType)); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new(slot) LocalType(&manager, &geometry, indices); +} + +inline void SetIndexBufferMessage(UpdateManager& manager, Render::Geometry& geometry, Render::Geometry::Uint32ContainerType& indices) { - using LocalType = IndexBufferMessage; + using LocalType = IndexBufferMessage; // Reserve some memory inside the message queue uint32_t* slot = manager.ReserveMessageSlot(sizeof(LocalType)); diff --git a/dali/public-api/rendering/geometry.cpp b/dali/public-api/rendering/geometry.cpp index 6c82097..a810779 100644 --- a/dali/public-api/rendering/geometry.cpp +++ b/dali/public-api/rendering/geometry.cpp @@ -67,6 +67,11 @@ void Geometry::SetIndexBuffer(const uint16_t* indices, size_t count) GetImplementation(*this).SetIndexBuffer(indices, static_cast(count)); } +void Geometry::SetIndexBuffer(const uint32_t* indices, size_t count) +{ + GetImplementation(*this).SetIndexBuffer(indices, static_cast(count)); +} + void Geometry::SetType(Type geometryType) { GetImplementation(*this).SetType(geometryType); diff --git a/dali/public-api/rendering/geometry.h b/dali/public-api/rendering/geometry.h index cfb0f15..81e0421 100644 --- a/dali/public-api/rendering/geometry.h +++ b/dali/public-api/rendering/geometry.h @@ -2,7 +2,7 @@ #define DALI_GEOMETRY_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. @@ -156,7 +156,7 @@ public: void RemoveVertexBuffer(std::size_t index); /** - * @brief Sets a the index data to be used as a source of indices for the geometry + * @brief Sets the index data to be used as a source of indices for the geometry * Setting this buffer will cause the geometry to be rendered using indices. * To unset call SetIndexBuffer with a null pointer or count 0. * @@ -167,6 +167,17 @@ public: void SetIndexBuffer(const uint16_t* indices, size_t count); /** + * @brief Sets the 32bits index data to be used as a source of indices for the geometry + * Setting this buffer will cause the geometry to be rendered using indices. + * To unset call SetIndexBuffer with a null pointer or count 0. + * + * @SINCE_2_2.16 + * @param[in] indices Array of indices with uint32_t elements. + * @param[in] count Number of indices in the array + */ + void SetIndexBuffer(const uint32_t* indices, size_t count); + + /** * @brief Sets the type of primitives this geometry contains. * * @SINCE_1_1.43 -- 2.7.4