UBO support with CPU-backed buffer
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / gles-graphics-command-buffer.h
1 #ifndef DALI_GRAPHICS_GLES_COMMAND_BUFFER_H
2 #define DALI_GRAPHICS_GLES_COMMAND_BUFFER_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <dali/graphics-api/graphics-command-buffer.h>
23
24 // INTERNAL INCLUDES
25 #include "egl-graphics-controller.h"
26 #include "gles-graphics-buffer.h"
27 #include "gles-graphics-pipeline.h"
28 #include "gles-graphics-types.h"
29
30 namespace Dali::Graphics::GLES
31 {
32 class Texture;
33 class Pipeline;
34
35 enum class CommandType
36 {
37   FLUSH,
38   BIND_TEXTURES,
39   BIND_SAMPLERS,
40   BIND_VERTEX_BUFFERS,
41   BIND_INDEX_BUFFER,
42   BIND_UNIFORM_BUFFER,
43   BIND_PIPELINE,
44   DRAW,
45   DRAW_INDEXED,
46   DRAW_INDEXED_INDIRECT
47 };
48
49 /**
50  * Command structure allocates memory to store a single command
51  */
52 struct Command
53 {
54   Command()
55   {
56   }
57
58   ~Command()
59   {
60   }
61
62   /**
63    * @brief Copy constructor
64    * @param[in] rhs Command
65    */
66   Command(const Command& rhs)
67   {
68     switch(rhs.type)
69     {
70       case CommandType::BIND_VERTEX_BUFFERS:
71       {
72         bindVertexBuffers = rhs.bindVertexBuffers;
73         break;
74       }
75       case CommandType::BIND_INDEX_BUFFER:
76       {
77         bindIndexBuffer = rhs.bindIndexBuffer;
78         break;
79       }
80       case CommandType::BIND_SAMPLERS:
81       {
82         bindSamplers = rhs.bindSamplers;
83         break;
84       }
85       case CommandType::BIND_TEXTURES:
86       {
87         bindTextures = rhs.bindTextures;
88         break;
89       }
90       case CommandType::BIND_PIPELINE:
91       {
92         bindPipeline = rhs.bindPipeline;
93         break;
94       }
95       case CommandType::BIND_UNIFORM_BUFFER:
96       {
97         bindUniformBuffers = rhs.bindUniformBuffers;
98         break;
99       }
100       case CommandType::DRAW:
101       {
102         draw.type = rhs.draw.type;
103         draw.draw = rhs.draw.draw;
104         break;
105       }
106       case CommandType::DRAW_INDEXED:
107       {
108         draw.type        = rhs.draw.type;
109         draw.drawIndexed = rhs.draw.drawIndexed;
110         break;
111       }
112       case CommandType::DRAW_INDEXED_INDIRECT:
113       {
114         draw.type                = rhs.draw.type;
115         draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
116         break;
117       }
118       case CommandType::FLUSH:
119       {
120         // Nothing to do
121         break;
122       }
123     }
124     type = rhs.type;
125   }
126
127   /**
128    * @brief Copy constructor
129    * @param[in] rhs Command
130    */
131   Command(Command&& rhs) noexcept
132   {
133     switch(rhs.type)
134     {
135       case CommandType::BIND_VERTEX_BUFFERS:
136       {
137         bindVertexBuffers = std::move(rhs.bindVertexBuffers);
138         break;
139       }
140       case CommandType::BIND_INDEX_BUFFER:
141       {
142         bindIndexBuffer = rhs.bindIndexBuffer;
143         break;
144       }
145       case CommandType::BIND_UNIFORM_BUFFER:
146       {
147         bindUniformBuffers = std::move(rhs.bindUniformBuffers);
148         break;
149       }
150       case CommandType::BIND_SAMPLERS:
151       {
152         bindSamplers = std::move(rhs.bindSamplers);
153         break;
154       }
155       case CommandType::BIND_TEXTURES:
156       {
157         bindTextures = std::move(rhs.bindTextures);
158         break;
159       }
160       case CommandType::BIND_PIPELINE:
161       {
162         bindPipeline = rhs.bindPipeline;
163         break;
164       }
165       case CommandType::DRAW:
166       {
167         draw.type = rhs.draw.type;
168         draw.draw = rhs.draw.draw;
169         break;
170       }
171       case CommandType::DRAW_INDEXED:
172       {
173         draw.type        = rhs.draw.type;
174         draw.drawIndexed = rhs.draw.drawIndexed;
175         break;
176       }
177       case CommandType::DRAW_INDEXED_INDIRECT:
178       {
179         draw.type                = rhs.draw.type;
180         draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
181         break;
182       }
183       case CommandType::FLUSH:
184       {
185         // Nothing to do
186         break;
187       }
188     }
189     type = rhs.type;
190   }
191
192   CommandType type{CommandType::FLUSH}; ///< Type of command
193
194   union
195   {
196     struct
197     {
198       std::vector<Graphics::TextureBinding> textureBindings;
199     } bindTextures{};
200
201     // BindSampler command
202     struct
203     {
204       std::vector<Graphics::SamplerBinding> samplerBindings;
205     } bindSamplers;
206
207     struct
208     {
209       using Binding = GLES::VertexBufferBindingDescriptor;
210       std::vector<Binding> vertexBufferBindings;
211     } bindVertexBuffers;
212
213     struct : public IndexBufferBindingDescriptor
214     {
215     } bindIndexBuffer;
216
217     struct
218     {
219       std::vector<UniformBufferBindingDescriptor> uniformBufferBindings{};
220       UniformBufferBindingDescriptor              standaloneUniformsBufferBinding{};
221     } bindUniformBuffers;
222
223     struct
224     {
225       const GLES::Pipeline* pipeline{nullptr};
226     } bindPipeline;
227
228     struct : public DrawCallDescriptor
229     {
230     } draw;
231   };
232 };
233
234 using CommandBufferResource = Resource<Graphics::CommandBuffer, Graphics::CommandBufferCreateInfo>;
235
236 class CommandBuffer : public CommandBufferResource
237 {
238 public:
239   CommandBuffer(const Graphics::CommandBufferCreateInfo& createInfo, EglGraphicsController& controller)
240   : CommandBufferResource(createInfo, controller)
241   {
242   }
243
244   ~CommandBuffer() override = default;
245
246   void BindVertexBuffers(uint32_t                             firstBinding,
247                          std::vector<const Graphics::Buffer*> buffers,
248                          std::vector<uint32_t>                offsets) override
249   {
250     mCommands.emplace_back();
251     mCommands.back().type = CommandType::BIND_VERTEX_BUFFERS;
252     auto& bindings        = mCommands.back().bindVertexBuffers.vertexBufferBindings;
253     if(bindings.size() < firstBinding + buffers.size())
254     {
255       bindings.resize(firstBinding + buffers.size());
256       auto index = firstBinding;
257       for(auto& buf : buffers)
258       {
259         bindings[index].buffer = static_cast<const GLES::Buffer*>(buf);
260         bindings[index].offset = offsets[index - firstBinding];
261         index++;
262       }
263     }
264   }
265
266   void BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings) override
267   {
268     mCommands.emplace_back();
269     auto& cmd     = mCommands.back();
270     cmd.type      = CommandType::BIND_UNIFORM_BUFFER;
271     auto& bindCmd = cmd.bindUniformBuffers;
272     for(const auto& binding : bindings)
273     {
274       if(binding.buffer)
275       {
276         auto glesBuffer = static_cast<const GLES::Buffer*>(binding.buffer);
277         if(glesBuffer->IsCPUAllocated()) // standalone uniforms
278         {
279           bindCmd.standaloneUniformsBufferBinding.buffer   = glesBuffer;
280           bindCmd.standaloneUniformsBufferBinding.offset   = binding.offset;
281           bindCmd.standaloneUniformsBufferBinding.binding  = binding.binding;
282           bindCmd.standaloneUniformsBufferBinding.emulated = true;
283         }
284         else // Bind regular UBO
285         {
286           // resize binding slots
287           if(binding.binding >= bindCmd.uniformBufferBindings.size())
288           {
289             bindCmd.uniformBufferBindings.resize(binding.binding + 1);
290           }
291           auto& slot    = bindCmd.uniformBufferBindings[binding.binding];
292           slot.buffer   = glesBuffer;
293           slot.offset   = binding.offset;
294           slot.binding  = binding.binding;
295           slot.emulated = false;
296         }
297       }
298     }
299   }
300
301   void BindPipeline(const Graphics::Pipeline& pipeline) override
302   {
303     mCommands.emplace_back();
304     mCommands.back().type                  = CommandType::BIND_PIPELINE;
305     mCommands.back().bindPipeline.pipeline = static_cast<const GLES::Pipeline*>(&pipeline);
306   }
307
308   void BindTextures(std::vector<TextureBinding>& textureBindings) override
309   {
310     mCommands.emplace_back();
311     mCommands.back().type                         = CommandType::BIND_TEXTURES;
312     mCommands.back().bindTextures.textureBindings = std::move(textureBindings);
313   }
314
315   void BindSamplers(std::vector<SamplerBinding>& samplerBindings) override
316   {
317     mCommands.emplace_back();
318     mCommands.back().bindSamplers.samplerBindings = std::move(samplerBindings);
319   }
320
321   void BindPushConstants(void*    data,
322                          uint32_t size,
323                          uint32_t binding) override
324   {
325   }
326
327   void BindIndexBuffer(const Graphics::Buffer& buffer,
328                        uint32_t                offset,
329                        Format                  format) override
330   {
331     mCommands.emplace_back();
332     mCommands.back().type                   = CommandType::BIND_INDEX_BUFFER;
333     mCommands.back().bindIndexBuffer.buffer = static_cast<const GLES::Buffer*>(&buffer);
334     mCommands.back().bindIndexBuffer.offset = offset;
335     mCommands.back().bindIndexBuffer.format = format;
336   }
337
338   void BeginRenderPass(
339     Graphics::RenderPass&   renderPass,
340     Graphics::RenderTarget& renderTarget,
341     Extent2D                renderArea,
342     std::vector<ClearValue> clearValues) override
343   {
344   }
345
346   /**
347    * @brief Ends current render pass
348    *
349    * This command must be issued in order to finalize the render pass.
350    * It's up to the implementation whether anything has to be done but
351    * the Controller may use end RP marker in order to resolve resource
352    * dependencies (for example, to know when target texture is ready
353    * before passing it to another render pass).
354    */
355   void EndRenderPass() override
356   {
357   }
358
359   void Draw(
360     uint32_t vertexCount,
361     uint32_t instanceCount,
362     uint32_t firstVertex,
363     uint32_t firstInstance) override
364   {
365     mCommands.emplace_back();
366     mCommands.back().type  = CommandType::DRAW;
367     auto& cmd              = mCommands.back().draw;
368     cmd.type               = DrawCallDescriptor::Type::DRAW;
369     cmd.draw.vertexCount   = vertexCount;
370     cmd.draw.instanceCount = instanceCount;
371     cmd.draw.firstInstance = firstInstance;
372     cmd.draw.firstVertex   = firstVertex;
373   }
374
375   void DrawIndexed(
376     uint32_t indexCount,
377     uint32_t instanceCount,
378     uint32_t firstIndex,
379     int32_t  vertexOffset,
380     uint32_t firstInstance) override
381   {
382     mCommands.emplace_back();
383     mCommands.back().type         = CommandType::DRAW_INDEXED;
384     auto& cmd                     = mCommands.back().draw;
385     cmd.type                      = DrawCallDescriptor::Type::DRAW_INDEXED;
386     cmd.drawIndexed.firstIndex    = firstIndex;
387     cmd.drawIndexed.firstInstance = firstInstance;
388     cmd.drawIndexed.indexCount    = indexCount;
389     cmd.drawIndexed.vertexOffset  = vertexOffset;
390     cmd.drawIndexed.instanceCount = instanceCount;
391   }
392
393   void DrawIndexedIndirect(
394     Graphics::Buffer& buffer,
395     uint32_t          offset,
396     uint32_t          drawCount,
397     uint32_t          stride) override
398   {
399     mCommands.emplace_back();
400     mCommands.back().type             = CommandType::DRAW_INDEXED_INDIRECT;
401     auto& cmd                         = mCommands.back().draw;
402     cmd.type                          = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT;
403     cmd.drawIndexedIndirect.buffer    = static_cast<const GLES::Buffer*>(&buffer);
404     cmd.drawIndexedIndirect.offset    = offset;
405     cmd.drawIndexedIndirect.drawCount = drawCount;
406     cmd.drawIndexedIndirect.stride    = stride;
407   }
408
409   void Reset() override
410   {
411     mCommands.clear();
412   }
413
414   void SetScissor(Extent2D value) override
415   {
416   }
417
418   void SetScissorTestEnable(bool value) override
419   {
420   }
421
422   void SetViewport(Viewport value) override
423   {
424   }
425
426   void SetViewportEnable(bool value) override
427   {
428   }
429
430   [[nodiscard]] const std::vector<Command>& GetCommands() const
431   {
432     return mCommands;
433   }
434
435   void DestroyResource() override
436   {
437     // Nothing to do
438   }
439
440   bool InitializeResource() override
441   {
442     // Nothing to do
443     return true;
444   }
445
446   void DiscardResource() override
447   {
448     // Nothing to do
449   }
450
451 private:
452   std::vector<Command> mCommands;
453 };
454 } // namespace Dali::Graphics::GLES
455
456 #endif