Redo of render paths
This commit is contained in:
@@ -1,7 +1,5 @@
|
||||
target_sources(SeeleEngine
|
||||
PRIVATE
|
||||
ForwardPlusRenderPath.h
|
||||
ForwardPlusRenderPath.cpp
|
||||
GraphicsResources.h
|
||||
GraphicsResources.cpp
|
||||
GraphicsInitializer.h
|
||||
@@ -10,6 +8,7 @@ target_sources(SeeleEngine
|
||||
Graphics.cpp
|
||||
Mesh.h
|
||||
Mesh.cpp
|
||||
MeshBatch.h
|
||||
RenderCore.h
|
||||
RenderCore.cpp
|
||||
RenderPath.h
|
||||
@@ -25,4 +24,5 @@ target_sources(SeeleEngine
|
||||
WindowManager.h
|
||||
WindowManager.cpp)
|
||||
|
||||
add_subdirectory(RenderPass/)
|
||||
add_subdirectory(Vulkan/)
|
||||
@@ -1,43 +0,0 @@
|
||||
#include "ForwardPlusRenderPath.h"
|
||||
#include "Scene/Scene.h"
|
||||
#include "Material/MaterialInstance.h"
|
||||
#include "Material/Material.h"
|
||||
#include "GraphicsResources.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Seele::ForwardPlusRenderPath::ForwardPlusRenderPath(Gfx::PGraphics graphics, Gfx::PViewport viewport)
|
||||
: SceneRenderPath(graphics, viewport)
|
||||
{
|
||||
PMaterial material = new Material("D:\\Private\\Programming\\C++\\Seele\\test.mat");
|
||||
material->compile();
|
||||
}
|
||||
|
||||
Seele::ForwardPlusRenderPath::~ForwardPlusRenderPath()
|
||||
{
|
||||
}
|
||||
|
||||
void Seele::ForwardPlusRenderPath::beginFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void Seele::ForwardPlusRenderPath::render()
|
||||
{
|
||||
for (auto entry : scene->getMeshBatches())
|
||||
{
|
||||
PMaterial material = entry.key;
|
||||
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
|
||||
renderCommand->bindPipeline(material->getPipeline());
|
||||
for (auto drawState : entry.value.instances)
|
||||
{
|
||||
renderCommand->bindVertexBuffer(drawState.vertexBuffer);
|
||||
renderCommand->bindIndexBuffer(drawState.indexBuffer);
|
||||
renderCommand->bindDescriptor(drawState.instance->getDescriptor());
|
||||
renderCommand->draw(drawState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Seele::ForwardPlusRenderPath::endFrame()
|
||||
{
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include "SceneRenderPath.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
class ForwardPlusRenderPath : public SceneRenderPath
|
||||
{
|
||||
public:
|
||||
ForwardPlusRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target);
|
||||
virtual ~ForwardPlusRenderPath();
|
||||
virtual void beginFrame() override;
|
||||
virtual void render() override;
|
||||
virtual void endFrame() override;
|
||||
|
||||
private:
|
||||
};
|
||||
} // namespace Seele
|
||||
@@ -13,6 +13,12 @@ public:
|
||||
Graphics();
|
||||
virtual ~Graphics();
|
||||
virtual void init(GraphicsInitializer initializer) = 0;
|
||||
|
||||
const QueueFamilyMapping getFamilyMapping() const
|
||||
{
|
||||
return queueMapping;
|
||||
}
|
||||
|
||||
virtual PWindow createWindow(const WindowCreateInfo &createInfo) = 0;
|
||||
virtual PViewport createViewport(PWindow owner, const ViewportCreateInfo &createInfo) = 0;
|
||||
|
||||
@@ -28,8 +34,18 @@ public:
|
||||
virtual PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) = 0;
|
||||
virtual PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) = 0;
|
||||
virtual PRenderCommand createRenderCommand() = 0;
|
||||
virtual PVertexShader createVertexShader(const ShaderCreateInfo& createInfo) = 0;
|
||||
virtual PControlShader createControlShader(const ShaderCreateInfo& createInfo) = 0;
|
||||
virtual PEvaluationShader createEvaluationShader(const ShaderCreateInfo& createInfo) = 0;
|
||||
virtual PGeometryShader createGeometryShader(const ShaderCreateInfo& createInfo) = 0;
|
||||
virtual PFragmentShader createFragmentShader(const ShaderCreateInfo& createInfo) = 0;
|
||||
virtual PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) = 0;
|
||||
|
||||
virtual Gfx::PDescriptorLayout createDescriptorLayout() = 0;
|
||||
virtual Gfx::PPipelineLayout createPipelineLayout() = 0;
|
||||
|
||||
protected:
|
||||
QueueFamilyMapping queueMapping;
|
||||
friend class Window;
|
||||
};
|
||||
DEFINE_REF(Graphics);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#pragma once
|
||||
#include "GraphicsEnums.h"
|
||||
|
||||
namespace Seele
|
||||
@@ -42,8 +43,20 @@ struct ViewportCreateInfo
|
||||
uint32 offsetX;
|
||||
uint32 offsetY;
|
||||
};
|
||||
// doesnt own the data, only proxy it
|
||||
struct BulkResourceData
|
||||
{
|
||||
uint32 size;
|
||||
uint8 *data;
|
||||
Gfx::QueueType owner;
|
||||
BulkResourceData()
|
||||
: size(0), data(nullptr), owner(Gfx::QueueType::GRAPHICS)
|
||||
{
|
||||
}
|
||||
};
|
||||
struct TextureCreateInfo
|
||||
{
|
||||
BulkResourceData resourceData;
|
||||
uint32 width;
|
||||
uint32 height;
|
||||
uint32 depth;
|
||||
@@ -53,20 +66,10 @@ struct TextureCreateInfo
|
||||
uint32 samples;
|
||||
Gfx::SeFormat format;
|
||||
Gfx::SeImageUsageFlagBits usage;
|
||||
Gfx::QueueType queueType;
|
||||
TextureCreateInfo()
|
||||
: width(1), height(1), depth(1), bArray(false), arrayLayers(1), mipLevels(1), samples(1), format(Gfx::SE_FORMAT_R32G32B32A32_SFLOAT), queueType(Gfx::QueueType::GRAPHICS), usage(Gfx::SE_IMAGE_USAGE_SAMPLED_BIT)
|
||||
{
|
||||
}
|
||||
};
|
||||
// doesnt own the data, only proxy it
|
||||
struct BulkResourceData
|
||||
{
|
||||
uint32 size;
|
||||
uint8 *data;
|
||||
Gfx::QueueType owner;
|
||||
BulkResourceData()
|
||||
: size(0), data(nullptr), owner(Gfx::QueueType::GRAPHICS)
|
||||
: resourceData(), width(1), height(1), depth(1), bArray(false), arrayLayers(1)
|
||||
, mipLevels(1), samples(1), format(Gfx::SE_FORMAT_R32G32B32A32_SFLOAT)
|
||||
, usage(Gfx::SE_IMAGE_USAGE_SAMPLED_BIT)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -90,6 +93,15 @@ struct IndexBufferCreateInfo
|
||||
{
|
||||
}
|
||||
};
|
||||
struct ShaderCreateInfo
|
||||
{
|
||||
std::string code;
|
||||
std::string entryPoint;
|
||||
Array<const char*> typeParameter;
|
||||
ShaderCreateInfo(const std::string& code)
|
||||
: code(code)
|
||||
{}
|
||||
};
|
||||
|
||||
namespace Gfx
|
||||
{
|
||||
@@ -101,6 +113,10 @@ struct SePushConstantRange
|
||||
};
|
||||
struct VertexElement
|
||||
{
|
||||
VertexElement(){}
|
||||
VertexElement(uint32 location, SeFormat vertexFormat, uint32 offset)
|
||||
: location(location), vertexFormat(vertexFormat), offset(offset)
|
||||
{}
|
||||
uint32 location;
|
||||
SeFormat vertexFormat;
|
||||
uint32 offset;
|
||||
@@ -173,7 +189,6 @@ struct GraphicsPipelineCreateInfo
|
||||
Gfx::PEvaluationShader evalShader;
|
||||
Gfx::PGeometryShader geometryShader;
|
||||
Gfx::PFragmentShader fragmentShader;
|
||||
Gfx::PPipelineLayout pipelineLayout;
|
||||
Gfx::PRenderPass renderPass;
|
||||
Gfx::SePrimitiveTopology topology;
|
||||
Gfx::RasterizationState rasterizationState;
|
||||
@@ -183,6 +198,23 @@ struct GraphicsPipelineCreateInfo
|
||||
GraphicsPipelineCreateInfo()
|
||||
{
|
||||
std::memset(this, 0, sizeof(*this));
|
||||
topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
rasterizationState.cullMode = Gfx::SE_CULL_MODE_BACK_BIT;
|
||||
rasterizationState.polygonMode = Gfx::SE_POLYGON_MODE_FILL;
|
||||
rasterizationState.frontFace = Gfx::SE_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||
depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_LESS;
|
||||
depthStencilState.minDepthBounds = 0.0f;
|
||||
depthStencilState.maxDepthBounds = 1.0f;
|
||||
depthStencilState.stencilTestEnable = false;
|
||||
depthStencilState.depthWriteEnable = true;
|
||||
depthStencilState.depthTestEnable = true;
|
||||
multisampleState.samples = 1;
|
||||
colorBlend.attachmentCount = 0;
|
||||
colorBlend.logicOpEnable = false;
|
||||
colorBlend.blendConstants[0] = 1.0f;
|
||||
colorBlend.blendConstants[1] = 1.0f;
|
||||
colorBlend.blendConstants[2] = 1.0f;
|
||||
colorBlend.blendConstants[3] = 1.0f;
|
||||
}
|
||||
};
|
||||
} // namespace Seele
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "GraphicsResources.h"
|
||||
#include "Material/MaterialInstance.h"
|
||||
#include "Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Gfx;
|
||||
@@ -56,22 +57,60 @@ void PipelineLayout::addPushConstants(const SePushConstantRange &pushConstant)
|
||||
pushConstants.add(pushConstant);
|
||||
}
|
||||
|
||||
UniformBuffer::UniformBuffer()
|
||||
QueueOwnedResource::QueueOwnedResource(PGraphics graphics, QueueType startQueueType)
|
||||
: graphics(graphics)
|
||||
, currentOwner(startQueueType)
|
||||
{
|
||||
}
|
||||
|
||||
QueueOwnedResource::~QueueOwnedResource()
|
||||
{
|
||||
}
|
||||
|
||||
void QueueOwnedResource::transferOwnership(QueueType newOwner)
|
||||
{
|
||||
if(graphics->getFamilyMapping().needsTransfer(currentOwner, newOwner))
|
||||
{
|
||||
executeOwnershipBarrier(newOwner);
|
||||
currentOwner = newOwner;
|
||||
}
|
||||
}
|
||||
|
||||
Buffer::Buffer(PGraphics graphics, QueueType startQueue)
|
||||
: QueueOwnedResource(graphics, startQueue)
|
||||
{
|
||||
}
|
||||
|
||||
Buffer::~Buffer()
|
||||
{
|
||||
}
|
||||
|
||||
UniformBuffer::UniformBuffer(PGraphics graphics, QueueType startQueueType)
|
||||
: Buffer(graphics, startQueueType)
|
||||
{
|
||||
}
|
||||
|
||||
UniformBuffer::~UniformBuffer()
|
||||
{
|
||||
}
|
||||
VertexBuffer::VertexBuffer(uint32 numVertices, uint32 vertexSize)
|
||||
: numVertices(numVertices), vertexSize(vertexSize)
|
||||
StructuredBuffer::StructuredBuffer(PGraphics graphics, QueueType startQueueType)
|
||||
: Buffer(graphics, startQueueType)
|
||||
{
|
||||
}
|
||||
StructuredBuffer::~StructuredBuffer()
|
||||
{
|
||||
}
|
||||
VertexBuffer::VertexBuffer(PGraphics graphics, uint32 numVertices, uint32 vertexSize, QueueType startQueueType)
|
||||
: Buffer(graphics, startQueueType)
|
||||
, numVertices(numVertices), vertexSize(vertexSize)
|
||||
{
|
||||
}
|
||||
VertexBuffer::~VertexBuffer()
|
||||
{
|
||||
}
|
||||
IndexBuffer::IndexBuffer(uint32 size, Gfx::SeIndexType indexType)
|
||||
: indexType(indexType)
|
||||
IndexBuffer::IndexBuffer(PGraphics graphics, uint32 size, Gfx::SeIndexType indexType, QueueType startQueueType)
|
||||
: Buffer(graphics, startQueueType)
|
||||
, indexType(indexType)
|
||||
{
|
||||
switch (indexType)
|
||||
{
|
||||
@@ -87,9 +126,8 @@ IndexBuffer::IndexBuffer(uint32 size, Gfx::SeIndexType indexType)
|
||||
IndexBuffer::~IndexBuffer()
|
||||
{
|
||||
}
|
||||
VertexStream::VertexStream(PVertexBuffer buffer, uint8 instanced)
|
||||
: buffer(buffer)
|
||||
, instanced(instanced)
|
||||
VertexStream::VertexStream(uint32 stride, uint8 instanced)
|
||||
: stride(stride), instanced(instanced)
|
||||
{
|
||||
}
|
||||
VertexStream::~VertexStream()
|
||||
@@ -103,11 +141,6 @@ const Array<VertexElement> VertexStream::getVertexDescriptions() const
|
||||
{
|
||||
return vertexDescription;
|
||||
}
|
||||
Gfx::PVertexBuffer VertexStream::getVertexBuffer()
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
VertexDeclaration::VertexDeclaration()
|
||||
{
|
||||
}
|
||||
@@ -125,6 +158,32 @@ const Array<VertexStream> &VertexDeclaration::getVertexStreams() const
|
||||
return vertexStreams;
|
||||
}
|
||||
|
||||
Texture::Texture(PGraphics graphics, Gfx::QueueType startQueueType)
|
||||
: QueueOwnedResource(graphics, startQueueType)
|
||||
{
|
||||
}
|
||||
|
||||
Texture::~Texture()
|
||||
{
|
||||
}
|
||||
|
||||
Texture2D::Texture2D(PGraphics graphics, Gfx::QueueType startQueueType)
|
||||
: Texture(graphics, startQueueType)
|
||||
{
|
||||
}
|
||||
|
||||
Texture2D::~Texture2D()
|
||||
{
|
||||
}
|
||||
|
||||
RenderCommand::RenderCommand()
|
||||
{
|
||||
}
|
||||
|
||||
RenderCommand::~RenderCommand()
|
||||
{
|
||||
}
|
||||
|
||||
RenderTargetLayout::RenderTargetLayout()
|
||||
: inputAttachments(), colorAttachments(), depthAttachment()
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Math/MemCRC.h"
|
||||
#include "Material/MaterialInstance.h"
|
||||
#include "GraphicsInitializer.h"
|
||||
#include "MeshBatch.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define ENABLE_VALIDATION
|
||||
@@ -13,34 +14,10 @@
|
||||
namespace Seele
|
||||
{
|
||||
|
||||
DECLARE_NAME_REF(Gfx, VertexBuffer);
|
||||
DECLARE_NAME_REF(Gfx, IndexBuffer);
|
||||
struct DrawInstance
|
||||
{
|
||||
Matrix4 modelMatrix;
|
||||
PMaterialInstance instance;
|
||||
Gfx::PIndexBuffer indexBuffer;
|
||||
Gfx::PVertexBuffer vertexBuffer;
|
||||
|
||||
uint32 numInstances;
|
||||
uint32 baseVertexIndex;
|
||||
uint32 minVertexIndex;
|
||||
uint32 firstInstance;
|
||||
DrawInstance()
|
||||
: instance(nullptr), indexBuffer(nullptr), vertexBuffer(nullptr), modelMatrix(1), numInstances(1), baseVertexIndex(0), minVertexIndex(0), firstInstance(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
struct DrawState
|
||||
{
|
||||
Array<DrawInstance> instances;
|
||||
|
||||
DrawState()
|
||||
{
|
||||
}
|
||||
};
|
||||
namespace Gfx
|
||||
{
|
||||
DECLARE_REF(Graphics);
|
||||
|
||||
class SamplerState
|
||||
{
|
||||
public:
|
||||
@@ -182,6 +159,7 @@ public:
|
||||
PipelineLayout() {}
|
||||
virtual ~PipelineLayout() {}
|
||||
virtual void create() = 0;
|
||||
virtual void reset() = 0;
|
||||
void addDescriptorLayout(uint32 setIndex, PDescriptorLayout layout);
|
||||
void addPushConstants(const SePushConstantRange &pushConstants);
|
||||
virtual uint32 getHash() const = 0;
|
||||
@@ -191,17 +169,79 @@ protected:
|
||||
Array<SePushConstantRange> pushConstants;
|
||||
};
|
||||
DEFINE_REF(PipelineLayout);
|
||||
class UniformBuffer
|
||||
|
||||
struct QueueFamilyMapping
|
||||
{
|
||||
uint32 graphicsFamily;
|
||||
uint32 computeFamily;
|
||||
uint32 transferFamily;
|
||||
uint32 dedicatedTransferFamily;
|
||||
uint32 getQueueTypeFamilyIndex(Gfx::QueueType type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Gfx::QueueType::GRAPHICS:
|
||||
return graphicsFamily;
|
||||
case Gfx::QueueType::COMPUTE:
|
||||
return computeFamily;
|
||||
case Gfx::QueueType::TRANSFER:
|
||||
return transferFamily;
|
||||
case Gfx::QueueType::DEDICATED_TRANSFER:
|
||||
return dedicatedTransferFamily;
|
||||
default:
|
||||
return 0x7fff;
|
||||
}
|
||||
}
|
||||
bool needsTransfer(Gfx::QueueType src, Gfx::QueueType dst) const
|
||||
{
|
||||
uint32 srcIndex = getQueueTypeFamilyIndex(src);
|
||||
uint32 dstIndex = getQueueTypeFamilyIndex(dst);
|
||||
return srcIndex != dstIndex;
|
||||
}
|
||||
};
|
||||
|
||||
class QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
UniformBuffer();
|
||||
QueueOwnedResource(PGraphics graphics, QueueType startQueueType);
|
||||
virtual ~QueueOwnedResource();
|
||||
|
||||
//Preliminary checks to see if the barrier should be executed at all
|
||||
void transferOwnership(QueueType newOwner);
|
||||
|
||||
protected:
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
Gfx::QueueType currentOwner;
|
||||
PGraphics graphics;
|
||||
};
|
||||
DEFINE_REF(QueueOwnedResource);
|
||||
|
||||
class Buffer : public QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
Buffer(PGraphics graphics, QueueType startQueueType);
|
||||
virtual ~Buffer();
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
};
|
||||
|
||||
class UniformBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
UniformBuffer(PGraphics graphics, QueueType startQueueType);
|
||||
virtual ~UniformBuffer();
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
};
|
||||
DEFINE_REF(UniformBuffer);
|
||||
class VertexBuffer
|
||||
|
||||
class VertexBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
VertexBuffer(uint32 numVertices, uint32 vertexSize);
|
||||
VertexBuffer(PGraphics graphics, uint32 numVertices, uint32 vertexSize, QueueType startQueueType);
|
||||
virtual ~VertexBuffer();
|
||||
inline uint32 getNumVertices()
|
||||
{
|
||||
@@ -214,14 +254,17 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
uint32 numVertices;
|
||||
uint32 vertexSize;
|
||||
};
|
||||
DEFINE_REF(VertexBuffer);
|
||||
class IndexBuffer
|
||||
|
||||
class IndexBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
IndexBuffer(uint32 size, Gfx::SeIndexType index);
|
||||
IndexBuffer(PGraphics graphics, uint32 size, Gfx::SeIndexType index, QueueType startQueueType);
|
||||
virtual ~IndexBuffer();
|
||||
inline uint32 getNumIndices() const
|
||||
{
|
||||
@@ -233,34 +276,41 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
Gfx::SeIndexType indexType;
|
||||
uint32 numIndices;
|
||||
};
|
||||
DEFINE_REF(IndexBuffer);
|
||||
class StructuredBuffer
|
||||
|
||||
class StructuredBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
virtual ~StructuredBuffer()
|
||||
{
|
||||
}
|
||||
StructuredBuffer(PGraphics graphics, QueueType startQueueType);
|
||||
virtual ~StructuredBuffer();
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
};
|
||||
DEFINE_REF(StructuredBuffer);
|
||||
|
||||
class VertexStream
|
||||
{
|
||||
public:
|
||||
VertexStream() {}
|
||||
VertexStream(PVertexBuffer buffer, uint8 instanced);
|
||||
VertexStream(uint32 stride, uint8 instanced);
|
||||
~VertexStream();
|
||||
void addVertexElement(VertexElement element);
|
||||
const Array<VertexElement> getVertexDescriptions() const;
|
||||
PVertexBuffer getVertexBuffer();
|
||||
inline uint8 isInstanced() const { return instanced; }
|
||||
|
||||
private:
|
||||
PVertexBuffer buffer;
|
||||
uint32 stride;
|
||||
uint32 offset;
|
||||
Array<VertexElement> vertexDescription;
|
||||
uint8 instanced;
|
||||
PVertexBuffer vertexBuffer;
|
||||
};
|
||||
DEFINE_REF(VertexStream);
|
||||
class VertexDeclaration
|
||||
{
|
||||
public:
|
||||
@@ -276,41 +326,46 @@ DEFINE_REF(VertexDeclaration);
|
||||
class GraphicsPipeline
|
||||
{
|
||||
public:
|
||||
GraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) : createInfo(createInfo) {}
|
||||
GraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo, PPipelineLayout layout) : createInfo(createInfo) , layout(layout) {}
|
||||
virtual ~GraphicsPipeline(){}
|
||||
const GraphicsPipelineCreateInfo& getCreateInfo() const {return createInfo;}
|
||||
PPipelineLayout getPipelineLayout() const { return layout; }
|
||||
protected:
|
||||
PPipelineLayout layout;
|
||||
GraphicsPipelineCreateInfo createInfo;
|
||||
};
|
||||
DEFINE_REF(GraphicsPipeline);
|
||||
class Texture
|
||||
class Texture : public QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
virtual ~Texture()
|
||||
{
|
||||
}
|
||||
Texture(PGraphics graphics, QueueType startQueueType);
|
||||
virtual ~Texture();
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
};
|
||||
DEFINE_REF(Texture);
|
||||
class Texture2D : public Texture
|
||||
{
|
||||
public:
|
||||
virtual ~Texture2D()
|
||||
{
|
||||
}
|
||||
Texture2D(PGraphics graphics, QueueType startQueueType);
|
||||
virtual ~Texture2D();
|
||||
protected:
|
||||
//Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
};
|
||||
DEFINE_REF(Texture2D);
|
||||
|
||||
class RenderCommand
|
||||
{
|
||||
public:
|
||||
virtual ~RenderCommand()
|
||||
{
|
||||
}
|
||||
RenderCommand();
|
||||
virtual ~RenderCommand();
|
||||
virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) = 0;
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0;
|
||||
virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) = 0;
|
||||
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) = 0;
|
||||
virtual void draw(DrawInstance data) = 0;
|
||||
virtual void draw(const MeshBatchElement& data) = 0;
|
||||
};
|
||||
DEFINE_REF(RenderCommand);
|
||||
|
||||
|
||||
@@ -1 +1,13 @@
|
||||
#include "Mesh.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Mesh::Mesh(Gfx::PVertexBuffer vertexBuffer, Gfx::PIndexBuffer indexBuffer)
|
||||
: vertexBuffer(vertexBuffer)
|
||||
, indexBuffer(indexBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
Mesh::~Mesh()
|
||||
{
|
||||
}
|
||||
@@ -10,7 +10,8 @@ public:
|
||||
~Mesh();
|
||||
|
||||
private:
|
||||
Gfx::VertexBuffer vertexBuffer;
|
||||
Gfx::IndexBuffer indexBuffer;
|
||||
Gfx::PVertexBuffer vertexBuffer;
|
||||
Gfx::PIndexBuffer indexBuffer;
|
||||
};
|
||||
DEFINE_REF(Mesh);
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,97 @@
|
||||
#pragma once
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_NAME_REF(Gfx, VertexBuffer);
|
||||
DECLARE_NAME_REF(Gfx, IndexBuffer);
|
||||
DECLARE_NAME_REF(Gfx, UniformBuffer);
|
||||
DECLARE_REF(Material);
|
||||
DECLARE_REF(VertexFactory);
|
||||
struct MeshBatchElement
|
||||
{
|
||||
public:
|
||||
Gfx::PUniformBuffer uniformBuffer;
|
||||
Gfx::PIndexBuffer indexBuffer;
|
||||
|
||||
union
|
||||
{
|
||||
uint32* instanceRuns;
|
||||
};
|
||||
|
||||
|
||||
uint32 firstIndex;
|
||||
uint32 numPrimitives;
|
||||
|
||||
uint32 numInstances;
|
||||
uint32 baseVertexIndex;
|
||||
uint32 minVertexIndex;
|
||||
uint32 maxVertexIndex;
|
||||
|
||||
uint8 isInstanced : 1;
|
||||
Gfx::PVertexBuffer indirectArgsBuffer;
|
||||
MeshBatchElement()
|
||||
: uniformBuffer(nullptr)
|
||||
, indexBuffer(nullptr)
|
||||
, indirectArgsBuffer(nullptr)
|
||||
, firstIndex(0)
|
||||
, numPrimitives(0)
|
||||
, numInstances(1)
|
||||
, baseVertexIndex(0)
|
||||
, minVertexIndex(0)
|
||||
, maxVertexIndex(0)
|
||||
{}
|
||||
};
|
||||
struct MeshBatch
|
||||
{
|
||||
Array<MeshBatchElement> elements;
|
||||
|
||||
uint8 useReverseCulling : 1;
|
||||
uint8 isBackfaceCullingDisabled : 1;
|
||||
uint8 isCastingShadow : 1;
|
||||
uint8 useWireframe : 1;
|
||||
|
||||
const Gfx::SePrimitiveTopology topology;
|
||||
|
||||
const PVertexFactory vertexFactory;
|
||||
|
||||
const PMaterial material;
|
||||
|
||||
inline int32 getNumPrimitives() const
|
||||
{
|
||||
int32 count = 0;
|
||||
for(uint32 index = 0; index < elements.size(); ++index)
|
||||
{
|
||||
if(elements[index].isInstanced && elements[index].instanceRuns)
|
||||
{
|
||||
for(uint32 run = 0; run < elements[index].numInstances; ++run)
|
||||
{
|
||||
count += elements[index].numPrimitives * (elements[index].instanceRuns[run * 2 + 1] - elements[index].instanceRuns[run * 2] - 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
count += elements[index].numPrimitives * elements[index].numInstances;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
MeshBatch()
|
||||
: useReverseCulling(false)
|
||||
, isBackfaceCullingDisabled(false)
|
||||
, isCastingShadow(true)
|
||||
, useWireframe(false)
|
||||
, vertexFactory(nullptr)
|
||||
, material(nullptr)
|
||||
, topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||||
{
|
||||
elements.add();
|
||||
}
|
||||
};
|
||||
DECLARE_REF(PrimitiveComponent);
|
||||
struct StaticMeshBatch : public MeshBatch
|
||||
{
|
||||
uint32 index;
|
||||
PPrimitiveComponent primitiveComponent;
|
||||
};
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
class BasePass
|
||||
{
|
||||
public:
|
||||
BasePass();
|
||||
~BasePass();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,10 @@
|
||||
target_sources(SeeleEngine
|
||||
PRIVATE
|
||||
BasePass.h
|
||||
BasePass.cpp
|
||||
DepthPrepass.h
|
||||
DepthPrepass.cpp
|
||||
MeshProcessor.h
|
||||
MeshProcessor.cpp
|
||||
VertexFactory.h
|
||||
VertexFactory.cpp)
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "MeshProcessor.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "VertexFactory.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
MeshProcessor::MeshProcessor(const PScene scene, Gfx::PGraphics graphics)
|
||||
: scene(scene)
|
||||
, graphics(graphics)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MeshProcessor::~MeshProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
void MeshProcessor::buildMeshDrawCommands(
|
||||
const MeshBatch& meshBatch,
|
||||
const PPrimitiveComponent primitiveComponent,
|
||||
PMaterial material,
|
||||
Gfx::PVertexShader vertexShader,
|
||||
Gfx::PControlShader controlShader,
|
||||
Gfx::PEvaluationShader evaluationShader,
|
||||
Gfx::PGeometryShader geometryShader,
|
||||
Gfx::PFragmentShader fragmentShader,
|
||||
bool positionOnly)
|
||||
{
|
||||
const PVertexFactory vertexFactory = meshBatch.vertexFactory;
|
||||
|
||||
GraphicsPipelineCreateInfo pipelineInitializer;
|
||||
pipelineInitializer.topology = meshBatch.topology;
|
||||
Gfx::PVertexDeclaration vertexDecl = positionOnly ? vertexFactory->getPositionDeclaration() : vertexFactory->getDeclaration();
|
||||
pipelineInitializer.vertexDeclaration = vertexDecl;
|
||||
pipelineInitializer.vertexShader = vertexShader;
|
||||
pipelineInitializer.controlShader = controlShader;
|
||||
pipelineInitializer.evalShader = evaluationShader;
|
||||
pipelineInitializer.geometryShader = geometryShader;
|
||||
pipelineInitializer.fragmentShader = fragmentShader;
|
||||
|
||||
VertexInputStreamArray vertexStreams;
|
||||
if(positionOnly)
|
||||
{
|
||||
vertexFactory->getPositionOnlyStream(vertexStreams);
|
||||
}
|
||||
else
|
||||
{
|
||||
vertexFactory->getStreams(vertexStreams);
|
||||
}
|
||||
if(vertexShader != nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Scene/Scene.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include "Graphics/MeshBatch.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
class MeshProcessor
|
||||
{
|
||||
public:
|
||||
MeshProcessor(const PScene scene, Gfx::PGraphics graphics);
|
||||
virtual ~MeshProcessor();
|
||||
private:
|
||||
PScene scene;
|
||||
Gfx::PGraphics graphics;
|
||||
virtual void addMeshBatch(
|
||||
const MeshBatch& meshBatch,
|
||||
const PPrimitiveComponent primitiveComponent,
|
||||
int32 staticMeshId = -1) = 0;
|
||||
void buildMeshDrawCommands(
|
||||
const MeshBatch& meshBatch,
|
||||
const PPrimitiveComponent primitiveComponent,
|
||||
PMaterial material,
|
||||
Gfx::PVertexShader vertexShader,
|
||||
Gfx::PControlShader controlShader,
|
||||
Gfx::PEvaluationShader evaluationShader,
|
||||
Gfx::PGeometryShader geometryShader,
|
||||
Gfx::PFragmentShader fragmentShader,
|
||||
bool positionOnly);
|
||||
};
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "VertexFactory.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
void VertexFactory::getStreams(VertexInputStreamArray& outVertexStreams) const
|
||||
{
|
||||
for(uint32 i = 0; i < streams.size(); ++i)
|
||||
{
|
||||
const Gfx::VertexStream& stream = streams[i];
|
||||
if(stream.vertexBuffer == nullptr)
|
||||
{
|
||||
outVertexStreams.add(VertexInputStream(i, 0, nullptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
outVertexStreams.add(VertexInputStream(i, stream.offset, stream.vertexBuffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VertexFactory::getPositionOnlyStream(VertexInputStreamArray& outVertexStreams) const
|
||||
{
|
||||
for (uint32 i = 0; i < positionStream.size(); ++i)
|
||||
{
|
||||
const Gfx::VertexStream& stream = positionStream[i];
|
||||
outVertexStreams.add(VertexInputStream(i, stream.offset, stream.vertexBuffer));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
struct VertexInputStream
|
||||
{
|
||||
uint32 streamIndex : 4;
|
||||
uint32 offset : 28;
|
||||
Gfx::PVertexBuffer vertexBuffer;
|
||||
|
||||
VertexInputStream()
|
||||
: streamIndex(0), offset(0), vertexBuffer(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
VertexInputStream(uint32 streamIndex, uint32 offset, Gfx::PVertexBuffer vertexBuffer)
|
||||
: streamIndex(streamIndex), offset(offset), vertexBuffer(vertexBuffer)
|
||||
{
|
||||
assert(this->streamIndex == streamIndex && this->offset == offset);
|
||||
}
|
||||
|
||||
inline bool operator==(const VertexInputStream &rhs) const
|
||||
{
|
||||
if (streamIndex != rhs.streamIndex || offset != rhs.offset || vertexBuffer != rhs.vertexBuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
inline bool operator!=(const VertexInputStream &rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
struct VertexStreamComponent
|
||||
{
|
||||
const Gfx::PVertexBuffer vertexBuffer = nullptr;
|
||||
|
||||
uint32 streamOffset = 0;
|
||||
|
||||
uint8 offset = 0;
|
||||
|
||||
uint8 stride;
|
||||
|
||||
Gfx::SeFormat type;
|
||||
|
||||
VertexStreamComponent()
|
||||
{
|
||||
}
|
||||
|
||||
VertexStreamComponent(const Gfx::PVertexBuffer vertexBuffer, uint32 offset, uint32 stride, Gfx::SeFormat type)
|
||||
: vertexBuffer(vertexBuffer)
|
||||
, streamOffset(0)
|
||||
, offset(offset)
|
||||
, stride(stride)
|
||||
, type(type)
|
||||
{
|
||||
}
|
||||
|
||||
VertexStreamComponent(const Gfx::PVertexBuffer vertexBuffer, uint32 streamOffset, uint32 offset, uint32 stride, Gfx::SeFormat type)
|
||||
: vertexBuffer(vertexBuffer)
|
||||
, streamOffset(streamOffset)
|
||||
, offset(offset)
|
||||
, stride(stride)
|
||||
, type(type)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef Array<VertexInputStream> VertexInputStreamArray;
|
||||
class VertexFactory
|
||||
{
|
||||
public:
|
||||
VertexFactory()
|
||||
{
|
||||
}
|
||||
void getStreams(VertexInputStreamArray& outVertexStreams) const;
|
||||
void getPositionOnlyStream(VertexInputStreamArray& outVertexStreams) const;
|
||||
virtual bool supportsTesselation() { return false; }
|
||||
Gfx::PVertexDeclaration getDeclaration() const {return declaration;}
|
||||
Gfx::PVertexDeclaration getPositionDeclaration() const {return positionDeclaration;}
|
||||
private:
|
||||
StaticArray<Gfx::VertexStream, 16> streams;
|
||||
StaticArray<Gfx::VertexStream, 16> positionStream;
|
||||
Gfx::PVertexDeclaration declaration;
|
||||
Gfx::PVertexDeclaration positionDeclaration;
|
||||
};
|
||||
DEFINE_REF(VertexFactory);
|
||||
} // namespace Seele
|
||||
@@ -9,6 +9,7 @@ public:
|
||||
RenderPath(Gfx::PGraphics graphics, Gfx::PViewport target);
|
||||
virtual ~RenderPath();
|
||||
virtual void applyArea(URect area);
|
||||
virtual void init() = 0;
|
||||
virtual void beginFrame() = 0;
|
||||
virtual void render() = 0;
|
||||
virtual void endFrame() = 0;
|
||||
|
||||
@@ -1,12 +1,39 @@
|
||||
#include "SceneRenderPath.h"
|
||||
#include "Scene/Scene.h"
|
||||
#include "Material/Material.h"
|
||||
|
||||
Seele::SceneRenderPath::SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target)
|
||||
using namespace Seele;
|
||||
|
||||
SceneRenderPath::SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target)
|
||||
: RenderPath(graphics, target)
|
||||
{
|
||||
scene = new Scene();
|
||||
}
|
||||
|
||||
Seele::SceneRenderPath::~SceneRenderPath()
|
||||
SceneRenderPath::~SceneRenderPath()
|
||||
{
|
||||
}
|
||||
|
||||
void SceneRenderPath::setTargetScene(PScene newScene)
|
||||
{
|
||||
scene = newScene;
|
||||
}
|
||||
|
||||
void SceneRenderPath::init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SceneRenderPath::beginFrame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SceneRenderPath::render()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SceneRenderPath::endFrame()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -9,9 +9,11 @@ class SceneRenderPath : public RenderPath
|
||||
public:
|
||||
SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target);
|
||||
virtual ~SceneRenderPath();
|
||||
virtual void beginFrame() = 0;
|
||||
virtual void render() = 0;
|
||||
virtual void endFrame() = 0;
|
||||
void setTargetScene(PScene scene);
|
||||
virtual void init();
|
||||
virtual void beginFrame();
|
||||
virtual void render();
|
||||
virtual void endFrame();
|
||||
|
||||
protected:
|
||||
PScene scene;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "SceneView.h"
|
||||
#include "ForwardPlusRenderPath.h"
|
||||
#include "SceneRenderPath.h"
|
||||
#include "Window.h"
|
||||
|
||||
Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo)
|
||||
: View(graphics, owner, createInfo)
|
||||
{
|
||||
renderer = new ForwardPlusRenderPath(graphics, viewport);
|
||||
renderer = new SceneRenderPath(graphics, viewport);
|
||||
}
|
||||
|
||||
Seele::SceneView::~SceneView()
|
||||
|
||||
@@ -61,16 +61,15 @@ Allocation::Allocation(PGraphics graphics, Allocator *allocator, VkDeviceSize si
|
||||
|
||||
Allocation::~Allocation()
|
||||
{
|
||||
allocator->free(this);
|
||||
}
|
||||
|
||||
PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
|
||||
{
|
||||
std::scoped_lock lck(lock);
|
||||
if (isDedicated)
|
||||
{
|
||||
if (activeAllocations.empty())
|
||||
if (activeAllocations.empty() && requestedSize == bytesAllocated)
|
||||
{
|
||||
assert(requestedSize == bytesAllocated);
|
||||
PSubAllocation suballoc = freeRanges[0];
|
||||
activeAllocations[0] = suballoc.getHandle();
|
||||
freeRanges.clear();
|
||||
@@ -82,9 +81,9 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
for (uint32 i = 0; i < freeRanges.size(); ++i)
|
||||
for (auto it : freeRanges)
|
||||
{
|
||||
PSubAllocation freeAllocation = freeRanges[i];
|
||||
PSubAllocation freeAllocation = it.value;
|
||||
VkDeviceSize allocatedOffset = freeAllocation->allocatedOffset;
|
||||
VkDeviceSize alignedOffset = align(allocatedOffset, alignment);
|
||||
VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset;
|
||||
@@ -115,32 +114,48 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
||||
|
||||
void Allocation::markFree(SubAllocation *allocation)
|
||||
{
|
||||
// Dont free if it is already a free allocation, since they also mark themselves on deletion
|
||||
if(freeRanges.find(allocation->allocatedOffset) != nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
VkDeviceSize lowerBound = allocation->allocatedOffset;
|
||||
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
||||
PSubAllocation allocHandle;
|
||||
std::scoped_lock lck(lock);
|
||||
//Join lower bound
|
||||
for (auto freeRange : freeRanges)
|
||||
{
|
||||
PSubAllocation freeAlloc = freeRange.value;
|
||||
if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize + 1 == lowerBound)
|
||||
if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize == lowerBound)
|
||||
{
|
||||
//extend freeAlloc by the allocatedSize
|
||||
freeAlloc->allocatedSize += allocation->allocatedSize;
|
||||
allocHandle = freeAlloc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto foundAlloc = freeRanges.find(upperBound + 1);
|
||||
//Join upper bound
|
||||
auto foundAlloc = freeRanges.find(upperBound);
|
||||
if (foundAlloc != freeRanges.end())
|
||||
{
|
||||
if (allocHandle == nullptr)
|
||||
// There is a free allocation ending where the new free one ends
|
||||
if (allocHandle != nullptr)
|
||||
{
|
||||
// extend allocHandle by another foundAlloc->allocatedSize bytes
|
||||
allocHandle->allocatedSize += foundAlloc->value->allocatedSize;
|
||||
freeRanges.erase(foundAlloc->key);
|
||||
}
|
||||
else
|
||||
{
|
||||
// set foundAlloc back by size amount
|
||||
allocHandle = foundAlloc->value;
|
||||
// remove from offset map since key changes
|
||||
freeRanges.erase(foundAlloc->key);
|
||||
allocHandle->allocatedOffset -= allocation->allocatedSize;
|
||||
allocHandle->alignedOffset -= allocation->allocatedSize;
|
||||
// place back at correct offset
|
||||
freeRanges[allocHandle->allocatedOffset] = allocHandle;
|
||||
}
|
||||
}
|
||||
if (allocHandle == nullptr)
|
||||
@@ -150,6 +165,8 @@ void Allocation::markFree(SubAllocation *allocation)
|
||||
}
|
||||
activeAllocations.erase(allocation->allocatedOffset);
|
||||
bytesUsed -= allocation->allocatedSize;
|
||||
|
||||
// TODO: delete allocation when bytesUsed == 0
|
||||
}
|
||||
|
||||
Allocator::Allocator(PGraphics graphics)
|
||||
@@ -167,6 +184,7 @@ Allocator::Allocator(PGraphics graphics)
|
||||
|
||||
Allocator::~Allocator()
|
||||
{
|
||||
std::scoped_lock lck(lock);
|
||||
for (auto heap : heaps)
|
||||
{
|
||||
for (auto alloc : heap.allocations)
|
||||
@@ -181,6 +199,7 @@ Allocator::~Allocator()
|
||||
|
||||
PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
||||
{
|
||||
std::scoped_lock lck(lock);
|
||||
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
|
||||
uint8 memoryTypeIndex;
|
||||
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
|
||||
@@ -213,6 +232,7 @@ PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2
|
||||
|
||||
void Allocator::free(Allocation *allocation)
|
||||
{
|
||||
std::scoped_lock lck(lock);
|
||||
for (auto heap : heaps)
|
||||
{
|
||||
for (uint32 i = 0; i < heap.allocations.size(); ++i)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "VulkanGraphicsEnums.h"
|
||||
#include "Containers/Map.h"
|
||||
#include "Containers/Array.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
@@ -101,6 +102,7 @@ private:
|
||||
VkMemoryPropertyFlags properties;
|
||||
Map<VkDeviceSize, SubAllocation *> activeAllocations;
|
||||
Map<VkDeviceSize, PSubAllocation> freeRanges;
|
||||
std::mutex lock;
|
||||
void *mappedPointer;
|
||||
uint8 memoryTypeIndex;
|
||||
uint8 isDedicated : 1;
|
||||
@@ -153,6 +155,7 @@ private:
|
||||
};
|
||||
Array<HeapInfo> heaps;
|
||||
VkResult findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex);
|
||||
std::mutex lock;
|
||||
PGraphics graphics;
|
||||
VkPhysicalDeviceMemoryProperties memProperties;
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ struct PendingBuffer
|
||||
static Map<Buffer *, PendingBuffer> pendingBuffers;
|
||||
|
||||
Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType)
|
||||
: QueueOwnedResource(graphics, queueType), currentBuffer(0), size(size)
|
||||
: graphics(graphics), currentBuffer(0), size(size), currentOwner(queueType)
|
||||
{
|
||||
if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ||
|
||||
usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT ||
|
||||
@@ -58,7 +58,7 @@ Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::Q
|
||||
|
||||
Buffer::~Buffer()
|
||||
{
|
||||
auto fence = getCommands()->getCommands()->getFence();
|
||||
auto fence = graphics->getQueueCommands(currentOwner)->getCommands()->getFence();
|
||||
auto &deletionQueue = graphics->getDeletionQueue();
|
||||
VkDevice device = graphics->getDevice();
|
||||
VkBuffer buf[Gfx::numFramesBuffered];
|
||||
@@ -74,11 +74,11 @@ void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
VkBufferMemoryBarrier barrier =
|
||||
init::BufferMemoryBarrier();
|
||||
PCommandBufferManager sourceManager = getCommands();
|
||||
PCommandBufferManager sourceManager = graphics->getQueueCommands(currentOwner);
|
||||
PCommandBufferManager dstManager = nullptr;
|
||||
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
||||
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
||||
barrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(currentOwner);
|
||||
barrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner);
|
||||
assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex);
|
||||
@@ -134,7 +134,7 @@ void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
vkCmdPipelineBarrier(srcCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
|
||||
vkCmdPipelineBarrier(dstCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
|
||||
sourceManager->submitCommands();
|
||||
cachedCmdBufferManager = dstManager;
|
||||
currentOwner = newOwner;
|
||||
}
|
||||
|
||||
void *Buffer::lock(bool bWriteOnly)
|
||||
@@ -160,19 +160,19 @@ void *Buffer::lock(bool bWriteOnly)
|
||||
pending.prevQueue = currentOwner;
|
||||
if (bWriteOnly)
|
||||
{
|
||||
transferOwnership(Gfx::QueueType::DEDICATED_TRANSFER);
|
||||
requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
|
||||
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
||||
data = stagingBuffer->getMappedPointer();
|
||||
pending.stagingBuffer = stagingBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
PCmdBuffer current = getCommands()->getCommands();
|
||||
getCommands()->submitCommands();
|
||||
getCommands()->waitForCommands(current);
|
||||
PCmdBuffer current = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||
graphics->getQueueCommands(currentOwner)->submitCommands();
|
||||
graphics->getQueueCommands(currentOwner)->waitForCommands(current);
|
||||
|
||||
transferOwnership(Gfx::QueueType::DEDICATED_TRANSFER);
|
||||
VkCommandBuffer handle = getCommands()->getCommands()->getHandle();
|
||||
requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
|
||||
VkCommandBuffer handle = graphics->getQueueCommands(currentOwner)->getCommands()->getHandle();
|
||||
|
||||
VkBufferMemoryBarrier barrier =
|
||||
init::BufferMemoryBarrier();
|
||||
@@ -194,8 +194,8 @@ void *Buffer::lock(bool bWriteOnly)
|
||||
|
||||
vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, ®ions);
|
||||
|
||||
getCommands()->submitCommands();
|
||||
vkQueueWaitIdle(getCommands()->getQueue()->getHandle());
|
||||
graphics->getQueueCommands(currentOwner)->submitCommands();
|
||||
vkQueueWaitIdle(graphics->getQueueCommands(currentOwner)->getQueue()->getHandle());
|
||||
|
||||
stagingBuffer->flushMappedMemory();
|
||||
pending.stagingBuffer = stagingBuffer;
|
||||
@@ -219,7 +219,7 @@ void Buffer::unlock()
|
||||
if (pending.bWriteOnly)
|
||||
{
|
||||
PStagingBuffer stagingBuffer = pending.stagingBuffer;
|
||||
PCmdBuffer cmdBuffer = getCommands()->getCommands();
|
||||
PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||
VkCommandBuffer cmdHandle = cmdBuffer->getHandle();
|
||||
|
||||
VkBufferCopy region;
|
||||
@@ -227,13 +227,14 @@ void Buffer::unlock()
|
||||
region.size = size;
|
||||
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion);
|
||||
}
|
||||
transferOwnership(pending.prevQueue);
|
||||
requestOwnershipTransfer(pending.prevQueue);
|
||||
graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
UniformBuffer::UniformBuffer(PGraphics graphics, const BulkResourceData &resourceData)
|
||||
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, resourceData.owner)
|
||||
, Gfx::UniformBuffer(graphics, resourceData.owner)
|
||||
{
|
||||
if (resourceData.data != nullptr)
|
||||
{
|
||||
@@ -247,6 +248,17 @@ UniformBuffer::~UniformBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
{
|
||||
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||
Buffer::currentOwner = newOwner;
|
||||
}
|
||||
|
||||
void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
Buffer::executeOwnershipBarrier(newOwner);
|
||||
}
|
||||
|
||||
VkAccessFlags UniformBuffer::getSourceAccessMask()
|
||||
{
|
||||
return VK_ACCESS_MEMORY_WRITE_BIT;
|
||||
@@ -259,6 +271,7 @@ VkAccessFlags UniformBuffer::getDestAccessMask()
|
||||
|
||||
StructuredBuffer::StructuredBuffer(PGraphics graphics, const BulkResourceData &resourceData)
|
||||
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, resourceData.owner)
|
||||
, Gfx::StructuredBuffer(graphics, resourceData.owner)
|
||||
{
|
||||
if (resourceData.data != nullptr)
|
||||
{
|
||||
@@ -272,6 +285,16 @@ StructuredBuffer::~StructuredBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void StructuredBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
{
|
||||
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||
}
|
||||
|
||||
void StructuredBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
Buffer::executeOwnershipBarrier(newOwner);
|
||||
}
|
||||
|
||||
VkAccessFlags StructuredBuffer::getSourceAccessMask()
|
||||
{
|
||||
return VK_ACCESS_MEMORY_WRITE_BIT;
|
||||
@@ -284,7 +307,7 @@ VkAccessFlags StructuredBuffer::getDestAccessMask()
|
||||
|
||||
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData)
|
||||
: Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner)
|
||||
, Gfx::VertexBuffer(resourceData.numVertices, resourceData.vertexSize)
|
||||
, Gfx::VertexBuffer(graphics, resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner)
|
||||
{
|
||||
if (resourceData.resourceData.data != nullptr)
|
||||
{
|
||||
@@ -298,6 +321,16 @@ VertexBuffer::~VertexBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
{
|
||||
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||
}
|
||||
|
||||
void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
Buffer::executeOwnershipBarrier(newOwner);
|
||||
}
|
||||
|
||||
VkAccessFlags VertexBuffer::getSourceAccessMask()
|
||||
{
|
||||
return VK_ACCESS_MEMORY_WRITE_BIT;
|
||||
@@ -310,7 +343,7 @@ VkAccessFlags VertexBuffer::getDestAccessMask()
|
||||
|
||||
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData)
|
||||
: Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner)
|
||||
, Gfx::IndexBuffer(resourceData.resourceData.size, resourceData.indexType)
|
||||
, Gfx::IndexBuffer(graphics, resourceData.resourceData.size, resourceData.indexType, resourceData.resourceData.owner)
|
||||
{
|
||||
if (resourceData.resourceData.data != nullptr)
|
||||
{
|
||||
@@ -324,6 +357,16 @@ IndexBuffer::~IndexBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
{
|
||||
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||
}
|
||||
|
||||
void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
Buffer::executeOwnershipBarrier(newOwner);
|
||||
}
|
||||
|
||||
VkAccessFlags IndexBuffer::getSourceAccessMask()
|
||||
{
|
||||
return VK_ACCESS_MEMORY_WRITE_BIT;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "VulkanRenderPass.h"
|
||||
#include "VulkanPipeline.h"
|
||||
#include "VulkanDescriptorSets.h"
|
||||
#include "Graphics/MeshBatch.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
@@ -174,9 +175,9 @@ void SecondaryCmdBuffer::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer)
|
||||
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
|
||||
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, VK_INDEX_TYPE_UINT16);
|
||||
}
|
||||
void SecondaryCmdBuffer::draw(DrawInstance data)
|
||||
void SecondaryCmdBuffer::draw(const MeshBatchElement& data)
|
||||
{
|
||||
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, data.firstInstance);
|
||||
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
|
||||
}
|
||||
|
||||
CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue)
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override;
|
||||
virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) override;
|
||||
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
|
||||
virtual void draw(DrawInstance data) override;
|
||||
virtual void draw(const MeshBatchElement& data) override;
|
||||
|
||||
private:
|
||||
PGraphicsPipeline pipeline;
|
||||
|
||||
@@ -72,6 +72,13 @@ void PipelineLayout::create()
|
||||
layoutHash = memCrc32(&createInfo, sizeof(VkPipelineLayoutCreateInfo), 0);
|
||||
}
|
||||
|
||||
void PipelineLayout::reset()
|
||||
{
|
||||
vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr);
|
||||
descriptorSetLayouts.clear();
|
||||
pushConstants.clear();
|
||||
}
|
||||
|
||||
DescriptorSet::~DescriptorSet()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ public:
|
||||
}
|
||||
virtual ~PipelineLayout();
|
||||
virtual void create();
|
||||
virtual void reset();
|
||||
inline VkPipelineLayout getHandle() const
|
||||
{
|
||||
return layoutHandle;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "VulkanRenderPass.h"
|
||||
#include "VulkanFramebuffer.h"
|
||||
#include "VulkanPipelineCache.h"
|
||||
#include "VulkanDescriptorSets.h"
|
||||
#include "VulkanShader.h"
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include <glfw/glfw3.h>
|
||||
|
||||
@@ -99,9 +101,7 @@ void Graphics::executeCommands(Array<Gfx::PRenderCommand> commands)
|
||||
|
||||
Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo)
|
||||
{
|
||||
PTexture2D result = new Texture2D(this, createInfo.width, createInfo.height, createInfo.bArray,
|
||||
createInfo.bArray, createInfo.arrayLayers, createInfo.format,
|
||||
createInfo.samples, createInfo.usage, createInfo.queueType);
|
||||
PTexture2D result = new Texture2D(this, createInfo);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -133,11 +133,51 @@ Gfx::PRenderCommand Graphics::createRenderCommand()
|
||||
cmdBuffer->begin(getGraphicsCommands()->getCommands());
|
||||
return cmdBuffer;
|
||||
}
|
||||
Gfx::PVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
PVertexShader shader = new VertexShader(this);
|
||||
shader->create(createInfo);
|
||||
return shader;
|
||||
}
|
||||
Gfx::PControlShader Graphics::createControlShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
PControlShader shader = new ControlShader(this);
|
||||
shader->create(createInfo);
|
||||
return shader;
|
||||
}
|
||||
Gfx::PEvaluationShader Graphics::createEvaluationShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
PEvaluationShader shader = new EvaluationShader(this);
|
||||
shader->create(createInfo);
|
||||
return shader;
|
||||
}
|
||||
Gfx::PGeometryShader Graphics::createGeometryShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
PGeometryShader shader = new GeometryShader(this);
|
||||
shader->create(createInfo);
|
||||
return shader;
|
||||
}
|
||||
Gfx::PFragmentShader Graphics::createFragmentShader(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
PFragmentShader shader = new FragmentShader(this);
|
||||
shader->create(createInfo);
|
||||
return shader;
|
||||
}
|
||||
Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo)
|
||||
{
|
||||
PGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo);
|
||||
return pipeline;
|
||||
}
|
||||
Gfx::PDescriptorLayout Graphics::createDescriptorLayout()
|
||||
{
|
||||
PDescriptorLayout layout = new DescriptorLayout(this);
|
||||
return layout;
|
||||
}
|
||||
Gfx::PPipelineLayout Graphics::createPipelineLayout()
|
||||
{
|
||||
PPipelineLayout layout = new PipelineLayout(this);
|
||||
return layout;
|
||||
}
|
||||
|
||||
VkInstance Graphics::getInstance() const
|
||||
{
|
||||
@@ -154,6 +194,23 @@ VkPhysicalDevice Graphics::getPhysicalDevice() const
|
||||
return physicalDevice;
|
||||
}
|
||||
|
||||
PCommandBufferManager Graphics::getQueueCommands(Gfx::QueueType queueType)
|
||||
{
|
||||
switch (queueType)
|
||||
{
|
||||
case Gfx::QueueType::GRAPHICS:
|
||||
return graphicsCommands;
|
||||
case Gfx::QueueType::COMPUTE:
|
||||
return computeCommands;
|
||||
case Gfx::QueueType::TRANSFER:
|
||||
return transferCommands;
|
||||
case Gfx::QueueType::DEDICATED_TRANSFER:
|
||||
return dedicatedTransferCommands;
|
||||
default:
|
||||
throw new std::logic_error("invalid queue type");
|
||||
}
|
||||
}
|
||||
|
||||
PCommandBufferManager Graphics::getGraphicsCommands()
|
||||
{
|
||||
return graphicsCommands;
|
||||
|
||||
@@ -22,15 +22,12 @@ public:
|
||||
VkDevice getDevice() const;
|
||||
VkPhysicalDevice getPhysicalDevice() const;
|
||||
|
||||
PCommandBufferManager getQueueCommands(Gfx::QueueType queueType);
|
||||
PCommandBufferManager getGraphicsCommands();
|
||||
PCommandBufferManager getComputeCommands();
|
||||
PCommandBufferManager getTransferCommands();
|
||||
PCommandBufferManager getDedicatedTransferCommands();
|
||||
|
||||
const QueueFamilyMapping getFamilyMapping() const
|
||||
{
|
||||
return queueMapping;
|
||||
}
|
||||
QueueOwnedResourceDeletion &getDeletionQueue()
|
||||
{
|
||||
return deletionQueue;
|
||||
@@ -56,8 +53,16 @@ public:
|
||||
virtual Gfx::PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) override;
|
||||
virtual Gfx::PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) override;
|
||||
virtual Gfx::PRenderCommand createRenderCommand() override;
|
||||
virtual Gfx::PVertexShader createVertexShader(const ShaderCreateInfo& createInfo) override;
|
||||
virtual Gfx::PControlShader createControlShader(const ShaderCreateInfo& createInfo) override;
|
||||
virtual Gfx::PEvaluationShader createEvaluationShader(const ShaderCreateInfo& createInfo) override;
|
||||
virtual Gfx::PGeometryShader createGeometryShader(const ShaderCreateInfo& createInfo) override;
|
||||
virtual Gfx::PFragmentShader createFragmentShader(const ShaderCreateInfo& createInfo) override;
|
||||
virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override;
|
||||
|
||||
virtual Gfx::PDescriptorLayout createDescriptorLayout() override;
|
||||
virtual Gfx::PPipelineLayout createPipelineLayout() override;
|
||||
|
||||
protected:
|
||||
Array<const char *> getRequiredExtensions();
|
||||
void initInstance(GraphicsInitializer initInfo);
|
||||
@@ -73,7 +78,6 @@ protected:
|
||||
PQueue computeQueue;
|
||||
PQueue transferQueue;
|
||||
PQueue dedicatedTransferQueue;
|
||||
QueueFamilyMapping queueMapping;
|
||||
QueueOwnedResourceDeletion deletionQueue;
|
||||
PPipelineCache pipelineCache;
|
||||
PCommandBufferManager graphicsCommands;
|
||||
|
||||
@@ -50,47 +50,6 @@ void QueueOwnedResourceDeletion::run()
|
||||
}
|
||||
}
|
||||
|
||||
QueueOwnedResource::QueueOwnedResource(PGraphics graphics, Gfx::QueueType startQueueType)
|
||||
: graphics(graphics), currentOwner(startQueueType)
|
||||
{
|
||||
}
|
||||
|
||||
QueueOwnedResource::~QueueOwnedResource()
|
||||
{
|
||||
cachedCmdBufferManager = nullptr;
|
||||
graphics = nullptr;
|
||||
}
|
||||
|
||||
void QueueOwnedResource::transferOwnership(Gfx::QueueType newOwner)
|
||||
{
|
||||
if (graphics->getFamilyMapping().needsTransfer(currentOwner, newOwner))
|
||||
{
|
||||
executeOwnershipBarrier(newOwner);
|
||||
currentOwner = newOwner;
|
||||
}
|
||||
}
|
||||
|
||||
PCommandBufferManager QueueOwnedResource::getCommands()
|
||||
{
|
||||
if (cachedCmdBufferManager != nullptr)
|
||||
{
|
||||
assert(cachedCmdBufferManager->getQueue()->getFamilyIndex() == graphics->getFamilyMapping().getQueueTypeFamilyIndex(currentOwner));
|
||||
return cachedCmdBufferManager;
|
||||
}
|
||||
switch (currentOwner)
|
||||
{
|
||||
case Gfx::QueueType::GRAPHICS:
|
||||
return graphics->getGraphicsCommands();
|
||||
case Gfx::QueueType::COMPUTE:
|
||||
return graphics->getComputeCommands();
|
||||
case Gfx::QueueType::TRANSFER:
|
||||
return graphics->getTransferCommands();
|
||||
case Gfx::QueueType::DEDICATED_TRANSFER:
|
||||
return graphics->getDedicatedTransferCommands();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Semaphore::Semaphore(PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#pragma once
|
||||
#include "Graphics/GraphicsResources.h"
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
#include <condition_variable>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
namespace Seele
|
||||
@@ -54,35 +51,6 @@ private:
|
||||
};
|
||||
DEFINE_REF(Fence);
|
||||
|
||||
struct QueueFamilyMapping
|
||||
{
|
||||
uint32 graphicsFamily;
|
||||
uint32 computeFamily;
|
||||
uint32 transferFamily;
|
||||
uint32 dedicatedTransferFamily;
|
||||
uint32 getQueueTypeFamilyIndex(Gfx::QueueType type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Gfx::QueueType::GRAPHICS:
|
||||
return graphicsFamily;
|
||||
case Gfx::QueueType::COMPUTE:
|
||||
return computeFamily;
|
||||
case Gfx::QueueType::TRANSFER:
|
||||
return transferFamily;
|
||||
case Gfx::QueueType::DEDICATED_TRANSFER:
|
||||
return dedicatedTransferFamily;
|
||||
default:
|
||||
return VK_QUEUE_FAMILY_IGNORED;
|
||||
}
|
||||
}
|
||||
bool needsTransfer(Gfx::QueueType src, Gfx::QueueType dst) const
|
||||
{
|
||||
uint32 srcIndex = getQueueTypeFamilyIndex(src);
|
||||
uint32 dstIndex = getQueueTypeFamilyIndex(dst);
|
||||
return srcIndex != dstIndex;
|
||||
}
|
||||
};
|
||||
class QueueOwnedResourceDeletion
|
||||
{
|
||||
public:
|
||||
@@ -103,24 +71,8 @@ private:
|
||||
static std::condition_variable cv;
|
||||
static List<PendingItem> deletionQueue;
|
||||
};
|
||||
class QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
QueueOwnedResource(PGraphics graphics, Gfx::QueueType startQueueType);
|
||||
virtual ~QueueOwnedResource();
|
||||
PCommandBufferManager getCommands();
|
||||
//Preliminary checks to see if the barrier should be executed at all
|
||||
void transferOwnership(Gfx::QueueType newOwner);
|
||||
|
||||
protected:
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) = 0;
|
||||
Gfx::QueueType currentOwner;
|
||||
PGraphics graphics;
|
||||
PCommandBufferManager cachedCmdBufferManager;
|
||||
};
|
||||
DEFINE_REF(QueueOwnedResource);
|
||||
|
||||
class Buffer : public QueueOwnedResource
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType);
|
||||
@@ -146,11 +98,14 @@ protected:
|
||||
uint32 numBuffers;
|
||||
uint32 currentBuffer;
|
||||
uint32 size;
|
||||
PGraphics graphics;
|
||||
Gfx::QueueType currentOwner;
|
||||
|
||||
void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0;
|
||||
|
||||
virtual VkAccessFlags getSourceAccessMask() = 0;
|
||||
virtual VkAccessFlags getDestAccessMask() = 0;
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||
};
|
||||
DEFINE_REF(Buffer);
|
||||
|
||||
@@ -161,8 +116,12 @@ public:
|
||||
virtual ~UniformBuffer();
|
||||
|
||||
protected:
|
||||
// Inherited via Vulkan::Buffer
|
||||
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
|
||||
virtual VkAccessFlags getSourceAccessMask();
|
||||
virtual VkAccessFlags getDestAccessMask();
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||
};
|
||||
DEFINE_REF(UniformBuffer);
|
||||
|
||||
@@ -173,8 +132,12 @@ public:
|
||||
virtual ~StructuredBuffer();
|
||||
|
||||
protected:
|
||||
// Inherited via Vulkan::Buffer
|
||||
virtual VkAccessFlags getSourceAccessMask();
|
||||
virtual VkAccessFlags getDestAccessMask();
|
||||
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||
};
|
||||
DEFINE_REF(StructuredBuffer);
|
||||
|
||||
@@ -185,8 +148,12 @@ public:
|
||||
virtual ~VertexBuffer();
|
||||
|
||||
protected:
|
||||
// Inherited via Vulkan::Buffer
|
||||
virtual VkAccessFlags getSourceAccessMask();
|
||||
virtual VkAccessFlags getDestAccessMask();
|
||||
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||
};
|
||||
DEFINE_REF(VertexBuffer);
|
||||
|
||||
@@ -197,17 +164,20 @@ public:
|
||||
virtual ~IndexBuffer();
|
||||
|
||||
protected:
|
||||
// Inherited via Vulkan::Buffer
|
||||
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
|
||||
virtual VkAccessFlags getSourceAccessMask();
|
||||
virtual VkAccessFlags getDestAccessMask();
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||
};
|
||||
DEFINE_REF(IndexBuffer);
|
||||
|
||||
class TextureHandle : public QueueOwnedResource
|
||||
class TextureHandle
|
||||
{
|
||||
public:
|
||||
TextureHandle(PGraphics graphics, VkImageViewType viewType, uint32 sizeX, uint32 sizeY, uint32 sizeZ,
|
||||
bool bArray, uint32 arraySize, uint32 mipLevels, Gfx::SeFormat format,
|
||||
uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner = Gfx::QueueType::GRAPHICS, VkImage existingImage = VK_NULL_HANDLE);
|
||||
TextureHandle(PGraphics graphics, VkImageViewType viewType,
|
||||
const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
|
||||
virtual ~TextureHandle();
|
||||
|
||||
inline VkImageView getView() const
|
||||
@@ -234,9 +204,10 @@ public:
|
||||
{
|
||||
return aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
}
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||
void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||
void changeLayout(VkImageLayout newLayout);
|
||||
|
||||
Gfx::QueueType currentOwner;
|
||||
private:
|
||||
PGraphics graphics;
|
||||
PSubAllocation allocation;
|
||||
@@ -276,10 +247,7 @@ DEFINE_REF(TextureBase);
|
||||
class Texture2D : public TextureBase, public Gfx::Texture2D
|
||||
{
|
||||
public:
|
||||
Texture2D(PGraphics graphics, uint32 sizeX, uint32 sizeY,
|
||||
bool bArray, uint32 arraySize, uint32 mipLevels, Gfx::SeFormat format,
|
||||
uint32 samples, Gfx::SeImageUsageFlags usage,
|
||||
Gfx::QueueType owner = Gfx::QueueType::GRAPHICS, VkImage existingImage = VK_NULL_HANDLE);
|
||||
Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
|
||||
virtual ~Texture2D();
|
||||
inline uint32 getSizeX() const
|
||||
{
|
||||
@@ -305,8 +273,10 @@ public:
|
||||
{
|
||||
return textureHandle->isDepthStencil();
|
||||
}
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||
|
||||
private:
|
||||
};
|
||||
DEFINE_REF(Texture2D);
|
||||
|
||||
|
||||
@@ -6,9 +6,8 @@ using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
GraphicsPipeline::GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo)
|
||||
: Gfx::GraphicsPipeline(createInfo)
|
||||
: Gfx::GraphicsPipeline(createInfo, pipelineLayout)
|
||||
, graphics(graphics)
|
||||
, layout(pipelineLayout)
|
||||
, pipeline(handle)
|
||||
{
|
||||
}
|
||||
@@ -24,5 +23,5 @@ void GraphicsPipeline::bind(VkCommandBuffer handle)
|
||||
|
||||
VkPipelineLayout GraphicsPipeline::getLayout() const
|
||||
{
|
||||
return layout->getHandle();
|
||||
return layout.cast<PipelineLayout>()->getHandle();
|
||||
}
|
||||
@@ -16,7 +16,6 @@ public:
|
||||
VkPipelineLayout getLayout() const;
|
||||
private:
|
||||
VkPipeline pipeline;
|
||||
PPipelineLayout layout;
|
||||
PGraphics graphics;
|
||||
};
|
||||
DEFINE_REF(GraphicsPipeline);
|
||||
|
||||
@@ -52,6 +52,9 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
createInfo.pNext = 0;
|
||||
createInfo.flags = 0;
|
||||
createInfo.stageCount = 0;
|
||||
|
||||
PPipelineLayout layout = graphics->createPipelineLayout();
|
||||
|
||||
VkPipelineTessellationStateCreateInfo tessInfo;
|
||||
VkPipelineShaderStageCreateInfo stageInfos[5];
|
||||
std::memset(stageInfos, 0, sizeof(stageInfos));
|
||||
@@ -63,6 +66,10 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
vertInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
vertInfo.module = shader->getModuleHandle();
|
||||
vertInfo.pName = shader->getEntryPointName();
|
||||
for(auto descriptor : shader->getDescriptorLayouts())
|
||||
{
|
||||
layout->addDescriptorLayout(descriptor.key, descriptor.value);
|
||||
}
|
||||
}
|
||||
if(gfxInfo.controlShader != nullptr)
|
||||
{
|
||||
@@ -86,6 +93,15 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
tessInfo.pNext = 0;
|
||||
tessInfo.flags = 0;
|
||||
tessInfo.patchControlPoints = control->getNumPatches();
|
||||
|
||||
for(auto descriptor : eval->getDescriptorLayouts())
|
||||
{
|
||||
layout->addDescriptorLayout(descriptor.key, descriptor.value);
|
||||
}
|
||||
for(auto descriptor : control->getDescriptorLayouts())
|
||||
{
|
||||
layout->addDescriptorLayout(descriptor.key, descriptor.value);
|
||||
}
|
||||
}
|
||||
if(gfxInfo.geometryShader != nullptr)
|
||||
{
|
||||
@@ -96,6 +112,11 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
geometryInfo.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||
geometryInfo.module = geometry->getModuleHandle();
|
||||
geometryInfo.pName = geometry->getEntryPointName();
|
||||
|
||||
for(auto descriptor : geometry->getDescriptorLayouts())
|
||||
{
|
||||
layout->addDescriptorLayout(descriptor.key, descriptor.value);
|
||||
}
|
||||
}
|
||||
if(gfxInfo.fragmentShader != nullptr)
|
||||
{
|
||||
@@ -106,7 +127,13 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
fragmentInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
fragmentInfo.module = fragment->getModuleHandle();
|
||||
fragmentInfo.pName = fragment->getEntryPointName();
|
||||
|
||||
for(auto descriptor : fragment->getDescriptorLayouts())
|
||||
{
|
||||
layout->addDescriptorLayout(descriptor.key, descriptor.value);
|
||||
}
|
||||
}
|
||||
layout->create();
|
||||
VkPipelineVertexInputStateCreateInfo vertexInput =
|
||||
init::PipelineVertexInputStateCreateInfo();
|
||||
Gfx::PVertexDeclaration vertexDecl = gfxInfo.vertexDeclaration;
|
||||
@@ -116,7 +143,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
uint32 bindingNum = 0;
|
||||
for(auto vertexBinding : vertexStreams)
|
||||
{
|
||||
uint32 stride = vertexBinding.getVertexBuffer()->getVertexSize();
|
||||
uint32 stride = 0;
|
||||
for(auto vertexAttrib : vertexBinding.getVertexDescriptions())
|
||||
{
|
||||
auto attrib = attribDesc.add();
|
||||
@@ -137,9 +164,9 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo assemblyInfo =
|
||||
init::PipelineInputAssemblyStateCreateInfo(
|
||||
cast(gfxInfo.topology),
|
||||
0,
|
||||
false
|
||||
cast(gfxInfo.topology),
|
||||
0,
|
||||
false
|
||||
);
|
||||
|
||||
VkPipelineViewportStateCreateInfo viewportInfo =
|
||||
@@ -214,6 +241,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
0
|
||||
);
|
||||
|
||||
|
||||
createInfo.pStages = stageInfos;
|
||||
createInfo.pVertexInputState = &vertexInput;
|
||||
createInfo.pInputAssemblyState = &assemblyInfo;
|
||||
@@ -225,7 +253,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
createInfo.pColorBlendState = &blendState;
|
||||
createInfo.pDynamicState = &dynamicState;
|
||||
createInfo.renderPass = gfxInfo.renderPass.cast<RenderPass>()->getHandle();
|
||||
createInfo.layout = gfxInfo.pipelineLayout.cast<PipelineLayout>()->getHandle();
|
||||
createInfo.layout = layout->getHandle();
|
||||
createInfo.subpass = 0;
|
||||
|
||||
VkPipeline pipelineHandle;
|
||||
@@ -235,6 +263,6 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
int64 delta = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - beginTime).count();
|
||||
std::cout << "Gfx creation time: " << delta << std::endl;
|
||||
|
||||
PGraphicsPipeline result = new GraphicsPipeline(graphics, pipelineHandle, gfxInfo.pipelineLayout.cast<PipelineLayout>(), gfxInfo);
|
||||
PGraphicsPipeline result = new GraphicsPipeline(graphics, pipelineHandle, layout, gfxInfo);
|
||||
return result;
|
||||
}
|
||||
@@ -1,4 +1,102 @@
|
||||
#include "VulkanShader.h"
|
||||
#include "VulkanGraphics.h"
|
||||
#include "VulkanDescriptorSets.h"
|
||||
#include "slang.h"
|
||||
|
||||
using namespace slang;
|
||||
using namespace Seele;
|
||||
using namespace Seele::Vulkan;
|
||||
using namespace Seele::Vulkan;
|
||||
|
||||
Shader::Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage)
|
||||
: graphics(graphics)
|
||||
, type(shaderType)
|
||||
, stage(stage)
|
||||
{
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
if(module != VK_NULL_HANDLE)
|
||||
{
|
||||
vkDestroyShaderModule(graphics->getDevice(), module, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Map<uint32, PDescriptorLayout> Shader::getDescriptorLayouts()
|
||||
{
|
||||
return descriptorSets;
|
||||
}
|
||||
|
||||
static SlangStage getStageFromShaderType(ShaderType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ShaderType::VERTEX:
|
||||
return SLANG_STAGE_VERTEX;
|
||||
case ShaderType::CONTROL:
|
||||
return SLANG_STAGE_HULL;
|
||||
case ShaderType::EVALUATION:
|
||||
return SLANG_STAGE_DOMAIN;
|
||||
case ShaderType::GEOMETRY:
|
||||
return SLANG_STAGE_GEOMETRY;
|
||||
case ShaderType::FRAGMENT:
|
||||
return SLANG_STAGE_PIXEL;
|
||||
default:
|
||||
return SLANG_STAGE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::create(const ShaderCreateInfo& createInfo)
|
||||
{
|
||||
entryPointName = createInfo.entryPoint;
|
||||
static SlangSession* session = spCreateSession(NULL);
|
||||
|
||||
SlangCompileRequest* request = spCreateCompileRequest(session);
|
||||
int targetIndex = spAddCodeGenTarget(request, SLANG_SPIRV);
|
||||
spSetTargetProfile(request, targetIndex, spFindProfile(session, "glsl_vk"));
|
||||
spSetDumpIntermediates(request, true);
|
||||
|
||||
int translationUnitIndex = spAddTranslationUnit(request, SLANG_SOURCE_LANGUAGE_SLANG, "");
|
||||
|
||||
spAddTranslationUnitSourceString(
|
||||
request,
|
||||
translationUnitIndex,
|
||||
entryPointName.c_str(),
|
||||
createInfo.code.c_str()
|
||||
);
|
||||
spAddSearchPath(request, "shaders/lib/");
|
||||
|
||||
spSetGlobalGenericArgs(request, createInfo.typeParameter.size(), createInfo.typeParameter.data());
|
||||
|
||||
int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type));
|
||||
if(spCompile(request))
|
||||
{
|
||||
char const* diagnostice = spGetDiagnosticOutput(request);
|
||||
std::cout << diagnostice << std::endl;
|
||||
}
|
||||
|
||||
ShaderReflection* reflection = slang::ShaderReflection::get(request);
|
||||
|
||||
uint32 parameterCount = reflection->getParameterCount();
|
||||
for(uint32 i = 0; i < parameterCount; ++i)
|
||||
{
|
||||
VariableLayoutReflection* parameter =
|
||||
reflection->getParameterByIndex(i);
|
||||
uint32 descriptorIndex = parameter->getBindingSpace();
|
||||
uint32 descriptorBinding = parameter->getBindingIndex();
|
||||
PDescriptorLayout& layout = descriptorSets[descriptorIndex];
|
||||
std::cout << parameter->getTypeLayout()->getName() << std::endl;
|
||||
//layout->addDescriptorBinding(descriptorBinding, parame)
|
||||
}
|
||||
|
||||
size_t dataSize = 0;
|
||||
const void* data = spGetEntryPointCode(request, entryPointIndex, &dataSize);
|
||||
|
||||
VkShaderModuleCreateInfo moduleInfo;
|
||||
moduleInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
moduleInfo.pNext = nullptr;
|
||||
moduleInfo.flags = 0;
|
||||
moduleInfo.codeSize = dataSize;
|
||||
moduleInfo.pCode = static_cast<const uint32*>(data);
|
||||
VK_CHECK(vkCreateShaderModule(graphics->getDevice(), &moduleInfo, nullptr, &module));
|
||||
}
|
||||
@@ -6,13 +6,16 @@ namespace Seele
|
||||
{
|
||||
namespace Vulkan
|
||||
{
|
||||
|
||||
DECLARE_REF(Graphics);
|
||||
DECLARE_REF(DescriptorLayout);
|
||||
class Shader
|
||||
{
|
||||
public:
|
||||
Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage);
|
||||
virtual ~Shader();
|
||||
|
||||
void create(const ShaderCreateInfo& createInfo);
|
||||
|
||||
VkShaderModule getModuleHandle() const
|
||||
{
|
||||
return module;
|
||||
@@ -21,18 +24,23 @@ public:
|
||||
{
|
||||
return entryPointName.c_str();
|
||||
}
|
||||
Map<uint32, PDescriptorLayout> getDescriptorLayouts();
|
||||
private:
|
||||
PGraphics graphics;
|
||||
Map<uint32, PDescriptorLayout> descriptorSets;
|
||||
VkShaderModule module;
|
||||
VkShaderStageFlags stage;
|
||||
ShaderType type;
|
||||
std::string entryPointName;
|
||||
};
|
||||
DEFINE_REF(Shader);
|
||||
|
||||
template <typename Base, ShaderType shaderType, VkShaderStageFlags stage>
|
||||
template <typename Base, ShaderType shaderType, VkShaderStageFlags stageFlags>
|
||||
class ShaderBase : public Base, public Shader
|
||||
{
|
||||
public:
|
||||
ShaderBase(PGraphics graphics)
|
||||
: Shader(graphics, shaderType, stage)
|
||||
: Shader(graphics, shaderType, stageFlags)
|
||||
{
|
||||
}
|
||||
virtual ~ShaderBase()
|
||||
|
||||
@@ -29,10 +29,21 @@ VkImageAspectFlags getAspectFromFormat(Gfx::SeFormat format)
|
||||
}
|
||||
}
|
||||
|
||||
TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint32 sizeX, uint32 sizeY, uint32 sizeZ,
|
||||
bool bArray, uint32 arraySize, uint32 mipLevel,
|
||||
Gfx::SeFormat format, uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner, VkImage existingImage)
|
||||
: QueueOwnedResource(graphics, owner), graphics(graphics), sizeX(sizeX), sizeY(sizeY), sizeZ(sizeZ), mipLevels(mipLevel), format(format), samples(samples), usage(usage), arrayCount(bArray ? arraySize : 1), aspect(getAspectFromFormat(format)), image(existingImage), layout(VK_IMAGE_LAYOUT_UNDEFINED)
|
||||
TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType,
|
||||
const TextureCreateInfo& createInfo, VkImage existingImage)
|
||||
: currentOwner(createInfo.resourceData.owner)
|
||||
, graphics(graphics)
|
||||
, sizeX(createInfo.width)
|
||||
, sizeY(createInfo.height)
|
||||
, sizeZ(createInfo.depth)
|
||||
, mipLevels(createInfo.mipLevels)
|
||||
, format(createInfo.format)
|
||||
, samples(createInfo.samples)
|
||||
, usage(createInfo.usage)
|
||||
, arrayCount(createInfo.bArray ? createInfo.arrayLayers : 1)
|
||||
, aspect(getAspectFromFormat(createInfo.format))
|
||||
, image(existingImage)
|
||||
, layout(VK_IMAGE_LAYOUT_UNDEFINED)
|
||||
{
|
||||
if (existingImage == VK_NULL_HANDLE)
|
||||
{
|
||||
@@ -42,7 +53,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3
|
||||
info.extent.width = sizeX;
|
||||
info.extent.height = sizeY;
|
||||
info.extent.depth = sizeZ;
|
||||
info.arrayLayers = arraySize;
|
||||
info.arrayLayers = arrayCount;
|
||||
info.format = cast(format);
|
||||
|
||||
uint32 layerCount = 1;
|
||||
@@ -67,13 +78,18 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3
|
||||
default:
|
||||
break;
|
||||
}
|
||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
info.mipLevels = mipLevel;
|
||||
info.initialLayout = layout;
|
||||
info.mipLevels = mipLevels;
|
||||
info.arrayLayers = arrayCount * layerCount;
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
info.samples = (VkSampleCountFlagBits)samples;
|
||||
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
info.usage = usage;
|
||||
//To upload to the image we need to specify transfer dst
|
||||
if(createInfo.resourceData.size > 0)
|
||||
{
|
||||
info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
}
|
||||
VK_CHECK(vkCreateImage(graphics->getDevice(), &info, nullptr, &image));
|
||||
|
||||
VkMemoryDedicatedRequirements memDedicatedRequirements;
|
||||
@@ -91,6 +107,37 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3
|
||||
allocation = allocator->allocate(requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, image);
|
||||
vkBindImageMemory(graphics->getDevice(), image, allocation->getHandle(), allocation->getOffset());
|
||||
}
|
||||
|
||||
const BulkResourceData& resourceData = createInfo.resourceData;
|
||||
if(resourceData.size > 0)
|
||||
{
|
||||
changeLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
PStagingBuffer staging = graphics->getStagingManager()->allocateStagingBuffer(resourceData.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
||||
void* data = staging->getMappedPointer();
|
||||
std::memcpy(data, resourceData.data, resourceData.size);
|
||||
staging->flushMappedMemory();
|
||||
|
||||
PCommandBufferManager cmdBufferManager = graphics->getQueueCommands(currentOwner);
|
||||
VkBufferImageCopy region;
|
||||
region.bufferOffset = 0;
|
||||
region.bufferRowLength = 0;
|
||||
region.bufferImageHeight = 0;
|
||||
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.mipLevel = 0;
|
||||
region.imageSubresource.baseArrayLayer = 0;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
|
||||
region.imageOffset = {0, 0, 0};
|
||||
region.imageExtent = {sizeX, sizeX, sizeZ};
|
||||
|
||||
vkCmdCopyBufferToImage(cmdBufferManager->getCommands()->getHandle(),
|
||||
staging->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
// When loading a texture from a file, we will almost always use it as a texture map for fragment shaders
|
||||
changeLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
|
||||
VkImageViewCreateInfo viewInfo =
|
||||
init::ImageViewCreateInfo();
|
||||
viewInfo.subresourceRange = init::ImageSubresourceRange(aspect);
|
||||
@@ -106,7 +153,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3
|
||||
TextureHandle::~TextureHandle()
|
||||
{
|
||||
auto &deletionQueue = graphics->getDeletionQueue();
|
||||
auto fence = getCommands()->getCommands()->getFence();
|
||||
auto fence = graphics->getQueueCommands(currentOwner)->getCommands()->getFence();
|
||||
VkDevice device = graphics->getDevice();
|
||||
VkImageView view = defaultView;
|
||||
VkImage img = image;
|
||||
@@ -114,6 +161,20 @@ TextureHandle::~TextureHandle()
|
||||
deletionQueue.addPendingDelete(fence, [device, img]() { vkDestroyImage(device, img, nullptr); });
|
||||
}
|
||||
|
||||
void TextureHandle::changeLayout(VkImageLayout newLayout)
|
||||
{
|
||||
VkImageMemoryBarrier barrier =
|
||||
init::ImageMemoryBarrier(
|
||||
image,
|
||||
layout,
|
||||
newLayout);
|
||||
PCommandBufferManager cmdManager = graphics->getQueueCommands(currentOwner);
|
||||
vkCmdPipelineBarrier(cmdManager->getCommands()->getHandle(),
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
layout = newLayout;
|
||||
}
|
||||
|
||||
void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
VkImageMemoryBarrier imageBarrier =
|
||||
@@ -122,11 +183,11 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
imageBarrier.oldLayout = layout;
|
||||
imageBarrier.newLayout = layout;
|
||||
imageBarrier.subresourceRange = init::ImageSubresourceRange(aspect);
|
||||
PCommandBufferManager sourceManager = getCommands();
|
||||
PCommandBufferManager sourceManager = graphics->getQueueCommands(currentOwner);
|
||||
PCommandBufferManager dstManager = nullptr;
|
||||
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
||||
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
||||
imageBarrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(currentOwner);
|
||||
imageBarrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner);
|
||||
if (currentOwner == Gfx::QueueType::TRANSFER || currentOwner == Gfx::QueueType::DEDICATED_TRANSFER)
|
||||
@@ -150,7 +211,7 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
dstManager = graphics->getTransferCommands();
|
||||
}
|
||||
else if (currentOwner == Gfx::QueueType::DEDICATED_TRANSFER)
|
||||
else if (newOwner == Gfx::QueueType::DEDICATED_TRANSFER)
|
||||
{
|
||||
imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
@@ -173,30 +234,25 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
vkCmdPipelineBarrier(sourceCmd, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
|
||||
vkCmdPipelineBarrier(destCmd, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
|
||||
sourceManager->submitCommands();
|
||||
cachedCmdBufferManager = dstManager;
|
||||
}
|
||||
|
||||
void TextureBase::changeLayout(VkImageLayout newLayout)
|
||||
{
|
||||
VkImageMemoryBarrier barrier =
|
||||
init::ImageMemoryBarrier(
|
||||
textureHandle->image,
|
||||
textureHandle->layout,
|
||||
newLayout);
|
||||
vkCmdPipelineBarrier(textureHandle->getCommands()->getCommands()->getHandle(),
|
||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||
textureHandle->layout = newLayout;
|
||||
textureHandle->changeLayout(newLayout);
|
||||
}
|
||||
|
||||
Texture2D::Texture2D(PGraphics graphics, uint32 sizeX, uint32 sizeY,
|
||||
bool bArray, uint32 arraySize, uint32 mipLevels, Gfx::SeFormat format,
|
||||
uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner, VkImage existingImage)
|
||||
Texture2D::Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage)
|
||||
: Gfx::Texture2D(graphics, createInfo.resourceData.owner)
|
||||
{
|
||||
textureHandle = new TextureHandle(graphics, bArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
|
||||
sizeX, sizeY, 1, bArray, arraySize, mipLevels, format, samples, usage, owner, existingImage);
|
||||
textureHandle = new TextureHandle(graphics, createInfo.bArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
|
||||
createInfo, existingImage);
|
||||
}
|
||||
|
||||
Texture2D::~Texture2D()
|
||||
{
|
||||
}
|
||||
|
||||
void Texture2D::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
textureHandle->executeOwnershipBarrier(newOwner);
|
||||
}
|
||||
@@ -181,13 +181,17 @@ void Window::createSwapchain()
|
||||
|
||||
PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands();
|
||||
|
||||
TextureCreateInfo backBufferCreateInfo;
|
||||
backBufferCreateInfo.width = sizeX;
|
||||
backBufferCreateInfo.height = sizeY;
|
||||
backBufferCreateInfo.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
backBufferCreateInfo.resourceData.owner = Gfx::QueueType::GRAPHICS;
|
||||
backBufferCreateInfo.format = cast(surfaceFormat.format);
|
||||
for (uint32 i = 0; i < numSwapchainImages; ++i)
|
||||
{
|
||||
imageAcquired[i] = new Semaphore(graphics);
|
||||
renderFinished[i] = new Semaphore(graphics);
|
||||
backBufferImages[i] = new Texture2D(graphics, sizeX, sizeY, false, 1, 1,
|
||||
cast(surfaceFormat.format), 1, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
Gfx::QueueType::GRAPHICS, swapchainImages[i]);
|
||||
backBufferImages[i] = new Texture2D(graphics, backBufferCreateInfo, swapchainImages[i]);
|
||||
|
||||
VkClearColorValue clearColor;
|
||||
std::memset(&clearColor, 0, sizeof(VkClearColorValue));
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "WindowManager.h"
|
||||
#include "Vulkan/VulkanGraphics.h"
|
||||
|
||||
Gfx::PGraphics WindowManager::graphics;
|
||||
|
||||
Seele::WindowManager::WindowManager()
|
||||
{
|
||||
graphics = new Vulkan::Graphics();
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
PWindow addWindow(const WindowCreateInfo &createInfo);
|
||||
void beginFrame();
|
||||
void endFrame();
|
||||
Gfx::PGraphics getGraphics()
|
||||
static Gfx::PGraphics getGraphics()
|
||||
{
|
||||
return graphics;
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
|
||||
private:
|
||||
Array<PWindow> windows;
|
||||
Gfx::PGraphics graphics;
|
||||
static Gfx::PGraphics graphics;
|
||||
};
|
||||
DEFINE_REF(WindowManager);
|
||||
} // namespace Seele
|
||||
Reference in New Issue
Block a user