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-types.h>
23 #include <dali/internal/common/image-sampler.h>
24 #include <dali/internal/render/common/render-instruction.h>
25 #include <dali/internal/render/data-providers/node-data-provider.h>
26 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
27 #include <dali/internal/render/gl-resources/context.h>
28 #include <dali/internal/render/renderers/render-sampler.h>
29 #include <dali/internal/render/renderers/render-texture.h>
30 #include <dali/internal/render/renderers/render-vertex-buffer.h>
31 #include <dali/internal/render/renderers/shader-cache.h>
32 #include <dali/internal/render/shaders/program.h>
33 #include <dali/internal/render/shaders/scene-graph-shader.h>
42 * Helper to set view and projection matrices once per program
43 * @param program to set the matrices to
44 * @param modelMatrix to set
45 * @param viewMatrix to set
46 * @param projectionMatrix to set
47 * @param modelViewMatrix to set
48 * @param modelViewProjectionMatrix to set
50 inline void SetMatrices(Program& program,
51 const Matrix& modelMatrix,
52 const Matrix& viewMatrix,
53 const Matrix& projectionMatrix,
54 const Matrix& modelViewMatrix)
56 GLint loc = program.GetUniformLocation(Program::UNIFORM_MODEL_MATRIX);
57 if(Program::UNIFORM_UNKNOWN != loc)
59 program.SetUniformMatrix4fv(loc, 1, modelMatrix.AsFloat());
61 loc = program.GetUniformLocation(Program::UNIFORM_VIEW_MATRIX);
62 if(Program::UNIFORM_UNKNOWN != loc)
64 if(program.GetViewMatrix() != &viewMatrix)
66 program.SetViewMatrix(&viewMatrix);
67 program.SetUniformMatrix4fv(loc, 1, viewMatrix.AsFloat());
70 // set projection matrix if program has not yet received it this frame or if it is dirty
71 loc = program.GetUniformLocation(Program::UNIFORM_PROJECTION_MATRIX);
72 if(Program::UNIFORM_UNKNOWN != loc)
74 if(program.GetProjectionMatrix() != &projectionMatrix)
76 program.SetProjectionMatrix(&projectionMatrix);
77 program.SetUniformMatrix4fv(loc, 1, projectionMatrix.AsFloat());
80 loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
81 if(Program::UNIFORM_UNKNOWN != loc)
83 program.SetUniformMatrix4fv(loc, 1, modelViewMatrix.AsFloat());
86 loc = program.GetUniformLocation(Program::UNIFORM_MVP_MATRIX);
87 if(Program::UNIFORM_UNKNOWN != loc)
89 Matrix modelViewProjectionMatrix(false);
90 Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
91 program.SetUniformMatrix4fv(loc, 1, modelViewProjectionMatrix.AsFloat());
94 loc = program.GetUniformLocation(Program::UNIFORM_NORMAL_MATRIX);
95 if(Program::UNIFORM_UNKNOWN != loc)
98 normalMatrix = modelViewMatrix;
99 normalMatrix.Invert();
100 normalMatrix.Transpose();
101 program.SetUniformMatrix3fv(loc, 1, normalMatrix.AsFloat());
105 // Helper to get the vertex input format
106 Dali::Graphics::VertexInputFormat GetPropertyVertexFormat(Property::Type propertyType)
108 Dali::Graphics::VertexInputFormat type{};
113 case Property::STRING:
114 case Property::ARRAY:
116 case Property::EXTENTS: // i4?
117 case Property::RECTANGLE: // i4/f4?
118 case Property::ROTATION:
120 type = Dali::Graphics::VertexInputFormat::UNDEFINED;
123 case Property::BOOLEAN:
125 type = Dali::Graphics::VertexInputFormat::UNDEFINED; // type = GL_BYTE; @todo new type for this?
128 case Property::INTEGER:
130 type = Dali::Graphics::VertexInputFormat::INTEGER; // (short)
133 case Property::FLOAT:
135 type = Dali::Graphics::VertexInputFormat::FLOAT;
138 case Property::VECTOR2:
140 type = Dali::Graphics::VertexInputFormat::FVECTOR2;
143 case Property::VECTOR3:
145 type = Dali::Graphics::VertexInputFormat::FVECTOR3;
148 case Property::VECTOR4:
150 type = Dali::Graphics::VertexInputFormat::FVECTOR4;
153 case Property::MATRIX3:
155 type = Dali::Graphics::VertexInputFormat::FLOAT;
158 case Property::MATRIX:
160 type = Dali::Graphics::VertexInputFormat::FLOAT;
168 constexpr Graphics::CullMode ConvertCullFace(Dali::FaceCullingMode::Type mode)
172 case Dali::FaceCullingMode::NONE:
174 return Graphics::CullMode::NONE;
176 case Dali::FaceCullingMode::FRONT:
178 return Graphics::CullMode::FRONT;
180 case Dali::FaceCullingMode::BACK:
182 return Graphics::CullMode::BACK;
184 case Dali::FaceCullingMode::FRONT_AND_BACK:
186 return Graphics::CullMode::FRONT_AND_BACK;
189 return Graphics::CullMode::NONE;
192 constexpr Graphics::BlendFactor ConvertBlendFactor(BlendFactor::Type blendFactor)
196 case BlendFactor::ZERO:
197 return Graphics::BlendFactor::ZERO;
198 case BlendFactor::ONE:
199 return Graphics::BlendFactor::ONE;
200 case BlendFactor::SRC_COLOR:
201 return Graphics::BlendFactor::SRC_COLOR;
202 case BlendFactor::ONE_MINUS_SRC_COLOR:
203 return Graphics::BlendFactor::ONE_MINUS_SRC_COLOR;
204 case BlendFactor::SRC_ALPHA:
205 return Graphics::BlendFactor::SRC_ALPHA;
206 case BlendFactor::ONE_MINUS_SRC_ALPHA:
207 return Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA;
208 case BlendFactor::DST_ALPHA:
209 return Graphics::BlendFactor::DST_ALPHA;
210 case BlendFactor::ONE_MINUS_DST_ALPHA:
211 return Graphics::BlendFactor::ONE_MINUS_DST_ALPHA;
212 case BlendFactor::DST_COLOR:
213 return Graphics::BlendFactor::DST_COLOR;
214 case BlendFactor::ONE_MINUS_DST_COLOR:
215 return Graphics::BlendFactor::ONE_MINUS_DST_COLOR;
216 case BlendFactor::SRC_ALPHA_SATURATE:
217 return Graphics::BlendFactor::SRC_ALPHA_SATURATE;
218 case BlendFactor::CONSTANT_COLOR:
219 return Graphics::BlendFactor::CONSTANT_COLOR;
220 case BlendFactor::ONE_MINUS_CONSTANT_COLOR:
221 return Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR;
222 case BlendFactor::CONSTANT_ALPHA:
223 return Graphics::BlendFactor::CONSTANT_ALPHA;
224 case BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
225 return Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA;
227 return Graphics::BlendFactor{};
230 constexpr Graphics::BlendOp ConvertBlendEquation(DevelBlendEquation::Type blendEquation)
232 switch(blendEquation)
234 case DevelBlendEquation::ADD:
235 return Graphics::BlendOp::ADD;
236 case DevelBlendEquation::SUBTRACT:
237 return Graphics::BlendOp::SUBTRACT;
238 case DevelBlendEquation::REVERSE_SUBTRACT:
239 return Graphics::BlendOp::REVERSE_SUBTRACT;
240 case DevelBlendEquation::COLOR:
241 case DevelBlendEquation::COLOR_BURN:
242 case DevelBlendEquation::COLOR_DODGE:
243 case DevelBlendEquation::DARKEN:
244 case DevelBlendEquation::DIFFERENCE:
245 case DevelBlendEquation::EXCLUSION:
246 case DevelBlendEquation::HARD_LIGHT:
247 case DevelBlendEquation::HUE:
248 case DevelBlendEquation::LIGHTEN:
249 case DevelBlendEquation::LUMINOSITY:
250 case DevelBlendEquation::MAX:
251 case DevelBlendEquation::MIN:
252 case DevelBlendEquation::MULTIPLY:
253 case DevelBlendEquation::OVERLAY:
254 case DevelBlendEquation::SATURATION:
255 case DevelBlendEquation::SCREEN:
256 case DevelBlendEquation::SOFT_LIGHT:
257 return Graphics::BlendOp{};
259 return Graphics::BlendOp{};
266 Renderer* Renderer::New(SceneGraph::RenderDataProvider* dataProvider,
267 Render::Geometry* geometry,
268 uint32_t blendingBitmask,
269 const Vector4& blendColor,
270 FaceCullingMode::Type faceCullingMode,
271 bool preMultipliedAlphaEnabled,
272 DepthWriteMode::Type depthWriteMode,
273 DepthTestMode::Type depthTestMode,
274 DepthFunction::Type depthFunction,
275 StencilParameters& stencilParameters)
277 return new Renderer(dataProvider, geometry, blendingBitmask, blendColor, faceCullingMode, preMultipliedAlphaEnabled, depthWriteMode, depthTestMode, depthFunction, stencilParameters);
280 Renderer::Renderer(SceneGraph::RenderDataProvider* dataProvider,
281 Render::Geometry* geometry,
282 uint32_t blendingBitmask,
283 const Vector4& blendColor,
284 FaceCullingMode::Type faceCullingMode,
285 bool preMultipliedAlphaEnabled,
286 DepthWriteMode::Type depthWriteMode,
287 DepthTestMode::Type depthTestMode,
288 DepthFunction::Type depthFunction,
289 StencilParameters& stencilParameters)
290 : mRenderDataProvider(dataProvider),
293 mProgramCache(nullptr),
295 mAttributeLocations(),
297 mStencilParameters(stencilParameters),
299 mIndexedDrawFirstElement(0),
300 mIndexedDrawElementsCount(0),
301 mDepthFunction(depthFunction),
302 mFaceCullingMode(faceCullingMode),
303 mDepthWriteMode(depthWriteMode),
304 mDepthTestMode(depthTestMode),
305 mUpdateAttributeLocations(true),
306 mPremultipledAlphaEnabled(preMultipliedAlphaEnabled),
307 mShaderChanged(false),
310 if(blendingBitmask != 0u)
312 mBlendingOptions.SetBitmask(blendingBitmask);
315 mBlendingOptions.SetBlendColor(blendColor);
318 void Renderer::Initialize(Context& context, Graphics::Controller& graphicsController, ProgramCache& programCache, Render::ShaderCache& shaderCache)
321 mGraphicsController = &graphicsController;
322 mProgramCache = &programCache;
323 mShaderCache = &shaderCache;
326 Renderer::~Renderer() = default;
328 void Renderer::SetGeometry(Render::Geometry* geometry)
330 mGeometry = geometry;
331 mUpdateAttributeLocations = true;
333 void Renderer::SetDrawCommands(Dali::DevelRenderer::DrawCommand* pDrawCommands, uint32_t size)
335 mDrawCommands.clear();
336 mDrawCommands.insert(mDrawCommands.end(), pDrawCommands, pDrawCommands + size);
339 void Renderer::GlContextDestroyed()
341 mGeometry->GlContextDestroyed();
344 void Renderer::GlCleanup()
348 void Renderer::SetUniforms(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider& node, const Vector3& size, Program& program)
350 // Check if the map has changed
351 DALI_ASSERT_DEBUG(mRenderDataProvider && "No Uniform map data provider available");
353 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
355 if(uniformMapDataProvider.GetUniformMapChanged(bufferIndex) ||
356 node.GetUniformMapChanged(bufferIndex) ||
357 mUniformIndexMap.Count() == 0 ||
360 // Reset shader pointer
361 mShaderChanged = false;
363 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
364 const SceneGraph::CollectedUniformMap& uniformMapNode = node.GetUniformMap(bufferIndex);
366 uint32_t maxMaps = static_cast<uint32_t>(uniformMap.Count() + uniformMapNode.Count()); // 4,294,967,295 maps should be enough
367 mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
368 mUniformIndexMap.Resize(maxMaps);
370 uint32_t mapIndex = 0;
371 for(; mapIndex < uniformMap.Count(); ++mapIndex)
373 mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex].propertyPtr;
374 mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform(uniformMap[mapIndex].uniformName);
377 for(uint32_t nodeMapIndex = 0; nodeMapIndex < uniformMapNode.Count(); ++nodeMapIndex)
379 uint32_t uniformIndex = program.RegisterUniform(uniformMapNode[nodeMapIndex].uniformName);
381 for(uint32_t i = 0; i < uniformMap.Count(); ++i)
383 if(mUniformIndexMap[i].uniformIndex == uniformIndex)
385 mUniformIndexMap[i].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
393 mUniformIndexMap[mapIndex].propertyValue = uniformMapNode[nodeMapIndex].propertyPtr;
394 mUniformIndexMap[mapIndex].uniformIndex = uniformIndex;
399 mUniformIndexMap.Resize(mapIndex);
402 // Set uniforms in local map
403 for(UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
404 end = mUniformIndexMap.End();
408 SetUniformFromProperty(bufferIndex, program, *iter);
411 GLint sizeLoc = program.GetUniformLocation(Program::UNIFORM_SIZE);
414 program.SetSizeUniform3f(sizeLoc, size.x, size.y, size.z);
418 void Renderer::SetUniformFromProperty(BufferIndex bufferIndex, Program& program, UniformIndexMap& map)
420 GLint location = program.GetUniformLocation(map.uniformIndex);
421 if(Program::UNIFORM_UNKNOWN != location)
423 // switch based on property type to use correct GL uniform setter
424 switch(map.propertyValue->GetType())
426 case Property::INTEGER:
428 program.SetUniform1i(location, map.propertyValue->GetInteger(bufferIndex));
431 case Property::FLOAT:
433 program.SetUniform1f(location, map.propertyValue->GetFloat(bufferIndex));
436 case Property::VECTOR2:
438 Vector2 value(map.propertyValue->GetVector2(bufferIndex));
439 program.SetUniform2f(location, value.x, value.y);
443 case Property::VECTOR3:
445 Vector3 value(map.propertyValue->GetVector3(bufferIndex));
446 program.SetUniform3f(location, value.x, value.y, value.z);
450 case Property::VECTOR4:
452 Vector4 value(map.propertyValue->GetVector4(bufferIndex));
453 program.SetUniform4f(location, value.x, value.y, value.z, value.w);
457 case Property::ROTATION:
459 Quaternion value(map.propertyValue->GetQuaternion(bufferIndex));
460 program.SetUniform4f(location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w);
464 case Property::MATRIX:
466 const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
467 program.SetUniformMatrix4fv(location, 1, value.AsFloat());
471 case Property::MATRIX3:
473 const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
474 program.SetUniformMatrix3fv(location, 1, value.AsFloat());
480 // Other property types are ignored
487 bool Renderer::BindTextures(Program& program, Graphics::CommandBuffer& commandBuffer, Vector<Graphics::Texture*>& boundTextures)
489 uint32_t textureUnit = 0;
492 GLint uniformLocation(-1);
493 std::vector<Render::Sampler*>& samplers(mRenderDataProvider->GetSamplers());
494 std::vector<Render::Texture*>& textures(mRenderDataProvider->GetTextures());
496 std::vector<Graphics::TextureBinding> textureBindings;
497 for(uint32_t i = 0; i < static_cast<uint32_t>(textures.size()) && result; ++i) // not expecting more than uint32_t of textures
501 if(program.GetSamplerUniformLocation(i, uniformLocation))
503 // if the sampler exists,
504 // if it's default, delete the graphics object
505 // otherwise re-initialize it if dirty
507 const Graphics::Sampler* graphicsSampler = (samplers[i] ? samplers[i]->GetGraphicsObject()
510 boundTextures.PushBack(textures[i]->GetGraphicsObject());
511 const Graphics::TextureBinding textureBinding{textures[i]->GetGraphicsObject(), graphicsSampler, textureUnit};
512 textureBindings.push_back(textureBinding);
514 program.SetUniform1i(uniformLocation, textureUnit); // Get through shader reflection
520 if(textureBindings.size() > 0)
522 commandBuffer.BindTextures(textureBindings);
528 void Renderer::SetFaceCullingMode(FaceCullingMode::Type mode)
530 mFaceCullingMode = mode;
534 void Renderer::SetBlendingBitMask(uint32_t bitmask)
536 mBlendingOptions.SetBitmask(bitmask);
540 void Renderer::SetBlendColor(const Vector4& color)
542 mBlendingOptions.SetBlendColor(color);
546 void Renderer::SetIndexedDrawFirstElement(uint32_t firstElement)
548 mIndexedDrawFirstElement = firstElement;
552 void Renderer::SetIndexedDrawElementsCount(uint32_t elementsCount)
554 mIndexedDrawElementsCount = elementsCount;
558 void Renderer::EnablePreMultipliedAlpha(bool enable)
560 mPremultipledAlphaEnabled = enable;
564 void Renderer::SetDepthWriteMode(DepthWriteMode::Type depthWriteMode)
566 mDepthWriteMode = depthWriteMode;
570 void Renderer::SetDepthTestMode(DepthTestMode::Type depthTestMode)
572 mDepthTestMode = depthTestMode;
576 DepthWriteMode::Type Renderer::GetDepthWriteMode() const
578 return mDepthWriteMode;
581 DepthTestMode::Type Renderer::GetDepthTestMode() const
583 return mDepthTestMode;
586 void Renderer::SetDepthFunction(DepthFunction::Type depthFunction)
588 mDepthFunction = depthFunction;
592 DepthFunction::Type Renderer::GetDepthFunction() const
594 return mDepthFunction;
597 void Renderer::SetRenderMode(RenderMode::Type renderMode)
599 mStencilParameters.renderMode = renderMode;
603 RenderMode::Type Renderer::GetRenderMode() const
605 return mStencilParameters.renderMode;
608 void Renderer::SetStencilFunction(StencilFunction::Type stencilFunction)
610 mStencilParameters.stencilFunction = stencilFunction;
614 StencilFunction::Type Renderer::GetStencilFunction() const
616 return mStencilParameters.stencilFunction;
619 void Renderer::SetStencilFunctionMask(int stencilFunctionMask)
621 mStencilParameters.stencilFunctionMask = stencilFunctionMask;
625 int Renderer::GetStencilFunctionMask() const
627 return mStencilParameters.stencilFunctionMask;
630 void Renderer::SetStencilFunctionReference(int stencilFunctionReference)
632 mStencilParameters.stencilFunctionReference = stencilFunctionReference;
636 int Renderer::GetStencilFunctionReference() const
638 return mStencilParameters.stencilFunctionReference;
641 void Renderer::SetStencilMask(int stencilMask)
643 mStencilParameters.stencilMask = stencilMask;
647 int Renderer::GetStencilMask() const
649 return mStencilParameters.stencilMask;
652 void Renderer::SetStencilOperationOnFail(StencilOperation::Type stencilOperationOnFail)
654 mStencilParameters.stencilOperationOnFail = stencilOperationOnFail;
658 StencilOperation::Type Renderer::GetStencilOperationOnFail() const
660 return mStencilParameters.stencilOperationOnFail;
663 void Renderer::SetStencilOperationOnZFail(StencilOperation::Type stencilOperationOnZFail)
665 mStencilParameters.stencilOperationOnZFail = stencilOperationOnZFail;
669 StencilOperation::Type Renderer::GetStencilOperationOnZFail() const
671 return mStencilParameters.stencilOperationOnZFail;
674 void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperationOnZPass)
676 mStencilParameters.stencilOperationOnZPass = stencilOperationOnZPass;
680 StencilOperation::Type Renderer::GetStencilOperationOnZPass() const
682 return mStencilParameters.stencilOperationOnZPass;
685 void Renderer::Upload()
687 mGeometry->Upload(*mGraphicsController);
690 void Renderer::Render(Context& context,
691 BufferIndex bufferIndex,
692 const SceneGraph::NodeDataProvider& node,
693 const Matrix& modelMatrix,
694 const Matrix& modelViewMatrix,
695 const Matrix& viewMatrix,
696 const Matrix& projectionMatrix,
699 Vector<Graphics::Texture*>& boundTextures,
700 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
703 // Before doing anything test if the call happens in the right queue
704 if(mDrawCommands.empty() && queueIndex > 0)
710 std::vector<DevelRenderer::DrawCommand*> commands;
711 for(auto& cmd : mDrawCommands)
713 if(cmd.queue == queueIndex)
715 commands.emplace_back(&cmd);
719 // Have commands but nothing to be drawn - abort
720 if(!mDrawCommands.empty() && commands.empty())
725 // Get the program to use
726 // The program cache owns the Program object so we don't need to worry about this raw allocation here.
727 ShaderDataPtr shaderData = mRenderDataProvider->GetShader().GetShaderData();
728 Program* program = Program::New(*mProgramCache, shaderData, (shaderData->GetHints() & Dali::Shader::Hint::MODIFIES_GEOMETRY) != 0x0);
732 DALI_LOG_ERROR("Failed to get program for shader at address %p.\n", reinterpret_cast<void*>(&mRenderDataProvider->GetShader()));
736 Graphics::UniquePtr<Graphics::CommandBuffer> commandBuffer = mGraphicsController->CreateCommandBuffer(
737 Graphics::CommandBufferCreateInfo()
738 .SetLevel(Graphics::CommandBufferLevel::SECONDARY),
742 if(!mDrawCommands.empty())
744 blend = (commands[0]->queue == DevelRenderer::RENDER_QUEUE_OPAQUE ? false : blend);
748 // Really, need to have a pipeline cache in implementation.
750 mLegacyProgram.programId = program->GetProgramId();
752 Dali::Graphics::Shader& vertexShader = mShaderCache->GetShader(
753 shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::VERTEX_SHADER),
754 Graphics::PipelineStage::VERTEX_SHADER,
755 shaderData->GetSourceMode());
757 Dali::Graphics::Shader& fragmentShader = mShaderCache->GetShader(
758 shaderData->GetShaderForPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER),
759 Graphics::PipelineStage::FRAGMENT_SHADER,
760 shaderData->GetSourceMode());
762 mShaderStates.clear();
763 mShaderStates.push_back(Graphics::ShaderState().SetShader(vertexShader).SetPipelineStage(Graphics::PipelineStage::VERTEX_SHADER));
764 mShaderStates.push_back(Graphics::ShaderState().SetShader(fragmentShader).SetPipelineStage(Graphics::PipelineStage::FRAGMENT_SHADER));
766 auto createInfo = Graphics::PipelineCreateInfo().SetShaderState(mShaderStates).SetNextExtension(&mLegacyProgram);
768 // Temporarily create a pipeline here - this will be used for transporting
769 // topology, vertex format, attrs, rasterization state
770 mGraphicsPipeline = std::move(PrepareGraphicsPipeline(*program, instruction, blend, createInfo)); // WRONG: @todo FIXME. Renderer can't own a pipeline.
771 commandBuffer->BindPipeline(*mGraphicsPipeline.get());
773 if(DALI_LIKELY(BindTextures(*program, *commandBuffer.get(), boundTextures)))
775 // Only set up and draw if we have textures and they are all valid
777 // set projection and view matrix if program has not yet received them yet this frame
778 SetMatrices(*program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix);
781 GLint loc = program->GetUniformLocation(Program::UNIFORM_COLOR);
782 if(Program::UNIFORM_UNKNOWN != loc)
784 const Vector4& color = node.GetRenderColor(bufferIndex);
785 if(mPremultipledAlphaEnabled)
787 float alpha = color.a * mRenderDataProvider->GetOpacity(bufferIndex);
788 program->SetUniform4f(loc, color.r * alpha, color.g * alpha, color.b * alpha, alpha);
792 program->SetUniform4f(loc, color.r, color.g, color.b, color.a * mRenderDataProvider->GetOpacity(bufferIndex));
796 SetUniforms(bufferIndex, node, size, *program);
798 bool drawn = false; // Draw can fail if there are no vertex buffers or they haven't been uploaded yet
799 // @todo We should detect this case much earlier to prevent unnecessary work
801 //@todo manage mDrawCommands in the same way as above command buffer?!
802 if(mDrawCommands.empty())
804 drawn = mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), mIndexedDrawFirstElement, mIndexedDrawElementsCount);
808 for(auto& cmd : commands)
810 // @todo This should generate a command buffer per cmd
811 // Tests WILL fail. (Temporarily commented out)
812 mGeometry->Draw(*mGraphicsController, *commandBuffer.get(), cmd->firstIndex, cmd->elementCount);
816 // Command buffer contains Texture bindings, vertex bindings, index buffer binding, pipeline(vertex format)
817 // @todo We should return the command buffer(s) and let the calling method submit
818 // If not drawn, then don't add command buffer to submit info, and if empty, don't
822 Graphics::SubmitInfo submitInfo{{}, 0 | Graphics::SubmitFlagBits::FLUSH};
823 submitInfo.cmdBuffer.push_back(commandBuffer.get());
824 mGraphicsController->SubmitCommandBuffers(submitInfo);
831 void Renderer::SetSortAttributes(BufferIndex bufferIndex,
832 SceneGraph::RenderInstructionProcessor::SortAttributes& sortAttributes) const
834 sortAttributes.shader = &(mRenderDataProvider->GetShader());
835 sortAttributes.geometry = mGeometry;
838 void Renderer::SetShaderChanged(bool value)
840 mShaderChanged = value;
843 bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvider* node)
851 if(mShaderChanged || mUpdateAttributeLocations || mGeometry->AttributesChanged())
856 for(const auto& texture : mRenderDataProvider->GetTextures())
858 if(texture && texture->IsNativeImage())
864 uint64_t hash = 0xc70f6907UL;
865 const SceneGraph::CollectedUniformMap& uniformMapNode = node->GetUniformMap(bufferIndex);
866 for(const auto& uniformProperty : uniformMapNode)
868 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
871 const SceneGraph::UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
872 const SceneGraph::CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap(bufferIndex);
873 for(const auto& uniformProperty : uniformMap)
875 hash = uniformProperty.propertyPtr->Hash(bufferIndex, hash);
878 if(mUniformsHash != hash)
880 mUniformsHash = hash;
887 Graphics::UniquePtr<Graphics::Pipeline> Renderer::PrepareGraphicsPipeline(
889 const Dali::Internal::SceneGraph::RenderInstruction& instruction,
891 Graphics::PipelineCreateInfo& createInfo)
893 Graphics::InputAssemblyState inputAssemblyState{};
894 Graphics::VertexInputState vertexInputState{};
895 uint32_t bindingIndex{0u};
897 if(mUpdateAttributeLocations || mGeometry->AttributesChanged())
899 mAttributeLocations.Clear();
900 mUpdateAttributeLocations = true;
907 for(auto&& vertexBuffer : mGeometry->GetVertexBuffers())
909 const VertexBuffer::Format& vertexFormat = *vertexBuffer->GetFormat();
911 vertexInputState.bufferBindings.emplace_back(vertexFormat.size, // stride
912 Graphics::VertexInputRate::PER_VERTEX);
914 const uint32_t attributeCount = vertexBuffer->GetAttributeCount();
915 for(uint32_t i = 0; i < attributeCount; ++i)
917 if(mUpdateAttributeLocations)
919 auto attributeName = vertexBuffer->GetAttributeName(i);
920 uint32_t index = program.RegisterCustomAttribute(attributeName);
921 int32_t pLocation = program.GetCustomAttributeLocation(index);
924 DALI_LOG_WARNING("Attribute not found in the shader: %s\n", attributeName.GetCString());
926 mAttributeLocations.PushBack(pLocation);
929 uint32_t location = static_cast<uint32_t>(mAttributeLocations[base + i]);
931 vertexInputState.attributes.emplace_back(location,
933 vertexFormat.components[i].offset,
934 GetPropertyVertexFormat(vertexFormat.components[i].type));
936 base += attributeCount;
939 mUpdateAttributeLocations = false;
942 inputAssemblyState.SetTopology(mGeometry->GetTopology());
944 Graphics::RasterizationState rasterizationState{};
947 const Dali::Internal::SceneGraph::Camera* cam = instruction.GetCamera();
948 if(cam->GetReflectionUsed())
950 auto adjFaceCullingMode = mFaceCullingMode;
951 switch(mFaceCullingMode)
953 case FaceCullingMode::Type::FRONT:
955 adjFaceCullingMode = FaceCullingMode::Type::BACK;
958 case FaceCullingMode::Type::BACK:
960 adjFaceCullingMode = FaceCullingMode::Type::FRONT;
965 // nothing to do, leave culling as it is
968 rasterizationState.SetCullMode(ConvertCullFace(adjFaceCullingMode));
972 rasterizationState.SetCullMode(ConvertCullFace(mFaceCullingMode));
975 rasterizationState.SetFrontFace(Graphics::FrontFace::COUNTER_CLOCKWISE);
980 switch(mGeometry->GetTopology())
982 case Graphics::PrimitiveTopology::TRIANGLE_LIST:
983 case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
984 case Graphics::PrimitiveTopology::TRIANGLE_FAN:
985 rasterizationState.SetPolygonMode(Graphics::PolygonMode::FILL);
987 case Graphics::PrimitiveTopology::LINE_LIST:
988 case Graphics::PrimitiveTopology::LINE_LOOP:
989 case Graphics::PrimitiveTopology::LINE_STRIP:
990 rasterizationState.SetPolygonMode(Graphics::PolygonMode::LINE);
992 case Graphics::PrimitiveTopology::POINT_LIST:
993 rasterizationState.SetPolygonMode(Graphics::PolygonMode::POINT);
997 // @todo How to signal a blend barrier is needed?
998 //if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1000 // context.BlendBarrier();
1003 Graphics::ColorBlendState colorBlendState{};
1004 colorBlendState.SetBlendEnable(false);
1008 colorBlendState.SetBlendEnable(true);
1010 Graphics::BlendOp rgbOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1011 Graphics::BlendOp alphaOp = ConvertBlendEquation(mBlendingOptions.GetBlendEquationRgb());
1012 if(mBlendingOptions.IsAdvancedBlendEquationApplied() && mPremultipledAlphaEnabled)
1014 if(rgbOp != alphaOp)
1016 DALI_LOG_ERROR("Advanced Blend Equation MUST be applied by using BlendEquation.\n");
1022 .SetSrcColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorRgb()))
1023 .SetSrcAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendSrcFactorAlpha()))
1024 .SetDstColorBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorRgb()))
1025 .SetDstAlphaBlendFactor(ConvertBlendFactor(mBlendingOptions.GetBlendDestFactorAlpha()))
1026 .SetColorBlendOp(rgbOp)
1027 .SetAlphaBlendOp(alphaOp);
1029 // Blend color is optional and rarely used
1030 Vector4* blendColor = const_cast<Vector4*>(mBlendingOptions.GetBlendColor());
1033 colorBlendState.SetBlendConstants(blendColor->AsFloat());
1037 // Take the program into use so we can send uniforms to it
1038 // @todo Remove this call entirely!
1043 // Create a new pipeline
1044 return mGraphicsController->CreatePipeline(
1046 .SetInputAssemblyState(&inputAssemblyState) // Passed as pointers - shallow copy will break. TOO C LIKE
1047 .SetVertexInputState(&vertexInputState)
1048 .SetRasterizationState(&rasterizationState)
1049 .SetColorBlendState(&colorBlendState),
1053 } // namespace Render
1055 } // namespace Internal