Fixed bug with dependency graph adding same dependency more than once to render target
Changed queue submission to handle vector of wait stage masks
(as a render task may depend on more than one offscreen to finish rendering)
Changed render task dependence so that only the "earliest" dependent needs to
wait for offscreen - (2nd dependant Submit can't wait on already signalled sema, apparently!)
Fixes a lot of lockups in demos.
Changed swapchain Submit() to pass in any offscreen dependencies.
Swapchain submit adds own dependence on acquireNextImageSemaphore.
Test harness:
Some tests skip initial "SendNotification" call. This means that scene-setup done by the test harness is ignored until the next frame.
Changed the TestApplication InitilizeCore method to ensure that the messages are processed after setup.
(So it doesn't matter if the test doesn't first call app.SendNotification()).
Change-Id: I05449137fa14ce1b00d3ecd152f4d0cf2409228d
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
createInfo.SetSurface({nullptr})
.SetExtent({mSurfaceWidth, mSurfaceHeight})
.SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
- //mRenderTarget = mGraphicsController.CreateRenderTarget(createInfo, nullptr);
+ // mRenderTarget = mGraphicsController.CreateRenderTarget(createInfo, nullptr);
mScene.SetSurfaceRenderTarget(createInfo);
}
{
mCore->SceneCreated();
mCore->Initialize();
+ mCore->ProcessEvents();
}
TestGraphicsApplication::~TestGraphicsApplication()
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
createInfo.SetSurface({nullptr})
.SetExtent({mSurfaceWidth, mSurfaceHeight})
.SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
- //mRenderTarget = mGraphicsController.CreateRenderTarget(createInfo, nullptr);
+
mScene.SetSurfaceRenderTarget(createInfo);
}
{
mCore->SceneCreated();
mCore->Initialize();
+ mCore->ProcessEvents();
}
TestGraphicsApplication::~TestGraphicsApplication()
#pragma once
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
void DoUpdate(uint32_t intervalMilliseconds, const char* location = NULL);
protected:
- TestPlatformAbstraction mPlatformAbstraction;
- TestRenderController mRenderController;
- TestVkAbstraction mVkAbstraction;
- Graphics::VulkanGraphics mGraphics; // Use real vulkan graphics
- Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget{nullptr};
- Dali::DisplayConnection* mDisplayConnection{nullptr};
+ TestPlatformAbstraction mPlatformAbstraction;
+ TestRenderController mRenderController;
+ TestVkAbstraction mVkAbstraction;
+ Graphics::VulkanGraphics mGraphics; // Use real vulkan graphics
+ Dali::DisplayConnection* mDisplayConnection{nullptr};
Integration::UpdateStatus mStatus;
Integration::RenderStatus mRenderStatus;
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
namespace Dali::Graphics::Vulkan
{
// submission
-SubmissionData::SubmissionData(const std::vector<vk::Semaphore>& waitSemaphores_,
- vk::PipelineStageFlags waitDestinationStageMask_,
- const std::vector<CommandBufferImpl*>& commandBuffers_,
- const std::vector<vk::Semaphore>& signalSemaphores_)
+SubmissionData::SubmissionData(const std::vector<vk::Semaphore>& waitSemaphores_,
+ const std::vector<vk::PipelineStageFlags>& waitDestinationStageMask_,
+ const std::vector<CommandBufferImpl*>& commandBuffers_,
+ const std::vector<vk::Semaphore>& signalSemaphores_)
: waitSemaphores(waitSemaphores_),
waitDestinationStageMask(waitDestinationStageMask_),
commandBuffers(commandBuffers_),
return *this;
}
-SubmissionData& SubmissionData::SetWaitDestinationStageMask(vk::PipelineStageFlags dstStageMask)
+SubmissionData& SubmissionData::SetWaitDestinationStageMask(const std::vector<vk::PipelineStageFlags>& dstStageMask)
{
waitDestinationStageMask = dstStageMask;
return *this;
auto submitInfo = vk::SubmitInfo()
.setWaitSemaphoreCount(U32(subData.waitSemaphores.size()))
.setPWaitSemaphores(subData.waitSemaphores.data())
- .setPWaitDstStageMask(&subData.waitDestinationStageMask)
+ .setPWaitDstStageMask(subData.waitDestinationStageMask.data())
.setCommandBufferCount(U32(subData.commandBuffers.size()))
.setPCommandBuffers(&commandBufferHandles[currentBufferIndex])
.setSignalSemaphoreCount(U32(subData.signalSemaphores.size()))
#define DALI_INTERNAL_GRAPHICS_VULKAN_QUEUE_IMPL_H
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
SubmissionData() = default;
- explicit SubmissionData(const std::vector<vk::Semaphore>& waitSemaphores_,
- vk::PipelineStageFlags waitDestinationStageMask_,
- const std::vector<CommandBufferImpl*>& commandBuffers_,
- const std::vector<vk::Semaphore>& signalSemaphores_);
+ explicit SubmissionData(const std::vector<vk::Semaphore>& waitSemaphores_,
+ const std::vector<vk::PipelineStageFlags>& waitDestinationStageMask_,
+ const std::vector<CommandBufferImpl*>& commandBuffers_,
+ const std::vector<vk::Semaphore>& signalSemaphores_);
SubmissionData& SetWaitSemaphores(const std::vector<vk::Semaphore>& semaphores);
- SubmissionData& SetWaitDestinationStageMask(vk::PipelineStageFlags dstStageMask);
+ SubmissionData& SetWaitDestinationStageMask(const std::vector<vk::PipelineStageFlags>& dstStageMask);
SubmissionData& SetCommandBuffers(const std::vector<CommandBufferImpl*>& cmdBuffers);
SubmissionData& SetSignalSemaphores(const std::vector<vk::Semaphore>& semaphores);
- std::vector<vk::Semaphore> waitSemaphores;
- vk::PipelineStageFlags waitDestinationStageMask;
- std::vector<CommandBufferImpl*> commandBuffers;
- std::vector<vk::Semaphore> signalSemaphores;
+ std::vector<vk::Semaphore> waitSemaphores;
+ std::vector<vk::PipelineStageFlags> waitDestinationStageMask;
+ std::vector<CommandBufferImpl*> commandBuffers;
+ std::vector<vk::Semaphore> signalSemaphores;
};
class Queue
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
auto& graphicsDevice = mController.GetGraphicsDevice();
auto surface = GetSurface();
+ std::vector<vk::Semaphore> waitSemaphores;
+ for(auto renderTarget : mDependencies)
+ {
+ // Only use semaphore if dependency render target was submitted
+ // already this frame and not already waited on.
+ if(renderTarget->mSubmitted && !renderTarget->mSemaphoreWaited)
+ {
+ waitSemaphores.push_back(renderTarget->mSubmitSemaphore);
+ renderTarget->mSemaphoreWaited = true;
+ }
+ }
+ std::vector<vk::PipelineStageFlags> waitDstStageMask{waitSemaphores.size(), vk::PipelineStageFlagBits::eColorAttachmentOutput};
+
if(surface)
{
auto surfaceId = static_cast<Internal::Adaptor::WindowRenderSurface*>(surface)->GetSurfaceId();
auto swapchain = graphicsDevice.GetSwapchainForSurfaceId(surfaceId);
- swapchain->Submit(cmdBuffer->GetImpl());
+ swapchain->Submit(cmdBuffer->GetImpl(), waitSemaphores);
}
else
{
- std::vector<vk::Semaphore> waitSemaphores;
- for(auto renderTarget : mDependencies)
- {
- waitSemaphores.push_back(renderTarget->mSubmitSemaphore);
- }
-
std::vector<vk::Semaphore> signalSemaphores{mSubmitSemaphore};
graphicsDevice.GetGraphicsQueue(0).Submit(
{SubmissionData{
waitSemaphores,
- {vk::PipelineStageFlagBits::eFragmentShader},
+ waitDstStageMask,
{cmdBuffer->GetImpl()},
signalSemaphores}},
nullptr);
}
+ mSubmitted = true;
}
} // namespace Dali::Graphics::Vulkan
#define DALI_INTERNAL_GRAPHICS_VULKAN_RENDER_TARGET_H
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
void ResetDependencies()
{
mDependencies.clear();
+ mSubmitted = false;
+ mSemaphoreWaited = false;
}
void AddDependency(RenderTarget* dependency)
{
- mDependencies.push_back(dependency);
+ auto iter = std::find(mDependencies.begin(), mDependencies.end(), dependency);
+ if(iter == mDependencies.end())
+ {
+ mDependencies.push_back(dependency);
+ }
}
void RemoveDependency(RenderTarget* dependency)
{
}
}
+ const std::vector<RenderTarget*>& GetDependencies() const;
+
private:
- vk::Semaphore mSubmitSemaphore; ///< Signaled when the command buffer for this target is processed
- std::vector<RenderTarget*> mDependencies; ///< Render targets whose output is used as input to this task.
+ std::vector<RenderTarget*> mDependencies; ///< Render targets whose output is used as input to this task.
+ vk::Semaphore mSubmitSemaphore; ///< Signaled when the command buffer for this target is processed
+ bool mSubmitted{false}; ///< Check if this render target was submitted this frame
+ bool mSemaphoreWaited{false};
};
} // namespace Dali::Graphics::Vulkan
/*
- * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
return mFramebuffers[mSwapchainImageIndex].get();
}
-void Swapchain::Submit(CommandBufferImpl* commandBuffer)
+void Swapchain::Submit(CommandBufferImpl* commandBuffer, const std::vector<vk::Semaphore>& depends)
{
auto& swapchainBuffer = mSwapchainBuffers[mGraphicsDevice.GetCurrentBufferIndex()];
swapchainBuffer->endOfFrameFence->Reset();
+ std::vector<vk::Semaphore> waitSemaphores{depends};
+ std::vector<vk::PipelineStageFlags> waitDstStageMask{waitSemaphores.size(), vk::PipelineStageFlagBits::eColorAttachmentOutput};
+
+ waitSemaphores.push_back(swapchainBuffer->acquireNextImageSemaphore);
+ waitDstStageMask.push_back(vk::PipelineStageFlagBits::eFragmentShader);
+
mQueue->Submit({Vulkan::SubmissionData{
- {swapchainBuffer->acquireNextImageSemaphore},
- {vk::PipelineStageFlagBits::eFragmentShader},
+ waitSemaphores,
+ waitDstStageMask,
{commandBuffer},
{swapchainBuffer->submitSemaphore}}},
swapchainBuffer->endOfFrameFence.get());
/**
* Submits the given command buffer to the swapchain queue
*/
- void Submit(CommandBufferImpl* commandBuffer);
+ void Submit(CommandBufferImpl* commandBuffer, const std::vector<vk::Semaphore>& depends);
/**
* Presents using default present queue, asynchronously