framegraph 资源优化 & 支持imgui::image
This commit is contained in:
parent
fef024d407
commit
44bf81dcfe
14
engine/modules/engine/render/impl/editor_system_impl.inl
Normal file
14
engine/modules/engine/render/impl/editor_system_impl.inl
Normal file
@ -0,0 +1,14 @@
|
||||
#include "render/editor_system.h"
|
||||
namespace api {
|
||||
SINGLETON_DEFINE(EditorSystem)
|
||||
EditorSystem::EditorSystem()
|
||||
{
|
||||
SINGLETON_PTR();
|
||||
}
|
||||
ImTextureID EditorSystem::AddTexture(FrameGraph& graph, TextureDesc& desc, TextureSampler key)
|
||||
{
|
||||
ImageViewPtr imageview = graph.ResolveTextureView(desc);
|
||||
SamplerPtr sampler = graph.ResolveTextureSampler(key);
|
||||
return AddTexture(imageview, sampler, desc.state);
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,5 @@
|
||||
#include "render/renderapi.h"
|
||||
#include "render/module.h"
|
||||
#ifdef WITH_EDITOR
|
||||
#include "render/editor_system.h"
|
||||
namespace api {
|
||||
SINGLETON_DEFINE(EditorSystem)
|
||||
EditorSystem::EditorSystem()
|
||||
{
|
||||
SINGLETON_PTR();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
namespace api {
|
||||
SINGLETON_DEFINE(RenderAPI)
|
||||
IMPLEMENT_STATIC_MODULE(RENDER_API, RenderModule, render);
|
||||
|
||||
@ -4,8 +4,14 @@
|
||||
#include "module/module_manager.h"
|
||||
#include <imgui.h>
|
||||
namespace api {
|
||||
class RenderEditorContext {
|
||||
|
||||
class EditorSystem;
|
||||
struct RenderEditorContext {
|
||||
EditorSystem* editor;
|
||||
uint32_t frame;
|
||||
uint32_t frameCount;
|
||||
EditorSystem* operator->() {
|
||||
return editor;
|
||||
}
|
||||
};
|
||||
class EditorPanel {
|
||||
public:
|
||||
@ -40,7 +46,8 @@ namespace api {
|
||||
mWindows.push_back(ptr);
|
||||
return ptr;
|
||||
}
|
||||
virtual ImTextureID AddTexture(const TextureDesc& desc) = 0;
|
||||
ImTextureID AddTexture(FrameGraph& graph, TextureDesc& desc, TextureSampler sampler);
|
||||
virtual ImTextureID AddTexture(ImageViewPtr imageview, SamplerPtr sampler, ResourceState state) = 0;
|
||||
};
|
||||
}
|
||||
#endif // WITH_EDITOR
|
||||
@ -6,8 +6,9 @@ namespace api {
|
||||
class FrameGraph
|
||||
{
|
||||
public:
|
||||
TextureDesc mSurface{};
|
||||
table<Tag, TextureDesc> mTextureTagMap;
|
||||
uint32_t mSurfaceID{0};
|
||||
table<TextureSampler, void*> mTextureSamplerPool;
|
||||
table<Tag, uint32_t> mTextureTagMap;
|
||||
table<TextureKey, uint32_t> mTextureKeyMap;
|
||||
std::vector<TextureDesc> mTexturePool;
|
||||
table<TextureViewKey, ImageViewPtr> mTextureViewPool;
|
||||
@ -17,8 +18,9 @@ namespace api {
|
||||
inline static Name NameSurface{ "surface" };
|
||||
#ifdef WITH_EDITOR
|
||||
inline static Name NameEditorSurface{ "editor_surface" };
|
||||
TextureDesc mEditorSurface{};
|
||||
bool mIsRenderEditorSurface{false};
|
||||
uint32_t mEditorSurfaceID{ 0 };
|
||||
TextureDesc& GetEditorSurface() { return ResolveTexture(mEditorSurfaceID); }
|
||||
#endif //
|
||||
public:
|
||||
template<typename T>
|
||||
@ -26,23 +28,27 @@ namespace api {
|
||||
FrameGraphNodePtr AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor);
|
||||
RenderPassBuilder CreateRenderPassBuild();
|
||||
void InitSurface(TextureDesc* surfaces, uint32_t frames);
|
||||
void Input(const TextureDesc& surfaces) { mSurface = surfaces; };
|
||||
void Input(const TextureDesc& surfaces) { mSurfaceID = surfaces.id; };
|
||||
void Setup();
|
||||
void Compile();
|
||||
void Execute(FRenderView& view);
|
||||
void Clear();
|
||||
void CullGraph();
|
||||
void FillGraph();
|
||||
TextureDesc& GetSurface() { return ResolveTexture(mSurfaceID); }
|
||||
TextureDesc& GetRenderSurface();
|
||||
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& ResolveTexture(uint32_t id);
|
||||
TextureDesc ResourceTexture(Name name, int num);
|
||||
ImageViewPtr ResolveTextureView(TextureDesc& desc);
|
||||
ImageViewPtr ResolveTextureView(TextureViewKey key);
|
||||
void* ResolveTextureSampler(TextureSampler sampler);
|
||||
void ResourceTexture(TextureDesc& desc);
|
||||
void SetResourceTexture(TextureDesc texture, Name name, int num = 0);
|
||||
uint32_t GetTextureID(Name name, int num);
|
||||
public:
|
||||
void ExecutePresentPass(FRenderView& view);
|
||||
void ExecuteRenderPass(RenderPassNode* node, FRenderView& view);
|
||||
|
||||
@ -11,6 +11,8 @@ namespace api {
|
||||
: graph(*graph) , node(node) {};
|
||||
RenderPassBuilder& Name(pmr::Name name);
|
||||
RenderPassBuilder& Type(RenderPassNodeType type,RenderPassNodeFlag flag = RenderPassNodeFlag::None);
|
||||
RenderPassBuilder& Read(TextureDesc desc, ResourceState state, pmr::Name name = {});
|
||||
RenderPassBuilder& Write(AttachmentDesc desc, ResourceState state, pmr::Name name = {});
|
||||
RenderPassBuilder& Dependency(RenderPassNode* rely) { node->dependencies.push_back(rely); return *this;}
|
||||
};
|
||||
}
|
||||
@ -40,9 +40,8 @@ namespace api {
|
||||
using Resource = std::variant<TextureDesc, BufferDesc, AttachmentDesc>;
|
||||
Name name;
|
||||
Resource res;
|
||||
RenderPassNode* node;
|
||||
FrameResource() noexcept = default;
|
||||
FrameResource(Name name,const Resource& res, RenderPassNode* node) : name(name), res(res), node(node){};
|
||||
FrameResource(Name name,const Resource& res) : name(name), res(res){};
|
||||
template<typename T>
|
||||
T& CastTo() {
|
||||
return std::get<T>(res);
|
||||
@ -56,8 +55,8 @@ namespace api {
|
||||
bool IsBuffer() const {
|
||||
return std::holds_alternative<BufferDesc>(res);
|
||||
}
|
||||
static FrameResource* Make(Name name, const Resource& res, RenderPassNode* node) {
|
||||
return new(FramePool()) FrameResource(name, res, node);
|
||||
static FrameResource* Make(Name name, const Resource& res) {
|
||||
return new(FramePool()) FrameResource(name, res);
|
||||
}
|
||||
};
|
||||
using FrameGraphEdgePtr = FrameResource*;
|
||||
|
||||
@ -35,7 +35,7 @@ namespace api {
|
||||
virtual void CreateBuffer(BufferDesc& desc) = 0;
|
||||
virtual void CreateTexture(TextureDesc& desc) = 0;
|
||||
virtual ImageViewPtr CreateTextureView(TextureViewKey desc) = 0;
|
||||
|
||||
virtual SamplerPtr CreateTextureSampler(TextureSampler sampler) = 0;
|
||||
virtual void BeginFrame() = 0;
|
||||
virtual void EndFrame() = 0;
|
||||
virtual void RenderView(FRenderView& view);
|
||||
|
||||
@ -119,6 +119,91 @@ namespace api {
|
||||
VERTEX = 0x1,
|
||||
FRAGMENT = 0x2,
|
||||
};
|
||||
//! Sampler Wrap mode
|
||||
enum class SamplerWrapMode : uint8_t {
|
||||
CLAMP_TO_EDGE, //!< clamp-to-edge. The edge of the texture extends to infinity.
|
||||
REPEAT, //!< repeat. The texture infinitely repeats in the wrap direction.
|
||||
MIRRORED_REPEAT, //!< mirrored-repeat. The texture infinitely repeats and mirrors in the wrap direction.
|
||||
};
|
||||
|
||||
//! Sampler minification filter
|
||||
enum class SamplerMinFilter : uint8_t {
|
||||
// don't change the enums values
|
||||
NEAREST = 0, //!< No filtering. Nearest neighbor is used.
|
||||
LINEAR = 1, //!< Box filtering. Weighted average of 4 neighbors is used.
|
||||
NEAREST_MIPMAP_NEAREST = 2, //!< Mip-mapping is activated. But no filtering occurs.
|
||||
LINEAR_MIPMAP_NEAREST = 3, //!< Box filtering within a mip-map level.
|
||||
NEAREST_MIPMAP_LINEAR = 4, //!< Mip-map levels are interpolated, but no other filtering occurs.
|
||||
LINEAR_MIPMAP_LINEAR = 5 //!< Both interpolated Mip-mapping and linear filtering are used.
|
||||
};
|
||||
|
||||
//! Sampler magnification filter
|
||||
enum class SamplerMagFilter : uint8_t {
|
||||
// don't change the enums values
|
||||
NEAREST = 0, //!< No filtering. Nearest neighbor is used.
|
||||
LINEAR = 1, //!< Box filtering. Weighted average of 4 neighbors is used.
|
||||
};
|
||||
|
||||
//! Sampler compare mode
|
||||
enum class SamplerCompareMode : uint8_t {
|
||||
// don't change the enums values
|
||||
NONE = 0,
|
||||
COMPARE_TO_TEXTURE = 1
|
||||
};
|
||||
|
||||
//! comparison function for the depth / stencil sampler
|
||||
enum class SamplerCompareFunc : uint8_t {
|
||||
// don't change the enums values
|
||||
LE = 0, //!< Less or equal
|
||||
GE, //!< Greater or equal
|
||||
L, //!< Strictly less than
|
||||
G, //!< Strictly greater than
|
||||
E, //!< Equal
|
||||
NE, //!< Not equal
|
||||
A, //!< Always. Depth / stencil testing is deactivated.
|
||||
N //!< Never. The depth / stencil test always fails.
|
||||
};
|
||||
using SamplerPtr = void*;
|
||||
//! Sampler parameters
|
||||
struct TextureSampler { // NOLINT
|
||||
SamplerMagFilter filterMag : 1; //!< magnification filter (NEAREST)
|
||||
SamplerMinFilter filterMin : 3; //!< minification filter (NEAREST)
|
||||
SamplerWrapMode wrapS : 2; //!< s-coordinate wrap mode (CLAMP_TO_EDGE)
|
||||
SamplerWrapMode wrapT : 2; //!< t-coordinate wrap mode (CLAMP_TO_EDGE)
|
||||
|
||||
SamplerWrapMode wrapR : 2; //!< r-coordinate wrap mode (CLAMP_TO_EDGE)
|
||||
uint8_t anisotropyLog2 : 3; //!< anisotropy level (0)
|
||||
SamplerCompareMode compareMode : 1; //!< sampler compare mode (NONE)
|
||||
uint8_t padding0 : 2; //!< reserved. must be 0.
|
||||
|
||||
SamplerCompareFunc compareFunc : 3; //!< sampler comparison function (LE)
|
||||
uint8_t padding1 : 5; //!< reserved. must be 0.
|
||||
uint8_t padding2 : 8; //!< reserved. must be 0.
|
||||
struct EqualTo {
|
||||
bool operator()(TextureSampler lhs, TextureSampler rhs) const noexcept {
|
||||
auto* pLhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&lhs));
|
||||
auto* pRhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&rhs));
|
||||
return *pLhs == *pRhs;
|
||||
}
|
||||
};
|
||||
|
||||
struct LessThan {
|
||||
bool operator()(TextureSampler lhs, TextureSampler rhs) const noexcept {
|
||||
auto* pLhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&lhs));
|
||||
auto* pRhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&rhs));
|
||||
return *pLhs == *pRhs;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
friend inline bool operator < (TextureSampler lhs, TextureSampler rhs) noexcept {
|
||||
return TextureSampler::LessThan{}(lhs, rhs);
|
||||
}
|
||||
public:
|
||||
friend inline bool operator== (TextureSampler lhs, TextureSampler rhs) noexcept {
|
||||
return TextureSampler::EqualTo{}(lhs, rhs);
|
||||
}
|
||||
};
|
||||
struct MaterialResource {
|
||||
Name name;
|
||||
bool isDirty;
|
||||
@ -209,6 +294,16 @@ namespace api {
|
||||
uint8_t layerCount;
|
||||
uint8_t baseMipLevel;
|
||||
uint8_t levelCount;
|
||||
friend 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;
|
||||
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;
|
||||
}
|
||||
};
|
||||
struct TextureKey {
|
||||
uint32_t id;
|
||||
@ -220,6 +315,17 @@ namespace api {
|
||||
TextureDimension dimension;
|
||||
uint8_t mipLevel;
|
||||
uint8_t arraySize;
|
||||
friend 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.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;
|
||||
}
|
||||
};
|
||||
struct TextureDesc : TextureKey {
|
||||
ImagePtr image;
|
||||
@ -303,27 +409,6 @@ namespace api {
|
||||
barrier.mTexture = texture;
|
||||
return barrier;
|
||||
}
|
||||
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;
|
||||
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 TextureKey& k1, const TextureKey& k2) {
|
||||
if (k1.format != k2.format) return false;
|
||||
if (k1.dimension != k2.dimension) 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"
|
||||
namespace std {
|
||||
@ -335,7 +420,7 @@ namespace std {
|
||||
return meta::MurmurHashFn(key);
|
||||
}
|
||||
};
|
||||
template<>
|
||||
template<>
|
||||
struct hash<api::TextureKey>
|
||||
{
|
||||
size_t operator()(const api::TextureKey& key) const noexcept
|
||||
@ -343,4 +428,12 @@ namespace std {
|
||||
return meta::MurmurHashFn(key);
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct hash<api::TextureSampler>
|
||||
{
|
||||
size_t operator()(const api::TextureSampler& key) const noexcept
|
||||
{
|
||||
return std::hash<int>{}(*(int*)&key);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -17,7 +17,8 @@ namespace api {
|
||||
}
|
||||
void FrameGraph::InitSurface(TextureDesc* surfaces, uint32_t frames)
|
||||
{
|
||||
mTexturePool.reserve(frames);
|
||||
mTexturePool.reserve(frames + 1);
|
||||
mTexturePool.push_back(TextureDesc{});
|
||||
for (uint32_t i = 0; i < frames;i++) {
|
||||
surfaces[i].id = mTexturePool.size() + 1;
|
||||
mTexturePool.push_back(surfaces[i]);
|
||||
@ -40,10 +41,8 @@ namespace api {
|
||||
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;
|
||||
@ -56,23 +55,6 @@ namespace api {
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!stack.empty()) {
|
||||
RenderPassNode* node = stack.top();
|
||||
stack.pop();
|
||||
if (node->isActive) {
|
||||
continue;
|
||||
}
|
||||
node->isActive = true;
|
||||
for (auto& edge : node->inEdges) {
|
||||
if (edge->node && !edge->node->isActive) {
|
||||
stack.push(edge->node);
|
||||
}
|
||||
}
|
||||
}
|
||||
auto end = std::remove_if(mNodes.begin(), mNodes.end(), [this](FrameGraphNodePtr& node) {
|
||||
return !node->isActive;
|
||||
});
|
||||
mNodes.erase(end, mNodes.end());
|
||||
if (outputNodes.size() > 1) {
|
||||
std::sort(outputNodes.begin(), outputNodes.end(), [](RenderPassNode* a, RenderPassNode* b) {
|
||||
if (a->type != b->type) {
|
||||
@ -84,20 +66,43 @@ namespace api {
|
||||
outputNodes[i]->dependencies.push_back(outputNodes[i - 1]);
|
||||
}
|
||||
}
|
||||
//todo 需要考虑拓扑排序
|
||||
std::stack<RenderPassNode*> stack;
|
||||
stack.push(mLastOutputNode);
|
||||
while (!stack.empty()) {
|
||||
RenderPassNode* node = stack.top();
|
||||
stack.pop();
|
||||
if (node->isActive) {
|
||||
continue;
|
||||
}
|
||||
node->isActive = true;
|
||||
for (auto& rely : node->dependencies) {
|
||||
if (!rely->isActive) {
|
||||
stack.push(rely);
|
||||
}
|
||||
}
|
||||
}
|
||||
auto end = std::remove_if(mNodes.begin(), mNodes.end(), [this](FrameGraphNodePtr& node) {
|
||||
return !node->isActive;
|
||||
});
|
||||
mNodes.erase(end, mNodes.end());
|
||||
}
|
||||
void FrameGraph::FillGraph()
|
||||
{
|
||||
std::pmr::unordered_set<RenderPassNode*> seenNodes{FramePool()};
|
||||
pmr::vector<RenderPassNode*> result{ FramePool() };
|
||||
for (auto& node : mNodes) {
|
||||
if (!node->dependencies.empty()) {
|
||||
seenNodes.insert(node->dependencies[0]);
|
||||
}
|
||||
for (auto& edge : node->inEdges) {
|
||||
RenderPassNode* srcNode = edge->node;
|
||||
if (srcNode && seenNodes.insert(srcNode).second) {
|
||||
node->dependencies.push_back(srcNode);
|
||||
bool isChange = false;
|
||||
for (auto& rely : node->dependencies) {
|
||||
bool isInsert = seenNodes.insert(rely).second;
|
||||
isChange = isChange || !isInsert;
|
||||
if (isInsert) {
|
||||
result.push_back(rely);
|
||||
}
|
||||
}
|
||||
if(isChange)
|
||||
node->dependencies = result;
|
||||
result.clear();
|
||||
seenNodes.clear();
|
||||
}
|
||||
if (mLastOutputNode) {
|
||||
@ -105,6 +110,14 @@ namespace api {
|
||||
mLastOutputNode->flag |= RenderPassNodeFlag::LastOutput;
|
||||
}
|
||||
}
|
||||
TextureDesc& FrameGraph::GetRenderSurface()
|
||||
{
|
||||
#ifdef WITH_EDITOR
|
||||
return ResolveTexture(mIsRenderEditorSurface ? mEditorSurfaceID: mSurfaceID);
|
||||
#else
|
||||
return ResolveTexture(mSurfaceID);
|
||||
#endif // WITH_EDITOR
|
||||
}
|
||||
void FrameGraph::Execute(FRenderView& view)
|
||||
{
|
||||
for (auto& node : mNodes) {
|
||||
@ -141,13 +154,8 @@ namespace api {
|
||||
}
|
||||
void FrameGraph::ExecutePresentPass(FRenderView& view)
|
||||
{
|
||||
#ifdef WITH_EDITOR
|
||||
TextureDesc& surface = ResolveTexture(mIsRenderEditorSurface ? mEditorSurface : mSurface);
|
||||
#else
|
||||
TextureDesc& surface = ResolveTexture(mSurface);
|
||||
#endif // WITH_EDITOR
|
||||
TextureDesc& surface = GetRenderSurface();
|
||||
if (surface.state == ResourceState::PRESENT) {
|
||||
surface.state = ResourceState::UNDEFINED;
|
||||
return;
|
||||
}
|
||||
TextureBarrier barrier{};
|
||||
@ -159,7 +167,6 @@ namespace api {
|
||||
desc.textureBarriersCount = 1;
|
||||
desc.pTextureBarriers = &barrier;
|
||||
view.context->ExecuteSurfaceBarriers(desc);
|
||||
surface.state = ResourceState::UNDEFINED;
|
||||
}
|
||||
void FrameGraph::ExecuteComputePass(RenderPassNode* node, FRenderView& view)
|
||||
{
|
||||
@ -204,32 +211,17 @@ namespace api {
|
||||
}
|
||||
void FrameGraph::TransitionState(TextureDesc& desc, ResourceState state)
|
||||
{
|
||||
TextureDesc& texture = ResolveTexture(desc);
|
||||
TextureDesc& texture = ResolveTexture(desc.id);
|
||||
desc.state = state;
|
||||
texture.state = state;
|
||||
if (texture.id == mSurface.id) {
|
||||
mSurface.state = state;
|
||||
}
|
||||
#ifdef WITH_EDITOR
|
||||
else if (texture.id == mEditorSurface.id) {
|
||||
mEditorSurface.state = state;
|
||||
}
|
||||
#endif // WITH_EDITOR
|
||||
}
|
||||
bool FrameGraph::ResolveState(TextureDesc& desc, ResourceState& srcstart, ResourceState& dststate)
|
||||
{
|
||||
TextureDesc& texture = ResolveTexture(desc);
|
||||
TextureDesc& texture = ResolveTexture(desc.id);
|
||||
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
|
||||
desc.image = texture.image;
|
||||
return srcstart == dststate;
|
||||
}
|
||||
bool FrameGraph::ResolveState(AttachmentDesc& desc, ResourceState& srcstart, ResourceState& dststate)
|
||||
@ -240,12 +232,12 @@ namespace api {
|
||||
{
|
||||
return true;
|
||||
}
|
||||
TextureDesc& FrameGraph::ResolveTexture(TextureDesc& desc)
|
||||
TextureDesc& FrameGraph::ResolveTexture(uint32_t id)
|
||||
{
|
||||
if (!desc.id || desc.id > mTexturePool.size()) {
|
||||
return desc;
|
||||
if (!id || id > mTexturePool.size()) {
|
||||
return mTexturePool[0];//empty
|
||||
}
|
||||
TextureDesc& texture = mTexturePool[desc.id - 1];
|
||||
TextureDesc& texture = mTexturePool[id - 1];
|
||||
if (!texture.image) {
|
||||
RenderAPI::Ptr()->CreateTexture(texture);
|
||||
}
|
||||
@ -254,7 +246,8 @@ namespace api {
|
||||
ImageViewPtr FrameGraph::ResolveTextureView(TextureDesc& desc)
|
||||
{
|
||||
if (!desc.image) {
|
||||
desc = ResolveTexture(desc);
|
||||
TextureDesc& texture = ResolveTexture(desc.id);
|
||||
desc.image = texture.image;
|
||||
}
|
||||
return ResolveTextureView(desc.ToTextureView());
|
||||
}
|
||||
@ -268,14 +261,22 @@ namespace api {
|
||||
mTextureViewPool.emplace(key, view);
|
||||
return view;
|
||||
}
|
||||
void* FrameGraph::ResolveTextureSampler(TextureSampler sampler)
|
||||
{
|
||||
auto iter = mTextureSamplerPool.find(sampler);
|
||||
if (iter != mTextureSamplerPool.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
return RenderAPI::Ptr()->CreateTextureSampler(sampler);
|
||||
}
|
||||
TextureDesc FrameGraph::ResourceTexture(Name name, int num)
|
||||
{
|
||||
Tag tag(name, num);
|
||||
auto it = mTextureTagMap.find(tag);
|
||||
if (it != mTextureTagMap.end()) {
|
||||
return it->second;
|
||||
return ResolveTexture(it->second);
|
||||
}
|
||||
return TextureDesc{};
|
||||
return mTexturePool[0];
|
||||
}
|
||||
void FrameGraph::ResourceTexture(TextureDesc& desc)
|
||||
{
|
||||
@ -289,17 +290,28 @@ namespace api {
|
||||
mTexturePool.push_back(desc);
|
||||
}
|
||||
}
|
||||
uint32_t FrameGraph::GetTextureID(Name name, int num)
|
||||
{
|
||||
Tag tag(name, num);
|
||||
auto it = mTextureTagMap.find(tag);
|
||||
if (it != mTextureTagMap.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void FrameGraph::SetResourceTexture(TextureDesc desc, Name name, int num)
|
||||
{
|
||||
if (!desc.id) {
|
||||
Tag tag(name, num);
|
||||
auto it = mTextureTagMap.find(tag);
|
||||
if (it != mTextureTagMap.end()) {
|
||||
//todo: destroy texture
|
||||
desc.id = it->second;
|
||||
mTexturePool[desc.id - 1] = desc;
|
||||
}
|
||||
else {
|
||||
desc.id = mTexturePool.size() + 1;
|
||||
mTexturePool.push_back(desc);
|
||||
mTextureTagMap[tag] = desc.id;
|
||||
}
|
||||
Tag tag(name, num);
|
||||
//auto it = mTextureTagMap.find(tag);
|
||||
//if (it != mTextureTagMap.end()) {
|
||||
//todo: destroy texture
|
||||
//}
|
||||
mTextureTagMap[tag] = desc;
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,10 +13,18 @@ namespace api {
|
||||
return *this;
|
||||
}
|
||||
|
||||
RenderPassBuilder& RenderPassBuilder::Read(TextureDesc desc, ResourceState state, pmr::Name name)
|
||||
{
|
||||
desc.state = state;
|
||||
FrameGraphEdgePtr edge = FrameResource::Make(name, desc);
|
||||
node->inEdges.push_back(edge);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RenderPassBuilder& RenderPassBuilder::Write(AttachmentDesc desc, ResourceState state, pmr::Name name)
|
||||
{
|
||||
desc.texture.state = state;
|
||||
FrameGraphEdgePtr edge = FrameResource::Make(name, desc, node.node);
|
||||
FrameGraphEdgePtr edge = FrameResource::Make(name, desc);
|
||||
node->outEdges.push_back(edge);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ namespace api {
|
||||
static RscHandle<Mesh> mesh;
|
||||
void DemoPass::Setup(FrameGraph& graph, RenderPassBuilder& builder)
|
||||
{
|
||||
AttachmentDesc surface{ graph.mSurface };
|
||||
AttachmentDesc surface{ graph.GetSurface()};
|
||||
builder.Name("MiniPass")
|
||||
.Type(RenderPassNodeType::Scene, RenderPassNodeFlag::Output)
|
||||
.Write(surface, ResourceState::COLOR_ATTACHMENT);
|
||||
@ -41,7 +41,7 @@ namespace api {
|
||||
auto materialInstance = mesh->GetMaterialInstance();
|
||||
materialInstance.SetClassResource(Name("uColor"), Vector4{1,0,0,1});
|
||||
}
|
||||
auto& surface = graph.mSurface;
|
||||
auto& surface = graph.GetSurface();
|
||||
ctx->SetViewport(0.0f, 0.0f,(float)surface.width,(float)surface.height, 0.f, 1.f);
|
||||
ctx->SetScissor(0, 0, surface.width, surface.height);
|
||||
RenderAPI::Ptr()->DrawStaticMesh(*mesh);
|
||||
|
||||
@ -23,6 +23,8 @@ namespace vkn {
|
||||
using api::ImagePtr;
|
||||
using api::TextureDimension;
|
||||
using api::SampleCount;
|
||||
using api::TextureSampler;
|
||||
using api::SamplerPtr;
|
||||
using api::ResourceState;
|
||||
using api::TextureDesc;
|
||||
using api::BufferDesc;
|
||||
@ -78,6 +80,17 @@ namespace vkn {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t layers;
|
||||
friend 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;
|
||||
}
|
||||
};
|
||||
// Equivalent to VkVertexInputAttributeDescription but half as big.
|
||||
struct VertexInputAttributeDescription {
|
||||
@ -121,17 +134,6 @@ namespace vkn {
|
||||
uint32_t descCount = 0;
|
||||
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 {
|
||||
template<>
|
||||
|
||||
@ -2,6 +2,11 @@
|
||||
#include "vulkan_context.h"
|
||||
#include "asset/res/guid.h"
|
||||
#include "backend.h"
|
||||
#ifdef API_DEBUG
|
||||
#define gLogSemaphore(...) //zlog::info(__VA_ARGS__)
|
||||
#else
|
||||
#define gLogSemaphore(...)
|
||||
#endif
|
||||
namespace vkn {
|
||||
class VulkanWindow;
|
||||
using api::Guid;
|
||||
@ -34,7 +39,7 @@ namespace vkn {
|
||||
void CreateBuffer(BufferDesc& desc) override;
|
||||
void CreateTexture(TextureDesc& desc)override;
|
||||
ImageViewPtr CreateTextureView(TextureViewKey desc)override;
|
||||
|
||||
SamplerPtr CreateTextureSampler(TextureSampler sampler) override;
|
||||
void BeginFrame()override;
|
||||
void EndFrame()override;
|
||||
void BeginRenderPass(RenderPassNode* node, FnEnterRenderPass callback) override;
|
||||
|
||||
@ -26,4 +26,5 @@ namespace vkn {
|
||||
VkDescriptorType vkApiGetDescriptorType(ShaderDescriptorType type);
|
||||
VkShaderStageFlags vkApiGetShaderStageFlags(ShaderStage stage);
|
||||
VkBufferUsageFlagBits vkApiGetBufferUsage(BufferUsage usage);
|
||||
VkSamplerCreateInfo vkApiGetSamplerCreateInfo(TextureSampler sampler);
|
||||
}
|
||||
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
#include "render/editor_system.h"
|
||||
#include "render/graph/frame_graph.h"
|
||||
#include "vkn/vulkan_api.h"
|
||||
namespace vkn {
|
||||
using api::TextureDesc;
|
||||
using api::FrameGraph;
|
||||
using api::RenderPassContext;
|
||||
using api::RenderPassBuilder;
|
||||
@ -12,7 +12,7 @@ namespace vkn {
|
||||
void Initialize() override;
|
||||
void Finalize() override;
|
||||
|
||||
ImTextureID AddTexture(const TextureDesc& desc) override;
|
||||
ImTextureID AddTexture(ImageViewPtr imageview, SamplerPtr sampler, ResourceState state) override;
|
||||
|
||||
void Render(FrameGraph& graph, RenderEditorContext& ctx);
|
||||
void OnBeginRenderFrame(FrameGraph& graph, uint32_t frame);
|
||||
|
||||
@ -325,6 +325,13 @@ namespace vkn {
|
||||
vkCreateImageView(backend.GetDevice().Ptr(), &createInfo, nullptr, &imageView);
|
||||
return (ImageViewPtr)imageView;
|
||||
}
|
||||
SamplerPtr VulkanAPI::CreateTextureSampler(TextureSampler key)
|
||||
{
|
||||
VkSamplerCreateInfo samplerInfo = vkApiGetSamplerCreateInfo(key);
|
||||
VkSampler sampler;
|
||||
vkCreateSampler(backend.GetDevice().Ptr(), &samplerInfo, nullptr, &sampler);
|
||||
return sampler;
|
||||
}
|
||||
void VulkanAPI::BeginFrame()
|
||||
{
|
||||
VulkanContext& ctx = *(VulkanContext*)&context;
|
||||
@ -435,13 +442,13 @@ namespace vkn {
|
||||
if (node->IsFirstInput()) {
|
||||
waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
waitSemaphores[semaphoreCount++] = ctx.surfaceSemaphore;
|
||||
//zlog::info("-----wait {:#x}", (uintptr_t)ctx.surfaceSemaphore);
|
||||
gLogSemaphore("-----wait {:#x}", (uintptr_t)ctx.surfaceSemaphore);
|
||||
}
|
||||
for (auto& it : node->dependencies) {
|
||||
RenderPassInfo* inputInfo = GetRenderPassInfo(it->name ,it->hash);
|
||||
waitDstStageMasks[semaphoreCount] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
waitSemaphores[semaphoreCount++] = inputInfo->semaphores[context.frame];
|
||||
//zlog::info("-----wait {:#x}", (uintptr_t)inputInfo->semaphores[context.frame]);
|
||||
gLogSemaphore("-----wait {:#x}", (uintptr_t)inputInfo->semaphores[context.frame]);
|
||||
}
|
||||
VkSubmitInfo submitInfo{};
|
||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
@ -455,11 +462,12 @@ namespace vkn {
|
||||
VkFence fence = nullptr;
|
||||
if (node->IsLastOutput()) {
|
||||
ctx.graphSemaphore = passInfo->semaphores[context.frame];
|
||||
if (graph.mSurface.state == ResourceState::PRESENT) {
|
||||
TextureDesc& surface = graph.GetRenderSurface();
|
||||
if (surface.state == ResourceState::PRESENT) {
|
||||
fence = ctx.surfaceFence;
|
||||
}
|
||||
}
|
||||
//zlog::info("+++++sign {:#x}", (uintptr_t)passInfo->semaphores[context.frame]);
|
||||
gLogSemaphore("+++++sign {:#x}", (uintptr_t)passInfo->semaphores[context.frame]);
|
||||
vkQueueSubmit(Backend::RenderWorker->GetQueue().Ptr(), 1, &submitInfo, fence);
|
||||
}
|
||||
RenderPassInfo* VulkanAPI::GetRenderPassInfo(Name name, size_t hash) {
|
||||
|
||||
@ -184,8 +184,10 @@ namespace vkn {
|
||||
VkImageUsageFlags usageFlags = 0;
|
||||
if (any(usage & TextureUsage::COLOR_ATTACHMENT))
|
||||
usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
else if (any(usage & TextureUsage::DEPTH_ATTACHMENT))
|
||||
if (any(usage & TextureUsage::DEPTH_ATTACHMENT))
|
||||
usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
if(any(usage & TextureUsage::SAMPLEABLE))
|
||||
usageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
return usageFlags;
|
||||
}
|
||||
VkImageViewType vkApiGetImageViewType(TextureDimension dimension, uint32_t arraySize)
|
||||
@ -267,4 +269,115 @@ namespace vkn {
|
||||
}
|
||||
return {};
|
||||
}
|
||||
using api::SamplerWrapMode;
|
||||
using api::SamplerMinFilter;
|
||||
using api::SamplerMagFilter;
|
||||
using api::SamplerCompareMode;
|
||||
using api::SamplerCompareFunc;
|
||||
constexpr inline VkSamplerAddressMode getWrapMode(SamplerWrapMode mode) noexcept {
|
||||
switch (mode) {
|
||||
case SamplerWrapMode::REPEAT:
|
||||
return VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
case SamplerWrapMode::CLAMP_TO_EDGE:
|
||||
return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
|
||||
case SamplerWrapMode::MIRRORED_REPEAT:
|
||||
return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline VkFilter getFilter(SamplerMinFilter filter) noexcept {
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMinFilter::LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST:
|
||||
return VK_FILTER_LINEAR;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline VkFilter getFilter(SamplerMagFilter filter) noexcept {
|
||||
switch (filter) {
|
||||
case SamplerMagFilter::NEAREST:
|
||||
return VK_FILTER_NEAREST;
|
||||
case SamplerMagFilter::LINEAR:
|
||||
return VK_FILTER_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline VkSamplerMipmapMode getMipmapMode(SamplerMinFilter filter) noexcept {
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST:
|
||||
return VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR:
|
||||
return VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline float getMaxLod(SamplerMinFilter filter) noexcept {
|
||||
switch (filter) {
|
||||
case SamplerMinFilter::NEAREST:
|
||||
case SamplerMinFilter::LINEAR:
|
||||
// The Vulkan spec recommends a max LOD of 0.25 to "disable" mipmapping.
|
||||
// See "Mapping of OpenGL to Vulkan filter modes" in the VK Spec.
|
||||
return 0.25f;
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_NEAREST:
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_NEAREST:
|
||||
case SamplerMinFilter::NEAREST_MIPMAP_LINEAR:
|
||||
case SamplerMinFilter::LINEAR_MIPMAP_LINEAR:
|
||||
return VK_LOD_CLAMP_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline VkBool32 getCompareEnable(SamplerCompareMode mode) noexcept {
|
||||
return mode == SamplerCompareMode::NONE ? VK_FALSE : VK_TRUE;
|
||||
}
|
||||
VkCompareOp getCompareOp(SamplerCompareFunc func) {
|
||||
using Compare = SamplerCompareFunc;
|
||||
switch (func) {
|
||||
case Compare::LE: return VK_COMPARE_OP_LESS_OR_EQUAL;
|
||||
case Compare::GE: return VK_COMPARE_OP_GREATER_OR_EQUAL;
|
||||
case Compare::L: return VK_COMPARE_OP_LESS;
|
||||
case Compare::G: return VK_COMPARE_OP_GREATER;
|
||||
case Compare::E: return VK_COMPARE_OP_EQUAL;
|
||||
case Compare::NE: return VK_COMPARE_OP_NOT_EQUAL;
|
||||
case Compare::A: return VK_COMPARE_OP_ALWAYS;
|
||||
case Compare::N: return VK_COMPARE_OP_NEVER;
|
||||
}
|
||||
}
|
||||
VkSamplerCreateInfo vkApiGetSamplerCreateInfo(TextureSampler sampler)
|
||||
{
|
||||
VkSamplerCreateInfo samplerInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.magFilter = getFilter(sampler.filterMag),
|
||||
.minFilter = getFilter(sampler.filterMin),
|
||||
.mipmapMode = getMipmapMode(sampler.filterMin),
|
||||
.addressModeU = getWrapMode(sampler.wrapS),
|
||||
.addressModeV = getWrapMode(sampler.wrapT),
|
||||
.addressModeW = getWrapMode(sampler.wrapR),
|
||||
.anisotropyEnable = sampler.anisotropyLog2 == 0 ? 0u : 1u,
|
||||
.maxAnisotropy = (float)(1u << sampler.anisotropyLog2),
|
||||
.compareEnable = getCompareEnable(sampler.compareMode),
|
||||
.compareOp = getCompareOp(sampler.compareFunc),
|
||||
.minLod = 0.0f,
|
||||
.maxLod = getMaxLod(sampler.filterMin),
|
||||
.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK,
|
||||
.unnormalizedCoordinates = VK_FALSE
|
||||
};
|
||||
return samplerInfo;
|
||||
}
|
||||
}
|
||||
@ -83,8 +83,8 @@ namespace vkn {
|
||||
|
||||
submitInfo.signalSemaphoreCount = 1;
|
||||
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||
//zlog::info("-----wait {:#x}", (uintptr_t)waitSemaphores[0]);
|
||||
//zlog::info("+++++sign {:#x}", (uintptr_t)signalSemaphores[0]);
|
||||
gLogSemaphore("-----wait {:#x}", (uintptr_t)waitSemaphores[0]);
|
||||
gLogSemaphore("+++++sign {:#x}", (uintptr_t)signalSemaphores[0]);
|
||||
vkQueueSubmit(queue, 1, &submitInfo, surfaceFence);
|
||||
graphSemaphore = presentSemaphore;
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#include "vkn/vulkan_imgui_editor.h"
|
||||
#include "vkn/vulkan_window.h"
|
||||
#include "vkn/vulkan_api.h"
|
||||
#include "vkn/vulkan_api_help.h"
|
||||
#include "vkn/backend.h"
|
||||
#include "vkn/wrapper/device.h"
|
||||
@ -110,8 +109,8 @@ namespace vkn {
|
||||
//gEngineConfig.IsRenderEditorSurface = true;
|
||||
if (gEngineConfig.IsRenderEditorSurface) {
|
||||
TextureDesc desc{};
|
||||
desc.width = 200;
|
||||
desc.height = 200;
|
||||
desc.width = 512;
|
||||
desc.height = 512;
|
||||
desc.format = TinyImageFormat_FromVkFormat((TinyImageFormat_VkFormat)VK_FORMAT_B8G8R8A8_SRGB);
|
||||
desc.state = ResourceState::UNDEFINED;
|
||||
desc.sampleCount = SampleCount::SAMPLE_COUNT_1;
|
||||
@ -119,7 +118,7 @@ namespace vkn {
|
||||
desc.mipLevel = 1;
|
||||
desc.depth = 1;
|
||||
desc.dimension = TextureDimension::TEX_2D;
|
||||
desc.usage = TextureUsage::COLOR_ATTACHMENT;
|
||||
desc.usage = TextureUsage::COLOR_ATTACHMENT | TextureUsage::SAMPLEABLE;
|
||||
for (uint32_t i = 0; i < API->context.frameCount; i++) {
|
||||
API->graph.SetResourceTexture(desc, FrameGraph::NameEditorSurface, i);
|
||||
}
|
||||
@ -130,12 +129,10 @@ namespace vkn {
|
||||
{
|
||||
|
||||
}
|
||||
ImTextureID VulkanImguiEditor::AddTexture(const TextureDesc& desc)
|
||||
ImTextureID VulkanImguiEditor::AddTexture(ImageViewPtr imageview, SamplerPtr sampler, ResourceState state)
|
||||
{
|
||||
// 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{};
|
||||
VkDescriptorSet descriptorSet = ImGui_ImplVulkan_AddTexture((VkSampler)sampler, (VkImageView)imageview, vkApiGetImageLayout(state));
|
||||
return reinterpret_cast<ImTextureID>(descriptorSet);
|
||||
}
|
||||
void VulkanImguiEditor::Render(FrameGraph& graph, RenderEditorContext& ctx)
|
||||
{
|
||||
@ -148,28 +145,31 @@ namespace vkn {
|
||||
{
|
||||
graph.mIsRenderEditorSurface = gEngineConfig.IsRenderEditorSurface;
|
||||
if (gEngineConfig.IsRenderEditorSurface) {
|
||||
graph.mEditorSurface = graph.mSurface;
|
||||
graph.mSurface = graph.ResourceTexture(FrameGraph::NameEditorSurface, frame);
|
||||
graph.mEditorSurfaceID = graph.mSurfaceID;
|
||||
graph.mSurfaceID = graph.GetTextureID(FrameGraph::NameEditorSurface, frame);
|
||||
}
|
||||
graph.AddRenderPass<VulkanImguiEditor>();
|
||||
}
|
||||
void VulkanImguiEditor::Setup(FrameGraph& graph, RenderPassBuilder& builder)
|
||||
{
|
||||
AttachmentDesc surface{ gEngineConfig.IsRenderEditorSurface ? graph.mEditorSurface : graph.mSurface };
|
||||
AttachmentDesc surface{ graph.GetRenderSurface() };
|
||||
builder.Name(ImguiPassName)
|
||||
.Type(RenderPassNodeType::Imgui, RenderPassNodeFlag::Output)
|
||||
.Write(surface, ResourceState::COLOR_ATTACHMENT);
|
||||
if (gEngineConfig.IsRenderEditorSurface) {
|
||||
builder.Read(graph.GetSurface(), ResourceState::READ_ONLY);
|
||||
}
|
||||
}
|
||||
void VulkanImguiEditor::Execute(FrameGraph& graph, RenderPassContext& context)
|
||||
{
|
||||
TextureDesc& surface = graph.mEditorSurface.image ? graph.mEditorSurface : graph.mSurface;
|
||||
graph.TransitionState(surface, ResourceState::PRESENT);
|
||||
graph.GetRenderSurface().state = ResourceState::PRESENT;
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
RenderEditorContext editorContext{};
|
||||
VulkanImguiEditor::Ptr()->Render(graph, editorContext);
|
||||
VulkanImguiEditor* editor = VulkanImguiEditor::Ptr();
|
||||
RenderEditorContext editorContext{.editor = editor, .frame = context->frame, .frameCount = context->frameCount };
|
||||
editor->Render(graph, editorContext);
|
||||
|
||||
ImGui::Render();
|
||||
VulkanContext& ctx = *(VulkanContext*)context.parent;
|
||||
|
||||
@ -103,11 +103,12 @@ namespace vkn {
|
||||
vkAcquireNextImageKHR(mDevice.Ptr(), mPtr, UINT64_MAX, surfaceSemaphore, VK_NULL_HANDLE, &ctx.presentFrame);
|
||||
vkResetFences(mDevice.Ptr(), 1, &surfaceFence);
|
||||
ctx.surface = mSurfaces[ctx.presentFrame];
|
||||
//zlog::info("aquire------------:: {:#x}", (uintptr_t)surfaceSemaphore);
|
||||
ctx.graphSemaphore = nullptr;
|
||||
gLogSemaphore("aquire------------:: {:#x}", (uintptr_t)surfaceSemaphore);
|
||||
}
|
||||
void VulkanSwapchain::Present(VulkanContext& ctx)
|
||||
{
|
||||
//zlog::info("present+++++++++++:: {:#x}", (uintptr_t)ctx.presentSemaphore);
|
||||
gLogSemaphore("present+++++++++++:: {:#x}", (uintptr_t)ctx.presentSemaphore);
|
||||
VkPresentInfoKHR presentInfo = {};
|
||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
presentInfo.pWaitSemaphores = &ctx.graphSemaphore;
|
||||
|
||||
@ -2,16 +2,19 @@
|
||||
#include "data/global.h"
|
||||
#include <imgui.h>
|
||||
namespace api {
|
||||
TextureSampler sampler;
|
||||
ImTextureID TextureIDList[10] = {};
|
||||
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));
|
||||
TextureDesc surface = graph.GetSurface();
|
||||
if (!TextureIDList[context.frame]) {
|
||||
TextureIDList[context.frame] = context->AddTexture(graph, surface, sampler);
|
||||
}
|
||||
// 每帧渲染时都可以通过 ImTextureID 使用
|
||||
ImGui::Image(TextureIDList[context.frame], ImVec2(surface.width, surface.height));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -21,6 +21,9 @@
|
||||
#define RENDER_API_VAL 1
|
||||
#include "renderapi_impl.inl"
|
||||
#include "window_impl.inl"
|
||||
#ifdef WITH_EDITOR
|
||||
#include "editor_system_impl.inl"
|
||||
#endif
|
||||
#endif // !RENDER_API_VAL
|
||||
|
||||
#ifndef APP_API_VAL
|
||||
|
||||
Loading…
Reference in New Issue
Block a user