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", "type": "cppvsdbg",
"request": "launch", "request": "launch",
"program": "${workspaceRoot}/bin/Debug/Seele_unit_tests.exe", "program": "${workspaceRoot}/bin/Debug/Seele_unit_tests.exe",
"args": [], "args": ["--detect_memory_leaks=15533"],
"stopAtEntry": false, "stopAtEntry": false,
"console": "internalConsole", "console": "internalConsole",
"cwd": "${workspaceRoot}/bin/Debug", "cwd": "${workspaceRoot}/bin/Debug",
+1 -1
View File
@@ -110,7 +110,7 @@ add_subdirectory(src/)
if(MSVC) if(MSVC)
set(_CRT_SECURE_NO_WARNINGS) set(_CRT_SECURE_NO_WARNINGS)
target_compile_options(SeeleEngine PRIVATE /DEBUG:FASTLINK /Zi) target_compile_options(SeeleEngine PRIVATE /Zi)
else() else()
target_compile_options(SeeleEngine PRIVATE -g -Wall -Wextra -Wno-delete-incomplete -pedantic -fcoroutines) target_compile_options(SeeleEngine PRIVATE -g -Wall -Wextra -Wno-delete-incomplete -pedantic -fcoroutines)
endif() endif()
+1 -1
View File
@@ -5,7 +5,7 @@
"cmakeCommandArgs": "-DUSE_SUPERBUILD=OFF", "cmakeCommandArgs": "-DUSE_SUPERBUILD=OFF",
"buildCommandArgs": "", "buildCommandArgs": "",
"ctestCommandArgs": "", "ctestCommandArgs": "",
"variables": [] "inheritEnvironments": []
} }
] ]
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

+1
View File
@@ -9,6 +9,7 @@ Asset::Asset()
, parentDir("") , parentDir("")
, extension("") , extension("")
, status(Status::Uninitialized) , status(Status::Uninitialized)
, byteSize(0)
{ {
} }
Asset::Asset(const std::filesystem::path& path) Asset::Asset(const std::filesystem::path& path)
+2 -2
View File
@@ -28,12 +28,12 @@ public:
std::string getExtension() const; std::string getExtension() const;
inline Status getStatus() inline Status getStatus()
{ {
std::unique_lock lck(lock); std::scoped_lock lck(lock);
return status; return status;
} }
inline void setStatus(Status status) inline void setStatus(Status status)
{ {
std::unique_lock lck(lock); std::scoped_lock lck(lock);
this->status = status; this->status = status;
} }
protected: protected:
+5 -9
View File
@@ -25,24 +25,20 @@ MeshAsset::~MeshAsset()
} }
void MeshAsset::save() void MeshAsset::save()
{ {
boost::archive::text_oarchive archive(getWriteStream());
archive << meshes;
} }
void MeshAsset::load() void MeshAsset::load()
{ {
boost::archive::text_iarchive archive(getReadStream());
archive >> meshes;
} }
void MeshAsset::addMesh(PMesh mesh) void MeshAsset::addMesh(PMesh mesh)
{ {
std::unique_lock lck(lock); std::scoped_lock lck(lock);
meshes.add(mesh); meshes.push_back(mesh);
referencedMaterials.add(mesh->referencedMaterial); 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; return meshes;
} }
+3 -3
View File
@@ -15,11 +15,11 @@ public:
virtual void save() override; virtual void save() override;
virtual void load() override; virtual void load() override;
void addMesh(PMesh mesh); void addMesh(PMesh mesh);
const Array<PMesh> getMeshes(); const std::vector<PMesh> getMeshes();
//Workaround while no editor //Workaround while no editor
Array<PMaterialAsset> referencedMaterials; std::vector<PMaterialAsset> referencedMaterials;
private: private:
Array<PMesh> meshes; std::vector<PMesh> meshes;
}; };
DEFINE_REF(MeshAsset) DEFINE_REF(MeshAsset)
} // namespace Seele } // 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.data = (uint8 *)buffer.data();
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
vbInfo.resourceData.size = sizeof(Vector) * (uint32)buffer.size(); 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) 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.data = (uint8 *)buffer.data();
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
vbInfo.resourceData.size = sizeof(Vector2) * (uint32)buffer.size(); 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) 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; virtual void load() override;
void setTexture(Gfx::PTexture texture) void setTexture(Gfx::PTexture texture)
{ {
std::unique_lock lck(lock); std::scoped_lock lck(lock);
this->texture = texture; this->texture = texture;
} }
Gfx::PTexture getTexture() Gfx::PTexture getTexture()
{ {
std::unique_lock lck(lock); std::scoped_lock lck(lock);
return texture; return texture;
} }
private: private:
File diff suppressed because it is too large Load Diff
+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 target_sources(SeeleEngine
PRIVATE PRIVATE
Array.natvis
Array.h Array.h
Map.h Map.h
List.h) List.h)
+36 -49
View File
@@ -152,15 +152,7 @@ public:
{ {
if(this != &other) if(this != &other)
{ {
if(root != nullptr) clear();
{
delete root;
}
if(tail != nullptr)
{
delete tail;
}
_size = 0;
for(const auto& it : other) for(const auto& it : other)
{ {
add(it); add(it);
@@ -173,10 +165,7 @@ public:
{ {
if(this != &other) if(this != &other)
{ {
if(root != nullptr) clear();
{
clear();
}
root = other.root; root = other.root;
tail = other.tail; tail = other.tail;
beginIt = other.beginIt; beginIt = other.beginIt;
@@ -205,6 +194,7 @@ public:
for (Node *tmp = root; tmp != tail;) for (Node *tmp = root; tmp != tail;)
{ {
tmp = tmp->next; tmp = tmp->next;
destroyNode(tmp->prev);
deallocateNode(tmp->prev); deallocateNode(tmp->prev);
} }
deallocateNode(tail); deallocateNode(tail);
@@ -216,43 +206,16 @@ public:
//Insert at the end //Insert at the end
iterator add(const T &value) iterator add(const T &value)
{ {
if (root == nullptr) return addInternal(value);
{
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;
} }
iterator add(T&& value) iterator add(T&& value)
{ {
if (root == nullptr) return addInternal(std::move(value));
{
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;
} }
// takes all elements from other and move-inserts them into // takes all elements from other and move-inserts them into
// this, clearing other in the process // this, clearing other in the process
void moveElements(List& other){ void moveElements(List& other)
{
tail->prev->next = other.root; tail->prev->next = other.root;
other.root->prev = tail->prev; other.root->prev = tail->prev;
_size += other._size; _size += other._size;
@@ -309,12 +272,13 @@ public:
} }
if(next == nullptr) if(next == nullptr)
{ {
root = prev; tail = prev;
} }
else else
{ {
next->prev = prev; next->prev = prev;
} }
destroyNode(pos.node);
deallocateNode(pos.node); deallocateNode(pos.node);
markIteratorDirty(); markIteratorDirty();
return Iterator(next); return Iterator(next);
@@ -408,10 +372,33 @@ private:
node->next, node->next,
std::forward<Type>(data)); std::forward<Type>(data));
} }
void destroyNode(Node* node)
{
std::allocator_traits<NodeAllocator>::destroy(allocator, node);
}
void deallocateNode(Node* node) void deallocateNode(Node* node)
{ {
allocator.deallocate(node, 1); 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() void markIteratorDirty()
{ {
beginIt = Iterator(root); beginIt = Iterator(root);
@@ -421,10 +408,10 @@ private:
} }
Node *root; Node *root;
Node *tail; Node *tail;
Iterator beginIt; iterator beginIt;
Iterator endIt; iterator endIt;
ConstIterator cbeginIt; const_iterator cbeginIt;
ConstIterator cendIt; const_iterator cendIt;
size_type _size; size_type _size;
NodeAllocator allocator; NodeAllocator allocator;
}; };
+1 -1
View File
@@ -56,7 +56,7 @@ public:
virtual PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) = 0; virtual PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) = 0;
virtual PDescriptorLayout createDescriptorLayout(const std::string& name = "") = 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; virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) = 0;
+1 -8
View File
@@ -22,20 +22,13 @@ struct GraphicsInitializer
GraphicsInitializer() GraphicsInitializer()
: applicationName("SeeleEngine") : applicationName("SeeleEngine")
, engineName("SeeleEngine") , engineName("SeeleEngine")
, windowLayoutFile(nullptr)
, layers{"VK_LAYER_KHRONOS_validation", "VK_LAYER_LUNARG_monitor"} , layers{"VK_LAYER_KHRONOS_validation", "VK_LAYER_LUNARG_monitor"}
, instanceExtensions{} , instanceExtensions{}
, deviceExtensions{"VK_KHR_swapchain"} , deviceExtensions{"VK_KHR_swapchain"}
, windowHandle(nullptr) , windowHandle(nullptr)
{ {
} }
GraphicsInitializer(const GraphicsInitializer &other)
: applicationName(other.applicationName)
, engineName(other.engineName)
, layers(other.layers)
, instanceExtensions(other.instanceExtensions)
, deviceExtensions(other.deviceExtensions)
{
}
}; };
struct WindowCreateInfo struct WindowCreateInfo
{ {
+4 -3
View File
@@ -57,6 +57,7 @@ ShaderCollection& ShaderMap::createShaders(
VertexInputType* vertexInput, VertexInputType* vertexInput,
bool /*bPositionOnly*/) bool /*bPositionOnly*/)
{ {
std::scoped_lock lock(shadersLock);
ShaderCollection& collection = shaders.add(); ShaderCollection& collection = shaders.add();
//collection.vertexDeclaration = bPositionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration(); //collection.vertexDeclaration = bPositionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration();
@@ -107,7 +108,7 @@ void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorTyp
PDescriptorSet DescriptorLayout::allocateDescriptorSet() PDescriptorSet DescriptorLayout::allocateDescriptorSet()
{ {
std::unique_lock lock(allocatorLock); std::scoped_lock lock(allocatorLock);
PDescriptorSet result; PDescriptorSet result;
allocator->allocateDescriptorSet(result); allocator->allocateDescriptorSet(result);
return result; return result;
@@ -115,7 +116,7 @@ PDescriptorSet DescriptorLayout::allocateDescriptorSet()
void DescriptorLayout::reset() void DescriptorLayout::reset()
{ {
std::unique_lock lock(allocatorLock); std::scoped_lock lock(allocatorLock);
allocator->reset(); allocator->reset();
} }
@@ -270,7 +271,7 @@ static Map<uint32, PVertexDeclaration> vertexDeclarationCache;
PVertexDeclaration VertexDeclaration::createDeclaration(PGraphics graphics, const Array<VertexElement>& elementList) PVertexDeclaration VertexDeclaration::createDeclaration(PGraphics graphics, const Array<VertexElement>& elementList)
{ {
std::unique_lock lock(vertexDeclarationLock); std::scoped_lock lock(vertexDeclarationLock);
boost::crc_32_type result; boost::crc_32_type result;
result.process_bytes(&elementList, sizeof(VertexElement) * elementList.size()); result.process_bytes(&elementList, sizeof(VertexElement) * elementList.size());
uint32 key = result.checksum(); uint32 key = result.checksum();
+9 -1
View File
@@ -144,6 +144,7 @@ public:
VertexInputType* vertexInput, VertexInputType* vertexInput,
bool bPositionOnly); bool bPositionOnly);
private: private:
std::mutex shadersLock;
Array<ShaderCollection> shaders; Array<ShaderCollection> shaders;
}; };
DEFINE_REF(ShaderMap) DEFINE_REF(ShaderMap)
@@ -242,7 +243,14 @@ DEFINE_REF(DescriptorLayout)
class PipelineLayout class PipelineLayout
{ {
public: public:
PipelineLayout() {} PipelineLayout(PPipelineLayout baseLayout)
{
if(baseLayout != nullptr)
{
descriptorSetLayouts = baseLayout->descriptorSetLayouts;
pushConstants = baseLayout->pushConstants;
}
}
virtual ~PipelineLayout() {} virtual ~PipelineLayout() {}
virtual void create() = 0; virtual void create() = 0;
virtual void reset() = 0; virtual void reset() = 0;
-5
View File
@@ -15,11 +15,6 @@ public:
PVertexShaderInput vertexInput; PVertexShaderInput vertexInput;
PMaterialAsset referencedMaterial; PMaterialAsset referencedMaterial;
private: private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive&, const unsigned int)
{
}
}; };
DEFINE_REF(Mesh) DEFINE_REF(Mesh)
} // namespace Seele } // namespace Seele
+1
View File
@@ -24,5 +24,6 @@ MeshBatch::MeshBatch()
, topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) , topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
, vertexInput(nullptr) , vertexInput(nullptr)
, material(nullptr) , material(nullptr)
, elements()
{ {
} }
+5 -1
View File
@@ -34,7 +34,7 @@ public:
}; };
struct MeshBatch struct MeshBatch
{ {
Array<MeshBatchElement> elements; std::vector<MeshBatchElement> elements;
uint8 useReverseCulling : 1; uint8 useReverseCulling : 1;
uint8 isBackfaceCullingDisabled : 1; uint8 isBackfaceCullingDisabled : 1;
@@ -68,6 +68,10 @@ struct MeshBatch
} }
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) DECLARE_REF(PrimitiveComponent)
struct StaticMeshBatch : public MeshBatch struct StaticMeshBatch : public MeshBatch
+6 -5
View File
@@ -20,11 +20,11 @@ BasePassMeshProcessor::~BasePassMeshProcessor()
{ {
} }
void BasePassMeshProcessor::processMeshBatch( Job BasePassMeshProcessor::processMeshBatch(
const MeshBatch& batch, const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent, // const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass, const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout, Gfx::PPipelineLayout baseLayout,
Gfx::PDescriptorLayout primitiveLayout, Gfx::PDescriptorLayout primitiveLayout,
Array<Gfx::PDescriptorSet> descriptorSets, Array<Gfx::PDescriptorSet> descriptorSets,
int32 /*staticMeshId*/) int32 /*staticMeshId*/)
@@ -40,6 +40,7 @@ void BasePassMeshProcessor::processMeshBatch(
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand(); Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
renderCommand->setViewport(target); renderCommand->setViewport(target);
Gfx::PPipelineLayout pipelineLayout = graphics->createPipelineLayout(baseLayout);
pipelineLayout->addDescriptorLayout(BasePass::INDEX_MATERIAL, material->getDescriptorLayout()); pipelineLayout->addDescriptorLayout(BasePass::INDEX_MATERIAL, material->getDescriptorLayout());
pipelineLayout->create(); pipelineLayout->create();
Gfx::PDescriptorSet materialSet = material->createDescriptorSet(); Gfx::PDescriptorSet materialSet = material->createDescriptorSet();
@@ -63,9 +64,9 @@ void BasePassMeshProcessor::processMeshBatch(
collection->fragmentShader, collection->fragmentShader,
false); false);
} }
std::unique_lock lock(commandLock); std::scoped_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)
@@ -157,7 +158,7 @@ MainJob BasePass::render()
for (auto &&meshBatch : passData.staticDrawList) for (auto &&meshBatch : passData.staticDrawList)
{ {
//jobs.add( //jobs.add(
processor->processMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets); co_await 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());
+2 -2
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 void processMeshBatch( virtual Job processMeshBatch(
const MeshBatch& batch, const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent, // const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass, const Gfx::PRenderPass& renderPass,
@@ -30,7 +30,7 @@ DECLARE_REF(CameraActor)
DECLARE_REF(CameraComponent) DECLARE_REF(CameraComponent)
struct BasePassData struct BasePassData
{ {
Array<StaticMeshBatch> staticDrawList; std::vector<StaticMeshBatch> staticDrawList;
}; };
class BasePass : public RenderPass<BasePassData> class BasePass : public RenderPass<BasePassData>
{ {
@@ -18,11 +18,11 @@ DepthPrepassMeshProcessor::~DepthPrepassMeshProcessor()
{ {
} }
void DepthPrepassMeshProcessor::processMeshBatch( Job DepthPrepassMeshProcessor::processMeshBatch(
const MeshBatch& batch, const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent, // const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass, const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout, Gfx::PPipelineLayout baseLayout,
Gfx::PDescriptorLayout primitiveLayout, Gfx::PDescriptorLayout primitiveLayout,
Array<Gfx::PDescriptorSet> descriptorSets, Array<Gfx::PDescriptorSet> descriptorSets,
int32 /*staticMeshId*/) int32 /*staticMeshId*/)
@@ -38,6 +38,7 @@ void DepthPrepassMeshProcessor::processMeshBatch(
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand(); Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
renderCommand->setViewport(target); renderCommand->setViewport(target);
Gfx::PPipelineLayout pipelineLayout = graphics->createPipelineLayout(baseLayout);
pipelineLayout->addDescriptorLayout(DepthPrepass::INDEX_MATERIAL, material->getDescriptorLayout()); pipelineLayout->addDescriptorLayout(DepthPrepass::INDEX_MATERIAL, material->getDescriptorLayout());
pipelineLayout->create(); pipelineLayout->create();
Gfx::PDescriptorSet materialSet = material->createDescriptorSet(); Gfx::PDescriptorSet materialSet = material->createDescriptorSet();
@@ -61,10 +62,10 @@ void DepthPrepassMeshProcessor::processMeshBatch(
collection->fragmentShader, collection->fragmentShader,
true); true);
} }
std::unique_lock lock(commandLock); std::scoped_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)
@@ -128,10 +129,9 @@ MainJob DepthPrepass::render()
for (auto &&meshBatch : passData.staticDrawList) for (auto &&meshBatch : passData.staticDrawList)
{ {
//jobs.add( //jobs.add(
processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets); co_await 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;
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 void processMeshBatch( virtual Job processMeshBatch(
const MeshBatch& batch, const MeshBatch& batch,
const Gfx::PRenderPass& renderPass, const Gfx::PRenderPass& renderPass,
Gfx::PPipelineLayout pipelineLayout, Gfx::PPipelineLayout pipelineLayout,
@@ -27,7 +27,7 @@ DECLARE_REF(CameraActor)
DECLARE_REF(CameraComponent) DECLARE_REF(CameraComponent)
struct DepthPrepassData struct DepthPrepassData
{ {
Array<StaticMeshBatch> staticDrawList; std::vector<StaticMeshBatch> staticDrawList;
}; };
class DepthPrepass : public RenderPass<DepthPrepassData> class DepthPrepass : public RenderPass<DepthPrepassData>
{ {
@@ -1,6 +1,7 @@
#include "MeshProcessor.h" #include "MeshProcessor.h"
#include "Graphics/Graphics.h" #include "Graphics/Graphics.h"
#include "Graphics/VertexShaderInput.h" #include "Graphics/VertexShaderInput.h"
#include "Graphics/Vulkan/VulkanGraphicsResources.h"
using namespace Seele; using namespace Seele;
@@ -32,8 +33,6 @@ void MeshProcessor::buildMeshDrawCommand(
GraphicsPipelineCreateInfo pipelineInitializer; GraphicsPipelineCreateInfo pipelineInitializer;
pipelineInitializer.topology = meshBatch.topology; pipelineInitializer.topology = meshBatch.topology;
Gfx::PVertexDeclaration vertexDecl = positionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration();
pipelineInitializer.vertexDeclaration = vertexDecl;
pipelineInitializer.vertexShader = vertexShader; pipelineInitializer.vertexShader = vertexShader;
pipelineInitializer.controlShader = controlShader; pipelineInitializer.controlShader = controlShader;
pipelineInitializer.evalShader = evaluationShader; pipelineInitializer.evalShader = evaluationShader;
@@ -46,10 +45,12 @@ void MeshProcessor::buildMeshDrawCommand(
if(positionOnly) if(positionOnly)
{ {
vertexInput->getPositionOnlyStream(vertexStreams); vertexInput->getPositionOnlyStream(vertexStreams);
pipelineInitializer.vertexDeclaration = vertexInput->getPositionDeclaration();
} }
else else
{ {
vertexInput->getStreams(vertexStreams); vertexInput->getStreams(vertexStreams);
pipelineInitializer.vertexDeclaration = vertexInput->getDeclaration();
} }
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(pipelineInitializer); Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(pipelineInitializer);
drawCommand->bindPipeline(pipeline); drawCommand->bindPipeline(pipeline);
@@ -17,7 +17,7 @@ public:
protected: protected:
PScene scene; PScene scene;
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
virtual void processMeshBatch( virtual Job processMeshBatch(
const MeshBatch& batch, const MeshBatch& batch,
// const PPrimitiveComponent primitiveComponent, // const PPrimitiveComponent primitiveComponent,
const Gfx::PRenderPass& renderPass, const Gfx::PRenderPass& renderPass,
@@ -77,7 +77,7 @@ void GpuCrashTracker::Initialize()
void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize)
{ {
// Make sure only one thread at a time... // 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. // Write to file for later in-depth analysis with Nsight Graphics.
WriteGpuCrashDumpToFile(pGpuCrashDump, gpuCrashDumpSize); 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) void GpuCrashTracker::OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize)
{ {
// Make sure only one thread at a time... // 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 // Get shader debug information identifier
GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier = {}; GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier = {};
+10 -7
View File
@@ -74,7 +74,7 @@ Allocation::~Allocation()
PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment) PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
{ {
std::unique_lock lck(lock); std::scoped_lock lck(lock);
if (isDedicated) if (isDedicated)
{ {
if (activeAllocations.empty() && requestedSize == bytesAllocated) if (activeAllocations.empty() && requestedSize == bytesAllocated)
@@ -134,7 +134,7 @@ void Allocation::markFree(SubAllocation *allocation)
PSubAllocation freeRangeToDelete; PSubAllocation freeRangeToDelete;
{ {
std::unique_lock lck(lock); std::scoped_lock lck(lock);
//Join lower bound //Join lower bound
for (auto freeRange : freeRanges) for (auto freeRange : freeRanges)
{ {
@@ -204,7 +204,7 @@ Allocator::Allocator(PGraphics graphics)
Allocator::~Allocator() Allocator::~Allocator()
{ {
std::unique_lock lck(lock); std::scoped_lock lck(lock);
for (auto heap : heaps) for (auto heap : heaps)
{ {
for (auto alloc : heap.allocations) for (auto alloc : heap.allocations)
@@ -219,7 +219,7 @@ Allocator::~Allocator()
PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) 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; const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
uint8 memoryTypeIndex; uint8 memoryTypeIndex;
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex)); VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
@@ -252,7 +252,7 @@ PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2
void Allocator::free(Allocation *allocation) void Allocator::free(Allocation *allocation)
{ {
std::unique_lock lck(lock); std::scoped_lock lck(lock);
for (auto heap : heaps) for (auto heap : heaps)
{ {
for (uint32 i = 0; i < heap.allocations.size(); ++i) 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) 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) for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
{ {
auto freeBuffer = *it; auto freeBuffer = *it;
@@ -323,6 +323,9 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF
PStagingBuffer stagingBuffer = new StagingBuffer(); PStagingBuffer stagingBuffer = new StagingBuffer();
VkBufferCreateInfo stagingBufferCreateInfo = init::BufferCreateInfo(usage, size); VkBufferCreateInfo stagingBufferCreateInfo = init::BufferCreateInfo(usage, size);
stagingBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 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(); VkDevice vulkanDevice = graphics->getDevice();
VK_CHECK(vkCreateBuffer(vulkanDevice, &stagingBufferCreateInfo, nullptr, &stagingBuffer->buffer)); VK_CHECK(vkCreateBuffer(vulkanDevice, &stagingBufferCreateInfo, nullptr, &stagingBuffer->buffer));
@@ -355,7 +358,7 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF
void StagingManager::releaseStagingBuffer(PStagingBuffer buffer) void StagingManager::releaseStagingBuffer(PStagingBuffer buffer)
{ {
std::unique_lock l(lock); std::scoped_lock l(lock);
freeBuffers.add(buffer); freeBuffers.add(buffer);
activeBuffers.remove(activeBuffers.find(buffer.getHandle())); activeBuffers.remove(activeBuffers.find(buffer.getHandle()));
} }
+309 -309
View File
@@ -10,277 +10,277 @@ using namespace Seele::Vulkan;
struct PendingBuffer struct PendingBuffer
{ {
PStagingBuffer stagingBuffer; PStagingBuffer stagingBuffer;
Gfx::QueueType prevQueue; Gfx::QueueType prevQueue;
bool bWriteOnly; bool bWriteOnly;
}; };
static Map<ShaderBuffer *, PendingBuffer> pendingBuffers; static Map<ShaderBuffer *, PendingBuffer> pendingBuffers;
ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic) ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic)
: graphics(graphics) : graphics(graphics)
, currentBuffer(0) , currentBuffer(0)
, size(size) , size(size)
, owner(queueType) , owner(queueType)
{ {
if(bDynamic) if(bDynamic)
{ {
numBuffers = Gfx::numFramesBuffered; numBuffers = Gfx::numFramesBuffered;
} }
else else
{ {
numBuffers = 1; numBuffers = 1;
} }
usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
VkBufferCreateInfo info = VkBufferCreateInfo info =
init::BufferCreateInfo( init::BufferCreateInfo(
usage, usage,
size); size);
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
uint32 queueFamilyIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(queueType); uint32 queueFamilyIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(queueType);
info.pQueueFamilyIndices = &queueFamilyIndex; info.pQueueFamilyIndices = &queueFamilyIndex;
info.queueFamilyIndexCount = 0; info.queueFamilyIndexCount = 1;
VkBufferMemoryRequirementsInfo2 bufferReqInfo; VkBufferMemoryRequirementsInfo2 bufferReqInfo;
bufferReqInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2; bufferReqInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
bufferReqInfo.pNext = nullptr; bufferReqInfo.pNext = nullptr;
VkMemoryDedicatedRequirements dedicatedRequirements; VkMemoryDedicatedRequirements dedicatedRequirements;
dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
dedicatedRequirements.pNext = nullptr; dedicatedRequirements.pNext = nullptr;
VkMemoryRequirements2 memRequirements; VkMemoryRequirements2 memRequirements;
memRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; memRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
memRequirements.pNext = &dedicatedRequirements; memRequirements.pNext = &dedicatedRequirements;
for (uint32 i = 0; i < numBuffers; ++i) for (uint32 i = 0; i < numBuffers; ++i)
{ {
VK_CHECK(vkCreateBuffer(graphics->getDevice(), &info, nullptr, &buffers[i].buffer)); VK_CHECK(vkCreateBuffer(graphics->getDevice(), &info, nullptr, &buffers[i].buffer));
bufferReqInfo.buffer = buffers[i].buffer; bufferReqInfo.buffer = buffers[i].buffer;
vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferReqInfo, &memRequirements); vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferReqInfo, &memRequirements);
auto temp = graphics->getAllocator()->allocate(memRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buffers[i].buffer); auto temp = graphics->getAllocator()->allocate(memRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buffers[i].buffer);
buffers[i].allocation = temp; buffers[i].allocation = temp;
vkBindBufferMemory(graphics->getDevice(), buffers[i].buffer, buffers[i].allocation->getHandle(), buffers[i].allocation->getOffset()); vkBindBufferMemory(graphics->getDevice(), buffers[i].buffer, buffers[i].allocation->getHandle(), buffers[i].allocation->getOffset());
} }
} }
ShaderBuffer::~ShaderBuffer() ShaderBuffer::~ShaderBuffer()
{ {
PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands(); PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands();
VkDevice device = graphics->getDevice(); VkDevice device = graphics->getDevice();
auto deletionLambda = [cmdBuffer, device](VkBuffer buffer) -> Job auto deletionLambda = [cmdBuffer, device](VkBuffer buffer) -> Job
{ {
//co_await cmdBuffer->asyncWait(); //co_await cmdBuffer->asyncWait();
//vkDestroyBuffer(device, buffer, nullptr); //vkDestroyBuffer(device, buffer, nullptr);
co_return; co_return;
}; };
for (uint32 i = 0; i < numBuffers; ++i) for (uint32 i = 0; i < numBuffers; ++i)
{ {
deletionLambda(buffers[i].buffer); deletionLambda(buffers[i].buffer);
buffers[i].allocation = nullptr; buffers[i].allocation = nullptr;
} }
graphics = nullptr; graphics = nullptr;
} }
VkDeviceSize ShaderBuffer::getOffset() const VkDeviceSize ShaderBuffer::getOffset() const
{ {
return buffers[currentBuffer].allocation->getOffset(); return buffers[currentBuffer].allocation->getOffset();
} }
void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{ {
VkBufferMemoryBarrier barrier = VkBufferMemoryBarrier barrier =
init::BufferMemoryBarrier(); init::BufferMemoryBarrier();
PCommandBufferManager sourceManager = graphics->getQueueCommands(owner); PCommandBufferManager sourceManager = graphics->getQueueCommands(owner);
PCommandBufferManager dstManager = nullptr; PCommandBufferManager dstManager = nullptr;
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping(); Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
barrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner); barrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner);
barrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner); barrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner);
assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex); assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex);
if (owner == Gfx::QueueType::TRANSFER || owner == Gfx::QueueType::DEDICATED_TRANSFER) if (owner == Gfx::QueueType::TRANSFER || owner == Gfx::QueueType::DEDICATED_TRANSFER)
{ {
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
} }
else if (owner == Gfx::QueueType::COMPUTE) else if (owner == Gfx::QueueType::COMPUTE)
{ {
barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
} }
else if (owner == Gfx::QueueType::GRAPHICS) else if (owner == Gfx::QueueType::GRAPHICS)
{ {
barrier.srcAccessMask = getSourceAccessMask(); barrier.srcAccessMask = getSourceAccessMask();
srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
} }
if (newOwner == Gfx::QueueType::TRANSFER) if (newOwner == Gfx::QueueType::TRANSFER)
{ {
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstManager = graphics->getTransferCommands(); dstManager = graphics->getTransferCommands();
} }
else if (newOwner == Gfx::QueueType::DEDICATED_TRANSFER) else if (newOwner == Gfx::QueueType::DEDICATED_TRANSFER)
{ {
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
dstManager = graphics->getDedicatedTransferCommands(); dstManager = graphics->getDedicatedTransferCommands();
} }
else if (newOwner == Gfx::QueueType::COMPUTE) else if (newOwner == Gfx::QueueType::COMPUTE)
{ {
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
dstStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; dstStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
dstManager = graphics->getComputeCommands(); dstManager = graphics->getComputeCommands();
} }
else if (newOwner == Gfx::QueueType::GRAPHICS) else if (newOwner == Gfx::QueueType::GRAPHICS)
{ {
barrier.dstAccessMask = getDestAccessMask(); barrier.dstAccessMask = getDestAccessMask();
dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
dstManager = graphics->getGraphicsCommands(); dstManager = graphics->getGraphicsCommands();
} }
VkCommandBuffer srcCommand = sourceManager->getCommands()->getHandle(); VkCommandBuffer srcCommand = sourceManager->getCommands()->getHandle();
VkCommandBuffer dstCommand = dstManager->getCommands()->getHandle(); VkCommandBuffer dstCommand = dstManager->getCommands()->getHandle();
VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered];
barrier.offset = 0; barrier.offset = 0;
barrier.size = size; barrier.size = size;
for (uint32 i = 0; i < numBuffers; ++i) for (uint32 i = 0; i < numBuffers; ++i)
{ {
dynamicBarriers[i] = barrier; dynamicBarriers[i] = barrier;
dynamicBarriers[i].buffer = buffers[i].buffer; dynamicBarriers[i].buffer = buffers[i].buffer;
} }
vkCmdPipelineBarrier(srcCommand, srcStage, srcStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); vkCmdPipelineBarrier(srcCommand, srcStage, srcStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
vkCmdPipelineBarrier(dstCommand, dstStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); vkCmdPipelineBarrier(dstCommand, dstStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
sourceManager->submitCommands(); sourceManager->submitCommands();
} }
void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) VkAccessFlags dstAccess, VkPipelineStageFlags dstStage)
{ {
PCmdBuffer commandBuffer = graphics->getQueueCommands(owner)->getCommands(); PCmdBuffer commandBuffer = graphics->getQueueCommands(owner)->getCommands();
VkBufferMemoryBarrier barrier = init::BufferMemoryBarrier(); VkBufferMemoryBarrier barrier = init::BufferMemoryBarrier();
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstAccessMask = dstAccess; barrier.dstAccessMask = dstAccess;
barrier.srcAccessMask = srcAccess; barrier.srcAccessMask = srcAccess;
barrier.offset = 0; barrier.offset = 0;
barrier.size = size; barrier.size = size;
VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered];
for(uint32 i = 0; i < numBuffers; ++i) for(uint32 i = 0; i < numBuffers; ++i)
{ {
dynamicBarriers[i] = barrier; dynamicBarriers[i] = barrier;
dynamicBarriers[i].buffer = buffers[i].buffer; dynamicBarriers[i].buffer = buffers[i].buffer;
} }
vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
} }
void *ShaderBuffer::lock(bool bWriteOnly) void *ShaderBuffer::lock(bool bWriteOnly)
{ {
void *data = nullptr; void *data = nullptr;
/*if (bVolatile) /*if (bVolatile)
{ {
if (lockMode == RLM_ReadOnly) if (lockMode == RLM_ReadOnly)
{ {
assert(0); assert(0);
} }
else else
{ {
throw new std::logic_error("TODO implement volatile buffers"); throw new std::logic_error("TODO implement volatile buffers");
//device->getRHIDevice()->getTemp //device->getRHIDevice()->getTemp
} }
}*/ }*/
//assert(bStatic || bDynamic || bUAV); //assert(bStatic || bDynamic || bUAV);
PendingBuffer pending; PendingBuffer pending;
pending.bWriteOnly = bWriteOnly; pending.bWriteOnly = bWriteOnly;
pending.prevQueue = owner; pending.prevQueue = owner;
if (bWriteOnly) if (bWriteOnly)
{ {
//requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); //requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
data = stagingBuffer->getMappedPointer(); data = stagingBuffer->getMappedPointer();
pending.stagingBuffer = stagingBuffer; pending.stagingBuffer = stagingBuffer;
} }
else else
{ {
PCmdBuffer current = graphics->getQueueCommands(owner)->getCommands(); PCmdBuffer current = graphics->getQueueCommands(owner)->getCommands();
graphics->getQueueCommands(owner)->submitCommands(); graphics->getQueueCommands(owner)->submitCommands();
current->waitForCommand(); current->waitForCommand();
requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
VkCommandBuffer handle = graphics->getQueueCommands(owner)->getCommands()->getHandle(); VkCommandBuffer handle = graphics->getQueueCommands(owner)->getCommands()->getHandle();
VkBufferMemoryBarrier barrier = VkBufferMemoryBarrier barrier =
init::BufferMemoryBarrier(); init::BufferMemoryBarrier();
barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
barrier.buffer = buffers[currentBuffer].buffer; barrier.buffer = buffers[currentBuffer].buffer;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.offset = 0; barrier.offset = 0;
barrier.size = size; barrier.size = size;
vkCmdPipelineBarrier(handle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); vkCmdPipelineBarrier(handle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr);
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true); PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, true);
VkBufferCopy regions; VkBufferCopy regions;
regions.size = size; regions.size = size;
regions.srcOffset = 0; regions.srcOffset = 0;
regions.dstOffset = 0; regions.dstOffset = 0;
vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, &regions); vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, &regions);
graphics->getQueueCommands(owner)->submitCommands(); graphics->getQueueCommands(owner)->submitCommands();
vkQueueWaitIdle(graphics->getQueueCommands(owner)->getQueue()->getHandle()); vkQueueWaitIdle(graphics->getQueueCommands(owner)->getQueue()->getHandle());
stagingBuffer->flushMappedMemory(); stagingBuffer->flushMappedMemory();
pending.stagingBuffer = stagingBuffer; pending.stagingBuffer = stagingBuffer;
data = stagingBuffer->getMappedPointer(); data = stagingBuffer->getMappedPointer();
} }
pendingBuffers[this] = pending; pendingBuffers[this] = pending;
assert(data); assert(data);
return data; return data;
} }
void ShaderBuffer::unlock() void ShaderBuffer::unlock()
{ {
auto found = pendingBuffers.find(this); auto found = pendingBuffers.find(this);
if (found != pendingBuffers.end()) if (found != pendingBuffers.end())
{ {
PendingBuffer pending = found->value; PendingBuffer pending = found->value;
pending.stagingBuffer->flushMappedMemory(); pending.stagingBuffer->flushMappedMemory();
pendingBuffers.erase(this); pendingBuffers.erase(this);
if (pending.bWriteOnly) if (pending.bWriteOnly)
{ {
PStagingBuffer stagingBuffer = pending.stagingBuffer; PStagingBuffer stagingBuffer = pending.stagingBuffer;
PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands(); PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands();
VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); VkCommandBuffer cmdHandle = cmdBuffer->getHandle();
VkBufferCopy region; VkBufferCopy region;
std::memset(&region, 0, sizeof(VkBufferCopy)); std::memset(&region, 0, sizeof(VkBufferCopy));
region.size = size; region.size = size;
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region); vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
graphics->getQueueCommands(owner)->submitCommands(); graphics->getQueueCommands(owner)->submitCommands();
} }
//requestOwnershipTransfer(pending.prevQueue); //requestOwnershipTransfer(pending.prevQueue);
graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer); graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer);
} }
} }
UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &createInfo) UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &createInfo)
: Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.resourceData) : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.resourceData)
, Vulkan::ShaderBuffer(graphics, createInfo.resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.bDynamic) , Vulkan::ShaderBuffer(graphics, createInfo.resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.bDynamic)
, dedicatedStagingBuffer(nullptr) , dedicatedStagingBuffer(nullptr)
{ {
if(createInfo.bDynamic) if(createInfo.bDynamic)
{ {
dedicatedStagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(createInfo.resourceData.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); dedicatedStagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(createInfo.resourceData.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
} }
if (createInfo.resourceData.data != nullptr) if (createInfo.resourceData.data != nullptr)
{ {
void *data = lock(); void *data = lock();
std::memcpy(data, createInfo.resourceData.data, createInfo.resourceData.size); std::memcpy(data, createInfo.resourceData.data, createInfo.resourceData.size);
unlock(); unlock();
} }
} }
UniformBuffer::~UniformBuffer() UniformBuffer::~UniformBuffer()
@@ -290,52 +290,52 @@ UniformBuffer::~UniformBuffer()
bool UniformBuffer::updateContents(const BulkResourceData &resourceData) bool UniformBuffer::updateContents(const BulkResourceData &resourceData)
{ {
if(!Gfx::UniformBuffer::updateContents(resourceData)) if(!Gfx::UniformBuffer::updateContents(resourceData))
{ {
// no update was performed, skip // no update was performed, skip
return false; return false;
} }
void* data = lock(); void* data = lock();
std::memcpy(data, resourceData.data, resourceData.size); std::memcpy(data, resourceData.data, resourceData.size);
unlock(); unlock();
return true; return true;
} }
void* UniformBuffer::lock(bool bWriteOnly) void* UniformBuffer::lock(bool bWriteOnly)
{ {
if(dedicatedStagingBuffer != nullptr) if(dedicatedStagingBuffer != nullptr)
{ {
return dedicatedStagingBuffer->getMappedPointer(); return dedicatedStagingBuffer->getMappedPointer();
} }
return ShaderBuffer::lock(bWriteOnly); return ShaderBuffer::lock(bWriteOnly);
} }
void UniformBuffer::unlock() void UniformBuffer::unlock()
{ {
if(dedicatedStagingBuffer != nullptr) if(dedicatedStagingBuffer != nullptr)
{ {
dedicatedStagingBuffer->flushMappedMemory(); dedicatedStagingBuffer->flushMappedMemory();
PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); VkCommandBuffer cmdHandle = cmdBuffer->getHandle();
VkBufferCopy region; VkBufferCopy region;
std::memset(&region, 0, sizeof(VkBufferCopy)); std::memset(&region, 0, sizeof(VkBufferCopy));
region.size = ShaderBuffer::size; region.size = ShaderBuffer::size;
vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region); vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
graphics->getQueueCommands(currentOwner)->submitCommands(); graphics->getQueueCommands(currentOwner)->submitCommands();
} }
else else
{ {
ShaderBuffer::unlock(); ShaderBuffer::unlock();
} }
} }
void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{ {
Gfx::QueueOwnedResource::transferOwnership(newOwner); Gfx::QueueOwnedResource::transferOwnership(newOwner);
} }
void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{ {
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
} }
void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
@@ -346,24 +346,24 @@ void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineSt
VkAccessFlags UniformBuffer::getSourceAccessMask() VkAccessFlags UniformBuffer::getSourceAccessMask()
{ {
return VK_ACCESS_MEMORY_WRITE_BIT; return VK_ACCESS_MEMORY_WRITE_BIT;
} }
VkAccessFlags UniformBuffer::getDestAccessMask() VkAccessFlags UniformBuffer::getDestAccessMask()
{ {
return VK_ACCESS_UNIFORM_READ_BIT; return VK_ACCESS_UNIFORM_READ_BIT;
} }
StructuredBuffer::StructuredBuffer(PGraphics graphics, const StructuredBufferCreateInfo &resourceData) StructuredBuffer::StructuredBuffer(PGraphics graphics, const StructuredBufferCreateInfo &resourceData)
: Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.resourceData) : Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.resourceData)
, Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, resourceData.bDynamic) , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, resourceData.bDynamic)
{ {
if (resourceData.resourceData.data != nullptr) if (resourceData.resourceData.data != nullptr)
{ {
void *data = lock(); void *data = lock();
std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size);
unlock(); unlock();
} }
} }
StructuredBuffer::~StructuredBuffer() StructuredBuffer::~StructuredBuffer()
@@ -373,49 +373,49 @@ StructuredBuffer::~StructuredBuffer()
bool StructuredBuffer::updateContents(const BulkResourceData &resourceData) bool StructuredBuffer::updateContents(const BulkResourceData &resourceData)
{ {
Gfx::StructuredBuffer::updateContents(resourceData); Gfx::StructuredBuffer::updateContents(resourceData);
//We always want to update, as the contents could be different on the GPU //We always want to update, as the contents could be different on the GPU
void* data = lock(); void* data = lock();
std::memcpy(data, resourceData.data, resourceData.size); std::memcpy(data, resourceData.data, resourceData.size);
unlock(); unlock();
return true; return true;
} }
void* StructuredBuffer::lock(bool bWriteOnly) void* StructuredBuffer::lock(bool bWriteOnly)
{ {
if(dedicatedStagingBuffer != nullptr) if(dedicatedStagingBuffer != nullptr)
{ {
return dedicatedStagingBuffer->getMappedPointer(); return dedicatedStagingBuffer->getMappedPointer();
} }
return ShaderBuffer::lock(bWriteOnly); return ShaderBuffer::lock(bWriteOnly);
} }
void StructuredBuffer::unlock() void StructuredBuffer::unlock()
{ {
if(dedicatedStagingBuffer != nullptr) if(dedicatedStagingBuffer != nullptr)
{ {
dedicatedStagingBuffer->flushMappedMemory(); dedicatedStagingBuffer->flushMappedMemory();
PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); VkCommandBuffer cmdHandle = cmdBuffer->getHandle();
VkBufferCopy region; VkBufferCopy region;
std::memset(&region, 0, sizeof(VkBufferCopy)); std::memset(&region, 0, sizeof(VkBufferCopy));
region.size = ShaderBuffer::size; region.size = ShaderBuffer::size;
vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region); vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
graphics->getQueueCommands(currentOwner)->submitCommands(); graphics->getQueueCommands(currentOwner)->submitCommands();
} }
else else
{ {
ShaderBuffer::unlock(); ShaderBuffer::unlock();
} }
} }
void StructuredBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) void StructuredBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{ {
Gfx::QueueOwnedResource::transferOwnership(newOwner); Gfx::QueueOwnedResource::transferOwnership(newOwner);
} }
void StructuredBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) void StructuredBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{ {
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
} }
void StructuredBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, void StructuredBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
@@ -426,24 +426,24 @@ void StructuredBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelin
VkAccessFlags StructuredBuffer::getSourceAccessMask() VkAccessFlags StructuredBuffer::getSourceAccessMask()
{ {
return VK_ACCESS_MEMORY_WRITE_BIT; return VK_ACCESS_MEMORY_WRITE_BIT;
} }
VkAccessFlags StructuredBuffer::getDestAccessMask() VkAccessFlags StructuredBuffer::getDestAccessMask()
{ {
return VK_ACCESS_MEMORY_READ_BIT; return VK_ACCESS_MEMORY_READ_BIT;
} }
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData) VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData)
: Gfx::VertexBuffer(graphics->getFamilyMapping(), resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner) : Gfx::VertexBuffer(graphics->getFamilyMapping(), resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner)
, Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner) , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner)
{ {
if (resourceData.resourceData.data != nullptr) if (resourceData.resourceData.data != nullptr)
{ {
void *data = lock(); void *data = lock();
std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size);
unlock(); unlock();
} }
} }
VertexBuffer::~VertexBuffer() VertexBuffer::~VertexBuffer()
@@ -452,12 +452,12 @@ VertexBuffer::~VertexBuffer()
void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{ {
Gfx::QueueOwnedResource::transferOwnership(newOwner); Gfx::QueueOwnedResource::transferOwnership(newOwner);
} }
void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{ {
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
} }
void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
@@ -468,24 +468,24 @@ void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineSta
VkAccessFlags VertexBuffer::getSourceAccessMask() VkAccessFlags VertexBuffer::getSourceAccessMask()
{ {
return VK_ACCESS_MEMORY_WRITE_BIT; return VK_ACCESS_MEMORY_WRITE_BIT;
} }
VkAccessFlags VertexBuffer::getDestAccessMask() VkAccessFlags VertexBuffer::getDestAccessMask()
{ {
return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
} }
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData) IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData)
: Gfx::IndexBuffer(graphics->getFamilyMapping(), resourceData.resourceData.size, resourceData.indexType, resourceData.resourceData.owner) : Gfx::IndexBuffer(graphics->getFamilyMapping(), resourceData.resourceData.size, resourceData.indexType, resourceData.resourceData.owner)
, Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, currentOwner) , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, currentOwner)
{ {
if (resourceData.resourceData.data != nullptr) if (resourceData.resourceData.data != nullptr)
{ {
void *data = lock(); void *data = lock();
std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size);
unlock(); unlock();
} }
} }
IndexBuffer::~IndexBuffer() IndexBuffer::~IndexBuffer()
@@ -494,12 +494,12 @@ IndexBuffer::~IndexBuffer()
void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{ {
Gfx::QueueOwnedResource::transferOwnership(newOwner); Gfx::QueueOwnedResource::transferOwnership(newOwner);
} }
void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
{ {
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
} }
void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage,
@@ -510,10 +510,10 @@ void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStag
VkAccessFlags IndexBuffer::getSourceAccessMask() VkAccessFlags IndexBuffer::getSourceAccessMask()
{ {
return VK_ACCESS_MEMORY_WRITE_BIT; return VK_ACCESS_MEMORY_WRITE_BIT;
} }
VkAccessFlags IndexBuffer::getDestAccessMask() VkAccessFlags IndexBuffer::getDestAccessMask()
{ {
return VK_ACCESS_INDEX_READ_BIT; return VK_ACCESS_INDEX_READ_BIT;
} }
@@ -16,16 +16,13 @@ using namespace Seele::Vulkan;
CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferManager manager) CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferManager manager)
: graphics(graphics) : graphics(graphics)
, manager(manager) , manager(manager)
, renderPass(nullptr)
, framebuffer(nullptr)
, subpassIndex(0)
, owner(cmdPool) , owner(cmdPool)
{ {
VkCommandBufferAllocateInfo allocInfo = VkCommandBufferAllocateInfo allocInfo =
init::CommandBufferAllocateInfo(cmdPool, init::CommandBufferAllocateInfo(cmdPool,
VK_COMMAND_BUFFER_LEVEL_PRIMARY, VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1); 1);
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle)) VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle))
fence = new Fence(graphics); fence = new Fence(graphics);
@@ -34,10 +31,8 @@ CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferMa
CmdBuffer::~CmdBuffer() CmdBuffer::~CmdBuffer()
{ {
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle); vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
renderPass = nullptr;
framebuffer = nullptr;
waitSemaphores.clear(); waitSemaphores.clear();
} }
@@ -46,24 +41,22 @@ void CmdBuffer::begin()
VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo beginInfo =
init::CommandBufferBeginInfo(); init::CommandBufferBeginInfo();
beginInfo.pInheritanceInfo = nullptr; beginInfo.pInheritanceInfo = nullptr;
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo)); VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
state = State::InsideBegin; state = State::InsideBegin;
} }
void CmdBuffer::end() void CmdBuffer::end()
{ {
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
VK_CHECK(vkEndCommandBuffer(handle)); VK_CHECK(vkEndCommandBuffer(handle));
state = State::Ended; state = State::Ended;
} }
void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFramebuffer) void CmdBuffer::beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer)
{ {
assert(state == State::InsideBegin); assert(state == State::InsideBegin);
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
renderPass = newRenderPass;
framebuffer = newFramebuffer;
VkRenderPassBeginInfo beginInfo = VkRenderPassBeginInfo beginInfo =
init::RenderPassBeginInfo(); init::RenderPassBeginInfo();
@@ -74,15 +67,13 @@ 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;
} }
void CmdBuffer::endRenderPass() void CmdBuffer::endRenderPass()
{ {
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
vkCmdEndRenderPass(handle); vkCmdEndRenderPass(handle);
state = State::InsideBegin; state = State::InsideBegin;
//std::cout << "Ending renderPass" << std::endl;
} }
void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands) void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
@@ -90,9 +81,10 @@ void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
assert(state == State::RenderPassActive); assert(state == State::RenderPassActive);
if(commands.size() == 0) if(commands.size() == 0)
{ {
std::cout << "No commands provided" << std::endl;
return; return;
} }
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
Array<VkCommandBuffer> cmdBuffers(commands.size()); Array<VkCommandBuffer> cmdBuffers(commands.size());
for (uint32 i = 0; i < commands.size(); ++i) 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) void CmdBuffer::executeCommands(const Array<Gfx::PComputeCommand>& commands)
{ {
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
if(commands.size() == 0) if(commands.size() == 0)
{ {
return; return;
@@ -134,14 +126,14 @@ void CmdBuffer::executeCommands(const Array<Gfx::PComputeCommand>& commands)
void CmdBuffer::addWaitSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore) void CmdBuffer::addWaitSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore)
{ {
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
waitSemaphores.add(semaphore); waitSemaphores.add(semaphore);
waitFlags.add(flags); waitFlags.add(flags);
} }
void CmdBuffer::refreshFence() void CmdBuffer::refreshFence()
{ {
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
if (state == State::Submitted) if (state == State::Submitted)
{ {
if (fence->isSignaled()) if (fence->isSignaled())
@@ -174,7 +166,7 @@ void CmdBuffer::refreshFence()
void CmdBuffer::waitForCommand(uint32 timeout) void CmdBuffer::waitForCommand(uint32 timeout)
{ {
std::unique_lock lock(handleLock); std::scoped_lock lock(handleLock);
fence->wait(timeout); fence->wait(timeout);
refreshFence(); refreshFence();
} }
@@ -212,7 +204,7 @@ RenderCommand::~RenderCommand()
vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle); vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle);
} }
void RenderCommand::begin(PCmdBuffer parent) void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer)
{ {
threadId = std::this_thread::get_id(); threadId = std::this_thread::get_id();
ready = false; ready = false;
@@ -220,9 +212,9 @@ void RenderCommand::begin(PCmdBuffer parent)
init::CommandBufferBeginInfo(); init::CommandBufferBeginInfo();
VkCommandBufferInheritanceInfo inheritanceInfo = VkCommandBufferInheritanceInfo inheritanceInfo =
init::CommandBufferInheritanceInfo(); init::CommandBufferInheritanceInfo();
inheritanceInfo.framebuffer = parent->framebuffer->getHandle(); inheritanceInfo.framebuffer = framebuffer->getHandle();
inheritanceInfo.renderPass = parent->renderPass->getHandle(); inheritanceInfo.renderPass = renderPass->getHandle();
inheritanceInfo.subpass = parent->subpassIndex; inheritanceInfo.subpass = 0;
beginInfo.pInheritanceInfo = &inheritanceInfo; beginInfo.pInheritanceInfo = &inheritanceInfo;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo)); VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo));
@@ -230,13 +222,11 @@ void RenderCommand::begin(PCmdBuffer parent)
void RenderCommand::end() void RenderCommand::end()
{ {
assert(threadId == std::this_thread::get_id());
VK_CHECK(vkEndCommandBuffer(handle)); VK_CHECK(vkEndCommandBuffer(handle));
} }
void RenderCommand::reset() void RenderCommand::reset()
{ {
assert(threadId == std::this_thread::get_id());
vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
boundDescriptors.clear(); boundDescriptors.clear();
ready = true; ready = true;
@@ -420,7 +410,7 @@ CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue)
activeCmdBuffer = new CmdBuffer(graphics, commandPool, this); activeCmdBuffer = new CmdBuffer(graphics, commandPool, this);
activeCmdBuffer->begin(); activeCmdBuffer->begin();
std::unique_lock lock(allocatedBufferLock); std::scoped_lock lock(allocatedBufferLock);
allocatedBuffers.add(activeCmdBuffer); allocatedBuffers.add(activeCmdBuffer);
} }
@@ -436,29 +426,29 @@ PCmdBuffer CommandBufferManager::getCommands()
return activeCmdBuffer; 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) for (uint32 i = 0; i < allocatedRenderCommands.size(); ++i)
{ {
PRenderCommand cmdBuffer = allocatedRenderCommands[i]; PRenderCommand cmdBuffer = allocatedRenderCommands[i];
if (cmdBuffer->isReady()) if (cmdBuffer->isReady())
{ {
cmdBuffer->name = name; cmdBuffer->name = name;
cmdBuffer->begin(activeCmdBuffer); cmdBuffer->begin(renderPass, framebuffer);
return cmdBuffer; return cmdBuffer;
} }
} }
PRenderCommand result = new RenderCommand(graphics, commandPool); PRenderCommand result = new RenderCommand(graphics, commandPool);
result->name = name; result->name = name;
result->begin(activeCmdBuffer); result->begin(renderPass, framebuffer);
allocatedRenderCommands.add(result); allocatedRenderCommands.add(result);
return result; return result;
} }
PComputeCommand CommandBufferManager::createComputeCommand(const std::string& name) 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) for (uint32 i = 0; i < allocatedComputeCommands.size(); ++i)
{ {
PComputeCommand cmdBuffer = allocatedComputeCommands[i]; PComputeCommand cmdBuffer = allocatedComputeCommands[i];
@@ -495,7 +485,7 @@ void CommandBufferManager::submitCommands(PSemaphore signalSemaphore)
queue->submitCommandBuffer(activeCmdBuffer); queue->submitCommandBuffer(activeCmdBuffer);
} }
} }
std::unique_lock lock(allocatedBufferLock); std::scoped_lock lock(allocatedBufferLock);
for (uint32 i = 0; i < allocatedBuffers.size(); ++i) for (uint32 i = 0; i < allocatedBuffers.size(); ++i)
{ {
PCmdBuffer cmdBuffer = allocatedBuffers[i]; PCmdBuffer cmdBuffer = allocatedBuffers[i];
@@ -47,10 +47,7 @@ public:
private: private:
PGraphics graphics; PGraphics graphics;
PCommandBufferManager manager; PCommandBufferManager manager;
PRenderPass renderPass;
PFramebuffer framebuffer;
PFence fence; PFence fence;
uint32 subpassIndex;
State state; State state;
VkViewport currentViewport; VkViewport currentViewport;
VkRect2D currentScissor; VkRect2D currentScissor;
@@ -79,7 +76,7 @@ public:
{ {
return handle; return handle;
} }
void begin(PCmdBuffer parent); void begin(PRenderPass renderPass, PFramebuffer framebuffer);
void end(); void end();
void reset(); void reset();
virtual bool isReady() override; virtual bool isReady() override;
@@ -145,7 +142,7 @@ public:
return queue; return queue;
} }
PCmdBuffer getCommands(); PCmdBuffer getCommands();
PRenderCommand createRenderCommand(const std::string& name); PRenderCommand createRenderCommand(PRenderPass renderPass, PFramebuffer framebuffer, const std::string& name);
PComputeCommand createComputeCommand(const std::string& name); PComputeCommand createComputeCommand(const std::string& name);
VkCommandPool getPoolHandle() const VkCommandPool getPoolHandle() const
{ {
@@ -54,7 +54,7 @@ PipelineLayout::~PipelineLayout()
{ {
if (layoutHandle != VK_NULL_HANDLE) 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 class PipelineLayout : public Gfx::PipelineLayout
{ {
public: public:
PipelineLayout(PGraphics graphics) PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout)
: graphics(graphics) : Gfx::PipelineLayout(baseLayout)
, graphics(graphics)
, layoutHash(0) , layoutHash(0)
, layoutHandle(VK_NULL_HANDLE) , layoutHandle(VK_NULL_HANDLE)
{ {}
}
virtual ~PipelineLayout(); virtual ~PipelineLayout();
virtual void create(); virtual void create();
virtual void reset(); virtual void reset();
+28 -29
View File
@@ -14,6 +14,11 @@
using namespace Seele::Vulkan; 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() Graphics::Graphics()
: instance(VK_NULL_HANDLE) : instance(VK_NULL_HANDLE)
, handle(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) Gfx::PViewport Graphics::createViewport(Gfx::PWindow owner, const ViewportCreateInfo &viewportInfo)
{ {
PViewport result = new Viewport(this, owner, viewportInfo); PViewport result = new Viewport(this, owner, viewportInfo);
std::unique_lock lock(viewportLock); std::scoped_lock lock(viewportLock);
viewports.add(result); viewports.add(result);
return result; return result;
} }
@@ -67,7 +72,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
uint32 framebufferHash = rp->getFramebufferHash(); uint32 framebufferHash = rp->getFramebufferHash();
PFramebuffer framebuffer; PFramebuffer framebuffer;
{ {
std::unique_lock lock(allocatedFrameBufferLock); std::scoped_lock lock(allocatedFrameBufferLock);
auto found = allocatedFramebuffers.find(framebufferHash); auto found = allocatedFramebuffers.find(framebufferHash);
if (found == allocatedFramebuffers.end()) if (found == allocatedFramebuffers.end())
{ {
@@ -80,12 +85,18 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
} }
} }
getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer); getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer);
std::scoped_lock lock(renderPassLock);
activeRenderPass = rp;
activeFramebuffer = framebuffer;
} }
void Graphics::endRenderPass() void Graphics::endRenderPass()
{ {
getGraphicsCommands()->getCommands()->endRenderPass(); getGraphicsCommands()->getCommands()->endRenderPass();
getGraphicsCommands()->submitCommands(); getGraphicsCommands()->submitCommands();
std::scoped_lock lock(renderPassLock);
activeRenderPass = nullptr;
activeFramebuffer = nullptr;
} }
void Graphics::executeCommands(const Array<Gfx::PRenderCommand>& commands) 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) Gfx::PRenderCommand Graphics::createRenderCommand(const std::string& name)
{ {
PRenderCommand cmdBuffer = getGraphicsCommands()->createRenderCommand(name); PRenderCommand cmdBuffer = getGraphicsCommands()->createRenderCommand(activeRenderPass, activeFramebuffer, name);
return cmdBuffer; return cmdBuffer;
} }
@@ -206,9 +217,9 @@ Gfx::PDescriptorLayout Graphics::createDescriptorLayout(const std::string& name)
PDescriptorLayout layout = new DescriptorLayout(this, name); PDescriptorLayout layout = new DescriptorLayout(this, name);
return layout; 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; return layout;
} }
@@ -295,49 +306,37 @@ PCommandBufferManager Graphics::getQueueCommands(Gfx::QueueType queueType)
throw new std::logic_error("invalid queue type"); throw new std::logic_error("invalid queue type");
} }
} }
std::mutex graphicsCommandLock;
PCommandBufferManager Graphics::getGraphicsCommands() PCommandBufferManager Graphics::getGraphicsCommands()
{ {
std::unique_lock lock(graphicsCommandLock); if(graphicsCommands == nullptr)
auto id = std::this_thread::get_id();
if(graphicsCommands.find(id) == graphicsCommands.end())
{ {
graphicsCommands[id] = new CommandBufferManager(this, graphicsQueue); graphicsCommands = new CommandBufferManager(this, graphicsQueue);
} }
return graphicsCommands[id]; return graphicsCommands;
} }
std::mutex computeCommandLock;
PCommandBufferManager Graphics::getComputeCommands() PCommandBufferManager Graphics::getComputeCommands()
{ {
std::unique_lock lock(computeCommandLock); if(computeCommands == nullptr)
auto id = std::this_thread::get_id();
if(computeCommands.find(id) == computeCommands.end())
{ {
computeCommands[id] = new CommandBufferManager(this, computeQueue); computeCommands = new CommandBufferManager(this, computeQueue);
} }
return computeCommands[id]; return computeCommands;
} }
std::mutex transferCommandLock;
PCommandBufferManager Graphics::getTransferCommands() PCommandBufferManager Graphics::getTransferCommands()
{ {
std::unique_lock lock(transferCommandLock); if(transferCommands == nullptr)
auto id = std::this_thread::get_id();
if(transferCommands.find(id) == transferCommands.end())
{ {
transferCommands[id] = new CommandBufferManager(this, transferQueue); transferCommands = new CommandBufferManager(this, transferQueue);
} }
return transferCommands[id]; return transferCommands;
} }
std::mutex dedicatedCommandLock;
PCommandBufferManager Graphics::getDedicatedTransferCommands() PCommandBufferManager Graphics::getDedicatedTransferCommands()
{ {
std::unique_lock lock(dedicatedCommandLock); if(dedicatedTransferCommands == dedicatedTransferCommands)
auto id = std::this_thread::get_id();
if(dedicatedTransferCommands.find(id) == dedicatedTransferCommands.end())
{ {
dedicatedTransferCommands[id] = new CommandBufferManager(this, dedicatedTransferQueue); dedicatedTransferCommands = new CommandBufferManager(this, dedicatedTransferQueue);
} }
return dedicatedTransferCommands[id]; return dedicatedTransferCommands;
} }
PAllocator Graphics::getAllocator() PAllocator Graphics::getAllocator()
{ {
+9 -5
View File
@@ -11,6 +11,7 @@ DECLARE_REF(Allocator)
DECLARE_REF(StagingManager) DECLARE_REF(StagingManager)
DECLARE_REF(CommandBufferManager) DECLARE_REF(CommandBufferManager)
DECLARE_REF(Queue) DECLARE_REF(Queue)
DECLARE_REF(RenderPass)
DECLARE_REF(Framebuffer) DECLARE_REF(Framebuffer)
DECLARE_REF(RenderCommand) DECLARE_REF(RenderCommand)
DECLARE_REF(PipelineCache) DECLARE_REF(PipelineCache)
@@ -63,7 +64,7 @@ public:
virtual Gfx::PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) override; virtual Gfx::PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) override;
virtual Gfx::PDescriptorLayout createDescriptorLayout(const std::string& name = "") 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; virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override;
protected: protected:
@@ -82,10 +83,13 @@ protected:
PQueue transferQueue; PQueue transferQueue;
PQueue dedicatedTransferQueue; PQueue dedicatedTransferQueue;
PPipelineCache pipelineCache; PPipelineCache pipelineCache;
Map<std::thread::id, PCommandBufferManager> graphicsCommands; std::mutex renderPassLock;
Map<std::thread::id, PCommandBufferManager> computeCommands; PRenderPass activeRenderPass;
Map<std::thread::id, PCommandBufferManager> transferCommands; PFramebuffer activeFramebuffer;
Map<std::thread::id, PCommandBufferManager> dedicatedTransferCommands; thread_local static PCommandBufferManager graphicsCommands;
thread_local static PCommandBufferManager computeCommands;
thread_local static PCommandBufferManager transferCommands;
thread_local static PCommandBufferManager dedicatedTransferCommands;
VkPhysicalDeviceProperties props; VkPhysicalDeviceProperties props;
VkPhysicalDeviceFeatures features; VkPhysicalDeviceFeatures features;
VkDebugReportCallbackEXT callback; VkDebugReportCallbackEXT callback;
@@ -296,6 +296,8 @@ VkBufferMemoryBarrier init::BufferMemoryBarrier()
VkBufferMemoryBarrier bufferMemoryBarrier = {}; VkBufferMemoryBarrier bufferMemoryBarrier = {};
bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
bufferMemoryBarrier.pNext = NULL; bufferMemoryBarrier.pNext = NULL;
bufferMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
bufferMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
return bufferMemoryBarrier; return bufferMemoryBarrier;
} }
@@ -323,7 +323,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
uint32 hash = crc.checksum(); uint32 hash = crc.checksum();
VkPipeline pipelineHandle; VkPipeline pipelineHandle;
std::unique_lock lock(createdPipelinesLock); std::scoped_lock lock(createdPipelinesLock);
auto foundPipeline = createdPipelines.find(hash); auto foundPipeline = createdPipelines.find(hash);
if (foundPipeline != createdPipelines.end()) if (foundPipeline != createdPipelines.end())
{ {
+1 -1
View File
@@ -22,7 +22,7 @@ Queue::~Queue()
void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore *signalSemaphores) 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); assert(cmdBuffer->state == CmdBuffer::State::Ended);
PFence fence = cmdBuffer->fence; 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) 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); return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
} }
+6 -2
View File
@@ -49,7 +49,7 @@ public:
~RefObject() ~RefObject()
{ {
{ {
std::unique_lock lock(registeredObjectsLock); std::scoped_lock lock(registeredObjectsLock);
registeredObjects.erase(handle); registeredObjects.erase(handle);
} }
// #pragma warning( disable: 4150) // #pragma warning( disable: 4150)
@@ -114,7 +114,7 @@ public:
} }
RefPtr(T *ptr, Deleter deleter = Deleter()) RefPtr(T *ptr, Deleter deleter = Deleter())
{ {
std::unique_lock l(registeredObjectsLock); std::scoped_lock l(registeredObjectsLock);
auto registeredObj = registeredObjects.find(ptr); auto registeredObj = registeredObjects.find(ptr);
// get here for thread safetly // get here for thread safetly
auto registeredEnd = registeredObjects.end(); auto registeredEnd = registeredObjects.end();
@@ -249,6 +249,10 @@ public:
{ {
return object->getHandle(); return object->getHandle();
} }
RefPtr<T, Deleter> clone()
{
return RefPtr<T, Deleter>(new T(*getHandle()));
}
private: private:
RefObject<T, Deleter> *object; 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) void Actor::notifySceneAttach(PScene scene)
{ {
+7 -2
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Math/Transform.h" #include "Math/Transform.h"
#include "ThreadPool.h"
namespace Seele namespace Seele
{ {
@@ -12,8 +13,12 @@ class Actor
public: public:
Actor(); Actor();
virtual ~Actor(); virtual ~Actor();
virtual void launchStart();
void tick(float deltaTime); 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); void notifySceneAttach(PScene scene);
PScene getScene(); PScene getScene();
+1
View File
@@ -1,5 +1,6 @@
target_sources(SeeleEngine target_sources(SeeleEngine
PRIVATE PRIVATE
Util.h
Scene.cpp Scene.cpp
Scene.h) Scene.h)
@@ -4,6 +4,10 @@ target_sources(SeeleEngine
CameraComponent.cpp CameraComponent.cpp
Component.h Component.h
Component.cpp Component.cpp
MyComponent.h
MyComponent.cpp
MyOtherComponent.h
MyOtherComponent.cpp
PrimitiveComponent.cpp PrimitiveComponent.cpp
PrimitiveComponent.h PrimitiveComponent.h
PrimitiveUniformBufferLayout.h) PrimitiveUniformBufferLayout.h)
@@ -5,11 +5,16 @@
using namespace Seele; using namespace Seele;
CameraComponent::CameraComponent() CameraComponent::CameraComponent()
: bNeedsViewBuild(true) : aspectRatio(0)
, fieldOfView(0)
, bNeedsViewBuild(true)
, bNeedsProjectionBuild(true) , bNeedsProjectionBuild(true)
, originPoint(0, 0, 0) , originPoint(0, 0, 0)
, cameraPosition(0, 0, 50) , cameraPosition(0, 0, 50)
, eye(Vector())
, projectionMatrix(Matrix4())
, viewMatrix(Matrix4())
{ {
distance = 50; distance = 50;
rotationX = 0; rotationX = 0;
+49 -11
View File
@@ -13,9 +13,38 @@ Component::Component()
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() PComponent Component::getParent()
{ {
return parent; return parent;
@@ -32,6 +61,25 @@ PActor Component::getOwner()
} }
return nullptr; 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) void Component::notifySceneAttach(PScene scene)
{ {
@@ -118,16 +166,6 @@ Transform Component::getTransform() const
return transform; return transform;
} }
void Component::setParent(PComponent newParent)
{
parent = newParent;
}
void Component::setOwner(PActor newOwner)
{
owner = newOwner;
}
void Component::internalSetTransform(Vector newLocation, Quaternion newRotation) void Component::internalSetTransform(Vector newLocation, Quaternion newRotation)
{ {
if (parent != nullptr) if (parent != nullptr)
+33 -1
View File
@@ -1,6 +1,8 @@
#pragma once #pragma once
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Math/Transform.h" #include "Math/Transform.h"
#include "Scene/Util.h"
#include "ThreadPool.h"
namespace Seele namespace Seele
{ {
@@ -12,11 +14,18 @@ class Component
public: public:
Component(); Component();
virtual ~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(); PComponent getParent();
PActor getOwner(); PActor getOwner();
const Array<PComponent>& getChildComponents();
void setParent(PComponent parent); void setParent(PComponent parent);
void setOwner(PActor owner); void setOwner(PActor owner);
void addChildComponent(PComponent component);
virtual void notifySceneAttach(PScene scene); virtual void notifySceneAttach(PScene scene);
void setWorldLocation(Vector location); void setWorldLocation(Vector location);
@@ -35,7 +44,30 @@ public:
Transform getTransform() const; Transform getTransform() const;
template<typename ComponentType>
RefPtr<ComponentType> getComponent()
{
return tryFindComponent<ComponentType>();
}
private: 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 internalSetTransform(Vector newLocation, Quaternion newRotation);
void propagateTransformUpdate(); void propagateTransformUpdate();
void updateComponentTransform(Quaternion relativeRotationQuat); 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.useReverseCulling = false;
batch.useWireframe = false; batch.useWireframe = false;
batch.vertexInput = assetMeshes[i]->vertexInput; batch.vertexInput = assetMeshes[i]->vertexInput;
auto& batchElement = batch.elements.add(); MeshBatchElement batchElement;
batchElement.baseVertexIndex = 0; batchElement.baseVertexIndex = 0;
batchElement.firstIndex = 0; batchElement.firstIndex = 0;
batchElement.indexBuffer = assetMeshes[i]->indexBuffer; batchElement.indexBuffer = assetMeshes[i]->indexBuffer;
@@ -35,6 +35,7 @@ PrimitiveComponent::PrimitiveComponent(PMeshAsset asset)
batchElement.isInstanced = false; batchElement.isInstanced = false;
batchElement.numInstances = 1; batchElement.numInstances = 1;
batchElement.numPrimitives = assetMeshes[i]->indexBuffer->getNumIndices() / 3; //TODO: hardcoded batchElement.numPrimitives = assetMeshes[i]->indexBuffer->getNumIndices() / 3; //TODO: hardcoded
batch.elements.push_back(batchElement);
} }
} }
@@ -16,14 +16,14 @@ public:
~PrimitiveComponent(); ~PrimitiveComponent();
virtual void notifySceneAttach(PScene scene) override; virtual void notifySceneAttach(PScene scene) override;
Matrix4 getRenderMatrix(); Matrix4 getRenderMatrix();
const Array<StaticMeshBatch>& getStaticMeshes() std::vector<StaticMeshBatch>& getStaticMeshes()
{ {
return staticMeshes; return staticMeshes;
} }
private: private:
Array<PMaterialAsset> materials; std::vector<PMaterialAsset> materials;
Gfx::PUniformBuffer uniformBuffer; Gfx::PUniformBuffer uniformBuffer;
Array<StaticMeshBatch> staticMeshes; std::vector<StaticMeshBatch> staticMeshes;
friend class Scene; friend class Scene;
}; };
DEFINE_REF(PrimitiveComponent) 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) void Scene::addActor(PActor actor)
{ {
rootActors.add(actor); rootActors.push_back(actor);
actor->notifySceneAttach(this); actor->notifySceneAttach(this);
} }
void Scene::addPrimitiveComponent(PPrimitiveComponent comp) void Scene::addPrimitiveComponent(PPrimitiveComponent comp)
{ {
primitives.add(comp); primitives.push_back(comp);
for(auto& batch : comp->getStaticMeshes()) for(auto& batch : comp->getStaticMeshes())
{ {
PrimitiveUniformBuffer data; PrimitiveUniformBuffer data;
@@ -62,6 +82,6 @@ void Scene::addPrimitiveComponent(PPrimitiveComponent comp)
{ {
element.uniformBuffer = uniformBuffer; element.uniformBuffer = uniformBuffer;
} }
staticMeshes.add(batch); staticMeshes.push_back(batch);
} }
} }
+8 -6
View File
@@ -38,17 +38,19 @@ class Scene
public: public:
Scene(Gfx::PGraphics graphics); Scene(Gfx::PGraphics graphics);
~Scene(); ~Scene();
void tick(double deltaTime); void start();
Job beginUpdate(double deltaTime);
Job commitUpdate();
void addActor(PActor actor); void addActor(PActor actor);
void addPrimitiveComponent(PPrimitiveComponent comp); void addPrimitiveComponent(PPrimitiveComponent comp);
const Array<PPrimitiveComponent>& getPrimitives() const { return primitives; } const std::vector<PPrimitiveComponent>& getPrimitives() const { return primitives; }
const Array<StaticMeshBatch>& getStaticMeshes() const { return staticMeshes; } const std::vector<StaticMeshBatch>& getStaticMeshes() const { return staticMeshes; }
const LightEnv& getLightBuffer() const { return lightEnv; } const LightEnv& getLightBuffer() const { return lightEnv; }
private: private:
Array<StaticMeshBatch> staticMeshes; std::vector<StaticMeshBatch> staticMeshes;
Array<PActor> rootActors; std::vector<PActor> rootActors;
Array<PPrimitiveComponent> primitives; std::vector<PPrimitiveComponent> primitives;
LightEnv lightEnv; LightEnv lightEnv;
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
}; };
+7 -7
View File
@@ -26,25 +26,25 @@ SceneUpdater::~SceneUpdater()
void SceneUpdater::registerComponentUpdate(PComponent component) void SceneUpdater::registerComponentUpdate(PComponent component)
{ {
std::unique_lock lck(pendingUpdatesLock); std::scoped_lock lck(pendingUpdatesLock);
updatesRan.add([component](float delta) mutable { component->tick(delta); }); updatesRan.add([component](float delta) mutable { component->tick(delta); });
} }
void SceneUpdater::registerActorUpdate(PActor actor) void SceneUpdater::registerActorUpdate(PActor actor)
{ {
std::unique_lock lck(pendingUpdatesLock); std::scoped_lock lck(pendingUpdatesLock);
updatesRan.add([actor](float delta) mutable { actor->tick(delta); }); updatesRan.add([actor](float delta) mutable { actor->tick(delta); });
} }
void SceneUpdater::runUpdates(float delta) void SceneUpdater::runUpdates(float delta)
{ {
std::unique_lock pendingLock(pendingUpdatesLock); std::scoped_lock pendingLock(pendingUpdatesLock);
frameDelta = delta; frameDelta = delta;
pendingUpdates = std::move(updatesRan); pendingUpdates = std::move(updatesRan);
updatesRan = List<std::function<void(float)>>(); updatesRan = List<std::function<void(float)>>();
std::unique_lock lck(frameFinishedLock); std::scoped_lock lck(frameFinishedLock);
pendingLock.unlock(); pendingLock.unlock();
pendingUpdatesSem.release(pendingUpdates.size()); pendingUpdatesSem.release(pendingUpdates.size());
frameFinishedCV.wait(lck); frameFinishedCV.wait(lck);
@@ -57,18 +57,18 @@ void SceneUpdater::work()
pendingUpdatesSem.acquire(); pendingUpdatesSem.acquire();
std::function<void(float)> function; std::function<void(float)> function;
{ {
std::unique_lock lck(pendingUpdatesLock); std::scoped_lock lck(pendingUpdatesLock);
function = std::move(pendingUpdates.front()); function = std::move(pendingUpdates.front());
pendingUpdates.popFront(); pendingUpdates.popFront();
if(pendingUpdates.empty()) if(pendingUpdates.empty())
{ {
std::unique_lock lck(frameFinishedLock); std::scoped_lock lck(frameFinishedLock);
frameFinishedCV.notify_all(); frameFinishedCV.notify_all();
} }
} }
function(frameDelta); function(frameDelta);
{ {
std::unique_lock lck(pendingUpdatesLock); std::scoped_lock lck(pendingUpdatesLock);
updatesRan.add(std::move(function)); 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
+51 -43
View File
@@ -6,7 +6,7 @@ using namespace Seele;
std::atomic_uint64_t Seele::globalCounter; std::atomic_uint64_t Seele::globalCounter;
Event::Event() 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) 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() ThreadPool::~ThreadPool()
{ {
running.store(false); running.store(false);
{
std::scoped_lock lock(jobQueueLock);
jobQueueCV.notify_all();
}
{
std::scoped_lock lock(mainJobLock);
mainJobCV.notify_all();
}
for (auto &thread : workers) for (auto &thread : workers)
{ {
thread.join(); thread.join();
} }
workers.clear();
waitingJobs.clear();
waitingMainJobs.clear();
} }
void ThreadPool::enqueueWaiting(Event &event, Promise* job) void ThreadPool::enqueueWaiting(Event &event, Promise* job)
{ {
assert(!job->done()); assert(!job->done());
if(event == nullptr) std::scoped_lock lock(waitingLock);
{ //std::cout << "Job " << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
std::unique_lock lock(jobQueueLock); waitingJobs[event].push_back(job);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
jobQueue.add(job);
jobQueueCV.notify_one();
}
else
{
std::unique_lock lock(waitingLock);
//std::cout << "Job " << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
waitingJobs[event].add(job);
}
} }
void ThreadPool::enqueueWaiting(Event &event, MainPromise* job) void ThreadPool::enqueueWaiting(Event &event, MainPromise* job)
{ {
assert(!job->done()); assert(!job->done());
if(event == nullptr || event) std::scoped_lock lock(waitingMainLock);
{ //std::cout << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
std::unique_lock lock(mainJobLock); waitingMainJobs[event].push_back(job);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl; }
mainJobs.add(job); void ThreadPool::scheduleJob(Promise* job)
mainJobCV.notify_one(); {
} assert(!job->done());
else std::scoped_lock lock(jobQueueLock);
{ //std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
std::unique_lock lock(waitingMainLock); jobQueue.push_back(job);
//std::cout << job->finishedEvent.name << " waiting on event " << event.name << std::endl; jobQueueCV.notify_one();
waitingMainJobs[event].add(job); }
} 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) void ThreadPool::notify(Event &event)
{ {
//std::cout << "Event " << event.name << " raised" << std::endl; //std::cout << "Event " << event.name << " raised" << std::endl;
{ {
std::unique_lock lock(jobQueueLock); std::scoped_lock lock(jobQueueLock, waitingLock);
std::unique_lock lock2(waitingLock); std::list<Promise*> jobs = std::move(waitingJobs[event]);
List<Promise*> &jobs = waitingJobs[event]; waitingJobs.erase(event);
for (auto &job : jobs) for (auto &job : jobs)
{ {
//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; job->state = Promise::State::SCHEDULED;
jobQueue.add(job); jobQueue.push_back(job);
jobQueueCV.notify_one(); jobQueueCV.notify_one();
} }
waitingJobs.erase(event);
} }
{ {
std::unique_lock lock(mainJobLock); std::scoped_lock lock(mainJobLock, waitingMainLock);
std::unique_lock lock2(waitingMainLock); std::list<MainPromise*> jobs = std::move(waitingMainJobs[event]);
List<MainPromise*> &jobs = waitingMainJobs[event]; waitingMainJobs.erase(event);
for (auto &job : jobs) for (auto &job : jobs)
{ {
//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; job->state = MainPromise::State::SCHEDULED;
mainJobs.add(job); mainJobs.push_back(job);
mainJobCV.notify_one(); mainJobCV.notify_one();
} }
waitingMainJobs.erase(event);
} }
} }
void ThreadPool::threadLoop(const bool mainThread) void ThreadPool::threadLoop(const bool mainThread)
@@ -134,7 +140,8 @@ void ThreadPool::threadLoop(const bool mainThread)
} }
if (!mainJobs.empty()) if (!mainJobs.empty())
{ {
job = mainJobs.retrieve(); job = mainJobs.front();
mainJobs.pop_front();
} }
else else
{ {
@@ -144,7 +151,7 @@ void ThreadPool::threadLoop(const bool mainThread)
job->resume(); job->resume();
if (job->done()) if (job->done())
{ {
job->raise(); job->finalize();
} }
} }
else else
@@ -158,7 +165,8 @@ void ThreadPool::threadLoop(const bool mainThread)
} }
if (!jobQueue.empty()) if (!jobQueue.empty())
{ {
job = jobQueue.retrieve(); job = jobQueue.front();
jobQueue.pop_front();
} }
else else
{ {
@@ -167,9 +175,9 @@ void ThreadPool::threadLoop(const bool mainThread)
} }
//std::cout << "Starting job " << job.id << std::endl; //std::cout << "Starting job " << job.id << std::endl;
job->resume(); job->resume();
if (job->done()) if(job->done())
{ {
job->raise(); job->finalize();
} }
} }
} }
+28 -25
View File
@@ -16,6 +16,7 @@ public:
Event(); Event();
Event(nullptr_t); Event(nullptr_t);
Event(const std::string& name); Event(const std::string& name);
~Event() = default;
auto operator<=>(const Event& other) const auto operator<=>(const Event& other) const
{ {
return flag <=> other.flag; return flag <=> other.flag;
@@ -41,7 +42,7 @@ public:
constexpr void await_resume() {} constexpr void await_resume() {}
private: private:
std::string name; std::string name;
RefPtr<std::atomic_bool> flag; std::shared_ptr<std::atomic_bool> flag;
friend class ThreadPool; friend class ThreadPool;
}; };
@@ -65,6 +66,13 @@ struct JobPromiseBase
id = globalCounter++; id = globalCounter++;
finishedEvent = Event(std::format("Job {}", id)); finishedEvent = Event(std::format("Job {}", id));
} }
~JobPromiseBase()
{
if (handle)
{
handle.destroy();
}
}
JobBase<MainJob> get_return_object() noexcept; JobBase<MainJob> get_return_object() noexcept;
inline auto initial_suspend() noexcept; inline auto initial_suspend() noexcept;
@@ -78,7 +86,6 @@ struct JobPromiseBase
void resume() void resume()
{ {
std::unique_lock lock(promiseLock);
if(!handle || handle.done() || executing()) if(!handle || handle.done() || executing())
{ {
return; return;
@@ -88,10 +95,9 @@ struct JobPromiseBase
} }
void setContinuation(JobPromiseBase* cont) void setContinuation(JobPromiseBase* cont)
{ {
std::unique_lock lock(promiseLock); std::scoped_lock lock(promiseLock, cont->promiseLock);
std::unique_lock lock2(cont->promiseLock);
continuation = cont->handle; continuation = cont->handle;
cont->precondition = finishedEvent; cont->state = State::SCHEDULED;
} }
bool done() bool done()
{ {
@@ -113,15 +119,15 @@ struct JobPromiseBase
{ {
return state == State::READY; return state == State::READY;
} }
void raise() void finalize()
{ {
std::unique_lock lock(promiseLock); std::scoped_lock lock(promiseLock);
state = State::DONE; state = State::DONE;
finishedEvent.raise(); finishedEvent.raise();
} }
void reset() void reset()
{ {
std::unique_lock lock(promiseLock); std::scoped_lock lock(promiseLock);
finishedEvent.reset(); finishedEvent.reset();
} }
void enqueue(Event& event) void enqueue(Event& event)
@@ -136,13 +142,12 @@ struct JobPromiseBase
} }
void schedule() void schedule()
{ {
std::unique_lock lock(promiseLock); std::scoped_lock lock(promiseLock);
if(!handle || done() || !ready()) if(!handle || done() || !ready())
{ {
return; return;
} }
state = (precondition == nullptr) ? State::SCHEDULED : State::WAITING; getGlobalThreadPool().scheduleJob(this);
getGlobalThreadPool().enqueueWaiting(precondition, this);
} }
std::mutex promiseLock; std::mutex promiseLock;
@@ -150,7 +155,6 @@ struct JobPromiseBase
std::coroutine_handle<> continuation = std::noop_coroutine(); std::coroutine_handle<> continuation = std::noop_coroutine();
uint64 id; uint64 id;
Event finishedEvent; Event finishedEvent;
Event precondition = nullptr;
State state = State::READY; State state = State::READY;
}; };
@@ -193,13 +197,9 @@ public:
{ {
return promise->done(); return promise->done();
} }
void raise() void finalize()
{ {
promise->raise(); promise->finalize();
}
void reset()
{
promise->reset();
} }
Event operator co_await() Event operator co_await()
{ {
@@ -245,30 +245,32 @@ using Promise = JobPromiseBase<false>;
class ThreadPool class ThreadPool
{ {
public: public:
ThreadPool(uint32 threadCount = std::thread::hardware_concurrency()); ThreadPool(uint32 threadCount = 1);
virtual ~ThreadPool(); 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); 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 enqueueWaiting(Event& event, MainPromise* job);
void scheduleJob(Promise* job);
void scheduleJob(MainPromise* job);
void notify(Event& event); void notify(Event& event);
void threadLoop(const bool isMainThread); void threadLoop(const bool isMainThread);
private: private:
std::atomic_bool running; std::atomic_bool running;
std::vector<std::thread> workers; std::vector<std::thread> workers;
List<MainPromise*> mainJobs; std::list<MainPromise*> mainJobs;
std::mutex mainJobLock; std::mutex mainJobLock;
std::condition_variable mainJobCV; std::condition_variable mainJobCV;
List<Promise*> jobQueue; std::list<Promise*> jobQueue;
std::mutex jobQueueLock; std::mutex jobQueueLock;
std::condition_variable jobQueueCV; std::condition_variable jobQueueCV;
std::map<Event, List<MainPromise*>> waitingMainJobs; std::map<Event, std::list<MainPromise*>> waitingMainJobs;
std::mutex waitingMainLock; std::mutex waitingMainLock;
std::map<Event, List<Promise*>> waitingJobs; std::map<Event, std::list<Promise*>> waitingJobs;
std::mutex waitingLock; std::mutex waitingLock;
}; };
@@ -283,6 +285,7 @@ inline auto JobPromiseBase<MainJob>::initial_suspend() noexcept
{ {
return std::suspend_always{}; return std::suspend_always{};
} }
template<bool MainJob> template<bool MainJob>
inline auto JobPromiseBase<MainJob>::final_suspend() const noexcept inline auto JobPromiseBase<MainJob>::final_suspend() const noexcept
{ {
+2
View File
@@ -5,6 +5,8 @@ using namespace Seele;
using namespace Seele::UI; using namespace Seele::UI;
Element::Element() Element::Element()
: dirty(false)
, enabled(false)
{ {
} }
+4 -4
View File
@@ -31,7 +31,7 @@ RenderHierarchy::~RenderHierarchy()
void RenderHierarchy::addElement(PElement addedElement) void RenderHierarchy::addElement(PElement addedElement)
{ {
std::unique_lock lock(updateLock); std::scoped_lock lock(updateLock);
updates.add(new AddElementRenderHierarchyUpdate{ updates.add(new AddElementRenderHierarchyUpdate{
addedElement.getHandle(), addedElement.getHandle(),
addedElement->getParent().getHandle() addedElement->getParent().getHandle()
@@ -40,7 +40,7 @@ void RenderHierarchy::addElement(PElement addedElement)
void RenderHierarchy::removeElement(PElement elementToRemove) void RenderHierarchy::removeElement(PElement elementToRemove)
{ {
std::unique_lock lock(updateLock); std::scoped_lock lock(updateLock);
updates.add(new RemoveElementRenderHierarchyUpdate{ updates.add(new RemoveElementRenderHierarchyUpdate{
elementToRemove.getHandle(), elementToRemove.getHandle(),
}); });
@@ -48,7 +48,7 @@ void RenderHierarchy::removeElement(PElement elementToRemove)
void RenderHierarchy::moveElement(PElement elementToMove, PElement newParent) void RenderHierarchy::moveElement(PElement elementToMove, PElement newParent)
{ {
std::unique_lock lock(updateLock); std::scoped_lock lock(updateLock);
updates.add(new AddElementRenderHierarchyUpdate{ updates.add(new AddElementRenderHierarchyUpdate{
elementToMove.getHandle(), elementToMove.getHandle(),
newParent.getHandle() newParent.getHandle()
@@ -62,7 +62,7 @@ void RenderHierarchy::updateHierarchy()
{ {
List<RenderHierarchyUpdate*> localUpdates; List<RenderHierarchyUpdate*> localUpdates;
{ // make a local copy of the updates so we dont hold the lock for too long { // 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; localUpdates = updates;
updates.clear(); 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() void InspectorView::commitUpdate()
+2 -2
View File
@@ -13,8 +13,8 @@ public:
InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo); InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo);
virtual ~InspectorView(); virtual ~InspectorView();
virtual void beginUpdate() override; virtual Job beginUpdate() override;
virtual void update() override; virtual Job update() override;
virtual void commitUpdate() override; virtual void commitUpdate() override;
virtual void prepareRender() override; virtual void prepareRender() override;
+21 -11
View File
@@ -6,6 +6,8 @@
#include "Asset/AssetRegistry.h" #include "Asset/AssetRegistry.h"
#include "Scene/Actor/CameraActor.h" #include "Scene/Actor/CameraActor.h"
#include "Scene/Components/CameraComponent.h" #include "Scene/Components/CameraComponent.h"
#include "Scene/Components/MyComponent.h"
#include "Scene/Components/MyOtherComponent.h"
using namespace Seele; using namespace Seele;
@@ -28,18 +30,23 @@ 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\\Ely\\Ely.fbx");
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Cube\\cube.obj"); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Cube\\cube.obj");
AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Plane\\plane.fbx"); 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(0, 0, 0));
PPrimitiveComponent ayaka = new PrimitiveComponent(AssetRegistry::findMesh("Ayaka")); ayaka->setWorldScale(Vector(10, 10, 10));
ayaka->addWorldTranslation(Vector(((float)rand() / RAND_MAX) * 100, 0, ((float)rand()/RAND_MAX) * 100)); scene->addPrimitiveComponent(ayaka);
ayaka->setWorldScale(Vector(10, 10, 10));
scene->addPrimitiveComponent(ayaka);
}
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));
scene->addPrimitiveComponent(plane); 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(); PRenderGraphResources resources = new RenderGraphResources();
depthPrepass.setResources(resources); depthPrepass.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() void SceneView::commitUpdate()
+2 -2
View File
@@ -13,8 +13,8 @@ class SceneView : public View
public: public:
SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo); SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo);
~SceneView(); ~SceneView();
virtual void beginUpdate() override; virtual Job beginUpdate() override;
virtual void update() override; virtual Job update() override;
virtual void commitUpdate() override; virtual void commitUpdate() override;
virtual void prepareRender() override; virtual void prepareRender() override;
+2 -2
View File
@@ -13,8 +13,8 @@ public:
virtual ~View(); virtual ~View();
// These are called from the view thread, and handle updating game data // These are called from the view thread, and handle updating game data
virtual void beginUpdate() = 0; virtual Job beginUpdate() = 0;
virtual void update() = 0; virtual Job update() = 0;
// End frame is called with a lock, so it is safe to write to shared memory // End frame is called with a lock, so it is safe to write to shared memory
virtual void commitUpdate() = 0; virtual void commitUpdate() = 0;
+2 -2
View File
@@ -32,7 +32,7 @@ MainJob Window::render()
co_await windowView->updateFinished; co_await windowView->updateFinished;
windowView->updateFinished.reset(); windowView->updateFinished.reset();
{ {
std::unique_lock lock(windowView->workerMutex); std::scoped_lock lock(windowView->workerMutex);
windowView->view->prepareRender(); windowView->view->prepareRender();
} }
windowView->view->render(); windowView->view->render();
@@ -78,7 +78,7 @@ Job Window::viewWorker(size_t viewIndex)
windowView->view->beginUpdate(); windowView->view->beginUpdate();
windowView->view->update(); windowView->view->update();
{ {
std::unique_lock lock(windowView->workerMutex); std::scoped_lock lock(windowView->workerMutex);
windowView->view->commitUpdate(); windowView->view->commitUpdate();
} }
//std::cout << "Update completed" << std::endl; //std::cout << "Update completed" << std::endl;
+1 -1
View File
@@ -41,7 +41,7 @@ void WindowManager::notifyWindowClosed(PWindow window)
windows.remove(windows.find(window)); windows.remove(windows.find(window));
if(windows.empty()) if(windows.empty())
{ {
std::unique_lock lock(windowsLock); std::scoped_lock lock(windowsLock);
windowsCV.notify_all(); windowsCV.notify_all();
} }
} }
+135 -96
View File
@@ -12,131 +12,170 @@ BOOST_AUTO_TEST_SUITE(Array_Suite)
BOOST_AUTO_TEST_CASE(empty_constructur) BOOST_AUTO_TEST_CASE(empty_constructur)
{ {
Array<uint8> array; Array<uint8> array;
BOOST_CHECK_EQUAL(array.size(), 0); BOOST_CHECK_EQUAL(array.size(), 0);
} }
BOOST_AUTO_TEST_CASE(initialial_size) BOOST_AUTO_TEST_CASE(initialial_size)
{ {
Array<uint8> array(3); Array<uint8> array(3);
BOOST_CHECK_EQUAL(array.size(), 3); BOOST_CHECK_EQUAL(array.size(), 3);
} }
BOOST_AUTO_TEST_CASE(resize) BOOST_AUTO_TEST_CASE(resize)
{ {
Array<uint8> array; Array<uint8> array;
array.add(2); array.add(2);
array.add(3); array.add(3);
BOOST_CHECK_EQUAL(array.size(), 2); BOOST_CHECK_EQUAL(array.size(), 2);
array.resize(5); array.resize(5);
BOOST_CHECK_EQUAL(array.size(), 5); BOOST_CHECK_EQUAL(array.size(), 5);
} }
BOOST_AUTO_TEST_CASE(clear) BOOST_AUTO_TEST_CASE(clear)
{ {
Array<uint8> array; Array<uint8> array;
array.add(3); array.add(3);
array.add(2); array.add(2);
array.add(6); array.add(6);
BOOST_CHECK_EQUAL(array.size(), 3); BOOST_CHECK_EQUAL(array.size(), 3);
array.clear(); array.clear();
BOOST_CHECK_EQUAL(array.size(), 0); BOOST_CHECK_EQUAL(array.size(), 0);
array.add(2);
} }
BOOST_AUTO_TEST_CASE(remove_keeporder) BOOST_AUTO_TEST_CASE(remove_keeporder)
{ {
Array<uint8> array; Array<uint8> array;
array.add(1); array.add(1);
array.add(2); array.add(2);
array.add(3); array.add(3);
array.add(4); array.add(4);
array.add(5); array.add(5);
array.remove(1); array.remove(1);
BOOST_CHECK_EQUAL(array[1], 3); BOOST_CHECK_EQUAL(array[1], 3);
BOOST_CHECK_EQUAL(array[2], 4); BOOST_CHECK_EQUAL(array[2], 4);
BOOST_CHECK_EQUAL(array[3], 5); BOOST_CHECK_EQUAL(array[3], 5);
BOOST_CHECK_EQUAL(array.size(), 4); BOOST_CHECK_EQUAL(array.size(), 4);
} }
BOOST_AUTO_TEST_CASE(remove_swap) BOOST_AUTO_TEST_CASE(remove_swap)
{ {
Array<uint8> array; Array<uint8> array;
array.add(1); array.add(1);
array.add(2); array.add(2);
array.add(3); array.add(3);
array.add(4); array.add(4);
array.add(5); array.add(5);
array.remove(1, false); array.remove(1, false);
BOOST_CHECK_EQUAL(array[1], 5); BOOST_CHECK_EQUAL(array[1], 5);
BOOST_CHECK_EQUAL(array[2], 3); BOOST_CHECK_EQUAL(array[2], 3);
BOOST_CHECK_EQUAL(array[3], 4); BOOST_CHECK_EQUAL(array[3], 4);
BOOST_CHECK_EQUAL(array.size(), 4); BOOST_CHECK_EQUAL(array.size(), 4);
} }
BOOST_AUTO_TEST_CASE(remove_iterator) BOOST_AUTO_TEST_CASE(remove_iterator)
{ {
Array<uint8> array; Array<uint8> array;
array.add(1); array.add(1);
array.add(2); array.add(2);
array.add(3); array.add(3);
array.add(4); array.add(4);
array.add(5); array.add(5);
array.remove(array.find(1), false); array.remove(array.find(1), false);
BOOST_CHECK_EQUAL(array[0], 5); BOOST_CHECK_EQUAL(array[0], 5);
BOOST_CHECK_EQUAL(array[1], 2); BOOST_CHECK_EQUAL(array[1], 2);
BOOST_CHECK_EQUAL(array[2], 3); BOOST_CHECK_EQUAL(array[2], 3);
BOOST_CHECK_EQUAL(array[3], 4); BOOST_CHECK_EQUAL(array[3], 4);
BOOST_CHECK_EQUAL(array.size(), 4); BOOST_CHECK_EQUAL(array.size(), 4);
} }
BOOST_AUTO_TEST_CASE(remove_iterator_keep_order) BOOST_AUTO_TEST_CASE(remove_iterator_keep_order)
{ {
Array<uint8> array; Array<uint8> array;
array.add(1); array.add(1);
array.add(2); array.add(2);
array.add(3); array.add(3);
array.add(4); array.add(4);
array.add(5); array.add(5);
array.remove(array.find(1)); array.remove(array.find(1));
BOOST_CHECK_EQUAL(array[0], 2); BOOST_CHECK_EQUAL(array[0], 2);
BOOST_CHECK_EQUAL(array[1], 3); BOOST_CHECK_EQUAL(array[1], 3);
BOOST_CHECK_EQUAL(array[2], 4); BOOST_CHECK_EQUAL(array[2], 4);
BOOST_CHECK_EQUAL(array[3], 5); BOOST_CHECK_EQUAL(array[3], 5);
BOOST_CHECK_EQUAL(array.size(), 4); BOOST_CHECK_EQUAL(array.size(), 4);
} }
BOOST_AUTO_TEST_CASE(random_access) BOOST_AUTO_TEST_CASE(random_access)
{ {
Array<uint8> array; Array<uint8> array;
array.add(4); array.add(4);
array.add(5); array.add(5);
array.add(6); array.add(6);
BOOST_CHECK_EQUAL(array[2], 6); BOOST_CHECK_EQUAL(array[2], 6);
BOOST_CHECK_EQUAL(array[0], 4); 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 class TestStruct
{ {
public: public:
uint32 data; uint32 data;
~TestStruct() ~TestStruct()
{ {
data = 1; data = 1;
} }
}; };
DECLARE_REF(TestStruct); DECLARE_REF(TestStruct);
BOOST_AUTO_TEST_CASE(refptr_interaction) BOOST_AUTO_TEST_CASE(refptr_interaction)
{ {
uint32* dataPtr; uint32* dataPtr;
{ {
PTestStruct test = new TestStruct(); PTestStruct test = new TestStruct();
test->data = 32123; test->data = 32123;
dataPtr = &test->data; dataPtr = &test->data;
{ {
Array<PTestStruct> arr(1); Array<PTestStruct> arr(1);
arr[0] = test; arr[0] = test;
} }
BOOST_CHECK_EQUAL(test->data, 32123); BOOST_CHECK_EQUAL(test->data, 32123);
} }
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
@@ -146,25 +185,25 @@ BOOST_AUTO_TEST_SUITE(StaticArray_Suite)
BOOST_AUTO_TEST_CASE(empty_constructur) BOOST_AUTO_TEST_CASE(empty_constructur)
{ {
StaticArray<uint8, 2> array; StaticArray<uint8, 2> array;
BOOST_CHECK_EQUAL(array.size(), 2); BOOST_CHECK_EQUAL(array.size(), 2);
} }
BOOST_AUTO_TEST_CASE(initialial_size) BOOST_AUTO_TEST_CASE(initialial_size)
{ {
StaticArray<uint8, 3> array(3); StaticArray<uint8, 3> array(3);
BOOST_CHECK_EQUAL(array.size(), 3); BOOST_CHECK_EQUAL(array.size(), 3);
BOOST_CHECK_EQUAL(array[1], 3); BOOST_CHECK_EQUAL(array[1], 3);
} }
BOOST_AUTO_TEST_CASE(random_access) BOOST_AUTO_TEST_CASE(random_access)
{ {
StaticArray<uint8, 3> array; StaticArray<uint8, 3> array;
array[0] = 4; array[0] = 4;
array[1] = 5; array[1] = 5;
array[2] = 6; array[2] = 6;
BOOST_CHECK_EQUAL(array[0], 4); BOOST_CHECK_EQUAL(array[0], 4);
BOOST_CHECK_EQUAL(array[2], 6); BOOST_CHECK_EQUAL(array[2], 6);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
+3
View File
@@ -1,4 +1,6 @@
#pragma once #pragma once
#include <vld.h>
#include "ThreadPool.h"
namespace Seele namespace Seele
{ {
@@ -6,6 +8,7 @@ namespace Seele
{ {
GlobalFixture() GlobalFixture()
{ {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
} }
~GlobalFixture() ~GlobalFixture()
{ {
+10 -5
View File
@@ -23,13 +23,18 @@ Job basicThenThird()
co_return; co_return;
} }
BOOST_AUTO_TEST_CASE(basic_then) Job basicThenBase()
{ {
basicThenFirst() co_await basicThenFirst();
.then(basicThenSecond()) co_await basicThenSecond();
.then(basicThenThird()); co_await basicThenThird();
} }
BOOST_AUTO_TEST_CASE(basic_then)
{
basicThenBase();
}
/*
uint64 basicAllState1 = 0; uint64 basicAllState1 = 0;
uint64 basicAllState2 = 0; uint64 basicAllState2 = 0;
Job basicAllFirst() Job basicAllFirst()
@@ -69,6 +74,6 @@ BOOST_AUTO_TEST_CASE(basic_callable)
BOOST_REQUIRE_EQUAL(basicCallable, 10); BOOST_REQUIRE_EQUAL(basicCallable, 10);
co_return; co_return;
}); });
} }*/
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()