Trying to fix invalid descriptorlayout

This commit is contained in:
Dynamitos
2020-10-03 11:00:10 +02:00
parent 79388bf41a
commit ceee96b462
69 changed files with 1087 additions and 393 deletions
+6 -1
View File
@@ -71,6 +71,11 @@ ShaderBuffer::~ShaderBuffer()
graphics = nullptr;
}
VkDeviceSize ShaderBuffer::getOffset() const
{
return buffers[currentBuffer].allocation->getOffset();
}
void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{
VkBufferMemoryBarrier barrier =
@@ -235,7 +240,7 @@ void ShaderBuffer::unlock()
UniformBuffer::UniformBuffer(PGraphics graphics, const BulkResourceData &resourceData)
: Vulkan::ShaderBuffer(graphics, resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, resourceData.owner)
, Gfx::UniformBuffer(graphics->getFamilyMapping(), resourceData.owner)
, Gfx::UniformBuffer(graphics->getFamilyMapping(), resourceData)
{
if (resourceData.data != nullptr)
{
@@ -150,6 +150,7 @@ void SecondaryCmdBuffer::begin(PCmdBuffer parent)
inheritanceInfo.renderPass = parent->renderPass->getHandle();
inheritanceInfo.subpass = parent->subpassIndex;
beginInfo.pInheritanceInfo = &inheritanceInfo;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
}
@@ -158,6 +159,14 @@ void SecondaryCmdBuffer::end()
VK_CHECK(vkEndCommandBuffer(handle));
}
void SecondaryCmdBuffer::setViewport(Gfx::PViewport viewport)
{
VkViewport vp = viewport.cast<Viewport>()->getHandle();
VkRect2D scissors = init::Rect2D(viewport->getSizeX(), viewport->getSizeY(), viewport->getOffsetX(), viewport->getOffsetY());
vkCmdSetViewport(handle, 0, 1, &vp);
vkCmdSetScissor(handle, 0, 1, &scissors);
}
void SecondaryCmdBuffer::bindPipeline(Gfx::PGraphicsPipeline gfxPipeline)
{
pipeline = gfxPipeline.cast<GraphicsPipeline>();
@@ -168,6 +177,17 @@ void SecondaryCmdBuffer::bindDescriptor(Gfx::PDescriptorSet descriptorSet)
VkDescriptorSet setHandle = descriptorSet.cast<DescriptorSet>()->getHandle();
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), descriptorSet->getSetIndex(), 1, &setHandle, 0, nullptr);
}
void SecondaryCmdBuffer::bindDescriptor(Array<Gfx::PDescriptorSet> descriptorSets)
{
VkDescriptorSet* sets = new VkDescriptorSet[descriptorSets.size()];
for(uint32 i = 0; i < descriptorSets.size(); ++i)
{
auto descriptorSet = descriptorSets[i].cast<DescriptorSet>();
sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle();
}
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, descriptorSets.size(), sets, 0, nullptr);
delete[] sets;
}
void SecondaryCmdBuffer::bindVertexBuffer(const Array<VertexInputStream>& streams)
{
Array<VkBuffer> buffers(streams.size());
@@ -70,15 +70,17 @@ private:
DEFINE_REF(CmdBuffer);
DECLARE_REF(GraphicsPipeline);
class SecondaryCmdBuffer : public CmdBufferBase, public Gfx::RenderCommand
class SecondaryCmdBuffer : public Gfx::RenderCommand, public CmdBufferBase
{
public:
SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool);
virtual ~SecondaryCmdBuffer();
void begin(PCmdBuffer parent);
void end();
virtual void setViewport(Gfx::PViewport viewport) override;
virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) override;
virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override;
virtual void bindDescriptor(Array<Gfx::PDescriptorSet> descriptorSets) override;
virtual void bindVertexBuffer(const Array<VertexInputStream>& streams) override;
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
virtual void draw(const MeshBatchElement& data) override;
@@ -7,6 +7,11 @@
using namespace Seele;
using namespace Seele::Vulkan;
DescriptorLayout::DescriptorLayout(PGraphics graphics)
: graphics(graphics)
, layoutHandle(VK_NULL_HANDLE)
{
}
DescriptorLayout::~DescriptorLayout()
{
if (layoutHandle != VK_NULL_HANDLE)
@@ -36,7 +41,13 @@ void DescriptorLayout::create()
init::DescriptorSetLayoutCreateInfo(bindings.data(), bindings.size());
VK_CHECK(vkCreateDescriptorSetLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
std::cout << "creating descriptorlayout " << layoutHandle << std::endl;
allocator = new DescriptorAllocator(graphics, *this);
boost::crc_32_type result;
result.process_bytes(bindings.data(), sizeof(VkDescriptorSetLayoutBinding) * bindings.size());
hash = result.checksum();
}
PipelineLayout::~PipelineLayout()
@@ -47,15 +58,23 @@ PipelineLayout::~PipelineLayout()
}
}
static Map<uint32, VkPipelineLayout> layoutCache;
void PipelineLayout::create()
{
vulkanDescriptorLayouts.resize(descriptorSetLayouts.size());
for (size_t i = 0; i < descriptorSetLayouts.size(); ++i)
{
// There could be unused descriptor set indices
if(descriptorSetLayouts[i] == nullptr)
{
continue;
}
PDescriptorLayout layout = descriptorSetLayouts[i].cast<DescriptorLayout>();
layout->create();
vulkanDescriptorLayouts[i] = layout->getHandle();
}
VkPipelineLayoutCreateInfo createInfo =
init::PipelineLayoutCreateInfo(vulkanDescriptorLayouts.data(), vulkanDescriptorLayouts.size());
Array<VkPushConstantRange> vkPushConstants(pushConstants.size());
@@ -67,11 +86,20 @@ void PipelineLayout::create()
}
createInfo.pushConstantRangeCount = vkPushConstants.size();
createInfo.pPushConstantRanges = vkPushConstants.data();
VK_CHECK(vkCreatePipelineLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
boost::crc_32_type result;
result.process_bytes(&createInfo, sizeof(VkPipelineLayoutCreateInfo));
result.process_bytes(createInfo.pPushConstantRanges, sizeof(VkPushConstantRange) * createInfo.pushConstantRangeCount);
result.process_bytes(createInfo.pSetLayouts, sizeof(VkDescriptorSetLayout) * createInfo.setLayoutCount);
layoutHash = result.checksum();
if(layoutCache[layoutHash] != VK_NULL_HANDLE)
{
layoutHandle = layoutCache[layoutHash];
return;
}
VK_CHECK(vkCreatePipelineLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
layoutCache[layoutHash] = layoutHandle;
}
void PipelineLayout::reset()
@@ -85,29 +113,57 @@ DescriptorSet::~DescriptorSet()
{
}
void DescriptorSet::beginFrame()
{
currentFrameSet = (currentFrameSet + 1) % Gfx::numFramesBuffered;
}
void DescriptorSet::endFrame()
{
}
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer)
{
PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>();
// VkDescriptorBufferInfo bufferInfo = init::DescriptorBufferInfo(vulkanBuffer->getHandle(), vulkanBuffer->getOffset(), vulkanBuffer->getSize());
// bufferInfos.add(bufferInfo);
UniformBuffer* cachedBuffer = reinterpret_cast<UniformBuffer*>(cachedData[currentFrameSet][binding]);
if(vulkanBuffer->isDataEquals(cachedBuffer))
{
return;
}
VkDescriptorBufferInfo bufferInfo = init::DescriptorBufferInfo(vulkanBuffer->getHandle(), 0, vulkanBuffer->getSize());
bufferInfos.add(bufferInfo);
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, binding, &bufferInfos.back());
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[currentFrameSet], VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, binding, &bufferInfos.back());
writeDescriptors.add(writeDescriptor);
cachedData[currentFrameSet][binding] = vulkanBuffer.getHandle();
}
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer)
{
PStructuredBuffer vulkanBuffer = uniformBuffer.cast<StructuredBuffer>();
// VkDescriptorBufferInfo bufferInfo = init::DescriptorBufferInfo(vulkanBuffer->getHandle(), vulkanBuffer->getOffset(), vulkanBuffer->getSize());
// bufferInfos.add(bufferInfo);
StructuredBuffer* cachedBuffer = reinterpret_cast<StructuredBuffer*>(cachedData[currentFrameSet][binding]);
if(vulkanBuffer.getHandle() == cachedBuffer)
{
return;
}
VkDescriptorBufferInfo bufferInfo = init::DescriptorBufferInfo(vulkanBuffer->getHandle(), 0, vulkanBuffer->getSize());
bufferInfos.add(bufferInfo);
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, binding, &bufferInfos.back());
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[currentFrameSet], VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, binding, &bufferInfos.back());
writeDescriptors.add(writeDescriptor);
cachedData[currentFrameSet][binding] = vulkanBuffer.getHandle();
}
void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSamplerState samplerState)
{
PSamplerState vulkanSampler = samplerState.cast<SamplerState>();
SamplerState* cachedSampler = reinterpret_cast<SamplerState*>(cachedData[currentFrameSet][binding]);
if(vulkanSampler.getHandle() == cachedSampler)
{
return;
}
VkDescriptorImageInfo imageInfo =
init::DescriptorImageInfo(
vulkanSampler->sampler,
@@ -115,13 +171,20 @@ void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSamplerState samplerSt
VK_IMAGE_LAYOUT_UNDEFINED);
imageInfos.add(imageInfo);
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_SAMPLER, binding, &imageInfos.back());
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[currentFrameSet], VK_DESCRIPTOR_TYPE_SAMPLER, binding, &imageInfos.back());
writeDescriptors.add(writeDescriptor);
cachedData[currentFrameSet][binding] = vulkanSampler.getHandle();
}
void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSamplerState samplerState)
{
PTextureHandle vulkanTexture = TextureBase::cast(texture);
TextureHandle* vulkanTexture = TextureBase::cast(texture);
TextureHandle* cachedTexture = reinterpret_cast<TextureHandle*>(cachedData[currentFrameSet][binding]);
if(vulkanTexture == cachedTexture)
{
return;
}
//It is assumed that the image is in the correct layout
VkDescriptorImageInfo imageInfo =
init::DescriptorImageInfo(
@@ -134,12 +197,14 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::
imageInfo.sampler = vulkanSampler->sampler;
}
imageInfos.add(imageInfo);
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, samplerState != nullptr ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, binding, &imageInfos.back());
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle[currentFrameSet], samplerState != nullptr ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, binding, &imageInfos.back());
if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT)
{
writeDescriptor.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
}
writeDescriptors.add(writeDescriptor);
cachedData[currentFrameSet][binding] = vulkanTexture;
}
bool DescriptorSet::operator<(Gfx::PDescriptorSet other)
@@ -160,8 +225,10 @@ void DescriptorSet::writeChanges()
}
DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout)
: layout(layout), graphics(graphics)
: layout(layout), graphics(graphics), currentCachedIndex(0)
{
std::memset(&cachedHandles, 0, sizeof(cachedHandles));
uint32 perTypeSizes[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]; // TODO: FIX ENUM
std::memset(perTypeSizes, 0, sizeof(perTypeSizes));
for (uint32 i = 0; i < layout.getBindings().size(); ++i)
@@ -198,5 +265,25 @@ void DescriptorAllocator::allocateDescriptorSet(Gfx::PDescriptorSet &descriptorS
VkDescriptorSetLayout layoutHandle = layout.getHandle();
VkDescriptorSetAllocateInfo allocInfo =
init::DescriptorSetAllocateInfo(poolHandle, &layoutHandle, 1);
VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &vulkanSet->setHandle));
for(uint32 i = 0; i < Gfx::numFramesBuffered; ++i)
{
if(cachedHandles[currentCachedIndex] != VK_NULL_HANDLE)
{
vulkanSet->setHandle[i] = cachedHandles[currentCachedIndex++];
}
else
{
VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &vulkanSet->setHandle[i]));
cachedHandles[currentCachedIndex++] = vulkanSet->setHandle[i];
}
vulkanSet->cachedData[i].resize(layout.bindings.size());
// Not really pretty, but this way the set knows which ones are valid
std::memset(vulkanSet->cachedData[i].data(), 0, sizeof(void*) * vulkanSet->cachedData[i].size());
}
}
void DescriptorAllocator::reset()
{
currentCachedIndex = 0;
}
@@ -9,10 +9,7 @@ DECLARE_REF(Graphics);
class DescriptorLayout : public Gfx::DescriptorLayout
{
public:
DescriptorLayout(PGraphics graphics)
: graphics(graphics), layoutHandle(VK_NULL_HANDLE)
{
}
DescriptorLayout(PGraphics graphics);
virtual ~DescriptorLayout();
virtual void create();
inline VkDescriptorSetLayout getHandle() const
@@ -21,9 +18,11 @@ public:
}
private:
uint32 hash;
PGraphics graphics;
Array<VkDescriptorSetLayoutBinding> bindings;
VkDescriptorSetLayout layoutHandle;
friend class DescriptorAllocator;
};
DEFINE_REF(DescriptorLayout);
class PipelineLayout : public Gfx::PipelineLayout
@@ -59,6 +58,7 @@ public:
DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout);
virtual ~DescriptorAllocator();
virtual void allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet);
virtual void reset();
inline VkDescriptorPool getHandle() const
{
@@ -71,7 +71,9 @@ public:
private:
PGraphics graphics;
int maxSets = 512;
const static int maxSets = 512;
VkDescriptorSet cachedHandles[maxSets];
uint32 currentCachedIndex;
VkDescriptorPool poolHandle;
DescriptorLayout &layout;
};
@@ -81,10 +83,13 @@ class DescriptorSet : public Gfx::DescriptorSet
{
public:
DescriptorSet(PGraphics graphics, PDescriptorAllocator owner)
: graphics(graphics), owner(owner), setHandle(VK_NULL_HANDLE)
: graphics(graphics), owner(owner), currentFrameSet(0)
{
}
virtual ~DescriptorSet();
virtual void beginFrame();
virtual void endFrame();
virtual void writeChanges();
virtual void updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer);
virtual void updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer);
virtual void updateSampler(uint32_t binding, Gfx::PSamplerState samplerState);
@@ -92,7 +97,7 @@ public:
virtual bool operator<(Gfx::PDescriptorSet other);
inline VkDescriptorSet getHandle() const
{
return setHandle;
return setHandle[currentFrameSet];
}
virtual uint32 getSetIndex() const
{
@@ -100,11 +105,15 @@ public:
}
private:
virtual void writeChanges();
Array<VkDescriptorImageInfo> imageInfos;
Array<VkDescriptorBufferInfo> bufferInfos;
Array<VkWriteDescriptorSet> writeDescriptors;
VkDescriptorSet setHandle;
// contains the previously bound resources at every binding
// since the layout is fixed, trying to bind a texture to a buffer
// would not work anyways, so casts should be safe
Array<void*> cachedData[Gfx::numFramesBuffered];
VkDescriptorSet setHandle[Gfx::numFramesBuffered];
uint32 currentFrameSet;
PDescriptorAllocator owner;
PGraphics graphics;
friend class DescriptorAllocator;
@@ -39,6 +39,7 @@ Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRende
renderPass->getRenderArea().extent.width,
renderPass->getRenderArea().extent.height,
1);
VK_CHECK(vkCreateFramebuffer(graphics->getDevice(), &createInfo, nullptr, &handle));
boost::crc_32_type result;
+17 -1
View File
@@ -124,6 +124,13 @@ Gfx::PRenderCommand Graphics::createRenderCommand()
cmdBuffer->begin(getGraphicsCommands()->getCommands());
return cmdBuffer;
}
Gfx::PVertexDeclaration Graphics::createVertexDeclaration(const Array<Gfx::VertexElement>& element)
{
PVertexDeclaration declaration = new VertexDeclaration(element);
return declaration;
}
Gfx::PVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createInfo)
{
PVertexShader shader = new VertexShader(this);
@@ -159,6 +166,15 @@ Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(const GraphicsPipelineCr
PGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo);
return pipeline;
}
Gfx::PSamplerState Graphics::createSamplerState(const SamplerCreateInfo& createInfo)
{
PSamplerState sampler = new SamplerState(); // TODO: proper sampler creation
VkSamplerCreateInfo vkInfo =
init::SamplerCreateInfo();
VK_CHECK(vkCreateSampler(handle, &vkInfo, nullptr, &sampler->sampler));
return sampler;
}
Gfx::PDescriptorLayout Graphics::createDescriptorLayout()
{
PDescriptorLayout layout = new DescriptorLayout(this);
@@ -280,7 +296,7 @@ void Graphics::initInstance(GraphicsInitializer initInfo)
appInfo.applicationVersion = VK_MAKE_VERSION(0, 0, 1);
appInfo.pEngineName = initInfo.engineName;
appInfo.engineVersion = VK_MAKE_VERSION(0, 0, 1);
appInfo.apiVersion = VK_API_VERSION_1_1;
appInfo.apiVersion = VK_API_VERSION_1_2;
VkInstanceCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@@ -53,12 +53,14 @@ public:
virtual Gfx::PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) override;
virtual Gfx::PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) override;
virtual Gfx::PRenderCommand createRenderCommand() 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::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override;
virtual Gfx::PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) override;
virtual Gfx::PDescriptorLayout createDescriptorLayout() override;
virtual Gfx::PPipelineLayout createPipelineLayout() override;
@@ -49,6 +49,14 @@ void QueueOwnedResourceDeletion::run()
}
}
void UniformBuffer::updateContents(const BulkResourceData &resourceData)
{
Gfx::UniformBuffer::updateContents(resourceData);
void* data = lock();
std::memcpy(data, resourceData.data, resourceData.size);
unlock();
}
Semaphore::Semaphore(PGraphics graphics)
: graphics(graphics)
{
@@ -121,3 +129,12 @@ void Fence::wait(uint32 timeout)
break;
}
}
VertexDeclaration::VertexDeclaration(const Array<Gfx::VertexElement>& elementList)
: elementList(elementList)
{
}
VertexDeclaration::~VertexDeclaration()
{
}
@@ -53,6 +53,17 @@ private:
};
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 QueueOwnedResourceDeletion
{
public:
@@ -83,6 +94,11 @@ public:
{
return buffers[currentBuffer].buffer;
}
uint32 getSize() const
{
return size;
}
VkDeviceSize getOffset() const;
void advanceBuffer()
{
currentBuffer = (currentBuffer + 1) % numBuffers;
@@ -116,7 +132,7 @@ class UniformBuffer : public Gfx::UniformBuffer, public ShaderBuffer
public:
UniformBuffer(PGraphics graphics, const BulkResourceData &resourceData);
virtual ~UniformBuffer();
virtual void updateContents(const BulkResourceData &resourceData);
protected:
// Inherited via Vulkan::Buffer
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
@@ -232,23 +248,16 @@ private:
friend class TextureBase;
friend class Texture2D;
};
DEFINE_REF(TextureHandle);
DECLARE_REF(TextureBase);
class TextureBase
{
public:
static PTextureHandle cast(Gfx::PTexture texture)
{
PTextureBase base = texture.cast<TextureBase>();
return base->textureHandle;
}
static TextureHandle* cast(Gfx::PTexture texture);
void changeLayout(VkImageLayout newLayout);
protected:
PTextureHandle textureHandle;
TextureHandle* textureHandle;
};
DEFINE_REF(TextureBase);
class Texture2D : public Gfx::Texture2D, public TextureBase
{
@@ -290,7 +299,7 @@ protected:
};
DEFINE_REF(Texture2D);
class SamplerState
class SamplerState : public Gfx::SamplerState
{
public:
VkSampler sampler;
@@ -343,9 +352,9 @@ public:
virtual ~Viewport();
virtual void resize(uint32 newX, uint32 newY);
virtual void move(uint32 newOffsetX, uint32 newOffsetY);
protected:
VkViewport getHandle() const { return handle; }
private:
VkViewport handle;
PGraphics graphics;
friend class Graphics;
};
@@ -768,7 +768,14 @@ VkPipelineShaderStageCreateInfo init::PipelineShaderStageCreateInfo(VkShaderStag
#pragma warning(disable : 4100)
VkBool32 Seele::Vulkan::debugCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t obj, size_t location, int32_t code, const char *layerPrefix, const char *msg, void *userDataManager)
{
std::cerr << layerPrefix << ": " << msg << std::endl;
if(flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
{
std::cerr << layerPrefix << ": " << msg << std::endl;
}
else
{
std::cerr << layerPrefix << ": " << msg << std::endl;
}
return VK_FALSE;
}
#pragma warning(default : 4100)
@@ -54,24 +54,17 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
createInfo.flags = 0;
createInfo.stageCount = 0;
PPipelineLayout layout = graphics->createPipelineLayout();
VkPipelineTessellationStateCreateInfo tessInfo;
VkPipelineShaderStageCreateInfo stageInfos[5];
std::memset(stageInfos, 0, sizeof(stageInfos));
if(gfxInfo.vertexShader != nullptr)
{
PVertexShader shader = 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 = shader->getModuleHandle();
vertInfo.pName = shader->getEntryPointName();
for(auto descriptor : shader->getDescriptorLayouts())
{
layout->addDescriptorLayout(descriptor.key, descriptor.value);
}
}
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();
if(gfxInfo.controlShader != nullptr)
{
assert(gfxInfo.evalShader != nullptr);
@@ -94,15 +87,6 @@ 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)
{
@@ -113,11 +97,6 @@ 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)
{
@@ -128,40 +107,81 @@ 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;
auto vertexStreams = vertexDecl->getVertexStreams();
Array<VkVertexInputBindingDescription> bindingDesc(vertexStreams.size());
Array<VkVertexInputAttributeDescription> attribDesc;
PVertexDeclaration vertexDecl = gfxInfo.vertexDeclaration;
auto vertexStreams = vertexDecl->elementList;
uint32 bindingNum = 0;
for(auto vertexBinding : vertexStreams)
uint32 bindingsMask = 0;
uint32 attributesNum = 0;
Array<VkVertexInputBindingDescription> bindings;
Array<VkVertexInputAttributeDescription> attributes;
Map<uint32, uint32> bindingToStream;
Map<uint32, uint32> streamToBinding;
std::memset(bindings.data(), 0, sizeof(VkVertexInputBindingDescription) * 16); // if default allocation size ever changes, this breaks
std::memset(attributes.data(), 0, sizeof(VkVertexInputAttributeDescription) * 16);
for(auto& element : vertexStreams)
{
uint32 stride = 0;
for(auto vertexAttrib : vertexBinding.getVertexDescriptions())
//if((1 << element.attributeIndex) & vertexAttributeMask) // TODO: attribute mask
{
auto attrib = attribDesc.add();
attrib.binding = bindingNum;
attrib.format = cast(vertexAttrib.vertexFormat);
attrib.location = vertexAttrib.location;
attrib.offset = vertexAttrib.offset;
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;
}
}
bindingDesc[bindingNum].binding = bindingNum;
bindingDesc[bindingNum].stride = stride;
bindingDesc[bindingNum].inputRate = vertexBinding.isInstanced() ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
}
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++;
}
vertexInput.pVertexBindingDescriptions = bindingDesc.data();
vertexInput.vertexBindingDescriptionCount = bindingDesc.size();
vertexInput.pVertexAttributeDescriptions = attribDesc.data();
vertexInput.vertexAttributeDescriptionCount = attribDesc.size();
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;
}
vertexInput.pVertexBindingDescriptions = bindings.data();
vertexInput.vertexBindingDescriptionCount = bindings.size();
vertexInput.pVertexAttributeDescriptions = attributes.data();
vertexInput.vertexAttributeDescriptionCount = attributes.size();
VkPipelineInputAssemblyStateCreateInfo assemblyInfo =
init::PipelineInputAssemblyStateCreateInfo(
@@ -242,6 +262,8 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
0
);
PPipelineLayout layout = gfxInfo.pipelineLayout.cast<PipelineLayout>();
createInfo.pStages = stageInfos;
createInfo.pVertexInputState = &vertexInput;
createInfo.pInputAssemblyState = &assemblyInfo;
@@ -260,7 +282,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
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::milliseconds>(endTime - beginTime).count();
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, gfxInfo);
@@ -11,6 +11,11 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::PRenderTargetLayout layout)
: Gfx::RenderPass(layout)
, graphics(graphics)
{
renderArea.extent.width = layout->width;
renderArea.extent.height = layout->height;
renderArea.offset.x = 0;
renderArea.offset.y = 0;
subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
Array<VkAttachmentDescription> attachments;
Array<VkAttachmentReference> inputRefs;
Array<VkAttachmentReference> colorRefs;
+38 -16
View File
@@ -2,6 +2,8 @@
#include "VulkanGraphics.h"
#include "VulkanDescriptorSets.h"
#include "slang.h"
#include "spirv_cross/spirv_reflect.hpp"
#include <fstream>
using namespace slang;
using namespace Seele;
@@ -46,8 +48,42 @@ static SlangStage getStageFromShaderType(ShaderType type)
}
}
/*static void createMixedDescriptorLayout(PDescriptorLayout layout, VariableLayoutReflection* parameter)
{
//std::cout << "category: " << (uint32)parameter->ge << std::endl;
uint32 categoryCount = parameter->getCategoryCount();
std::cout << "Mixed parameter " << parameter->getName() << " with categories: " << std::endl;
for(uint32 i = 0; i < categoryCount; ++i)
{
ParameterCategory category = parameter->getCategoryByIndex(i);
uint32 offset = parameter->getOffset(category);
uint32 space = parameter->getBindingSpace(category);
std::cout << "category: " << category << std::endl << " offset: " << offset << std::endl << " space: " << space << std::endl;
}
}
static Gfx::SeDescriptorType getTypeFromKind(slang::TypeReflection::Kind kind)
{
switch (kind)
{
case slang::TypeReflection::Kind::ConstantBuffer:
case slang::TypeReflection::Kind::GenericTypeParameter:
case slang::TypeReflection::Kind::ParameterBlock:
return Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
case slang::TypeReflection::Kind::ShaderStorageBuffer:
return Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER;
case slang::TypeReflection::Kind::TextureBuffer:
return Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
case slang::TypeReflection::Kind::SamplerState:
return Gfx::SE_DESCRIPTOR_TYPE_SAMPLER;
default:
return Gfx::SE_DESCRIPTOR_TYPE_MAX_ENUM;
}
}*/
void Shader::create(const ShaderCreateInfo& createInfo)
{
std::cout << "--------------------------------" << std::endl;
entryPointName = createInfo.entryPoint;
static SlangSession* session = spCreateSession(NULL);
@@ -82,28 +118,14 @@ void Shader::create(const ShaderCreateInfo& createInfo)
std::cout << diagnostics << 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);
const uint32* data = reinterpret_cast<const uint32*>(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);
moduleInfo.pCode = data;
VK_CHECK(vkCreateShaderModule(graphics->getDevice(), &moduleInfo, nullptr, &module));
}
+2 -1
View File
@@ -22,7 +22,8 @@ public:
}
const char* getEntryPointName() const
{
return entryPointName.c_str();
//SLang renames all entry points to main, so we dont need that
return "main";//entryPointName.c_str();
}
Map<uint32, PDescriptorLayout> getDescriptorLayouts();
private:
@@ -162,6 +162,16 @@ TextureHandle::~TextureHandle()
deletionQueue.addPendingDelete(cmdBuffer, [device, img]() { vkDestroyImage(device, img, nullptr); });
}
TextureHandle* TextureBase::cast(Gfx::PTexture texture)
{
if(texture->getTexture2D() != nullptr)
{
PTexture2D texture2D = texture.cast<Texture2D>();
return texture2D->textureHandle;
}
return nullptr;
}
void TextureHandle::changeLayout(VkImageLayout newLayout)
{
VkImageMemoryBarrier barrier =
@@ -258,6 +258,9 @@ void Window::choosePresentMode(const Array<VkPresentModeKHR> &modes)
Viewport::Viewport(PGraphics graphics, PWindow owner, const ViewportCreateInfo &viewportInfo)
: Gfx::Viewport(owner, viewportInfo), graphics(graphics)
{
handle = init::Viewport(static_cast<float>(viewportInfo.sizeX), static_cast<float>(viewportInfo.sizeY), 0.f, 1.f);
handle.x = static_cast<float>(viewportInfo.offsetX);
handle.y = static_cast<float>(viewportInfo.offsetY);
}
Viewport::~Viewport()