build
build.log
tct*core.h
-results_xml.*
\ No newline at end of file
+results_xml.*
+/CMakeLists.txt
build
build.log
tct*core.h
+/CMakeLists.txt
\ No newline at end of file
*.xml
build
build.log
+/CMakeLists.txt
\ No newline at end of file
protected:
Dali::Internal::Adaptor::AdaptorInternalServices* mAdaptor;
- Dali::Graphics::GraphicsInterface* mGraphics;
+ Dali::Graphics::GraphicsInterface* mGraphics;
Dali::DisplayConnection* mDisplayConnection;
WeakHandle<Dali::Integration::Scene> mScene;
bool mFullSwapNextFrame; ///< Whether the full surface swap is required
NotifyGraphicsInitialised();
- //@todo Vk swaps this around, but we need to support surfaceless context for multi-window
+ // Generate swapchains if needed
graphics.ConfigureSurface(mAdaptorInterfaces.GetRenderSurfaceInterface());
// Tell core it has a context
AddPerformanceMarker(PerformanceInterface::RENDER_START);
TRACE_UPDATE_RENDER_BEGIN("DALI_RENDER");
- // Upload shared resources
+ // Upload shared resources and process render messages
TRACE_UPDATE_RENDER_BEGIN("DALI_PRE_RENDER");
mCore.PreRender(renderStatus, mForceClear);
TRACE_UPDATE_RENDER_END("DALI_PRE_RENDER");
void CommandBuffer::Begin(const Graphics::CommandBufferBeginInfo& info)
{
+ if(mCommandBufferImpl)
+ {
+ mCommandBufferImpl->Begin(static_cast<vk::CommandBufferUsageFlags>(info.usage), nullptr);
+ }
}
void CommandBuffer::End()
{
+ if(mCommandBufferImpl)
+ {
+ mCommandBufferImpl->End();
+ }
+}
+
+void CommandBuffer::Reset()
+{
+ if(mCommandBufferImpl)
+ {
+ mCommandBufferImpl->Reset();
+ }
+ mLastSwapchain = nullptr;
}
void CommandBuffer::BindVertexBuffers(uint32_t firstBinding,
{
}
-void CommandBuffer::BeginRenderPass(Graphics::RenderPass* renderPass,
- Graphics::RenderTarget* renderTarget,
+void CommandBuffer::BeginRenderPass(Graphics::RenderPass* gfxRenderPass,
+ Graphics::RenderTarget* gfxRenderTarget,
Rect2D renderArea,
const std::vector<ClearValue>& clearValues)
{
- //@todo Find a better place to auto-insert begin/end.
- // mCommandBufferImpl->Begin(vk::CommandBufferUsageFlagBits::eOneTimeSubmit, nullptr );
-
- auto vulkanRenderPass = static_cast<Vulkan::RenderPass*>(renderPass);
- auto vulkanRenderTarget = static_cast<Vulkan::RenderTarget*>(renderTarget);
- auto surface = vulkanRenderTarget->GetSurface();
- auto& device = mController.GetGraphicsDevice();
+ auto renderPass = static_cast<Vulkan::RenderPass*>(gfxRenderPass);
+ auto renderTarget = static_cast<Vulkan::RenderTarget*>(gfxRenderTarget);
+ auto surface = renderTarget->GetSurface();
+ auto& device = mController.GetGraphicsDevice();
FramebufferImpl* framebuffer;
- vk::RenderPass vkRenderPass;
+ RenderPassImpl* renderPassImpl;
if(surface)
{
auto window = static_cast<Internal::Adaptor::WindowRenderSurface*>(surface);
auto surfaceId = window->GetSurfaceId();
auto swapchain = device.GetSwapchainForSurfaceId(surfaceId);
+ mLastSwapchain = swapchain;
framebuffer = swapchain->GetCurrentFramebuffer();
- vkRenderPass = framebuffer->GetRenderPass();
+ renderPassImpl = framebuffer->GetRenderPass(renderPass);
}
else
{
- auto coreFramebuffer = vulkanRenderTarget->GetFramebuffer();
+ auto coreFramebuffer = renderTarget->GetFramebuffer();
framebuffer = coreFramebuffer->GetImpl();
- vkRenderPass = vulkanRenderPass->GetImpl()->GetVkHandle();
+ renderPassImpl = framebuffer->GetRenderPass(renderPass);
}
std::vector<vk::ClearValue> vkClearValues;
- for(auto clearValue : clearValues)
+
+ auto attachments = renderPass->GetCreateInfo().attachments;
+ if(attachments != nullptr &&
+ !attachments->empty() &&
+ attachments->front().loadOp == Graphics::AttachmentLoadOp::CLEAR)
{
- vk::ClearColorValue color;
- color.float32[0] = clearValue.color.r;
- color.float32[1] = clearValue.color.g;
- color.float32[2] = clearValue.color.b;
- color.float32[3] = clearValue.color.a;
- vkClearValues.emplace_back(color);
+ for(auto clearValue : clearValues)
+ {
+ vk::ClearColorValue color;
+ color.float32[0] = clearValue.color.r;
+ color.float32[1] = clearValue.color.g;
+ color.float32[2] = clearValue.color.b;
+ color.float32[3] = clearValue.color.a;
+ vkClearValues.emplace_back(color);
+ }
}
- /**
- mCommandBufferImpl->BeginRenderPass( vk::RenderPassBeginInfo{}
- .setFramebuffer( framebuffer->GetVkHandle() )
- .setRenderPass( vkRenderPass )
- .setRenderArea( { {0, 0}, { renderArea.width, renderArea.height } } )
- .setPClearValues( vkClearValues.data() )
- .setClearValueCount( uint32_t(framebuffer->GetClearValues().size()) ),
- vk::SubpassContents::eInline );
-*/
+
+ mCommandBufferImpl->BeginRenderPass(vk::RenderPassBeginInfo{}
+ .setFramebuffer(framebuffer->GetVkHandle())
+ .setRenderPass(renderPassImpl->GetVkHandle())
+ .setRenderArea({{0, 0}, {renderArea.width, renderArea.height}})
+ .setPClearValues(vkClearValues.data())
+ .setClearValueCount(uint32_t(framebuffer->GetClearValues().size())),
+ vk::SubpassContents::eInline);
}
void CommandBuffer::EndRenderPass(Graphics::SyncObject* syncObject)
{
- // mCommandBufferImpl->EndRenderPass();
+ mCommandBufferImpl->EndRenderPass();
}
void CommandBuffer::ExecuteCommandBuffers(std::vector<const Graphics::CommandBuffer*>&& commandBuffers)
{
}
-void CommandBuffer::Reset()
-{
-}
-
void CommandBuffer::SetScissor(Rect2D value)
{
}
{
}
+Swapchain* CommandBuffer::GetLastSwapchain() const
+{
+ return mLastSwapchain;
+}
+
} // namespace Dali::Graphics::Vulkan
namespace Dali::Graphics::Vulkan
{
class CommandBufferImpl;
+class Swapchain;
using CommandBufferResource = Resource<Graphics::CommandBuffer, Graphics::CommandBufferCreateInfo>;
*/
void SetDepthWriteEnable(bool depthWriteEnable) override;
+public: //API
+ /**
+ * Get the last swapchain referenced by a BeginRenderPass command in this command buffer.
+ *
+ * @todo Should split the command buffer up into multiple buffers if there is more than one
+ * render target referenced in it.
+ */
+ Swapchain* GetLastSwapchain() const;
+
+ CommandBufferImpl* GetImpl() const
+ {
+ return mCommandBufferImpl;
+ }
+
private:
CommandBufferImpl* mCommandBufferImpl;
+ Swapchain* mLastSwapchain{nullptr};
};
} // namespace Dali::Graphics::Vulkan
#include <dali/internal/graphics/vulkan-impl/vulkan-image-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-image-view-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-render-pass.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-types.h>
#include <dali/internal/graphics/vulkan/vulkan-device.h>
#include <dali/integration-api/debug.h>
std::vector<FramebufferAttachment*>& attachments,
uint32_t width,
uint32_t height,
- bool hasDepthAttachments,
- bool takeRenderPassOwnership)
+ bool hasDepthAttachments)
{
std::vector<vk::ImageView> imageViewAttachments;
+ DALI_ASSERT_ALWAYS(renderPass != nullptr && "You require more render passes!");
+
std::transform(attachments.cbegin(),
attachments.cend(),
std::back_inserter(imageViewAttachments),
return new FramebufferImpl(device,
attachments,
vkFramebuffer,
- renderPass->GetVkHandle(),
+ *renderPass,
width,
height,
- hasDepthAttachments,
- takeRenderPassOwnership);
+ hasDepthAttachments);
}
FramebufferImpl* FramebufferImpl::New(
auto attachments = std::vector<FramebufferAttachment*>{};
// Flag that indicates if the render pass is externally provided
- bool renderPassTakeOwnership = false;
if(renderPass == nullptr)
{
- renderPass = RenderPassImpl::New(device, colorAttachments, depthAttachment);
- renderPassTakeOwnership = true;
+ // Create compatible render pass
+ renderPass = RenderPassImpl::New(device, colorAttachments, depthAttachment);
}
attachments.reserve(colorAttachments.size());
attachments.insert(attachments.begin(), colorAttachments.begin(), colorAttachments.end());
{
attachments.push_back(depthAttachment);
}
- return FramebufferImpl::New(device, renderPass, attachments, width, height, hasDepth, renderPassTakeOwnership);
+ return FramebufferImpl::New(device, renderPass, attachments, width, height, hasDepth);
}
FramebufferImpl::FramebufferImpl(Device& graphicsDevice,
const std::vector<FramebufferAttachment*>& attachments,
vk::Framebuffer vkHandle,
- vk::RenderPass renderPass,
+ const RenderPassImpl& renderPassImpl,
uint32_t width,
uint32_t height,
- bool hasDepthAttachment,
- bool takeRenderPassOwnership)
+ bool hasDepthAttachment)
: mGraphicsDevice(&graphicsDevice),
mWidth(width),
mHeight(height),
mAttachments(attachments),
mFramebuffer(vkHandle),
- mRenderPass(renderPass),
- mHasDepthAttachment(hasDepthAttachment),
- mRenderPassOwned(takeRenderPassOwnership)
+ mHasDepthAttachment(hasDepthAttachment)
{
+ mRenderPasses.push_back(RenderPassMapElement{nullptr, const_cast<RenderPassImpl*>(&renderPassImpl)});
}
uint32_t FramebufferImpl::GetWidth() const
return 0u;
}
-vk::RenderPass FramebufferImpl::GetRenderPass() const
+RenderPassImpl* FramebufferImpl::GetRenderPass(RenderPass* renderPass)
{
- return mRenderPass;
+ auto attachments = renderPass->GetCreateInfo().attachments;
+ auto matchLoadOp = attachments->front().loadOp;
+ auto matchStoreOp = attachments->front().storeOp;
+
+ for(auto& element : mRenderPasses)
+ {
+ // Test renderpass first
+ if(element.renderPass != nullptr)
+ {
+ auto firstAttachment = element.renderPass->GetCreateInfo().attachments->front();
+ if(firstAttachment.loadOp == matchLoadOp &&
+ firstAttachment.storeOp == matchStoreOp)
+ {
+ return element.renderPassImpl;
+ }
+ }
+ else
+ {
+ DALI_ASSERT_DEBUG(element.renderPassImpl != nullptr && "Render pass list doesn't contain impl");
+ auto createInfo = element.renderPassImpl->GetCreateInfo();
+
+ if(createInfo.attachmentDescriptions[0].loadOp == VkLoadOpType(matchLoadOp).loadOp &&
+ createInfo.attachmentDescriptions[0].storeOp == VkStoreOpType(matchStoreOp).storeOp)
+ {
+ // Point at passed in render pass... should be a weak ptr... What's lifecycle?!
+ element.renderPass = renderPass;
+ return element.renderPassImpl;
+ }
+ }
+ }
+
+ // @todo create new render pass from existing + load/store op, add it to mRenderPasses, and return it.
+
+ return mRenderPasses[0].renderPassImpl;
}
vk::Framebuffer FramebufferImpl::GetVkHandle() const
auto device = mGraphicsDevice->GetLogicalDevice();
auto frameBuffer = mFramebuffer;
- vk::RenderPass renderPass = mRenderPassOwned ? mRenderPass : vk::RenderPass{};
+ ///@todo Destroy all render passes.
+ vk::RenderPass renderPass = mRenderPasses[0].renderPassImpl->GetVkHandle();
auto allocator = &mGraphicsDevice->GetAllocator();
{
DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: render pass->%p\n", static_cast<VkRenderPass>(renderPass))
device.destroyRenderPass(renderPass, allocator);
- }
- });
+ } });
return false;
}
namespace Dali::Graphics::Vulkan
{
+class RenderPass;
class RenderPassImpl;
enum class AttachmentType
std::vector<FramebufferAttachment*>& attachments,
uint32_t width,
uint32_t height,
- bool hasDepthAttachment,
- bool takeRenderPassOwnership);
+ bool hasDepthAttachment);
static FramebufferImpl* New(
Vulkan::Device& device,
FramebufferImpl(Device& graphicsDevice,
const std::vector<FramebufferAttachment*>& attachments,
vk::Framebuffer vkHandle,
- vk::RenderPass renderPass,
+ const RenderPassImpl& renderPass,
uint32_t width,
uint32_t height,
- bool hasDepthAttachment,
- bool takeRenderPassOwnership);
+ bool hasDepthAttachment);
[[nodiscard]] uint32_t GetWidth() const;
[[nodiscard]] uint32_t GetAttachmentCount(AttachmentType type) const;
- [[nodiscard]] vk::RenderPass GetRenderPass() const;
+ [[nodiscard]] RenderPassImpl* GetRenderPass(RenderPass* renderPass); // May mutate mRenderPasses
[[nodiscard]] vk::Framebuffer GetVkHandle() const;
uint32_t mWidth;
uint32_t mHeight;
+ /**
+ * Structure to map RenderPass to RenderPassImpl.
+ */
+ struct RenderPassMapElement
+ {
+ RenderPass* renderPass{nullptr};
+ RenderPassImpl* renderPassImpl{nullptr};
+ };
+ using RenderPasses = std::vector<RenderPassMapElement>;
+
std::vector<FramebufferAttachment*> mAttachments;
vk::Framebuffer mFramebuffer;
- vk::RenderPass mRenderPass;
+ RenderPasses mRenderPasses;
bool mHasDepthAttachment{false};
- bool mRenderPassOwned{false};
};
} // Namespace Dali::Graphics::Vulkan
bool Framebuffer::InitializeResource()
{
- /*
- * Renderpass handling.
- * We get passed VulkanRenderPass
- * For actual framebuffer creation, we need at least the first VulkanRenderPass to have a VulkanRenderPassImpl created
- * and for subsequent VulkanRenderPasses to be compatible with the first (and can be created on the fly)
- */
-
// Create attachments
- auto renderPass = static_cast<Vulkan::RenderPass*>(mCreateInfo.renderPasses[0]);
-
- auto renderPassImpl = renderPass->GetImpl(); // Only generate actual render pass if needed
- if(!renderPassImpl)
+ std::vector<FramebufferAttachment*> colorAttachments;
+ // for(auto& attachment : mCreateInfo.colorAttachments)
{
- renderPass->InitializeResource();
+ // auto graphicsTexture = static_cast<const Vulkan::Texture*>(attachment.texture);
+ // colorAttachments.push_back(FramebufferAttachment::NewColorAttachment(attachment.texture->GetVkHandle(), clearColor, AttachmentType::COLOR, false);
+ }
+ FramebufferAttachment* depthStencilAttachment{nullptr};
+ if(mCreateInfo.depthStencilAttachment.depthTexture || mCreateInfo.depthStencilAttachment.stencilTexture)
+ {
+ // depthStencilAttachment = FramebufferAttachment::NewDepthAttachment();
}
- auto& device = mController.GetGraphicsDevice();
- std::vector<FramebufferAttachment*> colorAttachments;
- FramebufferAttachment* depthStencilAttachment{nullptr};
- //@todo FINISH ME! (Needs texture -> image view bindings)
+ // Create initial render pass.
+ auto renderPassImpl = RenderPassImpl::New(mController.GetGraphicsDevice(),
+ colorAttachments,
+ depthStencilAttachment);
+
+ auto& device = mController.GetGraphicsDevice();
mFramebufferImpl = FramebufferImpl::New(device, renderPassImpl, colorAttachments, depthStencilAttachment, mCreateInfo.size.width, mCreateInfo.size.height);
- //@todo Store all the render passes here. Will be used later to generate compatible render pass impls.
return true;
}
#include <dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-render-pass.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-render-target.h>
+#include <dali/internal/window-system/common/window-render-surface.h>
namespace Dali::Graphics::Vulkan
{
void AcquireNextFramebuffer()
{
- // for all swapchains acquire new framebuffer
+ // @todo for all swapchains acquire new framebuffer
auto surface = mGraphicsDevice->GetSurface(0u);
auto swapchain = mGraphicsDevice->GetSwapchainForSurfaceId(0u);
return *this;
}
+void VulkanGraphicsController::FrameStart()
+{
+ mImpl->mCapacity = 0;
+ mImpl->AcquireNextFramebuffer();
+}
+
void VulkanGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
{
+ // Figure out where to submit each command buffer.
+ for(auto gfxCmdBuffer : submitInfo.cmdBuffer)
+ {
+ auto cmdBuffer = static_cast<const CommandBuffer*>(gfxCmdBuffer);
+ auto swapchain = cmdBuffer->GetLastSwapchain();
+ if(swapchain)
+ {
+ swapchain->Submit(cmdBuffer->GetImpl());
+ }
+ }
}
void VulkanGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderTarget)
{
- // Test code to create a render pass to clear the surface
- mImpl->AcquireNextFramebuffer();
-
- auto swapchain = mImpl->mGraphicsDevice->GetSwapchainForSurfaceId(0u);
-
- CommandPool* commandPool = mImpl->mGraphicsDevice->GetCommandPool(std::this_thread::get_id());
- auto primaryCommandBuffer = commandPool->NewCommandBuffer(true);
-
- primaryCommandBuffer->Begin(vk::CommandBufferUsageFlagBits::eOneTimeSubmit, nullptr);
- primaryCommandBuffer->BeginRenderPass(vk::RenderPassBeginInfo{}
- .setFramebuffer(swapchain->GetCurrentFramebuffer()->GetVkHandle())
- .setRenderPass(swapchain->GetCurrentFramebuffer()->GetRenderPass())
- .setRenderArea({{0, 0}, {swapchain->GetCurrentFramebuffer()->GetWidth(), swapchain->GetCurrentFramebuffer()->GetHeight()}})
- .setPClearValues(swapchain->GetCurrentFramebuffer()->GetClearValues().data())
- .setClearValueCount(uint32_t(swapchain->GetCurrentFramebuffer()->GetClearValues().size())),
- vk::SubpassContents::eInline);
- primaryCommandBuffer->EndRenderPass();
- primaryCommandBuffer->End();
-
- // Submit command buffer
- swapchain->Submit(primaryCommandBuffer);
+ auto surface = static_cast<Vulkan::RenderTarget*>(renderTarget)->GetSurface();
+ auto surfaceId = static_cast<Internal::Adaptor::WindowRenderSurface*>(surface)->GetSurfaceId();
+ auto swapchain = mImpl->mGraphicsDevice->GetSwapchainForSurfaceId(surfaceId);
swapchain->Present();
}
UniquePtr<Graphics::RenderPass> VulkanGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, UniquePtr<Graphics::RenderPass>&& oldRenderPass)
{
- // If this is for a surface, then we already have a render pass hidden inside the swapchain...
- // The surface should have a GraphicsSurfaceId, which can be used to get the swapchain.
- // But, we want to create multiple render passes in Core on a scene's surface...
- // Now, renderPassCreateInfo contains renderTarget, so this implementation can decide to generate
- // surface's swapchain framebuffers based on this new renderpass. Though, should be explicit about it!
- auto renderPass = NewObject<Vulkan::RenderPass>(renderPassCreateInfo, *this, std::move(oldRenderPass));
+ auto renderPass = UniquePtr<Graphics::RenderPass>(new Vulkan::RenderPass(renderPassCreateInfo, *this));
- //auto vkRenderPass = static_cast<Vulkan::RenderPass*>(renderPass.get());
- //vkRenderPass->InitializeResource(); // This may create an actual resource.
+ // Don't create actual vulkan resource here. It will instead be done on demand. (e.g. framebuffer creation, CommandBuffer::BeginRenderPass())
return renderPass;
}
return texture;
}
-void VulkanGraphicsController::FrameStart()
-{
- mImpl->mCapacity = 0;
-}
-
std::size_t VulkanGraphicsController::GetCapacity() const
{
return mImpl->mCapacity;
#include <dali/internal/graphics/vulkan-impl/vulkan-render-pass-impl.h>
-#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.h>
-
#include <dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-image-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-image-view-impl.h>
namespace Dali::Graphics::Vulkan
{
-namespace
-{
-vk::RenderPass CreateCompatibleRenderPass(
+
+RenderPassImpl* RenderPassImpl::New(
Vulkan::Device& device,
const std::vector<FramebufferAttachment*>& colorAttachments,
- FramebufferAttachment* depthAttachment,
- std::vector<vk::ImageView>& attachments)
+ FramebufferAttachment* depthAttachment)
+{
+ auto renderPass = new RenderPassImpl(device, colorAttachments, depthAttachment);
+ return renderPass;
+}
+
+RenderPassImpl::RenderPassImpl(Vulkan::Device& device,
+ const std::vector<FramebufferAttachment*>& colorAttachments,
+ FramebufferAttachment* depthAttachment)
+: mGraphicsDevice(&device)
+{
+ CreateCompatibleCreateInfo(colorAttachments, depthAttachment);
+ CreateRenderPass();
+}
+
+RenderPassImpl::~RenderPassImpl() = default;
+
+vk::RenderPass RenderPassImpl::GetVkHandle()
+{
+ return mVkRenderPass;
+}
+
+bool RenderPassImpl::OnDestroy()
+{
+ if(mVkRenderPass)
+ {
+ auto device = mGraphicsDevice->GetLogicalDevice();
+ auto allocator = &mGraphicsDevice->GetAllocator();
+ auto renderPass = mVkRenderPass;
+ mGraphicsDevice->DiscardResource([device, renderPass, allocator]()
+ {
+ DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: swap chain->%p\n", static_cast<VkRenderPass>(renderPass))
+ device.destroyRenderPass(renderPass, allocator); });
+
+ mVkRenderPass = nullptr;
+ }
+ return false;
+}
+
+std::vector<vk::ImageView>& RenderPassImpl::GetAttachments()
+{
+ return mAttachments;
+}
+
+void RenderPassImpl::CreateCompatibleCreateInfo(
+ const std::vector<FramebufferAttachment*>& colorAttachments,
+ FramebufferAttachment* depthAttachment)
{
auto hasDepth = false;
if(depthAttachment)
// The total number of attachments
auto totalAttachmentCount = hasDepth ? colorAttachments.size() + 1 : colorAttachments.size();
- attachments.clear();
- attachments.reserve(totalAttachmentCount);
+ mAttachments.clear();
+ mAttachments.reserve(totalAttachmentCount);
// This vector stores the attachment references
- auto colorAttachmentReferences = std::vector<vk::AttachmentReference>{};
- colorAttachmentReferences.reserve(colorAttachments.size());
+ mCreateInfo.colorAttachmentReferences.reserve(colorAttachments.size());
// This vector stores the attachment descriptions
- auto attachmentDescriptions = std::vector<vk::AttachmentDescription>{};
- attachmentDescriptions.reserve(totalAttachmentCount);
+ mCreateInfo.attachmentDescriptions.reserve(totalAttachmentCount);
// For each color attachment...
for(auto i = 0u; i < colorAttachments.size(); ++i)
assert(imageLayout == vk::ImageLayout::eColorAttachmentOptimal);
// Add a reference and a descriptions and image views to their respective vectors
- colorAttachmentReferences.push_back(vk::AttachmentReference{}.setLayout(imageLayout).setAttachment(U32(i)));
+ mCreateInfo.colorAttachmentReferences.push_back(vk::AttachmentReference{}.setLayout(imageLayout).setAttachment(U32(i)));
- attachmentDescriptions.push_back(colorAttachments[i]->GetDescription());
+ mCreateInfo.attachmentDescriptions.push_back(colorAttachments[i]->GetDescription());
- attachments.push_back(colorAttachments[i]->GetImageView()->GetVkHandle());
+ mAttachments.push_back(colorAttachments[i]->GetImageView()->GetVkHandle());
}
// Follow the exact same procedure as color attachments
- auto depthAttachmentReference = vk::AttachmentReference{};
if(hasDepth)
{
auto imageLayout = depthAttachment->GetImageView()->GetImage()->GetImageLayout();
assert(imageLayout == vk::ImageLayout::eDepthStencilAttachmentOptimal);
- depthAttachmentReference.setLayout(imageLayout);
- depthAttachmentReference.setAttachment(U32(colorAttachmentReferences.size()));
+ mCreateInfo.depthAttachmentReference.setLayout(imageLayout);
+ mCreateInfo.depthAttachmentReference.setAttachment(U32(mCreateInfo.colorAttachmentReferences.size()));
- attachmentDescriptions.push_back(depthAttachment->GetDescription());
+ mCreateInfo.attachmentDescriptions.push_back(depthAttachment->GetDescription());
- attachments.push_back(depthAttachment->GetImageView()->GetVkHandle());
+ mAttachments.push_back(depthAttachment->GetImageView()->GetVkHandle());
}
// Creating a single subpass per framebuffer
- auto subpassDesc = vk::SubpassDescription{};
- subpassDesc.setPipelineBindPoint(vk::PipelineBindPoint::eGraphics);
- subpassDesc.setColorAttachmentCount(U32(colorAttachments.size()));
+ mCreateInfo.subpassDesc.setPipelineBindPoint(vk::PipelineBindPoint::eGraphics);
+ mCreateInfo.subpassDesc.setColorAttachmentCount(U32(colorAttachments.size()));
if(hasDepth)
{
- subpassDesc.setPDepthStencilAttachment(&depthAttachmentReference);
+ mCreateInfo.subpassDesc.setPDepthStencilAttachment(&mCreateInfo.depthAttachmentReference);
}
- subpassDesc.setPColorAttachments(colorAttachmentReferences.data());
+ mCreateInfo.subpassDesc.setPColorAttachments(mCreateInfo.colorAttachmentReferences.data());
// Creating 2 subpass dependencies using VK_SUBPASS_EXTERNAL to leverage the implicit image layout
// transitions provided by the driver
- std::array<vk::SubpassDependency, 2> subpassDependencies{
-
- vk::SubpassDependency{}.setSrcSubpass(VK_SUBPASS_EXTERNAL).setDstSubpass(0).setSrcStageMask(vk::PipelineStageFlagBits::eBottomOfPipe).setDstStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput).setSrcAccessMask(vk::AccessFlagBits::eMemoryRead).setDstAccessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite).setDependencyFlags(vk::DependencyFlagBits::eByRegion),
-
- vk::SubpassDependency{}.setSrcSubpass(0).setDstSubpass(VK_SUBPASS_EXTERNAL).setSrcStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput).setDstStageMask(vk::PipelineStageFlagBits::eBottomOfPipe).setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite).setDstAccessMask(vk::AccessFlagBits::eMemoryRead).setDependencyFlags(vk::DependencyFlagBits::eByRegion)
-
- };
-
- // Create the render pass
- auto renderPassCreateInfo = vk::RenderPassCreateInfo{}.setAttachmentCount(U32(attachmentDescriptions.size())).setPAttachments(attachmentDescriptions.data()).setPSubpasses(&subpassDesc).setSubpassCount(1).setPDependencies(subpassDependencies.data());
-
- auto vkRenderPass = VkAssert(device.GetLogicalDevice().createRenderPass(renderPassCreateInfo, device.GetAllocator()));
- return vkRenderPass;
-}
-
-} // namespace
-
-RenderPassImpl* RenderPassImpl::New(
- Vulkan::Device& device,
- const std::vector<FramebufferAttachment*>& colorAttachments,
- FramebufferAttachment* depthAttachment)
-{
- std::vector<vk::ImageView> attachments{};
- auto vkRenderPass = CreateCompatibleRenderPass(device, colorAttachments, depthAttachment, attachments);
-
- auto renderPass = new RenderPassImpl(device, vkRenderPass);
- renderPass->SetAttachments(attachments);
- return renderPass;
-}
-
-RenderPassImpl::RenderPassImpl(Vulkan::Device& device, vk::RenderPass renderPass)
-: mGraphicsDevice(&device),
- mVkRenderPass(renderPass)
-{
-}
-
-RenderPassImpl::RenderPassImpl(
- Vulkan::Device& device,
- const Graphics::RenderPassCreateInfo& createInfo,
- std::vector<FramebufferAttachment*>& colorAttachments,
- FramebufferAttachment* depthAttachment)
-: mGraphicsDevice(&device)
-{
- // @todo Do mostly as CreateCompatibleRenderPass above, but instead, get the attachment
- // descriptions from the createInfo passed in here.
- mVkRenderPass = CreateCompatibleRenderPass(*mGraphicsDevice, colorAttachments, depthAttachment, mAttachments);
-}
-
-RenderPassImpl::~RenderPassImpl() = default;
-
-vk::RenderPass RenderPassImpl::GetVkHandle()
-{
- return mVkRenderPass;
-}
-
-bool RenderPassImpl::OnDestroy()
-{
- if(mVkRenderPass)
- {
- auto device = mGraphicsDevice->GetLogicalDevice();
- auto allocator = &mGraphicsDevice->GetAllocator();
- auto renderPass = mVkRenderPass;
- mGraphicsDevice->DiscardResource([device, renderPass, allocator]()
- {
- DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: swap chain->%p\n", static_cast<VkRenderPass>(renderPass))
- device.destroyRenderPass(renderPass, allocator); });
-
- mVkRenderPass = nullptr;
- }
- return false;
-}
-
-std::vector<vk::ImageView>& RenderPassImpl::GetAttachments()
-{
- return mAttachments;
+ mCreateInfo.subpassDependencies = {
+ vk::SubpassDependency{}
+ .setSrcSubpass(VK_SUBPASS_EXTERNAL)
+ .setDstSubpass(0)
+ .setSrcStageMask(vk::PipelineStageFlagBits::eBottomOfPipe)
+ .setDstStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput)
+ .setSrcAccessMask(vk::AccessFlagBits::eMemoryRead)
+ .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite)
+ .setDependencyFlags(vk::DependencyFlagBits::eByRegion),
+
+ vk::SubpassDependency{}
+ .setSrcSubpass(0)
+ .setDstSubpass(VK_SUBPASS_EXTERNAL)
+ .setSrcStageMask(vk::PipelineStageFlagBits::eColorAttachmentOutput)
+ .setDstStageMask(vk::PipelineStageFlagBits::eBottomOfPipe)
+ .setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentRead | vk::AccessFlagBits::eColorAttachmentWrite)
+ .setDstAccessMask(vk::AccessFlagBits::eMemoryRead)
+ .setDependencyFlags(vk::DependencyFlagBits::eByRegion)};
+
+ mCreateInfo.createInfo.setAttachmentCount(U32(mCreateInfo.attachmentDescriptions.size()))
+ .setPAttachments(mCreateInfo.attachmentDescriptions.data())
+ .setPSubpasses(&mCreateInfo.subpassDesc)
+ .setSubpassCount(1)
+ .setPDependencies(mCreateInfo.subpassDependencies.data());
}
-void RenderPassImpl::SetAttachments(std::vector<vk::ImageView>& attachments)
+void RenderPassImpl::CreateRenderPass()
{
- // @todo Remove? How can we late bind attachments? Recreate the whole RP?
- mAttachments = std::move(attachments);
+ mVkRenderPass = VkAssert(mGraphicsDevice->GetLogicalDevice().createRenderPass(mCreateInfo.createInfo, mGraphicsDevice->GetAllocator()));
}
} // namespace Dali::Graphics::Vulkan
class VulkanGraphicsController;
class RenderTarget;
+/**
+ * Holder class for Vulkan RenderPass object.
+ *
+ * We need a render pass to create a Framebuffer; this can create a
+ * compatible render pass given the specific attachments.
+ *
+ * FramebufferImpl will own it's RenderPassImpl(s), NOT the Graphics::RenderPass
+ * implementation.
+ *
+ * When we want to use the FramebufferImpl (CommandBuffer::BeginRenderPass), then
+ * we try and match the supplied Graphics::RenderPass to the creating render pass.
+ * FramebufferImpl will create a separate compatible RenderPassImpl if a matching
+ * render pass is NOT found.
+ */
class RenderPassImpl final : public Dali::Graphics::Vulkan::VkManaged
{
public:
+ struct CreateInfo
+ {
+ std::vector<vk::AttachmentReference> colorAttachmentReferences;
+ vk::AttachmentReference depthAttachmentReference;
+ std::vector<vk::AttachmentDescription> attachmentDescriptions;
+ vk::SubpassDescription subpassDesc;
+ std::array<vk::SubpassDependency, 2> subpassDependencies;
+ vk::RenderPassCreateInfo createInfo;
+ };
+
static RenderPassImpl* New(
Vulkan::Device& device,
const std::vector<FramebufferAttachment*>& colorAttachments,
FramebufferAttachment* depthAttachment);
- RenderPassImpl(Vulkan::Device& device, vk::RenderPass renderPass);
-
- RenderPassImpl(Vulkan::Device& device, const Graphics::RenderPassCreateInfo& createInfo, std::vector<FramebufferAttachment*>& colorAttachments, FramebufferAttachment* depthAttachment);
+ RenderPassImpl(Vulkan::Device& device, const std::vector<FramebufferAttachment*>& colorAttachments, FramebufferAttachment* depthAttachment);
~RenderPassImpl() override;
vk::RenderPass GetVkHandle();
+ bool OnDestroy() override;
+
std::vector<vk::ImageView>& GetAttachments();
- void SetAttachments(std::vector<vk::ImageView>& attachments);
+ CreateInfo& GetCreateInfo()
+ {
+ return mCreateInfo;
+ }
- bool OnDestroy() override;
+private:
+ void CreateCompatibleCreateInfo(
+ const std::vector<FramebufferAttachment*>& colorAttachments,
+ FramebufferAttachment* depthAttachment);
+
+ void CreateRenderPass();
private:
Device* mGraphicsDevice;
+ CreateInfo mCreateInfo;
vk::RenderPass mVkRenderPass;
std::vector<vk::ImageView> mAttachments{};
};
namespace Dali::Graphics::Vulkan
{
RenderPass::RenderPass(const Graphics::RenderPassCreateInfo& createInfo, VulkanGraphicsController& controller)
-: RenderPassResource(createInfo, controller),
- mRenderPassImpl(nullptr)
+: mCreateInfo(createInfo),
+ mController(controller)
{
-}
-
-RenderPass::~RenderPass() = default;
-
-bool RenderPass::InitializeResource()
-{
- auto renderTarget = static_cast<RenderTarget*>(mCreateInfo.renderTarget);
- auto framebuffer = renderTarget->GetFramebuffer();
- if(framebuffer)
- {
- auto vkFramebuffer = framebuffer->GetImpl();
-
- // Note, Vulkan framebuffer can now be used with compatible render passes in vkBeginRenderPass.
- // So we can create multiple render passes.
-
- std::vector<FramebufferAttachment*> colorAttachments = vkFramebuffer->GetAttachments(AttachmentType::COLOR);
- ;
- std::vector<FramebufferAttachment*> depthAttachment = vkFramebuffer->GetAttachments(AttachmentType::DEPTH_STENCIL);
- ;
-
- mRenderPassImpl = new RenderPassImpl(mController.GetGraphicsDevice(), mCreateInfo, colorAttachments, depthAttachment[0]);
- }
- else
+ if(createInfo.attachments)
{
- // RenderTarget must be a surface.
- // Create a new render pass that's compatible with the surface's framebuffer.
- //
- // Does that mean it has to use the fbo's color attachment? YES.
- // I.e. should we generate separate RenderPassImpls for each of the surface's framebuffers?
- // GetImpl() then needs bufferIndex
+ mAttachments.insert(mAttachments.end(), createInfo.attachments->begin(), createInfo.attachments->end());
+ mCreateInfo.attachments = &mAttachments;
}
- return true;
}
-void RenderPass::DestroyResource()
-{
-}
-
-void RenderPass::DiscardResource()
-{
-}
-
-RenderPassImpl* RenderPass::GetImpl()
-{
- return mRenderPassImpl;
-}
+RenderPass::~RenderPass() = default;
} // namespace Dali::Graphics::Vulkan
#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-resource.h>
-#include <dali/graphics-api/graphics-render-pass.h>
#include <dali/graphics-api/graphics-render-pass-create-info.h>
+#include <dali/graphics-api/graphics-render-pass.h>
namespace Dali::Graphics::Vulkan
{
class RenderPassImpl;
-using RenderPassResource = Resource<Graphics::RenderPass, Graphics::RenderPassCreateInfo>;
-class RenderPass : public RenderPassResource
+/**
+ * This class represents a set of render pass operations.
+ *
+ * This class is not directly associated with a graphics resource, and is not
+ * responsible for the lifetime of actual vulkan render pass objects. That is
+ * instead the responsibility of the Framebuffer implementation.
+ *
+ * When this render pass is used, the Framebuffer will find or create a compatible
+ * render pass implementation, and cache it.
+ */
+class RenderPass : public Graphics::RenderPass
{
public:
RenderPass(const Graphics::RenderPassCreateInfo& createInfo, VulkanGraphicsController& controller);
~RenderPass() override;
- /**
- * @brief Called when GL resources are destroyed
- */
- void DestroyResource() override;
-
- /**
- * @brief Called when initializing the resource
- *
- * @return True on success
- */
- bool InitializeResource() override;
-
- /**
- * @brief Called when UniquePtr<> on client-side dies
- */
- void DiscardResource() override;
-
- RenderPassImpl* GetImpl();
+ [[nodiscard]] const Graphics::RenderPassCreateInfo& GetCreateInfo() const
+ {
+ return mCreateInfo;
+ }
private:
- RenderPassImpl* mRenderPassImpl;
+ Graphics::RenderPassCreateInfo mCreateInfo;
+ VulkanGraphicsController& mController;
+ std::vector<Graphics::AttachmentDescription> mAttachments;
};
} // namespace Dali::Graphics::Vulkan
#include <dali/internal/graphics/vulkan-impl/vulkan-swapchain-impl.h>
#include <dali/internal/graphics/vulkan/vulkan-device.h>
-#if 0
-#include <dali/internal/graphics/vulkan-impl/vulkan-debug.h>
-#include <dali/internal/graphics/vulkan-impl/vulkan-image-view.h>
-#include <dali/internal/graphics/vulkan-impl/vulkan-image.h>
-#include <dali/internal/graphics/vulkan-impl/vulkan-queue.h>
-#endif
-
#include <dali/integration-api/debug.h>
#if defined(DEBUG_ENABLED)
auto presentModes = surface->GetSurfacePresentModes();
auto found = std::find_if(presentModes.begin(),
presentModes.end(),
- [&](vk::PresentModeKHR mode)
- {
+ [&](vk::PresentModeKHR mode) {
return presentMode == mode;
});
auto swapchain = mSwapchainKHR;
auto allocator = &mGraphicsDevice.GetAllocator();
- mGraphicsDevice.DiscardResource([device, swapchain, allocator]()
- {
+ mGraphicsDevice.DiscardResource([device, swapchain, allocator]() {
DALI_LOG_INFO(gVulkanFilter, Debug::General, "Invoking deleter function: swap chain->%p\n", static_cast<VkSwapchainKHR>(swapchain))
device.destroySwapchainKHR(swapchain, allocator); });
// EXTERNAL INCLUDES
#include <atomic>
-#include <unordered_map>
-#include <memory>
#include <bitset>
+#include <memory>
+#include <unordered_map>
+#include <dali/graphics-api/graphics-types.h>
#include <dali/internal/graphics/vulkan/vulkan-hpp-wrapper.h>
// Ensure we can use this type name safely.
#undef WAYLAND
#endif
-
namespace Dali::Graphics
{
{
// Default value use to clear the stencil buffer
constexpr auto STENCIL_DEFAULT_CLEAR_VALUE = 255u;
-}
+} // namespace
-template< typename T, typename... Args >
-std::unique_ptr< T > MakeUnique( Args&& ... args )
+template<typename T, typename... Args>
+std::unique_ptr<T> MakeUnique(Args&&... args)
{
- return std::unique_ptr< T >( new T( std::forward< Args >( args )... ) );
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
namespace Vulkan
/**
* Unique pointers to Vulkan types
*/
-using UniqueQueue = std::unique_ptr< Queue >;
+using UniqueQueue = std::unique_ptr<Queue>;
/**
* Reference wrappers
*/
-using QueueRef = std::reference_wrapper< Queue >;
+using QueueRef = std::reference_wrapper<Queue>;
-template< typename T >
-T VkAssert( const vk::ResultValue< T >& result, vk::Result expected = vk::Result::eSuccess )
+template<typename T>
+T VkAssert(const vk::ResultValue<T>& result, vk::Result expected = vk::Result::eSuccess)
{
- assert( result.result == expected );
+ assert(result.result == expected);
return result.value;
}
-inline vk::Result VkAssert( vk::Result result, vk::Result expected = vk::Result::eSuccess )
+inline vk::Result VkAssert(vk::Result result, vk::Result expected = vk::Result::eSuccess)
{
- assert( result == expected );
+ assert(result == expected);
return result;
}
-inline vk::Result VkTest( vk::Result result, vk::Result expected = vk::Result::eSuccess )
+inline vk::Result VkTest(vk::Result result, vk::Result expected = vk::Result::eSuccess)
{
// todo: log if result different than expected?
return result;
}
-template< typename T >
-inline uint32_t U32( T value )
+template<typename T>
+inline uint32_t U32(T value)
{
- return static_cast< uint32_t >(value);
+ return static_cast<uint32_t>(value);
}
-template <typename T>
-inline int32_t I32( T value )
+template<typename T>
+inline int32_t I32(T value)
{
- return static_cast< int32_t >( value );
+ return static_cast<int32_t>(value);
}
-template <typename T>
-inline float F32( T value )
+template<typename T>
+inline float F32(T value)
{
- return static_cast< float >( value );
+ return static_cast<float>(value);
}
-template <typename T>
-inline double F64( T value )
+template<typename T>
+inline double F64(T value)
{
- return static_cast< double >( value );
+ return static_cast<double>(value);
}
enum class Platform
WAYLAND,
};
+struct VkLoadOpType
+{
+ constexpr explicit VkLoadOpType(Graphics::AttachmentLoadOp op)
+ {
+ switch(op)
+ {
+ case Graphics::AttachmentLoadOp::LOAD:
+ {
+ loadOp = vk::AttachmentLoadOp::eLoad;
+ break;
+ }
+ case Graphics::AttachmentLoadOp::CLEAR:
+ {
+ loadOp = vk::AttachmentLoadOp::eClear;
+ break;
+ }
+ case Graphics::AttachmentLoadOp::DONT_CARE:
+ {
+ loadOp = vk::AttachmentLoadOp::eDontCare;
+ break;
+ }
+ }
+ }
+ vk::AttachmentLoadOp loadOp{vk::AttachmentLoadOp::eDontCare};
+};
+
+struct VkStoreOpType
+{
+ constexpr explicit VkStoreOpType(Graphics::AttachmentStoreOp op)
+ {
+ switch(op)
+ {
+ case Graphics::AttachmentStoreOp::STORE:
+ {
+ Assign(vk::AttachmentStoreOp::eStore);
+ break;
+ }
+ case Graphics::AttachmentStoreOp::DONT_CARE:
+ {
+ Assign(vk::AttachmentStoreOp::eDontCare);
+ break;
+ }
+ }
+ }
+ constexpr inline void Assign(vk::AttachmentStoreOp op)
+ {
+ storeOp = op;
+ }
+ vk::AttachmentStoreOp storeOp{vk::AttachmentStoreOp::eDontCare};
+};
+
class VkManaged
{
public:
-
VkManaged() = default;
virtual ~VkManaged() = default;
void Release()
{
- OnRelease( --mRefCount );
+ OnRelease(--mRefCount);
- if( mRefCount == 0 )
+ if(mRefCount == 0)
{
// orphaned
- if( !Destroy() )
+ if(!Destroy())
{
delete this;
}
void Retain()
{
- OnRetain( ++mRefCount );
+ OnRetain(++mRefCount);
}
uint32_t GetRefCount()
return OnDestroy();
}
- virtual void OnRetain( uint32_t refcount )
+ virtual void OnRetain(uint32_t refcount)
{
}
- virtual void OnRelease( uint32_t refcount )
+ virtual void OnRelease(uint32_t refcount)
{
}
}
private:
-
- std::atomic_uint mRefCount{ 0u };
+ std::atomic_uint mRefCount{0u};
};
-
} // namespace Vulkan
} // namespace Dali::Graphics
-
#endif // DALI_GRAPHICS_VULKAN_TYPES