Rendering works now

This commit is contained in:
Dynamitos
2021-12-27 15:04:53 +01:00
parent 79ced0a30f
commit b2718dde70
15 changed files with 324 additions and 278 deletions
+1 -1
View File
@@ -504,7 +504,7 @@ namespace Seele
// As well as default initialize the others // As well as default initialize the others
for(size_type i = arraySize; i < newSize; ++i) for(size_type i = arraySize; i < newSize; ++i)
{ {
std::allocator_traits<allocator_type>::construct(allocator, &_data[i], std::move(value)); std::allocator_traits<allocator_type>::construct(allocator, &newData[i], std::move(value));
} }
deallocateArray(_data, allocated); deallocateArray(_data, allocated);
arraySize = newSize; arraySize = newSize;
+5 -4
View File
@@ -20,7 +20,7 @@ BasePassMeshProcessor::~BasePassMeshProcessor()
{ {
} }
Job BasePassMeshProcessor::processMeshBatch( void BasePassMeshProcessor::processMeshBatch(
const MeshBatch& batch, const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent, // const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass, const Gfx::PRenderPass& renderPass,
@@ -65,7 +65,7 @@ Job BasePassMeshProcessor::processMeshBatch(
} }
std::unique_lock lock(commandLock); std::unique_lock lock(commandLock);
renderCommands.add(renderCommand); renderCommands.add(renderCommand);
co_return; //co_return;
} }
BasePass::BasePass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source) BasePass::BasePass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source)
@@ -156,9 +156,10 @@ MainJob BasePass::render()
List<Job> jobs; List<Job> jobs;
for (auto &&meshBatch : passData.staticDrawList) for (auto &&meshBatch : passData.staticDrawList)
{ {
jobs.add(processor->processMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets)); //jobs.add(
processor->processMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets);
} }
co_await Job::all(jobs); //co_await Job::all(jobs);
graphics->executeCommands(processor->getRenderCommands()); graphics->executeCommands(processor->getRenderCommands());
graphics->endRenderPass(); graphics->endRenderPass();
co_return; co_return;
+1 -1
View File
@@ -11,7 +11,7 @@ public:
BasePassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics, uint8 translucentBasePass); BasePassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics, uint8 translucentBasePass);
virtual ~BasePassMeshProcessor(); virtual ~BasePassMeshProcessor();
virtual Job processMeshBatch( virtual void processMeshBatch(
const MeshBatch& batch, const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent, // const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass, const Gfx::PRenderPass& renderPass,
@@ -18,7 +18,7 @@ DepthPrepassMeshProcessor::~DepthPrepassMeshProcessor()
{ {
} }
Job DepthPrepassMeshProcessor::processMeshBatch( void DepthPrepassMeshProcessor::processMeshBatch(
const MeshBatch& batch, const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent, // const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass, const Gfx::PRenderPass& renderPass,
@@ -27,7 +27,7 @@ Job DepthPrepassMeshProcessor::processMeshBatch(
Array<Gfx::PDescriptorSet> descriptorSets, Array<Gfx::PDescriptorSet> descriptorSets,
int32 /*staticMeshId*/) int32 /*staticMeshId*/)
{ {
std::cout << "Depth job started" << std::endl; //std::cout << "Depth job started" << std::endl;
PMaterialAsset material = batch.material; PMaterialAsset material = batch.material;
//const Gfx::MaterialShadingModel shadingModel = material->getShadingModel(); //const Gfx::MaterialShadingModel shadingModel = material->getShadingModel();
@@ -63,8 +63,8 @@ Job DepthPrepassMeshProcessor::processMeshBatch(
} }
std::unique_lock lock(commandLock); std::unique_lock lock(commandLock);
renderCommands.add(renderCommand); renderCommands.add(renderCommand);
std::cout << "Finished depth job" << std::endl; //std::cout << "Finished depth job" << std::endl;
co_return; //co_return;
} }
DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source) DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source)
@@ -127,10 +127,11 @@ MainJob DepthPrepass::render()
List<Job> jobs; List<Job> jobs;
for (auto &&meshBatch : passData.staticDrawList) for (auto &&meshBatch : passData.staticDrawList)
{ {
jobs.add(processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets)); //jobs.add(
processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets);
} }
co_await Job::all(jobs); //co_await Job::all(jobs);
std::cout << "Finished waiting depth jobs " << std::endl; //std::cout << "Finished waiting depth jobs " << std::endl;
graphics->executeCommands(processor->getRenderCommands()); graphics->executeCommands(processor->getRenderCommands());
graphics->endRenderPass(); graphics->endRenderPass();
co_return; co_return;
@@ -11,7 +11,7 @@ public:
DepthPrepassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics); DepthPrepassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics);
virtual ~DepthPrepassMeshProcessor(); virtual ~DepthPrepassMeshProcessor();
virtual Job processMeshBatch( virtual void processMeshBatch(
const MeshBatch& batch, const MeshBatch& batch,
const Gfx::PRenderPass& renderPass, const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout, Gfx::PPipelineLayout pipelineLayout,
@@ -75,7 +75,7 @@ MainJob LightCullingPass::beginFrame()
lightEnvDescriptorSet->updateBuffer(2, pointLightBuffer); lightEnvDescriptorSet->updateBuffer(2, pointLightBuffer);
lightEnvDescriptorSet->updateBuffer(3, numPointLightBuffer); lightEnvDescriptorSet->updateBuffer(3, numPointLightBuffer);
lightEnvDescriptorSet->writeChanges(); lightEnvDescriptorSet->writeChanges();
std::cout << "Finished light culling beginFrame()" << std::endl; //std::cout << "Finished light culling beginFrame()" << std::endl;
co_return; co_return;
} }
@@ -17,7 +17,7 @@ public:
protected: protected:
PScene scene; PScene scene;
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
virtual Job processMeshBatch( virtual void processMeshBatch(
const MeshBatch& batch, const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent, // const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass, const Gfx::PRenderPass& renderPass,
@@ -74,7 +74,7 @@ void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFrame
beginInfo.framebuffer = framebuffer->getHandle(); beginInfo.framebuffer = framebuffer->getHandle();
vkCmdBeginRenderPass(handle, &beginInfo, renderPass->getSubpassContents()); vkCmdBeginRenderPass(handle, &beginInfo, renderPass->getSubpassContents());
state = State::RenderPassActive; state = State::RenderPassActive;
std::cout << "Beginning renderPass" << std::endl; //std::cout << "Beginning renderPass" << std::endl;
} }
void CmdBuffer::endRenderPass() void CmdBuffer::endRenderPass()
@@ -82,7 +82,7 @@ void CmdBuffer::endRenderPass()
std::unique_lock lock(handleLock); std::unique_lock lock(handleLock);
vkCmdEndRenderPass(handle); vkCmdEndRenderPass(handle);
state = State::InsideBegin; state = State::InsideBegin;
std::cout << "Ending renderPass" << std::endl; //std::cout << "Ending renderPass" << std::endl;
} }
void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands) void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
@@ -9,105 +9,105 @@ using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
DescriptorLayout::DescriptorLayout(PGraphics graphics, const std::string& name) DescriptorLayout::DescriptorLayout(PGraphics graphics, const std::string& name)
: Gfx::DescriptorLayout(name) : Gfx::DescriptorLayout(name)
, graphics(graphics) , graphics(graphics)
, layoutHandle(VK_NULL_HANDLE) , layoutHandle(VK_NULL_HANDLE)
{ {
} }
DescriptorLayout::~DescriptorLayout() DescriptorLayout::~DescriptorLayout()
{ {
if (layoutHandle != VK_NULL_HANDLE) if (layoutHandle != VK_NULL_HANDLE)
{ {
vkDestroyDescriptorSetLayout(graphics->getDevice(), layoutHandle, nullptr); vkDestroyDescriptorSetLayout(graphics->getDevice(), layoutHandle, nullptr);
} }
} }
void DescriptorLayout::create() void DescriptorLayout::create()
{ {
if (layoutHandle != VK_NULL_HANDLE) if (layoutHandle != VK_NULL_HANDLE)
{ {
return; return;
} }
bindings.resize(descriptorBindings.size()); bindings.resize(descriptorBindings.size());
for (size_t i = 0; i < descriptorBindings.size(); ++i) for (size_t i = 0; i < descriptorBindings.size(); ++i)
{ {
VkDescriptorSetLayoutBinding &binding = bindings[i]; VkDescriptorSetLayoutBinding &binding = bindings[i];
const Gfx::DescriptorBinding &rhiBinding = descriptorBindings[i]; const Gfx::DescriptorBinding &rhiBinding = descriptorBindings[i];
binding.binding = rhiBinding.binding; binding.binding = rhiBinding.binding;
binding.descriptorCount = rhiBinding.descriptorCount; binding.descriptorCount = rhiBinding.descriptorCount;
binding.descriptorType = cast(rhiBinding.descriptorType); binding.descriptorType = cast(rhiBinding.descriptorType);
binding.stageFlags = rhiBinding.shaderStages; binding.stageFlags = rhiBinding.shaderStages;
binding.pImmutableSamplers = nullptr; binding.pImmutableSamplers = nullptr;
} }
VkDescriptorSetLayoutCreateInfo createInfo = VkDescriptorSetLayoutCreateInfo createInfo =
init::DescriptorSetLayoutCreateInfo(bindings.data(), (uint32)bindings.size()); init::DescriptorSetLayoutCreateInfo(bindings.data(), (uint32)bindings.size());
VK_CHECK(vkCreateDescriptorSetLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle)); VK_CHECK(vkCreateDescriptorSetLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
allocator = new DescriptorAllocator(graphics, *this); allocator = new DescriptorAllocator(graphics, *this);
boost::crc_32_type result; boost::crc_32_type result;
result.process_bytes(bindings.data(), sizeof(VkDescriptorSetLayoutBinding) * bindings.size()); result.process_bytes(bindings.data(), sizeof(VkDescriptorSetLayoutBinding) * bindings.size());
hash = result.checksum(); hash = result.checksum();
} }
PipelineLayout::~PipelineLayout() PipelineLayout::~PipelineLayout()
{ {
if (layoutHandle != VK_NULL_HANDLE) if (layoutHandle != VK_NULL_HANDLE)
{ {
vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr); vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr);
} }
} }
static Map<uint32, VkPipelineLayout> layoutCache; static Map<uint32, VkPipelineLayout> layoutCache;
void PipelineLayout::create() void PipelineLayout::create()
{ {
vulkanDescriptorLayouts.resize(descriptorSetLayouts.size()); vulkanDescriptorLayouts.resize(descriptorSetLayouts.size());
for (size_t i = 0; i < descriptorSetLayouts.size(); ++i) for (size_t i = 0; i < descriptorSetLayouts.size(); ++i)
{ {
// There could be unused descriptor set indices // There could be unused descriptor set indices
if(descriptorSetLayouts[i] == nullptr) if(descriptorSetLayouts[i] == nullptr)
{ {
vulkanDescriptorLayouts[i] = VK_NULL_HANDLE; vulkanDescriptorLayouts[i] = VK_NULL_HANDLE;
continue; continue;
} }
PDescriptorLayout layout = descriptorSetLayouts[i].cast<DescriptorLayout>(); PDescriptorLayout layout = descriptorSetLayouts[i].cast<DescriptorLayout>();
layout->create(); layout->create();
vulkanDescriptorLayouts[i] = layout->getHandle(); vulkanDescriptorLayouts[i] = layout->getHandle();
} }
VkPipelineLayoutCreateInfo createInfo = VkPipelineLayoutCreateInfo createInfo =
init::PipelineLayoutCreateInfo(vulkanDescriptorLayouts.data(), (uint32)vulkanDescriptorLayouts.size()); init::PipelineLayoutCreateInfo(vulkanDescriptorLayouts.data(), (uint32)vulkanDescriptorLayouts.size());
Array<VkPushConstantRange> vkPushConstants(pushConstants.size()); Array<VkPushConstantRange> vkPushConstants(pushConstants.size());
for (size_t i = 0; i < pushConstants.size(); i++) for (size_t i = 0; i < pushConstants.size(); i++)
{ {
vkPushConstants[i].offset = pushConstants[i].offset; vkPushConstants[i].offset = pushConstants[i].offset;
vkPushConstants[i].size = pushConstants[i].size; vkPushConstants[i].size = pushConstants[i].size;
vkPushConstants[i].stageFlags = (VkShaderStageFlagBits)pushConstants[i].stageFlags; vkPushConstants[i].stageFlags = (VkShaderStageFlagBits)pushConstants[i].stageFlags;
} }
createInfo.pushConstantRangeCount = (uint32)vkPushConstants.size(); createInfo.pushConstantRangeCount = (uint32)vkPushConstants.size();
createInfo.pPushConstantRanges = vkPushConstants.data(); createInfo.pPushConstantRanges = vkPushConstants.data();
boost::crc_32_type result; boost::crc_32_type result;
result.process_bytes(createInfo.pPushConstantRanges, sizeof(VkPushConstantRange) * createInfo.pushConstantRangeCount); result.process_bytes(createInfo.pPushConstantRanges, sizeof(VkPushConstantRange) * createInfo.pushConstantRangeCount);
result.process_bytes(createInfo.pSetLayouts, sizeof(VkDescriptorSetLayout) * createInfo.setLayoutCount); result.process_bytes(createInfo.pSetLayouts, sizeof(VkDescriptorSetLayout) * createInfo.setLayoutCount);
layoutHash = result.checksum(); layoutHash = result.checksum();
if(layoutCache[layoutHash] != VK_NULL_HANDLE) if(layoutCache[layoutHash] != VK_NULL_HANDLE)
{ {
layoutHandle = layoutCache[layoutHash]; layoutHandle = layoutCache[layoutHash];
return; return;
} }
VK_CHECK(vkCreatePipelineLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle)); VK_CHECK(vkCreatePipelineLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
layoutCache[layoutHash] = layoutHandle; layoutCache[layoutHash] = layoutHandle;
} }
void PipelineLayout::reset() void PipelineLayout::reset()
{ {
vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr); vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr);
descriptorSetLayouts.clear(); descriptorSetLayouts.clear();
pushConstants.clear(); pushConstants.clear();
} }
DescriptorSet::~DescriptorSet() DescriptorSet::~DescriptorSet()
@@ -116,206 +116,219 @@ DescriptorSet::~DescriptorSet()
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer)
{ {
PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>(); PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>();
UniformBuffer* cachedBuffer = reinterpret_cast<UniformBuffer*>(cachedData[binding]); UniformBuffer* cachedBuffer = reinterpret_cast<UniformBuffer*>(cachedData[binding]);
if(vulkanBuffer->isDataEquals(cachedBuffer)) if(vulkanBuffer->isDataEquals(cachedBuffer))
{ {
std::cout << "uniform data equal, skip" << std::endl; std::cout << "uniform data equal, skip" << std::endl;
return; return;
} }
bufferInfos.add(init::DescriptorBufferInfo(vulkanBuffer->getHandle(), 0, vulkanBuffer->getSize())); bufferInfos.add(init::DescriptorBufferInfo(vulkanBuffer->getHandle(), 0, vulkanBuffer->getSize()));
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, binding, &bufferInfos.back()); VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, binding, &bufferInfos.back());
writeDescriptors.add(writeDescriptor); writeDescriptors.add(writeDescriptor);
cachedData[binding] = new UniformBuffer(*vulkanBuffer.getHandle()); cachedData[binding] = new UniformBuffer(*vulkanBuffer.getHandle());
} }
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer) void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PStructuredBuffer uniformBuffer)
{ {
PStructuredBuffer vulkanBuffer = uniformBuffer.cast<StructuredBuffer>(); PStructuredBuffer vulkanBuffer = uniformBuffer.cast<StructuredBuffer>();
StructuredBuffer* cachedBuffer = reinterpret_cast<StructuredBuffer*>(cachedData[binding]); StructuredBuffer* cachedBuffer = reinterpret_cast<StructuredBuffer*>(cachedData[binding]);
if(vulkanBuffer.getHandle() == cachedBuffer) if(vulkanBuffer.getHandle() == cachedBuffer)
{ {
return; return;
} }
bufferInfos.add(init::DescriptorBufferInfo(vulkanBuffer->getHandle(), 0, vulkanBuffer->getSize())); bufferInfos.add(init::DescriptorBufferInfo(vulkanBuffer->getHandle(), 0, vulkanBuffer->getSize()));
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, binding, &bufferInfos.back()); VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, binding, &bufferInfos.back());
writeDescriptors.add(writeDescriptor); writeDescriptors.add(writeDescriptor);
cachedData[binding] = vulkanBuffer.getHandle(); cachedData[binding] = vulkanBuffer.getHandle();
} }
void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSamplerState samplerState) void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSamplerState samplerState)
{ {
PSamplerState vulkanSampler = samplerState.cast<SamplerState>(); PSamplerState vulkanSampler = samplerState.cast<SamplerState>();
SamplerState* cachedSampler = reinterpret_cast<SamplerState*>(cachedData[binding]); SamplerState* cachedSampler = reinterpret_cast<SamplerState*>(cachedData[binding]);
if(vulkanSampler.getHandle() == cachedSampler) if(vulkanSampler.getHandle() == cachedSampler)
{ {
return; return;
} }
VkDescriptorImageInfo imageInfo = VkDescriptorImageInfo imageInfo =
init::DescriptorImageInfo( init::DescriptorImageInfo(
vulkanSampler->sampler, vulkanSampler->sampler,
VK_NULL_HANDLE, VK_NULL_HANDLE,
VK_IMAGE_LAYOUT_UNDEFINED); VK_IMAGE_LAYOUT_UNDEFINED);
imageInfos.add(imageInfo); imageInfos.add(imageInfo);
VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_SAMPLER, binding, &imageInfos.back()); VkWriteDescriptorSet writeDescriptor = init::WriteDescriptorSet(setHandle, VK_DESCRIPTOR_TYPE_SAMPLER, binding, &imageInfos.back());
writeDescriptors.add(writeDescriptor); writeDescriptors.add(writeDescriptor);
cachedData[binding] = vulkanSampler.getHandle(); cachedData[binding] = vulkanSampler.getHandle();
} }
void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSamplerState samplerState) void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSamplerState samplerState)
{ {
TextureHandle* vulkanTexture = TextureBase::cast(texture); TextureHandle* vulkanTexture = TextureBase::cast(texture);
TextureHandle* cachedTexture = reinterpret_cast<TextureHandle*>(cachedData[binding]); TextureHandle* cachedTexture = reinterpret_cast<TextureHandle*>(cachedData[binding]);
if(vulkanTexture == cachedTexture) if(vulkanTexture == cachedTexture)
{ {
return; return;
} }
//It is assumed that the image is in the correct layout //It is assumed that the image is in the correct layout
VkDescriptorImageInfo imageInfo = VkDescriptorImageInfo imageInfo =
init::DescriptorImageInfo( init::DescriptorImageInfo(
VK_NULL_HANDLE, VK_NULL_HANDLE,
vulkanTexture->getView(), vulkanTexture->getView(),
cast(vulkanTexture->getLayout())); cast(vulkanTexture->getLayout()));
if (samplerState != nullptr) if (samplerState != nullptr)
{ {
PSamplerState vulkanSampler = samplerState.cast<SamplerState>(); PSamplerState vulkanSampler = samplerState.cast<SamplerState>();
imageInfo.sampler = vulkanSampler->sampler; imageInfo.sampler = vulkanSampler->sampler;
} }
imageInfos.add(imageInfo); imageInfos.add(imageInfo);
VkWriteDescriptorSet writeDescriptor = VkWriteDescriptorSet writeDescriptor =
init::WriteDescriptorSet( init::WriteDescriptorSet(
setHandle, setHandle,
samplerState != nullptr ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, samplerState != nullptr ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
binding, binding,
&imageInfos.back()); &imageInfos.back());
if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT) if (vulkanTexture->getUsage() & VK_IMAGE_USAGE_STORAGE_BIT)
{ {
writeDescriptor.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; writeDescriptor.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
} }
writeDescriptors.add(writeDescriptor); writeDescriptors.add(writeDescriptor);
cachedData[binding] = vulkanTexture; cachedData[binding] = vulkanTexture;
} }
bool DescriptorSet::operator<(Gfx::PDescriptorSet other) bool DescriptorSet::operator<(Gfx::PDescriptorSet other)
{ {
PDescriptorSet otherSet = other.cast<DescriptorSet>(); PDescriptorSet otherSet = other.cast<DescriptorSet>();
return this < otherSet.getHandle(); return this < otherSet.getHandle();
} }
uint32 DescriptorSet::getSetIndex() const uint32 DescriptorSet::getSetIndex() const
{ {
return owner->getLayout().getSetIndex(); return owner->getLayout().getSetIndex();
} }
void DescriptorSet::writeChanges() void DescriptorSet::writeChanges()
{ {
if (writeDescriptors.size() > 0) if (writeDescriptors.size() > 0)
{ {
if(isCurrentlyBound()) if(isCurrentlyBound())
{ {
std::cout << "Descriptor currently bound, allocate a new one instead" << std::endl; std::cout << "Descriptor currently bound, allocate a new one instead" << std::endl;
assert(!isCurrentlyBound()); assert(!isCurrentlyBound());
} }
vkUpdateDescriptorSets(graphics->getDevice(), (uint32)writeDescriptors.size(), writeDescriptors.data(), 0, nullptr); vkUpdateDescriptorSets(graphics->getDevice(), (uint32)writeDescriptors.size(), writeDescriptors.data(), 0, nullptr);
writeDescriptors.clear(); writeDescriptors.clear();
imageInfos.clear(); imageInfos.clear();
bufferInfos.clear(); bufferInfos.clear();
} }
} }
DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout) DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout &layout)
: graphics(graphics) : graphics(graphics)
, layout(layout) , layout(layout)
{ {
for(uint32 i = 0; i < cachedHandles.size(); ++i) for(uint32 i = 0; i < cachedHandles.size(); ++i)
{ {
cachedHandles[i] = nullptr; cachedHandles[i] = nullptr;
} }
uint32 perTypeSizes[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]; // TODO: FIX ENUM uint32 perTypeSizes[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]; // TODO: FIX ENUM
std::memset(perTypeSizes, 0, sizeof(perTypeSizes)); std::memset(perTypeSizes, 0, sizeof(perTypeSizes));
for (uint32 i = 0; i < layout.getBindings().size(); ++i) for (uint32 i = 0; i < layout.getBindings().size(); ++i)
{ {
auto &binding = layout.getBindings()[i]; auto &binding = layout.getBindings()[i];
int typeIndex = binding.descriptorType; int typeIndex = binding.descriptorType;
perTypeSizes[typeIndex] += 256; perTypeSizes[typeIndex] += 256;
} }
Array<VkDescriptorPoolSize> poolSizes; Array<VkDescriptorPoolSize> poolSizes;
for (uint32 i = 0; i < VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; ++i) for (uint32 i = 0; i < VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; ++i)
{ {
if (perTypeSizes[i] > 0) if (perTypeSizes[i] > 0)
{ {
VkDescriptorPoolSize size; VkDescriptorPoolSize size;
size.descriptorCount = perTypeSizes[i]; size.descriptorCount = perTypeSizes[i];
size.type = (VkDescriptorType)i; size.type = (VkDescriptorType)i;
poolSizes.add(size); poolSizes.add(size);
} }
} }
VkDescriptorPoolCreateInfo createInfo VkDescriptorPoolCreateInfo createInfo
= init::DescriptorPoolCreateInfo( = init::DescriptorPoolCreateInfo(
(uint32)poolSizes.size(), (uint32)poolSizes.size(),
poolSizes.data(), poolSizes.data(),
maxSets * Gfx::numFramesBuffered); maxSets * Gfx::numFramesBuffered);
VK_CHECK(vkCreateDescriptorPool(graphics->getDevice(), &createInfo, nullptr, &poolHandle)); VK_CHECK(vkCreateDescriptorPool(graphics->getDevice(), &createInfo, nullptr, &poolHandle));
} }
DescriptorAllocator::~DescriptorAllocator() DescriptorAllocator::~DescriptorAllocator()
{ {
vkDestroyDescriptorPool(graphics->getDevice(), poolHandle, nullptr); vkDestroyDescriptorPool(graphics->getDevice(), poolHandle, nullptr);
graphics = nullptr; graphics = nullptr;
if(nextAlloc)
{
delete nextAlloc;
}
} }
void DescriptorAllocator::allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet) void DescriptorAllocator::allocateDescriptorSet(Gfx::PDescriptorSet &descriptorSet)
{ {
VkDescriptorSetLayout layoutHandle = layout.getHandle(); VkDescriptorSetLayout layoutHandle = layout.getHandle();
VkDescriptorSetAllocateInfo allocInfo = VkDescriptorSetAllocateInfo allocInfo =
init::DescriptorSetAllocateInfo(poolHandle, &layoutHandle, 1); init::DescriptorSetAllocateInfo(poolHandle, &layoutHandle, 1);
for(uint32 setIndex = 0; setIndex < cachedHandles.size(); ++setIndex) for(uint32 setIndex = 0; setIndex < cachedHandles.size(); ++setIndex)
{ {
if(cachedHandles[setIndex] == nullptr) if(cachedHandles[setIndex] == nullptr)
{ {
cachedHandles[setIndex] = new DescriptorSet(graphics, this); cachedHandles[setIndex] = new DescriptorSet(graphics, this);
} }
if(cachedHandles[setIndex]->isCurrentlyBound() || cachedHandles[setIndex]->isCurrentlyInUse()) if(cachedHandles[setIndex]->isCurrentlyBound() || cachedHandles[setIndex]->isCurrentlyInUse())
{ {
// Currently in use, skip // Currently in use, skip
continue; continue;
} }
if(cachedHandles[setIndex]->getHandle() == VK_NULL_HANDLE) if(cachedHandles[setIndex]->getHandle() == VK_NULL_HANDLE)
{ {
//If it hasnt been initialized, allocate it //If it hasnt been initialized, allocate it
VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &cachedHandles[setIndex]->setHandle)); VK_CHECK(vkAllocateDescriptorSets(graphics->getDevice(), &allocInfo, &cachedHandles[setIndex]->setHandle));
} }
cachedHandles[setIndex]->allocate(); cachedHandles[setIndex]->allocate();
descriptorSet = cachedHandles[setIndex]; descriptorSet = cachedHandles[setIndex];
PDescriptorSet vulkanSet = descriptorSet.cast<DescriptorSet>(); PDescriptorSet vulkanSet = descriptorSet.cast<DescriptorSet>();
vulkanSet->cachedData.resize(layout.bindings.size()); vulkanSet->cachedData.resize(layout.bindings.size());
// Not really pretty, but this way the set knows which ones are valid // Not really pretty, but this way the set knows which ones are valid
std::memset(vulkanSet->cachedData.data(), 0, sizeof(void*) * vulkanSet->cachedData.size()); std::memset(vulkanSet->cachedData.data(), 0, sizeof(void*) * vulkanSet->cachedData.size());
//Found set, stop searching //Found set, stop searching
return; return;
} }
throw std::logic_error("Out of descriptor sets"); if(nextAlloc == nullptr)
{
nextAlloc = new DescriptorAllocator(graphics, layout);
}
nextAlloc->allocateDescriptorSet(descriptorSet);
//throw std::logic_error("Out of descriptor sets");
} }
void DescriptorAllocator::reset() void DescriptorAllocator::reset()
{ {
for(uint32 i = 0; i < cachedHandles.size(); ++i) for(uint32 i = 0; i < cachedHandles.size(); ++i)
{ {
if(cachedHandles[i] == nullptr) if(cachedHandles[i] == nullptr)
{ {
return; return;
} }
cachedHandles[i]->free(); cachedHandles[i]->free();
} }
if(nextAlloc != nullptr)
{
nextAlloc->reset();
}
} }
@@ -145,6 +145,7 @@ private:
const static int maxSets = 64; const static int maxSets = 64;
StaticArray<PDescriptorSet, maxSets> cachedHandles; StaticArray<PDescriptorSet, maxSets> cachedHandles;
VkDescriptorPool poolHandle; VkDescriptorPool poolHandle;
DescriptorAllocator* nextAlloc = nullptr;
}; };
DEFINE_REF(DescriptorAllocator) DEFINE_REF(DescriptorAllocator)
} // namespace Vulkan } // namespace Vulkan
+5 -3
View File
@@ -3,6 +3,8 @@
using namespace Seele; using namespace Seele;
std::atomic_uint64_t Seele::globalCounter;
Event::Event() Event::Event()
: flag(new std::atomic_bool()) : flag(new std::atomic_bool())
{ {
@@ -54,7 +56,6 @@ ThreadPool::~ThreadPool()
void ThreadPool::enqueueWaiting(Event &event, Promise* job) void ThreadPool::enqueueWaiting(Event &event, Promise* job)
{ {
assert(!job->done()); assert(!job->done());
assert(job->schedulable);
if(event == nullptr) if(event == nullptr)
{ {
std::unique_lock lock(jobQueueLock); std::unique_lock lock(jobQueueLock);
@@ -72,8 +73,7 @@ void ThreadPool::enqueueWaiting(Event &event, Promise* job)
void ThreadPool::enqueueWaiting(Event &event, MainPromise* job) void ThreadPool::enqueueWaiting(Event &event, MainPromise* job)
{ {
assert(!job->done()); assert(!job->done());
assert(job->schedulable); if(event == nullptr || event)
if(event == nullptr)
{ {
std::unique_lock lock(mainJobLock); std::unique_lock lock(mainJobLock);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl; //std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
@@ -98,6 +98,7 @@ void ThreadPool::notify(Event &event)
{ {
//assert(job.id != -1ull); //assert(job.id != -1ull);
//std::cout << "Waking up " << job->finishedEvent.name << std::endl; //std::cout << "Waking up " << job->finishedEvent.name << std::endl;
job->state = Promise::State::SCHEDULED;
jobQueue.add(job); jobQueue.add(job);
jobQueueCV.notify_one(); jobQueueCV.notify_one();
} }
@@ -111,6 +112,7 @@ void ThreadPool::notify(Event &event)
{ {
//assert(job.id != -1ull); //assert(job.id != -1ull);
//std::cout << "Waking up main " << job->finishedEvent.name << std::endl; //std::cout << "Waking up main " << job->finishedEvent.name << std::endl;
job->state = MainPromise::State::SCHEDULED;
mainJobs.add(job); mainJobs.add(job);
mainJobCV.notify_one(); mainJobCV.notify_one();
} }
+37 -9
View File
@@ -45,12 +45,20 @@ private:
friend class ThreadPool; friend class ThreadPool;
}; };
static std::atomic_uint64_t globalCounter; extern std::atomic_uint64_t globalCounter;
template<bool MainJob> template<bool MainJob>
struct JobBase; struct JobBase;
template<bool MainJob> template<bool MainJob>
struct JobPromiseBase struct JobPromiseBase
{ {
enum class State
{
READY,
WAITING,
SCHEDULED,
EXECUTING,
DONE
};
JobPromiseBase() JobPromiseBase()
{ {
handle = std::coroutine_handle<JobPromiseBase<MainJob>>::from_promise(*this); handle = std::coroutine_handle<JobPromiseBase<MainJob>>::from_promise(*this);
@@ -71,11 +79,12 @@ struct JobPromiseBase
void resume() void resume()
{ {
std::unique_lock lock(promiseLock); std::unique_lock lock(promiseLock);
if(handle && !handle.done()) if(!handle || handle.done() || executing())
{ {
handle.resume(); return;
schedulable = true;
} }
state = State::EXECUTING;
handle.resume();
} }
void setContinuation(JobPromiseBase* cont) void setContinuation(JobPromiseBase* cont)
{ {
@@ -88,9 +97,26 @@ struct JobPromiseBase
{ {
return handle.done(); return handle.done();
} }
bool scheduled()
{
return state == State::SCHEDULED;
}
bool waiting()
{
return state == State::WAITING;
}
bool executing()
{
return state == State::EXECUTING;
}
bool ready()
{
return state == State::READY;
}
void raise() void raise()
{ {
std::unique_lock lock(promiseLock); std::unique_lock lock(promiseLock);
state = State::DONE;
finishedEvent.raise(); finishedEvent.raise();
} }
void reset() void reset()
@@ -100,22 +126,23 @@ struct JobPromiseBase
} }
void enqueue(Event& event) void enqueue(Event& event)
{ {
if(!handle || handle.done() || !schedulable) // no need to lock here, as it is only called while executing, where the lock is already held
if(!handle || handle.done() || waiting() || scheduled())
{ {
return; return;
} }
state = State::WAITING;
getGlobalThreadPool().enqueueWaiting(event, this); getGlobalThreadPool().enqueueWaiting(event, this);
schedulable = false;
} }
void schedule() void schedule()
{ {
std::unique_lock lock(promiseLock); std::unique_lock lock(promiseLock);
if(!handle || handle.done() || !schedulable) if(!handle || done() || !ready())
{ {
return; return;
} }
state = (precondition == nullptr) ? State::SCHEDULED : State::WAITING;
getGlobalThreadPool().enqueueWaiting(precondition, this); getGlobalThreadPool().enqueueWaiting(precondition, this);
schedulable = false;
} }
std::mutex promiseLock; std::mutex promiseLock;
@@ -124,7 +151,7 @@ struct JobPromiseBase
uint64 id; uint64 id;
Event finishedEvent; Event finishedEvent;
Event precondition = nullptr; Event precondition = nullptr;
bool schedulable = true; State state = State::READY;
}; };
template<bool MainJob = false> template<bool MainJob = false>
@@ -176,6 +203,7 @@ public:
} }
Event operator co_await() Event operator co_await()
{ {
promise->schedule();
return promise->finishedEvent; return promise->finishedEvent;
} }
static JobBase all() = delete; static JobBase all() = delete;
+19 -19
View File
@@ -18,29 +18,29 @@ Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const Viewpo
{ {
scene = new Scene(graphics); scene = new Scene(graphics);
scene->addActor(activeCamera); scene->addActor(activeCamera);
/*AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Sword_Ayaka_Tex_Body_Diffuse.png"); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Sword_Ayaka_Tex_Body_Diffuse.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Sword_Ayaka_Tex_Body_Lightmap.png"); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Sword_Ayaka_Tex_Body_Lightmap.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Sword_Ayaka_Tex_Face_Diffuse.png"); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Sword_Ayaka_Tex_Face_Diffuse.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Sword_Ayaka_Tex_Hair_Diffuse.png"); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Sword_Ayaka_Tex_Hair_Diffuse.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Sword_Ayaka_Tex_Hair_Lightmap.png"); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Sword_Ayaka_Tex_Hair_Lightmap.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Tex_FaceLightmap.png"); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Avatar_Girl_Tex_FaceLightmap.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Ayaka.fbx"); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ayaka\\Ayaka.fbx");
PPrimitiveComponent ayaka = new PrimitiveComponent(AssetRegistry::findMesh("Ayaka")); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ely\\Ely.fbx");
ayaka->addWorldTranslation(Vector(0, 0, 0)); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Cube\\cube.obj");
ayaka->setWorldScale(Vector(10, 10, 10)); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Plane\\plane.fbx");
scene->addPrimitiveComponent(ayaka);*/ srand(time(NULL));
for(uint32 i = 0; i < 100; ++i)
{
PPrimitiveComponent ayaka = new PrimitiveComponent(AssetRegistry::findMesh("Ayaka"));
ayaka->addWorldTranslation(Vector(((float)rand() / RAND_MAX) * 100, 0, ((float)rand()/RAND_MAX) * 100));
ayaka->setWorldScale(Vector(10, 10, 10));
scene->addPrimitiveComponent(ayaka);
}
AssetRegistry::importFile("D:\\Private\\Programming\\Unreal Engine\\Assets\\Ely\\Ely.fbx");
AssetRegistry::importFile("D:\\Private\\Programming\\Unreal Engine\\Assets\\Cube\\cube.obj");
AssetRegistry::importFile("D:\\Private\\Programming\\Unreal Engine\\Assets\\Plane\\plane.fbx");
PPrimitiveComponent plane = new PrimitiveComponent(AssetRegistry::findMesh("plane")); PPrimitiveComponent plane = new PrimitiveComponent(AssetRegistry::findMesh("plane"));
plane->setWorldScale(Vector(100, 100, 100)); plane->setWorldScale(Vector(100, 100, 100));
PPrimitiveComponent arissa = new PrimitiveComponent(AssetRegistry::findMesh("Ely"));
arissa->addWorldTranslation(Vector(0, 0, 100));
arissa->setWorldScale(Vector(0.1f, 0.1f, 0.1f));
scene->addPrimitiveComponent(plane); scene->addPrimitiveComponent(plane);
scene->addPrimitiveComponent(arissa);
PRenderGraphResources resources = new RenderGraphResources(); PRenderGraphResources resources = new RenderGraphResources();
depthPrepass.setResources(resources); depthPrepass.setResources(resources);
lightCullingPass.setResources(resources); lightCullingPass.setResources(resources);
+1 -1
View File
@@ -8,7 +8,7 @@ View::View(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &vi
: graphics(graphics) : graphics(graphics)
, owner(window) , owner(window)
, name(name) , name(name)
, renderFinishedEvent(name + "RenderFinished") , renderFinishedEvent(std::format("{}RenderFinished", name))
{ {
viewport = graphics->createViewport(owner->getGfxHandle(), viewportInfo); viewport = graphics->createViewport(owner->getGfxHandle(), viewportInfo);
} }
+4 -4
View File
@@ -9,7 +9,7 @@ using namespace Seele;
int main() int main()
{ {
PWindowManager windowManager = new WindowManager(); PWindowManager windowManager = new WindowManager();
AssetRegistry::init("D:\\Private\\Programming\\C++\\TestSeeleProject"); AssetRegistry::init("C:\\Users\\Dynamitos\\TestSeeleProject");
WindowCreateInfo mainWindowInfo; WindowCreateInfo mainWindowInfo;
mainWindowInfo.title = "SeeleEngine"; mainWindowInfo.title = "SeeleEngine";
mainWindowInfo.width = 1280; mainWindowInfo.width = 1280;
@@ -34,9 +34,9 @@ int main()
//PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo); //PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo);
//window->addView(inspectorView); //window->addView(inspectorView);
sceneView->setFocused(); sceneView->setFocused();
{
window->render(); window->render();
}
getGlobalThreadPool().threadLoop(true); getGlobalThreadPool().threadLoop(true);
return 0; return 0;
} }