+ // Create Program
+ ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
+
+ Program* program = Program::New(*mProgramCache,
+ shaderData,
+ *mGraphicsController);
+ if(!program)
+ {
+ DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
+ return false;
+ }
+
+ // If program doesn't have Gfx program object assigned yet, prepare it.
+ if(!program->GetGraphicsProgramPtr())
+ {
+ const std::vector<char> &vertShader = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER);
+ const std::vector<char> &fragShader = shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER);
+ Dali::Graphics::Shader &vertexShader = mShaderCache->GetShader(
+ vertShader,
+ Graphics::PipelineStage::VERTEX_SHADER,
+ shaderData->GetSourceMode());
+
+ Dali::Graphics::Shader &fragmentShader = mShaderCache->GetShader(
+ fragShader,
+ Graphics::PipelineStage::FRAGMENT_SHADER,
+ shaderData->GetSourceMode());
+
+ std::vector<Graphics::ShaderState> shaderStates{
+ Graphics::ShaderState()
+ .SetShader(vertexShader)
+ .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
+ Graphics::ShaderState()
+ .SetShader(fragmentShader)
+ .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
+
+ auto createInfo = Graphics::ProgramCreateInfo();
+ createInfo.SetShaderState(shaderStates);
+ auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
+ program->SetGraphicsProgram(std::move(graphicsProgram));
+ }
+
+ // Prepare the graphics pipeline. This may either re-use an existing pipeline or create a new one.
+ auto& pipeline = PrepareGraphicsPipeline(*program, instruction, node, blend);
+
+ commandBuffer.BindPipeline(pipeline);
+
+ BindTextures(commandBuffer, boundTextures);
+
+ BuildUniformIndexMap(bufferIndex, node, size, *program);
+
+ WriteUniformBuffer(bufferIndex, commandBuffer, program, instruction, node, modelMatrix, modelViewMatrix, viewMatrix, projectionMatrix, size);
+
+ bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
+ // @todo We should detect this case much earlier to prevent unnecessary work
+
+ if(mDrawCommands.empty())
+ {
+ drawn = mGeometry->Draw(*mGraphicsController, commandBuffer, mIndexedDrawFirstElement, mIndexedDrawElementsCount);
+ }
+ else
+ {
+ for(auto& cmd : commands)
+ {
+ mGeometry->Draw(*mGraphicsController, commandBuffer, cmd->firstIndex, cmd->elementCount);
+ }
+ }
+
+ mUpdated = false;
+ return drawn;
+}
+
+void Renderer::BuildUniformIndexMap(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
+{
+ // Check if the map has changed
+ DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
+
+ const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
+
+ if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
+ node.GetUniformMapChanged(bufferIndex) ||
+ mUniformIndexMap.Count() == 0 ||
+ mShaderChanged)