2 * Copyright (c) 2021 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.
19 #include <dali/internal/render/renderers/render-renderer.h>
22 #include <dali/internal/common/image-sampler.h>
23 #include <dali/internal/render/common/render-instruction.h>
24 #include <dali/internal/render/data-providers/node-data-provider.h>
25 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
26 #include <dali/internal/render/gl-resources/context.h>
27 #include <dali/internal/render/renderers/render-sampler.h>
28 #include <dali/internal/render/renderers/render-texture.h>
29 #include <dali/internal/render/renderers/render-vertex-buffer.h>
30 #include <dali/internal/render/shaders/program.h>
31 #include <dali/internal/render/shaders/scene-graph-shader.h>
40 * Helper to set view and projection matrices once per program
41 * @param program to set the matrices to
42 * @param modelMatrix to set
43 * @param viewMatrix to set
44 * @param projectionMatrix to set
45 * @param modelViewMatrix to set
46 * @param modelViewProjectionMatrix to set
48 inline void SetMatrices(Program& program,
49 const Matrix& modelMatrix,
50 const Matrix& viewMatrix,
51 const Matrix& projectionMatrix,
52 const Matrix& modelViewMatrix)
54 GLint loc = program.GetUniformLocation(Program::UNIFORM_MODEL_MATRIX);
55 if(Program::UNIFORM_UNKNOWN != loc)
57 program.SetUniformMatrix4fv(loc, 1, modelMatrix.AsFloat());
59 loc = program.GetUniformLocation(Program::UNIFORM_VIEW_MATRIX);
60 if(Program::UNIFORM_UNKNOWN != loc)
62 if(program.GetViewMatrix() != &viewMatrix)
64 program.SetViewMatrix(&viewMatrix);
65 program.SetUniformMatrix4fv(loc, 1, viewMatrix.AsFloat());
68 // set projection matrix if program has not yet received it this frame or if it is dirty
69 loc = program.GetUniformLocation(Program::UNIFORM_PROJECTION_MATRIX);
70 if(Program::UNIFORM_UNKNOWN != loc)
72 if(program.GetProjectionMatrix() != &projectionMatrix)
74 program.SetProjectionMatrix(&projectionMatrix);
75 program.SetUniformMatrix4fv(loc, 1, projectionMatrix.AsFloat());
78 loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
79 if(Program::UNIFORM_UNKNOWN != loc)
81 program.SetUniformMatrix4fv(loc, 1, modelViewMatrix.AsFloat());
84 loc = program.GetUniformLocation(Program::UNIFORM_MVP_MATRIX);
85 if(Program::UNIFORM_UNKNOWN != loc)
87 Matrix modelViewProjectionMatrix(false);
88 Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
89 program.SetUniformMatrix4fv(loc, 1, modelViewProjectionMatrix.AsFloat());
92 loc = program.GetUniformLocation(Program::UNIFORM_NORMAL_MATRIX);
93 if(Program::UNIFORM_UNKNOWN != loc)
96 normalMatrix = modelViewMatrix;
97 normalMatrix.Invert();
98 normalMatrix.Transpose();
99 program.SetUniformMatrix3fv(loc, 1, normalMatrix.AsFloat());
103 // Helper to get the vertex input format
104 Dali::Graphics::VertexInputFormat GetPropertyVertexFormat(Property::Type propertyType)
106 Dali::Graphics::VertexInputFormat type{};
111 case Property::STRING:
112 case Property::ARRAY:
114 case Property::EXTENTS: // i4?
115 case Property::RECTANGLE: // i4/f4?
116 case Property::ROTATION:
118 type = Dali::Graphics::VertexInputFormat::UNDEFINED;
121 case Property::BOOLEAN:
123 type = Dali::Graphics::VertexInputFormat::UNDEFINED; // type = GL_BYTE; @todo new type for this?
126 case Property::INTEGER:
128 type = Dali::Graphics::VertexInputFormat::INTEGER; // (short)
131 case Property::FLOAT:
133 type = Dali::Graphics::VertexInputFormat::FLOAT;
136 case Property::VECTOR2:
138 type = Dali::Graphics::VertexInputFormat::FVECTOR2;
141 case Property::VECTOR3:
143 type = Dali::Graphics::VertexInputFormat::FVECTOR3;
146 case Property::VECTOR4:
148 type = Dali::Graphics::VertexInputFormat::FVECTOR4;
151 case Property::MATRIX3:
153 type = Dali::Graphics::VertexInputFormat::FLOAT;
156 case Property::MATRIX:
158 type = Dali::Graphics::VertexInputFormat::FLOAT;
170 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
171 Render::Geometry* geometry,
172 uint32_t blendingBitmask,
173 const Vector4& blendColor,
174 FaceCullingMode::Type faceCullingMode,
175 bool preMultipliedAlphaEnabled,
176 DepthWriteMode::Type depthWriteMode,
177 DepthTestMode::Type depthTestMode,
178 DepthFunction::Type depthFunction,
179 StencilParameters& stencilParameters)
181 return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
184 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
185 Render::Geometry* geometry,
186 uint32_t blendingBitmask,
187 const Vector4& blendColor,
188 FaceCullingMode::Type faceCullingMode,
189 bool preMultipliedAlphaEnabled,
190 DepthWriteMode::Type depthWriteMode,
191 DepthTestMode::Type depthTestMode,
192 DepthFunction::Type depthFunction,
193 StencilParameters& stencilParameters)
194 : mRenderDataProvider(dataProvider),
198 mAttributeLocations(),
200 mStencilParameters(stencilParameters),
202 mIndexedDrawFirstElement(0),
203 mIndexedDrawElementsCount(0),
204 mDepthFunction(depthFunction),
205 mFaceCullingMode(faceCullingMode),
206 mDepthWriteMode(depthWriteMode),
207 mDepthTestMode(depthTestMode),
208 mUpdateAttributeLocations(true),
209 mPremultipledAlphaEnabled(preMultipliedAlphaEnabled),
210 mShaderChanged(false),
213 if(blendingBitmask != 0u)
215 mBlendingOptions.SetBitmask(blendingBitmask);
218 mBlendingOptions.SetBlendColor(blendColor);
221 void Renderer::Initialize(Context& context, Graphics::Controller& graphicsController)
224 mGraphicsController = &graphicsController;
227 Renderer::~Renderer() = default;
229 void Renderer::SetGeometry(Render::Geometry* geometry)
231 mGeometry = geometry;
232 mUpdateAttributeLocations = true;
234 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
236 mDrawCommands.clear();
237 mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
240 void Renderer::SetBlending(Context& context, bool blend)
242 context.SetBlend(blend);
245 // Blend color is optional and rarely used
246 const Vector4* blendColor = mBlendingOptions.GetBlendColor();
249 context.SetCustomBlendColor(*blendColor);
253 context.SetDefaultBlendColor();
256 // Set blend source & destination factors
257 context.BlendFuncSeparate(mBlendingOptions.GetBlendSrcFactorRgb(),
258 mBlendingOptions.GetBlendDestFactorRgb(),
259 mBlendingOptions.GetBlendSrcFactorAlpha(),
260 mBlendingOptions.GetBlendDestFactorAlpha());
262 // Set blend equations
263 Dali::DevelBlendEquation::Type rgbEquation = mBlendingOptions.GetBlendEquationRgb();
264 Dali::DevelBlendEquation::Type alphaEquation = mBlendingOptions.GetBlendEquationAlpha();
266 if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
268 if(rgbEquation != alphaEquation)
270 DALI_LOG_ERROR("Advanced Blend Equation have to be appried by using BlendEquation.\n");
272 context.BlendEquation(rgbEquation);
276 context.BlendEquationSeparate(rgbEquation, alphaEquation);
283 void Renderer::GlContextDestroyed()
285 mGeometry->GlContextDestroyed();
288 void Renderer::GlCleanup()
292 void Renderer::SetUniforms(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
294 // Check if the map has changed
295 DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
297 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
299 if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
300 node.GetUniformMapChanged(bufferIndex) ||
301 mUniformIndexMap.Count() == 0 ||
304 // Reset shader pointer
305 mShaderChanged = false;
307 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
308 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
310 uint32_t maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
311 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
312 mUniformIndexMap.Resize(maxMaps);
314 uint32_t mapIndex = 0;
315 for(; mapIndex < uniformMap.Count(); ++mapIndex)
317 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex].propertyPtr;
318 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform(uniformMap[mapIndex].uniformName);
321 for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
323 uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName);
325 for(uint32_t i = 0; i < uniformMap.Count(); ++i)
327 if(mUniformIndexMap[i].uniformIndex == uniformIndex)
329 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
337 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
338 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
343 mUniformIndexMap.Resize(mapIndex);
346 // Set uniforms in local map
347 for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
348 end = mUniformIndexMap.End();
352 SetUniformFromProperty(bufferIndex, program, *iter);
355 GLint sizeLoc = program.GetUniformLocation(Program::UNIFORM_SIZE);
358 program.SetSizeUniform3f(sizeLoc, size.x, size.y, size.z);
362 void Renderer::SetUniformFromProperty(BufferIndex bufferIndex, Program& program, UniformIndexMap& map)
364 GLint location = program.GetUniformLocation(map.uniformIndex);
365 if(Program::UNIFORM_UNKNOWN != location)
367 // switch based on property type to use correct GL uniform setter
368 switch(map.propertyValue->GetType())
370 case Property::INTEGER:
372 program.SetUniform1i(location, map.propertyValue->GetInteger(bufferIndex));
375 case Property::FLOAT:
377 program.SetUniform1f(location, map.propertyValue->GetFloat(bufferIndex));
380 case Property::VECTOR2:
382 Vector2 value(map.propertyValue->GetVector2(bufferIndex));
383 program.SetUniform2f(location, value.x, value.y);
387 case Property::VECTOR3:
389 Vector3 value(map.propertyValue->GetVector3(bufferIndex));
390 program.SetUniform3f(location, value.x, value.y, value.z);
394 case Property::VECTOR4:
396 Vector4 value(map.propertyValue->GetVector4(bufferIndex));
397 program.SetUniform4f(location, value.x, value.y, value.z, value.w);
401 case Property::ROTATION:
403 Quaternion value(map.propertyValue->GetQuaternion(bufferIndex));
404 program.SetUniform4f(location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w);
408 case Property::MATRIX:
410 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
411 program.SetUniformMatrix4fv(location, 1, value.AsFloat());
415 case Property::MATRIX3:
417 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
418 program.SetUniformMatrix3fv(location, 1, value.AsFloat());
424 // Other property types are ignored
431 bool Renderer::BindTextures(Context& context, Program& program, Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
433 uint32_t textureUnit = 0;
436 GLint uniformLocation(-1);
437 std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
438 std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
440 std::vector<Graphics::TextureBinding> textureBindings;
441 for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()) && result; ++i) // not expecting more than uint32_t of textures
445 if(program.GetSamplerUniformLocation(i, uniformLocation))
447 // if the sampler exists,
448 // if it's default, delete the graphics object
449 // otherwise re-initialize it if dirty
451 const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject()
454 boundTextures.PushBack(textures[i]->GetGraphicsObject());
455 const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
456 textureBindings.push_back(textureBinding);
458 program.SetUniform1i(uniformLocation, textureUnit); // Get through shader reflection
464 if(textureBindings.size() > 0)
466 commandBuffer.BindTextures(textureBindings);
472 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
474 mFaceCullingMode = mode;
478 void Renderer::SetBlendingBitMask(uint32_t bitmask)
480 mBlendingOptions.SetBitmask(bitmask);
484 void Renderer::SetBlendColor(const Vector4& color)
486 mBlendingOptions.SetBlendColor(color);
490 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
492 mIndexedDrawFirstElement = firstElement;
496 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
498 mIndexedDrawElementsCount = elementsCount;
502 void Renderer::EnablePreMultipliedAlpha(bool enable)
504 mPremultipledAlphaEnabled = enable;
508 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
510 mDepthWriteMode = depthWriteMode;
514 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
516 mDepthTestMode = depthTestMode;
520 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
522 return mDepthWriteMode;
525 DepthTestMode::Type Renderer::GetDepthTestMode() const
527 return mDepthTestMode;
530 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
532 mDepthFunction = depthFunction;
536 DepthFunction::Type Renderer::GetDepthFunction() const
538 return mDepthFunction;
541 void Renderer::SetRenderMode(RenderMode::Type renderMode)
543 mStencilParameters.renderMode = renderMode;
547 RenderMode::Type Renderer::GetRenderMode() const
549 return mStencilParameters.renderMode;
552 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
554 mStencilParameters.stencilFunction = stencilFunction;
558 StencilFunction::Type Renderer::GetStencilFunction() const
560 return mStencilParameters.stencilFunction;
563 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
565 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
569 int Renderer::GetStencilFunctionMask() const
571 return mStencilParameters.stencilFunctionMask;
574 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
576 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
580 int Renderer::GetStencilFunctionReference() const
582 return mStencilParameters.stencilFunctionReference;
585 void Renderer::SetStencilMask(int stencilMask)
587 mStencilParameters.stencilMask = stencilMask;
591 int Renderer::GetStencilMask() const
593 return mStencilParameters.stencilMask;
596 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
598 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
602 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
604 return mStencilParameters.stencilOperationOnFail;
607 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
609 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
613 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
615 return mStencilParameters.stencilOperationOnZFail;
618 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
620 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
624 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
626 return mStencilParameters.stencilOperationOnZPass;
629 void Renderer::Upload()
631 mGeometry->Upload(*mGraphicsController);
634 void Renderer::Render(Context& context,
635 BufferIndex bufferIndex,
636 const SceneGraph::NodeDataProvider& node,
637 const Matrix& modelMatrix,
638 const Matrix& modelViewMatrix,
639 const Matrix& viewMatrix,
640 const Matrix& projectionMatrix,
643 Vector<Graphics::Texture*>& boundTextures,
644 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
647 // Before doing anything test if the call happens in the right queue
648 if(mDrawCommands.empty() && queueIndex > 0)
654 std::vector<DevelRenderer::DrawCommand*> commands;
655 for(auto& cmd : mDrawCommands)
657 if(cmd.queue == queueIndex)
659 commands.emplace_back(&cmd);
663 // Have commands but nothing to be drawn - abort
664 if(!mDrawCommands.empty() && commands.empty())
669 // Get the program to use:
670 Program* program = mRenderDataProvider->GetShader().GetProgram();
673 DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
677 Graphics::UniquePtr<Graphics::CommandBuffer> commandBuffer = mGraphicsController->CreateCommandBuffer(
678 Graphics::CommandBufferCreateInfo()
679 .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
683 const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
684 if(cam->GetReflectionUsed())
686 auto adjFaceCullingMode = mFaceCullingMode;
687 switch(mFaceCullingMode)
689 case FaceCullingMode::Type::FRONT:
691 adjFaceCullingMode = FaceCullingMode::Type::BACK;
694 case FaceCullingMode::Type::BACK:
696 adjFaceCullingMode = FaceCullingMode::Type::FRONT;
701 // nothing to do, leave culling as it is
704 context.CullFace(adjFaceCullingMode);
708 context.CullFace(mFaceCullingMode);
711 // Temporarily create a pipeline here - this will be used for transporting
712 // topology and vertex format for now.
713 Graphics::UniquePtr<Graphics::Pipeline> pipeline = PrepareGraphicsPipeline(*program);
714 commandBuffer->BindPipeline(*pipeline.get());
716 // Take the program into use so we can send uniforms to it
719 if(DALI_LIKELY(BindTextures(context, *program, *commandBuffer.get(), boundTextures)))
721 // Only set up and draw if we have textures and they are all valid
723 // set projection and view matrix if program has not yet received them yet this frame
724 SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
727 GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
728 if(Program::UNIFORM_UNKNOWN != loc)
730 const Vector4& color = node.GetRenderColor(bufferIndex);
731 if(mPremultipledAlphaEnabled)
733 float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
734 program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
738 program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
742 SetUniforms(bufferIndex, node, size, *program);
744 if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
746 context.BlendBarrier();
749 //@todo manage mDrawCommands in the same way as above command buffer?!
750 if(mDrawCommands.empty())
752 SetBlending(context, blend);
754 mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), mIndexedDrawFirstElement, mIndexedDrawElementsCount);
758 for(auto& cmd : commands)
760 if(cmd->queue == queueIndex)
763 SetBlending(context, cmd->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
765 // @todo This should generate a command buffer per cmd
767 mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), cmd->firstIndex, cmd->elementCount);
772 // Command buffer contains Texture bindings, vertex bindings, index buffer binding, pipeline(vertex format)
773 Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
774 submitInfo.cmdBuffer.push_back(commandBuffer.get());
775 mGraphicsController->SubmitCommandBuffers(submitInfo);
781 void Renderer::SetSortAttributes(BufferIndex bufferIndex,
782 SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
784 sortAttributes.shader = &(mRenderDataProvider->GetShader());
785 sortAttributes.geometry = mGeometry;
788 void Renderer::SetShaderChanged(bool value)
790 mShaderChanged = value;
793 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
801 if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
806 for(const auto& texture : mRenderDataProvider->GetTextures())
808 if(texture && texture->IsNativeImage())
814 uint64_t hash = 0xc70f6907UL;
815 const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
816 for(const auto& uniformProperty : uniformMapNode)
818 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
821 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
822 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
823 for(const auto& uniformProperty : uniformMap)
825 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
828 if(mUniformsHash != hash)
830 mUniformsHash = hash;
837 Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(Program& program)
839 Graphics::InputAssemblyState inputAssemblyState{};
840 Graphics::VertexInputState vertexInputState{};
841 uint32_t bindingIndex{0u};
843 if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
845 mAttributeLocations.Clear();
846 mUpdateAttributeLocations = true;
850 for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
852 const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
854 vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
855 Graphics::VertexInputRate::PER_VERTEX);
857 const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
858 for(uint32_t i = 0; i < attributeCount; ++i)
860 if(mUpdateAttributeLocations)
862 auto attributeName = vertexBuffer->GetAttributeName(i);
863 uint32_t index = program.RegisterCustomAttribute(attributeName);
864 int32_t pLocation = program.GetCustomAttributeLocation(index);
867 DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
869 mAttributeLocations.PushBack(pLocation);
872 uint32_t location = static_cast<uint32_t>(mAttributeLocations[base + i]);
874 vertexInputState.attributes.emplace_back(location,
876 vertexFormat.components[i].offset,
877 GetPropertyVertexFormat(vertexFormat.components[i].type));
879 base += attributeCount;
882 mUpdateAttributeLocations = false;
885 inputAssemblyState.SetTopology(mGeometry->GetTopology());
887 // Create a new pipeline
888 return mGraphicsController->CreatePipeline(
889 Graphics::PipelineCreateInfo()
890 .SetInputAssemblyState(&inputAssemblyState) // Passed as pointers - shallow copy will break. TOO C LIKE
891 .SetVertexInputState(&vertexInputState),
895 } // namespace Render
897 } // namespace Internal