update framegraph & support imgui
This commit is contained in:
parent
7c3198d557
commit
1d3961ec74
2
engine/3rdparty/xmake.lua
vendored
2
engine/3rdparty/xmake.lua
vendored
@ -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")
|
||||||
@ -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() {};
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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})
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>())...);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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<>
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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() {
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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] };*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user