Refactoring graphics

This commit is contained in:
Dynamitos
2023-10-26 18:37:29 +02:00
parent 28e5c9ff01
commit 1ca861459c
113 changed files with 3131 additions and 3221 deletions
@@ -1,6 +1,6 @@
#include "VulkanAllocator.h"
#include "VulkanGraphics.h"
#include "VulkanInitializer.h"
#include "Allocator.h"
#include "Graphics.h"
#include "Initializer.h"
using namespace Seele::Vulkan;
@@ -1,6 +1,6 @@
#pragma once
#include "MinimalEngine.h"
#include "VulkanGraphicsEnums.h"
#include "Enums.h"
#include "Containers/Map.h"
#include "Containers/Array.h"
#include <mutex>
@@ -1,8 +1,4 @@
#include "VulkanGraphicsResources.h"
#include "VulkanInitializer.h"
#include "VulkanGraphics.h"
#include "VulkanCommandBuffer.h"
#include "VulkanAllocator.h"
#include "Buffer.h"
using namespace Seele;
using namespace Seele::Vulkan;
@@ -16,7 +12,7 @@ struct PendingBuffer
bool bWriteOnly;
};
static std::map<ShaderBuffer *, PendingBuffer> pendingBuffers;
static std::map<Vulkan::ShaderBuffer *, PendingBuffer> pendingBuffers;
ShaderBuffer::ShaderBuffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic)
: graphics(graphics)
+145
View File
@@ -0,0 +1,145 @@
#pragma once
#include "Graphics/Buffer.h"
#include "Graphics.h"
#include "Allocator.h"
namespace Seele
{
namespace Vulkan
{
class ShaderBuffer
{
public:
ShaderBuffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false);
virtual ~ShaderBuffer();
VkBuffer getHandle() const
{
return buffers[currentBuffer].buffer;
}
uint64 getSize() const
{
return size;
}
VkDeviceSize getOffset() const;
void advanceBuffer()
{
currentBuffer = (currentBuffer + 1) % numBuffers;
}
virtual void *lock(bool bWriteOnly = true);
virtual void *lockRegion(uint64 regionOffset, uint64 regionSize, bool bWriteOnly = true);
virtual void unlock();
protected:
struct BufferAllocation
{
VkBuffer buffer;
PSubAllocation allocation;
};
PGraphics graphics;
uint32 currentBuffer;
uint64 size;
Gfx::QueueType& owner;
BufferAllocation buffers[Gfx::numFramesBuffered];
uint32 numBuffers;
void executeOwnershipBarrier(Gfx::QueueType newOwner);
void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0;
virtual VkAccessFlags getSourceAccessMask() = 0;
virtual VkAccessFlags getDestAccessMask() = 0;
};
DEFINE_REF(ShaderBuffer)
DECLARE_REF(StagingBuffer)
class UniformBuffer : public Gfx::UniformBuffer, public ShaderBuffer
{
public:
UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &resourceData);
virtual ~UniformBuffer();
virtual bool updateContents(const BulkResourceData &resourceData);
virtual void* lock(bool bWriteOnly = true) override;
virtual void unlock() override;
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);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
private:
PStagingBuffer dedicatedStagingBuffer;
};
DEFINE_REF(UniformBuffer)
class ShaderBuffer : public Gfx::ShaderBuffer, public ShaderBuffer
{
public:
ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &resourceData);
virtual ~ShaderBuffer();
virtual bool updateContents(const BulkResourceData &resourceData);
virtual void* lock(bool bWriteOnly = true) override;
virtual void unlock() override;
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);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
private:
PStagingBuffer dedicatedStagingBuffer;
};
DEFINE_REF(ShaderBuffer)
class VertexBuffer : public Gfx::VertexBuffer, public ShaderBuffer
{
public:
VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData);
virtual ~VertexBuffer();
virtual void updateRegion(BulkResourceData update) override;
virtual void download(Array<uint8>& buffer) override;
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);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
};
DEFINE_REF(VertexBuffer)
class IndexBuffer : public Gfx::IndexBuffer, public ShaderBuffer
{
public:
IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData);
virtual ~IndexBuffer();
virtual void download(Array<uint8>& buffer) override;
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);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
};
DEFINE_REF(IndexBuffer)
}
}
+48 -42
View File
@@ -1,49 +1,55 @@
target_sources(Engine
PRIVATE
VulkanAllocator.h
VulkanAllocator.cpp
VulkanBuffer.cpp
VulkanCommandBuffer.h
VulkanCommandBuffer.cpp
VulkanFramebuffer.h
VulkanFramebuffer.cpp
VulkanGraphics.h
VulkanGraphics.cpp
VulkanGraphicsResources.h
VulkanGraphicsResources.cpp
VulkanDescriptorSets.h
VulkanDescriptorSets.cpp
VulkanGraphicsEnums.h
VulkanGraphicsEnums.cpp
VulkanInitializer.h
VulkanInitializer.cpp
VulkanRenderPass.h
VulkanRenderPass.cpp
VulkanPipeline.h
VulkanPipeline.cpp
VulkanPipelineCache.h
VulkanPipelineCache.cpp
VulkanShader.h
VulkanShader.cpp
VulkanTexture.cpp
VulkanQueue.h
VulkanQueue.cpp
VulkanViewport.cpp)
Allocator.h
Allocator.cpp
Buffer.h
Buffer.cpp
CommandBuffer.h
CommandBuffer.cpp
DescriptorSets.h
DescriptorSets.cpp
Enums.h
Enums.cpp
Framebuffer.h
Framebuffer.cpp
Graphics.h
Graphics.cpp
Initializer.h
Initializer.cpp
Pipeline.h
Pipeline.cpp
PipelineCache.h
PipelineCache.cpp
Queue.h
Queue.cpp
RenderPass.h
RenderPass.cpp
RenderTarget.h
RenderTarget.cpp
Resources.h
Resources.cpp
Shader.h
Shader.cpp
Texture.h
Texture.cpp)
target_sources(Engine
PUBLIC FILE_SET HEADERS
FILES
VulkanAllocator.h
VulkanCommandBuffer.h
VulkanFramebuffer.h
VulkanGraphics.h
VulkanGraphicsResources.h
VulkanDescriptorSets.h
VulkanGraphicsEnums.h
VulkanInitializer.h
VulkanRenderPass.h
VulkanPipeline.h
VulkanPipelineCache.h
VulkanShader.h
VulkanQueue.h)
Allocator.h
Buffer.h
CommandBuffer.h
DescriptorSets.h
Enums.h
Framebuffer.h
Graphics.h
Initializer.h
Pipeline.h
PipelineCache.h
Queue.h
RenderPass.h
RenderTarget.h
Resources.h
Shader.h
Texture.h)
@@ -1,13 +1,12 @@
#include "VulkanCommandBuffer.h"
#include "VulkanInitializer.h"
#include "VulkanGraphics.h"
#include "VulkanPipeline.h"
#include "VulkanGraphicsEnums.h"
#include "VulkanFramebuffer.h"
#include "VulkanRenderPass.h"
#include "VulkanPipeline.h"
#include "VulkanDescriptorSets.h"
#include "Graphics/MeshBatch.h"
#include "CommandBuffer.h"
#include "Initializer.h"
#include "Graphics.h"
#include "Pipeline.h"
#include "Enums.h"
#include "Framebuffer.h"
#include "RenderPass.h"
#include "Pipeline.h"
#include "DescriptorSets.h"
using namespace Seele;
using namespace Seele::Vulkan;
@@ -1,6 +1,7 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "VulkanQueue.h"
#include "Queue.h"
#include "DescriptorSets.h"
#include "Buffer.h"
namespace Seele
{
@@ -87,7 +88,7 @@ public:
virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) override;
virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override;
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets) override;
virtual void bindVertexBuffer(const Array<VertexInputStream>& streams) override;
virtual void bindVertexBuffer(const Array<PVertexBuffer>& buffers) override;
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
virtual void pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) override;
virtual void draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) override;
@@ -1,9 +1,7 @@
#include "VulkanDescriptorSets.h"
#include "VulkanGraphicsResources.h"
#include "VulkanGraphicsEnums.h"
#include "VulkanGraphics.h"
#include "VulkanInitializer.h"
#include "VulkanCommandBuffer.h"
#include "DescriptorSets.h"
#include "Graphics.h"
#include "Initializer.h"
#include "CommandBuffer.h"
using namespace Seele;
using namespace Seele::Vulkan;
@@ -1,5 +1,8 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "Enums.h"
#include "Graphics/Descriptor.h"
#include "Containers/List.h"
#include "Resources.h"
namespace Seele
{
@@ -1,5 +1,5 @@
#pragma once
#include "Graphics/GraphicsEnums.h"
#include "Graphics/Enums.h"
#include <vulkan/vulkan.h>
#include <iostream>
@@ -25,11 +25,10 @@ namespace Vulkan
enum class ShaderType
{
VERTEX = 0,
CONTROL = 1,
EVALUATION = 2,
GEOMETRY = 3,
FRAGMENT = 4,
COMPUTE = 5,
FRAGMENT = 1,
COMPUTE = 2,
TASK = 3,
MESH = 4,
};
VkDescriptorType cast(const Gfx::SeDescriptorType &descriptorType);
@@ -1,8 +1,9 @@
#include "VulkanFramebuffer.h"
#include "VulkanGraphicsEnums.h"
#include "VulkanInitializer.h"
#include "VulkanRenderPass.h"
#include "VulkanGraphics.h"
#include "Framebuffer.h"
#include "Enums.h"
#include "Initializer.h"
#include "RenderPass.h"
#include "Graphics.h"
#include "Texture.h"
using namespace Seele;
using namespace Seele::Vulkan;
@@ -1,5 +1,7 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "Enums.h"
#include "Graphics.h"
#include "Graphics/RenderTarget.h"
namespace Seele
{
@@ -1,5 +1,5 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "Enums.h"
#include "Graphics/Graphics.h"
namespace Seele
@@ -14,6 +14,9 @@ DECLARE_REF(RenderPass)
DECLARE_REF(Framebuffer)
DECLARE_REF(RenderCommand)
DECLARE_REF(PipelineCache)
DECLARE_REF(Window)
DECLARE_REF(RenderTargetLayout)
DECLARE_REF(Viewport)
class Graphics : public Gfx::Graphics
{
public:
@@ -55,13 +58,13 @@ public:
virtual Gfx::PComputeCommand createComputeCommand(const std::string& name) override;
virtual Gfx::PVertexDeclaration createVertexDeclaration(const Array<Gfx::VertexElement>& element) 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::PComputeShader createComputeShader(const ShaderCreateInfo& createInfo) override;
virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override;
virtual Gfx::PComputePipeline createComputePipeline(const ComputePipelineCreateInfo& createInfo) override;
virtual Gfx::PTaskShader createTaskShader(const ShaderCreateInfo& createInfo) override;
virtual Gfx::PMeshShader createMeshShader(const ShaderCreateInfo& createInfo) override;
virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const Gfx::LegacyPipelineCreateInfo& createInfo) override;
virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const Gfx::MeshPipelineCreateInfo& createInfo) override;
virtual Gfx::PComputePipeline createComputePipeline(const Gfx::ComputePipelineCreateInfo& createInfo) override;
virtual Gfx::PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) override;
virtual Gfx::PDescriptorLayout createDescriptorLayout(const std::string& name = "") override;
@@ -1,4 +1,4 @@
#include "VulkanInitializer.h"
#include "Initializer.h"
#include <iostream>
using namespace Seele::Vulkan;
@@ -1,12 +1,12 @@
#include "VulkanPipeline.h"
#include "VulkanDescriptorSets.h"
#include "VulkanGraphics.h"
#include "Pipeline.h"
#include "DescriptorSets.h"
#include "Graphics.h"
using namespace Seele;
using namespace Seele::Vulkan;
GraphicsPipeline::GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo)
: Gfx::GraphicsPipeline(createInfo, pipelineLayout)
GraphicsPipeline::GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout)
: Gfx::GraphicsPipeline(pipelineLayout)
, graphics(graphics)
, pipeline(handle)
{
@@ -26,8 +26,8 @@ VkPipelineLayout GraphicsPipeline::getLayout() const
return layout.cast<PipelineLayout>()->getHandle();
}
ComputePipeline::ComputePipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const ComputePipelineCreateInfo& createInfo)
: Gfx::ComputePipeline(createInfo, pipelineLayout)
ComputePipeline::ComputePipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout)
: Gfx::ComputePipeline(pipelineLayout)
, graphics(graphics)
, pipeline(handle)
{
@@ -1,5 +1,6 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "Enums.h"
#include "Graphics/Resources.h"
namespace Seele
{
@@ -10,7 +11,7 @@ DECLARE_REF(Graphics)
class GraphicsPipeline : public Gfx::GraphicsPipeline
{
public:
GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo);
GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout);
virtual ~GraphicsPipeline();
void bind(VkCommandBuffer handle);
VkPipelineLayout getLayout() const;
@@ -22,7 +23,7 @@ DEFINE_REF(GraphicsPipeline)
class ComputePipeline : public Gfx::ComputePipeline
{
public:
ComputePipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const ComputePipelineCreateInfo& createInfo);
ComputePipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout);
virtual ~ComputePipeline();
void bind(VkCommandBuffer handle);
VkPipelineLayout getLayout() const;
@@ -0,0 +1,393 @@
#include "PipelineCache.h"
#include "Graphics.h"
#include "Enums.h"
#include "Initializer.h"
#include "RenderPass.h"
#include "DescriptorSets.h"
#include "Shader.h"
#include <fstream>
using namespace Seele;
using namespace Seele::Vulkan;
PipelineCache::PipelineCache(PGraphics graphics, const std::string& cacheFilePath)
: graphics(graphics)
, cacheFile(cacheFilePath)
{
std::ifstream stream(cacheFilePath, std::ios::binary | std::ios::ate);
VkPipelineCacheCreateInfo cacheCreateInfo;
cacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
cacheCreateInfo.pNext = nullptr;
cacheCreateInfo.flags = 0;
cacheCreateInfo.initialDataSize = 0;
if(stream.good())
{
Array<uint8> cacheData;
uint32 fileSize = static_cast<uint32>(stream.tellg());
cacheData.resize(fileSize);
stream.seekg(0);
stream.read((char*)cacheData.data(), fileSize);
cacheCreateInfo.initialDataSize = fileSize;
cacheCreateInfo.pInitialData = cacheData.data();
std::cout << "Loaded " << fileSize << " bytes from pipeline cache" << std::endl;
}
VK_CHECK(vkCreatePipelineCache(graphics->getDevice(), &cacheCreateInfo, nullptr, &cache));
}
PipelineCache::~PipelineCache()
{
VkDeviceSize cacheSize;
vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, nullptr);
Array<uint8> cacheData;
vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, cacheData.data());
std::ofstream stream(cacheFile, std::ios::binary);
stream.write((char*)cacheData.data(), cacheSize);
stream.flush();
stream.close();
vkDestroyPipelineCache(graphics->getDevice(), cache, nullptr);
std::cout << "Written " << cacheSize << " bytes to cache" << std::endl;
}
PGraphicsPipeline PipelineCache::createPipeline(const Gfx::LegacyPipelineCreateInfo& gfxInfo)
{
uint32 stageCount = 0;
VkPipelineShaderStageCreateInfo stageInfos[2];
std::memset(stageInfos, 0, sizeof(stageInfos));
PVertexShader vertexShader = gfxInfo.vertexShader.cast<VertexShader>();
stageInfos[stageCount++] = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_VERTEX_BIT,
.module = vertexShader->getModuleHandle(),
.pName = vertexShader->getEntryPointName(),
};
if(gfxInfo.fragmentShader != nullptr)
{
PFragmentShader fragment = gfxInfo.fragmentShader.cast<FragmentShader>();
stageInfos[stageCount++] = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = fragment->getModuleHandle(),
.pName = fragment->getEntryPointName(),
};
}
VkPipelineVertexInputStateCreateInfo vertexInput =
init::PipelineVertexInputStateCreateInfo();
Array<VkVertexInputBindingDescription> bindings;
Array<VkVertexInputAttributeDescription> attributes;
if (gfxInfo.vertexDeclaration != nullptr)
{
PVertexDeclaration decl = gfxInfo.vertexDeclaration.cast<VertexDeclaration>();
for (const auto& elem : decl->elementList)
{
attributes.add(VkVertexInputAttributeDescription{
.location = elem.attributeIndex,
.binding = elem.binding,
.format = cast(elem.vertexFormat),
.offset = elem.offset,
});
auto res = bindings.find([elem](const VkVertexInputBindingDescription& b) {return b.binding == elem.binding; });
if (res == bindings.end())
{
bindings.add({});
res = bindings.end();
}
*res = VkVertexInputBindingDescription{
.binding = elem.binding,
.stride = elem.stride,
.inputRate = elem.bInstanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX,
};
}
vertexInput.pVertexAttributeDescriptions = attributes.data();
vertexInput.vertexAttributeDescriptionCount = attributes.size();
vertexInput.pVertexBindingDescriptions = bindings.data();
vertexInput.vertexBindingDescriptionCount = bindings.size();
}
VkPipelineInputAssemblyStateCreateInfo assemblyInfo =
init::PipelineInputAssemblyStateCreateInfo(
cast(gfxInfo.topology),
0,
false
);
VkPipelineViewportStateCreateInfo viewportInfo =
init::PipelineViewportStateCreateInfo(
1,
1,
0
);
VkPipelineRasterizationStateCreateInfo rasterizationState =
init::PipelineRasterizationStateCreateInfo(
cast(gfxInfo.rasterizationState.polygonMode),
gfxInfo.rasterizationState.cullMode,
(VkFrontFace)gfxInfo.rasterizationState.frontFace,
0
);
rasterizationState.depthBiasEnable = gfxInfo.rasterizationState.depthBiasEnable;
rasterizationState.depthBiasClamp = gfxInfo.rasterizationState.depthBiasClamp;
rasterizationState.depthBiasConstantFactor = gfxInfo.rasterizationState.depthBoasConstantFactor;
rasterizationState.depthBiasSlopeFactor = gfxInfo.rasterizationState.depthBiasSlopeFactor;
rasterizationState.depthClampEnable = gfxInfo.rasterizationState.depthClampEnable;
rasterizationState.lineWidth = gfxInfo.rasterizationState.lineWidth;
rasterizationState.rasterizerDiscardEnable = gfxInfo.rasterizationState.rasterizerDiscardEnable;
VkPipelineMultisampleStateCreateInfo multisampleState =
init::PipelineMultisampleStateCreateInfo(
(VkSampleCountFlagBits)gfxInfo.multisampleState.samples,
0);
multisampleState.alphaToCoverageEnable = gfxInfo.multisampleState.alphaCoverageEnable;
multisampleState.alphaToOneEnable = gfxInfo.multisampleState.alphaToOneEnable;
multisampleState.minSampleShading = gfxInfo.multisampleState.minSampleShading;
multisampleState.sampleShadingEnable = gfxInfo.multisampleState.sampleShadingEnable;
VkPipelineDepthStencilStateCreateInfo depthStencilState =
init::PipelineDepthStencilStateCreateInfo(
gfxInfo.depthStencilState.depthTestEnable,
gfxInfo.depthStencilState.depthWriteEnable,
cast(gfxInfo.depthStencilState.depthCompareOp)
);
const auto& colorAttachments = gfxInfo.renderPass->getLayout()->colorAttachments;
Array<VkPipelineColorBlendAttachmentState> blendAttachments(colorAttachments.size());
for(uint32 i = 0; i < colorAttachments.size(); ++i)
{
const Gfx::ColorBlendState::BlendAttachment& attachment = gfxInfo.colorBlend.blendAttachments[i];
blendAttachments[i] = {
.blendEnable = attachment.blendEnable,
.srcColorBlendFactor = (VkBlendFactor)attachment.srcColorBlendFactor,
.dstColorBlendFactor = (VkBlendFactor)attachment.dstColorBlendFactor,
.colorBlendOp = (VkBlendOp)attachment.colorBlendOp,
.srcAlphaBlendFactor = (VkBlendFactor)attachment.srcAlphaBlendFactor,
.dstAlphaBlendFactor = (VkBlendFactor)attachment.dstAlphaBlendFactor,
.alphaBlendOp = (VkBlendOp)attachment.alphaBlendOp,
.colorWriteMask = attachment.colorWriteMask,
};
}
VkPipelineColorBlendStateCreateInfo blendState =
init::PipelineColorBlendStateCreateInfo(
(uint32)blendAttachments.size(),
blendAttachments.data()
);
blendState.logicOpEnable = gfxInfo.colorBlend.logicOpEnable;
blendState.logicOp = (VkLogicOp)gfxInfo.colorBlend.logicOp;
std::memcpy(blendState.blendConstants, gfxInfo.colorBlend.blendConstants, sizeof(gfxInfo.colorBlend.blendConstants));
uint32 numDynamicEnabled = 0;
StaticArray<VkDynamicState, 2> dynamicEnabled;
dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_VIEWPORT;
dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_SCISSOR;
VkPipelineDynamicStateCreateInfo dynamicState =
init::PipelineDynamicStateCreateInfo(
dynamicEnabled.data(),
numDynamicEnabled,
0
);
PPipelineLayout layout = gfxInfo.pipelineLayout.cast<PipelineLayout>();
VkPipeline pipelineHandle;
VkGraphicsPipelineCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = 0,
.flags = 0,
.stageCount = stageCount,
.pStages = stageInfos,
.pVertexInputState = &vertexInput,
.pInputAssemblyState = &assemblyInfo,
.pViewportState = &viewportInfo,
.pRasterizationState = &rasterizationState,
.pMultisampleState = &multisampleState,
.pDepthStencilState = &depthStencilState,
.pColorBlendState = &blendState,
.pDynamicState = &dynamicState,
.layout = layout->getHandle(),
.renderPass = gfxInfo.renderPass.cast<RenderPass>()->getHandle(),
.subpass = 0,
};
auto beginTime = std::chrono::high_resolution_clock::now();
VK_CHECK(vkCreateGraphicsPipelines(graphics->getDevice(), cache, 1, &createInfo, nullptr, &pipelineHandle));
auto endTime = std::chrono::high_resolution_clock::now();
int64 delta = std::chrono::duration_cast<std::chrono::microseconds>(endTime - beginTime).count();
std::cout << "Gfx creation time: " << delta << std::endl;
PGraphicsPipeline result = new GraphicsPipeline(graphics, pipelineHandle, layout);
return result;
}
PGraphicsPipeline PipelineCache::createPipeline(const Gfx::MeshPipelineCreateInfo& gfxInfo)
{
uint32 stageCount = 0;
VkPipelineShaderStageCreateInfo stageInfos[3];
std::memset(stageInfos, 0, sizeof(stageInfos));
if (gfxInfo.taskShader != nullptr)
{
PTaskShader taskShader = gfxInfo.taskShader.cast<TaskShader>();
stageInfos[stageCount++] = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_TASK_BIT_EXT,
.module = taskShader->getModuleHandle(),
.pName = taskShader->getEntryPointName(),
};
}
PMeshShader meshShader = gfxInfo.meshShader.cast<MeshShader>();
stageInfos[stageCount++] = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_MESH_BIT_EXT,
.module = meshShader->getModuleHandle(),
.pName = meshShader->getEntryPointName(),
};
if (gfxInfo.fragmentShader != nullptr)
{
PFragmentShader fragment = gfxInfo.fragmentShader.cast<FragmentShader>();
stageInfos[stageCount++] = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
.module = fragment->getModuleHandle(),
.pName = fragment->getEntryPointName(),
};
}
VkPipelineViewportStateCreateInfo viewportInfo =
init::PipelineViewportStateCreateInfo(
1,
1,
0
);
VkPipelineRasterizationStateCreateInfo rasterizationState =
init::PipelineRasterizationStateCreateInfo(
cast(gfxInfo.rasterizationState.polygonMode),
gfxInfo.rasterizationState.cullMode,
(VkFrontFace)gfxInfo.rasterizationState.frontFace,
0
);
rasterizationState.depthBiasEnable = gfxInfo.rasterizationState.depthBiasEnable;
rasterizationState.depthBiasClamp = gfxInfo.rasterizationState.depthBiasClamp;
rasterizationState.depthBiasConstantFactor = gfxInfo.rasterizationState.depthBoasConstantFactor;
rasterizationState.depthBiasSlopeFactor = gfxInfo.rasterizationState.depthBiasSlopeFactor;
rasterizationState.depthClampEnable = gfxInfo.rasterizationState.depthClampEnable;
rasterizationState.lineWidth = gfxInfo.rasterizationState.lineWidth;
rasterizationState.rasterizerDiscardEnable = gfxInfo.rasterizationState.rasterizerDiscardEnable;
VkPipelineMultisampleStateCreateInfo multisampleState =
init::PipelineMultisampleStateCreateInfo(
(VkSampleCountFlagBits)gfxInfo.multisampleState.samples,
0);
multisampleState.alphaToCoverageEnable = gfxInfo.multisampleState.alphaCoverageEnable;
multisampleState.alphaToOneEnable = gfxInfo.multisampleState.alphaToOneEnable;
multisampleState.minSampleShading = gfxInfo.multisampleState.minSampleShading;
multisampleState.sampleShadingEnable = gfxInfo.multisampleState.sampleShadingEnable;
VkPipelineDepthStencilStateCreateInfo depthStencilState =
init::PipelineDepthStencilStateCreateInfo(
gfxInfo.depthStencilState.depthTestEnable,
gfxInfo.depthStencilState.depthWriteEnable,
cast(gfxInfo.depthStencilState.depthCompareOp)
);
const auto& colorAttachments = gfxInfo.renderPass->getLayout()->colorAttachments;
Array<VkPipelineColorBlendAttachmentState> blendAttachments(colorAttachments.size());
for (uint32 i = 0; i < colorAttachments.size(); ++i)
{
const Gfx::ColorBlendState::BlendAttachment& attachment = gfxInfo.colorBlend.blendAttachments[i];
blendAttachments[i] = {
.blendEnable = attachment.blendEnable,
.srcColorBlendFactor = (VkBlendFactor)attachment.srcColorBlendFactor,
.dstColorBlendFactor = (VkBlendFactor)attachment.dstColorBlendFactor,
.colorBlendOp = (VkBlendOp)attachment.colorBlendOp,
.srcAlphaBlendFactor = (VkBlendFactor)attachment.srcAlphaBlendFactor,
.dstAlphaBlendFactor = (VkBlendFactor)attachment.dstAlphaBlendFactor,
.alphaBlendOp = (VkBlendOp)attachment.alphaBlendOp,
.colorWriteMask = attachment.colorWriteMask,
};
}
VkPipelineColorBlendStateCreateInfo blendState =
init::PipelineColorBlendStateCreateInfo(
(uint32)blendAttachments.size(),
blendAttachments.data()
);
blendState.logicOpEnable = gfxInfo.colorBlend.logicOpEnable;
blendState.logicOp = (VkLogicOp)gfxInfo.colorBlend.logicOp;
std::memcpy(blendState.blendConstants, gfxInfo.colorBlend.blendConstants, sizeof(gfxInfo.colorBlend.blendConstants));
uint32 numDynamicEnabled = 0;
StaticArray<VkDynamicState, 2> dynamicEnabled;
dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_VIEWPORT;
dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_SCISSOR;
VkPipelineDynamicStateCreateInfo dynamicState =
init::PipelineDynamicStateCreateInfo(
dynamicEnabled.data(),
numDynamicEnabled,
0
);
PPipelineLayout layout = gfxInfo.pipelineLayout.cast<PipelineLayout>();
VkPipeline pipelineHandle;
VkGraphicsPipelineCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
.pNext = 0,
.flags = 0,
.stageCount = stageCount,
.pStages = stageInfos,
.pVertexInputState = nullptr,
.pInputAssemblyState = nullptr,
.pViewportState = &viewportInfo,
.pRasterizationState = &rasterizationState,
.pMultisampleState = &multisampleState,
.pDepthStencilState = &depthStencilState,
.pColorBlendState = &blendState,
.pDynamicState = &dynamicState,
.layout = layout->getHandle(),
.renderPass = gfxInfo.renderPass.cast<RenderPass>()->getHandle(),
.subpass = 0,
};
auto beginTime = std::chrono::high_resolution_clock::now();
VK_CHECK(vkCreateGraphicsPipelines(graphics->getDevice(), cache, 1, &createInfo, nullptr, &pipelineHandle));
auto endTime = std::chrono::high_resolution_clock::now();
int64 delta = std::chrono::duration_cast<std::chrono::microseconds>(endTime - beginTime).count();
std::cout << "Gfx creation time: " << delta << std::endl;
PGraphicsPipeline result = new GraphicsPipeline(graphics, pipelineHandle, layout);
return result;
}
PComputePipeline PipelineCache::createPipeline(const Gfx::ComputePipelineCreateInfo& computeInfo)
{
VkComputePipelineCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
createInfo.pNext = 0;
createInfo.flags = 0;
createInfo.basePipelineIndex = 0;
createInfo.basePipelineHandle = VK_NULL_HANDLE;
auto layout = computeInfo.pipelineLayout.cast<PipelineLayout>();
createInfo.layout = layout->getHandle();
auto computeStage = computeInfo.computeShader.cast<ComputeShader>();
createInfo.stage = init::PipelineShaderStageCreateInfo(
VK_SHADER_STAGE_COMPUTE_BIT,
computeStage->getModuleHandle(),
computeStage->getEntryPointName());
VkPipeline pipelineHandle;
auto beginTime = std::chrono::high_resolution_clock::now();
VK_CHECK(vkCreateComputePipelines(graphics->getDevice(), cache, 1, &createInfo, nullptr, &pipelineHandle));
auto endTime = std::chrono::high_resolution_clock::now();
int64 delta = std::chrono::duration_cast<std::chrono::microseconds>(endTime - beginTime).count();
std::cout << "Compute creation time: " << delta << std::endl;
PComputePipeline result = new ComputePipeline(graphics, pipelineHandle, layout);
return result;
}
@@ -1,5 +1,5 @@
#pragma once
#include "VulkanPipeline.h"
#include "Pipeline.h"
namespace Seele
{
@@ -10,14 +10,13 @@ class PipelineCache
public:
PipelineCache(PGraphics graphics, const std::string& cacheFilePath);
~PipelineCache();
PGraphicsPipeline createPipeline(const GraphicsPipelineCreateInfo& createInfo);
PComputePipeline createPipeline(const ComputePipelineCreateInfo& createInfo);
PGraphicsPipeline createPipeline(const Gfx::LegacyPipelineCreateInfo& createInfo);
PGraphicsPipeline createPipeline(const Gfx::MeshPipelineCreateInfo& createInfo);
PComputePipeline createPipeline(const Gfx::ComputePipelineCreateInfo& createInfo);
private:
VkPipelineCache cache;
PGraphics graphics;
std::string cacheFile;
std::mutex createdPipelinesLock;
Map<uint32, VkPipeline> createdPipelines;
};
DEFINE_REF(PipelineCache)
} // namespace Vulkan
@@ -1,9 +1,8 @@
#include "VulkanQueue.h"
#include "VulkanInitializer.h"
#include "VulkanGraphics.h"
#include "VulkanAllocator.h"
#include "VulkanCommandBuffer.h"
#include "VulkanGraphicsEnums.h"
#include "Queue.h"
#include "Initializer.h"
#include "Graphics.h"
#include "Allocator.h"
#include "CommandBuffer.h"
using namespace Seele;
using namespace Seele::Vulkan;
@@ -1,5 +1,5 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "Resources.h"
namespace Seele
{
@@ -1,8 +1,8 @@
#include "VulkanRenderPass.h"
#include "VulkanInitializer.h"
#include "VulkanGraphicsEnums.h"
#include "VulkanGraphics.h"
#include "VulkanFramebuffer.h"
#include "RenderPass.h"
#include "Initializer.h"
#include "Graphics.h"
#include "Framebuffer.h"
#include "Texture.h"
using namespace Seele;
using namespace Seele::Vulkan;
@@ -1,5 +1,6 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "Graphics/RenderTarget.h"
#include "Graphics.h"
namespace Seele
{
+83
View File
@@ -0,0 +1,83 @@
#pragma once
#include "Graphics/RenderTarget.h"
#include "Graphics.h"
#include "Texture.h"
#include "Resources.h"
namespace Seele
{
namespace Vulkan
{
class Window : public Gfx::Window
{
public:
Window(PGraphics graphics, const WindowCreateInfo &createInfo);
virtual ~Window();
virtual void beginFrame() override;
virtual void endFrame() override;
virtual Gfx::PTexture2D getBackBuffer() const override;
virtual void onWindowCloseEvent() override;
virtual void setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) override;
virtual void setMouseMoveCallback(std::function<void(double, double)> callback) override;
virtual void setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) override;
virtual void setScrollCallback(std::function<void(double, double)> callback) override;
virtual void setFileCallback(std::function<void(int, const char**)> callback) override;
virtual void setCloseCallback(std::function<void()> callback);
VkFormat getPixelFormat() const
{
return cast(windowState.pixelFormat);
}
std::function<void(KeyCode, InputAction, KeyModifier)> keyCallback;
std::function<void(double, double)> mouseMoveCallback;
std::function<void(MouseButton, InputAction, KeyModifier)> mouseButtonCallback;
std::function<void(double, double)> scrollCallback;
std::function<void(int, const char**)> fileCallback;
std::function<void()> closeCallback;
protected:
void advanceBackBuffer();
void recreateSwapchain(const WindowCreateInfo &createInfo);
void present();
void destroySwapchain();
void createSwapchain();
void chooseSurfaceFormat(const Array<VkSurfaceFormatKHR> &available, Gfx::SeFormat preferred);
void choosePresentMode(const Array<VkPresentModeKHR> &modes);
PTexture2D backBufferImages[Gfx::numFramesBuffered];
PSemaphore renderFinished[Gfx::numFramesBuffered];
PSemaphore imageAcquired[Gfx::numFramesBuffered];
PSemaphore imageAcquiredSemaphore;
PGraphics graphics;
VkInstance instance;
VkSwapchainKHR swapchain;
VkSampleCountFlags numSamples;
VkPresentModeKHR presentMode;
VkSurfaceKHR surface;
VkSurfaceFormatKHR surfaceFormat;
void *windowHandle;
int32 currentImageIndex;
int32 acquiredImageIndex;
int32 preAcquiredImageIndex;
int32 semaphoreIndex;
};
DEFINE_REF(Window)
class Viewport : public Gfx::Viewport
{
public:
Viewport(PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo);
virtual ~Viewport();
virtual void resize(uint32 newX, uint32 newY);
virtual void move(uint32 newOffsetX, uint32 newOffsetY);
VkViewport getHandle() const { return handle; }
private:
VkViewport handle;
PGraphics graphics;
friend class Graphics;
};
DECLARE_REF(Viewport)
}
}
+80
View File
@@ -0,0 +1,80 @@
#pragma once
#include <vulkan/vulkan.h>
#include <functional>
#include "Graphics/Resources.h"
#include "Allocator.h"
namespace Seele
{
namespace Vulkan
{
DECLARE_REF(DescriptorAllocator)
DECLARE_REF(CommandBufferManager)
DECLARE_REF(CmdBuffer)
DECLARE_REF(Graphics)
DECLARE_REF(SubAllocation)
class Semaphore
{
public:
Semaphore(PGraphics graphics);
virtual ~Semaphore();
inline VkSemaphore getHandle() const
{
return handle;
}
private:
VkSemaphore handle;
PGraphics graphics;
};
DEFINE_REF(Semaphore)
class Fence
{
public:
Fence(PGraphics graphics);
~Fence();
bool isSignaled();
void reset();
inline VkFence getHandle() const
{
return fence;
}
void wait(uint32 timeout);
/*Event& operator co_await()
{
return signaled;
}*/
bool operator<(const Fence &other) const
{
return fence < other.fence;
}
private:
PGraphics graphics;
bool signaled;
VkFence fence;
};
DEFINE_REF(Fence)
class VertexDeclaration : public Gfx::VertexDeclaration
{
public:
Array<Gfx::VertexElement> elementList;
VertexDeclaration(const Array<Gfx::VertexElement>& elementList);
virtual ~VertexDeclaration();
private:
};
DEFINE_REF(VertexDeclaration)
class SamplerState : public Gfx::SamplerState
{
public:
VkSampler sampler;
};
DEFINE_REF(SamplerState)
} // namespace Vulkan
} // namespace Seele
@@ -1,6 +1,7 @@
#pragma once
#include "VulkanGraphicsResources.h"
#include "VulkanGraphicsEnums.h"
#include "Resources.h"
#include "Enums.h"
#include "Graphics/Shader.h"
namespace Seele
{
@@ -51,18 +52,16 @@ public:
}
};
typedef ShaderBase<Gfx::VertexShader, ShaderType::VERTEX, VK_SHADER_STAGE_VERTEX_BIT> VertexShader;
typedef ShaderBase<Gfx::ControlShader, ShaderType::CONTROL, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT> ControlShader;
typedef ShaderBase<Gfx::EvaluationShader, ShaderType::EVALUATION, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT> EvaluationShader;
typedef ShaderBase<Gfx::GeometryShader, ShaderType::GEOMETRY, VK_SHADER_STAGE_GEOMETRY_BIT> GeometryShader;
typedef ShaderBase<Gfx::FragmentShader, ShaderType::FRAGMENT, VK_SHADER_STAGE_FRAGMENT_BIT> FragmentShader;
typedef ShaderBase<Gfx::ComputeShader, ShaderType::COMPUTE, VK_SHADER_STAGE_COMPUTE_BIT> ComputeShader;
typedef ShaderBase<Gfx::TaskShader, ShaderType::TASK, VK_SHADER_STAGE_TASK_BIT_EXT> TaskShader;
typedef ShaderBase<Gfx::MeshShader, ShaderType::MESH, VK_SHADER_STAGE_MESH_BIT_EXT> MeshShader;
DEFINE_REF(VertexShader)
DEFINE_REF(ControlShader)
DEFINE_REF(EvaluationShader)
DEFINE_REF(GeometryShader)
DEFINE_REF(FragmentShader)
DEFINE_REF(ComputeShader)
DEFINE_REF(TaskShader)
DEFINE_REF(MeshShader)
} // namespace Vulkan
}
+264
View File
@@ -0,0 +1,264 @@
#pragma once
#include "Graphics/Texture.h"
#include "Graphics.h"
#include "Allocator.h"
namespace Seele
{
namespace Vulkan
{
class TextureHandle
{
public:
TextureHandle(PGraphics graphics, VkImageViewType viewType,
const TextureCreateInfo& createInfo, Gfx::QueueType& owner, VkImage existingImage = VK_NULL_HANDLE);
virtual ~TextureHandle();
inline VkImage getImage() const
{
return image;
}
inline VkImageView getView() const
{
return defaultView;
}
inline Gfx::SeImageLayout getLayout() const
{
return layout;
}
inline VkImageAspectFlags getAspect() const
{
return aspect;
}
inline VkImageUsageFlags getUsage() const
{
return usage;
}
inline Gfx::SeFormat getFormat() const
{
return format;
}
inline Gfx::SeSampleCountFlags getNumSamples() const
{
return samples;
}
inline uint32 getMipLevels() const
{
return mipLevels;
}
inline bool isDepthStencil() const
{
return aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
}
void executeOwnershipBarrier(Gfx::QueueType newOwner);
void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
void changeLayout(Gfx::SeImageLayout newLayout);
void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer);
private:
//Updates via reference
Gfx::QueueType& currentOwner;
PGraphics graphics;
PSubAllocation allocation;
uint32 sizeX;
uint32 sizeY;
uint32 sizeZ;
uint32 arrayCount;
uint32 layerCount;
uint32 mipLevels;
uint32 samples;
Gfx::SeFormat format;
Gfx::SeImageUsageFlags usage;
VkImage image;
VkImageView defaultView;
VkImageAspectFlags aspect;
Gfx::SeImageLayout layout;
friend class TextureBase;
friend class Texture2D;
friend class Texture3D;
friend class TextureCube;
friend class Graphics;
};
class TextureBase
{
public:
static TextureHandle* cast(Gfx::PTexture texture);
protected:
TextureHandle* textureHandle;
friend class Graphics;
};
DECLARE_REF(TextureBase)
class Texture2D : public Gfx::Texture2D, public TextureBase
{
public:
Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
virtual ~Texture2D();
virtual uint32 getSizeX() const override
{
return textureHandle->sizeX;
}
virtual uint32 getSizeY() const override
{
return textureHandle->sizeY;
}
virtual uint32 getSizeZ() const override
{
return textureHandle->sizeZ;
}
virtual Gfx::SeFormat getFormat() const override
{
return textureHandle->format;
}
virtual Gfx::SeSampleCountFlags getNumSamples() const override
{
return textureHandle->getNumSamples();
}
virtual uint32 getMipLevels() const override
{
return textureHandle->getMipLevels();
}
virtual void changeLayout(Gfx::SeImageLayout newLayout) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
virtual void* getNativeHandle() override
{
return textureHandle;
}
inline VkImage getHandle() const
{
return textureHandle->image;
}
inline VkImageView getView() const
{
return textureHandle->defaultView;
}
inline bool isDepthStencil() const
{
return textureHandle->isDepthStencil();
}
protected:
// Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
};
DEFINE_REF(Texture2D)
class Texture3D : public Gfx::Texture3D, public TextureBase
{
public:
Texture3D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
virtual ~Texture3D();
virtual uint32 getSizeX() const override
{
return textureHandle->sizeX;
}
virtual uint32 getSizeY() const override
{
return textureHandle->sizeY;
}
virtual uint32 getSizeZ() const override
{
return textureHandle->sizeZ;
}
virtual Gfx::SeFormat getFormat() const override
{
return textureHandle->format;
}
virtual Gfx::SeSampleCountFlags getNumSamples() const override
{
return textureHandle->getNumSamples();
}
virtual uint32 getMipLevels() const override
{
return textureHandle->getMipLevels();
}
virtual void changeLayout(Gfx::SeImageLayout newLayout) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
virtual void* getNativeHandle() override
{
return textureHandle;
}
inline VkImage getHandle() const
{
return textureHandle->image;
}
inline VkImageView getView() const
{
return textureHandle->defaultView;
}
inline bool isDepthStencil() const
{
return textureHandle->isDepthStencil();
}
protected:
// Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
};
DEFINE_REF(Texture3D)
class TextureCube : public Gfx::TextureCube, public TextureBase
{
public:
TextureCube(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
virtual ~TextureCube();
virtual uint32 getSizeX() const override
{
return textureHandle->sizeX;
}
virtual uint32 getSizeY() const override
{
return textureHandle->sizeY;
}
virtual uint32 getSizeZ() const override
{
return textureHandle->sizeZ;
}
virtual Gfx::SeFormat getFormat() const override
{
return textureHandle->format;
}
virtual Gfx::SeSampleCountFlags getNumSamples() const override
{
return textureHandle->getNumSamples();
}
virtual uint32 getMipLevels() const override
{
return textureHandle->getMipLevels();
}
virtual void changeLayout(Gfx::SeImageLayout newLayout) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
virtual void* getNativeHandle() override
{
return textureHandle;
}
inline VkImage getHandle() const
{
return textureHandle->image;
}
inline VkImageView getView() const
{
return textureHandle->defaultView;
}
inline bool isDepthStencil() const
{
return textureHandle->isDepthStencil();
}
protected:
// Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
};
DEFINE_REF(TextureCube)
}
}
@@ -1,535 +0,0 @@
#pragma once
#include <vulkan/vulkan.h>
#include <functional>
#include "Graphics/GraphicsResources.h"
#include "VulkanAllocator.h"
namespace Seele
{
namespace Vulkan
{
DECLARE_REF(DescriptorAllocator)
DECLARE_REF(CommandBufferManager)
DECLARE_REF(CmdBuffer)
DECLARE_REF(Graphics)
DECLARE_REF(SubAllocation)
class Semaphore
{
public:
Semaphore(PGraphics graphics);
virtual ~Semaphore();
inline VkSemaphore getHandle() const
{
return handle;
}
private:
VkSemaphore handle;
PGraphics graphics;
};
DEFINE_REF(Semaphore)
class Fence
{
public:
Fence(PGraphics graphics);
~Fence();
bool isSignaled();
void reset();
inline VkFence getHandle() const
{
return fence;
}
void wait(uint32 timeout);
/*Event& operator co_await()
{
return signaled;
}*/
bool operator<(const Fence &other) const
{
return fence < other.fence;
}
private:
PGraphics graphics;
bool signaled;
VkFence fence;
};
DEFINE_REF(Fence)
class VertexDeclaration : public Gfx::VertexDeclaration
{
public:
Array<Gfx::VertexElement> elementList;
VertexDeclaration(const Array<Gfx::VertexElement>& elementList);
virtual ~VertexDeclaration();
private:
};
DEFINE_REF(VertexDeclaration)
class ShaderBuffer
{
public:
ShaderBuffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false);
virtual ~ShaderBuffer();
VkBuffer getHandle() const
{
return buffers[currentBuffer].buffer;
}
uint64 getSize() const
{
return size;
}
VkDeviceSize getOffset() const;
void advanceBuffer()
{
currentBuffer = (currentBuffer + 1) % numBuffers;
}
virtual void *lock(bool bWriteOnly = true);
virtual void *lockRegion(uint64 regionOffset, uint64 regionSize, bool bWriteOnly = true);
virtual void unlock();
protected:
struct BufferAllocation
{
VkBuffer buffer;
PSubAllocation allocation;
};
PGraphics graphics;
uint32 currentBuffer;
uint64 size;
Gfx::QueueType& owner;
BufferAllocation buffers[Gfx::numFramesBuffered];
uint32 numBuffers;
void executeOwnershipBarrier(Gfx::QueueType newOwner);
void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0;
virtual VkAccessFlags getSourceAccessMask() = 0;
virtual VkAccessFlags getDestAccessMask() = 0;
};
DEFINE_REF(ShaderBuffer)
DECLARE_REF(StagingBuffer)
class UniformBuffer : public Gfx::UniformBuffer, public ShaderBuffer
{
public:
UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &resourceData);
virtual ~UniformBuffer();
virtual bool updateContents(const BulkResourceData &resourceData);
virtual void* lock(bool bWriteOnly = true) override;
virtual void unlock() override;
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);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
private:
PStagingBuffer dedicatedStagingBuffer;
};
DEFINE_REF(UniformBuffer)
class ShaderBuffer : public Gfx::ShaderBuffer, public ShaderBuffer
{
public:
ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo &resourceData);
virtual ~ShaderBuffer();
virtual bool updateContents(const BulkResourceData &resourceData);
virtual void* lock(bool bWriteOnly = true) override;
virtual void unlock() override;
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);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
private:
PStagingBuffer dedicatedStagingBuffer;
};
DEFINE_REF(ShaderBuffer)
class VertexBuffer : public Gfx::VertexBuffer, public ShaderBuffer
{
public:
VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData);
virtual ~VertexBuffer();
virtual void updateRegion(BulkResourceData update) override;
virtual void download(Array<uint8>& buffer) override;
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);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
};
DEFINE_REF(VertexBuffer)
class IndexBuffer : public Gfx::IndexBuffer, public ShaderBuffer
{
public:
IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData);
virtual ~IndexBuffer();
virtual void download(Array<uint8>& buffer) override;
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);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
};
DEFINE_REF(IndexBuffer)
class TextureHandle
{
public:
TextureHandle(PGraphics graphics, VkImageViewType viewType,
const TextureCreateInfo& createInfo, Gfx::QueueType& owner, VkImage existingImage = VK_NULL_HANDLE);
virtual ~TextureHandle();
inline VkImage getImage() const
{
return image;
}
inline VkImageView getView() const
{
return defaultView;
}
inline Gfx::SeImageLayout getLayout() const
{
return layout;
}
inline VkImageAspectFlags getAspect() const
{
return aspect;
}
inline VkImageUsageFlags getUsage() const
{
return usage;
}
inline Gfx::SeFormat getFormat() const
{
return format;
}
inline Gfx::SeSampleCountFlags getNumSamples() const
{
return samples;
}
inline uint32 getMipLevels() const
{
return mipLevels;
}
inline bool isDepthStencil() const
{
return aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
}
void executeOwnershipBarrier(Gfx::QueueType newOwner);
void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
void changeLayout(Gfx::SeImageLayout newLayout);
void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer);
private:
//Updates via reference
Gfx::QueueType& currentOwner;
PGraphics graphics;
PSubAllocation allocation;
uint32 sizeX;
uint32 sizeY;
uint32 sizeZ;
uint32 arrayCount;
uint32 layerCount;
uint32 mipLevels;
uint32 samples;
Gfx::SeFormat format;
Gfx::SeImageUsageFlags usage;
VkImage image;
VkImageView defaultView;
VkImageAspectFlags aspect;
Gfx::SeImageLayout layout;
friend class TextureBase;
friend class Texture2D;
friend class Texture3D;
friend class TextureCube;
friend class Graphics;
};
class TextureBase
{
public:
static TextureHandle* cast(Gfx::PTexture texture);
protected:
TextureHandle* textureHandle;
friend class Graphics;
};
DECLARE_REF(TextureBase)
class Texture2D : public Gfx::Texture2D, public TextureBase
{
public:
Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
virtual ~Texture2D();
virtual uint32 getSizeX() const override
{
return textureHandle->sizeX;
}
virtual uint32 getSizeY() const override
{
return textureHandle->sizeY;
}
virtual uint32 getSizeZ() const override
{
return textureHandle->sizeZ;
}
virtual Gfx::SeFormat getFormat() const override
{
return textureHandle->format;
}
virtual Gfx::SeSampleCountFlags getNumSamples() const override
{
return textureHandle->getNumSamples();
}
virtual uint32 getMipLevels() const override
{
return textureHandle->getMipLevels();
}
virtual void changeLayout(Gfx::SeImageLayout newLayout) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
virtual void* getNativeHandle() override
{
return textureHandle;
}
inline VkImage getHandle() const
{
return textureHandle->image;
}
inline VkImageView getView() const
{
return textureHandle->defaultView;
}
inline bool isDepthStencil() const
{
return textureHandle->isDepthStencil();
}
protected:
// Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
};
DEFINE_REF(Texture2D)
class Texture3D : public Gfx::Texture3D, public TextureBase
{
public:
Texture3D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
virtual ~Texture3D();
virtual uint32 getSizeX() const override
{
return textureHandle->sizeX;
}
virtual uint32 getSizeY() const override
{
return textureHandle->sizeY;
}
virtual uint32 getSizeZ() const override
{
return textureHandle->sizeZ;
}
virtual Gfx::SeFormat getFormat() const override
{
return textureHandle->format;
}
virtual Gfx::SeSampleCountFlags getNumSamples() const override
{
return textureHandle->getNumSamples();
}
virtual uint32 getMipLevels() const override
{
return textureHandle->getMipLevels();
}
virtual void changeLayout(Gfx::SeImageLayout newLayout) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
virtual void* getNativeHandle() override
{
return textureHandle;
}
inline VkImage getHandle() const
{
return textureHandle->image;
}
inline VkImageView getView() const
{
return textureHandle->defaultView;
}
inline bool isDepthStencil() const
{
return textureHandle->isDepthStencil();
}
protected:
// Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
};
DEFINE_REF(Texture3D)
class TextureCube : public Gfx::TextureCube, public TextureBase
{
public:
TextureCube(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
virtual ~TextureCube();
virtual uint32 getSizeX() const override
{
return textureHandle->sizeX;
}
virtual uint32 getSizeY() const override
{
return textureHandle->sizeY;
}
virtual uint32 getSizeZ() const override
{
return textureHandle->sizeZ;
}
virtual Gfx::SeFormat getFormat() const override
{
return textureHandle->format;
}
virtual Gfx::SeSampleCountFlags getNumSamples() const override
{
return textureHandle->getNumSamples();
}
virtual uint32 getMipLevels() const override
{
return textureHandle->getMipLevels();
}
virtual void changeLayout(Gfx::SeImageLayout newLayout) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
virtual void* getNativeHandle() override
{
return textureHandle;
}
inline VkImage getHandle() const
{
return textureHandle->image;
}
inline VkImageView getView() const
{
return textureHandle->defaultView;
}
inline bool isDepthStencil() const
{
return textureHandle->isDepthStencil();
}
protected:
// Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
virtual void executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage);
};
DEFINE_REF(TextureCube)
class SamplerState : public Gfx::SamplerState
{
public:
VkSampler sampler;
};
DEFINE_REF(SamplerState)
class Window : public Gfx::Window
{
public:
Window(PGraphics graphics, const WindowCreateInfo &createInfo);
virtual ~Window();
virtual void beginFrame() override;
virtual void endFrame() override;
virtual Gfx::PTexture2D getBackBuffer() const override;
virtual void onWindowCloseEvent() override;
virtual void setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) override;
virtual void setMouseMoveCallback(std::function<void(double, double)> callback) override;
virtual void setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) override;
virtual void setScrollCallback(std::function<void(double, double)> callback) override;
virtual void setFileCallback(std::function<void(int, const char**)> callback) override;
virtual void setCloseCallback(std::function<void()> callback);
VkFormat getPixelFormat() const
{
return cast(windowState.pixelFormat);
}
std::function<void(KeyCode, InputAction, KeyModifier)> keyCallback;
std::function<void(double, double)> mouseMoveCallback;
std::function<void(MouseButton, InputAction, KeyModifier)> mouseButtonCallback;
std::function<void(double, double)> scrollCallback;
std::function<void(int, const char**)> fileCallback;
std::function<void()> closeCallback;
protected:
void advanceBackBuffer();
void recreateSwapchain(const WindowCreateInfo &createInfo);
void present();
void destroySwapchain();
void createSwapchain();
void chooseSurfaceFormat(const Array<VkSurfaceFormatKHR> &available, Gfx::SeFormat preferred);
void choosePresentMode(const Array<VkPresentModeKHR> &modes);
PTexture2D backBufferImages[Gfx::numFramesBuffered];
PSemaphore renderFinished[Gfx::numFramesBuffered];
PSemaphore imageAcquired[Gfx::numFramesBuffered];
PSemaphore imageAcquiredSemaphore;
PGraphics graphics;
VkInstance instance;
VkSwapchainKHR swapchain;
VkSampleCountFlags numSamples;
VkPresentModeKHR presentMode;
VkSurfaceKHR surface;
VkSurfaceFormatKHR surfaceFormat;
void *windowHandle;
int32 currentImageIndex;
int32 acquiredImageIndex;
int32 preAcquiredImageIndex;
int32 semaphoreIndex;
};
DEFINE_REF(Window)
class Viewport : public Gfx::Viewport
{
public:
Viewport(PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo);
virtual ~Viewport();
virtual void resize(uint32 newX, uint32 newY);
virtual void move(uint32 newOffsetX, uint32 newOffsetY);
VkViewport getHandle() const { return handle; }
private:
VkViewport handle;
PGraphics graphics;
friend class Graphics;
};
DECLARE_REF(Viewport)
} // namespace Vulkan
} // namespace Seele
@@ -1,381 +0,0 @@
#include "VulkanPipelineCache.h"
#include "VulkanGraphics.h"
#include "VulkanGraphicsEnums.h"
#include "VulkanInitializer.h"
#include "VulkanRenderPass.h"
#include "VulkanDescriptorSets.h"
#include "VulkanShader.h"
#include <fstream>
using namespace Seele;
using namespace Seele::Vulkan;
PipelineCache::PipelineCache(PGraphics graphics, const std::string& cacheFilePath)
: graphics(graphics)
, cacheFile(cacheFilePath)
{
std::ifstream stream(cacheFilePath, std::ios::binary | std::ios::ate);
VkPipelineCacheCreateInfo cacheCreateInfo;
cacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
cacheCreateInfo.pNext = nullptr;
cacheCreateInfo.flags = 0;
cacheCreateInfo.initialDataSize = 0;
if(stream.good())
{
Array<uint8> cacheData;
uint32 fileSize = static_cast<uint32>(stream.tellg());
cacheData.resize(fileSize);
stream.seekg(0);
stream.read((char*)cacheData.data(), fileSize);
cacheCreateInfo.initialDataSize = fileSize;
cacheCreateInfo.pInitialData = cacheData.data();
std::cout << "Loaded " << fileSize << " bytes from pipeline cache" << std::endl;
}
VK_CHECK(vkCreatePipelineCache(graphics->getDevice(), &cacheCreateInfo, nullptr, &cache));
}
PipelineCache::~PipelineCache()
{
VkDeviceSize cacheSize;
vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, nullptr);
Array<uint8> cacheData;
vkGetPipelineCacheData(graphics->getDevice(), cache, &cacheSize, cacheData.data());
std::ofstream stream(cacheFile, std::ios::binary);
stream.write((char*)cacheData.data(), cacheSize);
stream.flush();
stream.close();
vkDestroyPipelineCache(graphics->getDevice(), cache, nullptr);
std::cout << "Written " << cacheSize << " bytes to cache" << std::endl;
}
struct PipelineCreateHashStruct
{
uint32 vertexHash;
uint32 controlHash;
uint32 evalHash;
uint32 geometryHash;
uint32 fragmentHash;
uint32 pipelineLayoutHash;
VkPipelineTessellationStateCreateInfo tess;
VkVertexInputAttributeDescription attribs[16];
VkVertexInputBindingDescription bindings[16];
VkPipelineInputAssemblyStateCreateInfo inputAssembly;
VkPipelineViewportStateCreateInfo viewport;
VkPipelineRasterizationStateCreateInfo rasterization;
VkPipelineMultisampleStateCreateInfo multisample;
VkPipelineDepthStencilStateCreateInfo depthStencil;
VkPipelineColorBlendAttachmentState blendAttachments[16];
VkPipelineColorBlendStateCreateInfo blendState;
};
PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo& gfxInfo)
{
VkGraphicsPipelineCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
createInfo.pNext = 0;
createInfo.flags = 0;
createInfo.stageCount = 0;
VkPipelineTessellationStateCreateInfo tessInfo;
std::memset(&tessInfo, 0, sizeof(VkPipelineTessellationStateCreateInfo));
VkPipelineShaderStageCreateInfo stageInfos[5];
std::memset(stageInfos, 0, sizeof(stageInfos));
PipelineCreateHashStruct hashStruct;
std::memset(&hashStruct, 0, sizeof(PipelineCreateHashStruct));
PVertexShader vertexShader = gfxInfo.vertexShader.cast<VertexShader>();
VkPipelineShaderStageCreateInfo& vertInfo = stageInfos[createInfo.stageCount++];
vertInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
vertInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
vertInfo.module = vertexShader->getModuleHandle();
vertInfo.pName = vertexShader->getEntryPointName();
hashStruct.vertexHash = vertexShader->getShaderHash();
if(gfxInfo.controlShader != nullptr)
{
assert(gfxInfo.evalShader != nullptr);
PControlShader control = gfxInfo.controlShader.cast<ControlShader>();
PEvaluationShader eval = gfxInfo.evalShader.cast<EvaluationShader>();
VkPipelineShaderStageCreateInfo& controlInfo = stageInfos[createInfo.stageCount++];
controlInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
controlInfo.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
controlInfo.module = control->getModuleHandle();
controlInfo.pName = control->getEntryPointName();
VkPipelineShaderStageCreateInfo& evalInfo = stageInfos[createInfo.stageCount++];
evalInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
evalInfo.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
evalInfo.module = eval->getModuleHandle();
evalInfo.pName = eval->getEntryPointName();
tessInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
tessInfo.pNext = 0;
tessInfo.flags = 0;
tessInfo.patchControlPoints = control->getNumPatches();
hashStruct.controlHash = control->getShaderHash();
hashStruct.evalHash = eval->getShaderHash();
hashStruct.tess = tessInfo;
}
if(gfxInfo.geometryShader != nullptr)
{
PGeometryShader geometry = gfxInfo.geometryShader.cast<GeometryShader>();
VkPipelineShaderStageCreateInfo& geometryInfo = stageInfos[createInfo.stageCount++];
geometryInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
geometryInfo.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
geometryInfo.module = geometry->getModuleHandle();
geometryInfo.pName = geometry->getEntryPointName();
hashStruct.geometryHash = geometry->getShaderHash();
}
if(gfxInfo.fragmentShader != nullptr)
{
PFragmentShader fragment = gfxInfo.fragmentShader.cast<FragmentShader>();
VkPipelineShaderStageCreateInfo& fragmentInfo = stageInfos[createInfo.stageCount++];
fragmentInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
fragmentInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
fragmentInfo.module = fragment->getModuleHandle();
fragmentInfo.pName = fragment->getEntryPointName();
hashStruct.fragmentHash = fragment->getShaderHash();
}
VkPipelineVertexInputStateCreateInfo vertexInput =
init::PipelineVertexInputStateCreateInfo();
PVertexDeclaration vertexDecl = gfxInfo.vertexDeclaration;
auto vertexStreams = vertexDecl->elementList;
uint32 bindingNum = 0;
uint32 bindingsMask = 0;
uint32 attributesNum = 0;
Array<VkVertexInputBindingDescription> bindings;
Array<VkVertexInputAttributeDescription> attributes;
Map<uint32, uint32> bindingToStream;
Map<uint32, uint32> streamToBinding;
assert(DEFAULT_ALLOC_SIZE == 16);
std::memset(bindings.data(), 0, sizeof(VkVertexInputBindingDescription) * 16);
std::memset(attributes.data(), 0, sizeof(VkVertexInputAttributeDescription) * 16);
for(auto& element : vertexStreams)
{
//if((1 << element.attributeIndex) & vertexAttributeMask) // TODO: attribute mask
{
if(element.streamIndex >= bindings.size())
{
bindings.resize(element.streamIndex + 1); // This should not cause any actual allocations
}
VkVertexInputBindingDescription& currBinding = bindings[element.streamIndex];
if((bindingsMask & (1 << element.streamIndex)) != 0)
{
assert(currBinding.binding == element.streamIndex);
assert(currBinding.inputRate == element.bInstanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
assert(currBinding.stride == element.stride);
}
else
{
assert(currBinding.binding == 0 && currBinding.inputRate == 0 && currBinding.stride == 0);
currBinding.binding = element.streamIndex;
currBinding.inputRate = element.bInstanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
currBinding.stride = element.stride;
bindingsMask |= 1 << element.streamIndex;
}
}
}
for(uint32 i = 0; i < bindings.size(); ++i)
{
if(!((1 << i) & bindingsMask))
{
continue;
}
bindingToStream[bindingNum] = i;
streamToBinding[i] = bindingNum;
VkVertexInputBindingDescription& currBinding = bindings[bindingNum];
currBinding = bindings[i];
currBinding.binding = bindingNum;
bindingNum++;
}
for(auto& element : vertexStreams)
{
//TODO: vertex attribute mask
if(attributesNum >= attributes.size())
{
attributes.resize(attributesNum + 1); // This should not cause any actual allocations
}
VkVertexInputAttributeDescription& currAttribute = attributes[attributesNum++];
currAttribute.location = element.attributeIndex;
currAttribute.binding = streamToBinding[element.streamIndex];
currAttribute.format = cast(element.vertexFormat);
currAttribute.offset = element.offset;
}
std::memcpy(hashStruct.bindings, bindings.data(), bindings.size() * sizeof(VkVertexInputBindingDescription));
std::memcpy(hashStruct.attribs, attributes.data(), attributes.size() * sizeof(VkVertexInputAttributeDescription));
vertexInput.pVertexBindingDescriptions = bindings.data();
vertexInput.vertexBindingDescriptionCount = (uint32)bindings.size();
vertexInput.pVertexAttributeDescriptions = attributes.data();
vertexInput.vertexAttributeDescriptionCount = (uint32)attributes.size();
VkPipelineInputAssemblyStateCreateInfo assemblyInfo =
init::PipelineInputAssemblyStateCreateInfo(
cast(gfxInfo.topology),
0,
false
);
hashStruct.inputAssembly = assemblyInfo;
VkPipelineViewportStateCreateInfo viewportInfo =
init::PipelineViewportStateCreateInfo(
1,
1,
0
);
hashStruct.viewport = viewportInfo;
VkPipelineRasterizationStateCreateInfo rasterizationState =
init::PipelineRasterizationStateCreateInfo(
cast(gfxInfo.rasterizationState.polygonMode),
gfxInfo.rasterizationState.cullMode,
(VkFrontFace)gfxInfo.rasterizationState.frontFace,
0
);
rasterizationState.depthBiasEnable = gfxInfo.rasterizationState.depthBiasEnable;
rasterizationState.depthBiasClamp = gfxInfo.rasterizationState.depthBiasClamp;
rasterizationState.depthBiasConstantFactor = gfxInfo.rasterizationState.depthBoasConstantFactor;
rasterizationState.depthBiasSlopeFactor = gfxInfo.rasterizationState.depthBiasSlopeFactor;
rasterizationState.depthClampEnable = gfxInfo.rasterizationState.depthClampEnable;
rasterizationState.lineWidth = gfxInfo.rasterizationState.lineWidth;
rasterizationState.rasterizerDiscardEnable = gfxInfo.rasterizationState.rasterizerDiscardEnable;
hashStruct.rasterization = rasterizationState;
VkPipelineMultisampleStateCreateInfo multisampleState =
init::PipelineMultisampleStateCreateInfo(
(VkSampleCountFlagBits)gfxInfo.multisampleState.samples,
0);
multisampleState.alphaToCoverageEnable = gfxInfo.multisampleState.alphaCoverageEnable;
multisampleState.alphaToOneEnable = gfxInfo.multisampleState.alphaToOneEnable;
multisampleState.minSampleShading = gfxInfo.multisampleState.minSampleShading;
multisampleState.sampleShadingEnable = gfxInfo.multisampleState.sampleShadingEnable;
hashStruct.multisample = multisampleState;
VkPipelineDepthStencilStateCreateInfo depthStencilState =
init::PipelineDepthStencilStateCreateInfo(
gfxInfo.depthStencilState.depthTestEnable,
gfxInfo.depthStencilState.depthWriteEnable,
cast(gfxInfo.depthStencilState.depthCompareOp)
);
hashStruct.depthStencil = depthStencilState;
const auto& colorAttachments = gfxInfo.renderPass->getLayout()->colorAttachments;
Array<VkPipelineColorBlendAttachmentState> blendAttachments(colorAttachments.size());
for(uint32 i = 0; i < colorAttachments.size(); ++i)
{
const Gfx::ColorBlendState::BlendAttachment& attachment = gfxInfo.colorBlend.blendAttachments[i];
VkPipelineColorBlendAttachmentState& blendAttachment = blendAttachments[i];
blendAttachment.alphaBlendOp = (VkBlendOp)attachment.alphaBlendOp;
blendAttachment.blendEnable = attachment.blendEnable;
blendAttachment.colorBlendOp = (VkBlendOp)attachment.colorBlendOp;
blendAttachment.colorWriteMask = attachment.colorWriteMask;
blendAttachment.dstAlphaBlendFactor = (VkBlendFactor)attachment.dstAlphaBlendFactor;
blendAttachment.srcAlphaBlendFactor = (VkBlendFactor)attachment.srcAlphaBlendFactor;
blendAttachment.dstColorBlendFactor = (VkBlendFactor)attachment.dstColorBlendFactor;
blendAttachment.srcColorBlendFactor = (VkBlendFactor)attachment.srcColorBlendFactor;
hashStruct.blendAttachments[i] = blendAttachment;
}
VkPipelineColorBlendStateCreateInfo blendState =
init::PipelineColorBlendStateCreateInfo(
(uint32)blendAttachments.size(),
blendAttachments.data()
);
blendState.logicOpEnable = gfxInfo.colorBlend.logicOpEnable;
blendState.logicOp = (VkLogicOp)gfxInfo.colorBlend.logicOp;
std::memcpy(blendState.blendConstants, gfxInfo.colorBlend.blendConstants, sizeof(float)*4);
hashStruct.blendState = blendState;
hashStruct.blendState.pAttachments = nullptr;
uint32 numDynamicEnabled = 0;
StaticArray<VkDynamicState, 2> dynamicEnabled;
dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_VIEWPORT;
dynamicEnabled[numDynamicEnabled++] = VK_DYNAMIC_STATE_SCISSOR;
VkPipelineDynamicStateCreateInfo dynamicState =
init::PipelineDynamicStateCreateInfo(
dynamicEnabled.data(),
numDynamicEnabled,
0
);
PPipelineLayout layout = gfxInfo.pipelineLayout.cast<PipelineLayout>();
hashStruct.pipelineLayoutHash = layout->getHash();
uint32 hash = CRC::Calculate(&hashStruct, sizeof(PipelineCreateHashStruct), CRC::CRC_32());
VkPipeline pipelineHandle;
std::scoped_lock lock(createdPipelinesLock);
auto foundPipeline = createdPipelines.find(hash);
if (foundPipeline != createdPipelines.end())
{
pipelineHandle = foundPipeline->value;
}
else
{
createInfo.pStages = stageInfos;
createInfo.pVertexInputState = &vertexInput;
createInfo.pInputAssemblyState = &assemblyInfo;
createInfo.pTessellationState = &tessInfo;
createInfo.pViewportState = &viewportInfo;
createInfo.pRasterizationState = &rasterizationState;
createInfo.pMultisampleState = &multisampleState;
createInfo.pDepthStencilState = &depthStencilState;
createInfo.pColorBlendState = &blendState;
createInfo.pDynamicState = &dynamicState;
createInfo.renderPass = gfxInfo.renderPass.cast<RenderPass>()->getHandle();
createInfo.layout = layout->getHandle();
createInfo.subpass = 0;
auto beginTime = std::chrono::high_resolution_clock::now();
VK_CHECK(vkCreateGraphicsPipelines(graphics->getDevice(), cache, 1, &createInfo, nullptr, &pipelineHandle));
auto endTime = std::chrono::high_resolution_clock::now();
int64 delta = std::chrono::duration_cast<std::chrono::microseconds>(endTime - beginTime).count();
createdPipelines[hash] = pipelineHandle;
std::cout << "Gfx creation time: " << delta << std::endl;
}
PGraphicsPipeline result = new GraphicsPipeline(graphics, pipelineHandle, layout, gfxInfo);
return result;
}
PComputePipeline PipelineCache::createPipeline(const ComputePipelineCreateInfo& computeInfo)
{
VkComputePipelineCreateInfo createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
createInfo.pNext = 0;
createInfo.flags = 0;
createInfo.basePipelineIndex = 0;
createInfo.basePipelineHandle = VK_NULL_HANDLE;
auto layout = computeInfo.pipelineLayout.cast<PipelineLayout>();
createInfo.layout = layout->getHandle();
auto computeStage = computeInfo.computeShader.cast<ComputeShader>();
createInfo.stage = init::PipelineShaderStageCreateInfo(
VK_SHADER_STAGE_COMPUTE_BIT,
computeStage->getModuleHandle(),
computeStage->getEntryPointName());
VkPipeline pipelineHandle;
auto beginTime = std::chrono::high_resolution_clock::now();
VK_CHECK(vkCreateComputePipelines(graphics->getDevice(), cache, 1, &createInfo, nullptr, &pipelineHandle));
auto endTime = std::chrono::high_resolution_clock::now();
int64 delta = std::chrono::duration_cast<std::chrono::microseconds>(endTime - beginTime).count();
std::cout << "Compute creation time: " << delta << std::endl;
PComputePipeline result = new ComputePipeline(graphics, pipelineHandle, layout, computeInfo);
return result;
}