2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "test-graphics-controller.h"
19 #include "test-graphics-buffer.h"
20 #include "test-graphics-command-buffer.h"
21 #include "test-graphics-framebuffer.h"
22 #include "test-graphics-reflection.h"
23 #include "test-graphics-render-pass.h"
24 #include "test-graphics-render-target.h"
25 #include "test-graphics-sampler.h"
26 #include "test-graphics-shader.h"
27 #include "test-graphics-sync-object.h"
28 #include "test-graphics-texture.h"
30 #include <dali/integration-api/gl-defines.h>
39 std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
41 return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size;
44 std::ostream& operator<<(std::ostream& o, const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo)
46 return o << "level:" << (commandBufferCreateInfo.level == Graphics::CommandBufferLevel::PRIMARY ? "PRIMARY" : "SECONDARY")
47 << ", fixedCapacity:" << std::dec << commandBufferCreateInfo.fixedCapacity;
50 std::ostream& operator<<(std::ostream& o, const Graphics::TextureType& textureType)
54 case Graphics::TextureType::TEXTURE_2D:
57 case Graphics::TextureType::TEXTURE_3D:
60 case Graphics::TextureType::TEXTURE_CUBEMAP:
61 o << "TEXTURE_CUBEMAP";
67 std::ostream& operator<<(std::ostream& o, const Graphics::Extent2D extent)
69 o << "width:" << extent.width << ", height:" << extent.height;
73 std::ostream& operator<<(std::ostream& o, const Graphics::TextureCreateInfo& createInfo)
75 o << "textureType:" << createInfo.textureType
76 << " size:" << createInfo.size
77 << " format:" << static_cast<uint32_t>(createInfo.format)
78 << " mipMapFlag:" << createInfo.mipMapFlag
79 << " layout:" << (createInfo.layout == Graphics::TextureLayout::LINEAR ? "LINEAR" : "OPTIMAL")
80 << " usageFlags:" << std::hex << createInfo.usageFlags
81 << " data:" << std::hex << createInfo.data
82 << " dataSize:" << std::dec << createInfo.dataSize
83 << " nativeImagePtr:" << std::hex << createInfo.nativeImagePtr.Get();
87 std::ostream& operator<<(std::ostream& o, Graphics::SamplerAddressMode addressMode)
91 case Graphics::SamplerAddressMode::REPEAT:
94 case Graphics::SamplerAddressMode::MIRRORED_REPEAT:
95 o << "MIRRORED_REPEAT";
97 case Graphics::SamplerAddressMode::CLAMP_TO_EDGE:
100 case Graphics::SamplerAddressMode::CLAMP_TO_BORDER:
101 o << "CLAMP_TO_BORDER";
103 case Graphics::SamplerAddressMode::MIRROR_CLAMP_TO_EDGE:
104 o << "MIRROR_CLAMP_TO_EDGE";
110 std::ostream& operator<<(std::ostream& o, Graphics::SamplerFilter filterMode)
114 case Graphics::SamplerFilter::LINEAR:
117 case Graphics::SamplerFilter::NEAREST:
124 std::ostream& operator<<(std::ostream& o, Graphics::SamplerMipmapMode mipmapMode)
128 case Graphics::SamplerMipmapMode::NONE:
131 case Graphics::SamplerMipmapMode::LINEAR:
134 case Graphics::SamplerMipmapMode::NEAREST:
141 std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& createInfo)
143 o << "minFilter:" << createInfo.minFilter
144 << " magFilter:" << createInfo.magFilter
145 << " wrapModeU:" << createInfo.addressModeU
146 << " wrapModeV:" << createInfo.addressModeV
147 << " wrapModeW:" << createInfo.addressModeW
148 << " mipMapMode:" << createInfo.mipMapMode;
152 std::ostream& operator<<(std::ostream& o, const Graphics::ColorAttachment& colorAttachment)
154 o << "attachmentId:" << colorAttachment.attachmentId
155 << " layerId:" << colorAttachment.layerId
156 << " levelId:" << colorAttachment.levelId
157 << " texture:" << colorAttachment.texture;
161 std::ostream& operator<<(std::ostream& o, const Graphics::DepthStencilAttachment& depthStencilAttachment)
163 o << "depthTexture:" << depthStencilAttachment.depthTexture
164 << "depthLevel:" << depthStencilAttachment.depthLevel
165 << "stencilTexture:" << depthStencilAttachment.stencilTexture
166 << "stencilLevel:" << depthStencilAttachment.stencilLevel;
170 std::ostream& operator<<(std::ostream& o, const Graphics::FramebufferCreateInfo& createInfo)
172 o << "colorAttachments:";
173 for(auto i = 0u; i < createInfo.colorAttachments.size(); ++i)
175 o << "[" << i << "]=" << createInfo.colorAttachments[i] << " ";
177 o << "depthStencilAttachment:" << createInfo.depthStencilAttachment;
178 o << "size: " << createInfo.size;
182 int GetNumComponents(Graphics::VertexInputFormat vertexFormat)
186 case Graphics::VertexInputFormat::UNDEFINED:
187 case Graphics::VertexInputFormat::FLOAT:
188 case Graphics::VertexInputFormat::INTEGER:
190 case Graphics::VertexInputFormat::IVECTOR2:
191 case Graphics::VertexInputFormat::FVECTOR2:
193 case Graphics::VertexInputFormat::IVECTOR3:
194 case Graphics::VertexInputFormat::FVECTOR3:
196 case Graphics::VertexInputFormat::FVECTOR4:
197 case Graphics::VertexInputFormat::IVECTOR4:
203 GLint GetSize(Graphics::VertexInputFormat vertexFormat)
207 case Graphics::VertexInputFormat::UNDEFINED:
209 case Graphics::VertexInputFormat::INTEGER:
210 case Graphics::VertexInputFormat::IVECTOR2:
211 case Graphics::VertexInputFormat::IVECTOR3:
212 case Graphics::VertexInputFormat::IVECTOR4:
214 case Graphics::VertexInputFormat::FLOAT:
215 case Graphics::VertexInputFormat::FVECTOR2:
216 case Graphics::VertexInputFormat::FVECTOR3:
217 case Graphics::VertexInputFormat::FVECTOR4:
223 GLint GetGlType(Graphics::VertexInputFormat vertexFormat)
227 case Graphics::VertexInputFormat::UNDEFINED:
229 case Graphics::VertexInputFormat::INTEGER:
230 case Graphics::VertexInputFormat::IVECTOR2:
231 case Graphics::VertexInputFormat::IVECTOR3:
232 case Graphics::VertexInputFormat::IVECTOR4:
234 case Graphics::VertexInputFormat::FLOAT:
235 case Graphics::VertexInputFormat::FVECTOR2:
236 case Graphics::VertexInputFormat::FVECTOR3:
237 case Graphics::VertexInputFormat::FVECTOR4:
243 GLenum GetTopology(Graphics::PrimitiveTopology topology)
247 case Graphics::PrimitiveTopology::POINT_LIST:
250 case Graphics::PrimitiveTopology::LINE_LIST:
253 case Graphics::PrimitiveTopology::LINE_LOOP:
256 case Graphics::PrimitiveTopology::LINE_STRIP:
257 return GL_LINE_STRIP;
259 case Graphics::PrimitiveTopology::TRIANGLE_LIST:
262 case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
263 return GL_TRIANGLE_STRIP;
265 case Graphics::PrimitiveTopology::TRIANGLE_FAN:
266 return GL_TRIANGLE_FAN;
271 GLenum GetCullFace(Graphics::CullMode cullMode)
275 case Graphics::CullMode::NONE:
277 case Graphics::CullMode::FRONT:
279 case Graphics::CullMode::BACK:
281 case Graphics::CullMode::FRONT_AND_BACK:
282 return GL_FRONT_AND_BACK;
287 GLenum GetFrontFace(Graphics::FrontFace frontFace)
289 if(frontFace == Graphics::FrontFace::CLOCKWISE)
296 GLenum GetBlendFactor(Graphics::BlendFactor blendFactor)
298 GLenum glFactor = GL_ZERO;
302 case Graphics::BlendFactor::ZERO:
305 case Graphics::BlendFactor::ONE:
308 case Graphics::BlendFactor::SRC_COLOR:
309 glFactor = GL_SRC_COLOR;
311 case Graphics::BlendFactor::ONE_MINUS_SRC_COLOR:
312 glFactor = GL_ONE_MINUS_SRC_COLOR;
314 case Graphics::BlendFactor::DST_COLOR:
315 glFactor = GL_DST_COLOR;
317 case Graphics::BlendFactor::ONE_MINUS_DST_COLOR:
318 glFactor = GL_ONE_MINUS_DST_COLOR;
320 case Graphics::BlendFactor::SRC_ALPHA:
321 glFactor = GL_SRC_ALPHA;
323 case Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA:
324 glFactor = GL_ONE_MINUS_SRC_ALPHA;
326 case Graphics::BlendFactor::DST_ALPHA:
327 glFactor = GL_DST_ALPHA;
329 case Graphics::BlendFactor::ONE_MINUS_DST_ALPHA:
330 glFactor = GL_ONE_MINUS_DST_ALPHA;
332 case Graphics::BlendFactor::CONSTANT_COLOR:
333 glFactor = GL_CONSTANT_COLOR;
335 case Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR:
336 glFactor = GL_ONE_MINUS_CONSTANT_COLOR;
338 case Graphics::BlendFactor::CONSTANT_ALPHA:
339 glFactor = GL_CONSTANT_ALPHA;
341 case Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
342 glFactor = GL_ONE_MINUS_CONSTANT_ALPHA;
344 case Graphics::BlendFactor::SRC_ALPHA_SATURATE:
345 glFactor = GL_SRC_ALPHA_SATURATE;
347 // GLES doesn't appear to have dual source blending.
348 case Graphics::BlendFactor::SRC1_COLOR:
349 glFactor = GL_SRC_COLOR;
351 case Graphics::BlendFactor::ONE_MINUS_SRC1_COLOR:
352 glFactor = GL_ONE_MINUS_SRC_COLOR;
354 case Graphics::BlendFactor::SRC1_ALPHA:
355 glFactor = GL_SRC_ALPHA;
357 case Graphics::BlendFactor::ONE_MINUS_SRC1_ALPHA:
358 glFactor = GL_ONE_MINUS_SRC_ALPHA;
364 GLenum GetBlendOp(Graphics::BlendOp blendOp)
366 GLenum op = GL_FUNC_ADD;
369 case Graphics::BlendOp::ADD:
372 case Graphics::BlendOp::SUBTRACT:
373 op = GL_FUNC_SUBTRACT;
375 case Graphics::BlendOp::REVERSE_SUBTRACT:
376 op = GL_FUNC_REVERSE_SUBTRACT;
378 case Graphics::BlendOp::MIN:
381 case Graphics::BlendOp::MAX:
384 case Graphics::BlendOp::MULTIPLY:
389 case Graphics::BlendOp::SCREEN:
394 case Graphics::BlendOp::OVERLAY:
399 case Graphics::BlendOp::DARKEN:
404 case Graphics::BlendOp::LIGHTEN:
409 case Graphics::BlendOp::COLOR_DODGE:
414 case Graphics::BlendOp::COLOR_BURN:
419 case Graphics::BlendOp::HARD_LIGHT:
424 case Graphics::BlendOp::SOFT_LIGHT:
429 case Graphics::BlendOp::DIFFERENCE:
434 case Graphics::BlendOp::EXCLUSION:
439 case Graphics::BlendOp::HUE:
444 case Graphics::BlendOp::SATURATION:
446 op = GL_HSL_SATURATION;
449 case Graphics::BlendOp::COLOR:
454 case Graphics::BlendOp::LUMINOSITY:
456 op = GL_HSL_LUMINOSITY;
465 constexpr explicit GLCompareOp(Graphics::CompareOp compareOp)
469 case Graphics::CompareOp::NEVER:
472 case Graphics::CompareOp::LESS:
475 case Graphics::CompareOp::EQUAL:
478 case Graphics::CompareOp::LESS_OR_EQUAL:
481 case Graphics::CompareOp::GREATER:
484 case Graphics::CompareOp::NOT_EQUAL:
487 case Graphics::CompareOp::GREATER_OR_EQUAL:
490 case Graphics::CompareOp::ALWAYS:
500 constexpr explicit GLStencilOp(Graphics::StencilOp stencilOp)
504 case Graphics::StencilOp::KEEP:
507 case Graphics::StencilOp::ZERO:
510 case Graphics::StencilOp::REPLACE:
513 case Graphics::StencilOp::INCREMENT_AND_CLAMP:
516 case Graphics::StencilOp::DECREMENT_AND_CLAMP:
519 case Graphics::StencilOp::INVERT:
522 case Graphics::StencilOp::INCREMENT_AND_WRAP:
525 case Graphics::StencilOp::DECREMENT_AND_WRAP:
533 class TestGraphicsMemory : public Graphics::Memory
536 TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize)
537 : mCallStack(callStack),
539 mMappedOffset(mappedOffset),
540 mMappedSize(mappedSize),
546 void* LockRegion(uint32_t offset, uint32_t size) override
548 std::ostringstream o;
549 o << offset << ", " << size;
550 mCallStack.PushCall("Memory::LockRegion", o.str());
552 if(offset > mMappedOffset + mMappedSize ||
553 size + offset > mMappedOffset + mMappedSize)
555 fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds");
556 mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing
558 mLockedOffset = offset;
560 return &mBuffer.memory[mMappedOffset + offset];
563 void Unlock(bool flush) override
565 mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush"));
572 void Flush() override
574 mCallStack.PushCall("Memory::Flush", "");
576 mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize);
580 TraceCallStack& mCallStack;
581 TestGraphicsBuffer& mBuffer;
582 uint32_t mMappedOffset;
583 uint32_t mMappedSize;
584 uint32_t mLockedOffset;
585 uint32_t mLockedSize;
588 TestGraphicsController::TestGraphicsController()
589 : mCallStack(false, "TestGraphicsController."),
590 mCommandBufferCallStack(false, "TestCommandBuffer."),
591 mFrameBufferCallStack(false, "TestFrameBuffer.")
593 mCallStack.Enable(true);
594 mCommandBufferCallStack.Enable(true);
595 auto& trace = mGl.GetTextureTrace();
597 trace.EnableLogging(false);
600 void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo)
602 TraceCallStack::NamedParams namedParams;
603 namedParams["submitInfo"] << "cmdBuffer[" << submitInfo.cmdBuffer.size()
604 << "], flags:" << std::hex << submitInfo.flags;
606 mCallStack.PushCall("SubmitCommandBuffers", "", namedParams);
608 mSubmitStack.emplace_back(submitInfo);
610 for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer)
612 auto commandBuffer = Uncast<TestGraphicsCommandBuffer>(graphicsCommandBuffer);
613 ProcessCommandBuffer(*commandBuffer);
617 void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer)
619 bool scissorEnabled = false;
620 TestGraphicsFramebuffer* currentFramebuffer{nullptr};
621 TestGraphicsPipeline* currentPipeline{nullptr};
623 for(auto& cmd : commandBuffer.GetCommands())
628 case CommandType::FLUSH:
630 // Nothing to do here
633 case CommandType::BIND_TEXTURES:
635 for(auto& binding : cmd.data.bindTextures.textureBindings)
639 auto texture = Uncast<TestGraphicsTexture>(binding.texture);
640 texture->Bind(binding.binding);
644 auto sampler = Uncast<TestGraphicsSampler>(binding.sampler);
647 sampler->Apply(texture->GetTarget());
651 texture->Prepare(); // Ensure native texture is ready
656 case CommandType::BIND_VERTEX_BUFFERS:
658 for(auto& binding : cmd.data.bindVertexBuffers.vertexBufferBindings)
660 auto graphicsBuffer = binding.buffer;
661 auto vertexBuffer = Uncast<TestGraphicsBuffer>(graphicsBuffer);
662 vertexBuffer->Bind();
666 case CommandType::BIND_INDEX_BUFFER:
668 auto& indexBufferBinding = cmd.data.bindIndexBuffer;
669 if(indexBufferBinding.buffer)
671 auto buffer = Uncast<TestGraphicsBuffer>(indexBufferBinding.buffer);
676 case CommandType::BIND_UNIFORM_BUFFER:
680 auto& bindings = cmd.data.bindUniformBuffers;
681 auto buffer = bindings.standaloneUniformsBufferBinding;
683 // based on reflection, issue gl calls
684 buffer.buffer->BindAsUniformBuffer(static_cast<const TestGraphicsProgram*>(currentPipeline->programState.program), bindings.standaloneUniformsBufferBinding);
688 case CommandType::BIND_SAMPLERS:
692 case CommandType::BIND_PIPELINE:
694 currentPipeline = Uncast<TestGraphicsPipeline>(cmd.data.bindPipeline.pipeline);
695 BindPipeline(currentPipeline);
698 case CommandType::DRAW_NATIVE:
700 auto info = &cmd.data.draw.drawNative.drawNativeInfo;
702 if(info->glesNativeInfo.eglSharedContextStoragePointer)
704 auto* anyContext = reinterpret_cast<std::any*>(info->glesNativeInfo.eglSharedContextStoragePointer);
705 *anyContext = reinterpret_cast<void*>(0x12345678u);
708 CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
711 case CommandType::DRAW:
715 mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
717 cmd.data.draw.draw.vertexCount);
721 case CommandType::DRAW_INDEXED:
725 mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
726 static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
728 reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
732 case CommandType::DRAW_INDEXED_INDIRECT:
736 mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
737 static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
739 reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
743 case CommandType::SET_SCISSOR:
747 auto& rect = cmd.data.scissor.region;
748 mGl.Scissor(rect.x, rect.y, rect.width, rect.height);
752 case CommandType::SET_SCISSOR_TEST:
754 if(cmd.data.scissorTest.enable)
756 mGl.Enable(GL_SCISSOR_TEST);
757 scissorEnabled = true;
761 mGl.Disable(GL_SCISSOR_TEST);
762 scissorEnabled = false;
766 case CommandType::SET_VIEWPORT_TEST:
770 case CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
772 auto& rect = cmd.data.viewport.region;
773 mGl.Viewport(rect.x, rect.y, rect.width, rect.height);
777 case CommandType::SET_COLOR_MASK:
779 // Set all channels to the same mask
780 const bool mask = cmd.data.colorMask.enabled;
781 mGl.ColorMask(mask, mask, mask, mask);
784 case CommandType::CLEAR_STENCIL_BUFFER:
786 mGl.Clear(GL_STENCIL_BUFFER_BIT);
789 case CommandType::CLEAR_DEPTH_BUFFER:
791 mGl.Clear(GL_DEPTH_BUFFER_BIT);
795 case CommandType::SET_STENCIL_TEST_ENABLE:
797 if(cmd.data.stencilTest.enabled)
799 mGl.Enable(GL_STENCIL_TEST);
803 mGl.Disable(GL_STENCIL_TEST);
808 case CommandType::SET_STENCIL_FUNC:
810 mGl.StencilFunc(GLCompareOp(cmd.data.stencilFunc.compareOp).op,
811 cmd.data.stencilFunc.reference,
812 cmd.data.stencilFunc.compareMask);
816 case CommandType::SET_STENCIL_WRITE_MASK:
818 mGl.StencilMask(cmd.data.stencilWriteMask.mask);
821 case CommandType::SET_STENCIL_OP:
823 mGl.StencilOp(GLStencilOp(cmd.data.stencilOp.failOp).op,
824 GLStencilOp(cmd.data.stencilOp.depthFailOp).op,
825 GLStencilOp(cmd.data.stencilOp.passOp).op);
829 case CommandType::SET_DEPTH_COMPARE_OP:
831 mGl.DepthFunc(GLCompareOp(cmd.data.depth.compareOp).op);
834 case CommandType::SET_DEPTH_TEST_ENABLE:
836 if(cmd.data.depth.testEnabled)
838 mGl.Enable(GL_DEPTH_TEST);
842 mGl.Disable(GL_DEPTH_TEST);
846 case CommandType::SET_DEPTH_WRITE_ENABLE:
848 mGl.DepthMask(cmd.data.depth.writeEnabled);
852 case CommandType::EXECUTE_COMMAND_BUFFERS:
854 // Process secondary command buffers
855 for(auto& buf : cmd.data.executeCommandBuffers.buffers)
857 ProcessCommandBuffer(*Uncast<TestGraphicsCommandBuffer>(buf));
861 case CommandType::BEGIN_RENDER_PASS:
863 auto renderTarget = Uncast<TestGraphicsRenderTarget>(cmd.data.beginRenderPass.renderTarget);
867 auto fb = renderTarget->mCreateInfo.framebuffer;
870 if(currentFramebuffer != fb)
872 currentFramebuffer = Uncast<TestGraphicsFramebuffer>(fb);
873 currentFramebuffer->Bind();
878 mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
883 mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
886 auto& clearValues = cmd.data.beginRenderPass.clearValues;
887 if(clearValues.size() > 0)
889 const auto renderPass = static_cast<TestGraphicsRenderPass*>(cmd.data.beginRenderPass.renderPass);
892 const auto& color0 = renderPass->attachments[0];
894 if(color0.loadOp == Graphics::AttachmentLoadOp::CLEAR)
896 mask |= GL_COLOR_BUFFER_BIT;
898 // Set clear color (todo: cache it!)
899 // Something goes wrong here if Alpha mask is GL_TRUE
900 mGl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
901 mGl.ClearColor(clearValues[0].color.r,
902 clearValues[0].color.g,
903 clearValues[0].color.b,
904 clearValues[0].color.a);
907 // check for depth stencil
908 if(renderPass->attachments.size() > 1)
910 const auto& depthStencil = renderPass->attachments.back();
911 if(depthStencil.loadOp == Graphics::AttachmentLoadOp::CLEAR)
914 uint32_t depthClearColor = 0u;
915 if(clearValues.size() == renderPass->attachments.size())
917 depthClearColor = clearValues.back().depthStencil.depth;
919 mGl.ClearDepthf(depthClearColor);
920 mask |= GL_DEPTH_BUFFER_BIT;
922 if(depthStencil.stencilLoadOp == Graphics::AttachmentLoadOp::CLEAR)
924 uint32_t stencilClearColor = 0u;
925 if(clearValues.size() == renderPass->attachments.size())
927 stencilClearColor = clearValues.back().depthStencil.stencil;
929 mGl.ClearStencil(stencilClearColor);
930 mGl.StencilMask(0xFF); // Clear all the bitplanes (assume 8)
931 mask |= GL_STENCIL_BUFFER_BIT;
937 // Test scissor area and RT size
938 const auto& area = cmd.data.beginRenderPass.renderArea;
942 area.width == renderTarget->mCreateInfo.extent.width &&
943 area.height == renderTarget->mCreateInfo.extent.height)
945 mGl.Disable(GL_SCISSOR_TEST);
950 mGl.Enable(GL_SCISSOR_TEST);
951 mGl.Scissor(cmd.data.beginRenderPass.renderArea.x, cmd.data.beginRenderPass.renderArea.y, cmd.data.beginRenderPass.renderArea.width, cmd.data.beginRenderPass.renderArea.height);
953 mGl.Disable(GL_SCISSOR_TEST);
959 DALI_ASSERT_DEBUG(0 && "BeginRenderPass has no render pass");
964 case CommandType::END_RENDER_PASS:
966 if(cmd.data.endRenderPass.syncObject != nullptr)
968 auto syncObject = Uncast<TestGraphicsSyncObject>(cmd.data.endRenderPass.syncObject);
969 syncObject->InitializeResource(); // create the sync object.
977 void TestGraphicsController::BindPipeline(TestGraphicsPipeline* pipeline)
979 auto& vi = pipeline->vertexInputState;
980 for(auto& attribute : vi.attributes)
982 mGl.EnableVertexAttribArray(attribute.location);
983 uint32_t attributeOffset = attribute.offset;
984 GLsizei stride = vi.bufferBindings[attribute.binding].stride;
986 mGl.VertexAttribPointer(attribute.location,
987 GetNumComponents(attribute.format),
988 GetGlType(attribute.format),
989 GL_FALSE, // Not normalized
991 reinterpret_cast<void*>(attributeOffset));
995 auto& rasterizationState = pipeline->rasterizationState;
996 if(rasterizationState.cullMode == Graphics::CullMode::NONE)
998 mGl.Disable(GL_CULL_FACE);
1002 mGl.Enable(GL_CULL_FACE);
1003 mGl.CullFace(GetCullFace(rasterizationState.cullMode));
1006 mGl.FrontFace(GetFrontFace(rasterizationState.frontFace));
1009 auto& colorBlendState = pipeline->colorBlendState;
1010 if(colorBlendState.blendEnable)
1012 mGl.Enable(GL_BLEND);
1014 mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor),
1015 GetBlendFactor(colorBlendState.dstColorBlendFactor),
1016 GetBlendFactor(colorBlendState.srcAlphaBlendFactor),
1017 GetBlendFactor(colorBlendState.dstAlphaBlendFactor));
1018 if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp)
1020 mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp));
1024 mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp));
1026 mGl.BlendColor(colorBlendState.blendConstants[0],
1027 colorBlendState.blendConstants[1],
1028 colorBlendState.blendConstants[2],
1029 colorBlendState.blendConstants[3]);
1033 mGl.Disable(GL_BLEND);
1036 auto* program = static_cast<const TestGraphicsProgram*>(pipeline->programState.program);
1037 mGl.UseProgram(program->mImpl->mId);
1041 * @brief Presents render target
1042 * @param renderTarget render target to present
1044 void TestGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderTarget)
1046 auto* rt = static_cast<const TestGraphicsRenderTarget*>(renderTarget);
1047 TraceCallStack::NamedParams namedParams;
1048 namedParams["renderTarget"] << std::hex << renderTarget;
1049 namedParams["surface"] << std::hex << rt->mCreateInfo.surface;
1050 mCallStack.PushCall("PresentRenderTarget", namedParams.str(), namedParams);
1054 * @brief Waits until the GPU is idle
1056 void TestGraphicsController::WaitIdle()
1058 mCallStack.PushCall("WaitIdle", "");
1062 * @brief Lifecycle pause event
1064 void TestGraphicsController::Pause()
1066 mCallStack.PushCall("Pause", "");
1070 * @brief Lifecycle resume event
1072 void TestGraphicsController::Resume()
1074 mCallStack.PushCall("Resume", "");
1077 void TestGraphicsController::Shutdown()
1079 mCallStack.PushCall("Shutdown", "");
1082 void TestGraphicsController::Destroy()
1084 mCallStack.PushCall("Destroy", "");
1087 void TestGraphicsController::UpdateTextures(const std::vector<Graphics::TextureUpdateInfo>& updateInfoList,
1088 const std::vector<Graphics::TextureUpdateSourceInfo>& sourceList)
1090 TraceCallStack::NamedParams namedParams;
1091 namedParams["updateInfoList"] << "[" << updateInfoList.size() << "]:";
1092 namedParams["sourceList"] << "[" << sourceList.size() << "]:";
1094 mCallStack.PushCall("UpdateTextures", "", namedParams);
1096 // Call either TexImage2D or TexSubImage2D
1097 for(unsigned int i = 0; i < updateInfoList.size(); ++i)
1099 auto& updateInfo = updateInfoList[i];
1100 auto& source = sourceList[i];
1102 auto texture = static_cast<TestGraphicsTexture*>(updateInfo.dstTexture);
1103 texture->Bind(0); // Use first texture unit during resource update
1104 texture->Update(updateInfo, source);
1108 void TestGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
1110 mCallStack.PushCall("GenerateTextureMipmaps", "");
1112 auto gfxTexture = Uncast<TestGraphicsTexture>(&texture);
1113 mGl.BindTexture(gfxTexture->GetTarget(), 0);
1114 mGl.GenerateMipmap(gfxTexture->GetTarget());
1117 bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil)
1119 TraceCallStack::NamedParams namedParams;
1120 namedParams["enableDepth"] << (enableDepth ? "T" : "F");
1121 namedParams["enableStencil"] << (enableStencil ? "T" : "F");
1122 mCallStack.PushCall("EnableDepthStencilBuffer", "", namedParams);
1126 void TestGraphicsController::RunGarbageCollector(size_t numberOfDiscardedRenderers)
1128 TraceCallStack::NamedParams namedParams;
1129 namedParams["numberOfDiscardedRenderers"] << numberOfDiscardedRenderers;
1130 mCallStack.PushCall("RunGarbageCollector", "", namedParams);
1133 void TestGraphicsController::DiscardUnusedResources()
1135 mCallStack.PushCall("DiscardUnusedResources", "");
1138 bool TestGraphicsController::IsDiscardQueueEmpty()
1140 mCallStack.PushCall("IsDiscardQueueEmpty", "");
1141 return isDiscardQueueEmptyResult;
1145 * @brief Test if the graphics subsystem has resumed & should force a draw
1147 * @return true if the graphics subsystem requires a re-draw
1149 bool TestGraphicsController::IsDrawOnResumeRequired()
1151 mCallStack.PushCall("IsDrawOnResumeRequired", "");
1152 return isDrawOnResumeRequiredResult;
1155 Graphics::UniquePtr<Graphics::Buffer> TestGraphicsController::CreateBuffer(const Graphics::BufferCreateInfo& createInfo, Graphics::UniquePtr<Graphics::Buffer>&& oldBuffer)
1157 std::ostringstream oss;
1158 oss << "bufferCreateInfo:" << createInfo;
1159 mCallStack.PushCall("CreateBuffer", oss.str());
1160 return Graphics::MakeUnique<TestGraphicsBuffer>(mCallStack, mGl, createInfo.size, createInfo.usage);
1163 Graphics::UniquePtr<Graphics::CommandBuffer> TestGraphicsController::CreateCommandBuffer(const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo, Graphics::UniquePtr<Graphics::CommandBuffer>&& oldCommandBuffer)
1165 std::ostringstream oss;
1166 oss << "commandBufferCreateInfo:" << commandBufferCreateInfo;
1167 mCallStack.PushCall("CreateCommandBuffer", oss.str());
1168 return Graphics::MakeUnique<TestGraphicsCommandBuffer>(mCommandBufferCallStack, mGl);
1171 Graphics::UniquePtr<Graphics::RenderPass> TestGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<Graphics::RenderPass>&& oldRenderPass)
1173 mCallStack.PushCall("CreateRenderPass", "");
1174 return Graphics::MakeUnique<TestGraphicsRenderPass>(mGl, renderPassCreateInfo);
1177 Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::CreateTexture(const Graphics::TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Graphics::Texture>&& oldTexture)
1179 TraceCallStack::NamedParams namedParams;
1180 namedParams["textureCreateInfo"] << textureCreateInfo;
1181 mCallStack.PushCall("CreateTexture", namedParams.str(), namedParams);
1183 return Graphics::MakeUnique<TestGraphicsTexture>(mGl, textureCreateInfo);
1186 Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(
1187 const Graphics::FramebufferCreateInfo& createInfo,
1188 Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
1190 TraceCallStack::NamedParams namedParams;
1191 namedParams["framebufferCreateInfo"] << createInfo;
1192 mCallStack.PushCall("Controller::CreateFramebuffer", namedParams.str(), namedParams);
1194 return Graphics::MakeUnique<TestGraphicsFramebuffer>(mFrameBufferCallStack, mGl, createInfo);
1197 Graphics::UniquePtr<Graphics::Pipeline> TestGraphicsController::CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
1199 mCallStack.PushCall("CreatePipeline", "");
1200 return std::make_unique<TestGraphicsPipeline>(mGl, pipelineCreateInfo);
1203 Graphics::UniquePtr<Graphics::Program> TestGraphicsController::CreateProgram(const Graphics::ProgramCreateInfo& programCreateInfo, Graphics::UniquePtr<Graphics::Program>&& oldProgram)
1205 mCallStack.PushCall("CreateProgram", "");
1207 for(auto cacheEntry : mProgramCache)
1210 for(auto& shader : *(programCreateInfo.shaderState))
1212 auto graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
1213 std::vector<uint8_t> source;
1214 source.resize(graphicsShader->mCreateInfo.sourceSize);
1215 memcpy(&source[0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
1217 if(!std::equal(source.begin(), source.end(), cacheEntry.shaders[shader.pipelineStage].begin()))
1225 return Graphics::MakeUnique<TestGraphicsProgram>(cacheEntry.programImpl);
1229 mProgramCache.emplace_back();
1230 mProgramCache.back().programImpl = new TestGraphicsProgramImpl(mGl, programCreateInfo, mVertexFormats, mCustomUniforms);
1231 for(auto& shader : *(programCreateInfo.shaderState))
1233 auto graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
1234 mProgramCache.back().shaders[shader.pipelineStage].resize(graphicsShader->mCreateInfo.sourceSize);
1235 memcpy(&mProgramCache.back().shaders[shader.pipelineStage][0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
1237 return Graphics::MakeUnique<TestGraphicsProgram>(mProgramCache.back().programImpl);
1240 Graphics::UniquePtr<Graphics::Shader> TestGraphicsController::CreateShader(const Graphics::ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Graphics::Shader>&& oldShader)
1242 mCallStack.PushCall("CreateShader", "");
1243 return Graphics::MakeUnique<TestGraphicsShader>(mGl, shaderCreateInfo);
1246 Graphics::UniquePtr<Graphics::Sampler> TestGraphicsController::CreateSampler(const Graphics::SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Graphics::Sampler>&& oldSampler)
1248 TraceCallStack::NamedParams namedParams;
1249 namedParams["samplerCreateInfo"] << samplerCreateInfo;
1250 mCallStack.PushCall("CreateSampler", namedParams.str(), namedParams);
1252 return Graphics::MakeUnique<TestGraphicsSampler>(mGl, samplerCreateInfo);
1255 Graphics::UniquePtr<Graphics::RenderTarget> TestGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget)
1257 TraceCallStack::NamedParams namedParams;
1258 namedParams["surface"] << std::hex << renderTargetCreateInfo.surface;
1259 mCallStack.PushCall("CreateRenderTarget", namedParams.str(), namedParams);
1261 return Graphics::MakeUnique<TestGraphicsRenderTarget>(mGl, renderTargetCreateInfo);
1264 Graphics::UniquePtr<Graphics::SyncObject> TestGraphicsController::CreateSyncObject(
1265 const Graphics::SyncObjectCreateInfo& syncObjectCreateInfo,
1266 Graphics::UniquePtr<Graphics::SyncObject>&& oldSyncObject)
1268 mCallStack.PushCall("CreateSyncObject", "");
1269 return Graphics::MakeUnique<TestGraphicsSyncObject>(mGraphicsSyncImpl, syncObjectCreateInfo);
1272 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapBufferRange(const Graphics::MapBufferInfo& mapInfo)
1274 mCallStack.PushCall("MapBufferRange", "");
1276 auto buffer = static_cast<TestGraphicsBuffer*>(mapInfo.buffer);
1277 buffer->memory.resize(mapInfo.offset + mapInfo.size); // For initial testing, allow writes past capacity
1279 return std::make_unique<TestGraphicsMemory>(mCallStack, *buffer, mapInfo.offset, mapInfo.size);
1282 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapTextureRange(const Graphics::MapTextureInfo& mapInfo)
1284 mCallStack.PushCall("MapTextureRange", "");
1288 void TestGraphicsController::UnmapMemory(Graphics::UniquePtr<Graphics::Memory> memory)
1290 mCallStack.PushCall("UnmapMemory", "");
1293 Graphics::MemoryRequirements TestGraphicsController::GetTextureMemoryRequirements(Graphics::Texture& texture) const
1295 mCallStack.PushCall("GetTextureMemoryRequirements", "");
1296 return Graphics::MemoryRequirements{};
1299 Graphics::MemoryRequirements TestGraphicsController::GetBufferMemoryRequirements(Graphics::Buffer& buffer) const
1301 mCallStack.PushCall("GetBufferMemoryRequirements", "");
1302 return Graphics::MemoryRequirements{};
1305 Graphics::TextureProperties TestGraphicsController::GetTextureProperties(const Graphics::Texture& texture)
1307 static Graphics::TextureProperties textureProperties{};
1308 mCallStack.PushCall("GetTextureProperties", "");
1310 return textureProperties;
1313 const Graphics::Reflection& TestGraphicsController::GetProgramReflection(const Graphics::Program& program)
1315 mCallStack.PushCall("GetProgramReflection", "");
1317 return static_cast<const TestGraphicsProgram*>(&program)->GetReflection();
1320 bool TestGraphicsController::PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const
1322 mCallStack.PushCall("PipelineEquals", "");
1326 bool TestGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData)
1328 mCallStack.PushCall("GetProgramParameter", "");
1329 auto graphicsProgram = Uncast<TestGraphicsProgram>(&program);
1330 return graphicsProgram->GetParameter(parameterId, outData);