vulkan api bugfix
This commit is contained in:
parent
c39296d050
commit
9b1704246d
@ -10,7 +10,7 @@ public:
|
|||||||
~Singleton() {
|
~Singleton() {
|
||||||
ms_Singleton = nullptr;
|
ms_Singleton = nullptr;
|
||||||
}
|
}
|
||||||
static constexpr T* Ptr(void) {
|
static T* Ptr(void) {
|
||||||
return ms_Singleton;
|
return ms_Singleton;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1,6 +1,7 @@
|
|||||||
#include "render/renderapi.h"
|
#include "render/renderapi.h"
|
||||||
#include "render/module.h"
|
#include "render/module.h"
|
||||||
namespace api {
|
namespace api {
|
||||||
|
RenderAPI* API;
|
||||||
IMPLEMENT_STATIC_MODULE(RENDER_API, RenderModule, render);
|
IMPLEMENT_STATIC_MODULE(RENDER_API, RenderModule, render);
|
||||||
void RenderAPI::RenderView(FRenderView& view)
|
void RenderAPI::RenderView(FRenderView& view)
|
||||||
{
|
{
|
||||||
@ -15,4 +16,15 @@ namespace api {
|
|||||||
RenderView(view);
|
RenderView(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RenderAPI::RenderAPI(RenderContext* ctx) : context(*ctx)
|
||||||
|
{
|
||||||
|
API = this;
|
||||||
|
}
|
||||||
|
RenderAPI::~RenderAPI()
|
||||||
|
{
|
||||||
|
delete& context;
|
||||||
|
}
|
||||||
|
RenderAPI* RenderAPI::Ptr() {
|
||||||
|
return API;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -10,15 +10,16 @@ namespace api {
|
|||||||
public:
|
public:
|
||||||
TextureDesc mSurface;
|
TextureDesc mSurface;
|
||||||
table<Name, TextureDesc> mResourceTable;
|
table<Name, TextureDesc> mResourceTable;
|
||||||
table<TextureDesc::Key, TextureDesc> mResourcePool;
|
table<TextureDesc, ImagePtr> mResourcePool;
|
||||||
table<TextureDesc::Key, TextureDesc> mResourceViewPool;
|
table<TextureViewDesc, ImageViewPtr> mResourceViewPool;
|
||||||
lemon::ListGraph mGraph;
|
lemon::ListGraph mGraph;
|
||||||
pmr::vector<FrameGraphNodePtr> mNodes{FramePool()};
|
pmr::vector<FrameGraphNodePtr> mNodes{FramePool()};
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
FrameGraphNodePtr AddRenderPass() { return AddRenderPass(&T::Setup, &T::Execute); }
|
FrameGraphNodePtr AddRenderPass() { return AddRenderPass(&T::Setup, &T::Execute); }
|
||||||
using RenderPassSetupFunction = std::function<void(FrameGraph&, RenderPassBuilder&)>;
|
using RenderPassSetupFunction = std::function<bool(FrameGraph&, RenderPassBuilder&)>;
|
||||||
FrameGraphNodePtr AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor);
|
FrameGraphNodePtr AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor);
|
||||||
|
FrameGraphNodePtr AddPresent(const FrameGraphEdgePtr& edge);
|
||||||
using TextureSetupFunction = std::function<void(FrameGraph&, class TextureBuilder&)>;
|
using TextureSetupFunction = std::function<void(FrameGraph&, class TextureBuilder&)>;
|
||||||
FrameGraphEdgePtr CreateTexture(const TextureSetupFunction& setup);
|
FrameGraphEdgePtr CreateTexture(const TextureSetupFunction& setup);
|
||||||
|
|
||||||
@ -26,12 +27,18 @@ namespace api {
|
|||||||
void Execute(FRenderView& view);
|
void Execute(FRenderView& view);
|
||||||
void Clear();
|
void Clear();
|
||||||
TextureDesc Resource(Name name) {
|
TextureDesc Resource(Name name) {
|
||||||
|
constexpr size_t surface = pmr::string_hash("surface");
|
||||||
|
if (name.Hash() == surface) {
|
||||||
|
return mSurface;
|
||||||
|
}
|
||||||
auto it = mResourceTable.find(name);
|
auto it = mResourceTable.find(name);
|
||||||
if (it == mResourceTable.end()) {
|
if (it == mResourceTable.end()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
ImagePtr ResolveTexture(TextureDesc desc);
|
||||||
|
ImageViewPtr ResolveTextureView(TextureViewDesc desc);
|
||||||
public:
|
public:
|
||||||
void ExecuteRenderPass(RenderPassNode* node, FRenderView& view);
|
void ExecuteRenderPass(RenderPassNode* node, FRenderView& view);
|
||||||
void ExecutePresentPass(RenderPassNode* node, FRenderView& view);
|
void ExecutePresentPass(RenderPassNode* node, FRenderView& view);
|
||||||
@ -41,3 +48,4 @@ namespace api {
|
|||||||
void ExecuteResourceBarriers(RenderPassNode* node);
|
void ExecuteResourceBarriers(RenderPassNode* node);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
#include "frame_graph_builder.inl"
|
||||||
@ -1,5 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "frame_graph.h"
|
|
||||||
namespace api {
|
namespace api {
|
||||||
struct FrameGraph::RenderPassBuilder {
|
struct FrameGraph::RenderPassBuilder {
|
||||||
FrameGraph& graph;
|
FrameGraph& graph;
|
||||||
@ -9,19 +8,18 @@ namespace api {
|
|||||||
RenderPassBuilder(FrameGraph* graph, FrameGraphNodePtr& node) noexcept
|
RenderPassBuilder(FrameGraph* graph, FrameGraphNodePtr& node) noexcept
|
||||||
: graph(*graph) , node(node) {};
|
: graph(*graph) , node(node) {};
|
||||||
FrameGraph::RenderPassBuilder& Name(pmr::Name name);
|
FrameGraph::RenderPassBuilder& Name(pmr::Name name);
|
||||||
FrameGraph::RenderPassBuilder& Pass(RenderPass* pass);
|
|
||||||
FrameGraph::RenderPassBuilder& Read(TextureDesc desc, ResourceState state);
|
FrameGraph::RenderPassBuilder& Read(TextureDesc desc, ResourceState state);
|
||||||
FrameGraph::RenderPassBuilder& Write(BufferDesc desc, ResourceState state);
|
FrameGraph::RenderPassBuilder& Write(BufferDesc desc, ResourceState state);
|
||||||
FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc, ResourceState state);
|
FrameGraph::RenderPassBuilder& Attach(AttachmentDesc desc, ResourceState state);
|
||||||
FrameGraph::RenderPassBuilder& Read(const FrameGraphEdgePtr& edge);
|
FrameGraph::RenderPassBuilder& Read(const FrameGraphEdgePtr& refEdge, ResourceState state);
|
||||||
FrameGraph::RenderPassBuilder& Write(const FrameGraphEdgePtr& edge);
|
FrameGraph::RenderPassBuilder& Write(const FrameGraphEdgePtr& refEdge, ResourceState state);
|
||||||
|
FrameGraph::RenderPassBuilder& Present(const FrameGraphEdgePtr& refEdge, ResourceState state);
|
||||||
};
|
};
|
||||||
struct FrameGraph::TextureBuilder {
|
struct FrameGraph::TextureBuilder {
|
||||||
FrameGraph& graph;
|
FrameGraph& graph;
|
||||||
FrameGraphEdgePtr& edge;
|
FrameGraphEdgePtr& edge;
|
||||||
public:
|
public:
|
||||||
TextureBuilder(FrameGraph* graph, FrameGraphEdgePtr& edge)noexcept : graph(*graph), edge(edge) {};
|
TextureBuilder(FrameGraph* graph, FrameGraphEdgePtr& edge)noexcept : graph(*graph), edge(edge) {};
|
||||||
FrameGraph::TextureBuilder& Name(pmr::Name name);
|
FrameGraph::TextureBuilder& Import(pmr::Name name, AttachmentDesc desc, ResourceState state);
|
||||||
FrameGraph::TextureBuilder& Import(ImagePtr& ptr, AttachmentDesc desc, ResourceState state);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -27,6 +27,7 @@ namespace api {
|
|||||||
NodeType type{ NodeType::Render };
|
NodeType type{ NodeType::Render };
|
||||||
RenderPassNode* node;
|
RenderPassNode* node;
|
||||||
FrameGraphNodePtr() : node(nullptr){};
|
FrameGraphNodePtr() : node(nullptr){};
|
||||||
|
FrameGraphNodePtr(GraphNodeRef ref, NodeType type = NodeType::Present);
|
||||||
FrameGraphNodePtr(GraphNodeRef ref, const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render);
|
FrameGraphNodePtr(GraphNodeRef ref, const RenderPassNodeExecuteFn& executor, NodeType type = NodeType::Render);
|
||||||
operator bool() const {
|
operator bool() const {
|
||||||
return node;
|
return node;
|
||||||
@ -34,6 +35,7 @@ namespace api {
|
|||||||
RenderPassNode* operator ->()const {
|
RenderPassNode* operator ->()const {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
void Presnet(FrameGraph&, RenderPassContext&);
|
||||||
};
|
};
|
||||||
struct FrameResource {
|
struct FrameResource {
|
||||||
using Resource = std::variant<TextureDesc, BufferDesc, AttachmentDesc>;
|
using Resource = std::variant<TextureDesc, BufferDesc, AttachmentDesc>;
|
||||||
@ -59,8 +61,11 @@ namespace api {
|
|||||||
struct FrameGraphEdgePtr {
|
struct FrameGraphEdgePtr {
|
||||||
ResourceState targetState;
|
ResourceState targetState;
|
||||||
FrameResource* resource;
|
FrameResource* resource;
|
||||||
ImagePtr* ppImage;
|
|
||||||
FrameGraphEdgePtr() = default;
|
FrameGraphEdgePtr() = default;
|
||||||
|
FrameGraphEdgePtr(const FrameGraphEdgePtr& edge, ResourceState state) {
|
||||||
|
targetState = state;
|
||||||
|
resource = edge.resource;
|
||||||
|
}
|
||||||
FrameResource* Make() {
|
FrameResource* Make() {
|
||||||
resource = new (FramePool()) FrameResource();
|
resource = new (FramePool()) FrameResource();
|
||||||
return resource;
|
return resource;
|
||||||
@ -72,11 +77,11 @@ namespace api {
|
|||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
void Resolve(FrameGraph* graph);
|
void Resolve(FrameGraph* graph);
|
||||||
|
void ResolveView(FrameGraph* graph);
|
||||||
};
|
};
|
||||||
using RenderPassEdgeIterFn = std::function<void(FrameResource*, FrameGraphEdgePtr)>;
|
using RenderPassEdgeIterFn = std::function<void(FrameResource*, FrameGraphEdgePtr)>;
|
||||||
struct RenderPassNode {
|
struct RenderPassNode {
|
||||||
Name name;
|
Name name;
|
||||||
const void* pass;
|
|
||||||
RenderPassNodeExecuteFn executor;
|
RenderPassNodeExecuteFn executor;
|
||||||
pmr::vector<FrameGraphEdgePtr> inEdges{ FramePool() };
|
pmr::vector<FrameGraphEdgePtr> inEdges{ FramePool() };
|
||||||
pmr::vector<FrameGraphEdgePtr> outEdges{ FramePool() };
|
pmr::vector<FrameGraphEdgePtr> outEdges{ FramePool() };
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "render_pass.h"
|
#include "render_pass.h"
|
||||||
#include "render/graph/frame_graph_builder.h"
|
#include "render/graph/frame_graph.h"
|
||||||
namespace api {
|
namespace api {
|
||||||
class DemoPass : public RenderPass {
|
class DemoPass : public RenderPass {
|
||||||
public:
|
public:
|
||||||
static void Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder);
|
static bool Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder);
|
||||||
static void Execute(FrameGraph&, RenderPassContext&);
|
static void Execute(FrameGraph&, RenderPassContext&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -7,19 +7,21 @@ namespace api {
|
|||||||
class Mesh;
|
class Mesh;
|
||||||
class Shader;
|
class Shader;
|
||||||
class RenderPassNode;
|
class RenderPassNode;
|
||||||
class RENDER_API RenderAPI : public Singleton<RenderAPI>
|
class RENDER_API RenderAPI
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderContext& context;
|
RenderContext& context;
|
||||||
FrameGraph graph;
|
FrameGraph graph;
|
||||||
RenderAPI(RenderContext* ctx) : context(*ctx){};
|
RenderAPI(RenderContext* ctx);
|
||||||
virtual ~RenderAPI() { delete &context; };
|
virtual ~RenderAPI();
|
||||||
public:
|
public:
|
||||||
void* operator new(size_t size) {
|
void* operator new(size_t size) {
|
||||||
return ::operator new(size, GlobalPool());
|
return ::operator new(size, GlobalPool());
|
||||||
}
|
}
|
||||||
void operator delete(void* p) {}
|
void operator delete(void* p) {}
|
||||||
|
static RenderAPI* Ptr();
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
virtual void Shutdown() = 0;
|
virtual void Shutdown() = 0;
|
||||||
|
|
||||||
@ -27,6 +29,8 @@ namespace api {
|
|||||||
virtual void DrawStaticMesh(Mesh& mesh) = 0;
|
virtual void DrawStaticMesh(Mesh& mesh) = 0;
|
||||||
|
|
||||||
virtual void LoadShader(Shader& shader) = 0;
|
virtual void LoadShader(Shader& shader) = 0;
|
||||||
|
virtual ImagePtr CreateTexture(TextureDesc desc) = 0;
|
||||||
|
virtual ImageViewPtr CreateTextureView(TextureViewDesc desc) = 0;
|
||||||
|
|
||||||
virtual void BeginFrame() = 0;
|
virtual void BeginFrame() = 0;
|
||||||
virtual void EndFrame() = 0;
|
virtual void EndFrame() = 0;
|
||||||
|
|||||||
@ -17,30 +17,6 @@ namespace api {
|
|||||||
SAMPLE_COUNT_16 = 16,
|
SAMPLE_COUNT_16 = 16,
|
||||||
SAMPLE_COUNT_COUNT = 5,
|
SAMPLE_COUNT_COUNT = 5,
|
||||||
};
|
};
|
||||||
struct BufferDesc {
|
|
||||||
static BufferDesc Make() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
using ImagePtr = void*;
|
|
||||||
struct TextureDesc {
|
|
||||||
using Key = uint32_t;
|
|
||||||
ImagePtr image;
|
|
||||||
static TextureDesc Make() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
struct AttachmentDesc {
|
|
||||||
ImagePtr image;
|
|
||||||
TinyImageFormat colorFormat;
|
|
||||||
SampleCount sampleCount;
|
|
||||||
static AttachmentDesc Make() {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
TextureDesc ToTexture() {
|
|
||||||
return TextureDesc{image};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
enum class TargetBufferFlags : uint32_t {
|
enum class TargetBufferFlags : uint32_t {
|
||||||
NONE = 0x0u, //!< No buffer selected.
|
NONE = 0x0u, //!< No buffer selected.
|
||||||
COLOR0 = 0x00000001u, //!< Color buffer selected.
|
COLOR0 = 0x00000001u, //!< Color buffer selected.
|
||||||
@ -81,8 +57,64 @@ namespace api {
|
|||||||
// For color attachments, but also used when the image is a sampler.
|
// For color attachments, but also used when the image is a sampler.
|
||||||
// TODO: explore separate layout policies for attachment+sampling and just attachment.
|
// TODO: explore separate layout policies for attachment+sampling and just attachment.
|
||||||
COLOR_ATTACHMENT,
|
COLOR_ATTACHMENT,
|
||||||
// For color attachment MSAA resolves.
|
};
|
||||||
COLOR_ATTACHMENT_RESOLVE,
|
enum class TextureDimension
|
||||||
|
{
|
||||||
|
TEX_1D = 0x01,
|
||||||
|
TEX_2D = 0x02,
|
||||||
|
TEX_3D = 0x04,
|
||||||
|
TEX_CUBE = 0x08,
|
||||||
|
};
|
||||||
|
using ImagePtr = void*;
|
||||||
|
using ImageViewPtr = void*;
|
||||||
|
struct BufferDesc {
|
||||||
|
static BufferDesc Make() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
struct TextureViewDesc {
|
||||||
|
ImagePtr image;
|
||||||
|
TinyImageFormat format : 16;
|
||||||
|
ResourceState state : 8;
|
||||||
|
TextureDimension dimension: 8;
|
||||||
|
uint32_t baseArrayLayer : 8;
|
||||||
|
uint32_t layerCount : 8;
|
||||||
|
uint32_t baseMipLevel : 8;
|
||||||
|
uint32_t levelCount : 8;
|
||||||
|
};
|
||||||
|
struct AttachmentDesc {
|
||||||
|
ImagePtr image;
|
||||||
|
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;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
TextureDesc ToTexture() {
|
||||||
|
return TextureDesc{
|
||||||
|
.image = image,
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct TextureBarrier
|
struct TextureBarrier
|
||||||
{
|
{
|
||||||
@ -115,3 +147,22 @@ namespace api {
|
|||||||
uint32_t textureBarriersCount;
|
uint32_t textureBarriersCount;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
#include "meta/hash.h"
|
||||||
|
namespace std {
|
||||||
|
template<>
|
||||||
|
struct hash<api::TextureViewDesc>
|
||||||
|
{
|
||||||
|
size_t operator()(const api::TextureViewDesc& key) const noexcept
|
||||||
|
{
|
||||||
|
return meta::MurmurHashFn(key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
struct hash<api::TextureDesc>
|
||||||
|
{
|
||||||
|
size_t operator()(const api::TextureDesc& key) const noexcept
|
||||||
|
{
|
||||||
|
return meta::MurmurHashFn(key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,12 +1,43 @@
|
|||||||
#include "render/graph/frame_graph.h"
|
#include "render/graph/frame_graph.h"
|
||||||
#include "render/graph/frame_graph_builder.h"
|
|
||||||
#include "render/renderapi.h"
|
#include "render/renderapi.h"
|
||||||
namespace api {
|
namespace api {
|
||||||
|
inline bool operator==(const TextureViewDesc& k1, const TextureViewDesc& k2) {
|
||||||
|
if (k1.image != k2.image) return false;
|
||||||
|
if (k1.format != k2.format) return false;
|
||||||
|
if (k1.dimension != k2.dimension) return false;
|
||||||
|
if (k1.state != k2.state) return false;
|
||||||
|
if (k1.baseArrayLayer != k2.baseArrayLayer) return false;
|
||||||
|
if (k1.layerCount != k2.layerCount) return false;
|
||||||
|
if (k1.baseMipLevel != k2.baseMipLevel) return false;
|
||||||
|
if (k1.levelCount != k2.levelCount) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
inline bool operator==(const TextureDesc& k1, const TextureDesc& k2) {
|
||||||
|
if (k1.image != k2.image) return false;
|
||||||
|
if (k1.format != k2.format) return false;
|
||||||
|
if (k1.dimension != k2.dimension) return false;
|
||||||
|
if (k1.state != k2.state) return false;
|
||||||
|
if (k1.width != k2.width) return false;
|
||||||
|
if (k1.height != k2.height) return false;
|
||||||
|
if (k1.arraySize != k2.arraySize) return false;
|
||||||
|
if (k1.mipLevel != k2.mipLevel) return false;
|
||||||
|
if (k1.sampleCount != k2.sampleCount) return false;
|
||||||
|
if (k1.depth != k2.depth) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
FrameGraphNodePtr FrameGraph::AddPresent(const FrameGraphEdgePtr& edge)
|
||||||
|
{
|
||||||
|
FrameGraphNodePtr node_ptr{ mGraph.addNode()};
|
||||||
|
RenderPassBuilder builder{ this, node_ptr };
|
||||||
|
builder.Read(edge, ResourceState::PRESENT);
|
||||||
|
mNodes.push_back(node_ptr);
|
||||||
|
return node_ptr;
|
||||||
|
}
|
||||||
FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor)
|
FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor)
|
||||||
{
|
{
|
||||||
FrameGraphNodePtr node_ptr{ mGraph.addNode(), executor };
|
FrameGraphNodePtr node_ptr{ mGraph.addNode(), executor };
|
||||||
RenderPassBuilder builder{ this, node_ptr };
|
RenderPassBuilder builder{ this, node_ptr };
|
||||||
setup(*this, builder);
|
if(setup(*this, builder))
|
||||||
mNodes.push_back(node_ptr);
|
mNodes.push_back(node_ptr);
|
||||||
return node_ptr;
|
return node_ptr;
|
||||||
}
|
}
|
||||||
@ -63,8 +94,7 @@ namespace api {
|
|||||||
}
|
}
|
||||||
void FrameGraph::ExecutePresentPass(RenderPassNode* node, FRenderView& view)
|
void FrameGraph::ExecutePresentPass(RenderPassNode* node, FRenderView& view)
|
||||||
{
|
{
|
||||||
RenderPassContext context{};
|
ExecuteResourceBarriers(node);
|
||||||
std::get<RenderPassExecuteFunction>(node->executor)(*this, context);
|
|
||||||
}
|
}
|
||||||
void FrameGraph::ExecuteComputePass(RenderPassNode* node, FRenderView& view)
|
void FrameGraph::ExecuteComputePass(RenderPassNode* node, FRenderView& view)
|
||||||
{
|
{
|
||||||
@ -104,6 +134,7 @@ namespace api {
|
|||||||
}
|
}
|
||||||
textureBarrier.push_back(barrier);
|
textureBarrier.push_back(barrier);
|
||||||
}
|
}
|
||||||
|
resource->sourceState = edge.targetState;
|
||||||
});
|
});
|
||||||
if (bufferBarrier.empty() && textureBarrier.empty()) {
|
if (bufferBarrier.empty() && textureBarrier.empty()) {
|
||||||
return;
|
return;
|
||||||
@ -123,4 +154,24 @@ namespace api {
|
|||||||
fn(edge.resource, edge);
|
fn(edge.resource, edge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ImagePtr FrameGraph::ResolveTexture(TextureDesc desc)
|
||||||
|
{
|
||||||
|
auto it = mResourcePool.find(desc);
|
||||||
|
if (it != mResourcePool.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
ImagePtr image = RenderAPI::Ptr()->CreateTexture(desc);
|
||||||
|
mResourcePool.emplace(desc, image);
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
ImageViewPtr FrameGraph::ResolveTextureView(TextureViewDesc desc)
|
||||||
|
{
|
||||||
|
auto it = mResourceViewPool.find(desc);
|
||||||
|
if (it != mResourceViewPool.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
ImageViewPtr view = RenderAPI::Ptr()->CreateTextureView(desc);
|
||||||
|
mResourceViewPool.emplace(desc, view);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,12 @@
|
|||||||
#include "render/graph/frame_graph_builder.h"
|
#include "render/graph/frame_graph.h"
|
||||||
#include "render/pass/render_pass.h"
|
#include "render/pass/render_pass.h"
|
||||||
|
#include "meta/enum.h"
|
||||||
namespace api {
|
namespace api {
|
||||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Name(pmr::Name name)
|
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Name(pmr::Name name)
|
||||||
{
|
{
|
||||||
node->name = name;
|
node->name = name;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Pass(RenderPass* pass)
|
|
||||||
{
|
|
||||||
node->pass = pass;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc, ResourceState state)
|
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(TextureDesc desc, ResourceState state)
|
||||||
{
|
{
|
||||||
FrameGraphEdgePtr edge{};
|
FrameGraphEdgePtr edge{};
|
||||||
@ -44,34 +40,39 @@ namespace api {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(const FrameGraphEdgePtr& edge)
|
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Read(const FrameGraphEdgePtr& refEdge, ResourceState state)
|
||||||
{
|
{
|
||||||
if (!edge) { return *this; }
|
if (!refEdge) { return *this; }
|
||||||
|
FrameGraphEdgePtr edge{ refEdge , state};
|
||||||
node->inEdges.emplace_back(edge);
|
node->inEdges.emplace_back(edge);
|
||||||
edge->targets.emplace_back(node);
|
refEdge->targets.emplace_back(node);
|
||||||
if(edge->source)
|
if(refEdge->source)
|
||||||
graph.mGraph.addEdge(edge->source.ref, node.ref);
|
graph.mGraph.addEdge(refEdge->source.ref, node.ref);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(const FrameGraphEdgePtr& edge)
|
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Write(const FrameGraphEdgePtr& refEdge, ResourceState state)
|
||||||
{
|
{
|
||||||
if (!edge) { return *this; }
|
if (!refEdge) { return *this; }
|
||||||
|
FrameGraphEdgePtr edge{ refEdge , state };
|
||||||
node->outEdges.emplace_back(edge);
|
node->outEdges.emplace_back(edge);
|
||||||
edge->targets.emplace_back(node);
|
refEdge->targets.emplace_back(node);
|
||||||
if (edge->source)
|
if (refEdge->source)
|
||||||
graph.mGraph.addEdge(node.ref, edge->source.ref);
|
graph.mGraph.addEdge(node.ref, refEdge->source.ref);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Name(pmr::Name name)
|
FrameGraph::RenderPassBuilder& FrameGraph::RenderPassBuilder::Present(const FrameGraphEdgePtr& refEdge, ResourceState state)
|
||||||
{
|
{
|
||||||
|
Write(refEdge, state);
|
||||||
|
graph.mNodes.push_back(node);
|
||||||
|
graph.AddPresent(refEdge);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(pmr::Name name, AttachmentDesc desc, ResourceState state)
|
||||||
|
{
|
||||||
|
desc.image = nullptr;
|
||||||
edge->name = name;
|
edge->name = name;
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
FrameGraph::TextureBuilder& FrameGraph::TextureBuilder::Import(ImagePtr& ptr, AttachmentDesc desc, ResourceState state)
|
|
||||||
{
|
|
||||||
edge.ppImage = &ptr;
|
|
||||||
edge.targetState = state;
|
|
||||||
edge->resource = desc;
|
edge->resource = desc;
|
||||||
|
edge.targetState = state;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
#include "render/graph/type.h"
|
#include "render/graph/type.h"
|
||||||
|
#include "render/renderapi.h"
|
||||||
namespace api {
|
namespace api {
|
||||||
void FrameGraphEdgePtr::Resolve(FrameGraph* graph)
|
void FrameGraphEdgePtr::Resolve(FrameGraph* graph)
|
||||||
{
|
{
|
||||||
@ -17,8 +18,42 @@ namespace api {
|
|||||||
if (*imageptr) {
|
if (*imageptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ppImage) {
|
TextureDesc desc = graph->Resource(resource->name);
|
||||||
*imageptr = *ppImage;
|
if (!desc.image) {
|
||||||
|
graph->ResolveTexture(desc);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
*imageptr = desc.image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void FrameGraphEdgePtr::ResolveView(FrameGraph* graph)
|
||||||
|
{
|
||||||
|
if (!resource) {
|
||||||
|
Make();
|
||||||
|
}
|
||||||
|
if (resource->IsAttachment()) {
|
||||||
|
AttachmentDesc& attach = resource->CastTo<AttachmentDesc>();
|
||||||
|
TextureViewDesc view{};
|
||||||
|
view.image = attach.image;
|
||||||
|
view.format = attach.colorFormat;
|
||||||
|
view.state = targetState;
|
||||||
|
view.baseArrayLayer = 0;
|
||||||
|
view.baseMipLevel = 0;
|
||||||
|
view.layerCount = 1;
|
||||||
|
view.levelCount = 1;
|
||||||
|
view.dimension = attach.dimension;
|
||||||
|
attach.imageView = graph->ResolveTextureView(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FrameGraphNodePtr::FrameGraphNodePtr(GraphNodeRef ref, NodeType type)
|
||||||
|
: ref(ref), type(type)
|
||||||
|
{
|
||||||
|
node = new (FramePool()) RenderPassNode();
|
||||||
|
node->executor = [&](FrameGraph& graph, RenderPassContext& ctx) {
|
||||||
|
this->Presnet(graph, ctx);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
void FrameGraphNodePtr::Presnet(FrameGraph&, RenderPassContext&) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,20 @@
|
|||||||
#include "render/pass/demo_pass.h"
|
#include "render/pass/demo_pass.h"
|
||||||
|
|
||||||
namespace api {
|
namespace api {
|
||||||
void DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
|
bool DemoPass::Setup(FrameGraph& graph, FrameGraph::RenderPassBuilder& builder)
|
||||||
{
|
{
|
||||||
AttachmentDesc surface{};
|
AttachmentDesc surface{};
|
||||||
surface.colorFormat = TinyImageFormat_B8G8R8A8_UNORM;
|
surface.FromTexture(graph.mSurface);
|
||||||
|
surface.colorFormat = TinyImageFormat_B8G8R8A8_SRGB;
|
||||||
surface.sampleCount = SAMPLE_COUNT_1;
|
surface.sampleCount = SAMPLE_COUNT_1;
|
||||||
|
surface.dimension = TextureDimension::TEX_2D;
|
||||||
auto edge = graph.CreateTexture(
|
auto edge = graph.CreateTexture(
|
||||||
[=](FrameGraph& graph, FrameGraph::TextureBuilder& builder) {
|
[=](FrameGraph& graph, FrameGraph::TextureBuilder& builder) {
|
||||||
builder.Name("import")
|
builder.Import("surface", surface, ResourceState::COLOR_ATTACHMENT);
|
||||||
.Import(graph.mSurface.image, surface, ResourceState::PRESENT);
|
|
||||||
});
|
});
|
||||||
builder.Name("MiniPass")
|
builder.Name("MiniPass")
|
||||||
.Write(edge);
|
.Present(edge, edge.targetState);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
void DemoPass::Execute(FrameGraph&, RenderPassContext&)
|
void DemoPass::Execute(FrameGraph&, RenderPassContext&)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
static_component("render","engine")
|
static_component("render","engine")
|
||||||
add_includedirs("3rdparty", {public = true})
|
add_includedirs("3rdparty", {public = true})
|
||||||
add_headerfiles("include/**.h", "impl/*.inl")
|
add_headerfiles("include/**.h", "include/**.inl", "impl/*.inl")
|
||||||
add_files("src/**.cpp")
|
add_files("src/**.cpp")
|
||||||
add_deps("asset", "zlib", "core")
|
add_deps("asset", "zlib", "core")
|
||||||
add_syslinks("user32", {public = true})
|
add_syslinks("user32", {public = true})
|
||||||
|
|||||||
@ -15,6 +15,14 @@ namespace vkn {
|
|||||||
using voidFn = std::function<void()>;
|
using voidFn = std::function<void()>;
|
||||||
using commandFn = std::function<void(CommandBuffer& cmd)>;
|
using commandFn = std::function<void(CommandBuffer& cmd)>;
|
||||||
using api::TargetBufferFlags;
|
using api::TargetBufferFlags;
|
||||||
|
using api::ResourceBarrierDesc;
|
||||||
|
using api::TextureViewDesc;
|
||||||
|
using api::ImageViewPtr;
|
||||||
|
using api::ImagePtr;
|
||||||
|
using api::TextureDimension;
|
||||||
|
using api::SampleCount;
|
||||||
|
using api::ResourceState;
|
||||||
|
using api::TextureDesc;
|
||||||
|
|
||||||
constexpr string_view VulkanEngineName = "vulkan";
|
constexpr string_view VulkanEngineName = "vulkan";
|
||||||
constexpr uint8_t MAX_SUPPORTED_RENDER_TARGET_COUNT = 8u;
|
constexpr uint8_t MAX_SUPPORTED_RENDER_TARGET_COUNT = 8u;
|
||||||
@ -37,8 +45,15 @@ namespace vkn {
|
|||||||
uint8_t initialColorLayoutMask;// 1 byte
|
uint8_t initialColorLayoutMask;// 1 byte
|
||||||
uint8_t needsResolveMask; // 1 byte
|
uint8_t needsResolveMask; // 1 byte
|
||||||
};
|
};
|
||||||
|
struct FramebufferKey {
|
||||||
|
VkRenderPass pass;
|
||||||
|
VkImageView imageViews[MAX_SUPPORTED_RENDER_TARGET_COUNT * 2 + 1];
|
||||||
|
uint32_t attachmentCount;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
uint32_t layers;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#include "meta/hash.h"
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template<>
|
template<>
|
||||||
struct hash<vkn::RenderPassKey>
|
struct hash<vkn::RenderPassKey>
|
||||||
@ -48,4 +63,12 @@ namespace std {
|
|||||||
return meta::MurmurHashFn(key);
|
return meta::MurmurHashFn(key);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
template<>
|
||||||
|
struct hash<vkn::FramebufferKey>
|
||||||
|
{
|
||||||
|
size_t operator()(const vkn::FramebufferKey& key) const noexcept
|
||||||
|
{
|
||||||
|
return meta::MurmurHashFn(key);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
@ -13,7 +13,6 @@ namespace vkn {
|
|||||||
using api::Mesh;
|
using api::Mesh;
|
||||||
using api::Shader;
|
using api::Shader;
|
||||||
using api::RenderPassNode;
|
using api::RenderPassNode;
|
||||||
using api::ResourceBarrierDesc;
|
|
||||||
struct VulkanContext : public api::RenderContext {
|
struct VulkanContext : public api::RenderContext {
|
||||||
VkFence surfaceFence;;
|
VkFence surfaceFence;;
|
||||||
VkSemaphore surfaceSemaphore;
|
VkSemaphore surfaceSemaphore;
|
||||||
@ -26,6 +25,7 @@ namespace vkn {
|
|||||||
Backend backend;
|
Backend backend;
|
||||||
table<Guid, MeshVAO> MeshTable;
|
table<Guid, MeshVAO> MeshTable;
|
||||||
table<RenderPassKey, VkRenderPass> RenderPassCache;
|
table<RenderPassKey, VkRenderPass> RenderPassCache;
|
||||||
|
table<FramebufferKey, VkFramebuffer> FramebufferCache;
|
||||||
public:
|
public:
|
||||||
VulkanAPI();
|
VulkanAPI();
|
||||||
|
|
||||||
@ -36,6 +36,8 @@ namespace vkn {
|
|||||||
void DrawStaticMesh(Mesh& mesh)override;
|
void DrawStaticMesh(Mesh& mesh)override;
|
||||||
|
|
||||||
void LoadShader(Shader& shader)override;
|
void LoadShader(Shader& shader)override;
|
||||||
|
ImagePtr CreateTexture(TextureDesc desc)override;
|
||||||
|
ImageViewPtr CreateTextureView(TextureViewDesc desc)override;
|
||||||
|
|
||||||
void BeginFrame()override;
|
void BeginFrame()override;
|
||||||
void EndFrame()override;
|
void EndFrame()override;
|
||||||
@ -43,7 +45,7 @@ namespace vkn {
|
|||||||
void EndRenderPass(RenderPassNode* node) override;
|
void EndRenderPass(RenderPassNode* node) override;
|
||||||
void ExecuteResourceBarriers(const ResourceBarrierDesc& desc) override;
|
void ExecuteResourceBarriers(const ResourceBarrierDesc& desc) override;
|
||||||
|
|
||||||
VkPipeline GetPipeline();
|
VkPipeline GetPipeline() { return nullptr; };
|
||||||
VkRenderPass GetRenderPass(RenderPassKey& config);
|
VkRenderPass GetRenderPass(RenderPassKey& config);
|
||||||
|
|
||||||
Backend& GetBackend() {
|
Backend& GetBackend() {
|
||||||
|
|||||||
@ -10,6 +10,13 @@ namespace vkn {
|
|||||||
VkImageLayout mSrcState;
|
VkImageLayout mSrcState;
|
||||||
VkImageLayout mDstState;
|
VkImageLayout mDstState;
|
||||||
};
|
};
|
||||||
VkImageLayout GetVkLayout(ResourceState layout);
|
VkImageLayout vkApiGetAttachmentLayout(VkFormat format, bool includeStencilBit);
|
||||||
VkImageMemoryBarrier GetVkTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags mDstStage, const TextureBarrier& barrier);
|
VkImageLayout vkApiGetImageLayout(ResourceState layout);
|
||||||
|
VkImageMemoryBarrier vkApiGetTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags& mDstStage, const TextureBarrier& barrier);
|
||||||
|
VkImageAspectFlags vkApiGetImageAspectMask(VkFormat format, bool includeStencilBit);
|
||||||
|
VkImageUsageFlags vkApiGetImageUsageFlags(ResourceState startState);
|
||||||
|
VkImageViewType vkApiGetImageViewType(TextureDimension dimension, uint32_t arraySize);
|
||||||
|
VkImageType vkApiGetImageType(TextureDimension dimension);
|
||||||
|
VkImageCreateFlags vkApiGetImageCreateFlag(TextureDimension dimension, uint32_t arraySize);
|
||||||
|
VkSampleCountFlagBits vkApiGetSmpleCountFlag(SampleCount sample);
|
||||||
}
|
}
|
||||||
@ -20,10 +20,11 @@ namespace vkn {
|
|||||||
};
|
};
|
||||||
class VulkanSwapchain {
|
class VulkanSwapchain {
|
||||||
private:
|
private:
|
||||||
|
friend class VulkanWindow;
|
||||||
Device& mDevice;
|
Device& mDevice;
|
||||||
VkSwapchainKHR mPtr;
|
VkSwapchainKHR mPtr;
|
||||||
int mFrames;
|
int mFrames;
|
||||||
pmr::vector<TextureDesc> mSurfaces{GlobalPool()};
|
pmr::vector<TextureDesc> mSurfaces{ GlobalPool() };
|
||||||
pmr::vector<VkCommandBuffer> mCommands{ GlobalPool() };
|
pmr::vector<VkCommandBuffer> mCommands{ GlobalPool() };
|
||||||
pmr::vector<VkFence> mFences{ GlobalPool() };
|
pmr::vector<VkFence> mFences{ GlobalPool() };
|
||||||
pmr::vector<VkSemaphore> mSemaphores{ GlobalPool() };
|
pmr::vector<VkSemaphore> mSemaphores{ GlobalPool() };
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
#include "render/asset/mesh.h"
|
#include "render/asset/mesh.h"
|
||||||
#include "meta/enum.h"
|
#include "meta/enum.h"
|
||||||
#include "tinyimageformat/tinyimageformat_apis.h"
|
#include "tinyimageformat/tinyimageformat_apis.h"
|
||||||
|
#include "zlog.h"
|
||||||
namespace vkn {
|
namespace vkn {
|
||||||
inline bool operator==(const RenderPassKey& k1, const RenderPassKey& k2) {
|
inline bool operator==(const RenderPassKey& k1, const RenderPassKey& k2) {
|
||||||
if (k1.initialColorLayoutMask != k2.initialColorLayoutMask) return false;
|
if (k1.initialColorLayoutMask != k2.initialColorLayoutMask) return false;
|
||||||
@ -24,6 +24,17 @@ namespace vkn {
|
|||||||
if (k1.subpassMask != k2.subpassMask) return false;
|
if (k1.subpassMask != k2.subpassMask) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
inline bool operator==(const FramebufferKey& k1, const FramebufferKey& k2) {
|
||||||
|
if (k1.pass != k2.pass) return false;
|
||||||
|
if (k1.attachmentCount != k2.attachmentCount) return false;
|
||||||
|
for (int i = 0; i < k1.attachmentCount; i++) {
|
||||||
|
if (k1.imageViews[i] != k2.imageViews[i]) return false;
|
||||||
|
}
|
||||||
|
if (k1.height != k2.height) return false;
|
||||||
|
if (k1.width != k2.width) return false;
|
||||||
|
if (k1.layers != k2.layers) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
VulkanAPI::VulkanAPI() : RenderAPI(new VulkanContext())
|
VulkanAPI::VulkanAPI() : RenderAPI(new VulkanContext())
|
||||||
, window(*VulkanWindow::Ptr())
|
, window(*VulkanWindow::Ptr())
|
||||||
, backend(VulkanEngineName)
|
, backend(VulkanEngineName)
|
||||||
@ -67,6 +78,65 @@ namespace vkn {
|
|||||||
void VulkanAPI::LoadShader(Shader& shader)
|
void VulkanAPI::LoadShader(Shader& shader)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
ImagePtr 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,
|
||||||
|
.flags = vkApiGetImageCreateFlag(desc.dimension, desc.arraySize),
|
||||||
|
.imageType = vkApiGetImageType(desc.dimension),
|
||||||
|
.format = (VkFormat)TinyImageFormat_ToVkFormat(desc.format),
|
||||||
|
.extent = {
|
||||||
|
.width = (uint32_t)desc.width,
|
||||||
|
.height = (uint32_t)desc.height,
|
||||||
|
.depth = (uint32_t)desc.depth,
|
||||||
|
},
|
||||||
|
.mipLevels = desc.mipLevel,
|
||||||
|
.arrayLayers = desc.arraySize,
|
||||||
|
.samples = vkApiGetSmpleCountFlag(desc.sampleCount),
|
||||||
|
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||||
|
.usage = vkApiGetImageUsageFlags(desc.state),
|
||||||
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||||
|
.queueFamilyIndexCount = 0,
|
||||||
|
.pQueueFamilyIndices = NULL,
|
||||||
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED
|
||||||
|
};
|
||||||
|
return ImagePtr();
|
||||||
|
}
|
||||||
|
ImageViewPtr VulkanAPI::CreateTextureView(TextureViewDesc desc)
|
||||||
|
{
|
||||||
|
VkImageViewCreateInfo createInfo = {};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
createInfo.image = (VkImage)desc.image;
|
||||||
|
createInfo.viewType = vkApiGetImageViewType(desc.dimension, desc.layerCount);
|
||||||
|
createInfo.format = (VkFormat)TinyImageFormat_ToVkFormat(desc.format);
|
||||||
|
|
||||||
|
// components字段允许调整颜色通道的最终的映射逻辑
|
||||||
|
// 比如,我们可以将所有颜色通道映射为红色通道,以实现单色纹理,我们也可以将通道映射具体的常量数值0和1
|
||||||
|
// 这里用默认的
|
||||||
|
createInfo.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||||
|
createInfo.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||||
|
createInfo.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||||
|
createInfo.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||||
|
|
||||||
|
// subresourceRangle字段用于描述图像的使用目标是什么,以及可以被访问的有效区域
|
||||||
|
// 这个图像用作填充color还是depth stencil等
|
||||||
|
createInfo.subresourceRange.aspectMask = vkApiGetImageAspectMask(createInfo.format, false);
|
||||||
|
// 默认处理所有Mipmap
|
||||||
|
createInfo.subresourceRange.baseMipLevel = desc.baseMipLevel;
|
||||||
|
createInfo.subresourceRange.levelCount = desc.levelCount;
|
||||||
|
// 默认处理所有Layers
|
||||||
|
createInfo.subresourceRange.baseArrayLayer = desc.baseArrayLayer;
|
||||||
|
createInfo.subresourceRange.layerCount = desc.layerCount;
|
||||||
|
|
||||||
|
VkImageView imageView;
|
||||||
|
vkCreateImageView(backend.GetDevice().Ptr(), &createInfo, nullptr, &imageView);
|
||||||
|
return (ImageViewPtr)imageView;
|
||||||
|
}
|
||||||
void VulkanAPI::BeginFrame()
|
void VulkanAPI::BeginFrame()
|
||||||
{
|
{
|
||||||
VulkanContext& ctx = *(VulkanContext*)&context;
|
VulkanContext& ctx = *(VulkanContext*)&context;
|
||||||
@ -77,7 +147,21 @@ namespace vkn {
|
|||||||
{
|
{
|
||||||
VulkanContext& ctx = *(VulkanContext*)&context;
|
VulkanContext& ctx = *(VulkanContext*)&context;
|
||||||
ctx.command.EndRecord();
|
ctx.command.EndRecord();
|
||||||
ctx.command.Submit(Backend::RenderWorker->GetQueue().Ptr(), ctx.surfaceFence);
|
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; // 等待渲染阶段
|
||||||
|
VkSemaphore waitSemaphores[] = { ctx.surfaceSemaphore };
|
||||||
|
VkSemaphore signalSemaphores[] = { ctx.presentSemaphore };// 渲染完成信号量
|
||||||
|
VkSubmitInfo submitInfo{};
|
||||||
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = &ctx.command.Ptr();
|
||||||
|
|
||||||
|
submitInfo.waitSemaphoreCount = 1;
|
||||||
|
submitInfo.pWaitSemaphores = waitSemaphores;
|
||||||
|
submitInfo.pWaitDstStageMask = waitStages;
|
||||||
|
|
||||||
|
submitInfo.signalSemaphoreCount = 1;
|
||||||
|
submitInfo.pSignalSemaphores = signalSemaphores;
|
||||||
|
vkQueueSubmit(Backend::RenderWorker->GetQueue().Ptr(), 1, &submitInfo, ctx.surfaceFence);
|
||||||
window.Present(ctx);
|
window.Present(ctx);
|
||||||
}
|
}
|
||||||
void VulkanAPI::ExecuteResourceBarriers(const ResourceBarrierDesc& desc) {
|
void VulkanAPI::ExecuteResourceBarriers(const ResourceBarrierDesc& desc) {
|
||||||
@ -86,12 +170,11 @@ namespace vkn {
|
|||||||
bufferBarriers.reserve(desc.bufferBarriersCount);
|
bufferBarriers.reserve(desc.bufferBarriersCount);
|
||||||
pmr::vector<VkImageMemoryBarrier> imageBarriers{ FramePool() };
|
pmr::vector<VkImageMemoryBarrier> imageBarriers{ FramePool() };
|
||||||
imageBarriers.reserve(desc.textureBarriersCount);
|
imageBarriers.reserve(desc.textureBarriersCount);
|
||||||
using api::ResourceState;
|
|
||||||
VkPipelineStageFlags srcStageMask = 0, dstStageMask = 0;
|
VkPipelineStageFlags srcStageMask = 0, dstStageMask = 0;
|
||||||
for (uint32_t i = 0; i < desc.textureBarriersCount; i++)
|
for (uint32_t i = 0; i < desc.textureBarriersCount; i++)
|
||||||
{
|
{
|
||||||
auto& barrier = desc.pTextureBarriers[i];
|
auto& barrier = desc.pTextureBarriers[i];
|
||||||
auto desc = GetVkTextureTransition(srcStageMask, dstStageMask, barrier);
|
auto desc = vkApiGetTextureTransition(srcStageMask, dstStageMask, barrier);
|
||||||
imageBarriers.push_back(desc);
|
imageBarriers.push_back(desc);
|
||||||
}
|
}
|
||||||
if (dstStageMask == 0) {
|
if (dstStageMask == 0) {
|
||||||
@ -102,23 +185,65 @@ namespace vkn {
|
|||||||
void VulkanAPI::BeginRenderPass(RenderPassNode* node)
|
void VulkanAPI::BeginRenderPass(RenderPassNode* node)
|
||||||
{
|
{
|
||||||
RenderPassKey config{};
|
RenderPassKey config{};
|
||||||
|
FramebufferKey frameKey{.layers = 1};
|
||||||
|
VkClearValue clearValues[2 * MAX_SUPPORTED_RENDER_TARGET_COUNT + 1] = { 0 };
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto& it : node->outEdges) {
|
for (auto& it : node->outEdges) {
|
||||||
if (it->IsAttachment()) {
|
if (it->IsAttachment()) {
|
||||||
auto& desc = it->CastTo<api::AttachmentDesc>();
|
auto& desc = it->CastTo<api::AttachmentDesc>();
|
||||||
|
|
||||||
config.colorFormat[i] = (VkFormat)TinyImageFormat_ToVkFormat(desc.colorFormat);
|
config.colorFormat[i] = (VkFormat)TinyImageFormat_ToVkFormat(desc.colorFormat);
|
||||||
config.samples = (VkSampleCountFlagBits)desc.sampleCount;
|
config.samples = vkApiGetSmpleCountFlag(desc.sampleCount);
|
||||||
|
|
||||||
TargetBufferFlags flag = TargetBufferFlags(int(TargetBufferFlags::COLOR0) << i);
|
TargetBufferFlags flag = TargetBufferFlags(int(TargetBufferFlags::COLOR0) << i);
|
||||||
config.clear |= flag;
|
config.clear |= flag;
|
||||||
|
it.ResolveView(&graph);
|
||||||
|
frameKey.imageViews[i] = (VkImageView)desc.imageView;
|
||||||
|
frameKey.height = desc.height;
|
||||||
|
frameKey.width = desc.width;
|
||||||
|
|
||||||
|
//clearValues[i] =
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node->pass = GetRenderPass(config);
|
frameKey.attachmentCount = i;
|
||||||
|
VkRenderPass pass = GetRenderPass(config);
|
||||||
|
frameKey.pass = pass;
|
||||||
|
auto it = FramebufferCache.find(frameKey);
|
||||||
|
VkFramebuffer framebuffer = it->second;
|
||||||
|
if (it == FramebufferCache.end()) {
|
||||||
|
VkFramebufferCreateInfo framebufferInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||||
|
.renderPass = pass,
|
||||||
|
.attachmentCount = frameKey.attachmentCount,
|
||||||
|
.pAttachments = frameKey.imageViews,
|
||||||
|
.width = frameKey.width,
|
||||||
|
.height = frameKey.height,
|
||||||
|
.layers = frameKey.layers
|
||||||
|
};
|
||||||
|
vkCreateFramebuffer(backend.GetDevice().Ptr(), &framebufferInfo, nullptr, &framebuffer);
|
||||||
|
FramebufferCache.emplace(frameKey, framebuffer);
|
||||||
|
}
|
||||||
|
VkRect2D renderAarea = {
|
||||||
|
.offset = {0,0},
|
||||||
|
.extent = {frameKey.width,frameKey.height}
|
||||||
|
};
|
||||||
|
VkRenderPassBeginInfo beginInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
|
.pNext = VK_NULL_HANDLE,
|
||||||
|
.renderPass = pass,
|
||||||
|
.framebuffer = framebuffer,
|
||||||
|
.renderArea = renderAarea,
|
||||||
|
.clearValueCount = frameKey.attachmentCount,
|
||||||
|
.pClearValues = clearValues
|
||||||
|
};
|
||||||
|
VulkanContext& ctx = *(VulkanContext*)&context;
|
||||||
|
vkCmdBeginRenderPass(ctx.command.Ptr(), &beginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
}
|
}
|
||||||
void VulkanAPI::EndRenderPass(RenderPassNode* node)
|
void VulkanAPI::EndRenderPass(RenderPassNode* node)
|
||||||
{
|
{
|
||||||
|
VulkanContext& ctx = *(VulkanContext*)&context;
|
||||||
|
vkCmdEndRenderPass(ctx.command.Ptr());
|
||||||
}
|
}
|
||||||
VkRenderPass VulkanAPI::GetRenderPass(RenderPassKey& config) {
|
VkRenderPass VulkanAPI::GetRenderPass(RenderPassKey& config) {
|
||||||
auto it = RenderPassCache.find(config);
|
auto it = RenderPassCache.find(config);
|
||||||
@ -221,6 +346,7 @@ namespace vkn {
|
|||||||
const TargetBufferFlags flag = TargetBufferFlags(int(TargetBufferFlags::COLOR0) << i);
|
const TargetBufferFlags flag = TargetBufferFlags(int(TargetBufferFlags::COLOR0) << i);
|
||||||
const bool clear = any(config.clear & flag);
|
const bool clear = any(config.clear & flag);
|
||||||
const bool discard = any(config.discardStart & flag);
|
const bool discard = any(config.discardStart & flag);
|
||||||
|
VkImageLayout layout = vkApiGetAttachmentLayout(config.colorFormat[i], true);
|
||||||
attachments[attachmentIndex++] = {
|
attachments[attachmentIndex++] = {
|
||||||
.format = config.colorFormat[i],
|
.format = config.colorFormat[i],
|
||||||
.samples = config.samples,
|
.samples = config.samples,
|
||||||
@ -228,9 +354,8 @@ namespace vkn {
|
|||||||
.storeOp = kEnableStore,
|
.storeOp = kEnableStore,
|
||||||
.stencilLoadOp = kDontCare,
|
.stencilLoadOp = kDontCare,
|
||||||
.stencilStoreOp = kDisableStore,
|
.stencilStoreOp = kDisableStore,
|
||||||
.initialLayout = ((!discard && config.initialColorLayoutMask & (1 << i)) || clear)
|
.initialLayout = layout,
|
||||||
? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED,
|
.finalLayout = layout,
|
||||||
.finalLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// Nulling out the zero-sized lists is necessary to avoid VK_ERROR_OUT_OF_HOST_MEMORY on Adreno.
|
// Nulling out the zero-sized lists is necessary to avoid VK_ERROR_OUT_OF_HOST_MEMORY on Adreno.
|
||||||
|
|||||||
@ -1,7 +1,32 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include "vkn/vulkan_api_help.h"
|
#include "vkn/vulkan_api_help.h"
|
||||||
|
#include "meta/enum.h"
|
||||||
namespace vkn {
|
namespace vkn {
|
||||||
VkImageLayout GetVkLayout(ResourceState layout) {
|
VkImageLayout vkApiGetAttachmentLayout(VkFormat format, bool includeStencilBit)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
// Depth
|
||||||
|
case VK_FORMAT_D16_UNORM:
|
||||||
|
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
||||||
|
case VK_FORMAT_D32_SFLOAT:
|
||||||
|
return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
|
||||||
|
// Stencil
|
||||||
|
case VK_FORMAT_S8_UINT:
|
||||||
|
return VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
// Depth/stencil
|
||||||
|
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||||
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||||
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||||
|
if (includeStencilBit)
|
||||||
|
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
|
return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
|
||||||
|
// Assume everything else is Color
|
||||||
|
default:
|
||||||
|
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VkImageLayout vkApiGetImageLayout(ResourceState layout) {
|
||||||
switch (layout) {
|
switch (layout) {
|
||||||
case ResourceState::UNDEFINED:
|
case ResourceState::UNDEFINED:
|
||||||
return VK_IMAGE_LAYOUT_UNDEFINED;
|
return VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
@ -19,31 +44,22 @@ namespace vkn {
|
|||||||
return VK_IMAGE_LAYOUT_GENERAL;
|
return VK_IMAGE_LAYOUT_GENERAL;
|
||||||
case ResourceState::PRESENT:
|
case ResourceState::PRESENT:
|
||||||
return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||||
// Filament sometimes samples from one miplevel while writing to another level in the
|
|
||||||
// same texture (e.g. bloom does this). Moreover we'd like to avoid lots of expensive
|
|
||||||
// layout transitions. So, keep it simple and use GENERAL for all color-attachable
|
|
||||||
// textures.
|
|
||||||
case ResourceState::COLOR_ATTACHMENT:
|
case ResourceState::COLOR_ATTACHMENT:
|
||||||
return VK_IMAGE_LAYOUT_GENERAL;
|
|
||||||
case ResourceState::COLOR_ATTACHMENT_RESOLVE:
|
|
||||||
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VkImageMemoryBarrier GetVkTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags mDstStage, const TextureBarrier& barrier) {
|
VkImageMemoryBarrier vkApiGetTextureTransition(VkPipelineStageFlags& mSrcStage, VkPipelineStageFlags& mDstStage, const TextureBarrier& barrier) {
|
||||||
VkAccessFlags srcAccessMask, dstAccessMask;
|
VkAccessFlags srcAccessMask, dstAccessMask;
|
||||||
VkPipelineStageFlags srcStage, dstStage;
|
VkPipelineStageFlags srcStage, dstStage;
|
||||||
|
|
||||||
switch (barrier.mSrcState) {
|
switch (barrier.mSrcState) {
|
||||||
case ResourceState::UNDEFINED:
|
case ResourceState::UNDEFINED:
|
||||||
srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
srcAccessMask = 0;
|
||||||
srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
|
srcStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
break;
|
break;
|
||||||
case ResourceState::COLOR_ATTACHMENT:
|
case ResourceState::COLOR_ATTACHMENT:
|
||||||
srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
|
srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
|
srcStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
||||||
srcStage = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
|
||||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
break;
|
break;
|
||||||
case ResourceState::READ_WRITE:
|
case ResourceState::READ_WRITE:
|
||||||
srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
@ -69,23 +85,16 @@ namespace vkn {
|
|||||||
srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||||
srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
srcStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
break;
|
break;
|
||||||
case ResourceState::COLOR_ATTACHMENT_RESOLVE:
|
|
||||||
srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
|
||||||
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
|
||||||
break;
|
|
||||||
case ResourceState::PRESENT:
|
case ResourceState::PRESENT:
|
||||||
srcAccessMask = VK_ACCESS_NONE;
|
srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||||
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
srcStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (barrier.mDstState) {
|
switch (barrier.mDstState) {
|
||||||
case ResourceState::COLOR_ATTACHMENT:
|
case ResourceState::COLOR_ATTACHMENT:
|
||||||
dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT
|
dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||||
| VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
|
dstStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
|
||||||
dstStage = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
|
|
||||||
| VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
break;
|
break;
|
||||||
case ResourceState::READ_WRITE:
|
case ResourceState::READ_WRITE:
|
||||||
dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
@ -115,10 +124,9 @@ namespace vkn {
|
|||||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
|
||||||
break;
|
break;
|
||||||
case ResourceState::PRESENT:
|
case ResourceState::PRESENT:
|
||||||
case ResourceState::COLOR_ATTACHMENT_RESOLVE:
|
|
||||||
case ResourceState::UNDEFINED:
|
case ResourceState::UNDEFINED:
|
||||||
dstAccessMask = 0;
|
dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
|
||||||
dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
dstStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mSrcStage |= srcStage;
|
mSrcStage |= srcStage;
|
||||||
@ -134,12 +142,95 @@ namespace vkn {
|
|||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||||
.srcAccessMask = srcAccessMask,
|
.srcAccessMask = srcAccessMask,
|
||||||
.dstAccessMask = dstAccessMask,
|
.dstAccessMask = dstAccessMask,
|
||||||
.oldLayout = GetVkLayout(barrier.mSrcState),
|
.oldLayout = vkApiGetImageLayout(barrier.mSrcState),
|
||||||
.newLayout = GetVkLayout(barrier.mDstState),
|
.newLayout = vkApiGetImageLayout(barrier.mDstState),
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.image = (VkImage)barrier.mTexture.image,
|
.image = (VkImage)barrier.mTexture.image,
|
||||||
.subresourceRange = subresources
|
.subresourceRange = subresources
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
VkImageAspectFlags vkApiGetImageAspectMask(VkFormat format, bool includeStencilBit)
|
||||||
|
{
|
||||||
|
VkImageAspectFlags result = 0;
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
// Depth
|
||||||
|
case VK_FORMAT_D16_UNORM:
|
||||||
|
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
||||||
|
case VK_FORMAT_D32_SFLOAT:
|
||||||
|
result = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
break;
|
||||||
|
// Stencil
|
||||||
|
case VK_FORMAT_S8_UINT:
|
||||||
|
result = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
break;
|
||||||
|
// Depth/stencil
|
||||||
|
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||||
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||||
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||||
|
result = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
if (includeStencilBit)
|
||||||
|
result |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
break;
|
||||||
|
// Assume everything else is Color
|
||||||
|
default:
|
||||||
|
result = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
VkImageUsageFlags vkApiGetImageUsageFlags(ResourceState startState)
|
||||||
|
{
|
||||||
|
VkImageUsageFlags usageFlags = 0;
|
||||||
|
if (any(startState & ResourceState::COLOR_ATTACHMENT))
|
||||||
|
usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
else if (any(startState & ResourceState::DEPTH_ATTACHMENT))
|
||||||
|
usageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
|
return usageFlags;
|
||||||
|
}
|
||||||
|
VkImageViewType vkApiGetImageViewType(TextureDimension dimension, uint32_t arraySize)
|
||||||
|
{
|
||||||
|
if (any(dimension & TextureDimension::TEX_1D)) {
|
||||||
|
return arraySize > 1 ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_1D;
|
||||||
|
}
|
||||||
|
if (any(dimension & TextureDimension::TEX_CUBE)) {
|
||||||
|
return arraySize > 1 ? VK_IMAGE_VIEW_TYPE_CUBE_ARRAY : VK_IMAGE_VIEW_TYPE_CUBE;
|
||||||
|
}
|
||||||
|
if (any(dimension & TextureDimension::TEX_2D)) {
|
||||||
|
return arraySize > 1 ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
}
|
||||||
|
if (any(dimension & TextureDimension::TEX_3D)) {
|
||||||
|
return VK_IMAGE_VIEW_TYPE_3D;
|
||||||
|
}
|
||||||
|
return VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
||||||
|
}
|
||||||
|
VkImageType vkApiGetImageType(TextureDimension dimension)
|
||||||
|
{
|
||||||
|
if (any(dimension & TextureDimension::TEX_1D)) {
|
||||||
|
return VK_IMAGE_TYPE_1D;
|
||||||
|
}
|
||||||
|
if (any(dimension & TextureDimension::TEX_2D)) {
|
||||||
|
return VK_IMAGE_TYPE_2D;
|
||||||
|
}
|
||||||
|
if (any(dimension & TextureDimension::TEX_3D)) {
|
||||||
|
return VK_IMAGE_TYPE_3D;
|
||||||
|
}
|
||||||
|
return VK_IMAGE_TYPE_MAX_ENUM;
|
||||||
|
}
|
||||||
|
VkImageCreateFlags vkApiGetImageCreateFlag(TextureDimension dimension, uint32_t arraySize)
|
||||||
|
{
|
||||||
|
VkImageCreateFlags flag{};
|
||||||
|
if (any(dimension & TextureDimension::TEX_CUBE)) {
|
||||||
|
flag |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
||||||
|
}
|
||||||
|
if (arraySize > 0) {
|
||||||
|
flag |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR;
|
||||||
|
}
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
VkSampleCountFlagBits vkApiGetSmpleCountFlag(SampleCount sample)
|
||||||
|
{
|
||||||
|
return (VkSampleCountFlagBits)sample;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -8,6 +8,7 @@
|
|||||||
#include "asset/resource_system.h"
|
#include "asset/resource_system.h"
|
||||||
#include "zlog.h"
|
#include "zlog.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <tinyimageformat/tinyimageformat_apis.h>
|
||||||
namespace vkn {
|
namespace vkn {
|
||||||
bool VulkanWindow::CreateRender(CreatePFN createPFN, VulkanWindowArgs& args)
|
bool VulkanWindow::CreateRender(CreatePFN createPFN, VulkanWindowArgs& args)
|
||||||
{
|
{
|
||||||
@ -21,6 +22,7 @@ namespace vkn {
|
|||||||
args.width = mWidth;
|
args.width = mWidth;
|
||||||
args.height = mHeight;
|
args.height = mHeight;
|
||||||
mSwapchain = new (GlobalPool()) VulkanSwapchain(backend.GetDevice(), surface, args);
|
mSwapchain = new (GlobalPool()) VulkanSwapchain(backend.GetDevice(), surface, args);
|
||||||
|
api->graph.mSurface = mSwapchain->mSurfaces[0];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
VulkanSwapchain::VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args)
|
VulkanSwapchain::VulkanSwapchain(Device& device, VkSurfaceKHR surface, VulkanWindowArgs& args)
|
||||||
@ -63,8 +65,16 @@ namespace vkn {
|
|||||||
mSurfaces.reserve(mFrames);
|
mSurfaces.reserve(mFrames);
|
||||||
mCommands.reserve(mFrames);
|
mCommands.reserve(mFrames);
|
||||||
mSemaphores.reserve(mFrames + mFrames);
|
mSemaphores.reserve(mFrames + mFrames);
|
||||||
|
TextureDesc desc{};
|
||||||
|
desc.width = args.width;
|
||||||
|
desc.height = args.height;
|
||||||
|
desc.format = TinyImageFormat_FromVkFormat((TinyImageFormat_VkFormat)args.imageFormat);
|
||||||
|
desc.state = ResourceState::PRESENT;
|
||||||
|
desc.sampleCount = SampleCount::SAMPLE_COUNT_1;
|
||||||
|
desc.arraySize = 1;
|
||||||
|
desc.mipLevel = 1;
|
||||||
|
desc.depth = 1;
|
||||||
for (int i = 0; i < mFrames; i++) {
|
for (int i = 0; i < mFrames; i++) {
|
||||||
api::TextureDesc desc;
|
|
||||||
desc.image = swapchain_images[i];
|
desc.image = swapchain_images[i];
|
||||||
mSurfaces.push_back(desc);
|
mSurfaces.push_back(desc);
|
||||||
mSemaphores.push_back(mDevice.CreateSemaphore());
|
mSemaphores.push_back(mDevice.CreateSemaphore());
|
||||||
@ -91,7 +101,7 @@ namespace vkn {
|
|||||||
{
|
{
|
||||||
VkPresentInfoKHR presentInfo = {};
|
VkPresentInfoKHR presentInfo = {};
|
||||||
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
presentInfo.pWaitSemaphores = &ctx.surfaceSemaphore;
|
presentInfo.pWaitSemaphores = &ctx.presentSemaphore;
|
||||||
presentInfo.waitSemaphoreCount = 1;
|
presentInfo.waitSemaphoreCount = 1;
|
||||||
presentInfo.pSwapchains = &mPtr;
|
presentInfo.pSwapchains = &mPtr;
|
||||||
presentInfo.swapchainCount = 1;
|
presentInfo.swapchainCount = 1;
|
||||||
|
|||||||
@ -5,14 +5,6 @@
|
|||||||
#include "render/pass/demo_pass.h"
|
#include "render/pass/demo_pass.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using namespace api;
|
using namespace api;
|
||||||
FrameGraphNodePtr FrameGraph::AddRenderPass(const RenderPassSetupFunction& setup, const RenderPassNodeExecuteFn& executor)
|
|
||||||
{
|
|
||||||
FrameGraphNodePtr node_ptr{ mGraph.addNode(), executor };
|
|
||||||
RenderPassBuilder builder{ this, node_ptr };
|
|
||||||
setup(*this, builder);
|
|
||||||
mNodes.push_back(node_ptr);
|
|
||||||
return node_ptr;
|
|
||||||
}
|
|
||||||
RenderAPI* API;
|
RenderAPI* API;
|
||||||
void ZWorldModule::OnLoad(int argc, char** argv)
|
void ZWorldModule::OnLoad(int argc, char** argv)
|
||||||
{
|
{
|
||||||
@ -24,6 +16,7 @@ void ZWorldModule::OnLoad(int argc, char** argv)
|
|||||||
if (!window->CreateRender(&SDL_Vulkan_CreateSurface, args)) {
|
if (!window->CreateRender(&SDL_Vulkan_CreateSurface, args)) {
|
||||||
zlog::errorf("SDL_Vulkan_CreateSurface failed {}", SDL_GetError());
|
zlog::errorf("SDL_Vulkan_CreateSurface failed {}", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
API->Init();
|
||||||
API->context.views.push_back({});
|
API->context.views.push_back({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user