vulkan ui system

This commit is contained in:
ouczbs 2024-12-31 15:10:42 +08:00
parent 53e206e7c2
commit 2ea409e6d2
8 changed files with 81 additions and 113 deletions

View File

@ -44,6 +44,7 @@ namespace api {
mWindows.push_back(ptr); mWindows.push_back(ptr);
return ptr; return ptr;
} }
virtual void Render(FrameGraph& graph, RenderPassContext& ctx) = 0;
ImTextureID AddTexture(FrameGraph& graph, TextureDesc& desc, TextureSampler sampler); ImTextureID AddTexture(FrameGraph& graph, TextureDesc& desc, TextureSampler sampler);
virtual ImTextureID AddTexture(ImageViewPtr imageview, SamplerPtr sampler, ResourceState state) = 0; virtual ImTextureID AddTexture(ImageViewPtr imageview, SamplerPtr sampler, ResourceState state) = 0;
}; };

View File

@ -84,6 +84,11 @@ namespace api {
UITexture* uiTex = (UITexture*)texture; UITexture* uiTex = (UITexture*)texture;
TextureUpdateArgs args{.x = x, .y = y, .width = width,.height = height, .mipLevel = level, .data = data}; TextureUpdateArgs args{.x = x, .y = y, .width = width,.height = height, .mipLevel = level, .data = data};
Context().UpdateTexture(uiTex->desc, args, ResourceState::TRANSFER_DST); Context().UpdateTexture(uiTex->desc, args, ResourceState::TRANSFER_DST);
for (auto& barrier : mTextureBarriers) {
if (barrier.mTexture.image == uiTex->desc.image) {
return;
}
}
mTextureBarriers.push_back(uiTex->desc.ToBarrier(ResourceState::TRANSFER_DST, ResourceState::READ_ONLY)); mTextureBarriers.push_back(uiTex->desc.ToBarrier(ResourceState::TRANSFER_DST, ResourceState::READ_ONLY));
} }
void UIRenderDevice::BeginOffscreenRender() void UIRenderDevice::BeginOffscreenRender()

View File

@ -3,7 +3,7 @@
#include "asset/res/guid.h" #include "asset/res/guid.h"
#include "backend.h" #include "backend.h"
#ifdef API_DEBUG #ifdef API_DEBUG
#define gLogSemaphore(...) zlog::error(__VA_ARGS__) #define gLogSemaphore(...) //zlog::info(__VA_ARGS__)
#else #else
#define gLogSemaphore(...) #define gLogSemaphore(...)
#endif #endif

View File

@ -6,20 +6,15 @@ namespace vkn {
using api::FrameGraph; using api::FrameGraph;
using api::RenderPassContext; using api::RenderPassContext;
using api::RenderPassBuilder; using api::RenderPassBuilder;
using api::RenderEditorContext;
class VulkanImguiEditor : public api::EditorSystem { class VulkanImguiEditor : public api::EditorSystem {
public: public:
void Initialize() override; void Initialize() override;
void Finalize() override; void Finalize() override;
void Render(FrameGraph& graph, RenderPassContext& ctx) override;
ImTextureID AddTexture(ImageViewPtr imageview, SamplerPtr sampler, ResourceState state) override; ImTextureID AddTexture(ImageViewPtr imageview, SamplerPtr sampler, ResourceState state) override;
void Render(FrameGraph& graph, RenderEditorContext& ctx);
void OnBeginRenderFrame(FrameGraph& graph, uint32_t frame);
static VulkanImguiEditor* Ptr() { static VulkanImguiEditor* Ptr() {
return (VulkanImguiEditor*)api::EditorSystem::Ptr(); return (VulkanImguiEditor*)api::EditorSystem::Ptr();
}; };
static void Setup(FrameGraph& graph, RenderPassBuilder& builder);
static void Execute(FrameGraph&, RenderPassContext&);
}; };
} }

View File

@ -2,10 +2,16 @@
#include "vkn/vulkan_api.h" #include "vkn/vulkan_api.h"
#include "vkn/wrapper/device.h" #include "vkn/wrapper/device.h"
#include "ui/ui_render_system.h" #include "ui/ui_render_system.h"
#include "editor/editor_system.h"
#include "render/graph/frame_graph.h"
#include <NsCore/HashMap.h> #include <NsCore/HashMap.h>
namespace vkn { namespace vkn {
using Noesis::BaseVector; using Noesis::BaseVector;
using api::UITexture; using api::UITexture;
using api::FrameGraph;
using api::RenderPassContext;
using api::RenderPassBuilder;
using api::RenderEditorContext;
struct Layout struct Layout
{ {
uint32_t signature; uint32_t signature;
@ -52,9 +58,14 @@ namespace vkn {
VkShaderModule mPixelShaders[Noesis::Shader::Count]; VkShaderModule mPixelShaders[Noesis::Shader::Count];
Layout mLayouts[Noesis::Shader::Count]; Layout mLayouts[Noesis::Shader::Count];
public: public:
inline static Name UIPassName{ "UIPass" };
void InitNoesisRender(bool linearRendering, bool stereoSupport, SampleCount sampleCount)override; void InitNoesisRender(bool linearRendering, bool stereoSupport, SampleCount sampleCount)override;
void BeginRender(api::RenderContext* context) override; void BeginRender(api::RenderContext* context) override;
void DrawBatch(const Noesis::Batch& batch) override; void DrawBatch(const Noesis::Batch& batch) override;
public:
void OnBeginRenderFrame(FrameGraph& graph, uint32_t frame);
static void Setup(FrameGraph& graph, RenderPassBuilder& builder);
static void Execute(FrameGraph&, RenderPassContext&);
public: public:
void SetBuffers(const Noesis::Batch& batch); void SetBuffers(const Noesis::Batch& batch);
void BindDescriptors(const Noesis::Batch& batch, const Layout& layout); void BindDescriptors(const Noesis::Batch& batch, const Layout& layout);

View File

@ -5,6 +5,7 @@
#include "vkn/wrapper/device.h" #include "vkn/wrapper/device.h"
#include "vkn/wrapper/instance.h" #include "vkn/wrapper/instance.h"
#include "vkn/wrapper/queue.h" #include "vkn/wrapper/queue.h"
#include "vkn/vulkan_ui_system.h"
#include "imgui/imgui_impl_vulkan.h" #include "imgui/imgui_impl_vulkan.h"
#include "imgui/imgui_impl_sdl2.h" #include "imgui/imgui_impl_sdl2.h"
#include "data/global.h" #include "data/global.h"
@ -40,59 +41,6 @@ namespace vkn {
vkCreateDescriptorPool(device, &pool_info, VK_NULL_HANDLE, &descriptorPool); vkCreateDescriptorPool(device, &pool_info, VK_NULL_HANDLE, &descriptorPool);
return descriptorPool; return descriptorPool;
} }
VkRenderPass CreateRenderPass(TinyImageFormat format, VkDevice device) {
VkAttachmentDescription colorAttachment = {};
colorAttachment.format = (VkFormat)TinyImageFormat_ToVkFormat(format);
colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
colorAttachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VkAttachmentDescription stencilAttachment = {};
stencilAttachment.format = VK_FORMAT_S8_UINT;
stencilAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
stencilAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
stencilAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
stencilAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
stencilAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
stencilAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
stencilAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference colorAttachmentRef = {};
colorAttachmentRef.attachment = 0;
colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkSubpassDescription subpass = {};
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &colorAttachmentRef;
VkSubpassDependency dependency = {};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
VkAttachmentDescription attachmentList[2] = { colorAttachment , stencilAttachment };
VkRenderPassCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
info.attachmentCount = 2;
info.pAttachments = attachmentList;
info.subpassCount = 1;
info.pSubpasses = &subpass;
info.dependencyCount = 1;
info.pDependencies = &dependency;
VkRenderPass renderPass;
if (vkCreateRenderPass(device, &info, VK_NULL_HANDLE, &renderPass) != VK_SUCCESS)
throw std::runtime_error("Could not create Dear ImGui's render pass");
return renderPass;
}
void VulkanImguiEditor::Initialize() void VulkanImguiEditor::Initialize()
{ {
VulkanAPI* API = VulkanAPI::Ptr(); VulkanAPI* API = VulkanAPI::Ptr();
@ -101,7 +49,8 @@ namespace vkn {
Queue* pQueue = backend.GetDevice().GetQueue(Queue::RenderQueue); Queue* pQueue = backend.GetDevice().GetQueue(Queue::RenderQueue);
VkDescriptorPool descriptorPool = CreateDescriptorPool(backend.GetDevice().Ptr()); VkDescriptorPool descriptorPool = CreateDescriptorPool(backend.GetDevice().Ptr());
TextureDesc surface = API->context.surface; TextureDesc surface = API->context.surface;
VkRenderPass renderPass = CreateRenderPass(surface.format, backend.GetDevice().Ptr()); auto renderInfo = API->GetRenderPassInfo(VulkanUISystem::UIPassName, 0);
VkRenderPass renderPass = renderInfo->pass;
ImGui_ImplVulkan_InitInfo init_info = {}; ImGui_ImplVulkan_InitInfo init_info = {};
init_info.Instance = backend.GetInstance().Ptr(); init_info.Instance = backend.GetInstance().Ptr();
@ -118,8 +67,6 @@ namespace vkn {
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
init_info.Allocator = VK_NULL_HANDLE; init_info.Allocator = VK_NULL_HANDLE;
ImGui_ImplVulkan_Init(&init_info); ImGui_ImplVulkan_Init(&init_info);
API->SetRenderPassInfo(ImguiPassName, renderPass);
EventSystem::Ptr()->BeginRenderFrame.Subscribe(&VulkanImguiEditor::OnBeginRenderFrame, this);
} }
void VulkanImguiEditor::Finalize() void VulkanImguiEditor::Finalize()
{ {
@ -130,52 +77,17 @@ namespace vkn {
VkDescriptorSet descriptorSet = ImGui_ImplVulkan_AddTexture((VkSampler)sampler, (VkImageView)imageview, vkApiGetImageLayout(state)); VkDescriptorSet descriptorSet = ImGui_ImplVulkan_AddTexture((VkSampler)sampler, (VkImageView)imageview, vkApiGetImageLayout(state));
return reinterpret_cast<ImTextureID>(descriptorSet); return reinterpret_cast<ImTextureID>(descriptorSet);
} }
void VulkanImguiEditor::Render(FrameGraph& graph, RenderEditorContext& ctx) void VulkanImguiEditor::Render(FrameGraph& graph, RenderPassContext& context)
{ {
for (auto win : mWindows)
{
win->Draw(graph, ctx);
}
}
void VulkanImguiEditor::OnBeginRenderFrame(FrameGraph& graph, uint32_t frame)
{
graph.mIsRenderEditorSurface = gEngineConfig.IsRenderEditorSurface;
if (gEngineConfig.IsRenderEditorSurface) {
graph.mEditorSurfaceID = graph.mSurfaceID;
graph.mSurfaceID = graph.GetTextureID(FrameGraph::NameEditorSurface, frame);
}
graph.AddRenderPass<VulkanImguiEditor>();
}
void VulkanImguiEditor::Setup(FrameGraph& graph, RenderPassBuilder& builder)
{
TextureDesc stencil = graph.GetRenderSurface();
stencil.id = 0;
stencil.format = TinyImageFormat_S8_UINT;
stencil.image = nullptr;
stencil.usage = TextureUsage::STENCIL_ATTACHMENT | TextureUsage::DEPTH_ATTACHMENT;
graph.AcquireTexture(stencil);
builder.Name(ImguiPassName)
.Type(RenderPassNodeType::Imgui, RenderPassNodeFlag::Output)
.Write(graph.GetRenderSurface(), ResourceState::COLOR_ATTACHMENT)
.Write(stencil, ResourceState::DEPTH_ATTACHMENT);
if (gEngineConfig.IsRenderEditorSurface) {
builder.Read(graph.GetSurface(), ResourceState::READ_ONLY);
}
}
void VulkanImguiEditor::Execute(FrameGraph& graph, RenderPassContext& context)
{
auto& surface = graph.GetRenderSurface();
context->SetViewport(0.0f, 0.0f, (float)surface.width, (float)surface.height, 0.f, 1.f);
context->SetScissor(0, 0, surface.width, surface.height);
graph.GetRenderSurface().state = ResourceState::PRESENT;
ImGui_ImplVulkan_NewFrame(); ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame(); ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
VulkanImguiEditor* editor = VulkanImguiEditor::Ptr(); RenderEditorContext editorContext{ .editor = this, .frame = context->frame, .frameCount = context->frameCount };
RenderEditorContext editorContext{.editor = editor, .frame = context->frame, .frameCount = context->frameCount }; for (auto win : mWindows)
editor->Render(graph, editorContext); {
win->Draw(graph, editorContext);
}
ImGui::Render(); ImGui::Render();
VulkanContext& ctx = *(VulkanContext*)context.parent; VulkanContext& ctx = *(VulkanContext*)context.parent;

View File

@ -10,10 +10,10 @@ using namespace vkn;
void VulkanModule::OnLoad(int argc, char** argv) void VulkanModule::OnLoad(int argc, char** argv)
{ {
VulkanGlslLoader::Init(); VulkanGlslLoader::Init();
AddSystem<VulkanUISystem>();
#ifdef WITH_EDITOR #ifdef WITH_EDITOR
AddSystem<VulkanImguiEditor>(); AddSystem<VulkanImguiEditor>();
#endif // WITH_EDITOR #endif // WITH_EDITOR
AddSystem<VulkanUISystem>();
} }
void VulkanModule::OnUnload() void VulkanModule::OnUnload()

View File

@ -1,29 +1,71 @@
#include "vkn/vulkan_ui_system.h" #include "vkn/vulkan_ui_system.h"
#include "noesis/vulkan_noesis_help.h"
#include "vkn/vulkan_api_help.h" #include "vkn/vulkan_api_help.h"
#include "vkn/vulkan_api.h"
#ifdef WTIH_EDITOR
#include "editor/editor_system.h"
#endif // WTIH_EDITOR
#include "ui/utils/fast_lz.h" #include "ui/utils/fast_lz.h"
#include "event/event_system.h"
#include "data/global.h"
#include "noesis/vulkan_noesis_help.h"
#define DESCRIPTOR_POOL_MAX_SETS 128 #define DESCRIPTOR_POOL_MAX_SETS 128
namespace vkn { namespace vkn {
using api::FastLZ; using namespace api;
using api::DynamicBuffer; void vkn::VulkanUISystem::OnBeginRenderFrame(FrameGraph& graph, uint32_t frame)
using api::UITexture; {
#ifdef WITH_EDITOR
graph.mIsRenderEditorSurface = gEngineConfig.IsRenderEditorSurface;
if (gEngineConfig.IsRenderEditorSurface) {
graph.mEditorSurfaceID = graph.mSurfaceID;
graph.mSurfaceID = graph.GetTextureID(FrameGraph::NameEditorSurface, frame);
}
#endif // WITH_EDITOR
graph.AddRenderPass<VulkanUISystem>();
}
void VulkanUISystem::Setup(FrameGraph& graph, RenderPassBuilder& builder)
{
TextureDesc stencil = graph.GetRenderSurface();
stencil.id = 0;
stencil.format = TinyImageFormat_S8_UINT;
stencil.image = nullptr;
stencil.usage = TextureUsage::STENCIL_ATTACHMENT | TextureUsage::DEPTH_ATTACHMENT;
graph.AcquireTexture(stencil);
builder.Name(UIPassName)
.Type(RenderPassNodeType::Imgui, RenderPassNodeFlag::Output)
.Write(graph.GetRenderSurface(), ResourceState::COLOR_ATTACHMENT)
.Write(stencil, ResourceState::DEPTH_ATTACHMENT);
if (gEngineConfig.IsRenderEditorSurface) {
builder.Read(graph.GetSurface(), ResourceState::READ_ONLY);
}
}
void VulkanUISystem::Execute(FrameGraph& graph, RenderPassContext& context)
{
auto& surface = graph.GetRenderSurface();
context->SetViewport(0.0f, 0.0f, (float)surface.width, (float)surface.height, 0.f, 1.f);
context->SetScissor(0, 0, surface.width, surface.height);
graph.GetRenderSurface().state = ResourceState::PRESENT;
#ifdef WITH_EDITOR
EditorSystem::Ptr()->Render(graph, context);
#endif // WITH_EDITOR
}
void VulkanUISystem::InitNoesisRender(bool linearRendering, bool stereoSupport, SampleCount sampleCount_) void VulkanUISystem::InitNoesisRender(bool linearRendering, bool stereoSupport, SampleCount sampleCount_)
{ {
mDevice = &VulkanAPI::Ptr()->GetBackend().GetDevice(); VulkanAPI* API = VulkanAPI::Ptr();
auto info = VulkanAPI::Ptr()->GetRenderPassInfo("ImguiPass", 0); mDevice = &API->GetBackend().GetDevice();
mRenderPass = info->pass;
mHasExtendedDynamicState = false; mHasExtendedDynamicState = false;
mIsLinearRendering = linearRendering; mIsLinearRendering = linearRendering;
VkPhysicalDeviceProperties mDeviceProperties; VkPhysicalDeviceProperties mDeviceProperties;
vkGetPhysicalDeviceProperties(mDevice->GetPhysical(), &mDeviceProperties); vkGetPhysicalDeviceProperties(mDevice->GetPhysical(), &mDeviceProperties);
mMinUniformBufferOffsetAlignment = mDeviceProperties.limits.minUniformBufferOffsetAlignment; mMinUniformBufferOffsetAlignment = mDeviceProperties.limits.minUniformBufferOffsetAlignment;
VkSampleCountFlagBits sampleCount = vkApiGetSmpleCountFlag(sampleCount_); VkSampleCountFlagBits sampleCount = vkApiGetSmpleCountFlag(sampleCount_);
//CreateRenderPass(sampleCount); CreateRenderPass(sampleCount);
CreateLayouts(); CreateLayouts();
LoadShaders(stereoSupport); LoadShaders(stereoSupport);
CreatePipelines(sampleCount); CreatePipelines(sampleCount);
CreateSamplers(); CreateSamplers();
CreateDescriptorPool(); CreateDescriptorPool();
EventSystem::Ptr()->BeginRenderFrame.Subscribe(&VulkanUISystem::OnBeginRenderFrame, this);
API->SetRenderPassInfo(UIPassName, mRenderPass);
} }
void VulkanUISystem::BeginRender(api::RenderContext* context) { void VulkanUISystem::BeginRender(api::RenderContext* context) {
VulkanContext* ctx = (VulkanContext*)context; VulkanContext* ctx = (VulkanContext*)context;
@ -31,6 +73,8 @@ namespace vkn {
mFrameNumber = ctx->frameNumber; mFrameNumber = ctx->frameNumber;
mSafeFrameNumber = ctx->frameNumber - ctx->frameCount; mSafeFrameNumber = ctx->frameNumber - ctx->frameCount;
mWaitTransferCount = 0; mWaitTransferCount = 0;
mCachedIndexBuffer = nullptr;
mCachedPipeline = nullptr;
} }
void VulkanUISystem::DrawBatch(const Noesis::Batch& batch) void VulkanUISystem::DrawBatch(const Noesis::Batch& batch)
{ {