update framegraph & support imgui

This commit is contained in:
ouczbs 2024-12-15 17:24:35 +08:00
parent 7c3198d557
commit 1d3961ec74
20 changed files with 219 additions and 233 deletions

View File

@ -1,4 +1,4 @@
add_requires("spdlog", "lemon", "libsdl", "vulkansdk","shaderc","spirv","spirv-cross") add_requires("spdlog", "libsdl", "vulkansdk","shaderc","spirv","spirv-cross")
add_requires("mimalloc", {configs = {shared = true, debug = true, copy = true}}) add_requires("mimalloc", {configs = {shared = true, debug = true, copy = true}})
add_requires("imgui",{configs = {shared = true, debug = true, copy = true}}) add_requires("imgui",{configs = {shared = true, debug = true, copy = true}})
includes("*/xmake.lua") includes("*/xmake.lua")

View File

@ -3,7 +3,7 @@ namespace api {
template <typename ModuleClass> template <typename ModuleClass>
struct ModuleRegistrantImpl; struct ModuleRegistrantImpl;
struct IDynamicModule : public IModule { struct IDynamicModule : public IModule {
SharedLibrary mSharedLib; SharedLibrary mSharedLib{};
}; };
struct DefaultDynamicModule : public IDynamicModule { struct DefaultDynamicModule : public IDynamicModule {
DefaultDynamicModule(Name name) : IDynamicModule() {}; DefaultDynamicModule(Name name) : IDynamicModule() {};

View File

@ -9,11 +9,12 @@ namespace api {
class RenderPassBuilder; class RenderPassBuilder;
public: public:
inline static Name NameSurface{ "surface" }; inline static Name NameSurface{ "surface" };
RenderPassNode* mFirstInputNode{ nullptr };
RenderPassNode* mLastOutputNode{ nullptr };
TextureDesc mSurface; TextureDesc mSurface;
table<Name, TextureDesc> mTextureTable; table<Name, TextureDesc> mTextureTable;
table<TextureDesc, ImagePtr> mTexturePool; table<TextureDesc, ImagePtr> mTexturePool;
table<TextureViewDesc, ImageViewPtr> mTextureViewPool; table<TextureViewDesc, ImageViewPtr> mTextureViewPool;
lemon::ListGraph mGraph;
pmr::vector<FrameGraphNodePtr> mNodes{FramePool()}; pmr::vector<FrameGraphNodePtr> mNodes{FramePool()};
public: public:
template<typename T> template<typename T>
@ -21,10 +22,12 @@ namespace api {
using RenderPassSetupFunction = std::function<void(FrameGraph&, RenderPassBuilder&)>; using RenderPassSetupFunction = std::function<void(FrameGraph&, RenderPassBuilder&)>;
FrameGraphNodePtr AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor); FrameGraphNodePtr AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor);
TextureBuilder CreateTextureBuild(); TextureBuilder CreateTextureBuild();
void InitSurface(const pmr::vector<TextureDesc>& surfaces); void InitSurface(span<TextureDesc> surfaces);
void Compile(); void Compile();
void Execute(FRenderView& view); void Execute(FRenderView& view);
void Clear(); void Clear();
void CullGraph();
void FillGraph();
ResourceState Resolve(Name name,TextureDesc& desc, ResourceState state); ResourceState Resolve(Name name,TextureDesc& desc, ResourceState state);
ResourceState Resolve(Name name, AttachmentDesc& desc, ResourceState state); ResourceState Resolve(Name name, AttachmentDesc& desc, ResourceState state);
ResourceState Resolve(Name name, BufferDesc& desc, ResourceState state); ResourceState Resolve(Name name, BufferDesc& desc, ResourceState state);

View File

@ -20,7 +20,7 @@ namespace api {
FrameGraphEdgePtr edge; FrameGraphEdgePtr edge;
public: public:
TextureBuilder(FrameGraph* graph)noexcept : graph(*graph) { edge.Make(); }; TextureBuilder(FrameGraph* graph)noexcept : graph(*graph) { edge.Make(); };
FrameGraph::TextureBuilder& Import(pmr::Name name, AttachmentDesc desc, ResourceState state); FrameGraph::TextureBuilder& Import(pmr::Name name, AttachmentDesc desc);
FrameGraphEdgePtr Edge() { return edge; } FrameGraphEdgePtr Edge() const { return edge; }
}; };
} }

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "asset/asset.h" #include "asset/asset.h"
#include "render/type.h" #include "render/type.h"
#include "lemon/list_graph.h"
#include <functional> #include <functional>
namespace api { namespace api {
struct RenderPassNode; struct RenderPassNode;
@ -14,7 +13,7 @@ namespace api {
RenderContext* operator->() { RenderContext* operator->() {
return parent; return parent;
} }
size_t PassKey(); size_t PassKey()const;
}; };
struct CopyPassContext {}; struct CopyPassContext {};
@ -27,12 +26,10 @@ namespace api {
class RenderPassNode; class RenderPassNode;
struct FrameGraphNodePtr { struct FrameGraphNodePtr {
using NodeType = RenderPassType; using NodeType = RenderPassType;
using GraphNodeRef = lemon::ListGraphBase::Node;
GraphNodeRef ref;
NodeType type{ NodeType::Render };
RenderPassNode* node; RenderPassNode* node;
NodeType type{ NodeType::Render };
FrameGraphNodePtr() : node(nullptr){}; FrameGraphNodePtr() : node(nullptr){};
FrameGraphNodePtr(GraphNodeRef ref, const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render); FrameGraphNodePtr(const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render);
operator bool() const { operator bool() const {
return node; return node;
} }
@ -50,13 +47,13 @@ namespace api {
T& CastTo() { T& CastTo() {
return std::get<T>(resource); return std::get<T>(resource);
} }
bool IsAttachment() { bool IsAttachment() const {
return std::holds_alternative<AttachmentDesc>(resource); return std::holds_alternative<AttachmentDesc>(resource);
} }
bool IsTexture() { bool IsTexture() const{
return std::holds_alternative<TextureDesc>(resource); return std::holds_alternative<TextureDesc>(resource);
} }
bool IsBuffer() { bool IsBuffer() const {
return std::holds_alternative<BufferDesc>(resource); return std::holds_alternative<BufferDesc>(resource);
} }
}; };
@ -72,6 +69,9 @@ namespace api {
resource = new (FramePool()) FrameResource(); resource = new (FramePool()) FrameResource();
return resource; return resource;
} }
RenderPassNode* SourceNode()const {
return resource->source.node;
}
operator bool() const{ operator bool() const{
return resource; return resource;
} }
@ -88,26 +88,30 @@ namespace api {
enum class RenderPassNodeFlag : uint16_t enum class RenderPassNodeFlag : uint16_t
{ {
None = 0, None = 0,
Input = 0x01, Output = 0x01,
Output = 0x02, FirstInput = 0x02,
LastOutput = 0x04,
}; };
using RenderPassEdgeIterFn = std::function<void(FrameResource*, FrameGraphEdgePtr)>; using RenderPassEdgeIterFn = std::function<void(FrameResource*, FrameGraphEdgePtr)>;
struct RenderPassNode { struct RenderPassNode {
Name name; Name name;
size_t hash; size_t hash{0};
RenderPassNodeType type; RenderPassNodeType type{0};
RenderPassNodeFlag flag; RenderPassNodeFlag flag{0};
bool isActive{ false };
RenderPassNodeExecuteFn executor; RenderPassNodeExecuteFn executor;
pmr::vector<RenderPassNode*> dependencies{ FramePool() };
pmr::vector<FrameGraphEdgePtr> inEdges{ FramePool() }; pmr::vector<FrameGraphEdgePtr> inEdges{ FramePool() };
pmr::vector<FrameGraphEdgePtr> outEdges{ FramePool() }; pmr::vector<FrameGraphEdgePtr> outEdges{ FramePool() };
void ForeachEdge(RenderPassEdgeIterFn fn); void ForeachEdge(RenderPassEdgeIterFn fn);
bool IsInput() { return any(flag & RenderPassNodeFlag::Input); }
bool IsOutput() { return any(flag & RenderPassNodeFlag::Output); } bool IsOutput() { return any(flag & RenderPassNodeFlag::Output); }
bool IsFirstInput() { return any(flag & RenderPassNodeFlag::FirstInput); }
bool IsLastOutput() { return any(flag & RenderPassNodeFlag::LastOutput); }
FrameGraphEdgePtr GetInput(int i) { return inEdges[i]; }; FrameGraphEdgePtr GetInput(int i) { return inEdges[i]; };
FrameGraphEdgePtr GetOutput(int i) { return outEdges[i]; }; FrameGraphEdgePtr GetOutput(int i) { return outEdges[i]; };
FrameGraphEdgePtr FindInput(Name name) FrameGraphEdgePtr FindInput(Name name)
{ {
for (auto edge : inEdges) { for (auto& edge : inEdges) {
if (edge.resource->name == name) { if (edge.resource->name == name) {
return edge; return edge;
} }
@ -116,7 +120,7 @@ namespace api {
} }
FrameGraphEdgePtr FindOutput(Name name) FrameGraphEdgePtr FindOutput(Name name)
{ {
for (auto edge : outEdges) { for (auto& edge : outEdges) {
if (edge.resource->name == name) { if (edge.resource->name == name) {
return edge; return edge;
} }
@ -124,13 +128,13 @@ namespace api {
return {}; return {};
} }
}; };
inline FrameGraphNodePtr::FrameGraphNodePtr(GraphNodeRef ref, const RenderPassNodeExecuteFn& executor, NodeType type) inline FrameGraphNodePtr::FrameGraphNodePtr(const RenderPassNodeExecuteFn& executor, NodeType type)
: ref(ref), type(type) : type(type)
{ {
node = new (FramePool()) RenderPassNode(); node = new (FramePool()) RenderPassNode();
node->executor = executor; node->executor = executor;
} }
inline size_t RenderPassContext::PassKey() inline size_t RenderPassContext::PassKey()const
{ {
return node->hash; return node->hash;
} }

View File

@ -126,7 +126,7 @@ namespace api {
operator bool() { operator bool() {
return pResource; return pResource;
} }
MaterialResource* FindMaterialResource(Name name) { MaterialResource* FindMaterialResource(Name name) const {
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
MaterialResource* res = (pResource + i); MaterialResource* res = (pResource + i);
if (res->name == name) { if (res->name == name) {
@ -135,7 +135,7 @@ namespace api {
} }
return nullptr; return nullptr;
} }
void Upload(void** ppMappingAddr) { void Upload(void** ppMappingAddr) const {
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
auto res = pResource[i]; auto res = pResource[i];
if (res.isDirty || res.isUnique) { if (res.isDirty || res.isUnique) {
@ -186,7 +186,7 @@ namespace api {
static BufferDesc Make() { static BufferDesc Make() {
return {}; return {};
} }
BufferBarrier ToBarrier(ResourceState from, ResourceState to); BufferBarrier ToBarrier(ResourceState from, ResourceState to)const;
}; };
struct TextureViewDesc { struct TextureViewDesc {
ImagePtr image; ImagePtr image;
@ -219,7 +219,7 @@ namespace api {
desc.dimension = dimension; desc.dimension = dimension;
return desc; return desc;
} }
TextureBarrier ToBarrier(ResourceState from, ResourceState to); TextureBarrier ToBarrier(ResourceState from, ResourceState to)const;
}; };
struct AttachmentDesc { struct AttachmentDesc {
ImagePtr image; ImagePtr image;
@ -233,6 +233,9 @@ namespace api {
width = desc.width; width = desc.width;
height = desc.height; height = desc.height;
image = desc.image; image = desc.image;
sampleCount = desc.sampleCount;
colorFormat = desc.format;
dimension = desc.dimension;
return *this; return *this;
} }
TextureDesc ToTexture() const { TextureDesc ToTexture() const {
@ -253,7 +256,7 @@ namespace api {
desc.dimension = dimension; desc.dimension = dimension;
return desc; return desc;
} }
TextureBarrier ToBarrier(ResourceState from, ResourceState to); TextureBarrier ToBarrier(ResourceState from, ResourceState to)const;
}; };
struct TextureBarrier struct TextureBarrier
{ {
@ -286,29 +289,52 @@ namespace api {
const TextureBarrier* pTextureBarriers; const TextureBarrier* pTextureBarriers;
uint32_t textureBarriersCount; uint32_t textureBarriersCount;
}; };
inline BufferBarrier BufferDesc::ToBarrier(ResourceState from, ResourceState to) inline BufferBarrier BufferDesc::ToBarrier(ResourceState from, ResourceState to)const
{ {
BufferBarrier barrier; BufferBarrier barrier{};
barrier.mSrcState = from; barrier.mSrcState = from;
barrier.mDstState = to; barrier.mDstState = to;
return barrier; return barrier;
} }
inline TextureBarrier TextureDesc::ToBarrier(ResourceState from, ResourceState to) inline TextureBarrier TextureDesc::ToBarrier(ResourceState from, ResourceState to)const
{ {
TextureBarrier barrier; TextureBarrier barrier{};
barrier.mSrcState = from; barrier.mSrcState = from;
barrier.mDstState = to; barrier.mDstState = to;
barrier.mTexture = *this; barrier.mTexture = *this;
return barrier; return barrier;
} }
inline TextureBarrier AttachmentDesc::ToBarrier(ResourceState from, ResourceState to) inline TextureBarrier AttachmentDesc::ToBarrier(ResourceState from, ResourceState to)const
{ {
TextureBarrier barrier; TextureBarrier barrier{};
barrier.mSrcState = from; barrier.mSrcState = from;
barrier.mDstState = to; barrier.mDstState = to;
barrier.mTexture = ToTexture(); barrier.mTexture = ToTexture();
return barrier; return barrier;
} }
inline bool operator==(const TextureViewDesc& k1, const TextureViewDesc& k2) {
if (k1.image != k2.image) return false;
if (k1.format != k2.format) return false;
if (k1.dimension != k2.dimension) return false;
if (k1.baseArrayLayer != k2.baseArrayLayer) return false;
if (k1.layerCount != k2.layerCount) return false;
if (k1.baseMipLevel != k2.baseMipLevel) return false;
if (k1.levelCount != k2.levelCount) return false;
return true;
}
inline bool operator==(const TextureDesc& k1, const TextureDesc& k2) {
if (k1.image != k2.image) return false;
if (k1.format != k2.format) return false;
if (k1.dimension != k2.dimension) return false;
if (k1.state != k2.state) return false;
if (k1.width != k2.width) return false;
if (k1.height != k2.height) return false;
if (k1.arraySize != k2.arraySize) return false;
if (k1.mipLevel != k2.mipLevel) return false;
if (k1.sampleCount != k2.sampleCount) return false;
if (k1.depth != k2.depth) return false;
return true;
}
} }
#include "meta/hash.h" #include "meta/hash.h"
namespace std { namespace std {

View File

@ -1,32 +1,12 @@
#include "render/graph/frame_graph.h" #include "render/graph/frame_graph.h"
#include "render/renderapi.h" #include "render/renderapi.h"
#include <stack>
#include <unordered_set>
#include <algorithm>
namespace api { namespace api {
inline bool operator==(const TextureViewDesc& k1, const TextureViewDesc& k2) {
if (k1.image != k2.image) return false;
if (k1.format != k2.format) return false;
if (k1.dimension != k2.dimension) return false;
if (k1.baseArrayLayer != k2.baseArrayLayer) return false;
if (k1.layerCount != k2.layerCount) return false;
if (k1.baseMipLevel != k2.baseMipLevel) return false;
if (k1.levelCount != k2.levelCount) return false;
return true;
}
inline bool operator==(const TextureDesc& k1, const TextureDesc& k2) {
if (k1.image != k2.image) return false;
if (k1.format != k2.format) return false;
if (k1.dimension != k2.dimension) return false;
if (k1.state != k2.state) return false;
if (k1.width != k2.width) return false;
if (k1.height != k2.height) return false;
if (k1.arraySize != k2.arraySize) return false;
if (k1.mipLevel != k2.mipLevel) return false;
if (k1.sampleCount != k2.sampleCount) return false;
if (k1.depth != k2.depth) return false;
return true;
}
FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor) FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor)
{ {
FrameGraphNodePtr node_ptr{ mGraph.addNode(), executor }; FrameGraphNodePtr node_ptr{executor };
RenderPassBuilder builder{ this, node_ptr }; RenderPassBuilder builder{ this, node_ptr };
setup(*this, builder); setup(*this, builder);
mNodes.push_back(node_ptr); mNodes.push_back(node_ptr);
@ -36,7 +16,7 @@ namespace api {
{ {
return TextureBuilder{this}; return TextureBuilder{this};
} }
void FrameGraph::InitSurface(const pmr::vector<TextureDesc>& surfaces) void FrameGraph::InitSurface(span<TextureDesc> surfaces)
{ {
mSurface = surfaces[0]; mSurface = surfaces[0];
RenderAPI* API = RenderAPI::Ptr(); RenderAPI* API = RenderAPI::Ptr();
@ -48,18 +28,79 @@ namespace api {
} }
void FrameGraph::Compile() void FrameGraph::Compile()
{ {
auto end = std::remove_if(mNodes.begin(), mNodes.end(), [this](FrameGraphNodePtr& node) { CullGraph();
int degree = 0; FillGraph();
for (lemon::ListGraph::IncEdgeIt e(mGraph, node.ref); e != lemon::INVALID; ++e) { }
++degree; void FrameGraph::CullGraph()
{
pmr::vector<RenderPassNode*> outputNodes{FramePool()};
std::stack<RenderPassNode*> stack;
for (auto& node : mNodes) {
if (node->IsOutput()) {
stack.push(node.node);
outputNodes.push_back(node.node);
if ((!mLastOutputNode || node->type > mLastOutputNode->type)) {
mLastOutputNode = node.node;
}
} }
return !degree; }
while (!stack.empty()) {
RenderPassNode* node = stack.top();
stack.pop();
if (node->isActive) {
continue;
}
node->isActive = true;
bool isInput = node->IsOutput();
for (auto& edge : node->inEdges) {
if (!edge->source->isActive) {
stack.push(edge.SourceNode());
}
isInput = isInput || edge->name == NameSurface;
}
if (isInput && (!mFirstInputNode || node->type < mFirstInputNode->type)) {
mFirstInputNode = node;
}
}
auto end = std::remove_if(mNodes.begin(), mNodes.end(), [this](FrameGraphNodePtr& node) {
return !node->isActive;
}); });
//mNodes.erase(end, mNodes.end()); mNodes.erase(end, mNodes.end());
if (outputNodes.size() > 1) {
std::sort(outputNodes.begin(), outputNodes.end(), [](RenderPassNode* a, RenderPassNode* b) {
if (a->type != b->type) {
return a->type < b->type;
}
return a < b;
});
for (size_t i = 1; i < outputNodes.size(); ++i) {
outputNodes[i]->dependencies.push_back(outputNodes[i - 1]);
}
}
}
void FrameGraph::FillGraph()
{
std::pmr::unordered_set<RenderPassNode*> seenNodes{FramePool()};
for (auto& node : mNodes) {
if (!node->dependencies.empty()) {
seenNodes.insert(node->dependencies[0]);
}
for (auto& edge : node->inEdges) {
RenderPassNode* srcNode = edge.SourceNode();
if (seenNodes.insert(srcNode).second) {
node->dependencies.push_back(srcNode);
}
}
seenNodes.clear();
}
if (mLastOutputNode) {
mFirstInputNode->flag |= RenderPassNodeFlag::FirstInput;
mLastOutputNode->flag |= RenderPassNodeFlag::LastOutput;
}
} }
void FrameGraph::Execute(FRenderView& view) void FrameGraph::Execute(FRenderView& view)
{ {
for (auto node : mNodes) { for (auto& node : mNodes) {
switch (node.type) { switch (node.type) {
case RenderPassType::Render: case RenderPassType::Render:
ExecuteRenderPass(node.node, view); ExecuteRenderPass(node.node, view);
@ -78,8 +119,9 @@ namespace api {
} }
void FrameGraph::Clear() void FrameGraph::Clear()
{ {
mGraph.clear();
mNodes.clear(); mNodes.clear();
mFirstInputNode = nullptr;
mLastOutputNode = nullptr;
} }
void FrameGraph::ExecuteRenderPass(RenderPassNode* node, FRenderView& view) void FrameGraph::ExecuteRenderPass(RenderPassNode* node, FRenderView& view)
{ {

View File

@ -51,8 +51,6 @@ namespace api {
FrameGraphEdgePtr edge{ refEdge , state}; FrameGraphEdgePtr edge{ refEdge , state};
node->inEdges.emplace_back(edge); node->inEdges.emplace_back(edge);
refEdge->targets.emplace_back(node); refEdge->targets.emplace_back(node);
if(refEdge->source)
graph.mGraph.addEdge(refEdge->source.ref, node.ref);
return *this; return *this;
} }
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(const FrameGraphEdgePtr& refEdge, ResourceState state) FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(const FrameGraphEdgePtr& refEdge, ResourceState state)
@ -61,15 +59,12 @@ namespace api {
FrameGraphEdgePtr edge{ refEdge , state }; FrameGraphEdgePtr edge{ refEdge , state };
node->outEdges.emplace_back(edge); node->outEdges.emplace_back(edge);
refEdge->targets.emplace_back(node); refEdge->targets.emplace_back(node);
if (refEdge->source)
graph.mGraph.addEdge(node.ref, refEdge->source.ref);
return *this; return *this;
} }
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(pmr::Name name, AttachmentDesc desc, ResourceState state) FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(pmr::Name name, AttachmentDesc desc)
{ {
edge->name = name; edge->name = name;
edge->resource = desc; edge->resource = desc;
edge.targetState = state;
return *this; return *this;
} }
} }

View File

@ -13,15 +13,12 @@ namespace api {
{ {
AttachmentDesc surface{}; AttachmentDesc surface{};
surface.FromTexture(graph.mSurface); surface.FromTexture(graph.mSurface);
surface.colorFormat = TinyImageFormat_B8G8R8A8_SRGB;
surface.sampleCount = SAMPLE_COUNT_1;
surface.dimension = TextureDimension::TEX_2D;
auto edge = graph.CreateTextureBuild() auto edge = graph.CreateTextureBuild()
.Import(FrameGraph::NameSurface, surface, ResourceState::COLOR_ATTACHMENT) .Import(FrameGraph::NameSurface, surface)
.Edge(); .Edge();
builder.Name("MiniPass") builder.Name("MiniPass")
.Type(RenderPassNodeType::Scene, RenderPassNodeFlag::Input | RenderPassNodeFlag::Output) .Type(RenderPassNodeType::Scene, RenderPassNodeFlag::Output)
.Write(edge, edge.targetState); .Write(edge, ResourceState::COLOR_ATTACHMENT);
} }
void DemoPass::Execute(FrameGraph& graph, RenderPassContext& ctx) void DemoPass::Execute(FrameGraph& graph, RenderPassContext& ctx)
{ {

View File

@ -7,7 +7,7 @@ static_component("render","engine")
add_files("src/**.cpp", "3rdparty/imgui/*.cpp") add_files("src/**.cpp", "3rdparty/imgui/*.cpp")
add_deps("asset", "zlib", "core") add_deps("asset", "zlib", "core")
add_syslinks("user32", {public = true}) add_syslinks("user32", {public = true})
add_packages("lemon", "libsdl","shaderc","spirv-cross", {public = true}) add_packages("libsdl","shaderc","spirv-cross", {public = true})
if WITH_EDITOR then if WITH_EDITOR then
add_defines("WITH_EDITOR", {public = true}) add_defines("WITH_EDITOR", {public = true})
add_packages("imgui",{public = true}) add_packages("imgui",{public = true})

View File

@ -93,7 +93,7 @@ namespace pmr {
stringEntryHeader.Init((Hi >> 8u) & STRING_HASH_PROBE_MASK, view.size()); stringEntryHeader.Init((Hi >> 8u) & STRING_HASH_PROBE_MASK, view.size());
data = view.data(); data = view.data();
} }
const char* GetData() { const char* GetData() const {
return data; return data;
} }
uint32_t GetSlotIndex() const{ uint32_t GetSlotIndex() const{
@ -140,9 +140,9 @@ namespace pmr {
static constexpr double SLOT_POOL_RESIZE_USAGE_RATE = 0.9; static constexpr double SLOT_POOL_RESIZE_USAGE_RATE = 0.9;
static constexpr uint32_t SLOT_POOL_INITIALIZE_SIZE = 256u; static constexpr uint32_t SLOT_POOL_INITIALIZE_SIZE = 256u;
private: private:
uint32_t capcity; uint32_t capcity{0};
uint32_t size; uint32_t size{0};
Slot* slotArray; Slot* slotArray{ nullptr };
std::mutex mutex; std::mutex mutex;
public: public:
Slot& FindUnusedOrTargetSlot(HashInfo hashInfo); Slot& FindUnusedOrTargetSlot(HashInfo hashInfo);

View File

@ -48,7 +48,7 @@ namespace refl{
{ {
Any to{ ptr, cls }; Any to{ ptr, cls };
auto fieldList = cls->GetFields(refl::FIND_ALL_MEMBER, Name("")); auto fieldList = cls->GetFields(refl::FIND_ALL_MEMBER, Name(""));
for (auto field : fieldList) { for (auto& field : fieldList) {
Any obj = to.Member(field); Any obj = to.Member(field);
Convert::Construct(obj, Member(field)); Convert::Construct(obj, Member(field));
} }

View File

@ -66,7 +66,7 @@ namespace refl {
} }
else { else {
MethodType fptr = (MethodType)field->data.method.fptr; MethodType fptr = (MethodType)field->data.method.fptr;
auto ret = ArgsList.front(); auto& ret = ArgsList.front();
if (ret.cls == meta_info<R>()) { if (ret.cls == meta_info<R>()) {
*(R*)ret.ptr = fptr((param--->CastTo<Args>())...); *(R*)ret.ptr = fptr((param--->CastTo<Args>())...);
} }

View File

@ -121,6 +121,17 @@ namespace vkn {
uint32_t descCount = 0; uint32_t descCount = 0;
bool inUse = false; bool inUse = false;
}; };
inline bool operator==(const FramebufferKey& k1, const FramebufferKey& k2) {
if (k1.pass != k2.pass) return false;
if (k1.attachmentCount != k2.attachmentCount) return false;
for (int i = 0; i < k1.attachmentCount; i++) {
if (k1.imageViews[i] != k2.imageViews[i]) return false;
}
if (k1.height != k2.height) return false;
if (k1.width != k2.width) return false;
if (k1.layers != k2.layers) return false;
return true;
}
} }
namespace std { namespace std {
template<> template<>

View File

@ -43,6 +43,7 @@ namespace vkn {
VkPipeline GetPipeline() { return nullptr; }; VkPipeline GetPipeline() { return nullptr; };
RenderPassInfo* GetRenderPassInfo(Name name, size_t hash); RenderPassInfo* GetRenderPassInfo(Name name, size_t hash);
RenderPassInfo* GetRenderPassInfo(size_t& hash, const RenderPassKey& config); RenderPassInfo* GetRenderPassInfo(size_t& hash, const RenderPassKey& config);
void SetRenderPassInfo(Name name, VkRenderPass pass);
Backend& GetBackend() { Backend& GetBackend() {
return backend; return backend;
} }

View File

@ -23,7 +23,7 @@ namespace vkn {
friend class VulkanWindow; friend class VulkanWindow;
Device& mDevice; Device& mDevice;
VkSwapchainKHR mPtr; VkSwapchainKHR mPtr;
int mFrames; uint32_t mFrames;
pmr::vector<TextureDesc> mSurfaces{ GlobalPool() }; pmr::vector<TextureDesc> mSurfaces{ GlobalPool() };
pmr::vector<VkCommandBuffer> mCommands{ GlobalPool() }; pmr::vector<VkCommandBuffer> mCommands{ GlobalPool() };
pmr::vector<VkFence> mFences{ GlobalPool() }; pmr::vector<VkFence> mFences{ GlobalPool() };
@ -32,7 +32,7 @@ namespace vkn {
VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args); VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args);
void Aquire(VulkanContext& ctx); void Aquire(VulkanContext& ctx);
void Present(VulkanContext& ctx); void Present(VulkanContext& ctx);
int FrameCount() { int FrameCount() const {
return mFrames; return mFrames;
} }
const pmr::vector<TextureDesc>& GetSurface() { const pmr::vector<TextureDesc>& GetSurface() {

View File

@ -11,17 +11,6 @@
#include "zlog.h" #include "zlog.h"
namespace vkn { namespace vkn {
using api::EventSystem; using api::EventSystem;
inline bool operator==(const FramebufferKey& k1, const FramebufferKey& k2) {
if (k1.pass != k2.pass) return false;
if (k1.attachmentCount != k2.attachmentCount) return false;
for (int i = 0; i < k1.attachmentCount; i++) {
if (k1.imageViews[i] != k2.imageViews[i]) return false;
}
if (k1.height != k2.height) return false;
if (k1.width != k2.width) return false;
if (k1.layers != k2.layers) return false;
return true;
}
VulkanAPI::VulkanAPI() : RenderAPI(new VulkanContext()) VulkanAPI::VulkanAPI() : RenderAPI(new VulkanContext())
, window(*VulkanWindow::Ptr()) , window(*VulkanWindow::Ptr())
, backend(VulkanEngineName) , backend(VulkanEngineName)
@ -447,16 +436,16 @@ namespace vkn {
VkSemaphore waitSemaphores[8]; VkSemaphore waitSemaphores[8];
VkPipelineStageFlags waitDstStageMasks[8]; VkPipelineStageFlags waitDstStageMasks[8];
uint32_t semaphoreCount = 0; uint32_t semaphoreCount = 0;
if (node->IsInput()) { if (node->IsFirstInput()) {
waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
waitSemaphores[semaphoreCount++] = ctx.surfaceSemaphore; waitSemaphores[semaphoreCount++] = ctx.surfaceSemaphore;
zlog::info("-----wait {:#x}", (uintptr_t)ctx.surfaceSemaphore); //zlog::info("-----wait {:#x}", (uintptr_t)ctx.surfaceSemaphore);
} }
for (auto& it : node->inEdges) { for (auto& it : node->dependencies) {
RenderPassInfo* inputInfo = GetRenderPassInfo(it->source->name ,it->source->hash); RenderPassInfo* inputInfo = GetRenderPassInfo(it->name ,it->hash);
waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
waitSemaphores[semaphoreCount++] = inputInfo->semaphores[context.frame]; waitSemaphores[semaphoreCount++] = inputInfo->semaphores[context.frame];
zlog::info("-----wait {:#x}", (uintptr_t)inputInfo->semaphores[context.frame]); //zlog::info("-----wait {:#x}", (uintptr_t)inputInfo->semaphores[context.frame]);
} }
VkSubmitInfo submitInfo{}; VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
@ -467,10 +456,10 @@ namespace vkn {
submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitDstStageMasks; submitInfo.pWaitDstStageMask = waitDstStageMasks;
submitInfo.waitSemaphoreCount = semaphoreCount; submitInfo.waitSemaphoreCount = semaphoreCount;
if (node->IsOutput()) { if (node->IsLastOutput()) {
ctx.graphSemaphore = passInfo->semaphores[context.frame]; ctx.graphSemaphore = passInfo->semaphores[context.frame];
} }
zlog::info("+++++sign {:#x}", (uintptr_t)passInfo->semaphores[context.frame]); //zlog::info("+++++sign {:#x}", (uintptr_t)passInfo->semaphores[context.frame]);
vkQueueSubmit(Backend::RenderWorker->GetQueue().Ptr(), 1, &submitInfo, nullptr); vkQueueSubmit(Backend::RenderWorker->GetQueue().Ptr(), 1, &submitInfo, nullptr);
} }
RenderPassInfo* VulkanAPI::GetRenderPassInfo(Name name, size_t hash) { RenderPassInfo* VulkanAPI::GetRenderPassInfo(Name name, size_t hash) {
@ -665,4 +654,11 @@ namespace vkn {
RenderPassCache.emplace(hash, info); RenderPassCache.emplace(hash, info);
return &RenderPassCache[hash]; return &RenderPassCache[hash];
} }
void VulkanAPI::SetRenderPassInfo(Name name, VkRenderPass pass) {
RenderPassInfo info{};
info.config.pass = pass;
backend.GetDevice().CreateSemaphores(info.semaphores, context.frameCount);
Backend::RenderWorker->GetCommandPool().PopList(info.commands, context.frameCount);
RenderPassNameCache.emplace(name, info);
}
} }

View File

@ -76,8 +76,8 @@ namespace vkn {
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores; submitInfo.pSignalSemaphores = signalSemaphores;
zlog::info("-----wait {:#x}", (uintptr_t)waitSemaphores[0]); //zlog::info("-----wait {:#x}", (uintptr_t)waitSemaphores[0]);
zlog::info("+++++sign {:#x}", (uintptr_t)signalSemaphores[0]); //zlog::info("+++++sign {:#x}", (uintptr_t)signalSemaphores[0]);
vkQueueSubmit(queue, 1, &submitInfo, surfaceFence); vkQueueSubmit(queue, 1, &submitInfo, surfaceFence);
graphSemaphore = nullptr; graphSemaphore = nullptr;
} }

View File

@ -11,13 +11,9 @@
#include "event/event_system.h" #include "event/event_system.h"
#include "tinyimageformat/tinyimageformat_apis.h" #include "tinyimageformat/tinyimageformat_apis.h"
namespace vkn { namespace vkn {
using api::EventSystem; using namespace api;
static Name ImguiPassName{"ImguiPass"};
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
static VkRenderPass g_RenderPass = VK_NULL_HANDLE;
static VkCommandPool g_CommandPool = VK_NULL_HANDLE;
static std::vector<VkCommandBuffer> g_CommandBuffers;
static std::vector<VkFramebuffer> g_FrameBuffers;
static std::vector<VkSemaphore> g_RenderFinishSemaphores;
VkDescriptorPool CreateDescriptorPool(VkDevice device) { VkDescriptorPool CreateDescriptorPool(VkDevice device) {
VkDescriptorPoolSize pool_sizes[] = VkDescriptorPoolSize pool_sizes[] =
{ {
@ -84,59 +80,6 @@ namespace vkn {
throw std::runtime_error("Could not create Dear ImGui's render pass"); throw std::runtime_error("Could not create Dear ImGui's render pass");
return renderPass; return renderPass;
} }
void CreateFrameBuffer(VulkanAPI* API, VkRenderPass renderPass, const pmr::vector<TextureDesc>& surfaces) {
VkDevice device = API->GetBackend().GetDevice().Ptr();
g_FrameBuffers.resize(surfaces.size());
VkFramebuffer* framebuffer = g_FrameBuffers.data();
for (auto& surface : surfaces)
{
VkFramebufferCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
info.renderPass = renderPass;
info.pAttachments = (VkImageView*)API->graph.ResolveTextureView(surface.ToTextureView());
info.attachmentCount = 1;
info.width = surface.width;
info.height = surface.height;
info.layers = 1;
vkCreateFramebuffer(device, &info, VK_NULL_HANDLE, framebuffer++);
}
}
void CreateCommandPool(VkDevice device, int queueFamilyIndex, int frames) {
VkCommandPool commandPool;
// 创建一个专用的CommandPool
{
VkCommandPoolCreateInfo commandPoolCreateInfo = {};
commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
commandPoolCreateInfo.queueFamilyIndex = queueFamilyIndex;
commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
if (vkCreateCommandPool(device, &commandPoolCreateInfo, VK_NULL_HANDLE, &commandPool) != VK_SUCCESS)
throw std::runtime_error("Could not create graphics command pool");
}
// 创建专用的CommandBuffer
{
g_CommandBuffers.resize(frames);
VkCommandBufferAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandPool = commandPool;
allocInfo.commandBufferCount = frames;
if (vkAllocateCommandBuffers(device, &allocInfo, g_CommandBuffers.data()) != VK_SUCCESS)
throw std::runtime_error("failed to allocate command buffers!");
}
g_RenderFinishSemaphores.resize(frames);
for (size_t i = 0; i < frames; i++)
{
VkSemaphoreCreateInfo semaphoreInfo = {};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &g_RenderFinishSemaphores[i]) != VK_SUCCESS)
throw std::runtime_error("failed to create synchronization objects for a frame!");
}
}
void VulkanImguiSystem::Initialize() void VulkanImguiSystem::Initialize()
{ {
VulkanAPI* API = VulkanAPI::Ptr(); VulkanAPI* API = VulkanAPI::Ptr();
@ -161,11 +104,7 @@ 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);
g_RenderPass = renderPass;
auto& surfaces = window->Swapchain()->GetSurface();
//CreateFrameBuffer(API, renderPass, surfaces);
//CreateCommandPool(backend.GetDevice().Ptr(), pQueue->QueueFamilyIndex(), surfaces.size());
EventSystem::Ptr()->BeginRenderFrame.Subscribe(&VulkanImguiSystem::Render, this); EventSystem::Ptr()->BeginRenderFrame.Subscribe(&VulkanImguiSystem::Render, this);
} }
@ -175,15 +114,22 @@ namespace vkn {
} }
void VulkanImguiSystem::Render() void VulkanImguiSystem::Render()
{ {
if(false) VulkanAPI::Ptr()->graph.AddRenderPass<VulkanImguiSystem>();
VulkanAPI::Ptr()->graph.AddRenderPass<VulkanImguiSystem>();
} }
void VulkanImguiSystem::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder) void VulkanImguiSystem::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
{ {
AttachmentDesc surface{};
surface.FromTexture(graph.mSurface);
auto edge = graph.CreateTextureBuild()
.Import(FrameGraph::NameSurface, surface)
.Edge();
builder.Name(ImguiPassName)
.Type(RenderPassNodeType::Imgui, RenderPassNodeFlag::Output)
.Write(edge, ResourceState::COLOR_ATTACHMENT);
} }
void VulkanImguiSystem::Execute(FrameGraph&, RenderPassContext&) void VulkanImguiSystem::Execute(FrameGraph& graph, RenderPassContext& context)
{ {
graph.mSurface.state = ResourceState::PRESENT;
ImGui_ImplVulkan_NewFrame(); ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame(); ImGui_ImplSDL2_NewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
@ -194,53 +140,14 @@ namespace vkn {
ImGui::End(); ImGui::End();
ImGui::Render(); ImGui::Render();
VulkanContext& ctx = *(VulkanContext*)&context.parent;
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), ctx.command);
} ImGuiIO& io = ImGui::GetIO();
void EndEditorRender() // 更新并渲染平台窗口
{ if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
/* {
VulkanAPI* API = VulkanAPI::Ptr(); ImGui::UpdatePlatformWindows();
uint32_t frame = API->context.frame; ImGui::RenderPlatformWindowsDefault(nullptr, ctx.command);
CommandBuffer commandBuffer = CommandBuffer(g_CommandBuffers[frame]); }
commandBuffer.Reset();
commandBuffer.BeginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
VkRenderPassBeginInfo renderPassinfo = {};
renderPassinfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
renderPassinfo.renderPass = g_RenderPass;
renderPassinfo.framebuffer = g_FrameBuffers[frame];
renderPassinfo.renderArea.extent.width = API->graph.mSurface.width;
renderPassinfo.renderArea.extent.height = API->graph.mSurface.height;
renderPassinfo.clearValueCount = 0;
vkCmdBeginRenderPass(commandBuffer.Ptr(), &renderPassinfo, VK_SUBPASS_CONTENTS_INLINE);
// Record Imgui Draw Data and draw funcs into command buffer
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), commandBuffer.Ptr());
vkCmdEndRenderPass(commandBuffer.Ptr());
commandBuffer.EndRecord();
// 提交CommandBuffer
pmr::vector<VkPipelineStageFlags> waitStages{FramePool()};
waitStages.resize(renderAPI->curWaitSemaphores.size(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
vector<VkSemaphore> waitSemaphores = renderAPI->curWaitSemaphores;
waitStages.push_back(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
waitSemaphores.push_back(renderAPI->presentImageAvailableSemaphores[renderAPI->currentFrame]);
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.pCommandBuffers = &commandBuffer.Ptr();
submitInfo.commandBufferCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores.data();
submitInfo.pWaitDstStageMask = waitStages.data();
submitInfo.waitSemaphoreCount = static_cast<uint32_t>(waitSemaphores.size());
submitInfo.pSignalSemaphores = &g_RenderFinishSemaphores[renderAPI->currentFrame];
submitInfo.signalSemaphoreCount = 1;
VkFence fence = renderAPI->inFlightFences[renderAPI->currentFrame];
if (vkQueueSubmit(renderAPI->graphicsQueue, 1, &submitInfo, fence) != VK_SUCCESS)
throw std::runtime_error("failed to submit draw command buffer!");
renderAPI->curWaitSemaphores = { g_RenderFinishSemaphores[renderAPI->currentFrame] };*/
} }
} }

View File

@ -23,7 +23,7 @@ namespace vkn {
args.height = mHeight; args.height = mHeight;
mSwapchain = new (GlobalPool()) VulkanSwapchain(backend.GetDevice(), surface, args); mSwapchain = new (GlobalPool()) VulkanSwapchain(backend.GetDevice(), surface, args);
api->context.frameCount = args.frames; api->context.frameCount = args.frames;
api->graph.InitSurface(mSwapchain->mSurfaces); api->graph.InitSurface(std::span<TextureDesc>{mSwapchain->mSurfaces.data(), args.frames});
return true; return true;
} }
VulkanSwapchain::VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args) VulkanSwapchain::VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args)
@ -63,7 +63,7 @@ namespace vkn {
swapchain_images.resize(imageCount); swapchain_images.resize(imageCount);
vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, swapchain_images.data()); vkGetSwapchainImagesKHR(device.Ptr(), mPtr, &imageCount, swapchain_images.data());
mFences.reserve(mFrames); mFences.reserve(mFrames);
mSurfaces.reserve(mFrames); mSurfaces.reserve(imageCount);
mCommands.reserve(mFrames); mCommands.reserve(mFrames);
mSemaphores.reserve(mFrames + mFrames); mSemaphores.reserve(mFrames + mFrames);
TextureDesc desc{}; TextureDesc desc{};
@ -75,6 +75,7 @@ namespace vkn {
desc.arraySize = 1; desc.arraySize = 1;
desc.mipLevel = 1; desc.mipLevel = 1;
desc.depth = 1; desc.depth = 1;
desc.dimension = TextureDimension::TEX_2D;
for (int i = 0; i < mFrames; i++) { for (int i = 0; i < mFrames; i++) {
desc.image = swapchain_images[i]; desc.image = swapchain_images[i];
mSurfaces.push_back(desc); mSurfaces.push_back(desc);
@ -83,12 +84,15 @@ namespace vkn {
mCommands.push_back(Backend::RenderWorker->AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY)); mCommands.push_back(Backend::RenderWorker->AllocateBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY));
mFences.push_back(mDevice.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT)); mFences.push_back(mDevice.CreateFence(VK_FENCE_CREATE_SIGNALED_BIT));
} }
for (int i = mFrames; i < imageCount; i++) {
desc.image = swapchain_images[i];
mSurfaces.push_back(desc);
}
} }
void VulkanSwapchain::Aquire(VulkanContext& ctx) void VulkanSwapchain::Aquire(VulkanContext& ctx)
{ {
VkFence surfaceFence = mFences[ctx.frame]; VkFence surfaceFence = mFences[ctx.frame];
VkSemaphore surfaceSemaphore = mSemaphores[ctx.frame]; VkSemaphore surfaceSemaphore = mSemaphores[ctx.frame];
ctx.surface = mSurfaces[ctx.frame];
ctx.surfaceCommand = mCommands[ctx.frame]; ctx.surfaceCommand = mCommands[ctx.frame];
ctx.surfaceFence = surfaceFence; ctx.surfaceFence = surfaceFence;
ctx.surfaceSemaphore = surfaceSemaphore; ctx.surfaceSemaphore = surfaceSemaphore;
@ -97,12 +101,12 @@ namespace vkn {
throw std::runtime_error("Failed to wait for fence!"); throw std::runtime_error("Failed to wait for fence!");
vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, surfaceSemaphore, VK_NULL_HANDLE, &ctx.presentFrame); vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, surfaceSemaphore, VK_NULL_HANDLE, &ctx.presentFrame);
vkResetFences(mDevice.Ptr(), 1, &surfaceFence); vkResetFences(mDevice.Ptr(), 1, &surfaceFence);
ctx.presentFrame = ctx.presentFrame % mFrames; ctx.surface = mSurfaces[ctx.presentFrame];
zlog::info("aquire------------:: {:#x}", (uintptr_t)surfaceSemaphore); //zlog::info("aquire------------:: {:#x}", (uintptr_t)surfaceSemaphore);
} }
void VulkanSwapchain::Present(VulkanContext& ctx) void VulkanSwapchain::Present(VulkanContext& ctx)
{ {
zlog::info("present+++++++++++:: {:#x}", (uintptr_t)ctx.presentSemaphore); //zlog::info("present+++++++++++:: {:#x}", (uintptr_t)ctx.presentSemaphore);
VkPresentInfoKHR presentInfo = {}; VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.pWaitSemaphores = &ctx.presentSemaphore; presentInfo.pWaitSemaphores = &ctx.presentSemaphore;