2 * Copyright (c) 2021 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>
37 std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
39 return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size;
42 std::ostream& operator<<(std::ostream& o, const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo)
44 return o << "level:" << (commandBufferCreateInfo.level == Graphics::CommandBufferLevel::PRIMARY ? "PRIMARY" : "SECONDARY")
45 << ", fixedCapacity:" << std::dec << commandBufferCreateInfo.fixedCapacity;
48 std::ostream& operator<<(std::ostream& o, const Graphics::TextureType& textureType)
52 case Graphics::TextureType::TEXTURE_2D:
55 case Graphics::TextureType::TEXTURE_3D:
58 case Graphics::TextureType::TEXTURE_CUBEMAP:
59 o << "TEXTURE_CUBEMAP";
65 std::ostream& operator<<(std::ostream& o, const Graphics::Extent2D extent)
67 o << "width:" << extent.width << ", height:" << extent.height;
71 std::ostream& operator<<(std::ostream& o, const Graphics::TextureCreateInfo& createInfo)
73 o << "textureType:" << createInfo.textureType
74 << " size:" << createInfo.size
75 << " format:" << static_cast<uint32_t>(createInfo.format)
76 << " mipMapFlag:" << createInfo.mipMapFlag
77 << " layout:" << (createInfo.layout == Graphics::TextureLayout::LINEAR ? "LINEAR" : "OPTIMAL")
78 << " usageFlags:" << std::hex << createInfo.usageFlags
79 << " data:" << std::hex << createInfo.data
80 << " dataSize:" << std::dec << createInfo.dataSize
81 << " nativeImagePtr:" << std::hex << createInfo.nativeImagePtr;
85 std::ostream& operator<<(std::ostream& o, Graphics::SamplerAddressMode addressMode)
89 case Graphics::SamplerAddressMode::REPEAT:
92 case Graphics::SamplerAddressMode::MIRRORED_REPEAT:
93 o << "MIRRORED_REPEAT";
95 case Graphics::SamplerAddressMode::CLAMP_TO_EDGE:
98 case Graphics::SamplerAddressMode::CLAMP_TO_BORDER:
99 o << "CLAMP_TO_BORDER";
101 case Graphics::SamplerAddressMode::MIRROR_CLAMP_TO_EDGE:
102 o << "MIRROR_CLAMP_TO_EDGE";
108 std::ostream& operator<<(std::ostream& o, Graphics::SamplerFilter filterMode)
112 case Graphics::SamplerFilter::LINEAR:
115 case Graphics::SamplerFilter::NEAREST:
122 std::ostream& operator<<(std::ostream& o, Graphics::SamplerMipmapMode mipmapMode)
126 case Graphics::SamplerMipmapMode::NONE:
129 case Graphics::SamplerMipmapMode::LINEAR:
132 case Graphics::SamplerMipmapMode::NEAREST:
139 std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& createInfo)
141 o << "minFilter:" << createInfo.minFilter
142 << " magFilter:" << createInfo.magFilter
143 << " wrapModeU:" << createInfo.addressModeU
144 << " wrapModeV:" << createInfo.addressModeV
145 << " wrapModeW:" << createInfo.addressModeW
146 << " mipMapMode:" << createInfo.mipMapMode;
150 std::ostream& operator<<(std::ostream& o, const Graphics::ColorAttachment& colorAttachment)
152 o << "attachmentId:" << colorAttachment.attachmentId
153 << " layerId:" << colorAttachment.layerId
154 << " levelId:" << colorAttachment.levelId
155 << " texture:" << colorAttachment.texture;
159 std::ostream& operator<<(std::ostream& o, const Graphics::DepthStencilAttachment& depthStencilAttachment)
161 o << "depthTexture:" << depthStencilAttachment.depthTexture
162 << "depthLevel:" << depthStencilAttachment.depthLevel
163 << "stencilTexture:" << depthStencilAttachment.stencilTexture
164 << "stencilLevel:" << depthStencilAttachment.stencilLevel;
168 std::ostream& operator<<(std::ostream& o, const Graphics::FramebufferCreateInfo& createInfo)
170 o << "colorAttachments:";
171 for(auto i = 0u; i < createInfo.colorAttachments.size(); ++i)
173 o << "[" << i << "]=" << createInfo.colorAttachments[i] << " ";
175 o << "depthStencilAttachment:" << createInfo.depthStencilAttachment;
176 o << "size: " << createInfo.size;
180 int GetNumComponents(Graphics::VertexInputFormat vertexFormat)
184 case Graphics::VertexInputFormat::UNDEFINED:
185 case Graphics::VertexInputFormat::FLOAT:
186 case Graphics::VertexInputFormat::INTEGER:
188 case Graphics::VertexInputFormat::IVECTOR2:
189 case Graphics::VertexInputFormat::FVECTOR2:
191 case Graphics::VertexInputFormat::IVECTOR3:
192 case Graphics::VertexInputFormat::FVECTOR3:
194 case Graphics::VertexInputFormat::FVECTOR4:
195 case Graphics::VertexInputFormat::IVECTOR4:
201 GLint GetSize(Graphics::VertexInputFormat vertexFormat)
205 case Graphics::VertexInputFormat::UNDEFINED:
207 case Graphics::VertexInputFormat::INTEGER:
208 case Graphics::VertexInputFormat::IVECTOR2:
209 case Graphics::VertexInputFormat::IVECTOR3:
210 case Graphics::VertexInputFormat::IVECTOR4:
212 case Graphics::VertexInputFormat::FLOAT:
213 case Graphics::VertexInputFormat::FVECTOR2:
214 case Graphics::VertexInputFormat::FVECTOR3:
215 case Graphics::VertexInputFormat::FVECTOR4:
221 GLint GetGlType(Graphics::VertexInputFormat vertexFormat)
225 case Graphics::VertexInputFormat::UNDEFINED:
227 case Graphics::VertexInputFormat::INTEGER:
228 case Graphics::VertexInputFormat::IVECTOR2:
229 case Graphics::VertexInputFormat::IVECTOR3:
230 case Graphics::VertexInputFormat::IVECTOR4:
232 case Graphics::VertexInputFormat::FLOAT:
233 case Graphics::VertexInputFormat::FVECTOR2:
234 case Graphics::VertexInputFormat::FVECTOR3:
235 case Graphics::VertexInputFormat::FVECTOR4:
241 GLenum GetTopology(Graphics::PrimitiveTopology topology)
245 case Graphics::PrimitiveTopology::POINT_LIST:
248 case Graphics::PrimitiveTopology::LINE_LIST:
251 case Graphics::PrimitiveTopology::LINE_LOOP:
254 case Graphics::PrimitiveTopology::LINE_STRIP:
255 return GL_LINE_STRIP;
257 case Graphics::PrimitiveTopology::TRIANGLE_LIST:
260 case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
261 return GL_TRIANGLE_STRIP;
263 case Graphics::PrimitiveTopology::TRIANGLE_FAN:
264 return GL_TRIANGLE_FAN;
269 GLenum GetCullFace(Graphics::CullMode cullMode)
273 case Graphics::CullMode::NONE:
275 case Graphics::CullMode::FRONT:
277 case Graphics::CullMode::BACK:
279 case Graphics::CullMode::FRONT_AND_BACK:
280 return GL_FRONT_AND_BACK;
285 GLenum GetFrontFace(Graphics::FrontFace frontFace)
287 if(frontFace == Graphics::FrontFace::CLOCKWISE)
294 GLenum GetBlendFactor(Graphics::BlendFactor blendFactor)
296 GLenum glFactor = GL_ZERO;
300 case Graphics::BlendFactor::ZERO:
303 case Graphics::BlendFactor::ONE:
306 case Graphics::BlendFactor::SRC_COLOR:
307 glFactor = GL_SRC_COLOR;
309 case Graphics::BlendFactor::ONE_MINUS_SRC_COLOR:
310 glFactor = GL_ONE_MINUS_SRC_COLOR;
312 case Graphics::BlendFactor::DST_COLOR:
313 glFactor = GL_DST_COLOR;
315 case Graphics::BlendFactor::ONE_MINUS_DST_COLOR:
316 glFactor = GL_ONE_MINUS_DST_COLOR;
318 case Graphics::BlendFactor::SRC_ALPHA:
319 glFactor = GL_SRC_ALPHA;
321 case Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA:
322 glFactor = GL_ONE_MINUS_SRC_ALPHA;
324 case Graphics::BlendFactor::DST_ALPHA:
325 glFactor = GL_DST_ALPHA;
327 case Graphics::BlendFactor::ONE_MINUS_DST_ALPHA:
328 glFactor = GL_ONE_MINUS_DST_ALPHA;
330 case Graphics::BlendFactor::CONSTANT_COLOR:
331 glFactor = GL_CONSTANT_COLOR;
333 case Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR:
334 glFactor = GL_ONE_MINUS_CONSTANT_COLOR;
336 case Graphics::BlendFactor::CONSTANT_ALPHA:
337 glFactor = GL_CONSTANT_ALPHA;
339 case Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
340 glFactor = GL_ONE_MINUS_CONSTANT_ALPHA;
342 case Graphics::BlendFactor::SRC_ALPHA_SATURATE:
343 glFactor = GL_SRC_ALPHA_SATURATE;
345 // GLES doesn't appear to have dual source blending.
346 case Graphics::BlendFactor::SRC1_COLOR:
347 glFactor = GL_SRC_COLOR;
349 case Graphics::BlendFactor::ONE_MINUS_SRC1_COLOR:
350 glFactor = GL_ONE_MINUS_SRC_COLOR;
352 case Graphics::BlendFactor::SRC1_ALPHA:
353 glFactor = GL_SRC_ALPHA;
355 case Graphics::BlendFactor::ONE_MINUS_SRC1_ALPHA:
356 glFactor = GL_ONE_MINUS_SRC_ALPHA;
362 GLenum GetBlendOp(Graphics::BlendOp blendOp)
364 GLenum op = GL_FUNC_ADD;
367 case Graphics::BlendOp::ADD:
370 case Graphics::BlendOp::SUBTRACT:
371 op = GL_FUNC_SUBTRACT;
373 case Graphics::BlendOp::REVERSE_SUBTRACT:
374 op = GL_FUNC_REVERSE_SUBTRACT;
376 case Graphics::BlendOp::MIN:
379 case Graphics::BlendOp::MAX:
383 // @todo Add advanced blend equations
390 constexpr explicit GLCompareOp(Graphics::CompareOp compareOp)
394 case Graphics::CompareOp::NEVER:
397 case Graphics::CompareOp::LESS:
400 case Graphics::CompareOp::EQUAL:
403 case Graphics::CompareOp::LESS_OR_EQUAL:
406 case Graphics::CompareOp::GREATER:
409 case Graphics::CompareOp::NOT_EQUAL:
412 case Graphics::CompareOp::GREATER_OR_EQUAL:
415 case Graphics::CompareOp::ALWAYS:
425 constexpr explicit GLStencilOp(Graphics::StencilOp stencilOp)
429 case Graphics::StencilOp::KEEP:
432 case Graphics::StencilOp::ZERO:
435 case Graphics::StencilOp::REPLACE:
438 case Graphics::StencilOp::INCREMENT_AND_CLAMP:
441 case Graphics::StencilOp::DECREMENT_AND_CLAMP:
444 case Graphics::StencilOp::INVERT:
447 case Graphics::StencilOp::INCREMENT_AND_WRAP:
450 case Graphics::StencilOp::DECREMENT_AND_WRAP:
458 class TestGraphicsMemory : public Graphics::Memory
461 TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize)
462 : mCallStack(callStack),
464 mMappedOffset(mappedOffset),
465 mMappedSize(mappedSize),
471 void* LockRegion(uint32_t offset, uint32_t size) override
473 std::ostringstream o;
474 o << offset << ", " << size;
475 mCallStack.PushCall("Memory::LockRegion", o.str());
477 if(offset > mMappedOffset + mMappedSize ||
478 size + offset > mMappedOffset + mMappedSize)
480 fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds");
481 mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing
483 mLockedOffset = offset;
485 return &mBuffer.memory[mMappedOffset + offset];
488 void Unlock(bool flush) override
490 mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush"));
497 void Flush() override
499 mCallStack.PushCall("Memory::Flush", "");
501 mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize);
505 TraceCallStack& mCallStack;
506 TestGraphicsBuffer& mBuffer;
507 uint32_t mMappedOffset;
508 uint32_t mMappedSize;
509 uint32_t mLockedOffset;
510 uint32_t mLockedSize;
513 TestGraphicsController::TestGraphicsController()
514 : mCallStack(true, "TestGraphicsController."),
515 mCommandBufferCallStack(true, "TestCommandBuffer."),
516 mFrameBufferCallStack(true, "TestFrameBuffer.")
518 mCallStack.Enable(true);
519 mCommandBufferCallStack.Enable(true);
520 auto& trace = mGl.GetTextureTrace();
522 trace.EnableLogging(true);
525 void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo)
527 TraceCallStack::NamedParams namedParams;
528 namedParams["submitInfo"] << "cmdBuffer[" << submitInfo.cmdBuffer.size()
529 << "], flags:" << std::hex << submitInfo.flags;
531 mCallStack.PushCall("SubmitCommandBuffers", "", namedParams);
533 mSubmitStack.emplace_back(submitInfo);
535 for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer)
537 auto commandBuffer = Uncast<TestGraphicsCommandBuffer>(graphicsCommandBuffer);
538 ProcessCommandBuffer(*commandBuffer);
542 void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer)
544 bool scissorEnabled = false;
545 TestGraphicsFramebuffer* currentFramebuffer{nullptr};
546 TestGraphicsPipeline* currentPipeline{nullptr};
548 for(auto& cmd : commandBuffer.GetCommands())
553 case CommandType::FLUSH:
555 // Nothing to do here
558 case CommandType::BIND_TEXTURES:
560 for(auto& binding : cmd.data.bindTextures.textureBindings)
564 auto texture = Uncast<TestGraphicsTexture>(binding.texture);
565 texture->Bind(binding.binding);
569 auto sampler = Uncast<TestGraphicsSampler>(binding.sampler);
572 sampler->Apply(texture->GetTarget());
576 texture->Prepare(); // Ensure native texture is ready
581 case CommandType::BIND_VERTEX_BUFFERS:
583 for(auto& binding : cmd.data.bindVertexBuffers.vertexBufferBindings)
585 auto graphicsBuffer = binding.buffer;
586 auto vertexBuffer = Uncast<TestGraphicsBuffer>(graphicsBuffer);
587 vertexBuffer->Bind();
591 case CommandType::BIND_INDEX_BUFFER:
593 auto& indexBufferBinding = cmd.data.bindIndexBuffer;
594 if(indexBufferBinding.buffer)
596 auto buffer = Uncast<TestGraphicsBuffer>(indexBufferBinding.buffer);
601 case CommandType::BIND_UNIFORM_BUFFER:
603 auto& bindings = cmd.data.bindUniformBuffers;
604 auto buffer = bindings.standaloneUniformsBufferBinding;
606 // based on reflection, issue gl calls
607 buffer.buffer->BindAsUniformBuffer(static_cast<const TestGraphicsProgram*>(currentPipeline->programState.program));
610 case CommandType::BIND_SAMPLERS:
614 case CommandType::BIND_PIPELINE:
616 currentPipeline = Uncast<TestGraphicsPipeline>(cmd.data.bindPipeline.pipeline);
617 BindPipeline(currentPipeline);
620 case CommandType::DRAW:
622 mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
624 cmd.data.draw.draw.vertexCount);
627 case CommandType::DRAW_INDEXED:
629 mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
630 static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
632 reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
635 case CommandType::DRAW_INDEXED_INDIRECT:
637 mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
638 static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
640 reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
643 case CommandType::SET_SCISSOR:
647 auto& rect = cmd.data.scissor.region;
648 mGl.Scissor(rect.x, rect.y, rect.width, rect.height);
652 case CommandType::SET_SCISSOR_TEST:
654 if(cmd.data.scissorTest.enable)
656 mGl.Enable(GL_SCISSOR_TEST);
657 scissorEnabled = true;
661 mGl.Disable(GL_SCISSOR_TEST);
662 scissorEnabled = false;
666 case CommandType::SET_VIEWPORT_TEST:
670 case CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
672 auto& rect = cmd.data.viewport.region;
673 mGl.Viewport(rect.x, rect.y, rect.width, rect.height);
677 case CommandType::SET_COLOR_MASK:
679 // Set all channels to the same mask
680 const bool mask = cmd.data.colorMask.enabled;
681 mGl.ColorMask(mask, mask, mask, mask);
684 case CommandType::CLEAR_STENCIL_BUFFER:
686 mGl.Clear(GL_STENCIL_BUFFER_BIT);
689 case CommandType::CLEAR_DEPTH_BUFFER:
691 mGl.Clear(GL_DEPTH_BUFFER_BIT);
695 case CommandType::SET_STENCIL_TEST_ENABLE:
697 if(cmd.data.stencilTest.enabled)
699 mGl.Enable(GL_STENCIL_TEST);
703 mGl.Disable(GL_STENCIL_TEST);
708 case CommandType::SET_STENCIL_FUNC:
710 mGl.StencilFunc(GLCompareOp(cmd.data.stencilFunc.compareOp).op,
711 cmd.data.stencilFunc.reference,
712 cmd.data.stencilFunc.compareMask);
716 case CommandType::SET_STENCIL_WRITE_MASK:
718 mGl.StencilMask(cmd.data.stencilWriteMask.mask);
721 case CommandType::SET_STENCIL_OP:
723 mGl.StencilOp(GLStencilOp(cmd.data.stencilOp.failOp).op,
724 GLStencilOp(cmd.data.stencilOp.depthFailOp).op,
725 GLStencilOp(cmd.data.stencilOp.passOp).op);
729 case CommandType::SET_DEPTH_COMPARE_OP:
731 mGl.DepthFunc(GLCompareOp(cmd.data.depth.compareOp).op);
734 case CommandType::SET_DEPTH_TEST_ENABLE:
736 if(cmd.data.depth.testEnabled)
738 mGl.Enable(GL_DEPTH_TEST);
742 mGl.Disable(GL_DEPTH_TEST);
746 case CommandType::SET_DEPTH_WRITE_ENABLE:
748 mGl.DepthMask(cmd.data.depth.writeEnabled);
752 case CommandType::EXECUTE_COMMAND_BUFFERS:
754 // Process secondary command buffers
755 for(auto& buf : cmd.data.executeCommandBuffers.buffers)
757 ProcessCommandBuffer(*Uncast<TestGraphicsCommandBuffer>(buf));
761 case CommandType::BEGIN_RENDER_PASS:
763 auto renderTarget = Uncast<TestGraphicsRenderTarget>(cmd.data.beginRenderPass.renderTarget);
767 auto fb = renderTarget->mCreateInfo.framebuffer;
770 if(currentFramebuffer != fb)
772 currentFramebuffer = Uncast<TestGraphicsFramebuffer>(fb);
773 currentFramebuffer->Bind();
778 mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
783 mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
786 auto& clearValues = cmd.data.beginRenderPass.clearValues;
787 if(clearValues.size() > 0)
789 const auto renderPass = static_cast<TestGraphicsRenderPass*>(cmd.data.beginRenderPass.renderPass);
792 const auto& color0 = renderPass->attachments[0];
794 if(color0.loadOp == Graphics::AttachmentLoadOp::CLEAR)
796 mask |= GL_COLOR_BUFFER_BIT;
798 // Set clear color (todo: cache it!)
799 // Something goes wrong here if Alpha mask is GL_TRUE
800 mGl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
801 mGl.ClearColor(clearValues[0].color.r,
802 clearValues[0].color.g,
803 clearValues[0].color.b,
804 clearValues[0].color.a);
807 // check for depth stencil
808 if(renderPass->attachments.size() > 1)
810 const auto& depthStencil = renderPass->attachments.back();
811 if(depthStencil.loadOp == Graphics::AttachmentLoadOp::CLEAR)
814 uint32_t depthClearColor = 0u;
815 if(clearValues.size() == renderPass->attachments.size())
817 depthClearColor = clearValues.back().depthStencil.depth;
819 mGl.ClearDepthf(depthClearColor);
820 mask |= GL_DEPTH_BUFFER_BIT;
822 if(depthStencil.stencilLoadOp == Graphics::AttachmentLoadOp::CLEAR)
824 uint32_t stencilClearColor = 0u;
825 if(clearValues.size() == renderPass->attachments.size())
827 stencilClearColor = clearValues.back().depthStencil.stencil;
829 mGl.ClearStencil(stencilClearColor);
830 mGl.StencilMask(0xFF); // Clear all the bitplanes (assume 8)
831 mask |= GL_STENCIL_BUFFER_BIT;
837 // Test scissor area and RT size
838 const auto& area = cmd.data.beginRenderPass.renderArea;
841 area.width == renderTarget->mCreateInfo.extent.width &&
842 area.height == renderTarget->mCreateInfo.extent.height)
844 mGl.Disable(GL_SCISSOR_TEST);
849 mGl.Enable(GL_SCISSOR_TEST);
850 mGl.Scissor(cmd.data.beginRenderPass.renderArea.x, cmd.data.beginRenderPass.renderArea.y, cmd.data.beginRenderPass.renderArea.width, cmd.data.beginRenderPass.renderArea.height);
852 mGl.Disable(GL_SCISSOR_TEST);
858 DALI_ASSERT_DEBUG(0 && "BeginRenderPass has no render pass");
863 case CommandType::END_RENDER_PASS:
865 if(cmd.data.endRenderPass.syncObject != nullptr)
867 auto syncObject = Uncast<TestGraphicsSyncObject>(cmd.data.endRenderPass.syncObject);
868 syncObject->InitializeResource(); // create the sync object.
876 void TestGraphicsController::BindPipeline(TestGraphicsPipeline* pipeline)
878 auto& vi = pipeline->vertexInputState;
879 for(auto& attribute : vi.attributes)
881 mGl.EnableVertexAttribArray(attribute.location);
882 uint32_t attributeOffset = attribute.offset;
883 GLsizei stride = vi.bufferBindings[attribute.binding].stride;
885 mGl.VertexAttribPointer(attribute.location,
886 GetNumComponents(attribute.format),
887 GetGlType(attribute.format),
888 GL_FALSE, // Not normalized
890 reinterpret_cast<void*>(attributeOffset));
894 auto& rasterizationState = pipeline->rasterizationState;
895 if(rasterizationState.cullMode == Graphics::CullMode::NONE)
897 mGl.Disable(GL_CULL_FACE);
901 mGl.Enable(GL_CULL_FACE);
902 mGl.CullFace(GetCullFace(rasterizationState.cullMode));
905 mGl.FrontFace(GetFrontFace(rasterizationState.frontFace));
908 auto& colorBlendState = pipeline->colorBlendState;
909 if(colorBlendState.blendEnable)
911 mGl.Enable(GL_BLEND);
913 mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor),
914 GetBlendFactor(colorBlendState.dstColorBlendFactor),
915 GetBlendFactor(colorBlendState.srcAlphaBlendFactor),
916 GetBlendFactor(colorBlendState.dstAlphaBlendFactor));
917 if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp)
919 mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp));
923 mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp));
925 mGl.BlendColor(colorBlendState.blendConstants[0],
926 colorBlendState.blendConstants[1],
927 colorBlendState.blendConstants[2],
928 colorBlendState.blendConstants[3]);
932 mGl.Disable(GL_BLEND);
935 auto* program = static_cast<const TestGraphicsProgram*>(pipeline->programState.program);
936 mGl.UseProgram(program->mImpl->mId);
940 * @brief Presents render target
941 * @param renderTarget render target to present
943 void TestGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderTarget)
945 TraceCallStack::NamedParams namedParams;
946 namedParams["renderTarget"] << std::hex << renderTarget;
947 mCallStack.PushCall("PresentRenderTarget", "", namedParams);
951 * @brief Waits until the GPU is idle
953 void TestGraphicsController::WaitIdle()
955 mCallStack.PushCall("WaitIdle", "");
959 * @brief Lifecycle pause event
961 void TestGraphicsController::Pause()
963 mCallStack.PushCall("Pause", "");
967 * @brief Lifecycle resume event
969 void TestGraphicsController::Resume()
971 mCallStack.PushCall("Resume", "");
974 void TestGraphicsController::Shutdown()
976 mCallStack.PushCall("Shutdown", "");
979 void TestGraphicsController::Destroy()
981 mCallStack.PushCall("Destroy", "");
984 void TestGraphicsController::UpdateTextures(const std::vector<Graphics::TextureUpdateInfo>& updateInfoList,
985 const std::vector<Graphics::TextureUpdateSourceInfo>& sourceList)
987 TraceCallStack::NamedParams namedParams;
988 namedParams["updateInfoList"] << "[" << updateInfoList.size() << "]:";
989 namedParams["sourceList"] << "[" << sourceList.size() << "]:";
991 mCallStack.PushCall("UpdateTextures", "", namedParams);
993 // Call either TexImage2D or TexSubImage2D
994 for(unsigned int i = 0; i < updateInfoList.size(); ++i)
996 auto& updateInfo = updateInfoList[i];
997 auto& source = sourceList[i];
999 auto texture = static_cast<TestGraphicsTexture*>(updateInfo.dstTexture);
1000 texture->Bind(0); // Use first texture unit during resource update
1001 texture->Update(updateInfo, source);
1005 void TestGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
1007 mCallStack.PushCall("GenerateTextureMipmaps", "");
1009 auto gfxTexture = Uncast<TestGraphicsTexture>(&texture);
1010 mGl.BindTexture(gfxTexture->GetTarget(), 0);
1011 mGl.GenerateMipmap(gfxTexture->GetTarget());
1014 bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil)
1016 TraceCallStack::NamedParams namedParams;
1017 namedParams["enableDepth"] << (enableDepth ? "T" : "F");
1018 namedParams["enableStencil"] << (enableStencil ? "T" : "F");
1019 mCallStack.PushCall("EnableDepthStencilBuffer", "", namedParams);
1023 void TestGraphicsController::RunGarbageCollector(size_t numberOfDiscardedRenderers)
1025 TraceCallStack::NamedParams namedParams;
1026 namedParams["numberOfDiscardedRenderers"] << numberOfDiscardedRenderers;
1027 mCallStack.PushCall("RunGarbageCollector", "", namedParams);
1030 void TestGraphicsController::DiscardUnusedResources()
1032 mCallStack.PushCall("DiscardUnusedResources", "");
1035 bool TestGraphicsController::IsDiscardQueueEmpty()
1037 mCallStack.PushCall("IsDiscardQueueEmpty", "");
1038 return isDiscardQueueEmptyResult;
1042 * @brief Test if the graphics subsystem has resumed & should force a draw
1044 * @return true if the graphics subsystem requires a re-draw
1046 bool TestGraphicsController::IsDrawOnResumeRequired()
1048 mCallStack.PushCall("IsDrawOnResumeRequired", "");
1049 return isDrawOnResumeRequiredResult;
1052 Graphics::UniquePtr<Graphics::Buffer> TestGraphicsController::CreateBuffer(const Graphics::BufferCreateInfo& createInfo, Graphics::UniquePtr<Graphics::Buffer>&& oldBuffer)
1054 std::ostringstream oss;
1055 oss << "bufferCreateInfo:" << createInfo;
1056 mCallStack.PushCall("CreateBuffer", oss.str());
1057 return Graphics::MakeUnique<TestGraphicsBuffer>(mCallStack, mGl, createInfo.size, createInfo.usage);
1060 Graphics::UniquePtr<Graphics::CommandBuffer> TestGraphicsController::CreateCommandBuffer(const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo, Graphics::UniquePtr<Graphics::CommandBuffer>&& oldCommandBuffer)
1062 std::ostringstream oss;
1063 oss << "commandBufferCreateInfo:" << commandBufferCreateInfo;
1064 mCallStack.PushCall("CreateCommandBuffer", oss.str());
1065 return Graphics::MakeUnique<TestGraphicsCommandBuffer>(mCommandBufferCallStack, mGl);
1068 Graphics::UniquePtr<Graphics::RenderPass> TestGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<Graphics::RenderPass>&& oldRenderPass)
1070 mCallStack.PushCall("CreateRenderPass", "");
1071 return Graphics::MakeUnique<TestGraphicsRenderPass>(mGl, renderPassCreateInfo);
1074 Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::CreateTexture(const Graphics::TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Graphics::Texture>&& oldTexture)
1076 TraceCallStack::NamedParams namedParams;
1077 namedParams["textureCreateInfo"] << textureCreateInfo;
1078 mCallStack.PushCall("CreateTexture", namedParams.str(), namedParams);
1080 return Graphics::MakeUnique<TestGraphicsTexture>(mGl, textureCreateInfo);
1083 Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(
1084 const Graphics::FramebufferCreateInfo& createInfo,
1085 Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
1087 TraceCallStack::NamedParams namedParams;
1088 namedParams["framebufferCreateInfo"] << createInfo;
1089 mCallStack.PushCall("Controller::CreateFramebuffer", namedParams.str(), namedParams);
1091 return Graphics::MakeUnique<TestGraphicsFramebuffer>(mFrameBufferCallStack, mGl, createInfo);
1094 Graphics::UniquePtr<Graphics::Pipeline> TestGraphicsController::CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
1096 mCallStack.PushCall("CreatePipeline", "");
1097 return std::make_unique<TestGraphicsPipeline>(mGl, pipelineCreateInfo);
1100 Graphics::UniquePtr<Graphics::Program> TestGraphicsController::CreateProgram(const Graphics::ProgramCreateInfo& programCreateInfo, Graphics::UniquePtr<Graphics::Program>&& oldProgram)
1102 mCallStack.PushCall("CreateProgram", "");
1104 for(auto cacheEntry : mProgramCache)
1107 for(auto& shader : *(programCreateInfo.shaderState))
1109 auto graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
1110 std::vector<uint8_t> source;
1111 source.resize(graphicsShader->mCreateInfo.sourceSize);
1112 memcpy(&source[0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
1114 if(!std::equal(source.begin(), source.end(), cacheEntry.shaders[shader.pipelineStage].begin()))
1122 return Graphics::MakeUnique<TestGraphicsProgram>(cacheEntry.programImpl);
1126 mProgramCache.emplace_back();
1127 mProgramCache.back().programImpl = new TestGraphicsProgramImpl(mGl, programCreateInfo, mVertexFormats, mCustomUniforms);
1128 for(auto& shader : *(programCreateInfo.shaderState))
1130 auto graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
1131 mProgramCache.back().shaders[shader.pipelineStage].resize(graphicsShader->mCreateInfo.sourceSize);
1132 memcpy(&mProgramCache.back().shaders[shader.pipelineStage][0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
1134 return Graphics::MakeUnique<TestGraphicsProgram>(mProgramCache.back().programImpl);
1137 Graphics::UniquePtr<Graphics::Shader> TestGraphicsController::CreateShader(const Graphics::ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Graphics::Shader>&& oldShader)
1139 mCallStack.PushCall("CreateShader", "");
1140 return Graphics::MakeUnique<TestGraphicsShader>(mGl, shaderCreateInfo);
1143 Graphics::UniquePtr<Graphics::Sampler> TestGraphicsController::CreateSampler(const Graphics::SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Graphics::Sampler>&& oldSampler)
1145 TraceCallStack::NamedParams namedParams;
1146 namedParams["samplerCreateInfo"] << samplerCreateInfo;
1147 mCallStack.PushCall("CreateSampler", namedParams.str(), namedParams);
1149 return Graphics::MakeUnique<TestGraphicsSampler>(mGl, samplerCreateInfo);
1152 Graphics::UniquePtr<Graphics::RenderTarget> TestGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget)
1154 mCallStack.PushCall("CreateRenderTarget", "");
1155 return Graphics::MakeUnique<TestGraphicsRenderTarget>(mGl, renderTargetCreateInfo);
1158 Graphics::UniquePtr<Graphics::SyncObject> TestGraphicsController::CreateSyncObject(
1159 const Graphics::SyncObjectCreateInfo& syncObjectCreateInfo,
1160 Graphics::UniquePtr<Graphics::SyncObject>&& oldSyncObject)
1162 mCallStack.PushCall("CreateSyncObject", "");
1163 return Graphics::MakeUnique<TestGraphicsSyncObject>(mGraphicsSyncImpl, syncObjectCreateInfo);
1166 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapBufferRange(const Graphics::MapBufferInfo& mapInfo)
1168 mCallStack.PushCall("MapBufferRange", "");
1170 auto buffer = static_cast<TestGraphicsBuffer*>(mapInfo.buffer);
1171 buffer->memory.resize(mapInfo.offset + mapInfo.size); // For initial testing, allow writes past capacity
1173 return std::make_unique<TestGraphicsMemory>(mCallStack, *buffer, mapInfo.offset, mapInfo.size);
1176 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapTextureRange(const Graphics::MapTextureInfo& mapInfo)
1178 mCallStack.PushCall("MapTextureRange", "");
1182 void TestGraphicsController::UnmapMemory(Graphics::UniquePtr<Graphics::Memory> memory)
1184 mCallStack.PushCall("UnmapMemory", "");
1187 Graphics::MemoryRequirements TestGraphicsController::GetTextureMemoryRequirements(Graphics::Texture& texture) const
1189 mCallStack.PushCall("GetTextureMemoryRequirements", "");
1190 return Graphics::MemoryRequirements{};
1193 Graphics::MemoryRequirements TestGraphicsController::GetBufferMemoryRequirements(Graphics::Buffer& buffer) const
1195 mCallStack.PushCall("GetBufferMemoryRequirements", "");
1196 return Graphics::MemoryRequirements{};
1199 const Graphics::TextureProperties& TestGraphicsController::GetTextureProperties(const Graphics::Texture& texture)
1201 static Graphics::TextureProperties textureProperties{};
1202 mCallStack.PushCall("GetTextureProperties", "");
1204 return textureProperties;
1207 const Graphics::Reflection& TestGraphicsController::GetProgramReflection(const Graphics::Program& program)
1209 mCallStack.PushCall("GetProgramReflection", "");
1211 return static_cast<const TestGraphicsProgram*>(&program)->GetReflection();
1214 bool TestGraphicsController::PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const
1216 mCallStack.PushCall("PipelineEquals", "");
1220 bool TestGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData)
1222 mCallStack.PushCall("GetProgramParameter", "");
1223 auto graphicsProgram = Uncast<TestGraphicsProgram>(&program);
1224 return graphicsProgram->GetParameter(parameterId, outData);