2 * Copyright (c) 2024 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <dali/internal/render/renderers/render-geometry.h>
21 #include <dali/internal/common/buffer-index.h>
22 #include <dali/internal/render/renderers/render-vertex-buffer.h>
23 #include <dali/internal/render/shaders/program.h>
33 inline constexpr size_t GetSizeOfIndexFromIndexType(Dali::Graphics::Format graphicsFormat)
35 switch(graphicsFormat)
37 case Dali::Graphics::Format::R16_UINT:
39 return sizeof(uint16_t);
41 case Dali::Graphics::Format::R32_UINT:
43 return sizeof(uint32_t);
47 // TODO : Not implmeneted.
48 return sizeof(uint16_t);
52 } // unnamed namespace
55 mIndexBuffer(nullptr),
56 mIndexType(Dali::Graphics::Format::R16_UINT),
57 mGeometryType(Dali::Geometry::TRIANGLES),
58 mIndicesChanged(false),
59 mHasBeenUpdated(false),
60 mAttributesChanged(true)
64 Geometry::~Geometry() = default;
66 void Geometry::AddVertexBuffer(Render::VertexBuffer* vertexBuffer)
68 mVertexBuffers.PushBack(vertexBuffer);
69 mAttributesChanged = true;
72 const Vector<Render::VertexBuffer*>& Geometry::GetVertexBuffers() const
74 return mVertexBuffers;
77 void Geometry::SetIndexBuffer(Uint16ContainerType& indices)
79 mIndices.Swap(indices);
80 mIndicesChanged = true;
81 mIndexType = Graphics::Format::R16_UINT;
84 void Geometry::SetIndexBuffer(Uint32ContainerType& indices)
86 // mIndices type is not matched with indices. Copy memory hardly.
87 mIndices.ResizeUninitialized(indices.Count() * 2);
88 memcpy(mIndices.Begin(), indices.Begin(), indices.Count() * sizeof(uint32_t));
89 mIndicesChanged = true;
90 mIndexType = Graphics::Format::R32_UINT;
93 void Geometry::RemoveVertexBuffer(const Render::VertexBuffer* vertexBuffer)
95 const auto&& end = mVertexBuffers.End();
97 for(auto&& iter = mVertexBuffers.Begin(); iter != end; ++iter)
99 if(*iter == vertexBuffer)
101 //This will delete the gpu buffer associated to the RenderVertexBuffer if there is one
102 mVertexBuffers.Remove(iter);
103 mAttributesChanged = true;
109 void Geometry::OnRenderFinished()
111 mHasBeenUpdated = false;
112 mAttributesChanged = false;
115 void Geometry::Upload(Graphics::Controller& graphicsController)
124 mIndexBuffer = nullptr;
128 if(mIndexBuffer == nullptr)
130 // Currently we are unable to reuse index buffer so the write policy is to preserve current content
131 mIndexBuffer = new GpuBuffer(graphicsController, 0 | Graphics::BufferUsage::INDEX_BUFFER, GpuBuffer::WritePolicy::RETAIN);
134 uint32_t bufferSize = static_cast<uint32_t>(sizeof(uint16_t) * mIndices.Size());
135 mIndexBuffer->UpdateDataBuffer(graphicsController, bufferSize, &mIndices[0]);
138 mIndicesChanged = false;
141 for(auto&& buffer : mVertexBuffers)
143 if(!buffer->Update(graphicsController))
145 //Vertex buffer is not ready ( Size, data or format has not been specified yet )
150 mHasBeenUpdated = true;
154 bool Geometry::BindVertexAttributes(Graphics::CommandBuffer& commandBuffer)
156 //Bind buffers to attribute locations
157 const auto vertexBufferCount = static_cast<uint32_t>(mVertexBuffers.Count());
159 std::vector<const Graphics::Buffer*> buffers;
160 std::vector<uint32_t> offsets;
162 for(uint32_t i = 0; i < vertexBufferCount; ++i)
164 const GpuBuffer* gpuBuffer = mVertexBuffers[i]->GetGpuBuffer();
167 const Graphics::Buffer* buffer = gpuBuffer->GetGraphicsObject();
171 buffers.push_back(buffer);
172 offsets.push_back(0u);
175 //@todo Figure out why this is being drawn without geometry having been uploaded
177 if(buffers.empty() || buffers.size() != vertexBufferCount)
182 commandBuffer.BindVertexBuffers(0, buffers, offsets);
188 Graphics::Controller& graphicsController,
189 Graphics::CommandBuffer& commandBuffer,
190 uint32_t elementBufferOffset,
191 uint32_t elementBufferCount,
192 uint32_t instanceCount)
194 uint32_t numIndices(0u);
195 intptr_t firstIndexOffset(0u);
198 std::size_t sizeOfIndex = GetSizeOfIndexFromIndexType(mIndexType);
200 numIndices = static_cast<uint32_t>(mIndices.Size() * sizeof(uint16_t) / sizeOfIndex);
202 if(elementBufferOffset != 0u)
204 elementBufferOffset = (elementBufferOffset >= numIndices) ? numIndices : elementBufferOffset;
205 firstIndexOffset = intptr_t(elementBufferOffset * sizeOfIndex);
206 numIndices -= elementBufferOffset;
209 if(elementBufferCount != 0u)
211 numIndices = std::min(elementBufferCount, numIndices);
216 if(mIndexBuffer && mGeometryType != Dali::Geometry::POINTS)
218 // Issue draw call only if there's non-zero numIndices
222 const Graphics::Buffer* ibo = mIndexBuffer->GetGraphicsObject();
225 commandBuffer.BindIndexBuffer(*ibo, 0, mIndexType);
228 commandBuffer.DrawIndexed(numIndices, instanceCount, firstIndexOffset, 0, 0);
233 // Un-indexed draw call
234 uint32_t numVertices(0u);
235 uint32_t firstVertex(0u);
237 // Use element buffer count for drawing arrays (needs changing API, for workaround)
238 if(elementBufferCount)
240 numVertices = elementBufferCount;
241 firstVertex = elementBufferOffset;
243 else if(mVertexBuffers.Count() > 0)
245 // truncated, no value loss happening in practice
246 numVertices = static_cast<uint32_t>(mVertexBuffers[0]->GetRenderableElementCount());
248 // In case we have more buffers, we select buffer with less elements to render
249 // TODO: we may eventually support wrapping around buffers????
250 else if(mVertexBuffers.Count() > 1)
252 auto elementsCount = mVertexBuffers[0]->GetRenderableElementCount();
253 for(auto& vertexBuffer : mVertexBuffers)
255 elementsCount = std::min(elementsCount, vertexBuffer->GetRenderableElementCount());
257 numVertices = elementsCount;
260 // Issue draw call only if there's non-zero numVertices
263 commandBuffer.Draw(numVertices, instanceCount, firstVertex, 0);
269 Graphics::PrimitiveTopology Geometry::GetTopology() const
271 Graphics::PrimitiveTopology topology = Graphics::PrimitiveTopology::TRIANGLE_LIST;
273 switch(mGeometryType)
275 case Dali::Geometry::TRIANGLES:
277 topology = Graphics::PrimitiveTopology::TRIANGLE_LIST;
280 case Dali::Geometry::LINES:
282 topology = Graphics::PrimitiveTopology::LINE_LIST;
285 case Dali::Geometry::POINTS:
287 topology = Graphics::PrimitiveTopology::POINT_LIST;
290 case Dali::Geometry::TRIANGLE_STRIP:
292 topology = Graphics::PrimitiveTopology::TRIANGLE_STRIP;
295 case Dali::Geometry::TRIANGLE_FAN:
297 topology = Graphics::PrimitiveTopology::TRIANGLE_FAN;
300 case Dali::Geometry::LINE_LOOP:
302 topology = Graphics::PrimitiveTopology::LINE_LOOP;
305 case Dali::Geometry::LINE_STRIP:
307 topology = Graphics::PrimitiveTopology::LINE_STRIP;
314 } // namespace Render
315 } // namespace Internal