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-buffer.h"
28 #include "test-graphics-pipeline.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,
50 SET_SCISSOR = 1 << 10,
51 SET_SCISSOR_TEST = 1 << 11,
52 SET_VIEWPORT = 1 << 12,
53 SET_VIEWPORT_TEST = 1 << 13
56 using CommandTypeMask = uint32_t;
58 inline CommandTypeMask operator|(T flags, CommandType bit)
60 return static_cast<CommandTypeMask>(flags) | static_cast<CommandTypeMask>(bit);
64 * @brief Descriptor of single buffer binding within
67 struct VertexBufferBindingDescriptor
69 const TestGraphicsBuffer* buffer{nullptr};
74 * @brief Descriptor of ix buffer binding within
77 struct IndexBufferBindingDescriptor
79 const TestGraphicsBuffer* buffer{nullptr};
81 Graphics::Format format{};
85 * @brief Descriptor of uniform buffer binding within
88 struct UniformBufferBindingDescriptor
90 const TestGraphicsBuffer* buffer{nullptr};
93 bool emulated; ///<true if UBO is emulated for old gfx API
97 * @brief The descriptor of draw call
99 struct DrawCallDescriptor
102 * @brief Enum specifying type of the draw call
108 DRAW_INDEXED_INDIRECT
111 Type type{}; ///< Type of the draw call
114 * Union contains data for all types of draw calls.
119 * @brief Vertex array draw
123 uint32_t vertexCount;
124 uint32_t instanceCount;
125 uint32_t firstVertex;
126 uint32_t firstInstance;
130 * @brief Indexed draw
135 uint32_t instanceCount;
137 int32_t vertexOffset;
138 uint32_t firstInstance;
142 * @brief Indexed draw indirect
146 const TestGraphicsBuffer* buffer;
150 } drawIndexedIndirect;
155 * Command structure allocates memory to store a single command
168 * @brief Copy constructor
169 * @param[in] rhs Command
171 Command(const Command& rhs)
175 case CommandType::BIND_VERTEX_BUFFERS:
177 bindVertexBuffers = rhs.bindVertexBuffers;
180 case CommandType::BIND_INDEX_BUFFER:
182 bindIndexBuffer = rhs.bindIndexBuffer;
185 case CommandType::BIND_SAMPLERS:
187 bindSamplers = rhs.bindSamplers;
190 case CommandType::BIND_TEXTURES:
192 bindTextures = rhs.bindTextures;
195 case CommandType::BIND_PIPELINE:
197 bindPipeline = rhs.bindPipeline;
200 case CommandType::BIND_UNIFORM_BUFFER:
202 bindUniformBuffers = rhs.bindUniformBuffers;
205 case CommandType::DRAW:
207 draw.type = rhs.draw.type;
208 draw.draw = rhs.draw.draw;
211 case CommandType::DRAW_INDEXED:
213 draw.type = rhs.draw.type;
214 draw.drawIndexed = rhs.draw.drawIndexed;
217 case CommandType::DRAW_INDEXED_INDIRECT:
219 draw.type = rhs.draw.type;
220 draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
223 case CommandType::FLUSH:
228 case CommandType::SET_SCISSOR:
230 scissor.region = rhs.scissor.region;
233 case CommandType::SET_SCISSOR_TEST:
235 scissorTest.enable = rhs.scissorTest.enable;
238 case CommandType::SET_VIEWPORT:
240 viewport.region = rhs.viewport.region;
243 case CommandType::SET_VIEWPORT_TEST:
245 viewportTest.enable = rhs.viewportTest.enable;
253 * @brief move constructor
254 * @param[in] rhs Command
256 Command(Command&& rhs) noexcept
260 case CommandType::BIND_VERTEX_BUFFERS:
262 bindVertexBuffers = std::move(rhs.bindVertexBuffers);
265 case CommandType::BIND_INDEX_BUFFER:
267 bindIndexBuffer = rhs.bindIndexBuffer;
270 case CommandType::BIND_UNIFORM_BUFFER:
272 bindUniformBuffers = std::move(rhs.bindUniformBuffers);
275 case CommandType::BIND_SAMPLERS:
277 bindSamplers = std::move(rhs.bindSamplers);
280 case CommandType::BIND_TEXTURES:
282 bindTextures = std::move(rhs.bindTextures);
285 case CommandType::BIND_PIPELINE:
287 bindPipeline = rhs.bindPipeline;
290 case CommandType::DRAW:
292 draw.type = rhs.draw.type;
293 draw.draw = rhs.draw.draw;
296 case CommandType::DRAW_INDEXED:
298 draw.type = rhs.draw.type;
299 draw.drawIndexed = rhs.draw.drawIndexed;
302 case CommandType::DRAW_INDEXED_INDIRECT:
304 draw.type = rhs.draw.type;
305 draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
308 case CommandType::FLUSH:
313 case CommandType::SET_SCISSOR:
315 scissor.region = rhs.scissor.region;
318 case CommandType::SET_SCISSOR_TEST:
320 scissorTest.enable = rhs.scissorTest.enable;
323 case CommandType::SET_VIEWPORT:
325 viewport.region = rhs.viewport.region;
328 case CommandType::SET_VIEWPORT_TEST:
330 viewportTest.enable = rhs.viewportTest.enable;
337 CommandType type{CommandType::FLUSH}; ///< Type of command
343 std::vector<Graphics::TextureBinding> textureBindings;
346 // BindSampler command
349 std::vector<Graphics::SamplerBinding> samplerBindings;
354 using Binding = VertexBufferBindingDescriptor;
355 std::vector<Binding> vertexBufferBindings;
358 struct : public IndexBufferBindingDescriptor
364 std::vector<UniformBufferBindingDescriptor> uniformBufferBindings{};
365 UniformBufferBindingDescriptor standaloneUniformsBufferBinding{};
366 } bindUniformBuffers;
370 const TestGraphicsPipeline* pipeline{nullptr};
373 struct : public DrawCallDescriptor
379 Graphics::Rect2D region;
387 Graphics::Viewport region;
396 class TestGraphicsCommandBuffer : public Graphics::CommandBuffer
399 TestGraphicsCommandBuffer(TraceCallStack& callstack, TestGlAbstraction& glAbstraction);
400 ~TestGraphicsCommandBuffer()
404 void BindVertexBuffers(uint32_t firstBinding,
405 std::vector<const Graphics::Buffer*> buffers,
406 std::vector<uint32_t> offsets) override
408 mCommands.emplace_back();
409 mCommands.back().type = CommandType::BIND_VERTEX_BUFFERS;
410 auto& bindings = mCommands.back().bindVertexBuffers.vertexBufferBindings;
411 if(bindings.size() < firstBinding + buffers.size())
413 bindings.resize(firstBinding + buffers.size());
414 auto index = firstBinding;
415 for(auto& buf : buffers)
417 bindings[index].buffer = static_cast<const TestGraphicsBuffer*>(buf);
418 bindings[index].offset = offsets[index - firstBinding];
422 mCallStack.PushCall("BindVertexBuffers", "");
425 void BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings) override
427 mCommands.emplace_back();
428 auto& cmd = mCommands.back();
429 cmd.type = CommandType::BIND_UNIFORM_BUFFER;
430 auto& bindCmd = cmd.bindUniformBuffers;
431 for(const auto& binding : bindings)
435 auto testBuffer = static_cast<const TestGraphicsBuffer*>(binding.buffer);
436 if(testBuffer->IsCPUAllocated()) // standalone uniforms
438 bindCmd.standaloneUniformsBufferBinding.buffer = testBuffer;
439 bindCmd.standaloneUniformsBufferBinding.offset = binding.offset;
440 bindCmd.standaloneUniformsBufferBinding.binding = binding.binding;
441 bindCmd.standaloneUniformsBufferBinding.emulated = true;
443 else // Bind regular UBO
445 // resize binding slots
446 if(binding.binding >= bindCmd.uniformBufferBindings.size())
448 bindCmd.uniformBufferBindings.resize(binding.binding + 1);
450 auto& slot = bindCmd.uniformBufferBindings[binding.binding];
451 slot.buffer = testBuffer;
452 slot.offset = binding.offset;
453 slot.binding = binding.binding;
454 slot.emulated = false;
458 mCallStack.PushCall("BindUniformBuffers", "");
461 void BindPipeline(const Graphics::Pipeline& pipeline) override
463 mCommands.emplace_back();
464 mCommands.back().type = CommandType::BIND_PIPELINE;
465 mCommands.back().bindPipeline.pipeline = static_cast<const TestGraphicsPipeline*>(&pipeline);
466 mCallStack.PushCall("BindPipeline", "");
469 void BindTextures(std::vector<Graphics::TextureBinding>& textureBindings) override
471 mCommands.emplace_back();
472 mCommands.back().type = CommandType::BIND_TEXTURES;
473 mCommands.back().bindTextures.textureBindings = std::move(textureBindings);
474 mCallStack.PushCall("BindTextures", "");
477 void BindSamplers(std::vector<Graphics::SamplerBinding>& samplerBindings) override
479 mCommands.emplace_back();
480 mCommands.back().bindSamplers.samplerBindings = std::move(samplerBindings);
481 mCallStack.PushCall("BindSamplers", "");
484 void BindPushConstants(void* data,
486 uint32_t binding) override
488 mCallStack.PushCall("BindPushConstants", "");
491 void BindIndexBuffer(const Graphics::Buffer& buffer,
493 Graphics::Format format) override
495 mCommands.emplace_back();
496 mCommands.back().type = CommandType::BIND_INDEX_BUFFER;
497 mCommands.back().bindIndexBuffer.buffer = static_cast<const TestGraphicsBuffer*>(&buffer);
498 mCommands.back().bindIndexBuffer.offset = offset;
499 mCommands.back().bindIndexBuffer.format = format;
500 mCallStack.PushCall("BindIndexBuffer", "");
503 void BeginRenderPass(
504 Graphics::RenderPass& renderPass,
505 Graphics::RenderTarget& renderTarget,
506 Graphics::Extent2D renderArea,
507 std::vector<Graphics::ClearValue> clearValues) override
509 mCallStack.PushCall("BeginRenderPass", "");
513 * @brief Ends current render pass
515 * This command must be issued in order to finalize the render pass.
516 * It's up to the implementation whether anything has to be done but
517 * the Controller may use end RP marker in order to resolve resource
518 * dependencies (for example, to know when target texture is ready
519 * before passing it to another render pass).
521 void EndRenderPass() override
523 mCallStack.PushCall("EndRenderPass", "");
527 uint32_t vertexCount,
528 uint32_t instanceCount,
529 uint32_t firstVertex,
530 uint32_t firstInstance) override
532 mCommands.emplace_back();
533 mCommands.back().type = CommandType::DRAW;
534 auto& cmd = mCommands.back().draw;
535 cmd.type = DrawCallDescriptor::Type::DRAW;
536 cmd.draw.vertexCount = vertexCount;
537 cmd.draw.instanceCount = instanceCount;
538 cmd.draw.firstInstance = firstInstance;
539 cmd.draw.firstVertex = firstVertex;
540 mCallStack.PushCall("Draw", "");
545 uint32_t instanceCount,
547 int32_t vertexOffset,
548 uint32_t firstInstance) override
550 mCommands.emplace_back();
551 mCommands.back().type = CommandType::DRAW_INDEXED;
552 auto& cmd = mCommands.back().draw;
553 cmd.type = DrawCallDescriptor::Type::DRAW_INDEXED;
554 cmd.drawIndexed.firstIndex = firstIndex;
555 cmd.drawIndexed.firstInstance = firstInstance;
556 cmd.drawIndexed.indexCount = indexCount;
557 cmd.drawIndexed.vertexOffset = vertexOffset;
558 cmd.drawIndexed.instanceCount = instanceCount;
559 mCallStack.PushCall("DrawIndexed", "");
562 void DrawIndexedIndirect(
563 Graphics::Buffer& buffer,
566 uint32_t stride) override
568 mCommands.emplace_back();
569 mCommands.back().type = CommandType::DRAW_INDEXED_INDIRECT;
570 auto& cmd = mCommands.back().draw;
571 cmd.type = DrawCallDescriptor::Type::DRAW_INDEXED_INDIRECT;
572 cmd.drawIndexedIndirect.buffer = static_cast<const TestGraphicsBuffer*>(&buffer);
573 cmd.drawIndexedIndirect.offset = offset;
574 cmd.drawIndexedIndirect.drawCount = drawCount;
575 cmd.drawIndexedIndirect.stride = stride;
576 mCallStack.PushCall("DrawIndexedIndirect", "");
579 void Reset() override
582 mCallStack.PushCall("Reset", "");
585 void SetScissor(Graphics::Rect2D value) override
587 TraceCallStack::NamedParams params;
588 params["x"] << value.x;
589 params["y"] << value.y;
590 params["width"] << value.width;
591 params["height"] << value.height;
592 mCallStack.PushCall("SetScissor", params.str(), params);
594 mCommands.emplace_back();
595 mCommands.back().type = CommandType::SET_SCISSOR;
596 mCommands.back().scissor.region = value;
599 void SetScissorTestEnable(bool value) override
601 TraceCallStack::NamedParams params;
602 params["value"] << (value ? "T" : "F");
603 mCallStack.PushCall("SetScissorTestEnable", params.str(), params);
605 mCommands.emplace_back();
606 mCommands.back().type = CommandType::SET_SCISSOR_TEST;
607 mCommands.back().scissorTest.enable = value;
610 void SetViewport(Graphics::Viewport value) override
612 TraceCallStack::NamedParams params;
613 params["x"] << value.x;
614 params["y"] << value.y;
615 params["width"] << value.width;
616 params["height"] << value.height;
617 params["minDepth"] << value.minDepth;
618 params["maxDepth"] << value.maxDepth;
619 mCallStack.PushCall("SetViewport", params.str(), params);
621 mCommands.emplace_back();
622 mCommands.back().type = CommandType::SET_VIEWPORT;
623 mCommands.back().viewport.region = value;
626 void SetViewportEnable(bool value) override
628 TraceCallStack::NamedParams params;
629 params["value"] << (value ? "T" : "F");
630 mCallStack.PushCall("SetViewportEnable", params.str(), params);
632 mCommands.emplace_back();
633 mCommands.back().type = CommandType::SET_VIEWPORT_TEST;
634 mCommands.back().viewportTest.enable = value;
637 [[nodiscard]] const std::vector<Command>& GetCommands() const
643 * Returns number of draw commands
646 int GetDrawCallsCount();
649 * Retrieves state resolve for selected draw call
650 * @param drawCommandIndex
652 void GetStateForDrawCall(int drawCallIndex);
655 * Retrieves commands of specified type
657 std::vector<Command*> GetCommandsByType(CommandTypeMask mask);
660 TraceCallStack& mCallStack;
661 TestGlAbstraction& mGlAbstraction;
663 std::vector<Command> mCommands;
668 #endif //DALI_TEST_GRAPHICS_COMMAND_BUFFER_H