From 32aacd2ba695b6f2ab3b2e73e076d266102c7660 Mon Sep 17 00:00:00 2001 From: Adam Bialogonski Date: Fri, 12 Feb 2021 11:51:30 +0000 Subject: [PATCH] GLES Pipeline and draw call support This patch brings following changes: - Added BindPipeline and Draw(...) commands implementation - Pipeline initial implementation (VertexInputState, InputAssemblyState) - Added Context object to handle a stream of commands - Execution of GL state when draw command issued - Draw calls Draw and DrawIndexed supported Change-Id: Ib5f2841ee84d4dcb8502703fdfa11c1f2b70cb0f --- .../test-graphics-application.h | 2 +- .../dali-graphics/utc-Dali-GraphicsGeometry.cpp | 2 +- .../graphics/gles-impl/egl-graphics-controller.cpp | 57 ++-- .../graphics/gles-impl/egl-graphics-controller.h | 8 +- dali/internal/graphics/gles-impl/file.list | 1 + dali/internal/graphics/gles-impl/gles-context.cpp | 174 +++++++++++++ dali/internal/graphics/gles-impl/gles-context.h | 102 ++++++++ .../gles-impl/gles-graphics-command-buffer.h | 122 +++++++-- .../graphics/gles-impl/gles-graphics-pipeline.cpp | 133 +++++++++- .../graphics/gles-impl/gles-graphics-pipeline.h | 100 +++++-- .../graphics/gles-impl/gles-graphics-resource.h | 13 +- .../graphics/gles-impl/gles-graphics-shader.h | 18 ++ .../graphics/gles-impl/gles-graphics-texture.cpp | 3 +- .../graphics/gles-impl/gles-graphics-types.h | 244 +++++++++++++++++- .../graphics/gles/egl-graphics-controller.h | 286 --------------------- 15 files changed, 901 insertions(+), 364 deletions(-) create mode 100644 dali/internal/graphics/gles-impl/gles-context.cpp create mode 100644 dali/internal/graphics/gles-impl/gles-context.h delete mode 100644 dali/internal/graphics/gles/egl-graphics-controller.h diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-application.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-application.h index afcc1d2..e71ea41 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-application.h +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-application.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/automated-tests/src/dali-graphics/utc-Dali-GraphicsGeometry.cpp b/automated-tests/src/dali-graphics/utc-Dali-GraphicsGeometry.cpp index 85be66d..de8fbc1 100644 --- a/automated-tests/src/dali-graphics/utc-Dali-GraphicsGeometry.cpp +++ b/automated-tests/src/dali-graphics/utc-Dali-GraphicsGeometry.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include //#include diff --git a/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp b/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp index 96ecf93..4f5bee0 100644 --- a/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp +++ b/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp @@ -21,9 +21,9 @@ #include #include #include +#include #include #include - #include namespace Dali::Graphics @@ -89,6 +89,7 @@ T0* CastObject(T1* apiObject) void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction) { mGlAbstraction = &glAbstraction; + mContext = std::make_unique(*this); } void EglGraphicsController::Initialize(Integration::GlSyncAbstraction& glSyncAbstraction, @@ -150,6 +151,11 @@ EglGraphicsController::CreateBuffer(const BufferCreateInfo& bufferCreateInfo, Gr return NewObject(bufferCreateInfo, *this, std::move(oldBuffer)); } +Graphics::UniquePtr EglGraphicsController::CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr&& oldPipeline) +{ + return NewObject(pipelineCreateInfo, *this, std::move(oldPipeline)); +} + void EglGraphicsController::AddTexture(GLES::Texture& texture) { // Assuming we are on the correct context @@ -182,6 +188,9 @@ void EglGraphicsController::ProcessCreateQueues() void EglGraphicsController::ProcessCommandQueues() { + // TODO: command queue per context, sync between queues should be + // done externally + while(!mCommandQueue.empty()) { auto cmdBuf = mCommandQueue.front(); @@ -194,45 +203,49 @@ void EglGraphicsController::ProcessCommandQueues() { case GLES::CommandType::FLUSH: { + // Nothing to do here break; } - - // Bind textures case GLES::CommandType::BIND_TEXTURES: { - for(auto& binding : cmd.bindTextures.textureBindings) - { - static_cast(binding.texture)->Bind(binding); - } + mContext->BindTextures(cmd.bindTextures.textureBindings); break; } - case GLES::CommandType::BIND_VERTEX_BUFFERS: { auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings; - auto index = 0u; - for(auto& binding : bindings) - { - // TODO: this is all wrong, just hack to work with current DALi - if(binding.buffer) - { - CastObject(binding.buffer)->Bind(BufferUsage::VERTEX_BUFFER); - index++; - } - } - + mContext->BindVertexBuffers(bindings); break; } case GLES::CommandType::BIND_INDEX_BUFFER: { - auto buffer = static_cast(cmd.bindIndexBuffer.buffer); - buffer->Bind(BufferUsage::INDEX_BUFFER); + mContext->BindIndexBuffer(cmd.bindIndexBuffer); break; } case GLES::CommandType::BIND_SAMPLERS: { break; } + case GLES::CommandType::BIND_PIPELINE: + { + mContext->BindPipeline(cmd.bindPipeline.pipeline); + break; + } + case GLES::CommandType::DRAW: + { + mContext->Flush(false, cmd.draw); + break; + } + case GLES::CommandType::DRAW_INDEXED: + { + mContext->Flush(false, cmd.draw); + break; + } + case GLES::CommandType::DRAW_INDEXED_INDIRECT: + { + mContext->Flush(false, cmd.draw); + break; + } } } } @@ -302,8 +315,6 @@ void EglGraphicsController::UpdateTextures(const std::vector& // store staging buffer source.memorySource.memory = stagingBuffer; - - printf("Update ptr: %p\n", source.memorySource.memory); break; } case Graphics::TextureUpdateSourceInfo::Type::BUFFER: diff --git a/dali/internal/graphics/gles-impl/egl-graphics-controller.h b/dali/internal/graphics/gles-impl/egl-graphics-controller.h index 75221df..6a1cfa1 100644 --- a/dali/internal/graphics/gles-impl/egl-graphics-controller.h +++ b/dali/internal/graphics/gles-impl/egl-graphics-controller.h @@ -22,6 +22,7 @@ #include // INTERNAL INCLUDES +#include "gles-context.h" #include "gles-graphics-buffer.h" #include "gles-graphics-memory.h" #include "gles-graphics-texture.h" @@ -188,10 +189,7 @@ public: /** * @copydoc Dali::Graphics::CreatePipeline() */ - Graphics::UniquePtr CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr&& oldPipeline) override - { - return nullptr; - } + Graphics::UniquePtr CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr&& oldPipeline) override; /** * @copydoc Dali::Graphics::CreateShader() @@ -416,6 +414,8 @@ private: using TextureUpdateRequest = std::pair; std::queue mTextureUpdateRequests; + + std::unique_ptr mContext{nullptr}; ///< Context object handling command buffers execution }; } // namespace Graphics diff --git a/dali/internal/graphics/gles-impl/file.list b/dali/internal/graphics/gles-impl/file.list index 97ea3da..832ed14 100644 --- a/dali/internal/graphics/gles-impl/file.list +++ b/dali/internal/graphics/gles-impl/file.list @@ -13,5 +13,6 @@ SET( adaptor_graphics_gles_src_files ${adaptor_graphics_gles_src_files} ${adaptor_graphics_dir}/gles-impl/gles-graphics-sampler.cpp ${adaptor_graphics_dir}/gles-impl/gles-graphics-shader.cpp ${adaptor_graphics_dir}/gles-impl/gles-graphics-texture.cpp + ${adaptor_graphics_dir}/gles-impl/gles-context.cpp ) diff --git a/dali/internal/graphics/gles-impl/gles-context.cpp b/dali/internal/graphics/gles-impl/gles-context.cpp new file mode 100644 index 0000000..1522719 --- /dev/null +++ b/dali/internal/graphics/gles-impl/gles-context.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "gles-context.h" +#include +#include +#include "gles-graphics-buffer.h" +#include "gles-graphics-command-buffer.h" +#include "gles-graphics-pipeline.h" + +namespace Dali::Graphics::GLES +{ +struct Context::Impl +{ + Impl(EglGraphicsController& controller) + : mController(controller) + { + } + + ~Impl() = default; + + EglGraphicsController& mController; + + const GLES::Pipeline* mCurrentPipeline{nullptr}; ///< Currently bound pipeline + const GLES::Pipeline* mNewPipeline{nullptr}; ///< New pipeline to be set on flush + + std::vector mCurrentTextureBindings{}; + std::vector mCurrentSamplerBindings{}; + GLES::IndexBufferBindingDescriptor mCurrentIndexBufferBinding{}; + + struct VertexBufferBinding + { + GLES::Buffer* buffer{nullptr}; + uint32_t offset{0u}; + }; + + // Currently bound buffers + std::vector mCurrentVertexBufferBindings{}; +}; + +Context::Context(EglGraphicsController& controller) +{ + mImpl = std::make_unique(controller); +} + +Context::~Context() = default; + +void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall) +{ + auto& gl = *mImpl->mController.GetGL(); + + // Change pipeline + if(mImpl->mNewPipeline) + { + // Execute states if different + mImpl->mCurrentPipeline = mImpl->mNewPipeline; + mImpl->mNewPipeline = nullptr; + } + + // Bind textures + for(const auto& binding : mImpl->mCurrentTextureBindings) + { + gl.ActiveTexture(GL_TEXTURE0 + binding.binding); + gl.BindTexture(GL_TEXTURE_2D, + static_cast(binding.texture) + ->GetGLTexture()); + } + + // for each attribute bind vertices + const auto& pipelineState = mImpl->mCurrentPipeline->GetCreateInfo(); + const auto& vi = pipelineState.vertexInputState; + for(const auto& attr : vi->attributes) + { + // Enable location + gl.EnableVertexAttribArray(attr.location); + const auto& bufferSlot = mImpl->mCurrentVertexBufferBindings[attr.binding]; + const auto& bufferBinding = vi->bufferBindings[attr.binding]; + + auto glesBuffer = bufferSlot.buffer->GetGLBuffer(); + + // Bind buffer + gl.BindBuffer(GL_ARRAY_BUFFER, glesBuffer); + gl.VertexAttribPointer(attr.location, + GLVertexFormat(attr.format).size, + GLVertexFormat(attr.format).format, + GL_FALSE, + bufferBinding.stride, + reinterpret_cast(attr.offset)); + } + + // Resolve topology + const auto& ia = mImpl->mCurrentPipeline->GetCreateInfo().inputAssemblyState; + // Resolve drawcall + + switch(drawCall.type) + { + case DrawCallDescriptor::Type::DRAW: + { + gl.DrawArrays(GLESTopology(ia->topology), + drawCall.draw.firstVertex, + drawCall.draw.vertexCount); + break; + } + case DrawCallDescriptor::Type::DRAW_INDEXED: + { + const auto& binding = mImpl->mCurrentIndexBufferBinding; + const auto* glesBuffer = binding.buffer; + gl.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, glesBuffer->GetGLBuffer()); + auto indexBufferFormat = GLIndexFormat(binding.format).format; + gl.DrawElements(GLESTopology(ia->topology), + drawCall.drawIndexed.indexCount, + indexBufferFormat, + reinterpret_cast(binding.offset)); + break; + } + case DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT: + { + break; + } + } +} + +void Context::BindTextures(const std::vector& bindings) +{ + // for each texture allocate slot + for(const auto& binding : bindings) + { + // Resize binding array if needed + if(mImpl->mCurrentTextureBindings.size() <= binding.binding) + { + mImpl->mCurrentTextureBindings.resize(binding.binding + 1); + } + // Store the binding details + mImpl->mCurrentTextureBindings[binding.binding] = binding; + } +} + +void Context::BindVertexBuffers(const std::vector& bindings) +{ + if(bindings.size() > mImpl->mCurrentVertexBufferBindings.size()) + { + mImpl->mCurrentVertexBufferBindings.resize(bindings.size()); + } + // Copy only set slots + std::copy_if(bindings.begin(), bindings.end(), mImpl->mCurrentVertexBufferBindings.begin(), [](auto& item) { + return (nullptr != item.buffer); + }); +} + +void Context::BindIndexBuffer(const IndexBufferBindingDescriptor& indexBufferBinding) +{ + mImpl->mCurrentIndexBufferBinding = indexBufferBinding; +} + +void Context::BindPipeline(const GLES::Pipeline* newPipeline) +{ + mImpl->mNewPipeline = newPipeline; +} + +} // namespace Dali::Graphics::GLES diff --git a/dali/internal/graphics/gles-impl/gles-context.h b/dali/internal/graphics/gles-impl/gles-context.h new file mode 100644 index 0000000..9ccca2c --- /dev/null +++ b/dali/internal/graphics/gles-impl/gles-context.h @@ -0,0 +1,102 @@ +#ifndef DALI_GRAPHICS_GLES_CONTEXT_H +#define DALI_GRAPHICS_GLES_CONTEXT_H + +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include "gles-graphics-types.h" + +namespace Dali::Graphics +{ +class EglGraphicsController; +namespace GLES +{ +class Pipeline; +class Texture; + +/** + * @brief Context represents single GLES context + */ +class Context +{ +public: + explicit Context(EglGraphicsController& controller); + + ~Context(); + + /** + * @brief Flushes the context + * + * Flushes the context by issuing GL calls to set the required + * state. + * + * @param[in] reset If true then state is reset unconditionally + */ + void Flush(bool reset, const GLES::DrawCallDescriptor& drawCall); + + /** + * @brief Returns context Id + * @return + */ + uint32_t GetContextId() const + { + return 0; + } + + /** + * @brief Binds textures to the context + * + * Bindings are merged, they are resolved at later time + * when the draw call is issued. Then the texture binding + * slots (GL active texture binding) are enabled/disabled accordingly + * to the uniform layout. + * + * @param[in] bindings List of bindings + * + */ + void BindTextures(const std::vector& bindings); + + /** + * @brief Vertex buffers to bind + * + * The bindings are taken from a command buffer being + * currently processed and copied into the local storage. + */ + + void BindVertexBuffers(const std::vector& bindings); + + /** + * @brief Binds index buffer + * + * @param indexBufferBinding + */ + void BindIndexBuffer(const IndexBufferBindingDescriptor& indexBufferBinding); + + /** + * @brief Binds pipeline to the context + * @param newPipeline + */ + void BindPipeline(const GLES::Pipeline* newPipeline); + +private: + struct Impl; + std::unique_ptr mImpl; +}; +} // namespace GLES +} // namespace Dali::Graphics +#endif //DALI_GRAPHICS_GLES_CONTEXT_H diff --git a/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h b/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h index e388cfd..614b066 100644 --- a/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h +++ b/dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h @@ -23,17 +23,15 @@ // INTERNAL INCLUDES #include "egl-graphics-controller.h" +#include "gles-graphics-pipeline.h" +#include "gles-graphics-types.h" -namespace Dali +namespace Dali::Graphics::GLES { -namespace Graphics -{ -namespace GLES -{ -class EglController; class Texture; class Buffer; class Sampler; +class Pipeline; enum class CommandType { @@ -41,7 +39,11 @@ enum class CommandType BIND_TEXTURES, BIND_SAMPLERS, BIND_VERTEX_BUFFERS, - BIND_INDEX_BUFFER + BIND_INDEX_BUFFER, + BIND_PIPELINE, + DRAW, + DRAW_INDEXED, + DRAW_INDEXED_INDIRECT }; /** @@ -85,6 +87,29 @@ struct Command bindTextures = rhs.bindTextures; break; } + case CommandType::BIND_PIPELINE: + { + bindPipeline = rhs.bindPipeline; + break; + } + case CommandType::DRAW: + { + draw.type = rhs.draw.type; + draw.draw = rhs.draw.draw; + break; + } + case CommandType::DRAW_INDEXED: + { + draw.type = rhs.draw.type; + draw.drawIndexed = rhs.draw.drawIndexed; + break; + } + case CommandType::DRAW_INDEXED_INDIRECT: + { + draw.type = rhs.draw.type; + draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect; + break; + } case CommandType::FLUSH: { // Nothing to do @@ -122,6 +147,29 @@ struct Command bindTextures = std::move(rhs.bindTextures); break; } + case CommandType::BIND_PIPELINE: + { + bindPipeline = rhs.bindPipeline; + break; + } + case CommandType::DRAW: + { + draw.type = rhs.draw.type; + draw.draw = rhs.draw.draw; + break; + } + case CommandType::DRAW_INDEXED: + { + draw.type = rhs.draw.type; + draw.drawIndexed = rhs.draw.drawIndexed; + break; + } + case CommandType::DRAW_INDEXED_INDIRECT: + { + draw.type = rhs.draw.type; + draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect; + break; + } case CommandType::FLUSH: { // Nothing to do @@ -131,7 +179,7 @@ struct Command type = rhs.type; } - CommandType type{CommandType::FLUSH}; + CommandType type{CommandType::FLUSH}; ///< Type of command union { @@ -148,20 +196,22 @@ struct Command struct { - struct Binding - { - const Graphics::Buffer* buffer{nullptr}; - uint32_t offset{0u}; - }; + using Binding = GLES::VertexBufferBindingDescriptor; std::vector vertexBufferBindings; } bindVertexBuffers; - struct + struct : public IndexBufferBindingDescriptor { - const Graphics::Buffer* buffer{nullptr}; - uint32_t offset{}; - Graphics::Format format{}; } bindIndexBuffer; + + struct + { + const GLES::Pipeline* pipeline{nullptr}; + } bindPipeline; + + struct : public DrawCallDescriptor + { + } draw; }; }; @@ -175,6 +225,8 @@ public: { } + ~CommandBuffer() override = default; + void BindVertexBuffers(uint32_t firstBinding, std::vector buffers, std::vector offsets) override @@ -188,7 +240,7 @@ public: auto index = firstBinding; for(auto& buf : buffers) { - bindings[index].buffer = buf; + bindings[index].buffer = static_cast(buf); bindings[index].offset = offsets[index - firstBinding]; index++; } @@ -201,6 +253,9 @@ public: void BindPipeline(const Graphics::Pipeline& pipeline) override { + mCommands.emplace_back(); + mCommands.back().type = CommandType::BIND_PIPELINE; + mCommands.back().bindPipeline.pipeline = static_cast(&pipeline); } void BindTextures(std::vector& textureBindings) override @@ -228,7 +283,7 @@ public: { mCommands.emplace_back(); mCommands.back().type = CommandType::BIND_INDEX_BUFFER; - mCommands.back().bindIndexBuffer.buffer = &buffer; + mCommands.back().bindIndexBuffer.buffer = static_cast(&buffer); mCommands.back().bindIndexBuffer.offset = offset; mCommands.back().bindIndexBuffer.format = format; } @@ -260,6 +315,14 @@ public: uint32_t firstVertex, 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; } void DrawIndexed( @@ -269,6 +332,15 @@ public: int32_t vertexOffset, 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; } void DrawIndexedIndirect( @@ -277,6 +349,14 @@ public: uint32_t drawCount, 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; } void Reset(Graphics::CommandBuffer& commandBuffer) override @@ -324,8 +404,6 @@ public: private: std::vector mCommands; }; -} // Namespace GLES -} // Namespace Graphics -} // Namespace Dali +} // namespace Dali::Graphics::GLES #endif \ No newline at end of file diff --git a/dali/internal/graphics/gles-impl/gles-graphics-pipeline.cpp b/dali/internal/graphics/gles-impl/gles-graphics-pipeline.cpp index 210a180..2f31d6e 100644 --- a/dali/internal/graphics/gles-impl/gles-graphics-pipeline.cpp +++ b/dali/internal/graphics/gles-impl/gles-graphics-pipeline.cpp @@ -15,5 +15,136 @@ * */ -// CLASS HEADER #include "gles-graphics-pipeline.h" +#include +#include +#include +#include "egl-graphics-controller.h" +#include "gles-graphics-shader.h" + +namespace Dali::Graphics::GLES +{ +/** + * Copy of pipeline state, can be also used for internal caching + */ +struct Pipeline::PipelineState +{ + PipelineState() = default; + + ColorBlendState colorBlendState; + DepthStencilState depthStencilState; + std::vector shaderState; + ViewportState viewportState; + FramebufferState framebufferState; + RasterizationState rasterizationState; + VertexInputState vertexInputState; + InputAssemblyState inputAssemblyState; +}; + +Pipeline::Pipeline(const Graphics::PipelineCreateInfo& createInfo, Graphics::EglGraphicsController& controller) +: PipelineResource(createInfo, controller) +{ + // the creation is deferred so it's needed to copy certain parts of the CreateInfo structure + mPipelineState = std::make_unique(); + + // Make copies of structured pass by pointers and replace + // stored create info structure fields + CopyStateIfSet(createInfo.inputAssemblyState, mPipelineState->inputAssemblyState, &mCreateInfo.inputAssemblyState); + CopyStateIfSet(createInfo.vertexInputState, mPipelineState->vertexInputState, &mCreateInfo.vertexInputState); + CopyStateIfSet(createInfo.rasterizationState, mPipelineState->rasterizationState, &mCreateInfo.rasterizationState); + CopyStateIfSet(createInfo.framebufferState, mPipelineState->framebufferState, &mCreateInfo.framebufferState); + CopyStateIfSet(createInfo.colorBlendState, mPipelineState->colorBlendState, &mCreateInfo.colorBlendState); + CopyStateIfSet(createInfo.depthStencilState, mPipelineState->depthStencilState, &mCreateInfo.depthStencilState); + CopyStateIfSet(createInfo.shaderState, mPipelineState->shaderState, &mCreateInfo.shaderState); + CopyStateIfSet(createInfo.viewportState, mPipelineState->viewportState, &mCreateInfo.viewportState); +} + +bool Pipeline::InitializeResource() +{ + auto& gl = *GetController().GetGL(); + mGlProgram = gl.CreateProgram(); + + for(auto& shader : mPipelineState->shaderState) + { + // TODO: Compile shader (shouldn't compile if already did so) + const auto glesShader = static_cast(shader.shader); + if(glesShader->Compile()) + { + // Attach shader + gl.AttachShader(mGlProgram, glesShader->GetGLShader()); + } + else + { + // failure + gl.DeleteProgram(mGlProgram); + return false; + } + } + + // Link program + gl.LinkProgram(mGlProgram); + + // Check for errors + // TODO: + + return true; +} + +void Pipeline::DestroyResource() +{ + if(mGlProgram) + { + auto& gl = *GetController().GetGL(); + gl.DeleteProgram(mGlProgram); + } +} + +void Pipeline::DiscardResource() +{ + // Pass program to discard queue +} + +uint32_t Pipeline::GetGLProgram() const +{ + return mGlProgram; +} + +// FIXME: THIS FUNCTION IS NOT IN USE YET, REQUIRES PROPER PIPELINE +void Pipeline::Bind(GLES::Pipeline* prevPipeline) +{ + // Same pipeline to bind, nothing to do + if(prevPipeline == this) + { + return; + } + + auto& gl = *GetController().GetGL(); + + // ------------------ VIEWPORT + + const auto& viewportState = mPipelineState->viewportState; + auto setViewportState = [this, &gl, viewportState]() { + if(viewportState.scissorTestEnable) + { + gl.Enable(GL_SCISSOR_TEST); + const auto& scissor = mPipelineState->viewportState.scissor; + gl.Scissor(scissor.x, scissor.y, scissor.width, scissor.height); + } + else + { + gl.Disable(GL_SCISSOR_TEST); + const auto& scissor = mPipelineState->viewportState.scissor; + gl.Scissor(scissor.x, scissor.y, scissor.width, scissor.height); + } + }; + + // Resolve viewport/scissor state change + ExecuteStateChange(setViewportState, prevPipeline->GetCreateInfo().viewportState, &mPipelineState->viewportState); + + // ---------------------- PROGRAM + auto program = mGlProgram; + + gl.UseProgram(program); +} + +} // namespace Dali::Graphics::GLES \ No newline at end of file diff --git a/dali/internal/graphics/gles-impl/gles-graphics-pipeline.h b/dali/internal/graphics/gles-impl/gles-graphics-pipeline.h index 7ea1309..0f202e1 100644 --- a/dali/internal/graphics/gles-impl/gles-graphics-pipeline.h +++ b/dali/internal/graphics/gles-impl/gles-graphics-pipeline.h @@ -21,6 +21,7 @@ // EXTERNAL INCLUDES #include #include +#include // INTERNAL INCLUDES #include "gles-graphics-resource.h" @@ -34,47 +35,102 @@ class Pipeline : public PipelineResource public: /** * @brief Constructor - * @param[in] createInfo Valid createInfo structure - * @param[in] controller Reference to the controller + * @param[in] createInfo valid TextureCreateInfo structure + * @param[in] controller Reference to the Controller */ - Pipeline(const Graphics::PipelineCreateInfo& createInfo, Graphics::EglGraphicsController& controller) - : PipelineResource(createInfo, controller) - { - } + Pipeline(const Graphics::PipelineCreateInfo& createInfo, Graphics::EglGraphicsController& controller); + + /** + * @brief Destroys all the low-level resources used by the class + */ + void DestroyResource() override; + + /** + * @brief Initializes low-level resources + * + * @return Tron success + */ + bool InitializeResource() override; + + /** + * @brief Discards object + */ + void DiscardResource() override; /** - * @brief Destructor + * @brief returns GL program id + * @return GL program id */ - ~Pipeline() override = default; + [[nodiscard]] uint32_t GetGLProgram() const; /** - * @brief Called when GL resources are destroyed + * @brief Binds pipeline + * + * Binds Pipeline by binding GL program and flushing state. + * + * If previous pipeline specified, it will be used in order to + * avoid redundant state swiches. + * + * @param[in] prevPipeline previous pipeline */ - void DestroyResource() override + void Bind(GLES::Pipeline* prevPipeline); + + /** + * Executes state change function if condition met + */ + template + void ExecuteStateChange(FUNC& func, const STATE* prevPipelineState, const STATE* thisPipelineState) { - // TODO: Implement destroying the resource + if(!prevPipelineState) + { + func(); + } + else + { + // binary test and execute when different + if(memcmp(prevPipelineState, thisPipelineState, sizeof(STATE)) != 0) + { + func(); + } + } } +private: /** - * @brief Called when initializing the resource - * - * @return True on success + * @brief Helper function. Copies state if pointer is set */ - bool InitializeResource() override + template + void CopyStateIfSet(const T* sourceState, T& copyState, T** destState) { - // TODO: Implement initializing resource - return {}; + *destState = nullptr; + if(sourceState) + { + copyState = *sourceState; + *destState = ©State; + } } /** - * @brief Called when UniquePtr<> on client-side dies + * @brief Helper function. Copies const state if pointer is set */ - void DiscardResource() override + template + void CopyStateIfSet(const T* sourceState, T& copyState, const T** destState) { - // TODO: Implement moving to the discard queue + *destState = nullptr; + if(sourceState) + { + copyState = *sourceState; + *destState = ©State; + } } + + // Pipeline state is stored as a copy of create info + // data. + struct PipelineState; + std::unique_ptr mPipelineState{}; + + uint32_t mGlProgram{0u}; }; } // namespace Dali::Graphics::GLES - -#endif +#endif \ No newline at end of file diff --git a/dali/internal/graphics/gles-impl/gles-graphics-resource.h b/dali/internal/graphics/gles-impl/gles-graphics-resource.h index 3b132a5..ed0e297 100644 --- a/dali/internal/graphics/gles-impl/gles-graphics-resource.h +++ b/dali/internal/graphics/gles-impl/gles-graphics-resource.h @@ -27,8 +27,8 @@ namespace GLES /** * @brief Base class for the Graphics resource. */ -template -class Resource : public T +template +class Resource : public BASE { public: /** @@ -88,6 +88,15 @@ public: */ virtual void DiscardResource() = 0; + /** + * @brief returns pointer to base + * @return + */ + BASE* GetBase() + { + return this; + } + protected: CreateInfo mCreateInfo; ///< CreateInfo structure Graphics::EglGraphicsController& mController; ///< Reference to the Controller object diff --git a/dali/internal/graphics/gles-impl/gles-graphics-shader.h b/dali/internal/graphics/gles-impl/gles-graphics-shader.h index af3d68d..ece9c89 100644 --- a/dali/internal/graphics/gles-impl/gles-graphics-shader.h +++ b/dali/internal/graphics/gles-impl/gles-graphics-shader.h @@ -67,12 +67,30 @@ public: } /** + * @brief Compiles shader + * @return + */ + bool Compile() const + { + mGlShader = 0; + return true; + } + + /** * @brief Called when UniquePtr<> on client-side dies */ void DiscardResource() override { // TODO: Implement moving to the discard queue } + + uint32_t GetGLShader() const + { + return mGlShader; + } + +private: + mutable uint32_t mGlShader; }; } // namespace Dali::Graphics::GLES diff --git a/dali/internal/graphics/gles-impl/gles-graphics-texture.cpp b/dali/internal/graphics/gles-impl/gles-graphics-texture.cpp index 70db172..f267c7f 100644 --- a/dali/internal/graphics/gles-impl/gles-graphics-texture.cpp +++ b/dali/internal/graphics/gles-impl/gles-graphics-texture.cpp @@ -58,7 +58,8 @@ bool Texture::InitializeResource() { Graphics::GLES::GLTextureFormatType format(mCreateInfo.format); - if(format.format && format.type) + // TODO: find better condition, with this test the L8 doesn't work + if(1) //format.format && format.type) { // Bind texture gl->GenTextures(1, &texture); diff --git a/dali/internal/graphics/gles-impl/gles-graphics-types.h b/dali/internal/graphics/gles-impl/gles-graphics-types.h index 8f203d6..e7784c6 100644 --- a/dali/internal/graphics/gles-impl/gles-graphics-types.h +++ b/dali/internal/graphics/gles-impl/gles-graphics-types.h @@ -8,6 +8,7 @@ namespace Dali::Graphics::GLES { +class Buffer; // Conversion functions /** * Stucture delivers format and type that can be used @@ -33,7 +34,7 @@ struct GLTextureFormatType // Luminance formats case Graphics::Format::L8: { - Assign(0, 0); + Assign(GL_RED, GL_UNSIGNED_BYTE); break; } case Graphics::Format::L8A8: @@ -338,6 +339,7 @@ struct GLTextureFormatType Assign(0, 0); break; } + // TBD which of the formats are supported case Graphics::Format::A2R10G10B10_UNORM_PACK32: { @@ -1093,6 +1095,246 @@ struct GLSamplerFilterAndMipMapMode uint32_t glFilter{0}; }; +/** Converts vertex format to GL */ +struct GLVertexFormat +{ + constexpr explicit GLVertexFormat(Graphics::VertexInputFormat gfxFormat) + { + switch(gfxFormat) + { + case VertexInputFormat::FVECTOR2: + { + format = GL_FLOAT; + size = 2; + break; + } + case VertexInputFormat::FVECTOR3: + { + format = GL_FLOAT; + size = 3; + break; + } + case VertexInputFormat::FVECTOR4: + { + format = GL_FLOAT; + size = 4; + break; + } + case VertexInputFormat::FLOAT: + { + format = GL_FLOAT; + size = 1; + break; + } + case VertexInputFormat::INTEGER: + { + format = GL_INT; + size = 1; + break; + } + case VertexInputFormat::IVECTOR2: + { + format = GL_INT; + size = 2; + break; + } + case VertexInputFormat::IVECTOR3: + { + format = GL_INT; + size = 3; + break; + } + case VertexInputFormat::IVECTOR4: + { + format = GL_INT; + size = 4; + break; + } + case VertexInputFormat::UNDEFINED: + { + format = 0; + size = 0; + break; + } + } + } + + GLenum format{0u}; + uint32_t size{0u}; +}; + +/** + * @brief Descriptor of single buffer binding within + * command buffer. + */ +struct VertexBufferBindingDescriptor +{ + const GLES::Buffer* buffer{nullptr}; + uint32_t offset{0u}; +}; + +/** + * @brief Descriptor of ix buffer binding within + * command buffer. + */ +struct IndexBufferBindingDescriptor +{ + const GLES::Buffer* buffer{nullptr}; + uint32_t offset{}; + Graphics::Format format{}; +}; + +/** + * @brief The descriptor of draw call + */ +struct DrawCallDescriptor +{ + /** + * @brief Enum specifying type of the draw call + */ + enum class Type + { + DRAW, + DRAW_INDEXED, + DRAW_INDEXED_INDIRECT + }; + + Type type{}; ///< Type of the draw call + + /** + * Union contains data for all types of draw calls. + */ + union + { + /** + * @brief Vertex array draw + */ + struct + { + uint32_t vertexCount; + uint32_t instanceCount; + uint32_t firstVertex; + uint32_t firstInstance; + } draw; + + /** + * @brief Indexed draw + */ + struct + { + uint32_t indexCount; + uint32_t instanceCount; + uint32_t firstIndex; + int32_t vertexOffset; + uint32_t firstInstance; + } drawIndexed; + + /** + * @brief Indexed draw indirect + */ + struct + { + const GLES::Buffer* buffer; + uint32_t offset; + uint32_t drawCount; + uint32_t stride; + } drawIndexedIndirect; + }; +}; + +/** + * @brief Topologu conversion from Graphics to GLES + */ +struct GLESTopology +{ + explicit constexpr GLESTopology(PrimitiveTopology topology) + { + switch(topology) + { + case PrimitiveTopology::POINT_LIST: + { + primitiveTopology = GL_POINTS; + break; + } + case PrimitiveTopology::LINE_LIST: + { + primitiveTopology = GL_LINES; + break; + } + case PrimitiveTopology::LINE_LOOP: + { + primitiveTopology = GL_LINE_LOOP; + break; + } + case PrimitiveTopology::LINE_STRIP: + { + primitiveTopology = GL_LINE_STRIP; + break; + } + case PrimitiveTopology::TRIANGLE_LIST: + { + primitiveTopology = GL_TRIANGLES; + break; + } + case PrimitiveTopology::TRIANGLE_STRIP: + { + primitiveTopology = GL_TRIANGLE_STRIP; + break; + } + case PrimitiveTopology::TRIANGLE_FAN: + { + primitiveTopology = GL_TRIANGLE_FAN; + break; + } + } + } + + /** + * @brief Explicit type conversion operator + * @return converted value + */ + constexpr inline operator GLenum() const + { + return primitiveTopology; + } + + GLenum primitiveTopology{0}; ///< Topology +}; + +/** + * @brief Index format conversion structure + */ +struct GLIndexFormat +{ + explicit constexpr GLIndexFormat(Format _format) + { + switch(_format) + { + // TODO: add more formats + case Format::R16_UINT: + { + format = GL_UNSIGNED_SHORT; + break; + } + default: + { + format = 0; + } + } + } + + /** + * @brief Explicit type conversion operator + * @return converted value + */ + constexpr inline operator GLenum() const + { + return format; + } + + GLenum format{0}; ///< Converted format +}; + } // namespace Dali::Graphics::GLES #endif //DALI_GRAPHICS_API_TYPES_H diff --git a/dali/internal/graphics/gles/egl-graphics-controller.h b/dali/internal/graphics/gles/egl-graphics-controller.h deleted file mode 100644 index 5345b63..0000000 --- a/dali/internal/graphics/gles/egl-graphics-controller.h +++ /dev/null @@ -1,286 +0,0 @@ -#ifndef DALI_EGL_GRAPHICS_CONTROLLER_H -#define DALI_EGL_GRAPHICS_CONTROLLER_H - -/* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -namespace Dali -{ -namespace Integration -{ -class GlAbstraction; -class GlSyncAbstraction; -class GlContextHelperAbstraction; -} // namespace Integration - -namespace Graphics -{ -/** - * EGL Implementation of the graphics controller. - * - * Temporarily holds the old GL abstractions whilst dali-core is migrated to the new API. - */ -DALI_IMPORT_API class EglGraphicsController : public Graphics::Controller -{ -public: - EglGraphicsController() = default; - - ~EglGraphicsController() override = default; - - /** - * Initialize the GLES abstraction. This can be called from the main thread. - */ - void InitializeGLES(Integration::GlAbstraction& glAbstraction); - - /** - * Initialize with a reference to the GL abstractions. - * - * Note, this is now executed in the render thread, after core initialization - */ - void Initialize(Integration::GlSyncAbstraction& glSyncAbstraction, - Integration::GlContextHelperAbstraction& glContextHelperAbstraction); - - Integration::GlAbstraction& GetGlAbstraction() override; - Integration::GlSyncAbstraction& GetGlSyncAbstraction() override; - Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override; - - /** - * @copydoc Dali::Graphics::SubmitCommandBuffers() - */ - void SubmitCommandBuffers(const SubmitInfo& submitInfo) override - { - } - - /** - * @copydoc Dali::Graphics::PresentRenderTarget() - */ - void PresentRenderTarget(RenderTarget* renderTarget) override - { - } - - /** - * @copydoc Dali::Graphics::WaitIdle() - */ - void WaitIdle() override - { - } - - /** - * @copydoc Dali::Graphics::Pause() - */ - void Pause() override - { - } - - /** - * @copydoc Dali::Graphics::Resume() - */ - void Resume() override - { - } - - /** - * @copydoc Dali::Graphics::UpdateTextures() - */ - void UpdateTextures(const std::vector& updateInfoList, - const std::vector& sourceList) override - { - } - - /** - * @copydoc Dali::Graphics::EnableDepthStencilBuffer() - */ - bool EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) override - { - return {}; - } - - /** - * @copydoc Dali::Graphics::RunGarbageCollector() - */ - void RunGarbageCollector(size_t numberOfDiscardedRenderers) override - { - } - - /** - * @copydoc Dali::Graphics::DiscardUnusedResources() - */ - void DiscardUnusedResources() override - { - } - - /** - * @copydoc Dali::Graphics::IsDiscardQueueEmpty() - */ - bool IsDiscardQueueEmpty() override - { - return {}; - } - - /** - * @copydoc Dali::Graphics::IsDrawOnResumeRequired() - */ - bool IsDrawOnResumeRequired() override - { - return {}; - } - - /** - * @copydoc Dali::Graphics::CreateBuffer() - */ - Graphics::UniquePtr CreateBuffer(const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr&& oldBuffer) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::CreateCommandBuffer() - */ - Graphics::UniquePtr CreateCommandBuffer(const CommandBufferCreateInfo& commandBufferCreateInfo, Graphics::UniquePtr&& oldCommandBuffer) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::CreateRenderPass() - */ - Graphics::UniquePtr CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr&& oldRenderPass) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::CreateTexture() - */ - Graphics::UniquePtr CreateTexture(const TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr&& oldTexture) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::CreateFramebuffer() - */ - Graphics::UniquePtr CreateFramebuffer(const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr&& oldFramebuffer) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::CreatePipeline() - */ - Graphics::UniquePtr CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr&& oldPipeline) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::CreateShader() - */ - Graphics::UniquePtr CreateShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr&& oldShader) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::CreateSampler() - */ - Graphics::UniquePtr CreateSampler(const SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr&& oldSampler) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::CreateRenderTarget() - */ - Graphics::UniquePtr CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr&& oldRenderTarget) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::MapBufferRange() - */ - Graphics::UniquePtr MapBufferRange(const MapBufferInfo& mapInfo) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::MapTextureRange() - */ - Graphics::UniquePtr MapTextureRange(const MapTextureInfo& mapInfo) override - { - return nullptr; - } - - /** - * @copydoc Dali::Graphics::UnmapMemory() - */ - void UnmapMemory(Graphics::UniquePtr memory) override - { - } - /** - * @copydoc Dali::Graphics::GetTextureMemoryRequirements() - */ - MemoryRequirements GetTextureMemoryRequirements(Texture& texture) const override - { - return {}; - } - - /** - * @copydoc Dali::Graphics::GetBufferMemoryRequirements() - */ - MemoryRequirements GetBufferMemoryRequirements(Buffer& buffer) const override - { - return {}; - } - - /** - * @copydoc Dali::Graphics::GetTextureProperties() - */ - const TextureProperties& GetTextureProperties(const Texture& texture) override - { - // for compiler not to moan - static TextureProperties dummy{}; - return dummy; - } - - /** - * @copydoc Dali::Graphics::PipelineEquals() - */ - [[nodiscard]] bool PipelineEquals(const Pipeline& pipeline0, const Pipeline& pipeline1) const override - { - return {}; - } - - [[nodiscard]] Integration::GlAbstraction* GetGL() const - { - return mGlAbstraction; - } - -private: - Integration::GlAbstraction* mGlAbstraction{nullptr}; - Integration::GlSyncAbstraction* mGlSyncAbstraction{nullptr}; - Integration::GlContextHelperAbstraction* mGlContextHelperAbstraction{nullptr}; -}; - -} // namespace Graphics - -} // namespace Dali - -#endif //DALI_EGL_GRAPHICS_CONTROLLER_H -- 2.7.4