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-texture.h"
29 #include <dali/integration-api/gl-defines.h>
36 std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
38 return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size;
41 std::ostream& operator<<(std::ostream& o, const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo)
43 return o << "level:" << (commandBufferCreateInfo.level == Graphics::CommandBufferLevel::PRIMARY ? "PRIMARY" : "SECONDARY")
44 << ", fixedCapacity:" << std::dec << commandBufferCreateInfo.fixedCapacity;
47 std::ostream& operator<<(std::ostream& o, const Graphics::TextureType& textureType)
51 case Graphics::TextureType::TEXTURE_2D:
54 case Graphics::TextureType::TEXTURE_3D:
57 case Graphics::TextureType::TEXTURE_CUBEMAP:
58 o << "TEXTURE_CUBEMAP";
64 std::ostream& operator<<(std::ostream& o, const Graphics::Extent2D extent)
66 o << "width:" << extent.width << ", height:" << extent.height;
70 std::ostream& operator<<(std::ostream& o, const Graphics::TextureCreateInfo& createInfo)
72 o << "textureType:" << createInfo.textureType
73 << " size:" << createInfo.size
74 << " format:" << static_cast<uint32_t>(createInfo.format)
75 << " mipMapFlag:" << createInfo.mipMapFlag
76 << " layout:" << (createInfo.layout == Graphics::TextureLayout::LINEAR ? "LINEAR" : "OPTIMAL")
77 << " usageFlags:" << std::hex << createInfo.usageFlags
78 << " data:" << std::hex << createInfo.data
79 << " dataSize:" << std::dec << createInfo.dataSize
80 << " nativeImagePtr:" << std::hex << createInfo.nativeImagePtr;
84 std::ostream& operator<<(std::ostream& o, Graphics::SamplerAddressMode addressMode)
88 case Graphics::SamplerAddressMode::REPEAT:
91 case Graphics::SamplerAddressMode::MIRRORED_REPEAT:
92 o << "MIRRORED_REPEAT";
94 case Graphics::SamplerAddressMode::CLAMP_TO_EDGE:
97 case Graphics::SamplerAddressMode::CLAMP_TO_BORDER:
98 o << "CLAMP_TO_BORDER";
100 case Graphics::SamplerAddressMode::MIRROR_CLAMP_TO_EDGE:
101 o << "MIRROR_CLAMP_TO_EDGE";
107 std::ostream& operator<<(std::ostream& o, Graphics::SamplerFilter filterMode)
111 case Graphics::SamplerFilter::LINEAR:
114 case Graphics::SamplerFilter::NEAREST:
121 std::ostream& operator<<(std::ostream& o, Graphics::SamplerMipmapMode mipmapMode)
125 case Graphics::SamplerMipmapMode::NONE:
128 case Graphics::SamplerMipmapMode::LINEAR:
131 case Graphics::SamplerMipmapMode::NEAREST:
138 std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& createInfo)
140 o << "minFilter:" << createInfo.minFilter
141 << " magFilter:" << createInfo.magFilter
142 << " wrapModeU:" << createInfo.addressModeU
143 << " wrapModeV:" << createInfo.addressModeV
144 << " wrapModeW:" << createInfo.addressModeW
145 << " mipMapMode:" << createInfo.mipMapMode;
149 std::ostream& operator<<(std::ostream& o, const Graphics::ColorAttachment& colorAttachment)
151 o << "attachmentId:" << colorAttachment.attachmentId
152 << " layerId:" << colorAttachment.layerId
153 << " levelId:" << colorAttachment.levelId
154 << " texture:" << colorAttachment.texture;
158 std::ostream& operator<<(std::ostream& o, const Graphics::DepthStencilAttachment& depthStencilAttachment)
160 o << "depthTexture:" << depthStencilAttachment.depthTexture
161 << "depthLevel:" << depthStencilAttachment.depthLevel
162 << "stencilTexture:" << depthStencilAttachment.stencilTexture
163 << "stencilLevel:" << depthStencilAttachment.stencilLevel;
167 std::ostream& operator<<(std::ostream& o, const Graphics::FramebufferCreateInfo& createInfo)
169 o << "colorAttachments:";
170 for(auto i = 0u; i < createInfo.colorAttachments.size(); ++i)
172 o << "[" << i << "]=" << createInfo.colorAttachments[i] << " ";
174 o << "depthStencilAttachment:" << createInfo.depthStencilAttachment;
175 o << "size: " << createInfo.size;
179 int GetNumComponents(Graphics::VertexInputFormat vertexFormat)
183 case Graphics::VertexInputFormat::UNDEFINED:
184 case Graphics::VertexInputFormat::FLOAT:
185 case Graphics::VertexInputFormat::INTEGER:
187 case Graphics::VertexInputFormat::IVECTOR2:
188 case Graphics::VertexInputFormat::FVECTOR2:
190 case Graphics::VertexInputFormat::IVECTOR3:
191 case Graphics::VertexInputFormat::FVECTOR3:
193 case Graphics::VertexInputFormat::FVECTOR4:
194 case Graphics::VertexInputFormat::IVECTOR4:
200 GLint GetSize(Graphics::VertexInputFormat vertexFormat)
204 case Graphics::VertexInputFormat::UNDEFINED:
206 case Graphics::VertexInputFormat::INTEGER:
207 case Graphics::VertexInputFormat::IVECTOR2:
208 case Graphics::VertexInputFormat::IVECTOR3:
209 case Graphics::VertexInputFormat::IVECTOR4:
211 case Graphics::VertexInputFormat::FLOAT:
212 case Graphics::VertexInputFormat::FVECTOR2:
213 case Graphics::VertexInputFormat::FVECTOR3:
214 case Graphics::VertexInputFormat::FVECTOR4:
220 GLint GetGlType(Graphics::VertexInputFormat vertexFormat)
224 case Graphics::VertexInputFormat::UNDEFINED:
226 case Graphics::VertexInputFormat::INTEGER:
227 case Graphics::VertexInputFormat::IVECTOR2:
228 case Graphics::VertexInputFormat::IVECTOR3:
229 case Graphics::VertexInputFormat::IVECTOR4:
231 case Graphics::VertexInputFormat::FLOAT:
232 case Graphics::VertexInputFormat::FVECTOR2:
233 case Graphics::VertexInputFormat::FVECTOR3:
234 case Graphics::VertexInputFormat::FVECTOR4:
240 GLenum GetTopology(Graphics::PrimitiveTopology topology)
244 case Graphics::PrimitiveTopology::POINT_LIST:
247 case Graphics::PrimitiveTopology::LINE_LIST:
250 case Graphics::PrimitiveTopology::LINE_LOOP:
253 case Graphics::PrimitiveTopology::LINE_STRIP:
254 return GL_LINE_STRIP;
256 case Graphics::PrimitiveTopology::TRIANGLE_LIST:
259 case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
260 return GL_TRIANGLE_STRIP;
262 case Graphics::PrimitiveTopology::TRIANGLE_FAN:
263 return GL_TRIANGLE_FAN;
268 GLenum GetCullFace(Graphics::CullMode cullMode)
272 case Graphics::CullMode::NONE:
274 case Graphics::CullMode::FRONT:
276 case Graphics::CullMode::BACK:
278 case Graphics::CullMode::FRONT_AND_BACK:
279 return GL_FRONT_AND_BACK;
284 GLenum GetFrontFace(Graphics::FrontFace frontFace)
286 if(frontFace == Graphics::FrontFace::CLOCKWISE)
293 GLenum GetBlendFactor(Graphics::BlendFactor blendFactor)
295 GLenum glFactor = GL_ZERO;
299 case Graphics::BlendFactor::ZERO:
302 case Graphics::BlendFactor::ONE:
305 case Graphics::BlendFactor::SRC_COLOR:
306 glFactor = GL_SRC_COLOR;
308 case Graphics::BlendFactor::ONE_MINUS_SRC_COLOR:
309 glFactor = GL_ONE_MINUS_SRC_COLOR;
311 case Graphics::BlendFactor::DST_COLOR:
312 glFactor = GL_DST_COLOR;
314 case Graphics::BlendFactor::ONE_MINUS_DST_COLOR:
315 glFactor = GL_ONE_MINUS_DST_COLOR;
317 case Graphics::BlendFactor::SRC_ALPHA:
318 glFactor = GL_SRC_ALPHA;
320 case Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA:
321 glFactor = GL_ONE_MINUS_SRC_ALPHA;
323 case Graphics::BlendFactor::DST_ALPHA:
324 glFactor = GL_DST_ALPHA;
326 case Graphics::BlendFactor::ONE_MINUS_DST_ALPHA:
327 glFactor = GL_ONE_MINUS_DST_ALPHA;
329 case Graphics::BlendFactor::CONSTANT_COLOR:
330 glFactor = GL_CONSTANT_COLOR;
332 case Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR:
333 glFactor = GL_ONE_MINUS_CONSTANT_COLOR;
335 case Graphics::BlendFactor::CONSTANT_ALPHA:
336 glFactor = GL_CONSTANT_ALPHA;
338 case Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
339 glFactor = GL_ONE_MINUS_CONSTANT_ALPHA;
341 case Graphics::BlendFactor::SRC_ALPHA_SATURATE:
342 glFactor = GL_SRC_ALPHA_SATURATE;
344 // GLES doesn't appear to have dual source blending.
345 case Graphics::BlendFactor::SRC1_COLOR:
346 glFactor = GL_SRC_COLOR;
348 case Graphics::BlendFactor::ONE_MINUS_SRC1_COLOR:
349 glFactor = GL_ONE_MINUS_SRC_COLOR;
351 case Graphics::BlendFactor::SRC1_ALPHA:
352 glFactor = GL_SRC_ALPHA;
354 case Graphics::BlendFactor::ONE_MINUS_SRC1_ALPHA:
355 glFactor = GL_ONE_MINUS_SRC_ALPHA;
361 GLenum GetBlendOp(Graphics::BlendOp blendOp)
363 GLenum op = GL_FUNC_ADD;
366 case Graphics::BlendOp::ADD:
369 case Graphics::BlendOp::SUBTRACT:
370 op = GL_FUNC_SUBTRACT;
372 case Graphics::BlendOp::REVERSE_SUBTRACT:
373 op = GL_FUNC_REVERSE_SUBTRACT;
375 case Graphics::BlendOp::MIN:
378 case Graphics::BlendOp::MAX:
382 // @todo Add advanced blend equations
387 class TestGraphicsMemory : public Graphics::Memory
390 TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize)
391 : mCallStack(callStack),
393 mMappedOffset(mappedOffset),
394 mMappedSize(mappedSize),
400 void* LockRegion(uint32_t offset, uint32_t size) override
402 std::ostringstream o;
403 o << offset << ", " << size;
404 mCallStack.PushCall("Memory::LockRegion", o.str());
406 if(offset > mMappedOffset + mMappedSize ||
407 size + offset > mMappedOffset + mMappedSize)
409 fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds");
410 mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing
412 mLockedOffset = offset;
414 return &mBuffer.memory[mMappedOffset + offset];
417 void Unlock(bool flush) override
419 mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush"));
426 void Flush() override
428 mCallStack.PushCall("Memory::Flush", "");
430 mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize);
434 TraceCallStack& mCallStack;
435 TestGraphicsBuffer& mBuffer;
436 uint32_t mMappedOffset;
437 uint32_t mMappedSize;
438 uint32_t mLockedOffset;
439 uint32_t mLockedSize;
442 TestGraphicsController::TestGraphicsController()
443 : mCallStack(true, "TestGraphicsController."),
444 mCommandBufferCallStack(true, "TestCommandBuffer."),
445 mFrameBufferCallStack(true, "TestFrameBuffer.")
447 mCallStack.Enable(true);
448 mCommandBufferCallStack.Enable(true);
449 auto& trace = mGl.GetTextureTrace();
451 trace.EnableLogging(true);
454 void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo)
456 TraceCallStack::NamedParams namedParams;
457 namedParams["submitInfo"] << "cmdBuffer[" << submitInfo.cmdBuffer.size()
458 << "], flags:" << std::hex << submitInfo.flags;
460 mCallStack.PushCall("SubmitCommandBuffers", "", namedParams);
462 mSubmitStack.emplace_back(submitInfo);
464 for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer)
466 auto commandBuffer = Uncast<TestGraphicsCommandBuffer>(graphicsCommandBuffer);
467 ProcessCommandBuffer(*commandBuffer);
471 void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer)
473 bool scissorEnabled = false;
474 TestGraphicsFramebuffer* currentFramebuffer{nullptr};
475 TestGraphicsPipeline* currentPipeline{nullptr};
477 for(auto& cmd : commandBuffer.GetCommands())
482 case CommandType::FLUSH:
484 // Nothing to do here
487 case CommandType::BIND_TEXTURES:
489 for(auto& binding : cmd.data.bindTextures.textureBindings)
493 auto texture = Uncast<TestGraphicsTexture>(binding.texture);
494 texture->Bind(binding.binding);
498 auto sampler = Uncast<TestGraphicsSampler>(binding.sampler);
501 sampler->Apply(texture->GetTarget());
505 texture->Prepare(); // Ensure native texture is ready
510 case CommandType::BIND_VERTEX_BUFFERS:
512 for(auto& binding : cmd.data.bindVertexBuffers.vertexBufferBindings)
514 auto graphicsBuffer = binding.buffer;
515 auto vertexBuffer = Uncast<TestGraphicsBuffer>(graphicsBuffer);
516 vertexBuffer->Bind();
520 case CommandType::BIND_INDEX_BUFFER:
522 auto& indexBufferBinding = cmd.data.bindIndexBuffer;
523 if(indexBufferBinding.buffer)
525 auto buffer = Uncast<TestGraphicsBuffer>(indexBufferBinding.buffer);
530 case CommandType::BIND_UNIFORM_BUFFER:
532 auto& bindings = cmd.data.bindUniformBuffers;
533 auto buffer = bindings.standaloneUniformsBufferBinding;
535 // based on reflection, issue gl calls
536 buffer.buffer->BindAsUniformBuffer(static_cast<const TestGraphicsProgram*>(currentPipeline->programState.program));
539 case CommandType::BIND_SAMPLERS:
543 case CommandType::BIND_PIPELINE:
545 currentPipeline = Uncast<TestGraphicsPipeline>(cmd.data.bindPipeline.pipeline);
547 // Bind framebuffer if different. @todo Move to RenderPass
548 auto framebuffer = currentPipeline->framebufferState.framebuffer;
549 if(framebuffer && framebuffer != currentFramebuffer)
551 auto graphicsFramebuffer = Uncast<TestGraphicsFramebuffer>(framebuffer);
552 graphicsFramebuffer->Bind();
556 if(currentFramebuffer)
557 currentFramebuffer->Bind();
559 mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
561 BindPipeline(currentPipeline);
564 case CommandType::DRAW:
566 mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
568 cmd.data.draw.draw.vertexCount);
571 case CommandType::DRAW_INDEXED:
573 mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
574 static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
576 reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
579 case CommandType::DRAW_INDEXED_INDIRECT:
581 mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
582 static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
584 reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
587 case CommandType::SET_SCISSOR:
591 auto& rect = cmd.data.scissor.region;
592 mGl.Scissor(rect.x, rect.y, rect.width, rect.height);
596 case CommandType::SET_SCISSOR_TEST:
598 if(cmd.data.scissorTest.enable)
600 mGl.Enable(GL_SCISSOR_TEST);
601 scissorEnabled = true;
605 mGl.Disable(GL_SCISSOR_TEST);
606 scissorEnabled = false;
610 case CommandType::SET_VIEWPORT_TEST:
614 case CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
616 auto& rect = cmd.data.viewport.region;
617 mGl.Viewport(rect.x, rect.y, rect.width, rect.height);
620 case CommandType::EXECUTE_COMMAND_BUFFERS:
622 // Process secondary command buffers
623 for(auto& buf : cmd.data.executeCommandBuffers.buffers)
625 ProcessCommandBuffer(*static_cast<TestGraphicsCommandBuffer*>(buf));
629 case CommandType::BEGIN_RENDER_PASS:
631 auto renderTarget = Uncast<TestGraphicsRenderTarget>(cmd.data.beginRenderPass.renderTarget);
635 auto fb = renderTarget->mCreateInfo.framebuffer;
638 if(currentFramebuffer != fb)
640 currentFramebuffer = Uncast<TestGraphicsFramebuffer>(fb);
641 currentFramebuffer->Bind();
646 mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
651 mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
654 auto& clearValues = cmd.data.beginRenderPass.clearValues;
655 if(clearValues.size() > 0)
657 const auto renderPass = static_cast<TestGraphicsRenderPass*>(cmd.data.beginRenderPass.renderPass);
660 const auto& color0 = renderPass->attachments[0];
662 if(color0.loadOp == Graphics::AttachmentLoadOp::CLEAR)
664 mask |= GL_COLOR_BUFFER_BIT;
666 // Set clear color (todo: cache it!)
667 // Something goes wrong here if Alpha mask is GL_TRUE
668 mGl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
669 mGl.ClearColor(clearValues[0].color.r,
670 clearValues[0].color.g,
671 clearValues[0].color.b,
672 clearValues[0].color.a);
675 // check for depth stencil
676 if(renderPass->attachments.size() > 1)
678 const auto& depthStencil = renderPass->attachments.back();
679 if(depthStencil.loadOp == Graphics::AttachmentLoadOp::CLEAR)
681 mask |= GL_DEPTH_BUFFER_BIT;
683 if(depthStencil.stencilLoadOp == Graphics::AttachmentLoadOp::CLEAR)
685 mask |= GL_STENCIL_BUFFER_BIT;
691 // Test scissor area and RT size
692 const auto& area = cmd.data.beginRenderPass.renderArea;
695 area.width == renderTarget->mCreateInfo.extent.width &&
696 area.height == renderTarget->mCreateInfo.extent.height)
698 mGl.Disable(GL_SCISSOR_TEST);
703 mGl.Enable(GL_SCISSOR_TEST);
704 mGl.Scissor(cmd.data.beginRenderPass.renderArea.x, cmd.data.beginRenderPass.renderArea.y, cmd.data.beginRenderPass.renderArea.width, cmd.data.beginRenderPass.renderArea.height);
706 mGl.Disable(GL_SCISSOR_TEST);
712 DALI_ASSERT_DEBUG(0 && "BeginRenderPass has no render pass");
717 case CommandType::END_RENDER_PASS:
725 void TestGraphicsController::BindPipeline(TestGraphicsPipeline* pipeline)
727 auto& vi = pipeline->vertexInputState;
728 for(auto& attribute : vi.attributes)
730 mGl.EnableVertexAttribArray(attribute.location);
731 uint32_t attributeOffset = attribute.offset;
732 GLsizei stride = vi.bufferBindings[attribute.binding].stride;
734 mGl.VertexAttribPointer(attribute.location,
735 GetNumComponents(attribute.format),
736 GetGlType(attribute.format),
737 GL_FALSE, // Not normalized
739 reinterpret_cast<void*>(attributeOffset));
743 auto& rasterizationState = pipeline->rasterizationState;
744 if(rasterizationState.cullMode == Graphics::CullMode::NONE)
746 mGl.Disable(GL_CULL_FACE);
750 mGl.Enable(GL_CULL_FACE);
751 mGl.CullFace(GetCullFace(rasterizationState.cullMode));
754 mGl.FrontFace(GetFrontFace(rasterizationState.frontFace));
757 auto& colorBlendState = pipeline->colorBlendState;
758 if(colorBlendState.blendEnable)
760 mGl.Enable(GL_BLEND);
762 mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor),
763 GetBlendFactor(colorBlendState.dstColorBlendFactor),
764 GetBlendFactor(colorBlendState.srcAlphaBlendFactor),
765 GetBlendFactor(colorBlendState.dstAlphaBlendFactor));
766 if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp)
768 mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp));
772 mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp));
774 mGl.BlendColor(colorBlendState.blendConstants[0],
775 colorBlendState.blendConstants[1],
776 colorBlendState.blendConstants[2],
777 colorBlendState.blendConstants[3]);
781 mGl.Disable(GL_BLEND);
784 auto* program = static_cast<const TestGraphicsProgram*>(pipeline->programState.program);
785 mGl.UseProgram(program->mImpl->mId);
789 * @brief Presents render target
790 * @param renderTarget render target to present
792 void TestGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderTarget)
794 TraceCallStack::NamedParams namedParams;
795 namedParams["renderTarget"] << std::hex << renderTarget;
796 mCallStack.PushCall("PresentRenderTarget", "", namedParams);
800 * @brief Waits until the GPU is idle
802 void TestGraphicsController::WaitIdle()
804 mCallStack.PushCall("WaitIdle", "");
808 * @brief Lifecycle pause event
810 void TestGraphicsController::Pause()
812 mCallStack.PushCall("Pause", "");
816 * @brief Lifecycle resume event
818 void TestGraphicsController::Resume()
820 mCallStack.PushCall("Resume", "");
823 void TestGraphicsController::Shutdown()
825 mCallStack.PushCall("Shutdown", "");
828 void TestGraphicsController::Destroy()
830 mCallStack.PushCall("Destroy", "");
833 void TestGraphicsController::UpdateTextures(const std::vector<Graphics::TextureUpdateInfo>& updateInfoList,
834 const std::vector<Graphics::TextureUpdateSourceInfo>& sourceList)
836 TraceCallStack::NamedParams namedParams;
837 namedParams["updateInfoList"] << "[" << updateInfoList.size() << "]:";
838 namedParams["sourceList"] << "[" << sourceList.size() << "]:";
840 mCallStack.PushCall("UpdateTextures", "", namedParams);
842 // Call either TexImage2D or TexSubImage2D
843 for(unsigned int i = 0; i < updateInfoList.size(); ++i)
845 auto& updateInfo = updateInfoList[i];
846 auto& source = sourceList[i];
848 auto texture = static_cast<TestGraphicsTexture*>(updateInfo.dstTexture);
849 texture->Bind(0); // Use first texture unit during resource update
850 texture->Update(updateInfo, source);
854 bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil)
856 TraceCallStack::NamedParams namedParams;
857 namedParams["enableDepth"] << (enableDepth ? "T" : "F");
858 namedParams["enableStencil"] << (enableStencil ? "T" : "F");
859 mCallStack.PushCall("EnableDepthStencilBuffer", "", namedParams);
863 void TestGraphicsController::RunGarbageCollector(size_t numberOfDiscardedRenderers)
865 TraceCallStack::NamedParams namedParams;
866 namedParams["numberOfDiscardedRenderers"] << numberOfDiscardedRenderers;
867 mCallStack.PushCall("RunGarbageCollector", "", namedParams);
870 void TestGraphicsController::DiscardUnusedResources()
872 mCallStack.PushCall("DiscardUnusedResources", "");
875 bool TestGraphicsController::IsDiscardQueueEmpty()
877 mCallStack.PushCall("IsDiscardQueueEmpty", "");
878 return isDiscardQueueEmptyResult;
882 * @brief Test if the graphics subsystem has resumed & should force a draw
884 * @return true if the graphics subsystem requires a re-draw
886 bool TestGraphicsController::IsDrawOnResumeRequired()
888 mCallStack.PushCall("IsDrawOnResumeRequired", "");
889 return isDrawOnResumeRequiredResult;
892 Graphics::UniquePtr<Graphics::Buffer> TestGraphicsController::CreateBuffer(const Graphics::BufferCreateInfo& createInfo, Graphics::UniquePtr<Graphics::Buffer>&& oldBuffer)
894 std::ostringstream oss;
895 oss << "bufferCreateInfo:" << createInfo;
896 mCallStack.PushCall("CreateBuffer", oss.str());
897 return Graphics::MakeUnique<TestGraphicsBuffer>(mCallStack, mGl, createInfo.size, createInfo.usage);
900 Graphics::UniquePtr<Graphics::CommandBuffer> TestGraphicsController::CreateCommandBuffer(const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo, Graphics::UniquePtr<Graphics::CommandBuffer>&& oldCommandBuffer)
902 std::ostringstream oss;
903 oss << "commandBufferCreateInfo:" << commandBufferCreateInfo;
904 mCallStack.PushCall("CreateCommandBuffer", oss.str());
905 return Graphics::MakeUnique<TestGraphicsCommandBuffer>(mCommandBufferCallStack, mGl);
908 Graphics::UniquePtr<Graphics::RenderPass> TestGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<Graphics::RenderPass>&& oldRenderPass)
910 mCallStack.PushCall("CreateRenderPass", "");
911 return Graphics::MakeUnique<TestGraphicsRenderPass>(mGl, renderPassCreateInfo);
914 Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::CreateTexture(const Graphics::TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Graphics::Texture>&& oldTexture)
916 TraceCallStack::NamedParams namedParams;
917 namedParams["textureCreateInfo"] << textureCreateInfo;
918 mCallStack.PushCall("CreateTexture", namedParams.str(), namedParams);
920 return Graphics::MakeUnique<TestGraphicsTexture>(mGl, textureCreateInfo);
923 Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(
924 const Graphics::FramebufferCreateInfo& createInfo,
925 Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
927 TraceCallStack::NamedParams namedParams;
928 namedParams["framebufferCreateInfo"] << createInfo;
929 mCallStack.PushCall("Controller::CreateFramebuffer", namedParams.str(), namedParams);
931 return Graphics::MakeUnique<TestGraphicsFramebuffer>(mFrameBufferCallStack, mGl, createInfo);
934 Graphics::UniquePtr<Graphics::Pipeline> TestGraphicsController::CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
936 mCallStack.PushCall("CreatePipeline", "");
937 return std::make_unique<TestGraphicsPipeline>(mGl, pipelineCreateInfo);
940 Graphics::UniquePtr<Graphics::Program> TestGraphicsController::CreateProgram(const Graphics::ProgramCreateInfo& programCreateInfo, Graphics::UniquePtr<Graphics::Program>&& oldProgram)
942 mCallStack.PushCall("CreateProgram", "");
944 for(auto cacheEntry : mProgramCache)
947 for(auto& shader : *(programCreateInfo.shaderState))
949 auto graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
950 std::vector<uint8_t> source;
951 source.resize(graphicsShader->mCreateInfo.sourceSize);
952 memcpy(&source[0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
954 if(!std::equal(source.begin(), source.end(), cacheEntry.shaders[shader.pipelineStage].begin()))
962 return Graphics::MakeUnique<TestGraphicsProgram>(cacheEntry.programImpl);
966 mProgramCache.emplace_back();
967 mProgramCache.back().programImpl = new TestGraphicsProgramImpl(mGl, programCreateInfo, mVertexFormats, mCustomUniforms);
968 for(auto& shader : *(programCreateInfo.shaderState))
970 auto graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
971 mProgramCache.back().shaders[shader.pipelineStage].resize(graphicsShader->mCreateInfo.sourceSize);
972 memcpy(&mProgramCache.back().shaders[shader.pipelineStage][0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
974 return Graphics::MakeUnique<TestGraphicsProgram>(mProgramCache.back().programImpl);
977 Graphics::UniquePtr<Graphics::Shader> TestGraphicsController::CreateShader(const Graphics::ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Graphics::Shader>&& oldShader)
979 mCallStack.PushCall("CreateShader", "");
980 return Graphics::MakeUnique<TestGraphicsShader>(mGl, shaderCreateInfo);
983 Graphics::UniquePtr<Graphics::Sampler> TestGraphicsController::CreateSampler(const Graphics::SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Graphics::Sampler>&& oldSampler)
985 TraceCallStack::NamedParams namedParams;
986 namedParams["samplerCreateInfo"] << samplerCreateInfo;
987 mCallStack.PushCall("CreateSampler", namedParams.str(), namedParams);
989 return Graphics::MakeUnique<TestGraphicsSampler>(mGl, samplerCreateInfo);
992 Graphics::UniquePtr<Graphics::RenderTarget> TestGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget)
994 mCallStack.PushCall("CreateRenderTarget", "");
995 return Graphics::MakeUnique<TestGraphicsRenderTarget>(mGl, renderTargetCreateInfo);
998 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapBufferRange(const Graphics::MapBufferInfo& mapInfo)
1000 mCallStack.PushCall("MapBufferRange", "");
1002 auto buffer = static_cast<TestGraphicsBuffer*>(mapInfo.buffer);
1003 buffer->memory.resize(mapInfo.offset + mapInfo.size); // For initial testing, allow writes past capacity
1005 return std::make_unique<TestGraphicsMemory>(mCallStack, *buffer, mapInfo.offset, mapInfo.size);
1008 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapTextureRange(const Graphics::MapTextureInfo& mapInfo)
1010 mCallStack.PushCall("MapTextureRange", "");
1014 void TestGraphicsController::UnmapMemory(Graphics::UniquePtr<Graphics::Memory> memory)
1016 mCallStack.PushCall("UnmapMemory", "");
1019 Graphics::MemoryRequirements TestGraphicsController::GetTextureMemoryRequirements(Graphics::Texture& texture) const
1021 mCallStack.PushCall("GetTextureMemoryRequirements", "");
1022 return Graphics::MemoryRequirements{};
1025 Graphics::MemoryRequirements TestGraphicsController::GetBufferMemoryRequirements(Graphics::Buffer& buffer) const
1027 mCallStack.PushCall("GetBufferMemoryRequirements", "");
1028 return Graphics::MemoryRequirements{};
1031 const Graphics::TextureProperties& TestGraphicsController::GetTextureProperties(const Graphics::Texture& texture)
1033 static Graphics::TextureProperties textureProperties{};
1034 mCallStack.PushCall("GetTextureProperties", "");
1036 return textureProperties;
1039 const Graphics::Reflection& TestGraphicsController::GetProgramReflection(const Graphics::Program& program)
1041 mCallStack.PushCall("GetProgramReflection", "");
1043 return static_cast<const TestGraphicsProgram*>(&program)->GetReflection();
1046 bool TestGraphicsController::PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const
1048 mCallStack.PushCall("PipelineEquals", "");
1052 bool TestGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData)
1054 mCallStack.PushCall("GetProgramParameter", "");
1055 auto graphicsProgram = Uncast<TestGraphicsProgram>(&program);
1056 return graphicsProgram->GetParameter(parameterId, outData);