1 #ifndef DALI_TEST_GRAPHICS_COMMAND_BUFFER_H
2 #define DALI_TEST_GRAPHICS_COMMAND_BUFFER_H
5 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <dali/graphics-api/graphics-command-buffer-create-info.h>
21 #include <dali/graphics-api/graphics-command-buffer.h>
22 #include <dali/graphics-api/graphics-pipeline.h>
23 #include <dali/graphics-api/graphics-types.h>
26 #include "test-gl-abstraction.h"
27 #include "test-graphics-pipeline.h"
28 #include "test-graphics-buffer.h"
29 #include "test-trace-call-stack.h"
33 class TestGraphicsTexture;
34 class TestGraphicsBuffer;
35 class TestGraphicsSampler;
36 class TestGraphicsPipeline;
38 enum class CommandType
41 BIND_TEXTURES = 1 << 1,
42 BIND_SAMPLERS = 1 << 2,
43 BIND_VERTEX_BUFFERS = 1 << 3,
44 BIND_INDEX_BUFFER = 1 << 4,
45 BIND_UNIFORM_BUFFER = 1 << 5,
46 BIND_PIPELINE = 1 << 6,
48 DRAW_INDEXED = 1 << 8,
49 DRAW_INDEXED_INDIRECT = 1 << 9
52 using CommandTypeMask = uint32_t;
54 inline CommandTypeMask operator|(T flags, CommandType bit)
56 return static_cast<CommandTypeMask>(flags) | static_cast<CommandTypeMask>(bit);
60 * @brief Descriptor of single buffer binding within
63 struct VertexBufferBindingDescriptor
65 const TestGraphicsBuffer* buffer{nullptr};
70 * @brief Descriptor of ix buffer binding within
73 struct IndexBufferBindingDescriptor
75 const TestGraphicsBuffer* buffer{nullptr};
77 Graphics::Format format{};
81 * @brief Descriptor of uniform buffer binding within
84 struct UniformBufferBindingDescriptor
86 const TestGraphicsBuffer* buffer{nullptr};
89 bool emulated; ///<true if UBO is emulated for old gfx API
93 * @brief The descriptor of draw call
95 struct DrawCallDescriptor
98 * @brief Enum specifying type of the draw call
104 DRAW_INDEXED_INDIRECT
107 Type type{}; ///< Type of the draw call
110 * Union contains data for all types of draw calls.
115 * @brief Vertex array draw
119 uint32_t vertexCount;
120 uint32_t instanceCount;
121 uint32_t firstVertex;
122 uint32_t firstInstance;
126 * @brief Indexed draw
131 uint32_t instanceCount;
133 int32_t vertexOffset;
134 uint32_t firstInstance;
138 * @brief Indexed draw indirect
142 const TestGraphicsBuffer* buffer;
146 } drawIndexedIndirect;
151 * Command structure allocates memory to store a single command
164 * @brief Copy constructor
165 * @param[in] rhs Command
167 Command(const Command& rhs)
171 case CommandType::BIND_VERTEX_BUFFERS:
173 bindVertexBuffers = rhs.bindVertexBuffers;
176 case CommandType::BIND_INDEX_BUFFER:
178 bindIndexBuffer = rhs.bindIndexBuffer;
181 case CommandType::BIND_SAMPLERS:
183 bindSamplers = rhs.bindSamplers;
186 case CommandType::BIND_TEXTURES:
188 bindTextures = rhs.bindTextures;
191 case CommandType::BIND_PIPELINE:
193 bindPipeline = rhs.bindPipeline;
196 case CommandType::BIND_UNIFORM_BUFFER:
198 bindUniformBuffers = rhs.bindUniformBuffers;
201 case CommandType::DRAW:
203 draw.type = rhs.draw.type;
204 draw.draw = rhs.draw.draw;
207 case CommandType::DRAW_INDEXED:
209 draw.type = rhs.draw.type;
210 draw.drawIndexed = rhs.draw.drawIndexed;
213 case CommandType::DRAW_INDEXED_INDIRECT:
215 draw.type = rhs.draw.type;
216 draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
219 case CommandType::FLUSH:
229 * @brief Copy constructor
230 * @param[in] rhs Command
232 Command(Command&& rhs) noexcept
236 case CommandType::BIND_VERTEX_BUFFERS:
238 bindVertexBuffers = std::move(rhs.bindVertexBuffers);
241 case CommandType::BIND_INDEX_BUFFER:
243 bindIndexBuffer = rhs.bindIndexBuffer;
246 case CommandType::BIND_UNIFORM_BUFFER:
248 bindUniformBuffers = std::move(rhs.bindUniformBuffers);
251 case CommandType::BIND_SAMPLERS:
253 bindSamplers = std::move(rhs.bindSamplers);
256 case CommandType::BIND_TEXTURES:
258 bindTextures = std::move(rhs.bindTextures);
261 case CommandType::BIND_PIPELINE:
263 bindPipeline = rhs.bindPipeline;
266 case CommandType::DRAW:
268 draw.type = rhs.draw.type;
269 draw.draw = rhs.draw.draw;
272 case CommandType::DRAW_INDEXED:
274 draw.type = rhs.draw.type;
275 draw.drawIndexed = rhs.draw.drawIndexed;
278 case CommandType::DRAW_INDEXED_INDIRECT:
280 draw.type = rhs.draw.type;
281 draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
284 case CommandType::FLUSH:
293 CommandType type{CommandType::FLUSH}; ///< Type of command
299 std::vector<Graphics::TextureBinding> textureBindings;
302 // BindSampler command
305 std::vector<Graphics::SamplerBinding> samplerBindings;
310 using Binding = VertexBufferBindingDescriptor;
311 std::vector<Binding> vertexBufferBindings;
314 struct : public IndexBufferBindingDescriptor
320 std::vector<UniformBufferBindingDescriptor> uniformBufferBindings{};
321 UniformBufferBindingDescriptor standaloneUniformsBufferBinding{};
322 } bindUniformBuffers;
326 const TestGraphicsPipeline* pipeline{nullptr};
329 struct : public DrawCallDescriptor
336 class TestGraphicsCommandBuffer : public Graphics::CommandBuffer
339 TestGraphicsCommandBuffer(TraceCallStack& callstack, TestGlAbstraction& glAbstraction);
340 ~TestGraphicsCommandBuffer()
345 void BindVertexBuffers(uint32_t firstBinding,
346 std::vector<const Graphics::Buffer*> buffers,
347 std::vector<uint32_t> offsets) override
349 mCommands.emplace_back();
350 mCommands.back().type = CommandType::BIND_VERTEX_BUFFERS;
351 auto& bindings = mCommands.back().bindVertexBuffers.vertexBufferBindings;
352 if(bindings.size() < firstBinding + buffers.size())
354 bindings.resize(firstBinding + buffers.size());
355 auto index = firstBinding;
356 for(auto& buf : buffers)
358 bindings[index].buffer = static_cast<const TestGraphicsBuffer*>(buf);
359 bindings[index].offset = offsets[index - firstBinding];
363 mCallStack.PushCall("BindVertexBuffers", "");
366 void BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings) override
368 printf("BindUniformBuffers: bindings.size(): %lu\n", bindings.size());
370 mCommands.emplace_back();
371 auto& cmd = mCommands.back();
372 cmd.type = CommandType::BIND_UNIFORM_BUFFER;
373 auto& bindCmd = cmd.bindUniformBuffers;
374 for(const auto& binding : bindings)
378 auto testBuffer = static_cast<const TestGraphicsBuffer*>(binding.buffer);
379 if(testBuffer->IsCPUAllocated()) // standalone uniforms
381 bindCmd.standaloneUniformsBufferBinding.buffer = testBuffer;
382 bindCmd.standaloneUniformsBufferBinding.offset = binding.offset;
383 bindCmd.standaloneUniformsBufferBinding.binding = binding.binding;
384 bindCmd.standaloneUniformsBufferBinding.emulated = true;
386 else // Bind regular UBO
388 // resize binding slots
389 if(binding.binding >= bindCmd.uniformBufferBindings.size())
391 bindCmd.uniformBufferBindings.resize(binding.binding + 1);
393 auto& slot = bindCmd.uniformBufferBindings[binding.binding];
394 slot.buffer = testBuffer;
395 slot.offset = binding.offset;
396 slot.binding = binding.binding;
397 slot.emulated = false;
401 mCallStack.PushCall("BindUniformBuffers", "");
404 void BindPipeline(const Graphics::Pipeline& pipeline) override
406 mCommands.emplace_back();
407 mCommands.back().type = CommandType::BIND_PIPELINE;
408 mCommands.back().bindPipeline.pipeline = static_cast<const TestGraphicsPipeline*>(&pipeline);
409 mCallStack.PushCall("BindPipeline", "");
412 void BindTextures(std::vector<Graphics::TextureBinding>& textureBindings) override
414 mCommands.emplace_back();
415 mCommands.back().type = CommandType::BIND_TEXTURES;
416 mCommands.back().bindTextures.textureBindings = std::move(textureBindings);
417 mCallStack.PushCall("BindTextures", "");
420 void BindSamplers(std::vector<Graphics::SamplerBinding>& samplerBindings) override
422 mCommands.emplace_back();
423 mCommands.back().bindSamplers.samplerBindings = std::move(samplerBindings);
424 mCallStack.PushCall("BindSamplers", "");
427 void BindPushConstants(void* data,
429 uint32_t binding) override
431 mCallStack.PushCall("BindPushConstants", "");
434 void BindIndexBuffer(const Graphics::Buffer& buffer,
436 Graphics::Format format) override
438 mCommands.emplace_back();
439 mCommands.back().type = CommandType::BIND_INDEX_BUFFER;
440 mCommands.back().bindIndexBuffer.buffer = static_cast<const TestGraphicsBuffer*>(&buffer);
441 mCommands.back().bindIndexBuffer.offset = offset;
442 mCommands.back().bindIndexBuffer.format = format;
443 mCallStack.PushCall("BindIndexBuffer", "");
446 void BeginRenderPass(
447 Graphics::RenderPass& renderPass,
448 Graphics::RenderTarget& renderTarget,
449 Graphics::Extent2D renderArea,
450 std::vector<Graphics::ClearValue> clearValues) override
452 mCallStack.PushCall("BeginRenderPass", "");
456 * @brief Ends current render pass
458 * This command must be issued in order to finalize the render pass.
459 * It's up to the implementation whether anything has to be done but
460 * the Controller may use end RP marker in order to resolve resource
461 * dependencies (for example, to know when target texture is ready
462 * before passing it to another render pass).
464 void EndRenderPass() override
466 mCallStack.PushCall("EndRenderPass", "");
470 uint32_t vertexCount,
471 uint32_t instanceCount,
472 uint32_t firstVertex,
473 uint32_t firstInstance) override
475 mCommands.emplace_back();
476 mCommands.back().type = CommandType::DRAW;
477 auto& cmd = mCommands.back().draw;
478 cmd.type = DrawCallDescriptor::Type::DRAW;
479 cmd.draw.vertexCount = vertexCount;
480 cmd.draw.instanceCount = instanceCount;
481 cmd.draw.firstInstance = firstInstance;
482 cmd.draw.firstVertex = firstVertex;
483 mCallStack.PushCall("Draw", "");
488 uint32_t instanceCount,
490 int32_t vertexOffset,
491 uint32_t firstInstance) override
493 mCommands.emplace_back();
494 mCommands.back().type = CommandType::DRAW_INDEXED;
495 auto& cmd = mCommands.back().draw;
496 cmd.type = DrawCallDescriptor::Type::DRAW_INDEXED;
497 cmd.drawIndexed.firstIndex = firstIndex;
498 cmd.drawIndexed.firstInstance = firstInstance;
499 cmd.drawIndexed.indexCount = indexCount;
500 cmd.drawIndexed.vertexOffset = vertexOffset;
501 cmd.drawIndexed.instanceCount = instanceCount;
502 mCallStack.PushCall("DrawIndexed", "");
505 void DrawIndexedIndirect(
506 Graphics::Buffer& buffer,
509 uint32_t stride) override
511 mCommands.emplace_back();
512 mCommands.back().type = CommandType::DRAW_INDEXED_INDIRECT;
513 auto& cmd = mCommands.back().draw;
514 cmd.type = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT;
515 cmd.drawIndexedIndirect.buffer = static_cast<const TestGraphicsBuffer*>(&buffer);
516 cmd.drawIndexedIndirect.offset = offset;
517 cmd.drawIndexedIndirect.drawCount = drawCount;
518 cmd.drawIndexedIndirect.stride = stride;
519 mCallStack.PushCall("DrawIndexedIndirect", "");
522 void Reset() override
525 mCallStack.PushCall("Reset", "");
528 void SetScissor(Graphics::Extent2D value) override
530 mCallStack.PushCall("SetScissor", "");
533 void SetScissorTestEnable(bool value) override
535 mCallStack.PushCall("SetScissorTestEnable", "");
538 void SetViewport(Graphics::Viewport value) override
540 mCallStack.PushCall("SetViewport", "");
543 void SetViewportEnable(bool value) override
545 mCallStack.PushCall("SetViewportEnable", "");
548 [[nodiscard]] const std::vector<Command>& GetCommands() const
554 * Returns number of draw commands
557 int GetDrawCallsCount();
560 * Retrieves state resolve for selected draw call
561 * @param drawCommandIndex
563 void GetStateForDrawCall( int drawCallIndex );
566 * Retrieves commands of specified type
568 std::vector<Command*> GetCommandsByType( CommandTypeMask mask );
572 TraceCallStack& mCallStack;
573 TestGlAbstraction& mGlAbstraction;
574 std::vector<Command> mCommands;
579 #endif //DALI_TEST_GRAPHICS_COMMAND_BUFFER_H