From 1aa9ce2830c98b68c188a80439fa5451077af6ee Mon Sep 17 00:00:00 2001 From: David Steele Date: Mon, 8 Mar 2021 15:55:31 +0000 Subject: [PATCH] Syncing test harness changes Change-Id: I3c9704c47925123be511d509970e6dc6a9d5be77 --- .../dali-test-suite-utils/test-gl-abstraction.h | 52 +- .../dali-test-suite-utils/test-graphics-buffer.cpp | 66 +++ .../dali-test-suite-utils/test-graphics-buffer.h | 8 + .../test-graphics-command-buffer.cpp | 157 ++---- .../test-graphics-command-buffer.h | 559 ++++++++++++++++++--- .../test-graphics-controller.cpp | 209 ++++---- .../test-graphics-controller.h | 7 + .../test-graphics-program.cpp | 13 +- .../dali-test-suite-utils/test-graphics-program.h | 4 +- .../test-graphics-reflection.cpp | 135 ++++- .../test-graphics-reflection.h | 9 +- 11 files changed, 928 insertions(+), 291 deletions(-) diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.h index 1d93731..9357803 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.h +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.h @@ -38,6 +38,17 @@ namespace Dali { +struct UniformData +{ + std::string name; + Property::Type type; + UniformData(const std::string& name, Property::Type type = Property::Type::NONE) + : name(name), + type(type) + { + } +}; + class DALI_CORE_API TestGlAbstraction : public Dali::Integration::GlAbstraction { public: @@ -899,7 +910,7 @@ public: if(it2 == uniformIDs.end()) { // Uniform not found, so add it... - uniformIDs[name] = ++mLastUniformIdUsed; + uniformIDs[name] = mLastUniformIdUsed++; return mLastUniformIdUsed; } @@ -971,9 +982,35 @@ public: mShaderTrace.PushCall("LinkProgram", out.str(), namedParams); mNumberOfActiveUniforms = 3; - GetUniformLocation(program, "sTexture"); + + GetUniformLocation(program, "uRendererColor"); + GetUniformLocation(program, "uCustom"); + GetUniformLocation(program, "uCustom3"); + GetUniformLocation(program, "uFadeColor"); + GetUniformLocation(program, "uUniform1"); + GetUniformLocation(program, "uUniform2"); + GetUniformLocation(program, "uUniform3"); + GetUniformLocation(program, "uFadeProgress"); + GetUniformLocation(program, "uANormalMatrix"); GetUniformLocation(program, "sEffect"); + GetUniformLocation(program, "sTexture"); + GetUniformLocation(program, "sTextureRect"); GetUniformLocation(program, "sGloss"); + GetUniformLocation(program, "uColor"); + GetUniformLocation(program, "uModelMatrix"); + GetUniformLocation(program, "uModelView"); + GetUniformLocation(program, "uMvpMatrix"); + GetUniformLocation(program, "uNormalMatrix"); + GetUniformLocation(program, "uProjection"); + GetUniformLocation(program, "uSize"); + GetUniformLocation(program, "uViewMatrix"); + GetUniformLocation(program, "uLightCameraProjectionMatrix"); + GetUniformLocation(program, "uLightCameraViewMatrix"); + + for(const auto& uniform : mCustomUniformData) + { + GetUniformLocation(program, uniform.name.c_str()); + } } inline void PixelStorei(GLenum pname, GLint param) override @@ -2270,7 +2307,7 @@ public: // TEST FUNCTIONS } } - fprintf(stderr, "Not found, printing possible values:\n"); + fprintf(stderr, "%s Not found, printing possible values:\n", name); for(ProgramUniformMap::const_iterator program_it = mUniforms.begin(); program_it != mUniforms.end(); ++program_it) @@ -2289,7 +2326,7 @@ public: // TEST FUNCTIONS if(mProgramUniforms.GetUniformValue(programId, uniformId, origValue)) { std::stringstream out; - out << uniform_it->first << ": " << origValue; + out << "Program: " << programId << ", " << uniform_it->first << ": " << origValue; fprintf(stderr, "%s\n", out.str().c_str()); } } @@ -2323,6 +2360,11 @@ public: // TEST FUNCTIONS return false; } + inline void SetCustomUniforms(std::vector& customUniformData) + { + mCustomUniformData = customUniformData; + } + inline GLuint GetLastShaderCompiled() const { return mLastShaderCompiled; @@ -2506,6 +2548,8 @@ private: typedef std::map ProgramUniformMap; ProgramUniformMap mUniforms; + std::vector mCustomUniformData{}; + template struct ProgramUniformValue : public std::map > { diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp index 90640e5..2a75a2d 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp @@ -17,6 +17,8 @@ #include "test-graphics-buffer.h" #include #include "dali-test-suite-utils.h" +#include "test-graphics-program.h" +#include "test-graphics-reflection.h" namespace Dali { @@ -78,4 +80,68 @@ GLenum TestGraphicsBuffer::GetTarget() return target; } +void TestGraphicsBuffer::BindAsUniformBuffer(const TestGraphicsProgram* program) const +{ + auto* reflection = static_cast(&program->GetReflection()); + + Graphics::UniformBlockInfo uboInfo{}; + reflection->GetUniformBlock(0, uboInfo); + + auto* data = memory.data(); + + for(const auto& member : uboInfo.members) + { + auto type = reflection->GetMemberType(0, member.location); + switch(type) + { + case Property::VECTOR4: + { + auto value = *reinterpret_cast(data + member.offset); + mGl.Uniform4f(member.location, value.x, value.y, value.z, value.w); + break; + } + case Property::VECTOR3: + { + auto value = *reinterpret_cast(data + member.offset); + mGl.Uniform3f(member.location, value.x, value.y, value.z); + break; + } + case Property::VECTOR2: + { + auto value = *reinterpret_cast(data + member.offset); + mGl.Uniform2f(member.location, value.x, value.y); + break; + } + case Property::FLOAT: + { + auto value = *reinterpret_cast(data + member.offset); + mGl.Uniform1f(member.location, value); + break; + } + case Property::INTEGER: + { + auto ptr = reinterpret_cast(data + member.offset); + auto value = *ptr; + mGl.Uniform1i(member.location, value); + break; + } + case Property::MATRIX: + { + auto value = reinterpret_cast(data + member.offset); + mGl.UniformMatrix4fv(member.location, 1, GL_FALSE, value); + break; + } + case Property::MATRIX3: + { + auto value = reinterpret_cast(data + member.offset); + mGl.UniformMatrix3fv(member.location, 1, GL_FALSE, value); + break; + } + default: + { + } + } + } +} + } // namespace Dali diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.h index c4abc3e..87c9f87 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.h +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.h @@ -25,6 +25,7 @@ namespace Dali { +class TestGraphicsProgram; class TestGraphicsBuffer : public Graphics::Buffer { public: @@ -34,6 +35,13 @@ public: void Upload(uint32_t offset, uint32_t size); GLenum GetTarget(); + bool IsCPUAllocated() const + { + return true; + } + + void BindAsUniformBuffer(const TestGraphicsProgram* program) const; + TraceCallStack& mCallStack; TestGlAbstraction& mGl; std::vector memory; diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp index a0dee4a..ed63416 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp @@ -24,134 +24,53 @@ TestGraphicsCommandBuffer::TestGraphicsCommandBuffer(TraceCallStack& callstack, { } -void TestGraphicsCommandBuffer::BindVertexBuffers(uint32_t firstBinding, - std::vector buffers, - std::vector offsets) +int TestGraphicsCommandBuffer::GetDrawCallsCount() { - mVertexBufferBindings.firstBinding = firstBinding; - mVertexBufferBindings.buffers = buffers; // Copy - mVertexBufferBindings.offsets = offsets; // Copy - mCallStack.PushCall("BindVertexBuffers", ""); -} - -void TestGraphicsCommandBuffer::BindUniformBuffers(const std::vector& bindings) -{ - mCallStack.PushCall("BindUniformBuffers", ""); -} - -void TestGraphicsCommandBuffer::BindPipeline(const Graphics::Pipeline& pipeline) -{ - mPipeline = static_cast(const_cast(&pipeline)); - mCallStack.PushCall("BindPipeline", ""); -} - -void TestGraphicsCommandBuffer::BindTextures(std::vector& textureBindings) -{ - mCallStack.PushCall("BindTextures", ""); - for(auto& binding : textureBindings) + int count = 0; + for(auto& cmd : mCommands) { - mTextureBindings.push_back(binding); + if(cmd.type == CommandType::DRAW || + cmd.type == CommandType::DRAW_INDEXED || + cmd.type == CommandType::DRAW_INDEXED_INDIRECT) + { + ++count; + } } + return count; } -void TestGraphicsCommandBuffer::BindSamplers(std::vector& samplerBindings) -{ - mCallStack.PushCall("BindSamplers", ""); -} - -void TestGraphicsCommandBuffer::BindPushConstants(void* data, - uint32_t size, - uint32_t binding) -{ - mCallStack.PushCall("BindPushConstants", ""); -} - -void TestGraphicsCommandBuffer::BindIndexBuffer(const Graphics::Buffer& buffer, - uint32_t offset, - Graphics::Format format) -{ - mIndexBufferBinding.buffer = &buffer; - mIndexBufferBinding.offset = offset; - mIndexBufferBinding.format = format; - mCallStack.PushCall("BindIndexBuffer", ""); -} - -void TestGraphicsCommandBuffer::BeginRenderPass( - Graphics::RenderPass& renderPass, - Graphics::RenderTarget& renderTarget, - Graphics::Extent2D renderArea, - std::vector clearValues) -{ - mCallStack.PushCall("BeginRenderPass", ""); -} - -void TestGraphicsCommandBuffer::EndRenderPass() -{ - mCallStack.PushCall("EndRenderPass", ""); -} - -void TestGraphicsCommandBuffer::Draw( - uint32_t vertexCount, - uint32_t instanceCount, - uint32_t firstVertex, - uint32_t firstInstance) -{ - drawCommand.drawType = Draw::DrawType::Unindexed; - drawCommand.u.unindexedDraw.vertexCount = vertexCount; - drawCommand.u.unindexedDraw.instanceCount = instanceCount; - drawCommand.u.unindexedDraw.firstVertex = firstVertex; - drawCommand.u.unindexedDraw.firstInstance = firstInstance; - mCallStack.PushCall("Draw", ""); -} - -void TestGraphicsCommandBuffer::DrawIndexed( - uint32_t indexCount, - uint32_t instanceCount, - uint32_t firstIndex, - int32_t vertexOffset, - uint32_t firstInstance) -{ - drawCommand.drawType = TestGraphicsCommandBuffer::Draw::DrawType::Indexed; - drawCommand.u.indexedDraw.indexCount = indexCount; - drawCommand.u.indexedDraw.instanceCount = instanceCount; - drawCommand.u.indexedDraw.firstIndex = firstIndex; - drawCommand.u.indexedDraw.vertexOffset = vertexOffset; - drawCommand.u.indexedDraw.firstInstance = firstInstance; - mCallStack.PushCall("DrawIndexed", ""); -} - -void TestGraphicsCommandBuffer::DrawIndexedIndirect( - Graphics::Buffer& buffer, - uint32_t offset, - uint32_t drawCount, - uint32_t stride) -{ - mCallStack.PushCall("DrawIndexedIndirect", ""); -} - -void TestGraphicsCommandBuffer::Reset(Graphics::CommandBuffer& commandBuffer) +void TestGraphicsCommandBuffer::GetStateForDrawCall(int drawCallIndex) { - mCallStack.PushCall("Reset", ""); -} - -void TestGraphicsCommandBuffer::SetScissor(Graphics::Extent2D value) -{ - mCallStack.PushCall("SetScissor", ""); -} - -void TestGraphicsCommandBuffer::SetScissorTestEnable(bool value) -{ - mCallStack.PushCall("SetScissorTestEnable", ""); -} - -void TestGraphicsCommandBuffer::SetViewport(Graphics::Viewport value) -{ - mCallStack.PushCall("SetViewport", ""); + int index = 0; + std::vector mCommandStack{}; + for(auto& cmd : mCommands) + { + mCommandStack.push_back(cmd); + if(cmd.type == CommandType::DRAW || + cmd.type == CommandType::DRAW_INDEXED || + cmd.type == CommandType::DRAW_INDEXED_INDIRECT) + { + if(index == drawCallIndex) + { + break; + } + mCommandStack.clear(); + ++index; + } + } } -void TestGraphicsCommandBuffer::SetViewportEnable(bool value) +std::vector TestGraphicsCommandBuffer::GetCommandsByType(CommandTypeMask mask) { - mCallStack.PushCall("SetViewportEnable", ""); + std::vector mCommandStack{}; + for(auto& cmd : mCommands) + { + if(uint32_t(cmd.type) == (mask & uint32_t(cmd.type))) + { + mCommandStack.emplace_back(&cmd); + } + } + return mCommandStack; } } // namespace Dali diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.h index 151a9df..2ab178a 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.h +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.h @@ -24,120 +24,549 @@ #include #include #include "test-gl-abstraction.h" +#include "test-graphics-buffer.h" #include "test-graphics-pipeline.h" #include "test-trace-call-stack.h" namespace Dali { +class TestGraphicsTexture; +class TestGraphicsBuffer; +class TestGraphicsSampler; +class TestGraphicsPipeline; + +enum class CommandType +{ + FLUSH = 1 << 0, + BIND_TEXTURES = 1 << 1, + BIND_SAMPLERS = 1 << 2, + BIND_VERTEX_BUFFERS = 1 << 3, + BIND_INDEX_BUFFER = 1 << 4, + BIND_UNIFORM_BUFFER = 1 << 5, + BIND_PIPELINE = 1 << 6, + DRAW = 1 << 7, + DRAW_INDEXED = 1 << 8, + DRAW_INDEXED_INDIRECT = 1 << 9 +}; + +using CommandTypeMask = uint32_t; +template +inline CommandTypeMask operator|(T flags, CommandType bit) +{ + return static_cast(flags) | static_cast(bit); +} + +/** + * @brief Descriptor of single buffer binding within + * command buffer. + */ +struct VertexBufferBindingDescriptor +{ + const TestGraphicsBuffer* buffer{nullptr}; + uint32_t offset{0u}; +}; + +/** + * @brief Descriptor of ix buffer binding within + * command buffer. + */ +struct IndexBufferBindingDescriptor +{ + const TestGraphicsBuffer* buffer{nullptr}; + uint32_t offset{}; + Graphics::Format format{}; +}; + +/** + * @brief Descriptor of uniform buffer binding within + * command buffer. + */ +struct UniformBufferBindingDescriptor +{ + const TestGraphicsBuffer* buffer{nullptr}; + uint32_t binding{0u}; + uint32_t offset{0u}; + bool emulated; /// textureBindings; + } bindTextures{}; + + // BindSampler command + struct + { + std::vector samplerBindings; + } bindSamplers; + + struct + { + using Binding = VertexBufferBindingDescriptor; + std::vector vertexBufferBindings; + } bindVertexBuffers; + + struct : public IndexBufferBindingDescriptor + { + } bindIndexBuffer; + + struct + { + std::vector uniformBufferBindings{}; + UniformBufferBindingDescriptor standaloneUniformsBufferBinding{}; + } bindUniformBuffers; + + struct + { + const TestGraphicsPipeline* pipeline{nullptr}; + } bindPipeline; + + struct : public DrawCallDescriptor + { + } draw; + }; +}; + class TestGraphicsCommandBuffer : public Graphics::CommandBuffer { public: TestGraphicsCommandBuffer(TraceCallStack& callstack, TestGlAbstraction& glAbstraction); + ~TestGraphicsCommandBuffer() + { + } void BindVertexBuffers(uint32_t firstBinding, std::vector buffers, - std::vector offsets); + std::vector offsets) override + { + mCommands.emplace_back(); + mCommands.back().type = CommandType::BIND_VERTEX_BUFFERS; + auto& bindings = mCommands.back().bindVertexBuffers.vertexBufferBindings; + if(bindings.size() < firstBinding + buffers.size()) + { + bindings.resize(firstBinding + buffers.size()); + auto index = firstBinding; + for(auto& buf : buffers) + { + bindings[index].buffer = static_cast(buf); + bindings[index].offset = offsets[index - firstBinding]; + index++; + } + } + mCallStack.PushCall("BindVertexBuffers", ""); + } - void BindUniformBuffers(const std::vector& bindings); + void BindUniformBuffers(const std::vector& bindings) override + { + mCommands.emplace_back(); + auto& cmd = mCommands.back(); + cmd.type = CommandType::BIND_UNIFORM_BUFFER; + auto& bindCmd = cmd.bindUniformBuffers; + for(const auto& binding : bindings) + { + if(binding.buffer) + { + auto testBuffer = static_cast(binding.buffer); + if(testBuffer->IsCPUAllocated()) // standalone uniforms + { + bindCmd.standaloneUniformsBufferBinding.buffer = testBuffer; + bindCmd.standaloneUniformsBufferBinding.offset = binding.offset; + bindCmd.standaloneUniformsBufferBinding.binding = binding.binding; + bindCmd.standaloneUniformsBufferBinding.emulated = true; + } + else // Bind regular UBO + { + // resize binding slots + if(binding.binding >= bindCmd.uniformBufferBindings.size()) + { + bindCmd.uniformBufferBindings.resize(binding.binding + 1); + } + auto& slot = bindCmd.uniformBufferBindings[binding.binding]; + slot.buffer = testBuffer; + slot.offset = binding.offset; + slot.binding = binding.binding; + slot.emulated = false; + } + } + } + mCallStack.PushCall("BindUniformBuffers", ""); + } - void BindPipeline(const Graphics::Pipeline& pipeline); + void BindPipeline(const Graphics::Pipeline& pipeline) override + { + mCommands.emplace_back(); + mCommands.back().type = CommandType::BIND_PIPELINE; + mCommands.back().bindPipeline.pipeline = static_cast(&pipeline); + mCallStack.PushCall("BindPipeline", ""); + } - void BindTextures(std::vector& textureBindings); + void BindTextures(std::vector& textureBindings) override + { + mCommands.emplace_back(); + mCommands.back().type = CommandType::BIND_TEXTURES; + mCommands.back().bindTextures.textureBindings = std::move(textureBindings); + mCallStack.PushCall("BindTextures", ""); + } - void BindSamplers(std::vector& samplerBindings); + void BindSamplers(std::vector& samplerBindings) override + { + mCommands.emplace_back(); + mCommands.back().bindSamplers.samplerBindings = std::move(samplerBindings); + mCallStack.PushCall("BindSamplers", ""); + } void BindPushConstants(void* data, uint32_t size, - uint32_t binding); + uint32_t binding) override + { + mCallStack.PushCall("BindPushConstants", ""); + } void BindIndexBuffer(const Graphics::Buffer& buffer, uint32_t offset, - Graphics::Format format); + Graphics::Format format) override + { + mCommands.emplace_back(); + mCommands.back().type = CommandType::BIND_INDEX_BUFFER; + mCommands.back().bindIndexBuffer.buffer = static_cast(&buffer); + mCommands.back().bindIndexBuffer.offset = offset; + mCommands.back().bindIndexBuffer.format = format; + mCallStack.PushCall("BindIndexBuffer", ""); + } - void BeginRenderPass(Graphics::RenderPass& renderPass, - Graphics::RenderTarget& renderTarget, - Graphics::Extent2D renderArea, - std::vector clearValues); + void BeginRenderPass( + Graphics::RenderPass& renderPass, + Graphics::RenderTarget& renderTarget, + Graphics::Extent2D renderArea, + std::vector clearValues) override + { + mCallStack.PushCall("BeginRenderPass", ""); + } - void EndRenderPass(); + /** + * @brief Ends current render pass + * + * This command must be issued in order to finalize the render pass. + * It's up to the implementation whether anything has to be done but + * the Controller may use end RP marker in order to resolve resource + * dependencies (for example, to know when target texture is ready + * before passing it to another render pass). + */ + void EndRenderPass() override + { + mCallStack.PushCall("EndRenderPass", ""); + } void Draw( uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, - uint32_t firstInstance); + uint32_t firstInstance) override + { + mCommands.emplace_back(); + mCommands.back().type = CommandType::DRAW; + auto& cmd = mCommands.back().draw; + cmd.type = DrawCallDescriptor::Type::DRAW; + cmd.draw.vertexCount = vertexCount; + cmd.draw.instanceCount = instanceCount; + cmd.draw.firstInstance = firstInstance; + cmd.draw.firstVertex = firstVertex; + mCallStack.PushCall("Draw", ""); + } void DrawIndexed( uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, - uint32_t firstInstance); + uint32_t firstInstance) override + { + mCommands.emplace_back(); + mCommands.back().type = CommandType::DRAW_INDEXED; + auto& cmd = mCommands.back().draw; + cmd.type = DrawCallDescriptor::Type::DRAW_INDEXED; + cmd.drawIndexed.firstIndex = firstIndex; + cmd.drawIndexed.firstInstance = firstInstance; + cmd.drawIndexed.indexCount = indexCount; + cmd.drawIndexed.vertexOffset = vertexOffset; + cmd.drawIndexed.instanceCount = instanceCount; + mCallStack.PushCall("DrawIndexed", ""); + } void DrawIndexedIndirect( Graphics::Buffer& buffer, uint32_t offset, uint32_t drawCount, - uint32_t stride); - - void Reset(Graphics::CommandBuffer& commandBuffer); - - void SetScissor(Graphics::Extent2D value); - - void SetScissorTestEnable(bool value); + uint32_t stride) override + { + mCommands.emplace_back(); + mCommands.back().type = CommandType::DRAW_INDEXED_INDIRECT; + auto& cmd = mCommands.back().draw; + cmd.type = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT; + cmd.drawIndexedIndirect.buffer = static_cast(&buffer); + cmd.drawIndexedIndirect.offset = offset; + cmd.drawIndexedIndirect.drawCount = drawCount; + cmd.drawIndexedIndirect.stride = stride; + mCallStack.PushCall("DrawIndexedIndirect", ""); + } - void SetViewport(Graphics::Viewport value); + void Reset() override + { + mCommands.clear(); + mCallStack.PushCall("Reset", ""); + } - void SetViewportEnable(bool value); + void SetScissor(Graphics::Extent2D value) override + { + mCallStack.PushCall("SetScissor", ""); + } -public: - TraceCallStack& mCallStack; - TestGlAbstraction& mGlAbstraction; - TestGraphicsPipeline* mPipeline{nullptr}; - std::vector mTextureBindings{}; + void SetScissorTestEnable(bool value) override + { + mCallStack.PushCall("SetScissorTestEnable", ""); + } - struct VertexBuffersBinding + void SetViewport(Graphics::Viewport value) override { - uint32_t firstBinding; - std::vector buffers; - std::vector offsets; - }; - VertexBuffersBinding mVertexBufferBindings{}; + mCallStack.PushCall("SetViewport", ""); + } - struct IndexBufferBinding + void SetViewportEnable(bool value) override { - const Graphics::Buffer* buffer; - uint32_t offset; - Graphics::Format format; - }; - IndexBufferBinding mIndexBufferBinding{}; + mCallStack.PushCall("SetViewportEnable", ""); + } - struct Draw + [[nodiscard]] const std::vector& GetCommands() const { - enum class DrawType - { - Indexed, - Unindexed - } drawType; - union - { - struct IndexedDraw - { - uint32_t indexCount; - uint32_t instanceCount; - uint32_t firstIndex; - int32_t vertexOffset; - uint32_t firstInstance; - } indexedDraw; - struct UnindexedDraw - { - uint32_t vertexCount; - uint32_t instanceCount; - uint32_t firstVertex; - uint32_t firstInstance; - } unindexedDraw; - } u; - } drawCommand; + return mCommands; + } + + /** + * Returns number of draw commands + * @return + */ + int GetDrawCallsCount(); + + /** + * Retrieves state resolve for selected draw call + * @param drawCommandIndex + */ + void GetStateForDrawCall(int drawCallIndex); + + /** + * Retrieves commands of specified type + */ + std::vector GetCommandsByType(CommandTypeMask mask); + +private: + TraceCallStack& mCallStack; + TestGlAbstraction& mGlAbstraction; + std::vector mCommands; }; } // namespace Dali diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp index fe9c329..ac7d33a 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp @@ -458,121 +458,156 @@ void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& su for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer) { auto commandBuffer = Uncast(graphicsCommandBuffer); - for(auto& binding : commandBuffer->mTextureBindings) + + auto value = commandBuffer->GetCommandsByType(0 | CommandType::BIND_TEXTURES); + if(!value.empty()) { - if(binding.texture) + // must be fixed + for(auto& binding : value[0]->bindTextures.textureBindings) { - auto texture = Uncast(binding.texture); + if(binding.texture) + { + auto texture = Uncast(binding.texture); - texture->Bind(binding.binding); + texture->Bind(binding.binding); - if(binding.sampler) - { - auto sampler = Uncast(binding.sampler); - if(sampler) + if(binding.sampler) { - sampler->Apply(texture->GetTarget()); + auto sampler = Uncast(binding.sampler); + if(sampler) + { + sampler->Apply(texture->GetTarget()); + } } - } - texture->Prepare(); // Ensure native texture is ready + texture->Prepare(); // Ensure native texture is ready + } } } // IndexBuffer binding, - auto& indexBufferBinding = commandBuffer->mIndexBufferBinding; - if(indexBufferBinding.buffer) + auto bindIndexBufferCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_INDEX_BUFFER); + if(!bindIndexBufferCmds.empty()) { - auto buffer = Uncast(indexBufferBinding.buffer); - buffer->Bind(); + auto& indexBufferBinding = bindIndexBufferCmds[0]->bindIndexBuffer; + if(indexBufferBinding.buffer) + { + auto buffer = Uncast(indexBufferBinding.buffer); + buffer->Bind(); + } } // VertexBuffer binding, - for(auto graphicsBuffer : commandBuffer->mVertexBufferBindings.buffers) + auto bindVertexBufferCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_VERTEX_BUFFERS); + if(!bindVertexBufferCmds.empty()) { - auto vertexBuffer = Uncast(graphicsBuffer); - vertexBuffer->Bind(); + for(auto& binding : bindVertexBufferCmds[0]->bindVertexBuffers.vertexBufferBindings) + { + auto graphicsBuffer = binding.buffer; + auto vertexBuffer = Uncast(graphicsBuffer); + vertexBuffer->Bind(); + } } - // Pipeline attribute setup - auto& vi = commandBuffer->mPipeline->vertexInputState; - for(auto& attribute : vi.attributes) - { - mGl.EnableVertexAttribArray(attribute.location); - uint32_t attributeOffset = attribute.offset; - GLsizei stride = vi.bufferBindings[attribute.binding].stride; - - mGl.VertexAttribPointer(attribute.location, - GetNumComponents(attribute.format), - GetGlType(attribute.format), - GL_FALSE, // Not normalized - stride, - reinterpret_cast(attributeOffset)); - } - - // Cull face setup - auto& rasterizationState = commandBuffer->mPipeline->rasterizationState; - if(rasterizationState.cullMode == Graphics::CullMode::NONE) + auto bindPipelineCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_PIPELINE); + if(!bindPipelineCmds.empty()) { - mGl.Disable(GL_CULL_FACE); - } - else - { - mGl.Enable(GL_CULL_FACE); - mGl.CullFace(GetCullFace(rasterizationState.cullMode)); - } - - mGl.FrontFace(GetFrontFace(rasterizationState.frontFace)); - // We don't modify glPolygonMode in our context/abstraction from GL_FILL (the GL default), - // so it isn't present in the API (and won't have any tests!) + auto pipeline = bindPipelineCmds[0]->bindPipeline.pipeline; + auto& vi = pipeline->vertexInputState; + for(auto& attribute : vi.attributes) + { + mGl.EnableVertexAttribArray(attribute.location); + uint32_t attributeOffset = attribute.offset; + GLsizei stride = vi.bufferBindings[attribute.binding].stride; + + mGl.VertexAttribPointer(attribute.location, + GetNumComponents(attribute.format), + GetGlType(attribute.format), + GL_FALSE, // Not normalized + stride, + reinterpret_cast(attributeOffset)); + } + // Cull face setup + auto& rasterizationState = pipeline->rasterizationState; + if(rasterizationState.cullMode == Graphics::CullMode::NONE) + { + mGl.Disable(GL_CULL_FACE); + } + else + { + mGl.Enable(GL_CULL_FACE); + mGl.CullFace(GetCullFace(rasterizationState.cullMode)); + } - // Blending setup - auto& colorBlendState = commandBuffer->mPipeline->colorBlendState; - if(colorBlendState.blendEnable) - { - mGl.Enable(GL_BLEND); + mGl.FrontFace(GetFrontFace(rasterizationState.frontFace)); + // We don't modify glPolygonMode in our context/abstraction from GL_FILL (the GL default), + // so it isn't present in the API (and won't have any tests!) - mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor), - GetBlendFactor(colorBlendState.dstColorBlendFactor), - GetBlendFactor(colorBlendState.srcAlphaBlendFactor), - GetBlendFactor(colorBlendState.dstAlphaBlendFactor)); - if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp) + // Blending setup + auto& colorBlendState = pipeline->colorBlendState; + if(colorBlendState.blendEnable) { - mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp)); + mGl.Enable(GL_BLEND); + + mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor), + GetBlendFactor(colorBlendState.dstColorBlendFactor), + GetBlendFactor(colorBlendState.srcAlphaBlendFactor), + GetBlendFactor(colorBlendState.dstAlphaBlendFactor)); + if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp) + { + mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp)); + } + else + { + mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp)); + } + mGl.BlendColor(colorBlendState.blendConstants[0], + colorBlendState.blendConstants[1], + colorBlendState.blendConstants[2], + colorBlendState.blendConstants[3]); } else { - mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp)); + mGl.Disable(GL_BLEND); } - mGl.BlendColor(colorBlendState.blendConstants[0], - colorBlendState.blendConstants[1], - colorBlendState.blendConstants[2], - colorBlendState.blendConstants[3]); - } - else - { - mGl.Disable(GL_BLEND); - } - // draw call - auto topology = commandBuffer->mPipeline->inputAssemblyState.topology; + // draw call + auto topology = pipeline->inputAssemblyState.topology; - if(commandBuffer->drawCommand.drawType == TestGraphicsCommandBuffer::Draw::DrawType::Indexed) - { - mGl.DrawElements(GetTopology(topology), - static_cast(commandBuffer->drawCommand.u.indexedDraw.indexCount), - GL_UNSIGNED_SHORT, - reinterpret_cast(commandBuffer->drawCommand.u.indexedDraw.firstIndex)); - } - else - { - mGl.DrawArrays(GetTopology(topology), 0, commandBuffer->drawCommand.u.unindexedDraw.vertexCount); - } + // UniformBuffer binding (once we know pipeline) + auto bindUniformBuffersCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_UNIFORM_BUFFER); + if(!bindUniformBuffersCmds.empty()) + { + auto buffer = bindUniformBuffersCmds[0]->bindUniformBuffers.standaloneUniformsBufferBinding; - // attribute clear - for(auto& attribute : vi.attributes) - { - mGl.DisableVertexAttribArray(attribute.location); + // based on reflection, issue gl calls + buffer.buffer->BindAsUniformBuffer(static_cast(pipeline->programState.program)); + } + + auto drawCmds = commandBuffer->GetCommandsByType(0 | + CommandType::DRAW | + CommandType::DRAW_INDEXED_INDIRECT | + CommandType::DRAW_INDEXED); + + if(!drawCmds.empty()) + { + if(drawCmds[0]->draw.type == DrawCallDescriptor::Type::DRAW_INDEXED) + { + mGl.DrawElements(GetTopology(topology), + static_cast(drawCmds[0]->draw.drawIndexed.indexCount), + GL_UNSIGNED_SHORT, + reinterpret_cast(drawCmds[0]->draw.drawIndexed.firstIndex)); + } + else + { + mGl.DrawArrays(GetTopology(topology), 0, drawCmds[0]->draw.draw.vertexCount); + } + } + // attribute clear + for(auto& attribute : vi.attributes) + { + mGl.DisableVertexAttribArray(attribute.location); + } } } } @@ -737,7 +772,7 @@ Graphics::UniquePtr TestGraphicsController::CreateProgram(con } mProgramCache.emplace_back(); - mProgramCache.back().programImpl = new TestGraphicsProgramImpl(mGl, programCreateInfo, mVertexFormats); + mProgramCache.back().programImpl = new TestGraphicsProgramImpl(mGl, programCreateInfo, mVertexFormats, mCustomUniforms); for(auto& shader : *(programCreateInfo.shaderState)) { auto graphicsShader = Uncast(shader.shader); diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.h index fa2fd63..cbe78ec 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.h +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.h @@ -299,6 +299,11 @@ public: // Test Functions mVertexFormats = vfs; } + void AddCustomUniforms(std::vector& customUniforms) + { + mCustomUniforms = customUniforms; + } + void ClearSubmitStack() { mSubmitStack.clear(); @@ -336,6 +341,8 @@ public: TestGraphicsProgramImpl* programImpl; }; std::vector mProgramCache; + + std::vector mCustomUniforms; }; } // namespace Dali diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-program.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-program.cpp index 9a0afa6..0bf698a 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-program.cpp +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-program.cpp @@ -18,13 +18,16 @@ namespace Dali { -TestGraphicsProgramImpl::TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats) +TestGraphicsProgramImpl::TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats, std::vector& customUniforms) : mGl(gl), mCreateInfo(createInfo), - mReflection(gl, vertexFormats) + mReflection(gl, vertexFormats, createInfo, customUniforms) { mId = mGl.CreateProgram(); - mGl.LinkProgram(1); // Ensure active sampler uniforms are set + + // Ensure active sampler uniforms are set + mGl.SetCustomUniforms(customUniforms); + mGl.LinkProgram(mId); } bool TestGraphicsProgramImpl::GetParameter(uint32_t parameterId, void* outData) @@ -33,9 +36,9 @@ bool TestGraphicsProgramImpl::GetParameter(uint32_t parameterId, void* outData) return true; } -TestGraphicsProgram::TestGraphicsProgram(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats) +TestGraphicsProgram::TestGraphicsProgram(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats, std::vector& customUniforms) { - mImpl = new TestGraphicsProgramImpl(gl, createInfo, vertexFormats); + mImpl = new TestGraphicsProgramImpl(gl, createInfo, vertexFormats, customUniforms); } TestGraphicsProgram::TestGraphicsProgram(TestGraphicsProgramImpl* impl) diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-program.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-program.h index c098718..3aae276 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-program.h +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-program.h @@ -27,7 +27,7 @@ namespace Dali class TestGraphicsProgramImpl { public: - TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats); + TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats, std::vector& customUniforms); // For API const TestGraphicsReflection& GetReflection() const @@ -54,7 +54,7 @@ public: class TestGraphicsProgram : public Graphics::Program { public: - TestGraphicsProgram(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats); + TestGraphicsProgram(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats, std::vector& customUniforms); TestGraphicsProgram(TestGraphicsProgramImpl* impl); const TestGraphicsReflection& GetReflection() const diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp index c9ef2d0..d59f29f 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp @@ -15,12 +15,46 @@ */ #include "test-graphics-reflection.h" -#include +#include "test-graphics-shader.h" +#include +#include +#include namespace Dali { -TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl, Property::Array& vfs) -: mGl(gl) +namespace +{ +static const std::vector UNIFORMS = + { + UniformData("uRendererColor", Property::Type::FLOAT), + UniformData("uCustom", Property::Type::INTEGER), + UniformData("uCustom3", Property::Type::VECTOR3), + UniformData("uFadeColor", Property::Type::VECTOR4), + UniformData("uUniform1", Property::Type::VECTOR4), + UniformData("uUniform2", Property::Type::VECTOR4), + UniformData("uUniform3", Property::Type::VECTOR4), + UniformData("uFadeProgress", Property::Type::FLOAT), + UniformData("uANormalMatrix", Property::Type::MATRIX3), + UniformData("sEffect", Property::Type::FLOAT), + UniformData("sTexture", Property::Type::FLOAT), + UniformData("sTextureRect", Property::Type::FLOAT), + UniformData("sGloss", Property::Type::FLOAT), + UniformData("uColor", Property::Type::VECTOR4), + UniformData("uModelMatrix", Property::Type::MATRIX), + UniformData("uModelView", Property::Type::MATRIX), + UniformData("uMvpMatrix", Property::Type::MATRIX), + UniformData("uNormalMatrix", Property::Type::MATRIX3), + UniformData("uProjection", Property::Type::MATRIX), + UniformData("uSize", Property::Type::VECTOR3), + UniformData("uViewMatrix", Property::Type::MATRIX), + UniformData("uLightCameraProjectionMatrix", Property::Type::MATRIX), + UniformData("uLightCameraViewMatrix", Property::Type::MATRIX), +}; +} + +TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl, Property::Array& vfs, const Graphics::ProgramCreateInfo& createInfo, std::vector& customUniforms) +: mGl(gl), + mCustomUniforms(customUniforms) { for(Property::Array::SizeType i = 0; i < vfs.Count(); ++i) { @@ -37,6 +71,40 @@ TestGraphicsReflection::TestGraphicsReflection(TestGlAbstraction& gl, Property:: } } } + + mDefaultUniformBlock.name = ""; + mDefaultUniformBlock.members = {}; + mDefaultUniformBlock.binding = 0; + mDefaultUniformBlock.size = 64 * (UNIFORMS.size() + mCustomUniforms.size()); + mDefaultUniformBlock.descriptorSet = 0; + mDefaultUniformBlock.members.clear(); + int loc = 0; + for(const auto& data : UNIFORMS) + { + mDefaultUniformBlock.members.emplace_back(); + auto& item = mDefaultUniformBlock.members.back(); + item.name = data.name; + item.binding = 0; + item.offset = loc * 64; + item.location = loc++; + item.bufferIndex = 0; + item.uniformClass = Graphics::UniformClass::UNIFORM; + } + + for(const auto& data : mCustomUniforms) + { + fprintf(stderr, "\ncustom uniforms: %s\n", data.name.c_str()); + mDefaultUniformBlock.members.emplace_back(); + auto& item = mDefaultUniformBlock.members.back(); + item.name = data.name; + item.binding = 0; + item.offset = loc * 64; + item.location = loc++; + item.bufferIndex = 0; + item.uniformClass = Graphics::UniformClass::UNIFORM; + } + + mUniformBlocks.push_back(mDefaultUniformBlock); } uint32_t TestGraphicsReflection::GetVertexAttributeLocation(const std::string& name) const @@ -78,7 +146,7 @@ std::vector TestGraphicsReflection::GetVertexAttributeLocations() cons uint32_t TestGraphicsReflection::GetUniformBlockCount() const { - return 0u; + return mUniformBlocks.size(); } uint32_t TestGraphicsReflection::GetUniformBlockBinding(uint32_t index) const @@ -88,11 +156,36 @@ uint32_t TestGraphicsReflection::GetUniformBlockBinding(uint32_t index) const uint32_t TestGraphicsReflection::GetUniformBlockSize(uint32_t index) const { - return 0u; + // 64 bytes per uniform (64 = 4x4 matrix) + // TODO: fix if array will be used + return 64 * (UNIFORMS.size() + mCustomUniforms.size()); } bool TestGraphicsReflection::GetUniformBlock(uint32_t index, Dali::Graphics::UniformBlockInfo& out) const { + if(index >= mUniformBlocks.size()) + { + return false; + } + + const auto& block = mUniformBlocks[index]; + + out.name = block.name; + out.binding = block.binding; + out.descriptorSet = block.descriptorSet; + auto membersSize = block.members.size(); + out.members.resize(membersSize); + out.size = block.size; + for(auto i = 0u; i < out.members.size(); ++i) + { + const auto& memberUniform = block.members[i]; + out.members[i].name = memberUniform.name; + out.members[i].binding = block.binding; + out.members[i].uniformClass = Graphics::UniformClass::UNIFORM; + out.members[i].offset = memberUniform.offset; + out.members[i].location = memberUniform.location; + } + return true; } @@ -108,17 +201,38 @@ std::string TestGraphicsReflection::GetUniformBlockName(uint32_t blockIndex) con uint32_t TestGraphicsReflection::GetUniformBlockMemberCount(uint32_t blockIndex) const { - return 0u; + if(blockIndex < mUniformBlocks.size()) + { + return static_cast(mUniformBlocks[blockIndex].members.size()); + } + else + { + return 0u; + } } std::string TestGraphicsReflection::GetUniformBlockMemberName(uint32_t blockIndex, uint32_t memberLocation) const { - return std::string{}; + if(blockIndex < mUniformBlocks.size() && memberLocation < mUniformBlocks[blockIndex].members.size()) + { + return mUniformBlocks[blockIndex].members[memberLocation].name; + } + else + { + return std::string(); + } } uint32_t TestGraphicsReflection::GetUniformBlockMemberOffset(uint32_t blockIndex, uint32_t memberLocation) const { - return 0u; + if(blockIndex < mUniformBlocks.size() && memberLocation < mUniformBlocks[blockIndex].members.size()) + { + return mUniformBlocks[blockIndex].members[memberLocation].offset; + } + else + { + return 0u; + } } bool TestGraphicsReflection::GetNamedUniform(const std::string& name, Dali::Graphics::UniformInfo& out) const @@ -136,4 +250,9 @@ Graphics::ShaderLanguage TestGraphicsReflection::GetLanguage() const return Graphics::ShaderLanguage::GLSL_3_1; } +Dali::Property::Type TestGraphicsReflection::GetMemberType(int blockIndex, int location) const +{ + return location < static_cast(UNIFORMS.size()) ? UNIFORMS[location].type : mCustomUniforms[location - UNIFORMS.size()].type; +} + } // namespace Dali diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.h index 9311e07..7af052e 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.h +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-reflection.h @@ -17,6 +17,7 @@ * limitations under the License. */ +#include #include #include "test-gl-abstraction.h" @@ -25,7 +26,7 @@ namespace Dali class TestGraphicsReflection : public Graphics::Reflection { public: - TestGraphicsReflection(TestGlAbstraction& gl, Property::Array& vertexFormats); + TestGraphicsReflection(TestGlAbstraction& gl, Property::Array& vertexFormats, const Graphics::ProgramCreateInfo& createInfo, std::vector& customUniforms); uint32_t GetVertexAttributeLocation(const std::string& name) const override; Dali::Graphics::VertexInputAttributeFormat GetVertexAttributeFormat(uint32_t location) const override; @@ -55,8 +56,14 @@ public: // Test methods } } + Dali::Property::Type GetMemberType(int blockIndex, int location) const; + TestGlAbstraction& mGl; mutable std::vector mAttributes; + std::vector mCustomUniforms; + + Graphics::UniformBlockInfo mDefaultUniformBlock{}; ///< The emulated UBO containing all the standalone uniforms + std::vector mUniformBlocks{}; ///< List of uniform blocks }; } // namespace Dali -- 2.7.4