rebuild framegraph resource system
This commit is contained in:
parent
99803e7391
commit
fef024d407
@ -3,6 +3,6 @@
|
||||
namespace api {
|
||||
class AssetPreviewPanel : public EditorPanel{
|
||||
public:
|
||||
void DrawPanel() override;
|
||||
void DrawPanel(FrameGraph& graph, RenderEditorContext& context) override;
|
||||
};
|
||||
}
|
||||
@ -3,6 +3,6 @@
|
||||
namespace api {
|
||||
class MenuBarPanel : public EditorPanel {
|
||||
public:
|
||||
void DrawPanel() override;
|
||||
void DrawPanel(FrameGraph& graph, RenderEditorContext& context) override;
|
||||
};
|
||||
}
|
||||
@ -4,6 +4,6 @@ namespace api {
|
||||
class EditorMainWindow : public EditorWindow {
|
||||
public:
|
||||
EditorMainWindow();
|
||||
void Draw() override;
|
||||
void Draw(FrameGraph& graph, RenderEditorContext& context) override;
|
||||
};
|
||||
}
|
||||
@ -3,5 +3,9 @@
|
||||
namespace api{
|
||||
struct EngineConfig {
|
||||
GraphicsAPI API = GraphicsAPI::Vulkan;
|
||||
#ifdef WITH_EDITOR
|
||||
bool IsRenderEditorSurface = false;
|
||||
#endif // WITH_EDITOR
|
||||
|
||||
};
|
||||
}
|
||||
@ -22,7 +22,7 @@ namespace api{
|
||||
static std::function<R(Args...)> EasyBind(R(Type::* func)(Args... args) const, const Type* invoker) {
|
||||
return [=](auto&&... args) {
|
||||
return (invoker->*func)(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
};
|
||||
}
|
||||
public:
|
||||
Event(Name name) : name(name){};
|
||||
|
||||
@ -2,12 +2,13 @@
|
||||
#include "event.h"
|
||||
#include "module/module.h"
|
||||
namespace api {
|
||||
class FrameGraph;
|
||||
class APP_API EventSystem : public ISystem{
|
||||
SINGLETON_IMPL(EventSystem)
|
||||
public:
|
||||
EventSystem();
|
||||
void Initialize() override;
|
||||
void Finalize() override;
|
||||
Event<void()> BeginRenderFrame{"BeginRenderFrame"};
|
||||
Event<void(FrameGraph&, uint32_t)> BeginRenderFrame{"BeginRenderFrame"};
|
||||
};
|
||||
}
|
||||
@ -229,7 +229,7 @@
|
||||
*
|
||||
*
|
||||
*/
|
||||
typedef enum TinyImageFormat {
|
||||
typedef enum TinyImageFormat : uint8_t{
|
||||
TinyImageFormat_UNDEFINED = 0,
|
||||
TinyImageFormat_R1_UNORM = 1,
|
||||
TinyImageFormat_R2_UNORM = 2,
|
||||
|
||||
@ -22,6 +22,7 @@ namespace api {
|
||||
}
|
||||
void RenderAPI::Render()
|
||||
{
|
||||
graph.Setup();
|
||||
for (auto view : context.views) {
|
||||
RenderView(view);
|
||||
}
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
#pragma once
|
||||
#ifdef WITH_EDITOR
|
||||
#include "graph/frame_graph.h"
|
||||
#include "module/module_manager.h"
|
||||
#include <imgui.h>
|
||||
namespace api {
|
||||
class RenderEditorContext {
|
||||
|
||||
};
|
||||
class EditorPanel {
|
||||
public:
|
||||
EditorPanel() = default;
|
||||
~EditorPanel() = default;
|
||||
virtual void DrawPanel() = 0;
|
||||
virtual void DrawPanel(FrameGraph& graph, RenderEditorContext& ctx) = 0;
|
||||
};
|
||||
class EditorWindow {
|
||||
protected:
|
||||
@ -14,7 +19,7 @@ namespace api {
|
||||
public:
|
||||
EditorWindow() = default;
|
||||
~EditorWindow() = default;
|
||||
virtual void Draw() = 0;
|
||||
virtual void Draw(FrameGraph& graph, RenderEditorContext& ctx) = 0;
|
||||
template<typename T, typename ... Args>
|
||||
T* AddPanel(Args&&... args) {
|
||||
T* ptr = new (GlobalPool()) T(std::forward<Args>(args)...);
|
||||
@ -35,6 +40,7 @@ namespace api {
|
||||
mWindows.push_back(ptr);
|
||||
return ptr;
|
||||
}
|
||||
virtual ImTextureID AddTexture(const TextureDesc& desc) = 0;
|
||||
};
|
||||
}
|
||||
#endif // WITH_EDITOR
|
||||
@ -2,37 +2,47 @@
|
||||
#include "type.h"
|
||||
namespace api {
|
||||
struct FRenderView;
|
||||
using pmr::Tag;
|
||||
class FrameGraph
|
||||
{
|
||||
public:
|
||||
class TextureBuilder;
|
||||
class RenderPassBuilder;
|
||||
public:
|
||||
inline static Name NameSurface{ "surface" };
|
||||
TextureDesc mSurface{};
|
||||
table<Tag, TextureDesc> mTextureTagMap;
|
||||
table<TextureKey, uint32_t> mTextureKeyMap;
|
||||
std::vector<TextureDesc> mTexturePool;
|
||||
table<TextureViewKey, ImageViewPtr> mTextureViewPool;
|
||||
pmr::vector<FrameGraphNodePtr> mNodes{FramePool()};
|
||||
RenderPassNode* mFirstInputNode{ nullptr };
|
||||
RenderPassNode* mLastOutputNode{ nullptr };
|
||||
TextureDesc mSurface;
|
||||
table<Name, TextureDesc> mTextureTable;
|
||||
table<TextureDesc, ImagePtr> mTexturePool;
|
||||
table<TextureViewDesc, ImageViewPtr> mTextureViewPool;
|
||||
pmr::vector<FrameGraphNodePtr> mNodes{FramePool()};
|
||||
inline static Name NameSurface{ "surface" };
|
||||
#ifdef WITH_EDITOR
|
||||
inline static Name NameEditorSurface{ "editor_surface" };
|
||||
TextureDesc mEditorSurface{};
|
||||
bool mIsRenderEditorSurface{false};
|
||||
#endif //
|
||||
public:
|
||||
template<typename T>
|
||||
FrameGraphNodePtr AddRenderPass() { return AddRenderPass(&T::Setup, &T::Execute); }
|
||||
using RenderPassSetupFunction = std::function<void(FrameGraph&, RenderPassBuilder&)>;
|
||||
FrameGraphNodePtr AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor);
|
||||
TextureBuilder CreateTextureBuild();
|
||||
void InitSurface(span<TextureDesc> surfaces);
|
||||
RenderPassBuilder CreateRenderPassBuild();
|
||||
void InitSurface(TextureDesc* surfaces, uint32_t frames);
|
||||
void Input(const TextureDesc& surfaces) { mSurface = surfaces; };
|
||||
void Setup();
|
||||
void Compile();
|
||||
void Execute(FRenderView& view);
|
||||
void Clear();
|
||||
void CullGraph();
|
||||
void FillGraph();
|
||||
ResourceState Resolve(Name name,TextureDesc& desc, ResourceState state);
|
||||
ResourceState Resolve(Name name, AttachmentDesc& desc, ResourceState state);
|
||||
ResourceState Resolve(Name name, BufferDesc& desc, ResourceState state);
|
||||
ImagePtr ResolveTexture(TextureDesc desc);
|
||||
ImageViewPtr ResolveTextureView(TextureViewDesc desc);
|
||||
void TransitionState(TextureDesc& desc, ResourceState state);
|
||||
bool ResolveState(TextureDesc& desc, ResourceState& srcstart, ResourceState& dststate);
|
||||
bool ResolveState(AttachmentDesc& desc, ResourceState& srcstart, ResourceState& dststate);
|
||||
bool ResolveState(BufferDesc& desc, ResourceState& srcstart, ResourceState& dststate);
|
||||
TextureDesc& ResolveTexture(TextureDesc& desc);
|
||||
TextureDesc ResourceTexture(Name name, int num);
|
||||
ImageViewPtr ResolveTextureView(TextureDesc& desc);
|
||||
ImageViewPtr ResolveTextureView(TextureViewKey key);
|
||||
void ResourceTexture(TextureDesc& desc);
|
||||
void SetResourceTexture(TextureDesc texture, Name name, int num = 0);
|
||||
public:
|
||||
void ExecutePresentPass(FRenderView& view);
|
||||
void ExecuteRenderPass(RenderPassNode* node, FRenderView& view);
|
||||
|
||||
@ -1,26 +1,16 @@
|
||||
#pragma once
|
||||
namespace api {
|
||||
struct FrameGraph::RenderPassBuilder {
|
||||
struct RenderPassBuilder {
|
||||
FrameGraph& graph;
|
||||
FrameGraphNodePtr& node;
|
||||
FrameResource* resource;
|
||||
FrameGraphNodePtr node;
|
||||
FrameResource* resource{nullptr};
|
||||
public:
|
||||
RenderPassBuilder(FrameGraph* graph) noexcept
|
||||
: graph(*graph), node() {};
|
||||
RenderPassBuilder(FrameGraph* graph, FrameGraphNodePtr& node) noexcept
|
||||
: graph(*graph) , node(node) {};
|
||||
FrameGraph::RenderPassBuilder& Name(pmr::Name name);
|
||||
FrameGraph::RenderPassBuilder& Type(RenderPassNodeType type,RenderPassNodeFlag flag = RenderPassNodeFlag::None);
|
||||
FrameGraph::RenderPassBuilder& Read(TextureDesc desc, ResourceState state);
|
||||
FrameGraph::RenderPassBuilder& Write(BufferDesc desc, ResourceState state);
|
||||
FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc, ResourceState state);
|
||||
FrameGraph::RenderPassBuilder& Read(const FrameGraphEdgePtr& refEdge, ResourceState state);
|
||||
FrameGraph::RenderPassBuilder& Write(const FrameGraphEdgePtr& refEdge, ResourceState state);
|
||||
};
|
||||
struct FrameGraph::TextureBuilder {
|
||||
FrameGraph& graph;
|
||||
FrameGraphEdgePtr edge;
|
||||
public:
|
||||
TextureBuilder(FrameGraph* graph)noexcept : graph(*graph) { edge.Make(); };
|
||||
FrameGraph::TextureBuilder& Import(pmr::Name name, AttachmentDesc desc);
|
||||
FrameGraphEdgePtr Edge() const { return edge; }
|
||||
RenderPassBuilder& Name(pmr::Name name);
|
||||
RenderPassBuilder& Type(RenderPassNodeType type,RenderPassNodeFlag flag = RenderPassNodeFlag::None);
|
||||
RenderPassBuilder& Write(AttachmentDesc desc, ResourceState state, pmr::Name name = {});
|
||||
};
|
||||
}
|
||||
@ -3,6 +3,8 @@
|
||||
#include "render/type.h"
|
||||
#include <functional>
|
||||
namespace api {
|
||||
class FrameGraph;
|
||||
class RenderPassBuilder;
|
||||
struct RenderPassNode;
|
||||
struct RenderContext;
|
||||
struct ComputePassContext {};
|
||||
@ -16,20 +18,17 @@ namespace api {
|
||||
size_t PassKey()const;
|
||||
};
|
||||
struct CopyPassContext {};
|
||||
|
||||
class FrameGraph;
|
||||
using RenderPassSetupFunction = std::function<void(FrameGraph&, RenderPassBuilder&)>;
|
||||
using CopyPassExecuteFunction = std::function<void(FrameGraph&, CopyPassContext&)>;
|
||||
using ComputePassExecuteFunction = std::function<void(FrameGraph&, ComputePassContext&)>;
|
||||
using RenderPassExecuteFunction = std::function<void(FrameGraph&, RenderPassContext&)>;
|
||||
using RenderPassNodeExecuteFn = std::variant<RenderPassExecuteFunction, ComputePassExecuteFunction, CopyPassExecuteFunction>;
|
||||
class RenderPass;
|
||||
class RenderPassNode;
|
||||
struct FrameGraphNodePtr {
|
||||
using NodeType = RenderPassType;
|
||||
RenderPassNode* node;
|
||||
NodeType type{ NodeType::Render };
|
||||
FrameGraphNodePtr() : node(nullptr){};
|
||||
FrameGraphNodePtr(const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render);
|
||||
FrameGraphNodePtr(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render);
|
||||
operator bool() const {
|
||||
return node;
|
||||
}
|
||||
@ -40,65 +39,48 @@ namespace api {
|
||||
struct FrameResource {
|
||||
using Resource = std::variant<TextureDesc, BufferDesc, AttachmentDesc>;
|
||||
Name name;
|
||||
Resource resource;
|
||||
FrameGraphNodePtr source;
|
||||
pmr::vector<FrameGraphNodePtr> targets{ FramePool() };
|
||||
Resource res;
|
||||
RenderPassNode* node;
|
||||
FrameResource() noexcept = default;
|
||||
FrameResource(Name name,const Resource& res, RenderPassNode* node) : name(name), res(res), node(node){};
|
||||
template<typename T>
|
||||
T& CastTo() {
|
||||
return std::get<T>(resource);
|
||||
return std::get<T>(res);
|
||||
}
|
||||
bool IsAttachment() const {
|
||||
return std::holds_alternative<AttachmentDesc>(resource);
|
||||
return std::holds_alternative<AttachmentDesc>(res);
|
||||
}
|
||||
bool IsTexture() const{
|
||||
return std::holds_alternative<TextureDesc>(resource);
|
||||
return std::holds_alternative<TextureDesc>(res);
|
||||
}
|
||||
bool IsBuffer() const {
|
||||
return std::holds_alternative<BufferDesc>(resource);
|
||||
return std::holds_alternative<BufferDesc>(res);
|
||||
}
|
||||
static FrameResource* Make(Name name, const Resource& res, RenderPassNode* node) {
|
||||
return new(FramePool()) FrameResource(name, res, node);
|
||||
}
|
||||
};
|
||||
struct FrameGraphEdgePtr {
|
||||
ResourceState targetState;
|
||||
FrameResource* resource;
|
||||
FrameGraphEdgePtr() = default;
|
||||
FrameGraphEdgePtr(const FrameGraphEdgePtr& edge, ResourceState state) {
|
||||
targetState = state;
|
||||
resource = edge.resource;
|
||||
}
|
||||
FrameResource* Make() {
|
||||
resource = new (FramePool()) FrameResource();
|
||||
return resource;
|
||||
}
|
||||
RenderPassNode* SourceNode()const {
|
||||
return resource->source.node;
|
||||
}
|
||||
operator bool() const{
|
||||
return resource;
|
||||
}
|
||||
FrameResource* operator ->()const {
|
||||
return resource;
|
||||
}
|
||||
void ResolveView(FrameGraph* graph);
|
||||
};
|
||||
enum class RenderPassNodeType : uint16_t {
|
||||
using FrameGraphEdgePtr = FrameResource*;
|
||||
enum class RenderPassNodeType : uint8_t {
|
||||
None,
|
||||
Scene,
|
||||
Imgui,
|
||||
};
|
||||
enum class RenderPassNodeFlag : uint16_t
|
||||
enum class RenderPassNodeFlag : uint8_t
|
||||
{
|
||||
None = 0,
|
||||
Output = 0x01,
|
||||
FirstInput = 0x02,
|
||||
LastOutput = 0x04,
|
||||
};
|
||||
using RenderPassEdgeIterFn = std::function<void(FrameResource*, FrameGraphEdgePtr)>;
|
||||
using RenderPassEdgeIterFn = std::function<void(FrameResource*)>;
|
||||
struct RenderPassNode {
|
||||
Name name;
|
||||
size_t hash{0};
|
||||
RenderPassNodeType type{0};
|
||||
RenderPassNodeFlag flag{0};
|
||||
bool isActive{ false };
|
||||
RenderPassSetupFunction setup;
|
||||
RenderPassNodeExecuteFn executor;
|
||||
pmr::vector<RenderPassNode*> dependencies{ FramePool() };
|
||||
pmr::vector<FrameGraphEdgePtr> inEdges{ FramePool() };
|
||||
@ -112,7 +94,7 @@ namespace api {
|
||||
FrameGraphEdgePtr FindInput(Name name)
|
||||
{
|
||||
for (auto& edge : inEdges) {
|
||||
if (edge.resource->name == name) {
|
||||
if (edge->name == name) {
|
||||
return edge;
|
||||
}
|
||||
}
|
||||
@ -121,19 +103,13 @@ namespace api {
|
||||
FrameGraphEdgePtr FindOutput(Name name)
|
||||
{
|
||||
for (auto& edge : outEdges) {
|
||||
if (edge.resource->name == name) {
|
||||
if (edge->name == name) {
|
||||
return edge;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
||||
inline FrameGraphNodePtr::FrameGraphNodePtr(const RenderPassNodeExecuteFn& executor, NodeType type)
|
||||
: type(type)
|
||||
{
|
||||
node = new (FramePool()) RenderPassNode();
|
||||
node->executor = executor;
|
||||
}
|
||||
inline size_t RenderPassContext::PassKey()const
|
||||
{
|
||||
return node->hash;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
namespace api {
|
||||
class DemoPass : public RenderPass {
|
||||
public:
|
||||
static void Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder);
|
||||
static void Setup(FrameGraph& graph, RenderPassBuilder& builder);
|
||||
static void Execute(FrameGraph&, RenderPassContext&);
|
||||
};
|
||||
|
||||
|
||||
@ -33,8 +33,8 @@ namespace api {
|
||||
virtual void LoadShader(Shader& shader, size_t passKey) = 0;
|
||||
|
||||
virtual void CreateBuffer(BufferDesc& desc) = 0;
|
||||
virtual ImagePtr CreateTexture(TextureDesc desc) = 0;
|
||||
virtual ImageViewPtr CreateTextureView(TextureViewDesc desc) = 0;
|
||||
virtual void CreateTexture(TextureDesc& desc) = 0;
|
||||
virtual ImageViewPtr CreateTextureView(TextureViewKey desc) = 0;
|
||||
|
||||
virtual void BeginFrame() = 0;
|
||||
virtual void EndFrame() = 0;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
//#include <algorithm>
|
||||
namespace api {
|
||||
using pmr::Name;
|
||||
enum class GraphicsAPI
|
||||
enum class GraphicsAPI : uint8_t
|
||||
{
|
||||
OpenGL,
|
||||
Vulkan,
|
||||
@ -18,14 +18,14 @@ namespace api {
|
||||
Compute,
|
||||
Copy
|
||||
};
|
||||
enum class BufferUsage {
|
||||
enum class BufferUsage : uint8_t {
|
||||
STATIC = 0x01, //!< content modified once, used many times
|
||||
DYNAMIC = 0x02, //!< content modified frequently, used many times
|
||||
VERTEX = 0x04,
|
||||
UNIFORM = 0x08,
|
||||
SHADER_STORAGE = 0x10
|
||||
};
|
||||
enum class ResourceMemoryUsage
|
||||
enum class ResourceMemoryUsage : uint8_t
|
||||
{
|
||||
/// No intended memory usage specified.
|
||||
UNKNOWN = 0,
|
||||
@ -39,7 +39,7 @@ namespace api {
|
||||
GPU_TO_CPU = 4,
|
||||
COUNT,
|
||||
};
|
||||
enum SampleCount
|
||||
enum SampleCount : uint8_t
|
||||
{
|
||||
SAMPLE_COUNT_1 = 1,
|
||||
SAMPLE_COUNT_2 = 2,
|
||||
@ -66,7 +66,7 @@ namespace api {
|
||||
DEPTH_AND_STENCIL = DEPTH | STENCIL, //!< depth and stencil buffer selected.
|
||||
ALL = COLOR_ALL | DEPTH | STENCIL //!< Color, depth and stencil buffer selected.
|
||||
};
|
||||
enum class ResourceState
|
||||
enum class ResourceState : uint8_t
|
||||
{
|
||||
// The initial layout after the creation of the VkImage. We use this to denote the state before
|
||||
// any transition.
|
||||
@ -89,7 +89,20 @@ namespace api {
|
||||
// TODO: explore separate layout policies for attachment+sampling and just attachment.
|
||||
COLOR_ATTACHMENT,
|
||||
};
|
||||
enum class TextureDimension
|
||||
enum class TextureUsage :uint16_t {
|
||||
NONE = 0x0000,
|
||||
COLOR_ATTACHMENT = 0x0001, //!< Texture can be used as a color attachment
|
||||
DEPTH_ATTACHMENT = 0x0002, //!< Texture can be used as a depth attachment
|
||||
STENCIL_ATTACHMENT = 0x0004, //!< Texture can be used as a stencil attachment
|
||||
UPLOADABLE = 0x0008, //!< Data can be uploaded into this texture (default)
|
||||
SAMPLEABLE = 0x0010, //!< Texture can be sampled (default)
|
||||
SUBPASS_INPUT = 0x0020, //!< Texture can be used as a subpass input
|
||||
BLIT_SRC = 0x0040, //!< Texture can be used the source of a blit()
|
||||
BLIT_DST = 0x0080, //!< Texture can be used the destination of a blit()
|
||||
PROTECTED = 0x0100, //!< Texture can be used for protected content
|
||||
DEFAULT = UPLOADABLE | SAMPLEABLE //!< Default texture usage
|
||||
};
|
||||
enum class TextureDimension : uint8_t
|
||||
{
|
||||
TEX_NULL = 0,
|
||||
TEX_1D = 0x01,
|
||||
@ -101,7 +114,7 @@ namespace api {
|
||||
UNIFORM_BUFFER,
|
||||
SAMPLER,
|
||||
};
|
||||
enum class ShaderStage : uint32_t {
|
||||
enum class ShaderStage : uint8_t {
|
||||
NONE = 0,
|
||||
VERTEX = 0x1,
|
||||
FRAGMENT = 0x2,
|
||||
@ -188,28 +201,33 @@ namespace api {
|
||||
}
|
||||
BufferBarrier ToBarrier(ResourceState from, ResourceState to)const;
|
||||
};
|
||||
struct TextureViewDesc {
|
||||
struct TextureViewKey {
|
||||
ImagePtr image;
|
||||
TinyImageFormat format : 16;
|
||||
TextureDimension dimension : 8;
|
||||
uint32_t baseArrayLayer : 8;
|
||||
uint32_t layerCount : 8;
|
||||
uint32_t baseMipLevel : 8;
|
||||
uint32_t levelCount : 8;
|
||||
TinyImageFormat format;
|
||||
TextureDimension dimension;
|
||||
uint8_t baseArrayLayer;
|
||||
uint8_t layerCount;
|
||||
uint8_t baseMipLevel;
|
||||
uint8_t levelCount;
|
||||
};
|
||||
struct TextureDesc {
|
||||
ImagePtr image;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t depth : 16;
|
||||
TinyImageFormat format : 16;
|
||||
ResourceState state : 8;
|
||||
SampleCount sampleCount : 8;
|
||||
uint32_t arraySize : 8;
|
||||
TextureDimension dimension : 4;
|
||||
uint32_t mipLevel : 4;
|
||||
TextureViewDesc ToTextureView() const{
|
||||
TextureViewDesc desc{};
|
||||
struct TextureKey {
|
||||
uint32_t id;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint16_t depth;
|
||||
TinyImageFormat format;
|
||||
SampleCount sampleCount;
|
||||
TextureDimension dimension;
|
||||
uint8_t mipLevel;
|
||||
uint8_t arraySize;
|
||||
};
|
||||
struct TextureDesc : TextureKey {
|
||||
ImagePtr image;
|
||||
void* pData;//api数据 比如 vulkan 包含了内存信息,删除图像时要用到
|
||||
ResourceState state;
|
||||
TextureUsage usage;//这个字段是包含关系,即使不同,也可以指向相同的图像
|
||||
TextureViewKey ToTextureView() const{
|
||||
TextureViewKey desc{};
|
||||
desc.image = image;
|
||||
desc.format = format;
|
||||
desc.baseArrayLayer = 0;
|
||||
@ -222,39 +240,12 @@ namespace api {
|
||||
TextureBarrier ToBarrier(ResourceState from, ResourceState to)const;
|
||||
};
|
||||
struct AttachmentDesc {
|
||||
ImagePtr image;
|
||||
TextureDesc texture;
|
||||
ImageViewPtr imageView;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
TextureDimension dimension : 16;
|
||||
TinyImageFormat colorFormat : 16;
|
||||
SampleCount sampleCount : 16;
|
||||
AttachmentDesc& FromTexture(const TextureDesc& desc) {
|
||||
width = desc.width;
|
||||
height = desc.height;
|
||||
image = desc.image;
|
||||
sampleCount = desc.sampleCount;
|
||||
colorFormat = desc.format;
|
||||
dimension = desc.dimension;
|
||||
return *this;
|
||||
}
|
||||
TextureDesc ToTexture() const {
|
||||
return TextureDesc{
|
||||
.image = image,
|
||||
.width = width,
|
||||
.height = height,
|
||||
};
|
||||
}
|
||||
TextureViewDesc ToTextureView() const {
|
||||
TextureViewDesc desc{};
|
||||
desc.image = image;
|
||||
desc.format = colorFormat;
|
||||
desc.baseArrayLayer = 0;
|
||||
desc.baseMipLevel = 0;
|
||||
desc.layerCount = 1;
|
||||
desc.levelCount = 1;
|
||||
desc.dimension = dimension;
|
||||
return desc;
|
||||
AttachmentDesc() :texture(), imageView(nullptr) {};
|
||||
AttachmentDesc(const TextureDesc& desc): texture(desc), imageView(nullptr){}
|
||||
TextureViewKey ToTextureView() const {
|
||||
return texture.ToTextureView();
|
||||
}
|
||||
TextureBarrier ToBarrier(ResourceState from, ResourceState to)const;
|
||||
};
|
||||
@ -309,10 +300,10 @@ namespace api {
|
||||
TextureBarrier barrier{};
|
||||
barrier.mSrcState = from;
|
||||
barrier.mDstState = to;
|
||||
barrier.mTexture = ToTexture();
|
||||
barrier.mTexture = texture;
|
||||
return barrier;
|
||||
}
|
||||
inline bool operator==(const TextureViewDesc& k1, const TextureViewDesc& k2) {
|
||||
inline bool operator==(const TextureViewKey& k1, const TextureViewKey& k2) {
|
||||
if (k1.image != k2.image) return false;
|
||||
if (k1.format != k2.format) return false;
|
||||
if (k1.dimension != k2.dimension) return false;
|
||||
@ -322,11 +313,9 @@ namespace api {
|
||||
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;
|
||||
inline bool operator==(const TextureKey& k1, const TextureKey& k2) {
|
||||
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;
|
||||
@ -339,17 +328,17 @@ namespace api {
|
||||
#include "meta/hash.h"
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<api::TextureViewDesc>
|
||||
struct hash<api::TextureViewKey>
|
||||
{
|
||||
size_t operator()(const api::TextureViewDesc& key) const noexcept
|
||||
size_t operator()(const api::TextureViewKey& key) const noexcept
|
||||
{
|
||||
return meta::MurmurHashFn(key);
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct hash<api::TextureDesc>
|
||||
struct hash<api::TextureKey>
|
||||
{
|
||||
size_t operator()(const api::TextureDesc& key) const noexcept
|
||||
size_t operator()(const api::TextureKey& key) const noexcept
|
||||
{
|
||||
return meta::MurmurHashFn(key);
|
||||
}
|
||||
|
||||
@ -4,26 +4,32 @@
|
||||
#include <unordered_set>
|
||||
#include <algorithm>
|
||||
namespace api {
|
||||
//先准备再执行,这样就可以在执行之前,做一些特殊的资源初始化工作
|
||||
FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor)
|
||||
{
|
||||
FrameGraphNodePtr node_ptr{executor };
|
||||
RenderPassBuilder builder{ this, node_ptr };
|
||||
setup(*this, builder);
|
||||
FrameGraphNodePtr node_ptr{ setup, executor};
|
||||
mNodes.push_back(node_ptr);
|
||||
return node_ptr;
|
||||
}
|
||||
FrameGraph::TextureBuilder FrameGraph::CreateTextureBuild()
|
||||
RenderPassBuilder FrameGraph::CreateRenderPassBuild()
|
||||
{
|
||||
return TextureBuilder{this};
|
||||
return RenderPassBuilder{this};
|
||||
}
|
||||
void FrameGraph::InitSurface(span<TextureDesc> surfaces)
|
||||
void FrameGraph::InitSurface(TextureDesc* surfaces, uint32_t frames)
|
||||
{
|
||||
mSurface = surfaces[0];
|
||||
RenderAPI* API = RenderAPI::Ptr();
|
||||
for (auto& surface : surfaces) {
|
||||
TextureViewDesc desc = surface.ToTextureView();
|
||||
//ImageViewPtr view = API->CreateTextureView(desc);
|
||||
//mResourceViewPool.emplace(desc, view);
|
||||
mTexturePool.reserve(frames);
|
||||
for (uint32_t i = 0; i < frames;i++) {
|
||||
surfaces[i].id = mTexturePool.size() + 1;
|
||||
mTexturePool.push_back(surfaces[i]);
|
||||
}
|
||||
}
|
||||
void FrameGraph::Setup()
|
||||
{
|
||||
uint32_t size = mNodes.size();
|
||||
for (uint32_t i = 0; i < size;i++) {
|
||||
auto& node = mNodes[i];//mNodes 数量可能会增加
|
||||
RenderPassBuilder builder{this, node};
|
||||
node->setup(*this, builder);
|
||||
}
|
||||
}
|
||||
void FrameGraph::Compile()
|
||||
@ -42,6 +48,12 @@ namespace api {
|
||||
if ((!mLastOutputNode || node->type > mLastOutputNode->type)) {
|
||||
mLastOutputNode = node.node;
|
||||
}
|
||||
if ((!mFirstInputNode || node->type < mFirstInputNode->type)) {
|
||||
#ifdef WITH_EDITOR
|
||||
if(!mIsRenderEditorSurface || node->type >= RenderPassNodeType::Imgui)
|
||||
#endif // WITH_EDITOR
|
||||
mFirstInputNode = node.node;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!stack.empty()) {
|
||||
@ -51,15 +63,10 @@ namespace api {
|
||||
continue;
|
||||
}
|
||||
node->isActive = true;
|
||||
bool isInput = node->IsOutput();
|
||||
for (auto& edge : node->inEdges) {
|
||||
if (!edge->source->isActive) {
|
||||
stack.push(edge.SourceNode());
|
||||
if (edge->node && !edge->node->isActive) {
|
||||
stack.push(edge->node);
|
||||
}
|
||||
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) {
|
||||
@ -86,8 +93,8 @@ namespace api {
|
||||
seenNodes.insert(node->dependencies[0]);
|
||||
}
|
||||
for (auto& edge : node->inEdges) {
|
||||
RenderPassNode* srcNode = edge.SourceNode();
|
||||
if (seenNodes.insert(srcNode).second) {
|
||||
RenderPassNode* srcNode = edge->node;
|
||||
if (srcNode && seenNodes.insert(srcNode).second) {
|
||||
node->dependencies.push_back(srcNode);
|
||||
}
|
||||
}
|
||||
@ -134,18 +141,25 @@ namespace api {
|
||||
}
|
||||
void FrameGraph::ExecutePresentPass(FRenderView& view)
|
||||
{
|
||||
if (mSurface.state == ResourceState::PRESENT) {
|
||||
#ifdef WITH_EDITOR
|
||||
TextureDesc& surface = ResolveTexture(mIsRenderEditorSurface ? mEditorSurface : mSurface);
|
||||
#else
|
||||
TextureDesc& surface = ResolveTexture(mSurface);
|
||||
#endif // WITH_EDITOR
|
||||
if (surface.state == ResourceState::PRESENT) {
|
||||
surface.state = ResourceState::UNDEFINED;
|
||||
return;
|
||||
}
|
||||
TextureBarrier barrier{};
|
||||
barrier.mSrcState = mSurface.state;
|
||||
barrier.mSrcState = surface.state;
|
||||
barrier.mDstState = ResourceState::PRESENT;
|
||||
barrier.mTexture = mSurface;
|
||||
barrier.mTexture = surface;
|
||||
ResourceBarrierDesc desc{};
|
||||
desc.type = RenderPassType::Present;
|
||||
desc.textureBarriersCount = 1;
|
||||
desc.pTextureBarriers = &barrier;
|
||||
view.context->ExecuteSurfaceBarriers(desc);
|
||||
surface.state = ResourceState::UNDEFINED;
|
||||
}
|
||||
void FrameGraph::ExecuteComputePass(RenderPassNode* node, FRenderView& view)
|
||||
{
|
||||
@ -162,12 +176,11 @@ namespace api {
|
||||
pmr::vector<BufferBarrier> bufferBarrier{FramePool()};
|
||||
pmr::vector<TextureBarrier> textureBarrier{ FramePool() };
|
||||
auto graph = &RenderAPI::Ptr()->graph;
|
||||
node->ForeachEdge([&](FrameResource* resource, FrameGraphEdgePtr edge) {
|
||||
node->ForeachEdge([&](FrameResource* resource) {
|
||||
std::visit([&](auto& desc) {
|
||||
ResourceState targetState = edge.targetState;
|
||||
ResourceState sourceState = graph->Resolve(resource->name, desc, targetState);
|
||||
if (sourceState != targetState) {
|
||||
auto barrier = desc.ToBarrier(sourceState, targetState);
|
||||
ResourceState srcstate, dststate;
|
||||
if (!graph->ResolveState(desc, srcstate, dststate)) {
|
||||
auto barrier = desc.ToBarrier(srcstate, dststate);
|
||||
using T = decltype(barrier);
|
||||
if constexpr (std::is_same_v<T, BufferBarrier>) {
|
||||
bufferBarrier.push_back(barrier);
|
||||
@ -176,7 +189,7 @@ namespace api {
|
||||
textureBarrier.push_back(barrier);
|
||||
}
|
||||
}
|
||||
}, resource->resource);
|
||||
}, resource->res);
|
||||
});
|
||||
if (bufferBarrier.empty() && textureBarrier.empty()) {
|
||||
return;
|
||||
@ -189,47 +202,104 @@ namespace api {
|
||||
desc.pTextureBarriers = textureBarrier.data();
|
||||
RenderAPI::Ptr()->ExecuteResourceBarriers(desc);
|
||||
}
|
||||
ResourceState FrameGraph::Resolve(Name name, TextureDesc& desc, ResourceState state)
|
||||
void FrameGraph::TransitionState(TextureDesc& desc, ResourceState state)
|
||||
{
|
||||
ResourceState sourceState = ResourceState::UNDEFINED;
|
||||
if (name == NameSurface) {
|
||||
mSurface = desc;
|
||||
}
|
||||
return sourceState;
|
||||
}
|
||||
ResourceState FrameGraph::Resolve(Name name, AttachmentDesc& desc, ResourceState state)
|
||||
{
|
||||
ResourceState sourceState = ResourceState::UNDEFINED;
|
||||
if (name == NameSurface) {
|
||||
sourceState = mSurface.state;
|
||||
TextureDesc& texture = ResolveTexture(desc);
|
||||
desc.state = state;
|
||||
texture.state = state;
|
||||
if (texture.id == mSurface.id) {
|
||||
mSurface.state = state;
|
||||
return sourceState;
|
||||
}
|
||||
return sourceState;
|
||||
}
|
||||
ResourceState FrameGraph::Resolve(Name name, BufferDesc& desc, ResourceState state)
|
||||
{
|
||||
ResourceState sourceState = ResourceState::UNDEFINED;
|
||||
return sourceState;
|
||||
}
|
||||
ImagePtr FrameGraph::ResolveTexture(TextureDesc desc)
|
||||
{
|
||||
auto it = mTexturePool.find(desc);
|
||||
if (it != mTexturePool.end()) {
|
||||
return it->second;
|
||||
#ifdef WITH_EDITOR
|
||||
else if (texture.id == mEditorSurface.id) {
|
||||
mEditorSurface.state = state;
|
||||
}
|
||||
ImagePtr image = RenderAPI::Ptr()->CreateTexture(desc);
|
||||
mTexturePool.emplace(desc, image);
|
||||
return image;
|
||||
#endif // WITH_EDITOR
|
||||
}
|
||||
ImageViewPtr FrameGraph::ResolveTextureView(TextureViewDesc desc)
|
||||
bool FrameGraph::ResolveState(TextureDesc& desc, ResourceState& srcstart, ResourceState& dststate)
|
||||
{
|
||||
auto it = mTextureViewPool.find(desc);
|
||||
TextureDesc& texture = ResolveTexture(desc);
|
||||
srcstart = texture.state;
|
||||
dststate = desc.state;
|
||||
texture.state = dststate;
|
||||
if (texture.id == mSurface.id) {
|
||||
mSurface.state = dststate;
|
||||
}
|
||||
#ifdef WITH_EDITOR
|
||||
else if (texture.id == mEditorSurface.id) {
|
||||
mEditorSurface.state = dststate;
|
||||
}
|
||||
#endif // WITH_EDITOR
|
||||
return srcstart == dststate;
|
||||
}
|
||||
bool FrameGraph::ResolveState(AttachmentDesc& desc, ResourceState& srcstart, ResourceState& dststate)
|
||||
{
|
||||
return ResolveState(desc.texture, srcstart, dststate);
|
||||
}
|
||||
bool FrameGraph::ResolveState(BufferDesc& desc, ResourceState& srcstart, ResourceState& dststate)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
TextureDesc& FrameGraph::ResolveTexture(TextureDesc& desc)
|
||||
{
|
||||
if (!desc.id || desc.id > mTexturePool.size()) {
|
||||
return desc;
|
||||
}
|
||||
TextureDesc& texture = mTexturePool[desc.id - 1];
|
||||
if (!texture.image) {
|
||||
RenderAPI::Ptr()->CreateTexture(texture);
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
ImageViewPtr FrameGraph::ResolveTextureView(TextureDesc& desc)
|
||||
{
|
||||
if (!desc.image) {
|
||||
desc = ResolveTexture(desc);
|
||||
}
|
||||
return ResolveTextureView(desc.ToTextureView());
|
||||
}
|
||||
ImageViewPtr FrameGraph::ResolveTextureView(TextureViewKey key)
|
||||
{
|
||||
auto it = mTextureViewPool.find(key);
|
||||
if (it != mTextureViewPool.end()) {
|
||||
return it->second;
|
||||
}
|
||||
ImageViewPtr view = RenderAPI::Ptr()->CreateTextureView(desc);
|
||||
mTextureViewPool.emplace(desc, view);
|
||||
ImageViewPtr view = RenderAPI::Ptr()->CreateTextureView(key);
|
||||
mTextureViewPool.emplace(key, view);
|
||||
return view;
|
||||
}
|
||||
TextureDesc FrameGraph::ResourceTexture(Name name, int num)
|
||||
{
|
||||
Tag tag(name, num);
|
||||
auto it = mTextureTagMap.find(tag);
|
||||
if (it != mTextureTagMap.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return TextureDesc{};
|
||||
}
|
||||
void FrameGraph::ResourceTexture(TextureDesc& desc)
|
||||
{
|
||||
auto it = mTextureKeyMap.find(desc);
|
||||
if (it != mTextureKeyMap.end()) {
|
||||
desc.id = it->second;
|
||||
}
|
||||
else {
|
||||
desc.id = mTexturePool.size() + 1;
|
||||
mTextureKeyMap[desc] = desc.id;
|
||||
mTexturePool.push_back(desc);
|
||||
}
|
||||
}
|
||||
void FrameGraph::SetResourceTexture(TextureDesc desc, Name name, int num)
|
||||
{
|
||||
if (!desc.id) {
|
||||
desc.id = mTexturePool.size() + 1;
|
||||
mTexturePool.push_back(desc);
|
||||
}
|
||||
Tag tag(name, num);
|
||||
//auto it = mTextureTagMap.find(tag);
|
||||
//if (it != mTextureTagMap.end()) {
|
||||
//todo: destroy texture
|
||||
//}
|
||||
mTextureTagMap[tag] = desc;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,70 +1,24 @@
|
||||
#include "render/graph/frame_graph.h"
|
||||
#include "render/pass/render_pass.h"
|
||||
namespace api {
|
||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Name(pmr::Name name)
|
||||
RenderPassBuilder& RenderPassBuilder::Name(pmr::Name name)
|
||||
{
|
||||
node->name = name;
|
||||
return *this;
|
||||
}
|
||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Type(RenderPassNodeType type, RenderPassNodeFlag flag)
|
||||
RenderPassBuilder& RenderPassBuilder::Type(RenderPassNodeType type, RenderPassNodeFlag flag)
|
||||
{
|
||||
node->type = type;
|
||||
node->flag = flag;
|
||||
return *this;
|
||||
}
|
||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc, ResourceState state)
|
||||
{
|
||||
FrameGraphEdgePtr edge{};
|
||||
edge.targetState = state;
|
||||
resource = edge.Make();
|
||||
resource->source = node;
|
||||
resource->resource = desc;
|
||||
node->inEdges.push_back(edge);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(BufferDesc desc, ResourceState state)
|
||||
RenderPassBuilder& RenderPassBuilder::Write(AttachmentDesc desc, ResourceState state, pmr::Name name)
|
||||
{
|
||||
FrameGraphEdgePtr edge{};
|
||||
edge.targetState = state;
|
||||
resource = edge.Make();
|
||||
resource->source = node;
|
||||
resource->resource = desc;
|
||||
desc.texture.state = state;
|
||||
FrameGraphEdgePtr edge = FrameResource::Make(name, desc, node.node);
|
||||
node->outEdges.push_back(edge);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Attach(AttachmentDesc desc, ResourceState state)
|
||||
{
|
||||
FrameGraphEdgePtr edge{};
|
||||
edge.targetState = state;
|
||||
resource = edge.Make();
|
||||
resource->source = node;
|
||||
resource->resource = desc;
|
||||
node->outEdges.push_back(edge);
|
||||
return *this;
|
||||
}
|
||||
|
||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(const FrameGraphEdgePtr& refEdge, ResourceState state)
|
||||
{
|
||||
if (!refEdge) { return *this; }
|
||||
FrameGraphEdgePtr edge{ refEdge , state};
|
||||
node->inEdges.emplace_back(edge);
|
||||
refEdge->targets.emplace_back(node);
|
||||
return *this;
|
||||
}
|
||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(const FrameGraphEdgePtr& refEdge, ResourceState state)
|
||||
{
|
||||
if (!refEdge) { return *this; }
|
||||
FrameGraphEdgePtr edge{ refEdge , state };
|
||||
node->outEdges.emplace_back(edge);
|
||||
refEdge->targets.emplace_back(node);
|
||||
return *this;
|
||||
}
|
||||
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(pmr::Name name, AttachmentDesc desc)
|
||||
{
|
||||
edge->name = name;
|
||||
edge->resource = desc;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
@ -1,20 +1,18 @@
|
||||
#include "render/graph/type.h"
|
||||
#include "render/renderapi.h"
|
||||
namespace api {
|
||||
void FrameGraphEdgePtr::ResolveView(FrameGraph* graph)
|
||||
{
|
||||
if (resource->IsAttachment()) {
|
||||
AttachmentDesc& attach = resource->CastTo<AttachmentDesc>();
|
||||
TextureViewDesc desc = attach.ToTextureView();
|
||||
attach.imageView = graph->ResolveTextureView(desc);
|
||||
}
|
||||
}
|
||||
void RenderPassNode::ForeachEdge(RenderPassEdgeIterFn fn) {
|
||||
for (auto& edge : inEdges) {
|
||||
fn(edge.resource, edge);
|
||||
fn(edge);
|
||||
}
|
||||
for (auto& edge : outEdges) {
|
||||
fn(edge.resource, edge);
|
||||
fn(edge);
|
||||
}
|
||||
}
|
||||
FrameGraphNodePtr::FrameGraphNodePtr(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor, NodeType type) : type(type)
|
||||
{
|
||||
node = new (FramePool()) RenderPassNode();
|
||||
node->setup = setup;
|
||||
node->executor = executor;
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,16 +9,12 @@ namespace api {
|
||||
static RscHandle<Material> material;
|
||||
static RscHandle<Shader> shader;
|
||||
static RscHandle<Mesh> mesh;
|
||||
void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
|
||||
void DemoPass::Setup(FrameGraph& graph, RenderPassBuilder& builder)
|
||||
{
|
||||
AttachmentDesc surface{};
|
||||
surface.FromTexture(graph.mSurface);
|
||||
auto edge = graph.CreateTextureBuild()
|
||||
.Import(FrameGraph::NameSurface, surface)
|
||||
.Edge();
|
||||
AttachmentDesc surface{ graph.mSurface };
|
||||
builder.Name("MiniPass")
|
||||
.Type(RenderPassNodeType::Scene, RenderPassNodeFlag::Output)
|
||||
.Write(edge, ResourceState::COLOR_ATTACHMENT);
|
||||
.Write(surface, ResourceState::COLOR_ATTACHMENT);
|
||||
}
|
||||
void DemoPass::Execute(FrameGraph& graph, RenderPassContext& ctx)
|
||||
{
|
||||
|
||||
@ -173,17 +173,15 @@ namespace pmr {
|
||||
UNIQUER_INLINE_STATIC(StringEntryMemoryManager, stringEntryMemoryManager, "pmr::name::stringEntryMemoryManager")
|
||||
uint32_t flag3_memory29;
|
||||
public:
|
||||
friend class std::hash<Name>;
|
||||
Name()noexcept : flag3_memory29(0) {};
|
||||
Name(std::string view) noexcept : flag3_memory29(MakeInterned(view)) {};
|
||||
Name(std::string_view view) noexcept : flag3_memory29(MakeInterned(view)) {};
|
||||
template<size_t N>
|
||||
Name(const char(&str)[N]) noexcept : Name(std::string_view(str)) {}
|
||||
Name(const char* str)noexcept : Name(std::string_view(str)){};
|
||||
auto operator<=>(const Name& other) const noexcept { return flag3_memory29 <=> other.flag3_memory29; };
|
||||
constexpr auto operator<=>(const Name& other) const noexcept { return flag3_memory29 <=> other.flag3_memory29; };
|
||||
uint32_t MakeInterned(std::string_view view);
|
||||
uint32_t Hash() const{
|
||||
return flag3_memory29;
|
||||
}
|
||||
operator uint32_t() const {
|
||||
return flag3_memory29;
|
||||
}
|
||||
@ -212,14 +210,38 @@ namespace pmr {
|
||||
return std::string(stringEntry->GetData(), stringEntry->GetSize());
|
||||
}
|
||||
};
|
||||
|
||||
class Tag {
|
||||
private:
|
||||
Name name;
|
||||
int number;
|
||||
public:
|
||||
friend class std::hash<Tag>;
|
||||
Tag(Name name, int number): name(name), number(number) {}
|
||||
Tag(Name name): name(name), number(0) {}
|
||||
Tag(): name(), number(0) {}
|
||||
Name getName() const { return name; }
|
||||
int getNumber() const { return number; }
|
||||
constexpr auto operator<=>(const Tag& other) const noexcept = default;
|
||||
};
|
||||
}
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<::pmr::Name>
|
||||
{
|
||||
uint32_t operator()(const ::pmr::Name& name) const noexcept
|
||||
size_t operator()(const ::pmr::Name& name) const noexcept
|
||||
{
|
||||
return name.Hash();
|
||||
return std::hash<int>{}(name.flag3_memory29);
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct hash<::pmr::Tag>
|
||||
{
|
||||
size_t operator()(const ::pmr::Tag& tag) const noexcept
|
||||
{
|
||||
size_t h1 = std::hash<int>{}((uint32_t)tag.name);
|
||||
size_t h2 = std::hash<int>{}(tag.number);
|
||||
return h1 ^ (h2 + 0x9e3779b9 + (h1 << 6) + (h1 >> 2));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -37,6 +37,10 @@ namespace vkn {
|
||||
BufferCommand(const BufferUpload& cmd) : cmd(cmd){}
|
||||
BufferCommand(const BufferCreator& cmd) : cmd(cmd) {}
|
||||
};
|
||||
struct ImageCreator {
|
||||
VkImageCreateInfo imageInfo;
|
||||
VkImage* image;
|
||||
};
|
||||
class BufferWorker : public ThreadWorker<BufferCommand, BufferWorker>{
|
||||
public:
|
||||
//pmr::vector<Buffer> mPool{BufferPool()};
|
||||
@ -45,5 +49,6 @@ namespace vkn {
|
||||
void Loop();
|
||||
void UploadBuffer(const BufferUpload& elem);
|
||||
void CreateBuffer(BufferCreator& elem);
|
||||
void CreateImage(ImageCreator& elem);
|
||||
};
|
||||
};
|
||||
|
||||
@ -18,7 +18,7 @@ namespace vkn {
|
||||
using commandFn = std::function<void(CommandBuffer& cmd)>;
|
||||
using api::TargetBufferFlags;
|
||||
using api::ResourceBarrierDesc;
|
||||
using api::TextureViewDesc;
|
||||
using api::TextureViewKey;
|
||||
using api::ImageViewPtr;
|
||||
using api::ImagePtr;
|
||||
using api::TextureDimension;
|
||||
|
||||
@ -15,10 +15,10 @@ namespace vkn {
|
||||
private:
|
||||
VulkanWindow& window;
|
||||
Backend backend;
|
||||
table<Guid, MeshVAO> MeshTable;
|
||||
table<Guid, VulkanPipeline> PipelineTable;
|
||||
table<size_t, RenderPassInfo> RenderPassCache;
|
||||
table<Name, RenderPassInfo> RenderPassNameCache;
|
||||
table<Guid, MeshVAO> MeshTable;
|
||||
table<Guid, VulkanPipeline> PipelineTable;
|
||||
table<size_t, RenderPassInfo> RenderPassCache;
|
||||
table<Name, RenderPassInfo> RenderPassNameCache;
|
||||
table<FramebufferKey, VkFramebuffer> FramebufferCache;
|
||||
public:
|
||||
VulkanAPI();
|
||||
@ -32,8 +32,8 @@ namespace vkn {
|
||||
void LoadShader(Shader& shader, size_t passKey)override;
|
||||
|
||||
void CreateBuffer(BufferDesc& desc) override;
|
||||
ImagePtr CreateTexture(TextureDesc desc)override;
|
||||
ImageViewPtr CreateTextureView(TextureViewDesc desc)override;
|
||||
void CreateTexture(TextureDesc& desc)override;
|
||||
ImageViewPtr CreateTextureView(TextureViewKey desc)override;
|
||||
|
||||
void BeginFrame()override;
|
||||
void EndFrame()override;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#include "type.h"
|
||||
namespace vkn {
|
||||
using api::TextureUsage;
|
||||
using api::ResourceState;
|
||||
using api::TextureBarrier;
|
||||
using api::ShaderDescriptorType;
|
||||
@ -16,7 +17,7 @@ namespace vkn {
|
||||
VkImageLayout vkApiGetImageLayout(ResourceState layout);
|
||||
VkImageMemoryBarrier vkApiGetTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags& mDstStage, const TextureBarrier& barrier);
|
||||
VkImageAspectFlags vkApiGetImageAspectMask(VkFormat format, bool includeStencilBit);
|
||||
VkImageUsageFlags vkApiGetImageUsageFlags(ResourceState startState);
|
||||
VkImageUsageFlags vkApiGetImageUsageFlags(TextureUsage usage);
|
||||
VkImageViewType vkApiGetImageViewType(TextureDimension dimension, uint32_t arraySize);
|
||||
VkImageType vkApiGetImageType(TextureDimension dimension);
|
||||
VkImageCreateFlags vkApiGetImageCreateFlag(TextureDimension dimension, uint32_t arraySize);
|
||||
|
||||
@ -2,18 +2,24 @@
|
||||
#include "render/editor_system.h"
|
||||
#include "render/graph/frame_graph.h"
|
||||
namespace vkn {
|
||||
using api::TextureDesc;
|
||||
using api::FrameGraph;
|
||||
using api::RenderPassContext;
|
||||
using api::RenderPassBuilder;
|
||||
using api::RenderEditorContext;
|
||||
class VulkanImguiEditor : public api::EditorSystem {
|
||||
public:
|
||||
void Initialize() override;
|
||||
void Finalize() override;
|
||||
void Render();
|
||||
void OnBeginRenderFrame();
|
||||
|
||||
ImTextureID AddTexture(const TextureDesc& desc) override;
|
||||
|
||||
void Render(FrameGraph& graph, RenderEditorContext& ctx);
|
||||
void OnBeginRenderFrame(FrameGraph& graph, uint32_t frame);
|
||||
static VulkanImguiEditor* Ptr() {
|
||||
return (VulkanImguiEditor*)api::EditorSystem::Ptr();
|
||||
};
|
||||
static void Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder);
|
||||
static void Setup(FrameGraph& graph, RenderPassBuilder& builder);
|
||||
static void Execute(FrameGraph&, RenderPassContext&);
|
||||
};
|
||||
}
|
||||
@ -32,12 +32,6 @@ namespace vkn {
|
||||
VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args);
|
||||
void Aquire(VulkanContext& ctx);
|
||||
void Present(VulkanContext& ctx);
|
||||
int FrameCount() const {
|
||||
return mFrames;
|
||||
}
|
||||
const pmr::vector<TextureDesc>& GetSurface() {
|
||||
return mSurfaces;
|
||||
}
|
||||
};
|
||||
class VULKAN_API VulkanWindow : public api::Window {
|
||||
private:
|
||||
|
||||
@ -90,4 +90,13 @@ namespace vkn {
|
||||
if (elem.ppCpuData)
|
||||
vmaMapMemory(vmaAllocator, *elem.pAllocation, elem.ppCpuData);
|
||||
}
|
||||
void BufferWorker::CreateImage(ImageCreator& elem)
|
||||
{
|
||||
// 创建图像并分配内存
|
||||
VmaAllocationCreateInfo allocCreateInfo = {};
|
||||
allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||
|
||||
VmaAllocation allocation;
|
||||
VkResult result = vmaCreateImage(vmaAllocator, &elem.imageInfo, &allocCreateInfo, elem.image, &allocation, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,12 +269,8 @@ namespace vkn {
|
||||
{
|
||||
|
||||
}
|
||||
ImagePtr VulkanAPI::CreateTexture(TextureDesc desc)
|
||||
void VulkanAPI::CreateTexture(TextureDesc& desc)
|
||||
{
|
||||
if (desc.image) {
|
||||
return desc.image;
|
||||
}
|
||||
uint32_t depth = any(desc.dimension & TextureDimension::TEX_3D) ? 3 : 1;
|
||||
VkImageCreateInfo imageCreateInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.pNext = NULL,
|
||||
@ -290,15 +286,16 @@ namespace vkn {
|
||||
.arrayLayers = desc.arraySize,
|
||||
.samples = vkApiGetSmpleCountFlag(desc.sampleCount),
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.usage = vkApiGetImageUsageFlags(desc.state),
|
||||
.usage = vkApiGetImageUsageFlags(desc.usage),
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.queueFamilyIndexCount = 0,
|
||||
.pQueueFamilyIndices = NULL,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED
|
||||
.initialLayout = vkApiGetImageLayout(desc.state)
|
||||
};
|
||||
return ImagePtr();
|
||||
ImageCreator imageCreator{ .imageInfo = imageCreateInfo ,.image = (VkImage*)&desc.image };
|
||||
Backend::TransferWorker->CreateImage(imageCreator);
|
||||
}
|
||||
ImageViewPtr VulkanAPI::CreateTextureView(TextureViewDesc desc)
|
||||
ImageViewPtr VulkanAPI::CreateTextureView(TextureViewKey desc)
|
||||
{
|
||||
VkImageViewCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
@ -332,8 +329,8 @@ namespace vkn {
|
||||
{
|
||||
VulkanContext& ctx = *(VulkanContext*)&context;
|
||||
window.Aquire(ctx);
|
||||
graph.mSurface = ctx.surface;
|
||||
EventSystem::Ptr()->BeginRenderFrame.Invoke();
|
||||
graph.Input(ctx.surface);
|
||||
EventSystem::Ptr()->BeginRenderFrame.Invoke(graph, ctx.frame);
|
||||
}
|
||||
void VulkanAPI::EndFrame()
|
||||
{
|
||||
@ -361,7 +358,6 @@ namespace vkn {
|
||||
}
|
||||
void VulkanAPI::BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback)
|
||||
{
|
||||
RenderPassInfo* passInfo = GetRenderPassInfo(node->name, node->hash);
|
||||
RenderPassKey config{};
|
||||
FramebufferKey frameKey{.layers = 1};
|
||||
VkClearValue clearValues[2 * MAX_SUPPORTED_RENDER_TARGET_COUNT + 1] = { 0 };
|
||||
@ -369,22 +365,24 @@ namespace vkn {
|
||||
for (auto& it : node->outEdges) {
|
||||
if (it->IsAttachment()) {
|
||||
auto& desc = it->CastTo<api::AttachmentDesc>();
|
||||
|
||||
config.colorFormat[i] = (VkFormat)TinyImageFormat_ToVkFormat(desc.colorFormat);
|
||||
config.samples = vkApiGetSmpleCountFlag(desc.sampleCount);
|
||||
TextureDesc& texture = desc.texture;
|
||||
config.colorFormat[i] = (VkFormat)TinyImageFormat_ToVkFormat(texture.format);
|
||||
config.samples = vkApiGetSmpleCountFlag(texture.sampleCount);
|
||||
|
||||
TargetBufferFlags flag = TargetBufferFlags(int(TargetBufferFlags::COLOR0) << i);
|
||||
config.clear |= flag;
|
||||
it.ResolveView(&graph);
|
||||
desc.imageView = graph.ResolveTextureView(texture);
|
||||
|
||||
frameKey.imageViews[i] = (VkImageView)desc.imageView;
|
||||
frameKey.height = desc.height;
|
||||
frameKey.width = desc.width;
|
||||
frameKey.height = texture.height;
|
||||
frameKey.width = texture.width;
|
||||
|
||||
//clearValues[i] =
|
||||
i++;
|
||||
}
|
||||
}
|
||||
frameKey.attachmentCount = i;
|
||||
RenderPassInfo* passInfo = GetRenderPassInfo(node->name, node->hash);
|
||||
if (!passInfo) {
|
||||
passInfo = GetRenderPassInfo(node->hash, config);
|
||||
}
|
||||
|
||||
@ -179,12 +179,12 @@ namespace vkn {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
VkImageUsageFlags vkApiGetImageUsageFlags(ResourceState startState)
|
||||
VkImageUsageFlags vkApiGetImageUsageFlags(TextureUsage usage)
|
||||
{
|
||||
VkImageUsageFlags usageFlags = 0;
|
||||
if (any(startState & ResourceState::COLOR_ATTACHMENT))
|
||||
if (any(usage & TextureUsage::COLOR_ATTACHMENT))
|
||||
usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
else if (any(startState & ResourceState::DEPTH_ATTACHMENT))
|
||||
else if (any(usage & TextureUsage::DEPTH_ATTACHMENT))
|
||||
usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
return usageFlags;
|
||||
}
|
||||
@ -223,7 +223,7 @@ namespace vkn {
|
||||
if (any(dimension & TextureDimension::TEX_CUBE)) {
|
||||
flag |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
||||
}
|
||||
if (arraySize > 0) {
|
||||
if (arraySize > 1) {
|
||||
flag |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
|
||||
}
|
||||
return flag;
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "vkn/wrapper/queue.h"
|
||||
#include "imgui/imgui_impl_vulkan.h"
|
||||
#include "imgui/imgui_impl_sdl2.h"
|
||||
#include "data/global.h"
|
||||
#include "event/event_system.h"
|
||||
#include "tinyimageformat/tinyimageformat_apis.h"
|
||||
namespace vkn {
|
||||
@ -88,7 +89,7 @@ namespace vkn {
|
||||
Backend& backend = API->GetBackend();
|
||||
Queue* pQueue = backend.GetDevice().GetQueue(Queue::RenderQueue);
|
||||
VkDescriptorPool descriptorPool = CreateDescriptorPool(backend.GetDevice().Ptr());
|
||||
VkRenderPass renderPass = CreateRenderPass(API->graph.mSurface.format, backend.GetDevice().Ptr());
|
||||
VkRenderPass renderPass = CreateRenderPass(API->context.surface.format, backend.GetDevice().Ptr());
|
||||
|
||||
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||
init_info.Instance = backend.GetInstance().Ptr();
|
||||
@ -98,7 +99,7 @@ namespace vkn {
|
||||
init_info.Queue = pQueue->Ptr();
|
||||
init_info.DescriptorPool = descriptorPool;
|
||||
init_info.MinImageCount = 2;
|
||||
init_info.ImageCount = window->Swapchain()->FrameCount();
|
||||
init_info.ImageCount = API->context.frameCount;
|
||||
init_info.RenderPass = renderPass;
|
||||
init_info.PipelineCache = VK_NULL_HANDLE;
|
||||
init_info.Subpass = 0;
|
||||
@ -106,42 +107,69 @@ namespace vkn {
|
||||
init_info.Allocator = VK_NULL_HANDLE;
|
||||
ImGui_ImplVulkan_Init(&init_info);
|
||||
API->SetRenderPassInfo(ImguiPassName, renderPass);
|
||||
//gEngineConfig.IsRenderEditorSurface = true;
|
||||
if (gEngineConfig.IsRenderEditorSurface) {
|
||||
TextureDesc desc{};
|
||||
desc.width = 200;
|
||||
desc.height = 200;
|
||||
desc.format = TinyImageFormat_FromVkFormat((TinyImageFormat_VkFormat)VK_FORMAT_B8G8R8A8_SRGB);
|
||||
desc.state = ResourceState::UNDEFINED;
|
||||
desc.sampleCount = SampleCount::SAMPLE_COUNT_1;
|
||||
desc.arraySize = 1;
|
||||
desc.mipLevel = 1;
|
||||
desc.depth = 1;
|
||||
desc.dimension = TextureDimension::TEX_2D;
|
||||
desc.usage = TextureUsage::COLOR_ATTACHMENT;
|
||||
for (uint32_t i = 0; i < API->context.frameCount; i++) {
|
||||
API->graph.SetResourceTexture(desc, FrameGraph::NameEditorSurface, i);
|
||||
}
|
||||
}
|
||||
EventSystem::Ptr()->BeginRenderFrame.Subscribe(&VulkanImguiEditor::OnBeginRenderFrame, this);
|
||||
}
|
||||
void VulkanImguiEditor::Finalize()
|
||||
{
|
||||
|
||||
}
|
||||
void VulkanImguiEditor::Render()
|
||||
ImTextureID VulkanImguiEditor::AddTexture(const TextureDesc& desc)
|
||||
{
|
||||
// 2. 通过 ImGui_ImplVulkan_AddTexture 连接 Vulkan 纹理和 ImGui
|
||||
//ImTextureID textureID = (ImTextureID)(intptr_t)textureImageView;
|
||||
//ImGui_ImplVulkan_AddTexture(textureSampler, textureImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
return ImTextureID{};
|
||||
}
|
||||
void VulkanImguiEditor::Render(FrameGraph& graph, RenderEditorContext& ctx)
|
||||
{
|
||||
for (auto win : mWindows)
|
||||
{
|
||||
win->Draw();
|
||||
win->Draw(graph, ctx);
|
||||
}
|
||||
}
|
||||
void VulkanImguiEditor::OnBeginRenderFrame()
|
||||
void VulkanImguiEditor::OnBeginRenderFrame(FrameGraph& graph, uint32_t frame)
|
||||
{
|
||||
VulkanAPI::Ptr()->graph.AddRenderPass<VulkanImguiEditor>();
|
||||
graph.mIsRenderEditorSurface = gEngineConfig.IsRenderEditorSurface;
|
||||
if (gEngineConfig.IsRenderEditorSurface) {
|
||||
graph.mEditorSurface = graph.mSurface;
|
||||
graph.mSurface = graph.ResourceTexture(FrameGraph::NameEditorSurface, frame);
|
||||
}
|
||||
graph.AddRenderPass<VulkanImguiEditor>();
|
||||
}
|
||||
void VulkanImguiEditor::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
|
||||
void VulkanImguiEditor::Setup(FrameGraph& graph, RenderPassBuilder& builder)
|
||||
{
|
||||
AttachmentDesc surface{};
|
||||
surface.FromTexture(graph.mSurface);
|
||||
auto edge = graph.CreateTextureBuild()
|
||||
.Import(FrameGraph::NameSurface, surface)
|
||||
.Edge();
|
||||
AttachmentDesc surface{ gEngineConfig.IsRenderEditorSurface ? graph.mEditorSurface : graph.mSurface };
|
||||
builder.Name(ImguiPassName)
|
||||
.Type(RenderPassNodeType::Imgui, RenderPassNodeFlag::Output)
|
||||
.Write(edge, ResourceState::COLOR_ATTACHMENT);
|
||||
.Write(surface, ResourceState::COLOR_ATTACHMENT);
|
||||
}
|
||||
void VulkanImguiEditor::Execute(FrameGraph& graph, RenderPassContext& context)
|
||||
{
|
||||
graph.mSurface.state = ResourceState::PRESENT;
|
||||
TextureDesc& surface = graph.mEditorSurface.image ? graph.mEditorSurface : graph.mSurface;
|
||||
graph.TransitionState(surface, ResourceState::PRESENT);
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
VulkanImguiEditor::Ptr()->Render();
|
||||
RenderEditorContext editorContext{};
|
||||
VulkanImguiEditor::Ptr()->Render(graph, editorContext);
|
||||
|
||||
ImGui::Render();
|
||||
VulkanContext& ctx = *(VulkanContext*)context.parent;
|
||||
|
||||
@ -23,7 +23,8 @@ namespace vkn {
|
||||
args.height = mHeight;
|
||||
mSwapchain = new (GlobalPool()) VulkanSwapchain(backend.GetDevice(), surface, args);
|
||||
api->context.frameCount = args.frames;
|
||||
api->graph.InitSurface(std::span<TextureDesc>{mSwapchain->mSurfaces.data(), args.frames});
|
||||
api->context.surface = mSwapchain->mSurfaces[0];
|
||||
api->graph.InitSurface(mSwapchain->mSurfaces.data(), mSwapchain->mSurfaces.size());
|
||||
return true;
|
||||
}
|
||||
VulkanSwapchain::VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args)
|
||||
|
||||
@ -1,9 +1,17 @@
|
||||
#include "editor/panel/asset_preview_panel.h"
|
||||
#include "data/global.h"
|
||||
#include <imgui.h>
|
||||
namespace api {
|
||||
void AssetPreviewPanel::DrawPanel() {
|
||||
void AssetPreviewPanel::DrawPanel(FrameGraph& graph, RenderEditorContext& context) {
|
||||
static float my_float = 0.5f;
|
||||
ImGui::Text("This is some useful text.");
|
||||
ImGui::SliderFloat("float", &my_float, 0.0f, 1.0f);
|
||||
if (gEngineConfig.IsRenderEditorSurface) {
|
||||
TextureDesc& surface = graph.mSurface;
|
||||
// 2. 通过 ImGui_ImplVulkan_AddTexture 连接 Vulkan 纹理和 ImGui
|
||||
//ImTextureID textureID = (ImTextureID)(intptr_t)graph.ResolveTextureView(surface);
|
||||
// 3. 在 ImGui 窗口中渲染 Vulkan 纹理
|
||||
//ImGui::Image(textureID, ImVec2(surface.width, surface.height));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
#include <imgui.h>
|
||||
|
||||
namespace api {
|
||||
void MenuBarPanel::DrawPanel()
|
||||
void MenuBarPanel::DrawPanel(FrameGraph& graph, RenderEditorContext& context)
|
||||
{
|
||||
// 面板大小和位置
|
||||
if (ImGui::BeginMenu("Tools")) {
|
||||
|
||||
@ -8,11 +8,11 @@ namespace api {
|
||||
AddPanel<MenuBarPanel>();
|
||||
AddPanel<AssetPreviewPanel>();
|
||||
}
|
||||
void EditorMainWindow::Draw()
|
||||
void EditorMainWindow::Draw(FrameGraph& graph, RenderEditorContext& context)
|
||||
{
|
||||
ImGui::Begin("MainWindow");
|
||||
for (auto panel : mPanels) {
|
||||
panel->DrawPanel();
|
||||
panel->DrawPanel(graph, context);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@ -27,8 +27,8 @@ void ZWorldModule::OnLoad(int argc, char** argv)
|
||||
#ifdef WITH_EDITOR //绑定窗口交互
|
||||
ImGui_ImplSDL2_InitForVulkan(window->GetPtr());
|
||||
#endif
|
||||
EventSystem::Ptr()->BeginRenderFrame.Subscribe(mInfo.name, []() {
|
||||
API->graph.AddRenderPass<DemoPass>();
|
||||
EventSystem::Ptr()->BeginRenderFrame.Subscribe(mInfo.name, [](FrameGraph& graph, uint32_t frame) {
|
||||
graph.AddRenderPass<DemoPass>();
|
||||
});
|
||||
}
|
||||
void ZWorldModule::Initialize()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user