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/graphics-api/graphics-program.h>
23 #include <dali/graphics-api/graphics-types.h>
24 #include <dali/internal/common/image-sampler.h>
25 #include <dali/internal/render/common/render-instruction.h>
26 #include <dali/internal/render/data-providers/node-data-provider.h>
27 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
28 #include <dali/internal/render/gl-resources/context.h>
29 #include <dali/internal/render/renderers/render-sampler.h>
30 #include <dali/internal/render/renderers/render-texture.h>
31 #include <dali/internal/render/renderers/render-vertex-buffer.h>
32 #include <dali/internal/render/renderers/shader-cache.h>
33 #include <dali/internal/render/shaders/program.h>
34 #include <dali/internal/render/shaders/scene-graph-shader.h>
43 * Helper to set view and projection matrices once per program
44 * @param program to set the matrices to
45 * @param modelMatrix to set
46 * @param viewMatrix to set
47 * @param projectionMatrix to set
48 * @param modelViewMatrix to set
49 * @param modelViewProjectionMatrix to set
51 inline void SetMatrices(Program& program,
52 const Matrix& modelMatrix,
53 const Matrix& viewMatrix,
54 const Matrix& projectionMatrix,
55 const Matrix& modelViewMatrix)
57 GLint loc = program.GetUniformLocation(Program::UNIFORM_MODEL_MATRIX);
58 if(Program::UNIFORM_UNKNOWN != loc)
60 program.SetUniformMatrix4fv(loc, 1, modelMatrix.AsFloat());
62 loc = program.GetUniformLocation(Program::UNIFORM_VIEW_MATRIX);
63 if(Program::UNIFORM_UNKNOWN != loc)
65 if(program.GetViewMatrix() != &viewMatrix)
67 program.SetViewMatrix(&viewMatrix);
68 program.SetUniformMatrix4fv(loc, 1, viewMatrix.AsFloat());
71 // set projection matrix if program has not yet received it this frame or if it is dirty
72 loc = program.GetUniformLocation(Program::UNIFORM_PROJECTION_MATRIX);
73 if(Program::UNIFORM_UNKNOWN != loc)
75 if(program.GetProjectionMatrix() != &projectionMatrix)
77 program.SetProjectionMatrix(&projectionMatrix);
78 program.SetUniformMatrix4fv(loc, 1, projectionMatrix.AsFloat());
81 loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
82 if(Program::UNIFORM_UNKNOWN != loc)
84 program.SetUniformMatrix4fv(loc, 1, modelViewMatrix.AsFloat());
87 loc = program.GetUniformLocation(Program::UNIFORM_MVP_MATRIX);
88 if(Program::UNIFORM_UNKNOWN != loc)
90 Matrix modelViewProjectionMatrix(false);
91 Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
92 program.SetUniformMatrix4fv(loc, 1, modelViewProjectionMatrix.AsFloat());
95 loc = program.GetUniformLocation(Program::UNIFORM_NORMAL_MATRIX);
96 if(Program::UNIFORM_UNKNOWN != loc)
99 normalMatrix = modelViewMatrix;
100 normalMatrix.Invert();
101 normalMatrix.Transpose();
102 program.SetUniformMatrix3fv(loc, 1, normalMatrix.AsFloat());
106 // Helper to get the vertex input format
107 Dali::Graphics::VertexInputFormat GetPropertyVertexFormat(Property::Type propertyType)
109 Dali::Graphics::VertexInputFormat type{};
114 case Property::STRING:
115 case Property::ARRAY:
117 case Property::EXTENTS: // i4?
118 case Property::RECTANGLE: // i4/f4?
119 case Property::ROTATION:
121 type = Dali::Graphics::VertexInputFormat::UNDEFINED;
124 case Property::BOOLEAN:
126 type = Dali::Graphics::VertexInputFormat::UNDEFINED; // type = GL_BYTE; @todo new type for this?
129 case Property::INTEGER:
131 type = Dali::Graphics::VertexInputFormat::INTEGER; // (short)
134 case Property::FLOAT:
136 type = Dali::Graphics::VertexInputFormat::FLOAT;
139 case Property::VECTOR2:
141 type = Dali::Graphics::VertexInputFormat::FVECTOR2;
144 case Property::VECTOR3:
146 type = Dali::Graphics::VertexInputFormat::FVECTOR3;
149 case Property::VECTOR4:
151 type = Dali::Graphics::VertexInputFormat::FVECTOR4;
154 case Property::MATRIX3:
156 type = Dali::Graphics::VertexInputFormat::FLOAT;
159 case Property::MATRIX:
161 type = Dali::Graphics::VertexInputFormat::FLOAT;
169 constexpr Graphics::CullMode ConvertCullFace(Dali::FaceCullingMode::Type mode)
173 case Dali::FaceCullingMode::NONE:
175 return Graphics::CullMode::NONE;
177 case Dali::FaceCullingMode::FRONT:
179 return Graphics::CullMode::FRONT;
181 case Dali::FaceCullingMode::BACK:
183 return Graphics::CullMode::BACK;
185 case Dali::FaceCullingMode::FRONT_AND_BACK:
187 return Graphics::CullMode::FRONT_AND_BACK;
190 return Graphics::CullMode::NONE;
193 constexpr Graphics::BlendFactor ConvertBlendFactor(BlendFactor::Type blendFactor)
197 case BlendFactor::ZERO:
198 return Graphics::BlendFactor::ZERO;
199 case BlendFactor::ONE:
200 return Graphics::BlendFactor::ONE;
201 case BlendFactor::SRC_COLOR:
202 return Graphics::BlendFactor::SRC_COLOR;
203 case BlendFactor::ONE_MINUS_SRC_COLOR:
204 return Graphics::BlendFactor::ONE_MINUS_SRC_COLOR;
205 case BlendFactor::SRC_ALPHA:
206 return Graphics::BlendFactor::SRC_ALPHA;
207 case BlendFactor::ONE_MINUS_SRC_ALPHA:
208 return Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA;
209 case BlendFactor::DST_ALPHA:
210 return Graphics::BlendFactor::DST_ALPHA;
211 case BlendFactor::ONE_MINUS_DST_ALPHA:
212 return Graphics::BlendFactor::ONE_MINUS_DST_ALPHA;
213 case BlendFactor::DST_COLOR:
214 return Graphics::BlendFactor::DST_COLOR;
215 case BlendFactor::ONE_MINUS_DST_COLOR:
216 return Graphics::BlendFactor::ONE_MINUS_DST_COLOR;
217 case BlendFactor::SRC_ALPHA_SATURATE:
218 return Graphics::BlendFactor::SRC_ALPHA_SATURATE;
219 case BlendFactor::CONSTANT_COLOR:
220 return Graphics::BlendFactor::CONSTANT_COLOR;
221 case BlendFactor::ONE_MINUS_CONSTANT_COLOR:
222 return Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR;
223 case BlendFactor::CONSTANT_ALPHA:
224 return Graphics::BlendFactor::CONSTANT_ALPHA;
225 case BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
226 return Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA;
228 return Graphics::BlendFactor{};
231 constexpr Graphics::BlendOp ConvertBlendEquation(DevelBlendEquation::Type blendEquation)
233 switch(blendEquation)
235 case DevelBlendEquation::ADD:
236 return Graphics::BlendOp::ADD;
237 case DevelBlendEquation::SUBTRACT:
238 return Graphics::BlendOp::SUBTRACT;
239 case DevelBlendEquation::REVERSE_SUBTRACT:
240 return Graphics::BlendOp::REVERSE_SUBTRACT;
241 case DevelBlendEquation::COLOR:
242 case DevelBlendEquation::COLOR_BURN:
243 case DevelBlendEquation::COLOR_DODGE:
244 case DevelBlendEquation::DARKEN:
245 case DevelBlendEquation::DIFFERENCE:
246 case DevelBlendEquation::EXCLUSION:
247 case DevelBlendEquation::HARD_LIGHT:
248 case DevelBlendEquation::HUE:
249 case DevelBlendEquation::LIGHTEN:
250 case DevelBlendEquation::LUMINOSITY:
251 case DevelBlendEquation::MAX:
252 case DevelBlendEquation::MIN:
253 case DevelBlendEquation::MULTIPLY:
254 case DevelBlendEquation::OVERLAY:
255 case DevelBlendEquation::SATURATION:
256 case DevelBlendEquation::SCREEN:
257 case DevelBlendEquation::SOFT_LIGHT:
258 return Graphics::BlendOp{};
260 return Graphics::BlendOp{};
267 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
268 Render::Geometry* geometry,
269 uint32_t blendingBitmask,
270 const Vector4& blendColor,
271 FaceCullingMode::Type faceCullingMode,
272 bool preMultipliedAlphaEnabled,
273 DepthWriteMode::Type depthWriteMode,
274 DepthTestMode::Type depthTestMode,
275 DepthFunction::Type depthFunction,
276 StencilParameters& stencilParameters)
278 return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
281 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
282 Render::Geometry* geometry,
283 uint32_t blendingBitmask,
284 const Vector4& blendColor,
285 FaceCullingMode::Type faceCullingMode,
286 bool preMultipliedAlphaEnabled,
287 DepthWriteMode::Type depthWriteMode,
288 DepthTestMode::Type depthTestMode,
289 DepthFunction::Type depthFunction,
290 StencilParameters& stencilParameters)
291 : mRenderDataProvider(dataProvider),
294 mProgramCache(nullptr),
296 mAttributeLocations(),
298 mStencilParameters(stencilParameters),
300 mIndexedDrawFirstElement(0),
301 mIndexedDrawElementsCount(0),
302 mDepthFunction(depthFunction),
303 mFaceCullingMode(faceCullingMode),
304 mDepthWriteMode(depthWriteMode),
305 mDepthTestMode(depthTestMode),
306 mUpdateAttributeLocations(true),
307 mPremultipledAlphaEnabled(preMultipliedAlphaEnabled),
308 mShaderChanged(false),
311 if(blendingBitmask != 0u)
313 mBlendingOptions.SetBitmask(blendingBitmask);
316 mBlendingOptions.SetBlendColor(blendColor);
319 void Renderer::Initialize(Context& context, Graphics::Controller& graphicsController, ProgramCache& programCache, Render::ShaderCache& shaderCache)
322 mGraphicsController = &graphicsController;
323 mProgramCache = &programCache;
324 mShaderCache = &shaderCache;
327 Renderer::~Renderer() = default;
329 void Renderer::SetGeometry(Render::Geometry* geometry)
331 mGeometry = geometry;
332 mUpdateAttributeLocations = true;
334 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
336 mDrawCommands.clear();
337 mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
340 void Renderer::GlContextDestroyed()
342 mGeometry->GlContextDestroyed();
345 void Renderer::GlCleanup()
349 void Renderer::SetUniforms(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
351 // Check if the map has changed
352 DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
354 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
356 if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
357 node.GetUniformMapChanged(bufferIndex) ||
358 mUniformIndexMap.Count() == 0 ||
361 // Reset shader pointer
362 mShaderChanged = false;
364 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
365 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
367 uint32_t maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
368 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
369 mUniformIndexMap.Resize(maxMaps);
371 uint32_t mapIndex = 0;
372 for(; mapIndex < uniformMap.Count(); ++mapIndex)
374 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex].propertyPtr;
375 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform(uniformMap[mapIndex].uniformName);
378 for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
380 uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName);
382 for(uint32_t i = 0; i < uniformMap.Count(); ++i)
384 if(mUniformIndexMap[i].uniformIndex == uniformIndex)
386 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
394 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
395 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
400 mUniformIndexMap.Resize(mapIndex);
403 // Set uniforms in local map
404 for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
405 end = mUniformIndexMap.End();
409 SetUniformFromProperty(bufferIndex, program, *iter);
412 GLint sizeLoc = program.GetUniformLocation(Program::UNIFORM_SIZE);
415 program.SetSizeUniform3f(sizeLoc, size.x, size.y, size.z);
419 void Renderer::SetUniformFromProperty(BufferIndex bufferIndex, Program& program, UniformIndexMap& map)
421 GLint location = program.GetUniformLocation(map.uniformIndex);
422 if(Program::UNIFORM_UNKNOWN != location)
424 // switch based on property type to use correct GL uniform setter
425 switch(map.propertyValue->GetType())
427 case Property::INTEGER:
429 program.SetUniform1i(location, map.propertyValue->GetInteger(bufferIndex));
432 case Property::FLOAT:
434 program.SetUniform1f(location, map.propertyValue->GetFloat(bufferIndex));
437 case Property::VECTOR2:
439 Vector2 value(map.propertyValue->GetVector2(bufferIndex));
440 program.SetUniform2f(location, value.x, value.y);
444 case Property::VECTOR3:
446 Vector3 value(map.propertyValue->GetVector3(bufferIndex));
447 program.SetUniform3f(location, value.x, value.y, value.z);
451 case Property::VECTOR4:
453 Vector4 value(map.propertyValue->GetVector4(bufferIndex));
454 program.SetUniform4f(location, value.x, value.y, value.z, value.w);
458 case Property::ROTATION:
460 Quaternion value(map.propertyValue->GetQuaternion(bufferIndex));
461 program.SetUniform4f(location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w);
465 case Property::MATRIX:
467 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
468 program.SetUniformMatrix4fv(location, 1, value.AsFloat());
472 case Property::MATRIX3:
474 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
475 program.SetUniformMatrix3fv(location, 1, value.AsFloat());
481 // Other property types are ignored
488 bool Renderer::BindTextures(Program& program, Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
490 uint32_t textureUnit = 0;
493 GLint uniformLocation(-1);
494 std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
495 std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
497 std::vector<Graphics::TextureBinding> textureBindings;
498 for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()) && result; ++i) // not expecting more than uint32_t of textures
502 if(program.GetSamplerUniformLocation(i, uniformLocation))
504 // if the sampler exists,
505 // if it's default, delete the graphics object
506 // otherwise re-initialize it if dirty
508 const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject()
511 boundTextures.PushBack(textures[i]->GetGraphicsObject());
512 const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
513 textureBindings.push_back(textureBinding);
515 program.SetUniform1i(uniformLocation, textureUnit); // Get through shader reflection
521 if(textureBindings.size() > 0)
523 commandBuffer.BindTextures(textureBindings);
529 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
531 mFaceCullingMode = mode;
535 void Renderer::SetBlendingBitMask(uint32_t bitmask)
537 mBlendingOptions.SetBitmask(bitmask);
541 void Renderer::SetBlendColor(const Vector4& color)
543 mBlendingOptions.SetBlendColor(color);
547 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
549 mIndexedDrawFirstElement = firstElement;
553 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
555 mIndexedDrawElementsCount = elementsCount;
559 void Renderer::EnablePreMultipliedAlpha(bool enable)
561 mPremultipledAlphaEnabled = enable;
565 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
567 mDepthWriteMode = depthWriteMode;
571 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
573 mDepthTestMode = depthTestMode;
577 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
579 return mDepthWriteMode;
582 DepthTestMode::Type Renderer::GetDepthTestMode() const
584 return mDepthTestMode;
587 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
589 mDepthFunction = depthFunction;
593 DepthFunction::Type Renderer::GetDepthFunction() const
595 return mDepthFunction;
598 void Renderer::SetRenderMode(RenderMode::Type renderMode)
600 mStencilParameters.renderMode = renderMode;
604 RenderMode::Type Renderer::GetRenderMode() const
606 return mStencilParameters.renderMode;
609 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
611 mStencilParameters.stencilFunction = stencilFunction;
615 StencilFunction::Type Renderer::GetStencilFunction() const
617 return mStencilParameters.stencilFunction;
620 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
622 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
626 int Renderer::GetStencilFunctionMask() const
628 return mStencilParameters.stencilFunctionMask;
631 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
633 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
637 int Renderer::GetStencilFunctionReference() const
639 return mStencilParameters.stencilFunctionReference;
642 void Renderer::SetStencilMask(int stencilMask)
644 mStencilParameters.stencilMask = stencilMask;
648 int Renderer::GetStencilMask() const
650 return mStencilParameters.stencilMask;
653 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
655 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
659 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
661 return mStencilParameters.stencilOperationOnFail;
664 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
666 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
670 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
672 return mStencilParameters.stencilOperationOnZFail;
675 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
677 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
681 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
683 return mStencilParameters.stencilOperationOnZPass;
686 void Renderer::Upload()
688 mGeometry->Upload(*mGraphicsController);
691 void Renderer::Render(Context& context,
692 BufferIndex bufferIndex,
693 const SceneGraph::NodeDataProvider& node,
694 const Matrix& modelMatrix,
695 const Matrix& modelViewMatrix,
696 const Matrix& viewMatrix,
697 const Matrix& projectionMatrix,
700 Vector<Graphics::Texture*>& boundTextures,
701 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
704 // Before doing anything test if the call happens in the right queue
705 if(mDrawCommands.empty() && queueIndex > 0)
711 std::vector<DevelRenderer::DrawCommand*> commands;
712 for(auto& cmd : mDrawCommands)
714 if(cmd.queue == queueIndex)
716 commands.emplace_back(&cmd);
720 // Have commands but nothing to be drawn - abort
721 if(!mDrawCommands.empty() && commands.empty())
726 Graphics::UniquePtr<Graphics::CommandBuffer> commandBuffer = mGraphicsController->CreateCommandBuffer(
727 Graphics::CommandBufferCreateInfo()
728 .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
732 if(!mDrawCommands.empty())
734 blend = (commands[0]->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
738 // Really, need to have a pipeline cache in implementation.
739 // Get the program to use
740 // The program cache owns the Program object so we don't need to worry about this raw allocation here.
741 ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
743 Dali::Graphics::Shader& vertexShader = mShaderCache->GetShader(
744 shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
745 Graphics::PipelineStage::VERTEX_SHADER,
746 shaderData->GetSourceMode());
748 Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
749 shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER),
750 Graphics::PipelineStage::FRAGMENT_SHADER,
751 shaderData->GetSourceMode());
753 std::vector<Graphics::ShaderState> shaderStates{
754 Graphics::ShaderState()
755 .SetShader(vertexShader)
756 .SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
757 Graphics::ShaderState()
758 .SetShader(fragmentShader)
759 .SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER)};
761 auto createInfo = Graphics::ProgramCreateInfo();
762 createInfo.SetShaderState(shaderStates);
764 auto graphicsProgram = mGraphicsController->CreateProgram(createInfo, nullptr);
765 Program* program = Program::New(*mProgramCache,
767 *mGraphicsController,
768 std::move(graphicsProgram),
769 (shaderData->GetHints() & Dali::Shader::Hint::MODIFIES_GEOMETRY) != 0x0);
773 DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
777 // Temporarily create a pipeline here - this will be used for transporting
778 // topology, vertex format, attrs, rasterization state
779 mGraphicsPipeline = PrepareGraphicsPipeline(*program, instruction, blend, std::move(mGraphicsPipeline));
781 commandBuffer->BindPipeline(*mGraphicsPipeline.get());
783 if(DALI_LIKELY(BindTextures(*program, *commandBuffer.get(), boundTextures)))
785 // Only set up and draw if we have textures and they are all valid
787 // set projection and view matrix if program has not yet received them yet this frame
788 SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
791 GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
792 if(Program::UNIFORM_UNKNOWN != loc)
794 const Vector4& color = node.GetRenderColor(bufferIndex);
795 if(mPremultipledAlphaEnabled)
797 float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
798 program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
802 program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
806 SetUniforms(bufferIndex, node, size, *program);
808 bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
809 // @todo We should detect this case much earlier to prevent unnecessary work
811 //@todo manage mDrawCommands in the same way as above command buffer?!
812 if(mDrawCommands.empty())
814 drawn = mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), mIndexedDrawFirstElement, mIndexedDrawElementsCount);
818 for(auto& cmd : commands)
820 // @todo This should generate a command buffer per cmd
821 // Tests WILL fail. (Temporarily commented out)
822 mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), cmd->firstIndex, cmd->elementCount);
826 // Command buffer contains Texture bindings, vertex bindings, index buffer binding, pipeline(vertex format)
827 // @todo We should return the command buffer(s) and let the calling method submit
828 // If not drawn, then don't add command buffer to submit info, and if empty, don't
832 Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
833 submitInfo.cmdBuffer.push_back(commandBuffer.get());
834 mGraphicsController->SubmitCommandBuffers(submitInfo);
841 void Renderer::SetSortAttributes(BufferIndex bufferIndex,
842 SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
844 sortAttributes.shader = &(mRenderDataProvider->GetShader());
845 sortAttributes.geometry = mGeometry;
848 void Renderer::SetShaderChanged(bool value)
850 mShaderChanged = value;
853 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
861 if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
866 for(const auto& texture : mRenderDataProvider->GetTextures())
868 if(texture && texture->IsNativeImage())
874 uint64_t hash = 0xc70f6907UL;
875 const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
876 for(const auto& uniformProperty : uniformMapNode)
878 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
881 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
882 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
883 for(const auto& uniformProperty : uniformMap)
885 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
888 if(mUniformsHash != hash)
890 mUniformsHash = hash;
897 Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
899 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
901 Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
903 Graphics::InputAssemblyState inputAssemblyState{};
904 Graphics::VertexInputState vertexInputState{};
905 Graphics::ProgramState programState{};
906 uint32_t bindingIndex{0u};
908 if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
910 mAttributeLocations.Clear();
911 mUpdateAttributeLocations = true;
914 auto& reflection = mGraphicsController->GetProgramReflection(program.GetGraphicsProgram());
920 for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
922 const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
924 vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
925 Graphics::VertexInputRate::PER_VERTEX);
927 const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
928 for(uint32_t i = 0; i < attributeCount; ++i)
930 if(mUpdateAttributeLocations)
932 auto attributeName = vertexBuffer->GetAttributeName(i);
933 int32_t pLocation = reflection.GetVertexAttributeLocation(std::string(attributeName.GetStringView()));
936 DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
938 mAttributeLocations.PushBack(pLocation);
941 uint32_t location = static_cast<uint32_t>(mAttributeLocations[base + i]);
943 vertexInputState.attributes.emplace_back(location,
945 vertexFormat.components[i].offset,
946 GetPropertyVertexFormat(vertexFormat.components[i].type));
948 base += attributeCount;
951 mUpdateAttributeLocations = false;
954 inputAssemblyState.SetTopology(mGeometry->GetTopology());
957 programState.SetProgram(program.GetGraphicsProgram());
959 Graphics::RasterizationState rasterizationState{};
962 const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
963 if(cam->GetReflectionUsed())
965 auto adjFaceCullingMode = mFaceCullingMode;
966 switch(mFaceCullingMode)
968 case FaceCullingMode::Type::FRONT:
970 adjFaceCullingMode = FaceCullingMode::Type::BACK;
973 case FaceCullingMode::Type::BACK:
975 adjFaceCullingMode = FaceCullingMode::Type::FRONT;
980 // nothing to do, leave culling as it is
983 rasterizationState.SetCullMode(ConvertCullFace(adjFaceCullingMode));
987 rasterizationState.SetCullMode(ConvertCullFace(mFaceCullingMode));
990 rasterizationState.SetFrontFace(Graphics::FrontFace::COUNTER_CLOCKWISE);
995 switch(mGeometry->GetTopology())
997 case Graphics::PrimitiveTopology::TRIANGLE_LIST:
998 case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
999 case Graphics::PrimitiveTopology::TRIANGLE_FAN:
1000 rasterizationState.SetPolygonMode(Graphics::PolygonMode::FILL);
1002 case Graphics::PrimitiveTopology::LINE_LIST:
1003 case Graphics::PrimitiveTopology::LINE_LOOP:
1004 case Graphics::PrimitiveTopology::LINE_STRIP:
1005 rasterizationState.SetPolygonMode(Graphics::PolygonMode::LINE);
1007 case Graphics::PrimitiveTopology::POINT_LIST:
1008 rasterizationState.SetPolygonMode(Graphics::PolygonMode::POINT);
1012 // @todo How to signal a blend barrier is needed?
1013 //if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1015 // context.BlendBarrier();
1018 Graphics::ColorBlendState colorBlendState{};
1019 colorBlendState.SetBlendEnable(false);
1023 colorBlendState.SetBlendEnable(true);
1025 Graphics::BlendOp rgbOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1026 Graphics::BlendOp alphaOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1027 if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1029 if(rgbOp != alphaOp)
1031 DALI_LOG_ERROR("Advanced Blend Equation MUST be applied by using BlendEquation.\n");
1037 .SetSrcColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorRgb()))
1038 .SetSrcAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorAlpha()))
1039 .SetDstColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorRgb()))
1040 .SetDstAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorAlpha()))
1041 .SetColorBlendOp(rgbOp)
1042 .SetAlphaBlendOp(alphaOp);
1044 // Blend color is optional and rarely used
1045 Vector4* blendColor = const_cast<Vector4*>(mBlendingOptions.GetBlendColor());
1048 colorBlendState.SetBlendConstants(blendColor->AsFloat());
1052 // Take the program into use so we can send uniforms to it
1053 // @todo Remove this call entirely!
1058 // Create a new pipeline
1059 return mGraphicsController->CreatePipeline(
1060 Graphics::PipelineCreateInfo()
1061 .SetInputAssemblyState(&inputAssemblyState) // Passed as pointers - shallow copy will break. TOO C LIKE
1062 .SetVertexInputState(&vertexInputState)
1063 .SetRasterizationState(&rasterizationState)
1064 .SetColorBlendState(&colorBlendState)
1065 .SetProgramState(&programState)
1066 .SetNextExtension(&mLegacyProgram),
1067 std::move(oldPipeline));
1070 } // namespace Render
1072 } // namespace Internal