Basic mutability framework

This commit is contained in:
Dynamitos
2022-01-12 14:40:26 +01:00
parent b2718dde70
commit 6d48267ec2
72 changed files with 1781 additions and 1341 deletions
+1 -1
View File
@@ -77,7 +77,7 @@
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/Seele_unit_tests.exe",
"args": [],
"args": ["--detect_memory_leaks=15533"],
"stopAtEntry": false,
"console": "internalConsole",
"cwd": "${workspaceRoot}/bin/Debug",
+1 -1
View File
@@ -110,7 +110,7 @@ add_subdirectory(src/)
if(MSVC)
set(_CRT_SECURE_NO_WARNINGS)
target_compile_options(SeeleEngine PRIVATE /DEBUG:FASTLINK /Zi)
target_compile_options(SeeleEngine PRIVATE /Zi)
else()
target_compile_options(SeeleEngine PRIVATE -g -Wall -Wextra -Wno-delete-incomplete -pedantic -fcoroutines)
endif()
+1 -1
View File
@@ -5,7 +5,7 @@
"cmakeCommandArgs": "-DUSE_SUPERBUILD=OFF",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"variables": []
"inheritEnvironments": []
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

+1
View File
@@ -9,6 +9,7 @@ Asset::Asset()
, parentDir("")
, extension("")
, status(Status::Uninitialized)
, byteSize(0)
{
}
Asset::Asset(const std::filesystem::path& path)
+2 -2
View File
@@ -28,12 +28,12 @@ public:
std::string getExtension() const;
inline Status getStatus()
{
std::unique_lock lck(lock);
std::scoped_lock lck(lock);
return status;
}
inline void setStatus(Status status)
{
std::unique_lock lck(lock);
std::scoped_lock lck(lock);
this->status = status;
}
protected:
+5 -9
View File
@@ -25,24 +25,20 @@ MeshAsset::~MeshAsset()
}
void MeshAsset::save()
{
boost::archive::text_oarchive archive(getWriteStream());
archive << meshes;
}
void MeshAsset::load()
{
boost::archive::text_iarchive archive(getReadStream());
archive >> meshes;
}
void MeshAsset::addMesh(PMesh mesh)
{
std::unique_lock lck(lock);
meshes.add(mesh);
referencedMaterials.add(mesh->referencedMaterial);
std::scoped_lock lck(lock);
meshes.push_back(mesh);
referencedMaterials.push_back(mesh->referencedMaterial);
}
const Array<PMesh> MeshAsset::getMeshes()
const std::vector<PMesh> MeshAsset::getMeshes()
{
std::unique_lock lck(lock);
std::scoped_lock lck(lock);
return meshes;
}
+3 -3
View File
@@ -15,11 +15,11 @@ public:
virtual void save() override;
virtual void load() override;
void addMesh(PMesh mesh);
const Array<PMesh> getMeshes();
const std::vector<PMesh> getMeshes();
//Workaround while no editor
Array<PMaterialAsset> referencedMaterials;
std::vector<PMaterialAsset> referencedMaterials;
private:
Array<PMesh> meshes;
std::vector<PMesh> meshes;
};
DEFINE_REF(MeshAsset)
} // namespace Seele
+6 -2
View File
@@ -122,7 +122,9 @@ VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gf
vbInfo.resourceData.data = (uint8 *)buffer.data();
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
vbInfo.resourceData.size = sizeof(Vector) * (uint32)buffer.size();
return VertexStreamComponent(graphics->createVertexBuffer(vbInfo), 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT);
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT);
}
VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics)
{
@@ -137,7 +139,9 @@ VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gf
vbInfo.resourceData.data = (uint8 *)buffer.data();
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
vbInfo.resourceData.size = sizeof(Vector2) * (uint32)buffer.size();
return VertexStreamComponent(graphics->createVertexBuffer(vbInfo), 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT);
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT);
}
void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials, Gfx::PGraphics graphics)
{
+2 -2
View File
@@ -14,12 +14,12 @@ public:
virtual void load() override;
void setTexture(Gfx::PTexture texture)
{
std::unique_lock lck(lock);
std::scoped_lock lck(lock);
this->texture = texture;
}
Gfx::PTexture getTexture()
{
std::unique_lock lck(lock);
std::scoped_lock lck(lock);
return texture;
}
private:
+33 -30
View File
@@ -12,10 +12,10 @@
namespace Seele
{
template <typename T, typename Allocator = std::pmr::polymorphic_allocator<T>>
struct Array
{
public:
template <typename T, typename Allocator = std::pmr::polymorphic_allocator<T>>
struct Array
{
public:
template <typename X>
class IteratorBase
{
@@ -118,6 +118,7 @@ namespace Seele
, allocator(alloc)
{
_data = allocateArray(size);
assert(_data != nullptr);
for (size_type i = 0; i < size; ++i)
{
_data[i] = value;
@@ -130,6 +131,7 @@ namespace Seele
, allocator(alloc)
{
_data = allocateArray(size);
assert(_data != nullptr);
for (size_type i = 0; i < size; ++i)
{
std::allocator_traits<allocator_type>::construct(allocator, &_data[i]);
@@ -142,6 +144,7 @@ namespace Seele
, allocator(alloc)
{
_data = allocateArray(init.size());
assert(_data != nullptr);
markIteratorDirty();
std::uninitialized_copy(init.begin(), init.end(), begin());
}
@@ -151,6 +154,7 @@ namespace Seele
, allocator(std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.allocator))
{
_data = allocateArray(other.allocated);
assert(_data != nullptr);
markIteratorDirty();
std::uninitialized_copy(other.begin(), other.end(), begin());
}
@@ -174,17 +178,16 @@ namespace Seele
if (!std::allocator_traits<allocator_type>::is_always_equal::value
&& allocator != other.allocator)
{
deallocateArray(_data, allocated);
_data = nullptr;
clear();
}
allocator = other.allocator;
}
if(_data == nullptr || other.arraySize > allocated)
if (other.arraySize > allocated)
{
if(_data != nullptr)
{
deallocateArray(_data, allocated);
clear();
}
if(_data == nullptr)
{
_data = allocateArray(other.allocated);
allocated = other.allocated;
}
@@ -200,18 +203,11 @@ namespace Seele
{
if constexpr (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
{
if (!std::allocator_traits<allocator_type>::is_always_equal::value
&& allocator != other.allocator)
{
deallocateArray(_data, allocated);
_data = nullptr;
}
allocator = std::move(other.allocator);
}
if (_data != nullptr)
{
deallocateArray(_data, allocated);
_data = nullptr;
clear();
}
allocated = std::move(other.allocated);
arraySize = std::move(other.arraySize);
@@ -286,6 +282,13 @@ namespace Seele
{
return addInternal(std::forward<T>(item));
}
constexpr void addAll(Array other)
{
for(auto value : other)
{
addInternal(value);
}
}
constexpr reference addUnique(const value_type &item = value_type())
{
iterator it;
@@ -349,7 +352,7 @@ namespace Seele
}
for(size_type i = 0; i < arraySize; ++i)
{
_data[i].~T();
std::allocator_traits<allocator_type>::destroy(allocator, &_data[i]);
}
deallocateArray(_data, allocated);
_data = nullptr;
@@ -401,7 +404,7 @@ namespace Seele
}
void pop()
{
_data[--arraySize].~T();
std::allocator_traits<allocator_type>::destroy(allocator, &_data[--arraySize]);
markIteratorDirty();
}
constexpr inline reference operator[](size_type index)
@@ -414,17 +417,17 @@ namespace Seele
assert(index < arraySize);
return _data[index];
}
private:
private:
size_type calculateGrowth(size_type newSize) const
{
const size_type oldCapacity = capacity();
if (oldCapacity > SIZE_MAX - oldCapacity / 2)
if (oldCapacity > SIZE_MAX - oldCapacity)
{
return newSize; // geometric growth would overflow
}
const size_type geometric = oldCapacity + oldCapacity / 2;
const size_type geometric = oldCapacity + oldCapacity;
if (geometric < newSize)
{
@@ -529,12 +532,12 @@ namespace Seele
Iterator endIt;
T *_data = nullptr;
allocator_type allocator;
};
};
template <typename T, size_t N>
struct StaticArray
{
public:
template <typename T, size_t N>
struct StaticArray
{
public:
template <typename X>
class IteratorBase
{
@@ -662,7 +665,7 @@ namespace Seele
{
return beginIt;
}
private:
private:
T _data[N];
iterator beginIt;
iterator endIt;
@@ -674,5 +677,5 @@ namespace Seele
ar & N;
ar & _data;
}
};
};
} // namespace Seele
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="Seele::Array&lt;*&gt;">
<DisplayString>{{ size={arraySize} }}</DisplayString>
<Expand>
<Item Name="[size]" ExcludeView="simple">arraySize</Item>
<Item Name="[allocated]" ExcludeView="simple">allocated</Item>
<ArrayItems>
<Size>arraySize</Size>
<ValuePointer>_data</ValuePointer>
</ArrayItems>
</Type>
</AutoVisualizer>
+1
View File
@@ -1,5 +1,6 @@
target_sources(SeeleEngine
PRIVATE
Array.natvis
Array.h
Map.h
List.h)
+35 -48
View File
@@ -152,15 +152,7 @@ public:
{
if(this != &other)
{
if(root != nullptr)
{
delete root;
}
if(tail != nullptr)
{
delete tail;
}
_size = 0;
clear();
for(const auto& it : other)
{
add(it);
@@ -172,11 +164,8 @@ public:
List& operator=(List&& other)
{
if(this != &other)
{
if(root != nullptr)
{
clear();
}
root = other.root;
tail = other.tail;
beginIt = other.beginIt;
@@ -205,6 +194,7 @@ public:
for (Node *tmp = root; tmp != tail;)
{
tmp = tmp->next;
destroyNode(tmp->prev);
deallocateNode(tmp->prev);
}
deallocateNode(tail);
@@ -216,43 +206,16 @@ public:
//Insert at the end
iterator add(const T &value)
{
if (root == nullptr)
{
root = allocateNode();
tail = root;
}
initializeNode(tail, value);
Node *newTail = allocateNode();
newTail->prev = tail;
newTail->next = nullptr;
tail->next = newTail;
iterator insertedElement(tail);
tail = newTail;
markIteratorDirty();
_size++;
return insertedElement;
return addInternal(value);
}
iterator add(T&& value)
{
if (root == nullptr)
{
root = allocateNode();
tail = root;
}
initializeNode(tail, std::move(value));
Node *newTail = allocateNode();
newTail->prev = tail;
newTail->next = nullptr;
tail->next = newTail;
Iterator insertedElement(tail);
tail = newTail;
markIteratorDirty();
_size++;
return insertedElement;
return addInternal(std::move(value));
}
// takes all elements from other and move-inserts them into
// this, clearing other in the process
void moveElements(List& other){
void moveElements(List& other)
{
tail->prev->next = other.root;
other.root->prev = tail->prev;
_size += other._size;
@@ -309,12 +272,13 @@ public:
}
if(next == nullptr)
{
root = prev;
tail = prev;
}
else
{
next->prev = prev;
}
destroyNode(pos.node);
deallocateNode(pos.node);
markIteratorDirty();
return Iterator(next);
@@ -408,10 +372,33 @@ private:
node->next,
std::forward<Type>(data));
}
void destroyNode(Node* node)
{
std::allocator_traits<NodeAllocator>::destroy(allocator, node);
}
void deallocateNode(Node* node)
{
allocator.deallocate(node, 1);
}
template<typename ValueType>
iterator addInternal(ValueType&& value)
{
if (root == nullptr)
{
root = allocateNode();
tail = root;
}
initializeNode(tail, std::forward<ValueType>(value));
Node* newTail = allocateNode();
newTail->prev = tail;
newTail->next = nullptr;
tail->next = newTail;
Iterator insertedElement(tail);
tail = newTail;
markIteratorDirty();
_size++;
return insertedElement;
}
void markIteratorDirty()
{
beginIt = Iterator(root);
@@ -421,10 +408,10 @@ private:
}
Node *root;
Node *tail;
Iterator beginIt;
Iterator endIt;
ConstIterator cbeginIt;
ConstIterator cendIt;
iterator beginIt;
iterator endIt;
const_iterator cbeginIt;
const_iterator cendIt;
size_type _size;
NodeAllocator allocator;
};
+1 -1
View File
@@ -56,7 +56,7 @@ public:
virtual PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) = 0;
virtual PDescriptorLayout createDescriptorLayout(const std::string& name = "") = 0;
virtual PPipelineLayout createPipelineLayout() = 0;
virtual PPipelineLayout createPipelineLayout(PPipelineLayout baseLayout = nullptr) = 0;
virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) = 0;
+1 -8
View File
@@ -22,20 +22,13 @@ struct GraphicsInitializer
GraphicsInitializer()
: applicationName("SeeleEngine")
, engineName("SeeleEngine")
, windowLayoutFile(nullptr)
, layers{"VK_LAYER_KHRONOS_validation", "VK_LAYER_LUNARG_monitor"}
, instanceExtensions{}
, deviceExtensions{"VK_KHR_swapchain"}
, windowHandle(nullptr)
{
}
GraphicsInitializer(const GraphicsInitializer &other)
: applicationName(other.applicationName)
, engineName(other.engineName)
, layers(other.layers)
, instanceExtensions(other.instanceExtensions)
, deviceExtensions(other.deviceExtensions)
{
}
};
struct WindowCreateInfo
{
+4 -3
View File
@@ -57,6 +57,7 @@ ShaderCollection& ShaderMap::createShaders(
VertexInputType* vertexInput,
bool /*bPositionOnly*/)
{
std::scoped_lock lock(shadersLock);
ShaderCollection& collection = shaders.add();
//collection.vertexDeclaration = bPositionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration();
@@ -107,7 +108,7 @@ void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorTyp
PDescriptorSet DescriptorLayout::allocateDescriptorSet()
{
std::unique_lock lock(allocatorLock);
std::scoped_lock lock(allocatorLock);
PDescriptorSet result;
allocator->allocateDescriptorSet(result);
return result;
@@ -115,7 +116,7 @@ PDescriptorSet DescriptorLayout::allocateDescriptorSet()
void DescriptorLayout::reset()
{
std::unique_lock lock(allocatorLock);
std::scoped_lock lock(allocatorLock);
allocator->reset();
}
@@ -270,7 +271,7 @@ static Map<uint32, PVertexDeclaration> vertexDeclarationCache;
PVertexDeclaration VertexDeclaration::createDeclaration(PGraphics graphics, const Array<VertexElement>& elementList)
{
std::unique_lock lock(vertexDeclarationLock);
std::scoped_lock lock(vertexDeclarationLock);
boost::crc_32_type result;
result.process_bytes(&elementList, sizeof(VertexElement) * elementList.size());
uint32 key = result.checksum();
+9 -1
View File
@@ -144,6 +144,7 @@ public:
VertexInputType* vertexInput,
bool bPositionOnly);
private:
std::mutex shadersLock;
Array<ShaderCollection> shaders;
};
DEFINE_REF(ShaderMap)
@@ -242,7 +243,14 @@ DEFINE_REF(DescriptorLayout)
class PipelineLayout
{
public:
PipelineLayout() {}
PipelineLayout(PPipelineLayout baseLayout)
{
if(baseLayout != nullptr)
{
descriptorSetLayouts = baseLayout->descriptorSetLayouts;
pushConstants = baseLayout->pushConstants;
}
}
virtual ~PipelineLayout() {}
virtual void create() = 0;
virtual void reset() = 0;
-5
View File
@@ -15,11 +15,6 @@ public:
PVertexShaderInput vertexInput;
PMaterialAsset referencedMaterial;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive&, const unsigned int)
{
}
};
DEFINE_REF(Mesh)
} // namespace Seele
+1
View File
@@ -24,5 +24,6 @@ MeshBatch::MeshBatch()
, topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
, vertexInput(nullptr)
, material(nullptr)
, elements()
{
}
+5 -1
View File
@@ -34,7 +34,7 @@ public:
};
struct MeshBatch
{
Array<MeshBatchElement> elements;
std::vector<MeshBatchElement> elements;
uint8 useReverseCulling : 1;
uint8 isBackfaceCullingDisabled : 1;
@@ -68,6 +68,10 @@ struct MeshBatch
}
MeshBatch();
MeshBatch(const MeshBatch& other) = default;
MeshBatch(MeshBatch&& other) = default;
MeshBatch& operator=(const MeshBatch& other) = default;
MeshBatch& operator=(MeshBatch&& other) = default;
};
DECLARE_REF(PrimitiveComponent)
struct StaticMeshBatch : public MeshBatch
+6 -5
View File
@@ -20,11 +20,11 @@ BasePassMeshProcessor::~BasePassMeshProcessor()
{
}
void BasePassMeshProcessor::processMeshBatch(
Job BasePassMeshProcessor::processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout,
Gfx::PPipelineLayout baseLayout,
Gfx::PDescriptorLayout primitiveLayout,
Array<Gfx::PDescriptorSet> descriptorSets,
int32 /*staticMeshId*/)
@@ -40,6 +40,7 @@ void BasePassMeshProcessor::processMeshBatch(
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
renderCommand->setViewport(target);
Gfx::PPipelineLayout pipelineLayout = graphics->createPipelineLayout(baseLayout);
pipelineLayout->addDescriptorLayout(BasePass::INDEX_MATERIAL, material->getDescriptorLayout());
pipelineLayout->create();
Gfx::PDescriptorSet materialSet = material->createDescriptorSet();
@@ -63,9 +64,9 @@ void BasePassMeshProcessor::processMeshBatch(
collection->fragmentShader,
false);
}
std::unique_lock lock(commandLock);
std::scoped_lock lock(commandLock);
renderCommands.add(renderCommand);
//co_return;
co_return;
}
BasePass::BasePass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source)
@@ -157,7 +158,7 @@ MainJob BasePass::render()
for (auto &&meshBatch : passData.staticDrawList)
{
//jobs.add(
processor->processMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets);
co_await processor->processMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets);
}
//co_await Job::all(jobs);
graphics->executeCommands(processor->getRenderCommands());
+2 -2
View File
@@ -11,7 +11,7 @@ public:
BasePassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics, uint8 translucentBasePass);
virtual ~BasePassMeshProcessor();
virtual void processMeshBatch(
virtual Job processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass,
@@ -30,7 +30,7 @@ DECLARE_REF(CameraActor)
DECLARE_REF(CameraComponent)
struct BasePassData
{
Array<StaticMeshBatch> staticDrawList;
std::vector<StaticMeshBatch> staticDrawList;
};
class BasePass : public RenderPass<BasePassData>
{
@@ -18,11 +18,11 @@ DepthPrepassMeshProcessor::~DepthPrepassMeshProcessor()
{
}
void DepthPrepassMeshProcessor::processMeshBatch(
Job DepthPrepassMeshProcessor::processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout,
Gfx::PPipelineLayout baseLayout,
Gfx::PDescriptorLayout primitiveLayout,
Array<Gfx::PDescriptorSet> descriptorSets,
int32 /*staticMeshId*/)
@@ -38,6 +38,7 @@ void DepthPrepassMeshProcessor::processMeshBatch(
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
renderCommand->setViewport(target);
Gfx::PPipelineLayout pipelineLayout = graphics->createPipelineLayout(baseLayout);
pipelineLayout->addDescriptorLayout(DepthPrepass::INDEX_MATERIAL, material->getDescriptorLayout());
pipelineLayout->create();
Gfx::PDescriptorSet materialSet = material->createDescriptorSet();
@@ -61,10 +62,10 @@ void DepthPrepassMeshProcessor::processMeshBatch(
collection->fragmentShader,
true);
}
std::unique_lock lock(commandLock);
std::scoped_lock lock(commandLock);
renderCommands.add(renderCommand);
//std::cout << "Finished depth job" << std::endl;
//co_return;
co_return;
}
DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source)
@@ -128,10 +129,9 @@ MainJob DepthPrepass::render()
for (auto &&meshBatch : passData.staticDrawList)
{
//jobs.add(
processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets);
co_await processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets);
}
//co_await Job::all(jobs);
//std::cout << "Finished waiting depth jobs " << std::endl;
graphics->executeCommands(processor->getRenderCommands());
graphics->endRenderPass();
co_return;
@@ -11,7 +11,7 @@ public:
DepthPrepassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics);
virtual ~DepthPrepassMeshProcessor();
virtual void processMeshBatch(
virtual Job processMeshBatch(
const MeshBatch& batch,
const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout,
@@ -27,7 +27,7 @@ DECLARE_REF(CameraActor)
DECLARE_REF(CameraComponent)
struct DepthPrepassData
{
Array<StaticMeshBatch> staticDrawList;
std::vector<StaticMeshBatch> staticDrawList;
};
class DepthPrepass : public RenderPass<DepthPrepassData>
{
@@ -1,6 +1,7 @@
#include "MeshProcessor.h"
#include "Graphics/Graphics.h"
#include "Graphics/VertexShaderInput.h"
#include "Graphics/Vulkan/VulkanGraphicsResources.h"
using namespace Seele;
@@ -32,8 +33,6 @@ void MeshProcessor::buildMeshDrawCommand(
GraphicsPipelineCreateInfo pipelineInitializer;
pipelineInitializer.topology = meshBatch.topology;
Gfx::PVertexDeclaration vertexDecl = positionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration();
pipelineInitializer.vertexDeclaration = vertexDecl;
pipelineInitializer.vertexShader = vertexShader;
pipelineInitializer.controlShader = controlShader;
pipelineInitializer.evalShader = evaluationShader;
@@ -46,10 +45,12 @@ void MeshProcessor::buildMeshDrawCommand(
if(positionOnly)
{
vertexInput->getPositionOnlyStream(vertexStreams);
pipelineInitializer.vertexDeclaration = vertexInput->getPositionDeclaration();
}
else
{
vertexInput->getStreams(vertexStreams);
pipelineInitializer.vertexDeclaration = vertexInput->getDeclaration();
}
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(pipelineInitializer);
drawCommand->bindPipeline(pipeline);
@@ -17,7 +17,7 @@ public:
protected:
PScene scene;
Gfx::PGraphics graphics;
virtual void processMeshBatch(
virtual Job processMeshBatch(
const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass,
@@ -77,7 +77,7 @@ void GpuCrashTracker::Initialize()
void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize)
{
// Make sure only one thread at a time...
std::unique_lock<std::mutex> lock(m_mutex);
std::scoped_lock<std::mutex> lock(m_mutex);
// Write to file for later in-depth analysis with Nsight Graphics.
WriteGpuCrashDumpToFile(pGpuCrashDump, gpuCrashDumpSize);
@@ -87,7 +87,7 @@ void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuC
void GpuCrashTracker::OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize)
{
// Make sure only one thread at a time...
std::unique_lock<std::mutex> lock(m_mutex);
std::scoped_lock<std::mutex> lock(m_mutex);
// Get shader debug information identifier
GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier = {};
+10 -7
View File
@@ -74,7 +74,7 @@ Allocation::~Allocation()
PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
{
std::unique_lock lck(lock);
std::scoped_lock lck(lock);
if (isDedicated)
{
if (activeAllocations.empty() && requestedSize == bytesAllocated)
@@ -134,7 +134,7 @@ void Allocation::markFree(SubAllocation *allocation)
PSubAllocation freeRangeToDelete;
{
std::unique_lock lck(lock);
std::scoped_lock lck(lock);
//Join lower bound
for (auto freeRange : freeRanges)
{
@@ -204,7 +204,7 @@ Allocator::Allocator(PGraphics graphics)
Allocator::~Allocator()
{
std::unique_lock lck(lock);
std::scoped_lock lck(lock);
for (auto heap : heaps)
{
for (auto alloc : heap.allocations)
@@ -219,7 +219,7 @@ Allocator::~Allocator()
PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
{
std::unique_lock lck(lock);
std::scoped_lock lck(lock);
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
uint8 memoryTypeIndex;
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
@@ -252,7 +252,7 @@ PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2
void Allocator::free(Allocation *allocation)
{
std::unique_lock lck(lock);
std::scoped_lock lck(lock);
for (auto heap : heaps)
{
for (uint32 i = 0; i < heap.allocations.size(); ++i)
@@ -307,7 +307,7 @@ void StagingManager::clearPending()
PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead)
{
std::unique_lock l(lock);
std::scoped_lock l(lock);
for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
{
auto freeBuffer = *it;
@@ -323,6 +323,9 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF
PStagingBuffer stagingBuffer = new StagingBuffer();
VkBufferCreateInfo stagingBufferCreateInfo = init::BufferCreateInfo(usage, size);
stagingBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
uint32 queueIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(Gfx::QueueType::DEDICATED_TRANSFER);
stagingBufferCreateInfo.queueFamilyIndexCount = 1;
stagingBufferCreateInfo.pQueueFamilyIndices = &queueIndex;
VkDevice vulkanDevice = graphics->getDevice();
VK_CHECK(vkCreateBuffer(vulkanDevice, &stagingBufferCreateInfo, nullptr, &stagingBuffer->buffer));
@@ -355,7 +358,7 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF
void StagingManager::releaseStagingBuffer(PStagingBuffer buffer)
{
std::unique_lock l(lock);
std::scoped_lock l(lock);
freeBuffers.add(buffer);
activeBuffers.remove(activeBuffers.find(buffer.getHandle()));
}
+1 -1
View File
@@ -40,7 +40,7 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags u
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
uint32 queueFamilyIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(queueType);
info.pQueueFamilyIndices = &queueFamilyIndex;
info.queueFamilyIndexCount = 0;
info.queueFamilyIndexCount = 1;
VkBufferMemoryRequirementsInfo2 bufferReqInfo;
bufferReqInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
bufferReqInfo.pNext = nullptr;
@@ -16,16 +16,13 @@ using namespace Seele::Vulkan;
CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferManager manager)
: graphics(graphics)
, manager(manager)
, renderPass(nullptr)
, framebuffer(nullptr)
, subpassIndex(0)
, owner(cmdPool)
{
VkCommandBufferAllocateInfo allocInfo =
init::CommandBufferAllocateInfo(cmdPool,
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1);
std::unique_lock lock(handleLock);
std::scoped_lock lock(handleLock);
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle))
fence = new Fence(graphics);
@@ -34,10 +31,8 @@ CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferMa
CmdBuffer::~CmdBuffer()
{
std::unique_lock lock(handleLock);
std::scoped_lock lock(handleLock);
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
renderPass = nullptr;
framebuffer = nullptr;
waitSemaphores.clear();
}
@@ -46,24 +41,22 @@ void CmdBuffer::begin()
VkCommandBufferBeginInfo beginInfo =
init::CommandBufferBeginInfo();
beginInfo.pInheritanceInfo = nullptr;
std::unique_lock lock(handleLock);
std::scoped_lock lock(handleLock);
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
state = State::InsideBegin;
}
void CmdBuffer::end()
{
std::unique_lock lock(handleLock);
std::scoped_lock lock(handleLock);
VK_CHECK(vkEndCommandBuffer(handle));
state = State::Ended;
}
void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFramebuffer)
void CmdBuffer::beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer)
{
assert(state == State::InsideBegin);
std::unique_lock lock(handleLock);
renderPass = newRenderPass;
framebuffer = newFramebuffer;
std::scoped_lock lock(handleLock);
VkRenderPassBeginInfo beginInfo =
init::RenderPassBeginInfo();
@@ -74,15 +67,13 @@ void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFrame
beginInfo.framebuffer = framebuffer->getHandle();
vkCmdBeginRenderPass(handle, &beginInfo, renderPass->getSubpassContents());
state = State::RenderPassActive;
//std::cout << "Beginning renderPass" << std::endl;
}
void CmdBuffer::endRenderPass()
{
std::unique_lock lock(handleLock);
std::scoped_lock lock(handleLock);
vkCmdEndRenderPass(handle);
state = State::InsideBegin;
//std::cout << "Ending renderPass" << std::endl;
}
void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
@@ -90,9 +81,10 @@ void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
assert(state == State::RenderPassActive);
if(commands.size() == 0)
{
std::cout << "No commands provided" << std::endl;
return;
}
std::unique_lock lock(handleLock);
std::scoped_lock lock(handleLock);
Array<VkCommandBuffer> cmdBuffers(commands.size());
for (uint32 i = 0; i < commands.size(); ++i)
{
@@ -111,7 +103,7 @@ void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
void CmdBuffer::executeCommands(const Array<Gfx::PComputeCommand>& commands)
{
std::unique_lock lock(handleLock);
std::scoped_lock lock(handleLock);
if(commands.size() == 0)
{
return;
@@ -134,14 +126,14 @@ void CmdBuffer::executeCommands(const Array<Gfx::PComputeCommand>& commands)
void CmdBuffer::addWaitSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore)
{
std::unique_lock lock(handleLock);
std::scoped_lock lock(handleLock);
waitSemaphores.add(semaphore);
waitFlags.add(flags);
}
void CmdBuffer::refreshFence()
{
std::unique_lock lock(handleLock);
std::scoped_lock lock(handleLock);
if (state == State::Submitted)
{
if (fence->isSignaled())
@@ -174,7 +166,7 @@ void CmdBuffer::refreshFence()
void CmdBuffer::waitForCommand(uint32 timeout)
{
std::unique_lock lock(handleLock);
std::scoped_lock lock(handleLock);
fence->wait(timeout);
refreshFence();
}
@@ -212,7 +204,7 @@ RenderCommand::~RenderCommand()
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
}
void RenderCommand::begin(PCmdBuffer parent)
void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer)
{
threadId = std::this_thread::get_id();
ready = false;
@@ -220,9 +212,9 @@ void RenderCommand::begin(PCmdBuffer parent)
init::CommandBufferBeginInfo();
VkCommandBufferInheritanceInfo inheritanceInfo =
init::CommandBufferInheritanceInfo();
inheritanceInfo.framebuffer = parent->framebuffer->getHandle();
inheritanceInfo.renderPass = parent->renderPass->getHandle();
inheritanceInfo.subpass = parent->subpassIndex;
inheritanceInfo.framebuffer = framebuffer->getHandle();
inheritanceInfo.renderPass = renderPass->getHandle();
inheritanceInfo.subpass = 0;
beginInfo.pInheritanceInfo = &inheritanceInfo;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
@@ -230,13 +222,11 @@ void RenderCommand::begin(PCmdBuffer parent)
void RenderCommand::end()
{
assert(threadId == std::this_thread::get_id());
VK_CHECK(vkEndCommandBuffer(handle));
}
void RenderCommand::reset()
{
assert(threadId == std::this_thread::get_id());
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
boundDescriptors.clear();
ready = true;
@@ -420,7 +410,7 @@ CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue)
activeCmdBuffer = new CmdBuffer(graphics, commandPool, this);
activeCmdBuffer->begin();
std::unique_lock lock(allocatedBufferLock);
std::scoped_lock lock(allocatedBufferLock);
allocatedBuffers.add(activeCmdBuffer);
}
@@ -436,29 +426,29 @@ PCmdBuffer CommandBufferManager::getCommands()
return activeCmdBuffer;
}
PRenderCommand CommandBufferManager::createRenderCommand(const std::string& name)
PRenderCommand CommandBufferManager::createRenderCommand(PRenderPass renderPass, PFramebuffer framebuffer, const std::string& name)
{
std::unique_lock lck(allocatedRenderLock);
std::scoped_lock lck(allocatedRenderLock);
for (uint32 i = 0; i < allocatedRenderCommands.size(); ++i)
{
PRenderCommand cmdBuffer = allocatedRenderCommands[i];
if (cmdBuffer->isReady())
{
cmdBuffer->name = name;
cmdBuffer->begin(activeCmdBuffer);
cmdBuffer->begin(renderPass, framebuffer);
return cmdBuffer;
}
}
PRenderCommand result = new RenderCommand(graphics, commandPool);
result->name = name;
result->begin(activeCmdBuffer);
result->begin(renderPass, framebuffer);
allocatedRenderCommands.add(result);
return result;
}
PComputeCommand CommandBufferManager::createComputeCommand(const std::string& name)
{
std::unique_lock lck(allocatedComputeLock);
std::scoped_lock lck(allocatedComputeLock);
for (uint32 i = 0; i < allocatedComputeCommands.size(); ++i)
{
PComputeCommand cmdBuffer = allocatedComputeCommands[i];
@@ -495,7 +485,7 @@ void CommandBufferManager::submitCommands(PSemaphore signalSemaphore)
queue->submitCommandBuffer(activeCmdBuffer);
}
}
std::unique_lock lock(allocatedBufferLock);
std::scoped_lock lock(allocatedBufferLock);
for (uint32 i = 0; i < allocatedBuffers.size(); ++i)
{
PCmdBuffer cmdBuffer = allocatedBuffers[i];
@@ -47,10 +47,7 @@ public:
private:
PGraphics graphics;
PCommandBufferManager manager;
PRenderPass renderPass;
PFramebuffer framebuffer;
PFence fence;
uint32 subpassIndex;
State state;
VkViewport currentViewport;
VkRect2D currentScissor;
@@ -79,7 +76,7 @@ public:
{
return handle;
}
void begin(PCmdBuffer parent);
void begin(PRenderPass renderPass, PFramebuffer framebuffer);
void end();
void reset();
virtual bool isReady() override;
@@ -145,7 +142,7 @@ public:
return queue;
}
PCmdBuffer getCommands();
PRenderCommand createRenderCommand(const std::string& name);
PRenderCommand createRenderCommand(PRenderPass renderPass, PFramebuffer framebuffer, const std::string& name);
PComputeCommand createComputeCommand(const std::string& name);
VkCommandPool getPoolHandle() const
{
@@ -54,7 +54,7 @@ PipelineLayout::~PipelineLayout()
{
if (layoutHandle != VK_NULL_HANDLE)
{
vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr);
//vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr);
}
}
@@ -29,12 +29,12 @@ DEFINE_REF(DescriptorLayout)
class PipelineLayout : public Gfx::PipelineLayout
{
public:
PipelineLayout(PGraphics graphics)
: graphics(graphics)
PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout)
: Gfx::PipelineLayout(baseLayout)
, graphics(graphics)
, layoutHash(0)
, layoutHandle(VK_NULL_HANDLE)
{
}
{}
virtual ~PipelineLayout();
virtual void create();
virtual void reset();
+28 -29
View File
@@ -14,6 +14,11 @@
using namespace Seele::Vulkan;
thread_local PCommandBufferManager Seele::Vulkan::Graphics::graphicsCommands = nullptr;
thread_local PCommandBufferManager Seele::Vulkan::Graphics::computeCommands = nullptr;
thread_local PCommandBufferManager Seele::Vulkan::Graphics::transferCommands = nullptr;
thread_local PCommandBufferManager Seele::Vulkan::Graphics::dedicatedTransferCommands = nullptr;
Graphics::Graphics()
: instance(VK_NULL_HANDLE)
, handle(VK_NULL_HANDLE)
@@ -52,7 +57,7 @@ Gfx::PWindow Graphics::createWindow(const WindowCreateInfo &createInfo)
Gfx::PViewport Graphics::createViewport(Gfx::PWindow owner, const ViewportCreateInfo &viewportInfo)
{
PViewport result = new Viewport(this, owner, viewportInfo);
std::unique_lock lock(viewportLock);
std::scoped_lock lock(viewportLock);
viewports.add(result);
return result;
}
@@ -67,7 +72,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
uint32 framebufferHash = rp->getFramebufferHash();
PFramebuffer framebuffer;
{
std::unique_lock lock(allocatedFrameBufferLock);
std::scoped_lock lock(allocatedFrameBufferLock);
auto found = allocatedFramebuffers.find(framebufferHash);
if (found == allocatedFramebuffers.end())
{
@@ -80,12 +85,18 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
}
}
getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer);
std::scoped_lock lock(renderPassLock);
activeRenderPass = rp;
activeFramebuffer = framebuffer;
}
void Graphics::endRenderPass()
{
getGraphicsCommands()->getCommands()->endRenderPass();
getGraphicsCommands()->submitCommands();
std::scoped_lock lock(renderPassLock);
activeRenderPass = nullptr;
activeFramebuffer = nullptr;
}
void Graphics::executeCommands(const Array<Gfx::PRenderCommand>& commands)
@@ -128,7 +139,7 @@ Gfx::PIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkD
}
Gfx::PRenderCommand Graphics::createRenderCommand(const std::string& name)
{
PRenderCommand cmdBuffer = getGraphicsCommands()->createRenderCommand(name);
PRenderCommand cmdBuffer = getGraphicsCommands()->createRenderCommand(activeRenderPass, activeFramebuffer, name);
return cmdBuffer;
}
@@ -206,9 +217,9 @@ Gfx::PDescriptorLayout Graphics::createDescriptorLayout(const std::string& name)
PDescriptorLayout layout = new DescriptorLayout(this, name);
return layout;
}
Gfx::PPipelineLayout Graphics::createPipelineLayout()
Gfx::PPipelineLayout Graphics::createPipelineLayout(Gfx::PPipelineLayout baseLayout)
{
PPipelineLayout layout = new PipelineLayout(this);
PPipelineLayout layout = new PipelineLayout(this, baseLayout);
return layout;
}
@@ -295,49 +306,37 @@ PCommandBufferManager Graphics::getQueueCommands(Gfx::QueueType queueType)
throw new std::logic_error("invalid queue type");
}
}
std::mutex graphicsCommandLock;
PCommandBufferManager Graphics::getGraphicsCommands()
{
std::unique_lock lock(graphicsCommandLock);
auto id = std::this_thread::get_id();
if(graphicsCommands.find(id) == graphicsCommands.end())
if(graphicsCommands == nullptr)
{
graphicsCommands[id] = new CommandBufferManager(this, graphicsQueue);
graphicsCommands = new CommandBufferManager(this, graphicsQueue);
}
return graphicsCommands[id];
return graphicsCommands;
}
std::mutex computeCommandLock;
PCommandBufferManager Graphics::getComputeCommands()
{
std::unique_lock lock(computeCommandLock);
auto id = std::this_thread::get_id();
if(computeCommands.find(id) == computeCommands.end())
if(computeCommands == nullptr)
{
computeCommands[id] = new CommandBufferManager(this, computeQueue);
computeCommands = new CommandBufferManager(this, computeQueue);
}
return computeCommands[id];
return computeCommands;
}
std::mutex transferCommandLock;
PCommandBufferManager Graphics::getTransferCommands()
{
std::unique_lock lock(transferCommandLock);
auto id = std::this_thread::get_id();
if(transferCommands.find(id) == transferCommands.end())
if(transferCommands == nullptr)
{
transferCommands[id] = new CommandBufferManager(this, transferQueue);
transferCommands = new CommandBufferManager(this, transferQueue);
}
return transferCommands[id];
return transferCommands;
}
std::mutex dedicatedCommandLock;
PCommandBufferManager Graphics::getDedicatedTransferCommands()
{
std::unique_lock lock(dedicatedCommandLock);
auto id = std::this_thread::get_id();
if(dedicatedTransferCommands.find(id) == dedicatedTransferCommands.end())
if(dedicatedTransferCommands == dedicatedTransferCommands)
{
dedicatedTransferCommands[id] = new CommandBufferManager(this, dedicatedTransferQueue);
dedicatedTransferCommands = new CommandBufferManager(this, dedicatedTransferQueue);
}
return dedicatedTransferCommands[id];
return dedicatedTransferCommands;
}
PAllocator Graphics::getAllocator()
{
+9 -5
View File
@@ -11,6 +11,7 @@ DECLARE_REF(Allocator)
DECLARE_REF(StagingManager)
DECLARE_REF(CommandBufferManager)
DECLARE_REF(Queue)
DECLARE_REF(RenderPass)
DECLARE_REF(Framebuffer)
DECLARE_REF(RenderCommand)
DECLARE_REF(PipelineCache)
@@ -63,7 +64,7 @@ public:
virtual Gfx::PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) override;
virtual Gfx::PDescriptorLayout createDescriptorLayout(const std::string& name = "") override;
virtual Gfx::PPipelineLayout createPipelineLayout() override;
virtual Gfx::PPipelineLayout createPipelineLayout(Gfx::PPipelineLayout baseLayout = nullptr) override;
virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override;
protected:
@@ -82,10 +83,13 @@ protected:
PQueue transferQueue;
PQueue dedicatedTransferQueue;
PPipelineCache pipelineCache;
Map<std::thread::id, PCommandBufferManager> graphicsCommands;
Map<std::thread::id, PCommandBufferManager> computeCommands;
Map<std::thread::id, PCommandBufferManager> transferCommands;
Map<std::thread::id, PCommandBufferManager> dedicatedTransferCommands;
std::mutex renderPassLock;
PRenderPass activeRenderPass;
PFramebuffer activeFramebuffer;
thread_local static PCommandBufferManager graphicsCommands;
thread_local static PCommandBufferManager computeCommands;
thread_local static PCommandBufferManager transferCommands;
thread_local static PCommandBufferManager dedicatedTransferCommands;
VkPhysicalDeviceProperties props;
VkPhysicalDeviceFeatures features;
VkDebugReportCallbackEXT callback;
@@ -296,6 +296,8 @@ VkBufferMemoryBarrier init::BufferMemoryBarrier()
VkBufferMemoryBarrier bufferMemoryBarrier = {};
bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufferMemoryBarrier.pNext = NULL;
bufferMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
return bufferMemoryBarrier;
}
@@ -323,7 +323,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
uint32 hash = crc.checksum();
VkPipeline pipelineHandle;
std::unique_lock lock(createdPipelinesLock);
std::scoped_lock lock(createdPipelinesLock);
auto foundPipeline = createdPipelines.find(hash);
if (foundPipeline != createdPipelines.end())
{
+1 -1
View File
@@ -22,7 +22,7 @@ Queue::~Queue()
void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore *signalSemaphores)
{
std::unique_lock lck(queueLock);
std::scoped_lock lck(queueLock);
assert(cmdBuffer->state == CmdBuffer::State::Ended);
PFence fence = cmdBuffer->fence;
+1 -1
View File
@@ -185,6 +185,6 @@ const Gfx::ShaderCollection* MaterialAsset::getShaders(Gfx::RenderPassType rende
Gfx::ShaderCollection& MaterialAsset::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
{
std::unique_lock lock(shaderMapLock);
std::scoped_lock lock(shaderMapLock);
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
}
+6 -2
View File
@@ -49,7 +49,7 @@ public:
~RefObject()
{
{
std::unique_lock lock(registeredObjectsLock);
std::scoped_lock lock(registeredObjectsLock);
registeredObjects.erase(handle);
}
// #pragma warning( disable: 4150)
@@ -114,7 +114,7 @@ public:
}
RefPtr(T *ptr, Deleter deleter = Deleter())
{
std::unique_lock l(registeredObjectsLock);
std::scoped_lock l(registeredObjectsLock);
auto registeredObj = registeredObjects.find(ptr);
// get here for thread safetly
auto registeredEnd = registeredObjects.end();
@@ -249,6 +249,10 @@ public:
{
return object->getHandle();
}
RefPtr<T, Deleter> clone()
{
return RefPtr<T, Deleter>(new T(*getHandle()));
}
private:
RefObject<T, Deleter> *object;
+29 -1
View File
@@ -12,8 +12,36 @@ Actor::~Actor()
{
}
void Actor::tick(float)
void Actor::launchStart()
{
rootComponent->launchStart();
for(auto child : children)
{
child->launchStart();
}
start();
}
Array<Job> Actor::launchTick(float deltaTime) const
{
Array<Job> result = rootComponent->launchTick(deltaTime);
for(auto child : children)
{
result.addAll(child->launchTick(deltaTime));
}
result.add(tick(deltaTime));
return result;
}
Array<Job> Actor::launchUpdate()
{
Array<Job> result = rootComponent->launchUpdate();
for(auto child : children)
{
result.addAll(child->launchUpdate());
}
result.add(update());
return result;
}
void Actor::notifySceneAttach(PScene scene)
{
+7 -2
View File
@@ -1,6 +1,7 @@
#pragma once
#include "MinimalEngine.h"
#include "Math/Transform.h"
#include "ThreadPool.h"
namespace Seele
{
@@ -12,8 +13,12 @@ class Actor
public:
Actor();
virtual ~Actor();
void tick(float deltaTime);
virtual void launchStart();
virtual void start() {}
Array<Job> launchTick(float deltaTime) const;
virtual Job tick(float deltaTime) const { co_return; }
Array<Job> launchUpdate();
virtual Job update() { co_return; }
void notifySceneAttach(PScene scene);
PScene getScene();
+1
View File
@@ -1,5 +1,6 @@
target_sources(SeeleEngine
PRIVATE
Util.h
Scene.cpp
Scene.h)
@@ -4,6 +4,10 @@ target_sources(SeeleEngine
CameraComponent.cpp
Component.h
Component.cpp
MyComponent.h
MyComponent.cpp
MyOtherComponent.h
MyOtherComponent.cpp
PrimitiveComponent.cpp
PrimitiveComponent.h
PrimitiveUniformBufferLayout.h)
@@ -6,10 +6,15 @@
using namespace Seele;
CameraComponent::CameraComponent()
: bNeedsViewBuild(true)
: aspectRatio(0)
, fieldOfView(0)
, bNeedsViewBuild(true)
, bNeedsProjectionBuild(true)
, originPoint(0, 0, 0)
, cameraPosition(0, 0, 50)
, eye(Vector())
, projectionMatrix(Matrix4())
, viewMatrix(Matrix4())
{
distance = 50;
rotationX = 0;
+49 -11
View File
@@ -13,9 +13,38 @@ Component::Component()
Component::~Component()
{
}
void Component::tick(float)
void Component::launchStart()
{
for(auto child : children)
{
child->launchStart();
}
start();
}
Array<Job> Component::launchTick(float deltaTime) const
{
Array<Job> result;
for(auto child : children)
{
result.addAll(child->launchTick(deltaTime));
}
result.add(tick(deltaTime));
return result;
}
Array<Job> Component::launchUpdate()
{
Array<Job> result;
for(auto child : children)
{
result.addAll(child->launchUpdate());
}
result.add(update());
return result;
}
PComponent Component::getParent()
{
return parent;
@@ -32,6 +61,25 @@ PActor Component::getOwner()
}
return nullptr;
}
const Array<PComponent>& Component::getChildComponents()
{
return children;
}
void Component::setParent(PComponent newParent)
{
parent = newParent;
}
void Component::setOwner(PActor newOwner)
{
owner = newOwner;
}
void Component::addChildComponent(PComponent component)
{
children.add(component);
}
void Component::notifySceneAttach(PScene scene)
{
@@ -118,16 +166,6 @@ Transform Component::getTransform() const
return transform;
}
void Component::setParent(PComponent newParent)
{
parent = newParent;
}
void Component::setOwner(PActor newOwner)
{
owner = newOwner;
}
void Component::internalSetTransform(Vector newLocation, Quaternion newRotation)
{
if (parent != nullptr)
+33 -1
View File
@@ -1,6 +1,8 @@
#pragma once
#include "MinimalEngine.h"
#include "Math/Transform.h"
#include "Scene/Util.h"
#include "ThreadPool.h"
namespace Seele
{
@@ -12,11 +14,18 @@ class Component
public:
Component();
virtual ~Component();
void tick(float deltaTime);
void launchStart();
virtual void start() {};
Array<Job> launchTick(float deltaTime) const;
virtual Job tick(float deltaTime) const { co_return; }
Array<Job> launchUpdate();
virtual Job update() { co_return; }
PComponent getParent();
PActor getOwner();
const Array<PComponent>& getChildComponents();
void setParent(PComponent parent);
void setOwner(PActor owner);
void addChildComponent(PComponent component);
virtual void notifySceneAttach(PScene scene);
void setWorldLocation(Vector location);
@@ -35,7 +44,30 @@ public:
Transform getTransform() const;
template<typename ComponentType>
RefPtr<ComponentType> getComponent()
{
return tryFindComponent<ComponentType>();
}
private:
template<typename ComponentType>
RefPtr<ComponentType> tryFindComponent()
{
for(auto child : children)
{
RefPtr<ComponentType> result = child.cast<ComponentType>();
if(result != nullptr)
{
return result;
}
result = parent->tryFindComponent<ComponentType>();
if(result != nullptr)
{
return result;
}
}
return nullptr;
}
void internalSetTransform(Vector newLocation, Quaternion newRotation);
void propagateTransformUpdate();
void updateComponentTransform(Quaternion relativeRotationQuat);
@@ -0,0 +1,26 @@
#include "MyComponent.h"
using namespace Seele;
MyComponent::MyComponent()
{
}
void MyComponent::start()
{
otherComp = getComponent<MyOtherComponent>();
otherComp.update();
}
Job MyComponent::tick(float deltatime) const
{
writable++;
otherComp->data = *writable;
co_return;
}
Job MyComponent::update()
{
writable.update();
co_return;
}
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "Component.h"
#include "MyOtherComponent.h"
namespace Seele
{
class MyComponent : public Component
{
public:
MyComponent();
virtual void start();
virtual Job tick(float deltatime) const;
virtual Job update();
private:
Writable<PMyOtherComponent> otherComp;
Writable<uint32> writable = Writable<uint32>(0);
uint32 notWritable = 10;
};
DECLARE_REF(MyComponent);
} // namespace Seele
@@ -0,0 +1,15 @@
#include "MyOtherComponent.h"
using namespace Seele;
Job MyOtherComponent::tick(float deltaTime) const
{
std::cout << *data << std::endl;
co_return;
}
Job MyOtherComponent::update()
{
data.update();
co_return;
}
@@ -0,0 +1,15 @@
#pragma once
#include "Component.h"
namespace Seele
{
class MyOtherComponent : public Component
{
public:
virtual Job tick(float deltaTime) const;
virtual Job update();
Writable<uint32> data = Writable<uint32>(0);
private:
};
DEFINE_REF(MyOtherComponent);
} // namespace Seele
@@ -26,7 +26,7 @@ PrimitiveComponent::PrimitiveComponent(PMeshAsset asset)
batch.useReverseCulling = false;
batch.useWireframe = false;
batch.vertexInput = assetMeshes[i]->vertexInput;
auto& batchElement = batch.elements.add();
MeshBatchElement batchElement;
batchElement.baseVertexIndex = 0;
batchElement.firstIndex = 0;
batchElement.indexBuffer = assetMeshes[i]->indexBuffer;
@@ -35,6 +35,7 @@ PrimitiveComponent::PrimitiveComponent(PMeshAsset asset)
batchElement.isInstanced = false;
batchElement.numInstances = 1;
batchElement.numPrimitives = assetMeshes[i]->indexBuffer->getNumIndices() / 3; //TODO: hardcoded
batch.elements.push_back(batchElement);
}
}
@@ -16,14 +16,14 @@ public:
~PrimitiveComponent();
virtual void notifySceneAttach(PScene scene) override;
Matrix4 getRenderMatrix();
const Array<StaticMeshBatch>& getStaticMeshes()
std::vector<StaticMeshBatch>& getStaticMeshes()
{
return staticMeshes;
}
private:
Array<PMaterialAsset> materials;
std::vector<PMaterialAsset> materials;
Gfx::PUniformBuffer uniformBuffer;
Array<StaticMeshBatch> staticMeshes;
std::vector<StaticMeshBatch> staticMeshes;
friend class Scene;
};
DEFINE_REF(PrimitiveComponent)
+24 -4
View File
@@ -33,19 +33,39 @@ Scene::~Scene()
{
}
void Scene::tick(double)
void Scene::start()
{
for(auto actor : rootActors)
{
actor->launchStart();
}
}
Job Scene::beginUpdate(double deltaTime)
{
for(auto actor : rootActors)
{
co_await Job::all(actor->launchTick(static_cast<float>(deltaTime)));
}
}
Job Scene::commitUpdate()
{
for(auto actor : rootActors)
{
co_await Job::all(actor->launchUpdate());
}
}
void Scene::addActor(PActor actor)
{
rootActors.add(actor);
rootActors.push_back(actor);
actor->notifySceneAttach(this);
}
void Scene::addPrimitiveComponent(PPrimitiveComponent comp)
{
primitives.add(comp);
primitives.push_back(comp);
for(auto& batch : comp->getStaticMeshes())
{
PrimitiveUniformBuffer data;
@@ -62,6 +82,6 @@ void Scene::addPrimitiveComponent(PPrimitiveComponent comp)
{
element.uniformBuffer = uniformBuffer;
}
staticMeshes.add(batch);
staticMeshes.push_back(batch);
}
}
+8 -6
View File
@@ -38,17 +38,19 @@ class Scene
public:
Scene(Gfx::PGraphics graphics);
~Scene();
void tick(double deltaTime);
void start();
Job beginUpdate(double deltaTime);
Job commitUpdate();
void addActor(PActor actor);
void addPrimitiveComponent(PPrimitiveComponent comp);
const Array<PPrimitiveComponent>& getPrimitives() const { return primitives; }
const Array<StaticMeshBatch>& getStaticMeshes() const { return staticMeshes; }
const std::vector<PPrimitiveComponent>& getPrimitives() const { return primitives; }
const std::vector<StaticMeshBatch>& getStaticMeshes() const { return staticMeshes; }
const LightEnv& getLightBuffer() const { return lightEnv; }
private:
Array<StaticMeshBatch> staticMeshes;
Array<PActor> rootActors;
Array<PPrimitiveComponent> primitives;
std::vector<StaticMeshBatch> staticMeshes;
std::vector<PActor> rootActors;
std::vector<PPrimitiveComponent> primitives;
LightEnv lightEnv;
Gfx::PGraphics graphics;
};
+7 -7
View File
@@ -26,25 +26,25 @@ SceneUpdater::~SceneUpdater()
void SceneUpdater::registerComponentUpdate(PComponent component)
{
std::unique_lock lck(pendingUpdatesLock);
std::scoped_lock lck(pendingUpdatesLock);
updatesRan.add([component](float delta) mutable { component->tick(delta); });
}
void SceneUpdater::registerActorUpdate(PActor actor)
{
std::unique_lock lck(pendingUpdatesLock);
std::scoped_lock lck(pendingUpdatesLock);
updatesRan.add([actor](float delta) mutable { actor->tick(delta); });
}
void SceneUpdater::runUpdates(float delta)
{
std::unique_lock pendingLock(pendingUpdatesLock);
std::scoped_lock pendingLock(pendingUpdatesLock);
frameDelta = delta;
pendingUpdates = std::move(updatesRan);
updatesRan = List<std::function<void(float)>>();
std::unique_lock lck(frameFinishedLock);
std::scoped_lock lck(frameFinishedLock);
pendingLock.unlock();
pendingUpdatesSem.release(pendingUpdates.size());
frameFinishedCV.wait(lck);
@@ -57,18 +57,18 @@ void SceneUpdater::work()
pendingUpdatesSem.acquire();
std::function<void(float)> function;
{
std::unique_lock lck(pendingUpdatesLock);
std::scoped_lock lck(pendingUpdatesLock);
function = std::move(pendingUpdates.front());
pendingUpdates.popFront();
if(pendingUpdates.empty())
{
std::unique_lock lck(frameFinishedLock);
std::scoped_lock lck(frameFinishedLock);
frameFinishedCV.notify_all();
}
}
function(frameDelta);
{
std::unique_lock lck(pendingUpdatesLock);
std::scoped_lock lck(pendingUpdatesLock);
updatesRan.add(std::move(function));
}
}
+149
View File
@@ -0,0 +1,149 @@
#pragma once
#include "MinimalEngine.h"
namespace Seele
{
template<typename T>
class Writable
{
public:
Writable()
{}
explicit Writable(T initialData)
: data(initialData)
, toBeWritten(initialData)
{}
Writable(const Writable& other) = delete;
Writable(Writable&& other) = default;
~Writable() = default;
Writable& operator=(const Writable& other) = delete;
Writable& operator=(Writable&& other) = default;
const Writable& operator=(const T& other) const
{
deferWrite(other);
return *this;
}
const Writable& operator=(T&& other) const
{
deferWrite(std::move(other));
return *this;
}
template<typename Other>
const Writable& operator+(Other&& other) const
{
deferWrite(data + std::forward<Other>(other));
return *this;
}
template<typename Other>
const Writable& operator-(Other&& other) const
{
deferWrite(data - std::forward<Other>(other));
return *this;
}
template<typename Other>
const Writable& operator*(Other&& other) const
{
deferWrite(data * std::forward<Other>(other));
return *this;
}
template<typename Other>
const Writable& operator/(Other&& other) const
{
deferWrite(data / std::forward<Other>(other));
return *this;
}
template<typename Other>
const Writable& operator%(Other&& other) const
{
deferWrite(data % std::forward<Other>(other));
return *this;
}
template<typename Other>
const Writable& operator^(Other&& other) const
{
deferWrite(data ^ std::forward<Other>(other));
return *this;
}
template<typename Other>
const Writable& operator&(Other&& other) const
{
deferWrite(data & std::forward<Other>(other));
return *this;
}
template<typename Other>
const Writable& operator|(Other&& other) const
{
deferWrite(data | std::forward<Other>(other));
return *this;
}
template<typename Type>
bool operator==(Type other) const
{
return data == other.data;
}
template<typename Type>
bool operator<=>(Type other) const
{
return data <=> other.data;
}
const Writable& operator++() const
{
deferWrite(data+1);
return *this;
}
const Writable& operator--() const
{
deferWrite(data-1);
return *this;
}
Writable&& operator++(int) const
{
Writable tmp(data);
++*this;
return std::move(tmp);
}
Writable&& operator--(int) const
{
Writable tmp(data);
--*this;
return std::move(tmp);
}
const T& operator*() const
{
return data;
}
const T& get() const
{
return data;
}
const T& operator->() const
{
return data;
}
void update()
{
// lock should not be necessary, but lets keep it for now
std::scoped_lock lock(dataLock);
data = toBeWritten;
dirty = false;
}
private:
template<typename Type>
void deferWrite(Type&& newValue) const
{
std::scoped_lock lock(dataLock);
assert(!dirty);
toBeWritten = std::forward<Type>(newValue);
dirty = true;
}
mutable bool dirty = false;
mutable std::mutex dataLock;
mutable T toBeWritten;
T data;
};
template<typename A>
concept writable = requires(A&& a)
{
a.update();
};
} // namespace Seele
+49 -41
View File
@@ -6,7 +6,7 @@ using namespace Seele;
std::atomic_uint64_t Seele::globalCounter;
Event::Event()
: flag(new std::atomic_bool())
: flag(std::make_shared<std::atomic_bool>())
{
}
@@ -16,7 +16,8 @@ Event::Event(nullptr_t)
}
Event::Event(const std::string &name)
: name(name), flag(new std::atomic_bool())
: name(name)
, flag(std::make_shared<std::atomic_bool>())
{
}
@@ -48,75 +49,80 @@ ThreadPool::ThreadPool(uint32 threadCount)
ThreadPool::~ThreadPool()
{
running.store(false);
{
std::scoped_lock lock(jobQueueLock);
jobQueueCV.notify_all();
}
{
std::scoped_lock lock(mainJobLock);
mainJobCV.notify_all();
}
for (auto &thread : workers)
{
thread.join();
}
workers.clear();
waitingJobs.clear();
waitingMainJobs.clear();
}
void ThreadPool::enqueueWaiting(Event &event, Promise* job)
{
assert(!job->done());
if(event == nullptr)
{
std::unique_lock lock(jobQueueLock);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
jobQueue.add(job);
jobQueueCV.notify_one();
}
else
{
std::unique_lock lock(waitingLock);
std::scoped_lock lock(waitingLock);
//std::cout << "Job " << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
waitingJobs[event].add(job);
}
waitingJobs[event].push_back(job);
}
void ThreadPool::enqueueWaiting(Event &event, MainPromise* job)
{
assert(!job->done());
if(event == nullptr || event)
{
std::unique_lock lock(mainJobLock);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
mainJobs.add(job);
mainJobCV.notify_one();
}
else
{
std::unique_lock lock(waitingMainLock);
std::scoped_lock lock(waitingMainLock);
//std::cout << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
waitingMainJobs[event].add(job);
}
waitingMainJobs[event].push_back(job);
}
void ThreadPool::scheduleJob(Promise* job)
{
assert(!job->done());
std::scoped_lock lock(jobQueueLock);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
jobQueue.push_back(job);
jobQueueCV.notify_one();
}
void ThreadPool::scheduleJob(MainPromise* job)
{
assert(!job->done());
std::scoped_lock lock(mainJobLock);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
mainJobs.push_back(job);
mainJobCV.notify_one();
}
void ThreadPool::notify(Event &event)
{
//std::cout << "Event " << event.name << " raised" << std::endl;
{
std::unique_lock lock(jobQueueLock);
std::unique_lock lock2(waitingLock);
List<Promise*> &jobs = waitingJobs[event];
std::scoped_lock lock(jobQueueLock, waitingLock);
std::list<Promise*> jobs = std::move(waitingJobs[event]);
waitingJobs.erase(event);
for (auto &job : jobs)
{
//assert(job.id != -1ull);
//std::cout << "Waking up " << job->finishedEvent.name << std::endl;
job->state = Promise::State::SCHEDULED;
jobQueue.add(job);
jobQueue.push_back(job);
jobQueueCV.notify_one();
}
waitingJobs.erase(event);
}
{
std::unique_lock lock(mainJobLock);
std::unique_lock lock2(waitingMainLock);
List<MainPromise*> &jobs = waitingMainJobs[event];
std::scoped_lock lock(mainJobLock, waitingMainLock);
std::list<MainPromise*> jobs = std::move(waitingMainJobs[event]);
waitingMainJobs.erase(event);
for (auto &job : jobs)
{
//assert(job.id != -1ull);
//std::cout << "Waking up main " << job->finishedEvent.name << std::endl;
job->state = MainPromise::State::SCHEDULED;
mainJobs.add(job);
mainJobs.push_back(job);
mainJobCV.notify_one();
}
waitingMainJobs.erase(event);
}
}
void ThreadPool::threadLoop(const bool mainThread)
@@ -134,7 +140,8 @@ void ThreadPool::threadLoop(const bool mainThread)
}
if (!mainJobs.empty())
{
job = mainJobs.retrieve();
job = mainJobs.front();
mainJobs.pop_front();
}
else
{
@@ -144,7 +151,7 @@ void ThreadPool::threadLoop(const bool mainThread)
job->resume();
if (job->done())
{
job->raise();
job->finalize();
}
}
else
@@ -158,7 +165,8 @@ void ThreadPool::threadLoop(const bool mainThread)
}
if (!jobQueue.empty())
{
job = jobQueue.retrieve();
job = jobQueue.front();
jobQueue.pop_front();
}
else
{
@@ -167,9 +175,9 @@ void ThreadPool::threadLoop(const bool mainThread)
}
//std::cout << "Starting job " << job.id << std::endl;
job->resume();
if (job->done())
if(job->done())
{
job->raise();
job->finalize();
}
}
}
+28 -25
View File
@@ -16,6 +16,7 @@ public:
Event();
Event(nullptr_t);
Event(const std::string& name);
~Event() = default;
auto operator<=>(const Event& other) const
{
return flag <=> other.flag;
@@ -41,7 +42,7 @@ public:
constexpr void await_resume() {}
private:
std::string name;
RefPtr<std::atomic_bool> flag;
std::shared_ptr<std::atomic_bool> flag;
friend class ThreadPool;
};
@@ -65,6 +66,13 @@ struct JobPromiseBase
id = globalCounter++;
finishedEvent = Event(std::format("Job {}", id));
}
~JobPromiseBase()
{
if (handle)
{
handle.destroy();
}
}
JobBase<MainJob> get_return_object() noexcept;
inline auto initial_suspend() noexcept;
@@ -78,7 +86,6 @@ struct JobPromiseBase
void resume()
{
std::unique_lock lock(promiseLock);
if(!handle || handle.done() || executing())
{
return;
@@ -88,10 +95,9 @@ struct JobPromiseBase
}
void setContinuation(JobPromiseBase* cont)
{
std::unique_lock lock(promiseLock);
std::unique_lock lock2(cont->promiseLock);
std::scoped_lock lock(promiseLock, cont->promiseLock);
continuation = cont->handle;
cont->precondition = finishedEvent;
cont->state = State::SCHEDULED;
}
bool done()
{
@@ -113,15 +119,15 @@ struct JobPromiseBase
{
return state == State::READY;
}
void raise()
void finalize()
{
std::unique_lock lock(promiseLock);
std::scoped_lock lock(promiseLock);
state = State::DONE;
finishedEvent.raise();
}
void reset()
{
std::unique_lock lock(promiseLock);
std::scoped_lock lock(promiseLock);
finishedEvent.reset();
}
void enqueue(Event& event)
@@ -136,13 +142,12 @@ struct JobPromiseBase
}
void schedule()
{
std::unique_lock lock(promiseLock);
std::scoped_lock lock(promiseLock);
if(!handle || done() || !ready())
{
return;
}
state = (precondition == nullptr) ? State::SCHEDULED : State::WAITING;
getGlobalThreadPool().enqueueWaiting(precondition, this);
getGlobalThreadPool().scheduleJob(this);
}
std::mutex promiseLock;
@@ -150,7 +155,6 @@ struct JobPromiseBase
std::coroutine_handle<> continuation = std::noop_coroutine();
uint64 id;
Event finishedEvent;
Event precondition = nullptr;
State state = State::READY;
};
@@ -193,13 +197,9 @@ public:
{
return promise->done();
}
void raise()
void finalize()
{
promise->raise();
}
void reset()
{
promise->reset();
promise->finalize();
}
Event operator co_await()
{
@@ -245,30 +245,32 @@ using Promise = JobPromiseBase<false>;
class ThreadPool
{
public:
ThreadPool(uint32 threadCount = std::thread::hardware_concurrency());
ThreadPool(uint32 threadCount = 1);
virtual ~ThreadPool();
// Adds a job to the waiting queue for event, or directly to the job queue if event is nullptr
// Adds a job to the waiting queue for event
void enqueueWaiting(Event& event, Promise* job);
// Adds a job to the waiting queue for event, or directly to the job queue if event is nullptr
// Adds a job to the waiting queue for event
void enqueueWaiting(Event& event, MainPromise* job);
void scheduleJob(Promise* job);
void scheduleJob(MainPromise* job);
void notify(Event& event);
void threadLoop(const bool isMainThread);
private:
std::atomic_bool running;
std::vector<std::thread> workers;
List<MainPromise*> mainJobs;
std::list<MainPromise*> mainJobs;
std::mutex mainJobLock;
std::condition_variable mainJobCV;
List<Promise*> jobQueue;
std::list<Promise*> jobQueue;
std::mutex jobQueueLock;
std::condition_variable jobQueueCV;
std::map<Event, List<MainPromise*>> waitingMainJobs;
std::map<Event, std::list<MainPromise*>> waitingMainJobs;
std::mutex waitingMainLock;
std::map<Event, List<Promise*>> waitingJobs;
std::map<Event, std::list<Promise*>> waitingJobs;
std::mutex waitingLock;
};
@@ -283,6 +285,7 @@ inline auto JobPromiseBase<MainJob>::initial_suspend() noexcept
{
return std::suspend_always{};
}
template<bool MainJob>
inline auto JobPromiseBase<MainJob>::final_suspend() const noexcept
{
+2
View File
@@ -5,6 +5,8 @@ using namespace Seele;
using namespace Seele::UI;
Element::Element()
: dirty(false)
, enabled(false)
{
}
+4 -4
View File
@@ -31,7 +31,7 @@ RenderHierarchy::~RenderHierarchy()
void RenderHierarchy::addElement(PElement addedElement)
{
std::unique_lock lock(updateLock);
std::scoped_lock lock(updateLock);
updates.add(new AddElementRenderHierarchyUpdate{
addedElement.getHandle(),
addedElement->getParent().getHandle()
@@ -40,7 +40,7 @@ void RenderHierarchy::addElement(PElement addedElement)
void RenderHierarchy::removeElement(PElement elementToRemove)
{
std::unique_lock lock(updateLock);
std::scoped_lock lock(updateLock);
updates.add(new RemoveElementRenderHierarchyUpdate{
elementToRemove.getHandle(),
});
@@ -48,7 +48,7 @@ void RenderHierarchy::removeElement(PElement elementToRemove)
void RenderHierarchy::moveElement(PElement elementToMove, PElement newParent)
{
std::unique_lock lock(updateLock);
std::scoped_lock lock(updateLock);
updates.add(new AddElementRenderHierarchyUpdate{
elementToMove.getHandle(),
newParent.getHandle()
@@ -62,7 +62,7 @@ void RenderHierarchy::updateHierarchy()
{
List<RenderHierarchyUpdate*> localUpdates;
{ // make a local copy of the updates so we dont hold the lock for too long
std::unique_lock lock(updateLock);
std::scoped_lock lock(updateLock);
localUpdates = updates;
updates.clear();
}
+4 -3
View File
@@ -19,13 +19,14 @@ InspectorView::~InspectorView()
{
}
void InspectorView::beginUpdate()
Job InspectorView::beginUpdate()
{
co_return;
}
void InspectorView::update()
Job InspectorView::update()
{
co_return;
}
void InspectorView::commitUpdate()
+2 -2
View File
@@ -13,8 +13,8 @@ public:
InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo);
virtual ~InspectorView();
virtual void beginUpdate() override;
virtual void update() override;
virtual Job beginUpdate() override;
virtual Job update() override;
virtual void commitUpdate() override;
virtual void prepareRender() override;
+18 -8
View File
@@ -6,6 +6,8 @@
#include "Asset/AssetRegistry.h"
#include "Scene/Actor/CameraActor.h"
#include "Scene/Components/CameraComponent.h"
#include "Scene/Components/MyComponent.h"
#include "Scene/Components/MyOtherComponent.h"
using namespace Seele;
@@ -28,19 +30,24 @@ Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const Viewpo
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Ely\\Ely.fbx");
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Cube\\cube.obj");
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Plane\\plane.fbx");
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->addWorldTranslation(Vector(0, 0, 0));
ayaka->setWorldScale(Vector(10, 10, 10));
scene->addPrimitiveComponent(ayaka);
}
PPrimitiveComponent plane = new PrimitiveComponent(AssetRegistry::findMesh("plane"));
plane->setWorldScale(Vector(100, 100, 100));
scene->addPrimitiveComponent(plane);
PMyComponent myComp = new MyComponent();
PMyOtherComponent myOtherComp = new MyOtherComponent();
PActor actor = new Actor();
actor->setRootComponent(myComp);
myComp->addChildComponent(myOtherComp);
scene->addActor(actor);
scene->start();
PRenderGraphResources resources = new RenderGraphResources();
depthPrepass.setResources(resources);
lightCullingPass.setResources(resources);
@@ -59,13 +66,16 @@ Seele::SceneView::~SceneView()
{
}
void SceneView::beginUpdate()
Job SceneView::beginUpdate()
{
scene->tick(Gfx::currentFrameDelta);
co_await scene->beginUpdate(Gfx::currentFrameDelta);
co_return;
}
void SceneView::update()
Job SceneView::update()
{
co_await scene->commitUpdate();
co_return;
}
void SceneView::commitUpdate()
+2 -2
View File
@@ -13,8 +13,8 @@ class SceneView : public View
public:
SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo);
~SceneView();
virtual void beginUpdate() override;
virtual void update() override;
virtual Job beginUpdate() override;
virtual Job update() override;
virtual void commitUpdate() override;
virtual void prepareRender() override;
+2 -2
View File
@@ -13,8 +13,8 @@ public:
virtual ~View();
// These are called from the view thread, and handle updating game data
virtual void beginUpdate() = 0;
virtual void update() = 0;
virtual Job beginUpdate() = 0;
virtual Job update() = 0;
// End frame is called with a lock, so it is safe to write to shared memory
virtual void commitUpdate() = 0;
+2 -2
View File
@@ -32,7 +32,7 @@ MainJob Window::render()
co_await windowView->updateFinished;
windowView->updateFinished.reset();
{
std::unique_lock lock(windowView->workerMutex);
std::scoped_lock lock(windowView->workerMutex);
windowView->view->prepareRender();
}
windowView->view->render();
@@ -78,7 +78,7 @@ Job Window::viewWorker(size_t viewIndex)
windowView->view->beginUpdate();
windowView->view->update();
{
std::unique_lock lock(windowView->workerMutex);
std::scoped_lock lock(windowView->workerMutex);
windowView->view->commitUpdate();
}
//std::cout << "Update completed" << std::endl;
+1 -1
View File
@@ -41,7 +41,7 @@ void WindowManager::notifyWindowClosed(PWindow window)
windows.remove(windows.find(window));
if(windows.empty())
{
std::unique_lock lock(windowsLock);
std::scoped_lock lock(windowsLock);
windowsCV.notify_all();
}
}
+39
View File
@@ -40,6 +40,7 @@ BOOST_AUTO_TEST_CASE(clear)
BOOST_CHECK_EQUAL(array.size(), 3);
array.clear();
BOOST_CHECK_EQUAL(array.size(), 0);
array.add(2);
}
BOOST_AUTO_TEST_CASE(remove_keeporder)
{
@@ -113,6 +114,44 @@ BOOST_AUTO_TEST_CASE(random_access)
BOOST_CHECK_EQUAL(array[0], 4);
}
BOOST_AUTO_TEST_CASE(copy)
{
Array<uint8> array;
array.add(0);
array.add(1);
array.add(2);
array.add(3);
Array<uint8> copy = array;
BOOST_CHECK_EQUAL_COLLECTIONS(array.begin(), array.end(), copy.begin(), copy.end());
Array<uint8> copy2(copy);
BOOST_CHECK_EQUAL_COLLECTIONS(array.begin(), array.end(), copy2.begin(), copy2.end());
}
class BaseElement
{
uint64 test;
};
class BaseContainer
{
Array<BaseElement> elements;
};
class DerivedContainer : public BaseContainer
{
uint64 test;
};
BOOST_AUTO_TEST_CASE(virtual_classes)
{
Array<DerivedContainer> array(64);
for(uint32 i = 0; i < 100; ++i)
{
Array<DerivedContainer> copy = array;
BOOST_CHECK_EQUAL(array.size(), copy.size());
}
}
class TestStruct
{
public:
+3
View File
@@ -1,4 +1,6 @@
#pragma once
#include <vld.h>
#include "ThreadPool.h"
namespace Seele
{
@@ -6,6 +8,7 @@ namespace Seele
{
GlobalFixture()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
}
~GlobalFixture()
{
+10 -5
View File
@@ -23,13 +23,18 @@ Job basicThenThird()
co_return;
}
BOOST_AUTO_TEST_CASE(basic_then)
Job basicThenBase()
{
basicThenFirst()
.then(basicThenSecond())
.then(basicThenThird());
co_await basicThenFirst();
co_await basicThenSecond();
co_await basicThenThird();
}
BOOST_AUTO_TEST_CASE(basic_then)
{
basicThenBase();
}
/*
uint64 basicAllState1 = 0;
uint64 basicAllState2 = 0;
Job basicAllFirst()
@@ -69,6 +74,6 @@ BOOST_AUTO_TEST_CASE(basic_callable)
BOOST_REQUIRE_EQUAL(basicCallable, 10);
co_return;
});
}
}*/
BOOST_AUTO_TEST_SUITE_END()