diff --git a/.vscode/launch.json b/.vscode/launch.json index edebfa5..ad270ca 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -77,7 +77,7 @@ "type": "cppvsdbg", "request": "launch", "program": "${workspaceRoot}/bin/Debug/Seele_unit_tests.exe", - "args": [], + "args": ["--detect_memory_leaks=15533"], "stopAtEntry": false, "console": "internalConsole", "cwd": "${workspaceRoot}/bin/Debug", diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a8921d..2cbbe02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,7 @@ add_subdirectory(src/) if(MSVC) set(_CRT_SECURE_NO_WARNINGS) - target_compile_options(SeeleEngine PRIVATE /DEBUG:FASTLINK /Zi) + target_compile_options(SeeleEngine PRIVATE /Zi) else() target_compile_options(SeeleEngine PRIVATE -g -Wall -Wextra -Wno-delete-incomplete -pedantic -fcoroutines) endif() diff --git a/CMakeSettings.json b/CMakeSettings.json index 85715ee..78e54b1 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -5,7 +5,7 @@ "cmakeCommandArgs": "-DUSE_SUPERBUILD=OFF", "buildCommandArgs": "", "ctestCommandArgs": "", - "variables": [] + "inheritEnvironments": [] } ] } \ No newline at end of file diff --git a/res/textures/Logo.png b/res/textures/Logo.png new file mode 100644 index 0000000..d127357 Binary files /dev/null and b/res/textures/Logo.png differ diff --git a/src/Engine/Asset/Asset.cpp b/src/Engine/Asset/Asset.cpp index 234aaa4..9ae4201 100644 --- a/src/Engine/Asset/Asset.cpp +++ b/src/Engine/Asset/Asset.cpp @@ -9,6 +9,7 @@ Asset::Asset() , parentDir("") , extension("") , status(Status::Uninitialized) + , byteSize(0) { } Asset::Asset(const std::filesystem::path& path) diff --git a/src/Engine/Asset/Asset.h b/src/Engine/Asset/Asset.h index b748f21..5fa86bb 100644 --- a/src/Engine/Asset/Asset.h +++ b/src/Engine/Asset/Asset.h @@ -28,12 +28,12 @@ public: std::string getExtension() const; inline Status getStatus() { - std::unique_lock lck(lock); + std::scoped_lock lck(lock); return status; } inline void setStatus(Status status) { - std::unique_lock lck(lock); + std::scoped_lock lck(lock); this->status = status; } protected: diff --git a/src/Engine/Asset/MeshAsset.cpp b/src/Engine/Asset/MeshAsset.cpp index 319a5ff..39e4567 100644 --- a/src/Engine/Asset/MeshAsset.cpp +++ b/src/Engine/Asset/MeshAsset.cpp @@ -25,24 +25,20 @@ MeshAsset::~MeshAsset() } void MeshAsset::save() { - boost::archive::text_oarchive archive(getWriteStream()); - archive << meshes; } void MeshAsset::load() { - boost::archive::text_iarchive archive(getReadStream()); - archive >> meshes; } void MeshAsset::addMesh(PMesh mesh) { - std::unique_lock lck(lock); - meshes.add(mesh); - referencedMaterials.add(mesh->referencedMaterial); + std::scoped_lock lck(lock); + meshes.push_back(mesh); + referencedMaterials.push_back(mesh->referencedMaterial); } -const Array MeshAsset::getMeshes() +const std::vector MeshAsset::getMeshes() { - std::unique_lock lck(lock); + std::scoped_lock lck(lock); return meshes; } \ No newline at end of file diff --git a/src/Engine/Asset/MeshAsset.h b/src/Engine/Asset/MeshAsset.h index 3af4fcf..39e8033 100644 --- a/src/Engine/Asset/MeshAsset.h +++ b/src/Engine/Asset/MeshAsset.h @@ -15,11 +15,11 @@ public: virtual void save() override; virtual void load() override; void addMesh(PMesh mesh); - const Array getMeshes(); + const std::vector getMeshes(); //Workaround while no editor - Array referencedMaterials; + std::vector referencedMaterials; private: - Array meshes; + std::vector meshes; }; DEFINE_REF(MeshAsset) } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Asset/MeshLoader.cpp b/src/Engine/Asset/MeshLoader.cpp index e97b2ae..4718027 100644 --- a/src/Engine/Asset/MeshLoader.cpp +++ b/src/Engine/Asset/MeshLoader.cpp @@ -122,7 +122,9 @@ VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gf vbInfo.resourceData.data = (uint8 *)buffer.data(); vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; vbInfo.resourceData.size = sizeof(Vector) * (uint32)buffer.size(); - return VertexStreamComponent(graphics->createVertexBuffer(vbInfo), 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT); + Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo); + vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS); + return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT); } VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics) { @@ -137,7 +139,9 @@ VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gf vbInfo.resourceData.data = (uint8 *)buffer.data(); vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; vbInfo.resourceData.size = sizeof(Vector2) * (uint32)buffer.size(); - return VertexStreamComponent(graphics->createVertexBuffer(vbInfo), 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT); + Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo); + vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS); + return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT); } void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array& globalMeshes, const Array& materials, Gfx::PGraphics graphics) { diff --git a/src/Engine/Asset/TextureAsset.h b/src/Engine/Asset/TextureAsset.h index 7afd679..7e1a0b2 100644 --- a/src/Engine/Asset/TextureAsset.h +++ b/src/Engine/Asset/TextureAsset.h @@ -14,12 +14,12 @@ public: virtual void load() override; void setTexture(Gfx::PTexture texture) { - std::unique_lock lck(lock); + std::scoped_lock lck(lock); this->texture = texture; } Gfx::PTexture getTexture() { - std::unique_lock lck(lock); + std::scoped_lock lck(lock); return texture; } private: diff --git a/src/Engine/Containers/Array.h b/src/Engine/Containers/Array.h index c91c52d..1afc34d 100644 --- a/src/Engine/Containers/Array.h +++ b/src/Engine/Containers/Array.h @@ -12,667 +12,670 @@ namespace Seele { - template > - struct Array +template > +struct Array +{ +public: + template + class IteratorBase { public: - template - class IteratorBase - { - public: - using iterator_category = std::random_access_iterator_tag; - using value_type = X; - using difference_type = std::ptrdiff_t; - using reference = X&; - using pointer = X*; - - IteratorBase(X *x = nullptr) - : p(x) - { - } - reference operator*() const - { - return *p; - } - pointer operator->() const - { - return p; - } - inline bool operator!=(const IteratorBase &other) const - { - return p != other.p; - } - inline bool operator==(const IteratorBase &other) const - { - return p == other.p; - } - inline int operator-(const IteratorBase &other) const - { - return (int)(p - other.p); - } - IteratorBase &operator++() - { - p++; - return *this; - } - IteratorBase &operator--() - { - p--; - return *this; - } - IteratorBase operator++(int) - { - IteratorBase tmp(*this); - ++*this; - return tmp; - } - IteratorBase operator--(int) - { - IteratorBase tmp(*this); - --*this; - return tmp; - } - - private: - X *p; - }; - - using value_type = T; - using allocator_type = Allocator; - using size_type = std::size_t; + using iterator_category = std::random_access_iterator_tag; + using value_type = X; using difference_type = std::ptrdiff_t; - using pointer = T*; - using const_pointer = const T*; - using reference = value_type&; - using const_reference = const value_type&; + using reference = X&; + using pointer = X*; - using Iterator = IteratorBase; - using ConstIterator = IteratorBase; - using iterator = Iterator; - using const_iterator = ConstIterator; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - constexpr Array() noexcept(noexcept(Allocator())) - : arraySize(0) - , allocated(DEFAULT_ALLOC_SIZE) - , allocator(Allocator()) + IteratorBase(X *x = nullptr) + : p(x) { - _data = allocateArray(DEFAULT_ALLOC_SIZE); - assert(_data != nullptr); - markIteratorDirty(); + } + reference operator*() const + { + return *p; + } + pointer operator->() const + { + return p; + } + inline bool operator!=(const IteratorBase &other) const + { + return p != other.p; + } + inline bool operator==(const IteratorBase &other) const + { + return p == other.p; + } + inline int operator-(const IteratorBase &other) const + { + return (int)(p - other.p); + } + IteratorBase &operator++() + { + p++; + return *this; + } + IteratorBase &operator--() + { + p--; + return *this; + } + IteratorBase operator++(int) + { + IteratorBase tmp(*this); + ++*this; + return tmp; + } + IteratorBase operator--(int) + { + IteratorBase tmp(*this); + --*this; + return tmp; } - constexpr explicit Array(const allocator_type& alloc) - : arraySize(0) - , allocated(DEFAULT_ALLOC_SIZE) - , allocator(alloc) + private: + X *p; + }; + + using value_type = T; + using allocator_type = Allocator; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using const_pointer = const T*; + using reference = value_type&; + using const_reference = const value_type&; + + using Iterator = IteratorBase; + using ConstIterator = IteratorBase; + using iterator = Iterator; + using const_iterator = ConstIterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + constexpr Array() noexcept(noexcept(Allocator())) + : arraySize(0) + , allocated(DEFAULT_ALLOC_SIZE) + , allocator(Allocator()) + { + _data = allocateArray(DEFAULT_ALLOC_SIZE); + assert(_data != nullptr); + markIteratorDirty(); + } + + constexpr explicit Array(const allocator_type& alloc) + : arraySize(0) + , allocated(DEFAULT_ALLOC_SIZE) + , allocator(alloc) + { + _data = allocateArray(DEFAULT_ALLOC_SIZE); + assert(_data != nullptr); + markIteratorDirty(); + } + constexpr Array(size_type size, const value_type& value, const allocator_type& alloc = allocator_type()) + : arraySize(size) + , allocated(size) + , allocator(alloc) + { + _data = allocateArray(size); + assert(_data != nullptr); + for (size_type i = 0; i < size; ++i) { - _data = allocateArray(DEFAULT_ALLOC_SIZE); - assert(_data != nullptr); - markIteratorDirty(); + _data[i] = value; } - constexpr Array(size_type size, const value_type& value, const allocator_type& alloc = allocator_type()) - : arraySize(size) - , allocated(size) - , allocator(alloc) + markIteratorDirty(); + } + constexpr explicit Array(size_type size, const allocator_type& alloc = allocator_type()) + : arraySize(size) + , allocated(size) + , allocator(alloc) + { + _data = allocateArray(size); + assert(_data != nullptr); + for (size_type i = 0; i < size; ++i) { - _data = allocateArray(size); - for (size_type i = 0; i < size; ++i) + std::allocator_traits::construct(allocator, &_data[i]); + } + markIteratorDirty(); + } + constexpr Array(std::initializer_list init, const allocator_type& alloc = allocator_type()) + : arraySize(init.size()) + , allocated(init.size()) + , allocator(alloc) + { + _data = allocateArray(init.size()); + assert(_data != nullptr); + markIteratorDirty(); + std::uninitialized_copy(init.begin(), init.end(), begin()); + } + Array(const Array &other) + : arraySize(other.arraySize) + , allocated(other.allocated) + , allocator(std::allocator_traits::select_on_container_copy_construction(other.allocator)) + { + _data = allocateArray(other.allocated); + assert(_data != nullptr); + markIteratorDirty(); + std::uninitialized_copy(other.begin(), other.end(), begin()); + } + Array(Array &&other) noexcept + : arraySize(std::move(other.arraySize)) + , allocated(std::move(other.allocated)) + , allocator(std::move(other.allocator)) + { + _data = other._data; + other._data = nullptr; + other.allocated = 0; + other.arraySize = 0; + markIteratorDirty(); + } + Array &operator=(const Array &other) noexcept + { + if (this != &other) + { + if constexpr (std::allocator_traits::propagate_on_container_copy_assignment::value ) { - _data[i] = value; + if (!std::allocator_traits::is_always_equal::value + && allocator != other.allocator) + { + clear(); + } + allocator = other.allocator; } - markIteratorDirty(); - } - constexpr explicit Array(size_type size, const allocator_type& alloc = allocator_type()) - : arraySize(size) - , allocated(size) - , allocator(alloc) - { - _data = allocateArray(size); - for (size_type i = 0; i < size; ++i) + if (other.arraySize > allocated) { - std::allocator_traits::construct(allocator, &_data[i]); + clear(); } - markIteratorDirty(); - } - constexpr Array(std::initializer_list init, const allocator_type& alloc = allocator_type()) - : arraySize(init.size()) - , allocated(init.size()) - , allocator(alloc) - { - _data = allocateArray(init.size()); - markIteratorDirty(); - std::uninitialized_copy(init.begin(), init.end(), begin()); - } - Array(const Array &other) - : arraySize(other.arraySize) - , allocated(other.allocated) - , allocator(std::allocator_traits::select_on_container_copy_construction(other.allocator)) - { - _data = allocateArray(other.allocated); + if(_data == nullptr) + { + _data = allocateArray(other.allocated); + allocated = other.allocated; + } + arraySize = other.arraySize; markIteratorDirty(); std::uninitialized_copy(other.begin(), other.end(), begin()); } - Array(Array &&other) noexcept - : arraySize(std::move(other.arraySize)) - , allocated(std::move(other.allocated)) - , allocator(std::move(other.allocator)) + return *this; + } + Array &operator=(Array &&other) noexcept + { + if (this != &other) { + if constexpr (std::allocator_traits::propagate_on_container_move_assignment::value) + { + allocator = std::move(other.allocator); + } + if (_data != nullptr) + { + clear(); + } + allocated = std::move(other.allocated); + arraySize = std::move(other.arraySize); _data = other._data; other._data = nullptr; - other.allocated = 0; - other.arraySize = 0; markIteratorDirty(); } - Array &operator=(const Array &other) noexcept + return *this; + } + ~Array() + { + clear(); + } + + constexpr bool operator==(const Array &other) + { + return _data == other._data; + } + + constexpr bool operator!=(const Array &other) + { + return !(*this == other); + } + + constexpr iterator find(const value_type &item) + { + for (uint32 i = 0; i < arraySize; ++i) { - if (this != &other) + if (_data[i] == item) { - if constexpr (std::allocator_traits::propagate_on_container_copy_assignment::value ) - { - if (!std::allocator_traits::is_always_equal::value - && allocator != other.allocator) - { - deallocateArray(_data, allocated); - _data = nullptr; - } - allocator = other.allocator; - } - if(_data == nullptr || other.arraySize > allocated) - { - if(_data != nullptr) - { - deallocateArray(_data, allocated); - } - _data = allocateArray(other.allocated); - allocated = other.allocated; - } - arraySize = other.arraySize; - markIteratorDirty(); - std::uninitialized_copy(other.begin(), other.end(), begin()); + return iterator(&_data[i]); } - return *this; } - Array &operator=(Array &&other) noexcept + return endIt; + } + constexpr iterator find(value_type&& item) + { + for (uint32 i = 0; i < arraySize; ++i) { - if (this != &other) + if (_data[i] == item) { - if constexpr (std::allocator_traits::propagate_on_container_move_assignment::value) - { - if (!std::allocator_traits::is_always_equal::value - && allocator != other.allocator) - { - deallocateArray(_data, allocated); - _data = nullptr; - } - allocator = std::move(other.allocator); - } - if (_data != nullptr) - { - deallocateArray(_data, allocated); - _data = nullptr; - } - allocated = std::move(other.allocated); - arraySize = std::move(other.arraySize); - _data = other._data; - other._data = nullptr; - markIteratorDirty(); + return iterator(&_data[i]); } - return *this; } - ~Array() + return endIt; + } + constexpr allocator_type get_allocator() const + { + return allocator; + } + constexpr iterator begin() const + { + return beginIt; + } + constexpr iterator end() const + { + return endIt; + } + constexpr const_iterator cbegin() const + { + return beginIt; + } + constexpr const_iterator cend() const + { + return endIt; + } + constexpr reference add(const value_type &item = value_type()) + { + return addInternal(item); + } + constexpr reference add(value_type&& item) + { + return addInternal(std::forward(item)); + } + constexpr void addAll(Array other) + { + for(auto value : other) { - clear(); + addInternal(value); + } + } + constexpr reference addUnique(const value_type &item = value_type()) + { + iterator it; + if((it = std::move(find(item))) != endIt) + { + return *it; + } + return addInternal(item); + } + template + constexpr reference emplace(args... arguments) + { + if (arraySize == allocated) + { + size_type newSize = arraySize + 1; + allocated = calculateGrowth(newSize); + T *tempArray = allocateArray(allocated); + assert(tempArray != nullptr); + + std::uninitialized_move(begin(), end(), Iterator(tempArray)); + deallocateArray(_data, arraySize); + _data = tempArray; + } + std::allocator_traits::construct(allocator, &_data[arraySize++], arguments...); + markIteratorDirty(); + return _data[arraySize - 1]; + } + constexpr void remove(iterator it, bool keepOrder = true) + { + remove(it - beginIt, keepOrder); + } + constexpr void remove(int index, bool keepOrder = true) + { + if (keepOrder) + { + for(uint32 i = index; i < arraySize-1; ++i) + { + _data[i] = std::move(_data[i+1]); + } + } + else + { + _data[index] = std::move(_data[arraySize - 1]); + } + arraySize--; + markIteratorDirty(); + } + constexpr void resize(size_type newSize) + { + resizeInternal(newSize, std::move(T())); + } + constexpr void resize(size_type newSize, const value_type& value) + { + resizeInternal(newSize, value); + } + constexpr void clear() + { + if(_data == nullptr) + { + return; + } + for(size_type i = 0; i < arraySize; ++i) + { + std::allocator_traits::destroy(allocator, &_data[i]); + } + deallocateArray(_data, allocated); + _data = nullptr; + arraySize = 0; + allocated = 0; + markIteratorDirty(); + } + inline size_type indexOf(iterator iterator) + { + return iterator - beginIt; + } + inline size_type indexOf(const_iterator iterator) const + { + return iterator.p - beginIt.p; + } + inline size_type indexOf(T& t) + { + return indexOf(find(t)); + } + inline size_type indexOf(const T& t) const + { + return indexOf(find(t)); + } + inline size_type size() const + { + return arraySize; + } + inline size_type empty() const + { + return arraySize == 0; + } + inline size_type capacity() const + { + return allocated; + } + inline pointer data() const + { + return _data; + } + inline reference front() const + { + assert(arraySize > 0); + return _data[0]; + } + inline reference back() const + { + assert(arraySize > 0); + return _data[arraySize - 1]; + } + void pop() + { + std::allocator_traits::destroy(allocator, &_data[--arraySize]); + markIteratorDirty(); + } + constexpr inline reference operator[](size_type index) + { + assert(index < arraySize); + return _data[index]; + } + constexpr inline const reference operator[](size_type index) const + { + assert(index < arraySize); + return _data[index]; + } +private: + size_type calculateGrowth(size_type newSize) const + { + const size_type oldCapacity = capacity(); + + if (oldCapacity > SIZE_MAX - oldCapacity) + { + return newSize; // geometric growth would overflow } - constexpr bool operator==(const Array &other) + const size_type geometric = oldCapacity + oldCapacity; + + if (geometric < newSize) { - return _data == other._data; + return newSize; // geometric growth would be insufficient } - constexpr bool operator!=(const Array &other) + return geometric; // geometric growth is sufficient + } + void markIteratorDirty() + { + beginIt = Iterator(_data); + endIt = Iterator(_data + arraySize); + } + T* allocateArray(size_type size) + { + T* result = allocator.allocate(size); + assert(result != nullptr); + return result; + } + void deallocateArray(T* ptr, size_type size) + { + allocator.deallocate(ptr, size); + } + template + T& addInternal(Type&& t) + { + if (arraySize == allocated) { - return !(*this == other); - } - - constexpr iterator find(const value_type &item) - { - for (uint32 i = 0; i < arraySize; ++i) + size_type newSize = arraySize + 1; + allocated = calculateGrowth(newSize); + T *tempArray = allocateArray(allocated); + for (size_type i = 0; i < arraySize; ++i) { - if (_data[i] == item) + std::allocator_traits::construct(allocator, &tempArray[i], std::forward(_data[i])); + } + deallocateArray(_data, arraySize); + _data = tempArray; + } + std::allocator_traits::construct(allocator, &_data[arraySize++], std::forward(t)); + markIteratorDirty(); + return _data[arraySize - 1]; + } + template + void resizeInternal(size_type newSize, Type&& value) + { + if (newSize <= allocated) + { + // The array is already big enough + if(newSize < arraySize) + { + // But since we are sizing down we destruct some of them + for(size_type i = newSize; i < arraySize; ++i) { - return iterator(&_data[i]); - } - } - return endIt; - } - constexpr iterator find(value_type&& item) - { - for (uint32 i = 0; i < arraySize; ++i) - { - if (_data[i] == item) - { - return iterator(&_data[i]); - } - } - return endIt; - } - constexpr allocator_type get_allocator() const - { - return allocator; - } - constexpr iterator begin() const - { - return beginIt; - } - constexpr iterator end() const - { - return endIt; - } - constexpr const_iterator cbegin() const - { - return beginIt; - } - constexpr const_iterator cend() const - { - return endIt; - } - constexpr reference add(const value_type &item = value_type()) - { - return addInternal(item); - } - constexpr reference add(value_type&& item) - { - return addInternal(std::forward(item)); - } - constexpr reference addUnique(const value_type &item = value_type()) - { - iterator it; - if((it = std::move(find(item))) != endIt) - { - return *it; - } - return addInternal(item); - } - template - constexpr reference emplace(args... arguments) - { - if (arraySize == allocated) - { - size_type newSize = arraySize + 1; - allocated = calculateGrowth(newSize); - T *tempArray = allocateArray(allocated); - assert(tempArray != nullptr); - - std::uninitialized_move(begin(), end(), Iterator(tempArray)); - deallocateArray(_data, arraySize); - _data = tempArray; - } - std::allocator_traits::construct(allocator, &_data[arraySize++], arguments...); - markIteratorDirty(); - return _data[arraySize - 1]; - } - constexpr void remove(iterator it, bool keepOrder = true) - { - remove(it - beginIt, keepOrder); - } - constexpr void remove(int index, bool keepOrder = true) - { - if (keepOrder) - { - for(uint32 i = index; i < arraySize-1; ++i) - { - _data[i] = std::move(_data[i+1]); + std::allocator_traits::destroy(allocator, &_data[i]); } } else { - _data[index] = std::move(_data[arraySize - 1]); - } - arraySize--; - markIteratorDirty(); - } - constexpr void resize(size_type newSize) - { - resizeInternal(newSize, std::move(T())); - } - constexpr void resize(size_type newSize, const value_type& value) - { - resizeInternal(newSize, value); - } - constexpr void clear() - { - if(_data == nullptr) - { - return; - } - for(size_type i = 0; i < arraySize; ++i) - { - _data[i].~T(); - } - deallocateArray(_data, allocated); - _data = nullptr; - arraySize = 0; - allocated = 0; - markIteratorDirty(); - } - inline size_type indexOf(iterator iterator) - { - return iterator - beginIt; - } - inline size_type indexOf(const_iterator iterator) const - { - return iterator.p - beginIt.p; - } - inline size_type indexOf(T& t) - { - return indexOf(find(t)); - } - inline size_type indexOf(const T& t) const - { - return indexOf(find(t)); - } - inline size_type size() const - { - return arraySize; - } - inline size_type empty() const - { - return arraySize == 0; - } - inline size_type capacity() const - { - return allocated; - } - inline pointer data() const - { - return _data; - } - inline reference front() const - { - assert(arraySize > 0); - return _data[0]; - } - inline reference back() const - { - assert(arraySize > 0); - return _data[arraySize - 1]; - } - void pop() - { - _data[--arraySize].~T(); - markIteratorDirty(); - } - constexpr inline reference operator[](size_type index) - { - assert(index < arraySize); - return _data[index]; - } - constexpr inline const reference operator[](size_type index) const - { - assert(index < arraySize); - return _data[index]; - } - private: - size_type calculateGrowth(size_type newSize) const - { - const size_type oldCapacity = capacity(); - - if (oldCapacity > SIZE_MAX - oldCapacity / 2) - { - return newSize; // geometric growth would overflow - } - - const size_type geometric = oldCapacity + oldCapacity / 2; - - if (geometric < newSize) - { - return newSize; // geometric growth would be insufficient - } - - return geometric; // geometric growth is sufficient - } - void markIteratorDirty() - { - beginIt = Iterator(_data); - endIt = Iterator(_data + arraySize); - } - T* allocateArray(size_type size) - { - T* result = allocator.allocate(size); - assert(result != nullptr); - return result; - } - void deallocateArray(T* ptr, size_type size) - { - allocator.deallocate(ptr, size); - } - template - T& addInternal(Type&& t) - { - if (arraySize == allocated) - { - size_type newSize = arraySize + 1; - allocated = calculateGrowth(newSize); - T *tempArray = allocateArray(allocated); - for (size_type i = 0; i < arraySize; ++i) - { - std::allocator_traits::construct(allocator, &tempArray[i], std::forward(_data[i])); - } - deallocateArray(_data, arraySize); - _data = tempArray; - } - std::allocator_traits::construct(allocator, &_data[arraySize++], std::forward(t)); - markIteratorDirty(); - return _data[arraySize - 1]; - } - template - void resizeInternal(size_type newSize, Type&& value) - { - if (newSize <= allocated) - { - // The array is already big enough - if(newSize < arraySize) - { - // But since we are sizing down we destruct some of them - for(size_type i = newSize; i < arraySize; ++i) - { - std::allocator_traits::destroy(allocator, &_data[i]); - } - } - else - { - // Or construct the new elements by default - for(size_type i = arraySize; i < newSize; ++i) - { - std::allocator_traits::construct(allocator, &_data[i], std::move(value)); - } - } - arraySize = newSize; - } - else - { - // The array is not big enough, so we make a new one - T *newData = allocateArray(newSize); - - // And move the current elements into that one - for(size_type i = 0; i < arraySize; ++i) - { - newData[i] = std::forward(_data[i]); - } - // As well as default initialize the others + // Or construct the new elements by default for(size_type i = arraySize; i < newSize; ++i) { - std::allocator_traits::construct(allocator, &newData[i], std::move(value)); + std::allocator_traits::construct(allocator, &_data[i], std::move(value)); } - deallocateArray(_data, allocated); - arraySize = newSize; - allocated = newSize; - _data = newData; } - markIteratorDirty(); + arraySize = newSize; } - friend class boost::serialization::access; - template - void serialize(Archive& ar, const unsigned int) + else { - ar & arraySize; - resize(arraySize); + // The array is not big enough, so we make a new one + T *newData = allocateArray(newSize); + + // And move the current elements into that one for(size_type i = 0; i < arraySize; ++i) - ar & _data[i]; - markIteratorDirty(); + { + newData[i] = std::forward(_data[i]); + } + // As well as default initialize the others + for(size_type i = arraySize; i < newSize; ++i) + { + std::allocator_traits::construct(allocator, &newData[i], std::move(value)); + } + deallocateArray(_data, allocated); + arraySize = newSize; + allocated = newSize; + _data = newData; } - size_type arraySize = 0; - size_type allocated = 0; - Iterator beginIt; - Iterator endIt; - T *_data = nullptr; - allocator_type allocator; - }; - - template - struct StaticArray + markIteratorDirty(); + } + friend class boost::serialization::access; + template + void serialize(Archive& ar, const unsigned int) { - public: - template - class IteratorBase - { - public: - using iterator_category = std::random_access_iterator_tag; - using value_type = X; - using difference_type = std::ptrdiff_t; - using reference = X&; - using pointer = X*; + ar & arraySize; + resize(arraySize); + for(size_type i = 0; i < arraySize; ++i) + ar & _data[i]; + markIteratorDirty(); + } + size_type arraySize = 0; + size_type allocated = 0; + Iterator beginIt; + Iterator endIt; + T *_data = nullptr; + allocator_type allocator; +}; - IteratorBase(X *x = nullptr) - : p(x) - { - } - reference operator*() const - { - return *p; - } - pointer operator->() const - { - return p; - } - inline bool operator!=(const IteratorBase &other) - { - return p != other.p; - } - inline bool operator==(const IteratorBase &other) - { - return p == other.p; - } - IteratorBase &operator++() - { - p++; - return *this; - } - IteratorBase operator++(int) - { - IteratorBase tmp(*this); - ++*this; - return tmp; - } - IteratorBase &operator--() - { - p--; - return *this; - } - IteratorBase operator--(int) - { - IteratorBase tmp(*this); - --*this; - return tmp; - } - - - private: - X *p; - }; - using value_type = T; - using size_type = size_t; +template +struct StaticArray +{ +public: + template + class IteratorBase + { + public: + using iterator_category = std::random_access_iterator_tag; + using value_type = X; using difference_type = std::ptrdiff_t; - using pointer = T*; - using const_pointer = const T*; - using reference = T&; - using const_reference = const T&; + using reference = X&; + using pointer = X*; - using iterator = IteratorBase; - using const_iterator = IteratorBase; - - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - StaticArray() + IteratorBase(X *x = nullptr) + : p(x) { - beginIt = iterator(_data); - endIt = iterator(_data + N); } - StaticArray(T value) + reference operator*() const { - for (int i = 0; i < N; ++i) - { - _data[i] = value; - } - beginIt = iterator(_data); - endIt = iterator(_data + N); + return *p; } - ~StaticArray() + pointer operator->() const { + return p; + } + inline bool operator!=(const IteratorBase &other) + { + return p != other.p; + } + inline bool operator==(const IteratorBase &other) + { + return p == other.p; + } + IteratorBase &operator++() + { + p++; + return *this; + } + IteratorBase operator++(int) + { + IteratorBase tmp(*this); + ++*this; + return tmp; + } + IteratorBase &operator--() + { + p--; + return *this; + } + IteratorBase operator--(int) + { + IteratorBase tmp(*this); + --*this; + return tmp; } - inline size_type size() const - { - return N; - } - inline pointer data() - { - return _data; - } - inline const_pointer data() const - { - return _data; - } - constexpr reference operator[](size_type index) noexcept - { - assert(index < N); - return _data[index]; - } - constexpr const_reference operator[](size_type index) const noexcept - { - assert(index < N); - return _data[index]; - } - iterator begin() - { - return beginIt; - } - iterator end() - { - return endIt; - } - const_iterator begin() const - { - return beginIt; - } - const_iterator end() const - { - return beginIt; - } + private: - T _data[N]; - iterator beginIt; - iterator endIt; - friend class boost::serialization::access; - template - void serialize(Archive& ar, const unsigned int version) - { - ar & version; - ar & N; - ar & _data; - } + X *p; }; + using value_type = T; + using size_type = size_t; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + + using iterator = IteratorBase; + using const_iterator = IteratorBase; + + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + StaticArray() + { + beginIt = iterator(_data); + endIt = iterator(_data + N); + } + StaticArray(T value) + { + for (int i = 0; i < N; ++i) + { + _data[i] = value; + } + beginIt = iterator(_data); + endIt = iterator(_data + N); + } + ~StaticArray() + { + } + + inline size_type size() const + { + return N; + } + inline pointer data() + { + return _data; + } + inline const_pointer data() const + { + return _data; + } + constexpr reference operator[](size_type index) noexcept + { + assert(index < N); + return _data[index]; + } + constexpr const_reference operator[](size_type index) const noexcept + { + assert(index < N); + return _data[index]; + } + iterator begin() + { + return beginIt; + } + iterator end() + { + return endIt; + } + const_iterator begin() const + { + return beginIt; + } + const_iterator end() const + { + return beginIt; + } +private: + T _data[N]; + iterator beginIt; + iterator endIt; + friend class boost::serialization::access; + template + void serialize(Archive& ar, const unsigned int version) + { + ar & version; + ar & N; + ar & _data; + } +}; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Containers/Array.natvis b/src/Engine/Containers/Array.natvis new file mode 100644 index 0000000..d2620ed --- /dev/null +++ b/src/Engine/Containers/Array.natvis @@ -0,0 +1,13 @@ + + + + {{ size={arraySize} }} + + arraySize + allocated + + arraySize + _data + + + diff --git a/src/Engine/Containers/CMakeLists.txt b/src/Engine/Containers/CMakeLists.txt index 93a7932..24e2d04 100644 --- a/src/Engine/Containers/CMakeLists.txt +++ b/src/Engine/Containers/CMakeLists.txt @@ -1,5 +1,6 @@ target_sources(SeeleEngine PRIVATE + Array.natvis Array.h Map.h List.h) \ No newline at end of file diff --git a/src/Engine/Containers/List.h b/src/Engine/Containers/List.h index a9ca027..3b1a3e7 100644 --- a/src/Engine/Containers/List.h +++ b/src/Engine/Containers/List.h @@ -152,15 +152,7 @@ public: { if(this != &other) { - if(root != nullptr) - { - delete root; - } - if(tail != nullptr) - { - delete tail; - } - _size = 0; + clear(); for(const auto& it : other) { add(it); @@ -173,10 +165,7 @@ public: { if(this != &other) { - if(root != nullptr) - { - clear(); - } + clear(); root = other.root; tail = other.tail; beginIt = other.beginIt; @@ -205,6 +194,7 @@ public: for (Node *tmp = root; tmp != tail;) { tmp = tmp->next; + destroyNode(tmp->prev); deallocateNode(tmp->prev); } deallocateNode(tail); @@ -216,43 +206,16 @@ public: //Insert at the end iterator add(const T &value) { - if (root == nullptr) - { - root = allocateNode(); - tail = root; - } - initializeNode(tail, value); - Node *newTail = allocateNode(); - newTail->prev = tail; - newTail->next = nullptr; - tail->next = newTail; - iterator insertedElement(tail); - tail = newTail; - markIteratorDirty(); - _size++; - return insertedElement; + return addInternal(value); } iterator add(T&& value) { - if (root == nullptr) - { - root = allocateNode(); - tail = root; - } - initializeNode(tail, std::move(value)); - Node *newTail = allocateNode(); - newTail->prev = tail; - newTail->next = nullptr; - tail->next = newTail; - Iterator insertedElement(tail); - tail = newTail; - markIteratorDirty(); - _size++; - return insertedElement; + return addInternal(std::move(value)); } // takes all elements from other and move-inserts them into // this, clearing other in the process - void moveElements(List& other){ + void moveElements(List& other) + { tail->prev->next = other.root; other.root->prev = tail->prev; _size += other._size; @@ -309,12 +272,13 @@ public: } if(next == nullptr) { - root = prev; + tail = prev; } else { next->prev = prev; } + destroyNode(pos.node); deallocateNode(pos.node); markIteratorDirty(); return Iterator(next); @@ -408,10 +372,33 @@ private: node->next, std::forward(data)); } + void destroyNode(Node* node) + { + std::allocator_traits::destroy(allocator, node); + } void deallocateNode(Node* node) { allocator.deallocate(node, 1); } + template + iterator addInternal(ValueType&& value) + { + if (root == nullptr) + { + root = allocateNode(); + tail = root; + } + initializeNode(tail, std::forward(value)); + Node* newTail = allocateNode(); + newTail->prev = tail; + newTail->next = nullptr; + tail->next = newTail; + Iterator insertedElement(tail); + tail = newTail; + markIteratorDirty(); + _size++; + return insertedElement; + } void markIteratorDirty() { beginIt = Iterator(root); @@ -421,10 +408,10 @@ private: } Node *root; Node *tail; - Iterator beginIt; - Iterator endIt; - ConstIterator cbeginIt; - ConstIterator cendIt; + iterator beginIt; + iterator endIt; + const_iterator cbeginIt; + const_iterator cendIt; size_type _size; NodeAllocator allocator; }; diff --git a/src/Engine/Graphics/Graphics.h b/src/Engine/Graphics/Graphics.h index 18d1e9f..af73c17 100644 --- a/src/Engine/Graphics/Graphics.h +++ b/src/Engine/Graphics/Graphics.h @@ -56,7 +56,7 @@ public: virtual PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) = 0; virtual PDescriptorLayout createDescriptorLayout(const std::string& name = "") = 0; - virtual PPipelineLayout createPipelineLayout() = 0; + virtual PPipelineLayout createPipelineLayout(PPipelineLayout baseLayout = nullptr) = 0; virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) = 0; diff --git a/src/Engine/Graphics/GraphicsInitializer.h b/src/Engine/Graphics/GraphicsInitializer.h index 750d1ee..1c3c1f3 100644 --- a/src/Engine/Graphics/GraphicsInitializer.h +++ b/src/Engine/Graphics/GraphicsInitializer.h @@ -22,20 +22,13 @@ struct GraphicsInitializer GraphicsInitializer() : applicationName("SeeleEngine") , engineName("SeeleEngine") + , windowLayoutFile(nullptr) , layers{"VK_LAYER_KHRONOS_validation", "VK_LAYER_LUNARG_monitor"} , instanceExtensions{} , deviceExtensions{"VK_KHR_swapchain"} , windowHandle(nullptr) { } - GraphicsInitializer(const GraphicsInitializer &other) - : applicationName(other.applicationName) - , engineName(other.engineName) - , layers(other.layers) - , instanceExtensions(other.instanceExtensions) - , deviceExtensions(other.deviceExtensions) - { - } }; struct WindowCreateInfo { diff --git a/src/Engine/Graphics/GraphicsResources.cpp b/src/Engine/Graphics/GraphicsResources.cpp index 90b1d57..8fa32c3 100644 --- a/src/Engine/Graphics/GraphicsResources.cpp +++ b/src/Engine/Graphics/GraphicsResources.cpp @@ -57,6 +57,7 @@ ShaderCollection& ShaderMap::createShaders( VertexInputType* vertexInput, bool /*bPositionOnly*/) { + std::scoped_lock lock(shadersLock); ShaderCollection& collection = shaders.add(); //collection.vertexDeclaration = bPositionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration(); @@ -107,7 +108,7 @@ void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorTyp PDescriptorSet DescriptorLayout::allocateDescriptorSet() { - std::unique_lock lock(allocatorLock); + std::scoped_lock lock(allocatorLock); PDescriptorSet result; allocator->allocateDescriptorSet(result); return result; @@ -115,7 +116,7 @@ PDescriptorSet DescriptorLayout::allocateDescriptorSet() void DescriptorLayout::reset() { - std::unique_lock lock(allocatorLock); + std::scoped_lock lock(allocatorLock); allocator->reset(); } @@ -270,7 +271,7 @@ static Map vertexDeclarationCache; PVertexDeclaration VertexDeclaration::createDeclaration(PGraphics graphics, const Array& elementList) { - std::unique_lock lock(vertexDeclarationLock); + std::scoped_lock lock(vertexDeclarationLock); boost::crc_32_type result; result.process_bytes(&elementList, sizeof(VertexElement) * elementList.size()); uint32 key = result.checksum(); diff --git a/src/Engine/Graphics/GraphicsResources.h b/src/Engine/Graphics/GraphicsResources.h index 1dcd4d7..ba5c4a9 100644 --- a/src/Engine/Graphics/GraphicsResources.h +++ b/src/Engine/Graphics/GraphicsResources.h @@ -144,6 +144,7 @@ public: VertexInputType* vertexInput, bool bPositionOnly); private: + std::mutex shadersLock; Array shaders; }; DEFINE_REF(ShaderMap) @@ -242,7 +243,14 @@ DEFINE_REF(DescriptorLayout) class PipelineLayout { public: - PipelineLayout() {} + PipelineLayout(PPipelineLayout baseLayout) + { + if(baseLayout != nullptr) + { + descriptorSetLayouts = baseLayout->descriptorSetLayouts; + pushConstants = baseLayout->pushConstants; + } + } virtual ~PipelineLayout() {} virtual void create() = 0; virtual void reset() = 0; diff --git a/src/Engine/Graphics/Mesh.h b/src/Engine/Graphics/Mesh.h index e7ad89c..00d70ba 100644 --- a/src/Engine/Graphics/Mesh.h +++ b/src/Engine/Graphics/Mesh.h @@ -15,11 +15,6 @@ public: PVertexShaderInput vertexInput; PMaterialAsset referencedMaterial; private: - friend class boost::serialization::access; - template - void serialize(Archive&, const unsigned int) - { - } }; DEFINE_REF(Mesh) } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/MeshBatch.cpp b/src/Engine/Graphics/MeshBatch.cpp index 5c5091b..745dfa0 100644 --- a/src/Engine/Graphics/MeshBatch.cpp +++ b/src/Engine/Graphics/MeshBatch.cpp @@ -24,5 +24,6 @@ MeshBatch::MeshBatch() , topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) , vertexInput(nullptr) , material(nullptr) + , elements() { } \ No newline at end of file diff --git a/src/Engine/Graphics/MeshBatch.h b/src/Engine/Graphics/MeshBatch.h index b9ffc8a..656e04e 100644 --- a/src/Engine/Graphics/MeshBatch.h +++ b/src/Engine/Graphics/MeshBatch.h @@ -34,7 +34,7 @@ public: }; struct MeshBatch { - Array elements; + std::vector elements; uint8 useReverseCulling : 1; uint8 isBackfaceCullingDisabled : 1; @@ -68,6 +68,10 @@ struct MeshBatch } MeshBatch(); + MeshBatch(const MeshBatch& other) = default; + MeshBatch(MeshBatch&& other) = default; + MeshBatch& operator=(const MeshBatch& other) = default; + MeshBatch& operator=(MeshBatch&& other) = default; }; DECLARE_REF(PrimitiveComponent) struct StaticMeshBatch : public MeshBatch diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index 3062b64..5fbd58c 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -20,11 +20,11 @@ BasePassMeshProcessor::~BasePassMeshProcessor() { } -void BasePassMeshProcessor::processMeshBatch( +Job BasePassMeshProcessor::processMeshBatch( const MeshBatch& batch, // const PPrimitiveComponent primitiveComponent, const Gfx::PRenderPass& renderPass, - Gfx::PPipelineLayout pipelineLayout, + Gfx::PPipelineLayout baseLayout, Gfx::PDescriptorLayout primitiveLayout, Array descriptorSets, int32 /*staticMeshId*/) @@ -40,6 +40,7 @@ void BasePassMeshProcessor::processMeshBatch( Gfx::PRenderCommand renderCommand = graphics->createRenderCommand(); renderCommand->setViewport(target); + Gfx::PPipelineLayout pipelineLayout = graphics->createPipelineLayout(baseLayout); pipelineLayout->addDescriptorLayout(BasePass::INDEX_MATERIAL, material->getDescriptorLayout()); pipelineLayout->create(); Gfx::PDescriptorSet materialSet = material->createDescriptorSet(); @@ -63,9 +64,9 @@ void BasePassMeshProcessor::processMeshBatch( collection->fragmentShader, false); } - std::unique_lock lock(commandLock); + std::scoped_lock lock(commandLock); renderCommands.add(renderCommand); - //co_return; + co_return; } BasePass::BasePass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source) @@ -157,7 +158,7 @@ MainJob BasePass::render() for (auto &&meshBatch : passData.staticDrawList) { //jobs.add( - processor->processMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets); + co_await processor->processMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets); } //co_await Job::all(jobs); graphics->executeCommands(processor->getRenderCommands()); diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index 7822500..bbcc9a4 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -11,7 +11,7 @@ public: BasePassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics, uint8 translucentBasePass); virtual ~BasePassMeshProcessor(); - virtual void processMeshBatch( + virtual Job processMeshBatch( const MeshBatch& batch, // const PPrimitiveComponent primitiveComponent, const Gfx::PRenderPass& renderPass, @@ -30,7 +30,7 @@ DECLARE_REF(CameraActor) DECLARE_REF(CameraComponent) struct BasePassData { - Array staticDrawList; + std::vector staticDrawList; }; class BasePass : public RenderPass { diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp index e9fd5df..a4bc161 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -18,11 +18,11 @@ DepthPrepassMeshProcessor::~DepthPrepassMeshProcessor() { } -void DepthPrepassMeshProcessor::processMeshBatch( +Job DepthPrepassMeshProcessor::processMeshBatch( const MeshBatch& batch, // const PPrimitiveComponent primitiveComponent, const Gfx::PRenderPass& renderPass, - Gfx::PPipelineLayout pipelineLayout, + Gfx::PPipelineLayout baseLayout, Gfx::PDescriptorLayout primitiveLayout, Array descriptorSets, int32 /*staticMeshId*/) @@ -38,6 +38,7 @@ void DepthPrepassMeshProcessor::processMeshBatch( Gfx::PRenderCommand renderCommand = graphics->createRenderCommand(); renderCommand->setViewport(target); + Gfx::PPipelineLayout pipelineLayout = graphics->createPipelineLayout(baseLayout); pipelineLayout->addDescriptorLayout(DepthPrepass::INDEX_MATERIAL, material->getDescriptorLayout()); pipelineLayout->create(); Gfx::PDescriptorSet materialSet = material->createDescriptorSet(); @@ -61,10 +62,10 @@ void DepthPrepassMeshProcessor::processMeshBatch( collection->fragmentShader, true); } - std::unique_lock lock(commandLock); + std::scoped_lock lock(commandLock); renderCommands.add(renderCommand); //std::cout << "Finished depth job" << std::endl; - //co_return; + co_return; } DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source) @@ -128,10 +129,9 @@ MainJob DepthPrepass::render() for (auto &&meshBatch : passData.staticDrawList) { //jobs.add( - processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets); + co_await processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets); } //co_await Job::all(jobs); - //std::cout << "Finished waiting depth jobs " << std::endl; graphics->executeCommands(processor->getRenderCommands()); graphics->endRenderPass(); co_return; diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.h b/src/Engine/Graphics/RenderPass/DepthPrepass.h index 55d91e4..d87ab35 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.h +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.h @@ -11,7 +11,7 @@ public: DepthPrepassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics); virtual ~DepthPrepassMeshProcessor(); - virtual void processMeshBatch( + virtual Job processMeshBatch( const MeshBatch& batch, const Gfx::PRenderPass& renderPass, Gfx::PPipelineLayout pipelineLayout, @@ -27,7 +27,7 @@ DECLARE_REF(CameraActor) DECLARE_REF(CameraComponent) struct DepthPrepassData { - Array staticDrawList; + std::vector staticDrawList; }; class DepthPrepass : public RenderPass { diff --git a/src/Engine/Graphics/RenderPass/MeshProcessor.cpp b/src/Engine/Graphics/RenderPass/MeshProcessor.cpp index d3540a0..910de4d 100644 --- a/src/Engine/Graphics/RenderPass/MeshProcessor.cpp +++ b/src/Engine/Graphics/RenderPass/MeshProcessor.cpp @@ -1,6 +1,7 @@ #include "MeshProcessor.h" #include "Graphics/Graphics.h" #include "Graphics/VertexShaderInput.h" +#include "Graphics/Vulkan/VulkanGraphicsResources.h" using namespace Seele; @@ -32,8 +33,6 @@ void MeshProcessor::buildMeshDrawCommand( GraphicsPipelineCreateInfo pipelineInitializer; pipelineInitializer.topology = meshBatch.topology; - Gfx::PVertexDeclaration vertexDecl = positionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration(); - pipelineInitializer.vertexDeclaration = vertexDecl; pipelineInitializer.vertexShader = vertexShader; pipelineInitializer.controlShader = controlShader; pipelineInitializer.evalShader = evaluationShader; @@ -46,10 +45,12 @@ void MeshProcessor::buildMeshDrawCommand( if(positionOnly) { vertexInput->getPositionOnlyStream(vertexStreams); + pipelineInitializer.vertexDeclaration = vertexInput->getPositionDeclaration(); } else { vertexInput->getStreams(vertexStreams); + pipelineInitializer.vertexDeclaration = vertexInput->getDeclaration(); } Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(pipelineInitializer); drawCommand->bindPipeline(pipeline); diff --git a/src/Engine/Graphics/RenderPass/MeshProcessor.h b/src/Engine/Graphics/RenderPass/MeshProcessor.h index a24663c..24010ec 100644 --- a/src/Engine/Graphics/RenderPass/MeshProcessor.h +++ b/src/Engine/Graphics/RenderPass/MeshProcessor.h @@ -17,7 +17,7 @@ public: protected: PScene scene; Gfx::PGraphics graphics; - virtual void processMeshBatch( + virtual Job processMeshBatch( const MeshBatch& batch, // const PPrimitiveComponent primitiveComponent, const Gfx::PRenderPass& renderPass, diff --git a/src/Engine/Graphics/Vulkan/NsightAftermathGpuCrashTracker.cpp b/src/Engine/Graphics/Vulkan/NsightAftermathGpuCrashTracker.cpp index 5f44808..b19c44d 100644 --- a/src/Engine/Graphics/Vulkan/NsightAftermathGpuCrashTracker.cpp +++ b/src/Engine/Graphics/Vulkan/NsightAftermathGpuCrashTracker.cpp @@ -77,7 +77,7 @@ void GpuCrashTracker::Initialize() void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize) { // Make sure only one thread at a time... - std::unique_lock lock(m_mutex); + std::scoped_lock lock(m_mutex); // Write to file for later in-depth analysis with Nsight Graphics. WriteGpuCrashDumpToFile(pGpuCrashDump, gpuCrashDumpSize); @@ -87,7 +87,7 @@ void GpuCrashTracker::OnCrashDump(const void* pGpuCrashDump, const uint32_t gpuC void GpuCrashTracker::OnShaderDebugInfo(const void* pShaderDebugInfo, const uint32_t shaderDebugInfoSize) { // Make sure only one thread at a time... - std::unique_lock lock(m_mutex); + std::scoped_lock lock(m_mutex); // Get shader debug information identifier GFSDK_Aftermath_ShaderDebugInfoIdentifier identifier = {}; diff --git a/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp b/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp index 472830e..fbcef8c 100644 --- a/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp @@ -74,7 +74,7 @@ Allocation::~Allocation() PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment) { - std::unique_lock lck(lock); + std::scoped_lock lck(lock); if (isDedicated) { if (activeAllocations.empty() && requestedSize == bytesAllocated) @@ -134,7 +134,7 @@ void Allocation::markFree(SubAllocation *allocation) PSubAllocation freeRangeToDelete; { - std::unique_lock lck(lock); + std::scoped_lock lck(lock); //Join lower bound for (auto freeRange : freeRanges) { @@ -204,7 +204,7 @@ Allocator::Allocator(PGraphics graphics) Allocator::~Allocator() { - std::unique_lock lck(lock); + std::scoped_lock lck(lock); for (auto heap : heaps) { for (auto alloc : heap.allocations) @@ -219,7 +219,7 @@ Allocator::~Allocator() PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo) { - std::unique_lock lck(lock); + std::scoped_lock lck(lock); const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements; uint8 memoryTypeIndex; VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex)); @@ -252,7 +252,7 @@ PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2 void Allocator::free(Allocation *allocation) { - std::unique_lock lck(lock); + std::scoped_lock lck(lock); for (auto heap : heaps) { for (uint32 i = 0; i < heap.allocations.size(); ++i) @@ -307,7 +307,7 @@ void StagingManager::clearPending() PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead) { - std::unique_lock l(lock); + std::scoped_lock l(lock); for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it) { auto freeBuffer = *it; @@ -323,6 +323,9 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF PStagingBuffer stagingBuffer = new StagingBuffer(); VkBufferCreateInfo stagingBufferCreateInfo = init::BufferCreateInfo(usage, size); stagingBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + uint32 queueIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(Gfx::QueueType::DEDICATED_TRANSFER); + stagingBufferCreateInfo.queueFamilyIndexCount = 1; + stagingBufferCreateInfo.pQueueFamilyIndices = &queueIndex; VkDevice vulkanDevice = graphics->getDevice(); VK_CHECK(vkCreateBuffer(vulkanDevice, &stagingBufferCreateInfo, nullptr, &stagingBuffer->buffer)); @@ -355,7 +358,7 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF void StagingManager::releaseStagingBuffer(PStagingBuffer buffer) { - std::unique_lock l(lock); + std::scoped_lock l(lock); freeBuffers.add(buffer); activeBuffers.remove(activeBuffers.find(buffer.getHandle())); } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp index 87ecc94..62c44c8 100644 --- a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp @@ -10,277 +10,277 @@ using namespace Seele::Vulkan; struct PendingBuffer { - PStagingBuffer stagingBuffer; - Gfx::QueueType prevQueue; - bool bWriteOnly; + PStagingBuffer stagingBuffer; + Gfx::QueueType prevQueue; + bool bWriteOnly; }; static Map pendingBuffers; ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic) - : graphics(graphics) - , currentBuffer(0) - , size(size) - , owner(queueType) + : graphics(graphics) + , currentBuffer(0) + , size(size) + , owner(queueType) { - if(bDynamic) - { - numBuffers = Gfx::numFramesBuffered; - } - else - { - numBuffers = 1; - } - usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; - usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - VkBufferCreateInfo info = - init::BufferCreateInfo( - usage, - size); - info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - uint32 queueFamilyIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(queueType); - info.pQueueFamilyIndices = &queueFamilyIndex; - info.queueFamilyIndexCount = 0; - VkBufferMemoryRequirementsInfo2 bufferReqInfo; - bufferReqInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2; - bufferReqInfo.pNext = nullptr; - VkMemoryDedicatedRequirements dedicatedRequirements; - dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; - dedicatedRequirements.pNext = nullptr; - VkMemoryRequirements2 memRequirements; - memRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; - memRequirements.pNext = &dedicatedRequirements; - for (uint32 i = 0; i < numBuffers; ++i) - { - VK_CHECK(vkCreateBuffer(graphics->getDevice(), &info, nullptr, &buffers[i].buffer)); - bufferReqInfo.buffer = buffers[i].buffer; - 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); - buffers[i].allocation = temp; - vkBindBufferMemory(graphics->getDevice(), buffers[i].buffer, buffers[i].allocation->getHandle(), buffers[i].allocation->getOffset()); - } + if(bDynamic) + { + numBuffers = Gfx::numFramesBuffered; + } + else + { + numBuffers = 1; + } + usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; + usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + VkBufferCreateInfo info = + init::BufferCreateInfo( + usage, + size); + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + uint32 queueFamilyIndex = graphics->getFamilyMapping().getQueueTypeFamilyIndex(queueType); + info.pQueueFamilyIndices = &queueFamilyIndex; + info.queueFamilyIndexCount = 1; + VkBufferMemoryRequirementsInfo2 bufferReqInfo; + bufferReqInfo.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2; + bufferReqInfo.pNext = nullptr; + VkMemoryDedicatedRequirements dedicatedRequirements; + dedicatedRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS; + dedicatedRequirements.pNext = nullptr; + VkMemoryRequirements2 memRequirements; + memRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; + memRequirements.pNext = &dedicatedRequirements; + for (uint32 i = 0; i < numBuffers; ++i) + { + VK_CHECK(vkCreateBuffer(graphics->getDevice(), &info, nullptr, &buffers[i].buffer)); + bufferReqInfo.buffer = buffers[i].buffer; + 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); + buffers[i].allocation = temp; + vkBindBufferMemory(graphics->getDevice(), buffers[i].buffer, buffers[i].allocation->getHandle(), buffers[i].allocation->getOffset()); + } } ShaderBuffer::~ShaderBuffer() { - PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands(); - VkDevice device = graphics->getDevice(); - auto deletionLambda = [cmdBuffer, device](VkBuffer buffer) -> Job - { - //co_await cmdBuffer->asyncWait(); - //vkDestroyBuffer(device, buffer, nullptr); + PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands(); + VkDevice device = graphics->getDevice(); + auto deletionLambda = [cmdBuffer, device](VkBuffer buffer) -> Job + { + //co_await cmdBuffer->asyncWait(); + //vkDestroyBuffer(device, buffer, nullptr); co_return; }; - for (uint32 i = 0; i < numBuffers; ++i) - { - deletionLambda(buffers[i].buffer); - buffers[i].allocation = nullptr; - } - graphics = nullptr; + for (uint32 i = 0; i < numBuffers; ++i) + { + deletionLambda(buffers[i].buffer); + buffers[i].allocation = nullptr; + } + graphics = nullptr; } VkDeviceSize ShaderBuffer::getOffset() const { - return buffers[currentBuffer].allocation->getOffset(); + return buffers[currentBuffer].allocation->getOffset(); } void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - VkBufferMemoryBarrier barrier = - init::BufferMemoryBarrier(); - PCommandBufferManager sourceManager = graphics->getQueueCommands(owner); - PCommandBufferManager dstManager = nullptr; - VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; - VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; - Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping(); - barrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner); - barrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner); - assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex); - if (owner == Gfx::QueueType::TRANSFER || owner == Gfx::QueueType::DEDICATED_TRANSFER) - { - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - } - else if (owner == Gfx::QueueType::COMPUTE) - { - barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; - srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - } - else if (owner == Gfx::QueueType::GRAPHICS) - { - barrier.srcAccessMask = getSourceAccessMask(); - srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; - } - if (newOwner == Gfx::QueueType::TRANSFER) - { - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - dstManager = graphics->getTransferCommands(); - } - else if (newOwner == Gfx::QueueType::DEDICATED_TRANSFER) - { - barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; - dstManager = graphics->getDedicatedTransferCommands(); - } - else if (newOwner == Gfx::QueueType::COMPUTE) - { - barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; - dstStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; - dstManager = graphics->getComputeCommands(); - } - else if (newOwner == Gfx::QueueType::GRAPHICS) - { - barrier.dstAccessMask = getDestAccessMask(); - dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; - dstManager = graphics->getGraphicsCommands(); - } - VkCommandBuffer srcCommand = sourceManager->getCommands()->getHandle(); - VkCommandBuffer dstCommand = dstManager->getCommands()->getHandle(); - VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; - barrier.offset = 0; - barrier.size = size; - for (uint32 i = 0; i < numBuffers; ++i) - { - dynamicBarriers[i] = barrier; - dynamicBarriers[i].buffer = buffers[i].buffer; - } - vkCmdPipelineBarrier(srcCommand, srcStage, srcStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); - vkCmdPipelineBarrier(dstCommand, dstStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); - sourceManager->submitCommands(); + VkBufferMemoryBarrier barrier = + init::BufferMemoryBarrier(); + PCommandBufferManager sourceManager = graphics->getQueueCommands(owner); + PCommandBufferManager dstManager = nullptr; + VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping(); + barrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(owner); + barrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner); + assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex); + if (owner == Gfx::QueueType::TRANSFER || owner == Gfx::QueueType::DEDICATED_TRANSFER) + { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + } + else if (owner == Gfx::QueueType::COMPUTE) + { + barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT; + srcStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + } + else if (owner == Gfx::QueueType::GRAPHICS) + { + barrier.srcAccessMask = getSourceAccessMask(); + srcStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; + } + if (newOwner == Gfx::QueueType::TRANSFER) + { + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + dstManager = graphics->getTransferCommands(); + } + else if (newOwner == Gfx::QueueType::DEDICATED_TRANSFER) + { + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + dstManager = graphics->getDedicatedTransferCommands(); + } + else if (newOwner == Gfx::QueueType::COMPUTE) + { + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + dstStage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; + dstManager = graphics->getComputeCommands(); + } + else if (newOwner == Gfx::QueueType::GRAPHICS) + { + barrier.dstAccessMask = getDestAccessMask(); + dstStage = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; + dstManager = graphics->getGraphicsCommands(); + } + VkCommandBuffer srcCommand = sourceManager->getCommands()->getHandle(); + VkCommandBuffer dstCommand = dstManager->getCommands()->getHandle(); + VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; + barrier.offset = 0; + barrier.size = size; + for (uint32 i = 0; i < numBuffers; ++i) + { + dynamicBarriers[i] = barrier; + dynamicBarriers[i].buffer = buffers[i].buffer; + } + vkCmdPipelineBarrier(srcCommand, srcStage, srcStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); + vkCmdPipelineBarrier(dstCommand, dstStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); + sourceManager->submitCommands(); } void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, VkAccessFlags dstAccess, VkPipelineStageFlags dstStage) { - PCmdBuffer commandBuffer = graphics->getQueueCommands(owner)->getCommands(); - VkBufferMemoryBarrier barrier = init::BufferMemoryBarrier(); - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstAccessMask = dstAccess; - barrier.srcAccessMask = srcAccess; - barrier.offset = 0; - barrier.size = size; - VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; - for(uint32 i = 0; i < numBuffers; ++i) - { - dynamicBarriers[i] = barrier; - dynamicBarriers[i].buffer = buffers[i].buffer; - } - vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); + PCmdBuffer commandBuffer = graphics->getQueueCommands(owner)->getCommands(); + VkBufferMemoryBarrier barrier = init::BufferMemoryBarrier(); + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstAccessMask = dstAccess; + barrier.srcAccessMask = srcAccess; + barrier.offset = 0; + barrier.size = size; + VkBufferMemoryBarrier dynamicBarriers[Gfx::numFramesBuffered]; + for(uint32 i = 0; i < numBuffers; ++i) + { + dynamicBarriers[i] = barrier; + dynamicBarriers[i].buffer = buffers[i].buffer; + } + vkCmdPipelineBarrier(commandBuffer->getHandle(), srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr); } void *ShaderBuffer::lock(bool bWriteOnly) { - void *data = nullptr; + void *data = nullptr; - /*if (bVolatile) - { - if (lockMode == RLM_ReadOnly) - { - assert(0); - } - else - { - throw new std::logic_error("TODO implement volatile buffers"); - //device->getRHIDevice()->getTemp - } - }*/ - //assert(bStatic || bDynamic || bUAV); + /*if (bVolatile) + { + if (lockMode == RLM_ReadOnly) + { + assert(0); + } + else + { + throw new std::logic_error("TODO implement volatile buffers"); + //device->getRHIDevice()->getTemp + } + }*/ + //assert(bStatic || bDynamic || bUAV); - PendingBuffer pending; - pending.bWriteOnly = bWriteOnly; - pending.prevQueue = owner; - if (bWriteOnly) - { - //requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); - PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); - data = stagingBuffer->getMappedPointer(); - pending.stagingBuffer = stagingBuffer; - } - else - { - PCmdBuffer current = graphics->getQueueCommands(owner)->getCommands(); - graphics->getQueueCommands(owner)->submitCommands(); - current->waitForCommand(); + PendingBuffer pending; + pending.bWriteOnly = bWriteOnly; + pending.prevQueue = owner; + if (bWriteOnly) + { + //requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); + PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + data = stagingBuffer->getMappedPointer(); + pending.stagingBuffer = stagingBuffer; + } + else + { + PCmdBuffer current = graphics->getQueueCommands(owner)->getCommands(); + graphics->getQueueCommands(owner)->submitCommands(); + current->waitForCommand(); - requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); - VkCommandBuffer handle = graphics->getQueueCommands(owner)->getCommands()->getHandle(); + requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER); + VkCommandBuffer handle = graphics->getQueueCommands(owner)->getCommands()->getHandle(); - VkBufferMemoryBarrier barrier = - init::BufferMemoryBarrier(); - barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - barrier.buffer = buffers[currentBuffer].buffer; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.offset = 0; - barrier.size = size; - vkCmdPipelineBarrier(handle, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1, &barrier, 0, nullptr); + VkBufferMemoryBarrier barrier = + init::BufferMemoryBarrier(); + barrier.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + barrier.buffer = buffers[currentBuffer].buffer; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.offset = 0; + barrier.size = size; + 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; - regions.size = size; - regions.srcOffset = 0; - regions.dstOffset = 0; + VkBufferCopy regions; + regions.size = size; + regions.srcOffset = 0; + regions.dstOffset = 0; - vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, ®ions); + vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, ®ions); - graphics->getQueueCommands(owner)->submitCommands(); - vkQueueWaitIdle(graphics->getQueueCommands(owner)->getQueue()->getHandle()); + graphics->getQueueCommands(owner)->submitCommands(); + vkQueueWaitIdle(graphics->getQueueCommands(owner)->getQueue()->getHandle()); - stagingBuffer->flushMappedMemory(); - pending.stagingBuffer = stagingBuffer; + stagingBuffer->flushMappedMemory(); + pending.stagingBuffer = stagingBuffer; - data = stagingBuffer->getMappedPointer(); - } - pendingBuffers[this] = pending; + data = stagingBuffer->getMappedPointer(); + } + pendingBuffers[this] = pending; - assert(data); - return data; + assert(data); + return data; } void ShaderBuffer::unlock() { - auto found = pendingBuffers.find(this); - if (found != pendingBuffers.end()) - { - PendingBuffer pending = found->value; - pending.stagingBuffer->flushMappedMemory(); - pendingBuffers.erase(this); - if (pending.bWriteOnly) - { - PStagingBuffer stagingBuffer = pending.stagingBuffer; - PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands(); - VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); + auto found = pendingBuffers.find(this); + if (found != pendingBuffers.end()) + { + PendingBuffer pending = found->value; + pending.stagingBuffer->flushMappedMemory(); + pendingBuffers.erase(this); + if (pending.bWriteOnly) + { + PStagingBuffer stagingBuffer = pending.stagingBuffer; + PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands(); + VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); - VkBufferCopy region; - std::memset(®ion, 0, sizeof(VkBufferCopy)); - region.size = size; - vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); - graphics->getQueueCommands(owner)->submitCommands(); - } - //requestOwnershipTransfer(pending.prevQueue); - graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer); - } + VkBufferCopy region; + std::memset(®ion, 0, sizeof(VkBufferCopy)); + region.size = size; + vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); + graphics->getQueueCommands(owner)->submitCommands(); + } + //requestOwnershipTransfer(pending.prevQueue); + graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer); + } } UniformBuffer::UniformBuffer(PGraphics graphics, const UniformBufferCreateInfo &createInfo) - : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.resourceData) - , Vulkan::ShaderBuffer(graphics, createInfo.resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.bDynamic) - , dedicatedStagingBuffer(nullptr) + : Gfx::UniformBuffer(graphics->getFamilyMapping(), createInfo.resourceData) + , Vulkan::ShaderBuffer(graphics, createInfo.resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, currentOwner, createInfo.bDynamic) + , dedicatedStagingBuffer(nullptr) { - if(createInfo.bDynamic) - { - dedicatedStagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(createInfo.resourceData.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); - } - if (createInfo.resourceData.data != nullptr) - { - void *data = lock(); - std::memcpy(data, createInfo.resourceData.data, createInfo.resourceData.size); - unlock(); - } + if(createInfo.bDynamic) + { + dedicatedStagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(createInfo.resourceData.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + } + if (createInfo.resourceData.data != nullptr) + { + void *data = lock(); + std::memcpy(data, createInfo.resourceData.data, createInfo.resourceData.size); + unlock(); + } } UniformBuffer::~UniformBuffer() @@ -290,52 +290,52 @@ UniformBuffer::~UniformBuffer() bool UniformBuffer::updateContents(const BulkResourceData &resourceData) { if(!Gfx::UniformBuffer::updateContents(resourceData)) - { - // no update was performed, skip - return false; - } + { + // no update was performed, skip + return false; + } void* data = lock(); std::memcpy(data, resourceData.data, resourceData.size); unlock(); - return true; + return true; } void* UniformBuffer::lock(bool bWriteOnly) { - if(dedicatedStagingBuffer != nullptr) - { - return dedicatedStagingBuffer->getMappedPointer(); - } - return ShaderBuffer::lock(bWriteOnly); + if(dedicatedStagingBuffer != nullptr) + { + return dedicatedStagingBuffer->getMappedPointer(); + } + return ShaderBuffer::lock(bWriteOnly); } void UniformBuffer::unlock() { - if(dedicatedStagingBuffer != nullptr) - { - dedicatedStagingBuffer->flushMappedMemory(); - PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); - VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); + if(dedicatedStagingBuffer != nullptr) + { + dedicatedStagingBuffer->flushMappedMemory(); + PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); + VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); - VkBufferCopy region; - std::memset(®ion, 0, sizeof(VkBufferCopy)); - region.size = ShaderBuffer::size; - vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); - graphics->getQueueCommands(currentOwner)->submitCommands(); - } - else - { - ShaderBuffer::unlock(); - } + VkBufferCopy region; + std::memset(®ion, 0, sizeof(VkBufferCopy)); + region.size = ShaderBuffer::size; + vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); + graphics->getQueueCommands(currentOwner)->submitCommands(); + } + else + { + ShaderBuffer::unlock(); + } } void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { - Gfx::QueueOwnedResource::transferOwnership(newOwner); + Gfx::QueueOwnedResource::transferOwnership(newOwner); } void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); + Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, @@ -346,24 +346,24 @@ void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineSt VkAccessFlags UniformBuffer::getSourceAccessMask() { - return VK_ACCESS_MEMORY_WRITE_BIT; + return VK_ACCESS_MEMORY_WRITE_BIT; } VkAccessFlags UniformBuffer::getDestAccessMask() { - return VK_ACCESS_UNIFORM_READ_BIT; + return VK_ACCESS_UNIFORM_READ_BIT; } StructuredBuffer::StructuredBuffer(PGraphics graphics, const StructuredBufferCreateInfo &resourceData) - : Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.resourceData) - , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, resourceData.bDynamic) + : Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.resourceData) + , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, currentOwner, resourceData.bDynamic) { - if (resourceData.resourceData.data != nullptr) - { - void *data = lock(); - std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); - unlock(); - } + if (resourceData.resourceData.data != nullptr) + { + void *data = lock(); + std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); + unlock(); + } } StructuredBuffer::~StructuredBuffer() @@ -373,49 +373,49 @@ StructuredBuffer::~StructuredBuffer() bool StructuredBuffer::updateContents(const BulkResourceData &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(); std::memcpy(data, resourceData.data, resourceData.size); unlock(); - return true; + return true; } void* StructuredBuffer::lock(bool bWriteOnly) { - if(dedicatedStagingBuffer != nullptr) - { - return dedicatedStagingBuffer->getMappedPointer(); - } - return ShaderBuffer::lock(bWriteOnly); + if(dedicatedStagingBuffer != nullptr) + { + return dedicatedStagingBuffer->getMappedPointer(); + } + return ShaderBuffer::lock(bWriteOnly); } void StructuredBuffer::unlock() { - if(dedicatedStagingBuffer != nullptr) - { - dedicatedStagingBuffer->flushMappedMemory(); - PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); - VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); + if(dedicatedStagingBuffer != nullptr) + { + dedicatedStagingBuffer->flushMappedMemory(); + PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); + VkCommandBuffer cmdHandle = cmdBuffer->getHandle(); - VkBufferCopy region; - std::memset(®ion, 0, sizeof(VkBufferCopy)); - region.size = ShaderBuffer::size; - vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); - graphics->getQueueCommands(currentOwner)->submitCommands(); - } - else - { - ShaderBuffer::unlock(); - } + VkBufferCopy region; + std::memset(®ion, 0, sizeof(VkBufferCopy)); + region.size = ShaderBuffer::size; + vkCmdCopyBuffer(cmdHandle, dedicatedStagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion); + graphics->getQueueCommands(currentOwner)->submitCommands(); + } + else + { + ShaderBuffer::unlock(); + } } void StructuredBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { - Gfx::QueueOwnedResource::transferOwnership(newOwner); + Gfx::QueueOwnedResource::transferOwnership(newOwner); } void StructuredBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); + Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } void StructuredBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, @@ -426,24 +426,24 @@ void StructuredBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelin VkAccessFlags StructuredBuffer::getSourceAccessMask() { - return VK_ACCESS_MEMORY_WRITE_BIT; + return VK_ACCESS_MEMORY_WRITE_BIT; } VkAccessFlags StructuredBuffer::getDestAccessMask() { - return VK_ACCESS_MEMORY_READ_BIT; + return VK_ACCESS_MEMORY_READ_BIT; } VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData) - : Gfx::VertexBuffer(graphics->getFamilyMapping(), resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner) - , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner) + : Gfx::VertexBuffer(graphics->getFamilyMapping(), resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner) + , Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, currentOwner) { - if (resourceData.resourceData.data != nullptr) - { - void *data = lock(); - std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); - unlock(); - } + if (resourceData.resourceData.data != nullptr) + { + void *data = lock(); + std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); + unlock(); + } } VertexBuffer::~VertexBuffer() @@ -452,12 +452,12 @@ VertexBuffer::~VertexBuffer() void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { - Gfx::QueueOwnedResource::transferOwnership(newOwner); + Gfx::QueueOwnedResource::transferOwnership(newOwner); } void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); + Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, @@ -468,24 +468,24 @@ void VertexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineSta VkAccessFlags VertexBuffer::getSourceAccessMask() { - return VK_ACCESS_MEMORY_WRITE_BIT; + return VK_ACCESS_MEMORY_WRITE_BIT; } VkAccessFlags VertexBuffer::getDestAccessMask() { - return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; + return VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; } IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData) - : 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) + : 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) { - if (resourceData.resourceData.data != nullptr) - { - void *data = lock(); - std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); - unlock(); - } + if (resourceData.resourceData.data != nullptr) + { + void *data = lock(); + std::memcpy(data, resourceData.resourceData.data, resourceData.resourceData.size); + unlock(); + } } IndexBuffer::~IndexBuffer() @@ -494,12 +494,12 @@ IndexBuffer::~IndexBuffer() void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { - Gfx::QueueOwnedResource::transferOwnership(newOwner); + Gfx::QueueOwnedResource::transferOwnership(newOwner); } void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); + Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlags srcStage, @@ -510,10 +510,10 @@ void IndexBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineStag VkAccessFlags IndexBuffer::getSourceAccessMask() { - return VK_ACCESS_MEMORY_WRITE_BIT; + return VK_ACCESS_MEMORY_WRITE_BIT; } VkAccessFlags IndexBuffer::getDestAccessMask() { - return VK_ACCESS_INDEX_READ_BIT; + return VK_ACCESS_INDEX_READ_BIT; } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp index b28da6f..9761db2 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp @@ -16,16 +16,13 @@ using namespace Seele::Vulkan; CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferManager manager) : graphics(graphics) , manager(manager) - , renderPass(nullptr) - , framebuffer(nullptr) - , subpassIndex(0) , owner(cmdPool) { VkCommandBufferAllocateInfo allocInfo = init::CommandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); - std::unique_lock lock(handleLock); + std::scoped_lock lock(handleLock); VK_CHECK(vkAllocateCommandBuffers(graphics->getDevice(), &allocInfo, &handle)) fence = new Fence(graphics); @@ -34,10 +31,8 @@ CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferMa CmdBuffer::~CmdBuffer() { - std::unique_lock lock(handleLock); + std::scoped_lock lock(handleLock); vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle); - renderPass = nullptr; - framebuffer = nullptr; waitSemaphores.clear(); } @@ -46,24 +41,22 @@ void CmdBuffer::begin() VkCommandBufferBeginInfo beginInfo = init::CommandBufferBeginInfo(); beginInfo.pInheritanceInfo = nullptr; - std::unique_lock lock(handleLock); + std::scoped_lock lock(handleLock); VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo)); state = State::InsideBegin; } void CmdBuffer::end() { - std::unique_lock lock(handleLock); + std::scoped_lock lock(handleLock); VK_CHECK(vkEndCommandBuffer(handle)); state = State::Ended; } -void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFramebuffer) +void CmdBuffer::beginRenderPass(PRenderPass renderPass, PFramebuffer framebuffer) { assert(state == State::InsideBegin); - std::unique_lock lock(handleLock); - renderPass = newRenderPass; - framebuffer = newFramebuffer; + std::scoped_lock lock(handleLock); VkRenderPassBeginInfo beginInfo = init::RenderPassBeginInfo(); @@ -74,15 +67,13 @@ void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFrame beginInfo.framebuffer = framebuffer->getHandle(); vkCmdBeginRenderPass(handle, &beginInfo, renderPass->getSubpassContents()); state = State::RenderPassActive; - //std::cout << "Beginning renderPass" << std::endl; } void CmdBuffer::endRenderPass() { - std::unique_lock lock(handleLock); + std::scoped_lock lock(handleLock); vkCmdEndRenderPass(handle); state = State::InsideBegin; - //std::cout << "Ending renderPass" << std::endl; } void CmdBuffer::executeCommands(const Array& commands) @@ -90,9 +81,10 @@ void CmdBuffer::executeCommands(const Array& commands) assert(state == State::RenderPassActive); if(commands.size() == 0) { + std::cout << "No commands provided" << std::endl; return; } - std::unique_lock lock(handleLock); + std::scoped_lock lock(handleLock); Array cmdBuffers(commands.size()); for (uint32 i = 0; i < commands.size(); ++i) { @@ -111,7 +103,7 @@ void CmdBuffer::executeCommands(const Array& commands) void CmdBuffer::executeCommands(const Array& commands) { - std::unique_lock lock(handleLock); + std::scoped_lock lock(handleLock); if(commands.size() == 0) { return; @@ -134,14 +126,14 @@ void CmdBuffer::executeCommands(const Array& commands) void CmdBuffer::addWaitSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore) { - std::unique_lock lock(handleLock); + std::scoped_lock lock(handleLock); waitSemaphores.add(semaphore); waitFlags.add(flags); } void CmdBuffer::refreshFence() { - std::unique_lock lock(handleLock); + std::scoped_lock lock(handleLock); if (state == State::Submitted) { if (fence->isSignaled()) @@ -174,7 +166,7 @@ void CmdBuffer::refreshFence() void CmdBuffer::waitForCommand(uint32 timeout) { - std::unique_lock lock(handleLock); + std::scoped_lock lock(handleLock); fence->wait(timeout); refreshFence(); } @@ -212,7 +204,7 @@ RenderCommand::~RenderCommand() vkFreeCommandBuffers(graphics->getDevice(), owner, 1, &handle); } -void RenderCommand::begin(PCmdBuffer parent) +void RenderCommand::begin(PRenderPass renderPass, PFramebuffer framebuffer) { threadId = std::this_thread::get_id(); ready = false; @@ -220,9 +212,9 @@ void RenderCommand::begin(PCmdBuffer parent) init::CommandBufferBeginInfo(); VkCommandBufferInheritanceInfo inheritanceInfo = init::CommandBufferInheritanceInfo(); - inheritanceInfo.framebuffer = parent->framebuffer->getHandle(); - inheritanceInfo.renderPass = parent->renderPass->getHandle(); - inheritanceInfo.subpass = parent->subpassIndex; + inheritanceInfo.framebuffer = framebuffer->getHandle(); + inheritanceInfo.renderPass = renderPass->getHandle(); + inheritanceInfo.subpass = 0; beginInfo.pInheritanceInfo = &inheritanceInfo; beginInfo.flags = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; VK_CHECK(vkBeginCommandBuffer(handle, &beginInfo)); @@ -230,13 +222,11 @@ void RenderCommand::begin(PCmdBuffer parent) void RenderCommand::end() { - assert(threadId == std::this_thread::get_id()); VK_CHECK(vkEndCommandBuffer(handle)); } void RenderCommand::reset() { - assert(threadId == std::this_thread::get_id()); vkResetCommandBuffer(handle, VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT); boundDescriptors.clear(); ready = true; @@ -420,7 +410,7 @@ CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue) activeCmdBuffer = new CmdBuffer(graphics, commandPool, this); activeCmdBuffer->begin(); - std::unique_lock lock(allocatedBufferLock); + std::scoped_lock lock(allocatedBufferLock); allocatedBuffers.add(activeCmdBuffer); } @@ -436,29 +426,29 @@ PCmdBuffer CommandBufferManager::getCommands() return activeCmdBuffer; } -PRenderCommand CommandBufferManager::createRenderCommand(const std::string& name) +PRenderCommand CommandBufferManager::createRenderCommand(PRenderPass renderPass, PFramebuffer framebuffer, const std::string& name) { - std::unique_lock lck(allocatedRenderLock); + std::scoped_lock lck(allocatedRenderLock); for (uint32 i = 0; i < allocatedRenderCommands.size(); ++i) { PRenderCommand cmdBuffer = allocatedRenderCommands[i]; if (cmdBuffer->isReady()) { cmdBuffer->name = name; - cmdBuffer->begin(activeCmdBuffer); + cmdBuffer->begin(renderPass, framebuffer); return cmdBuffer; } } PRenderCommand result = new RenderCommand(graphics, commandPool); result->name = name; - result->begin(activeCmdBuffer); + result->begin(renderPass, framebuffer); allocatedRenderCommands.add(result); return result; } PComputeCommand CommandBufferManager::createComputeCommand(const std::string& name) { - std::unique_lock lck(allocatedComputeLock); + std::scoped_lock lck(allocatedComputeLock); for (uint32 i = 0; i < allocatedComputeCommands.size(); ++i) { PComputeCommand cmdBuffer = allocatedComputeCommands[i]; @@ -495,7 +485,7 @@ void CommandBufferManager::submitCommands(PSemaphore signalSemaphore) queue->submitCommandBuffer(activeCmdBuffer); } } - std::unique_lock lock(allocatedBufferLock); + std::scoped_lock lock(allocatedBufferLock); for (uint32 i = 0; i < allocatedBuffers.size(); ++i) { PCmdBuffer cmdBuffer = allocatedBuffers[i]; diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h index dad4831..59aee44 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h @@ -47,10 +47,7 @@ public: private: PGraphics graphics; PCommandBufferManager manager; - PRenderPass renderPass; - PFramebuffer framebuffer; PFence fence; - uint32 subpassIndex; State state; VkViewport currentViewport; VkRect2D currentScissor; @@ -79,7 +76,7 @@ public: { return handle; } - void begin(PCmdBuffer parent); + void begin(PRenderPass renderPass, PFramebuffer framebuffer); void end(); void reset(); virtual bool isReady() override; @@ -145,7 +142,7 @@ public: return queue; } PCmdBuffer getCommands(); - PRenderCommand createRenderCommand(const std::string& name); + PRenderCommand createRenderCommand(PRenderPass renderPass, PFramebuffer framebuffer, const std::string& name); PComputeCommand createComputeCommand(const std::string& name); VkCommandPool getPoolHandle() const { diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp index 7d2b5fb..db06c23 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp @@ -54,7 +54,7 @@ PipelineLayout::~PipelineLayout() { if (layoutHandle != VK_NULL_HANDLE) { - vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr); + //vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr); } } diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h index a13b489..3d997c8 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h @@ -29,12 +29,12 @@ DEFINE_REF(DescriptorLayout) class PipelineLayout : public Gfx::PipelineLayout { public: - PipelineLayout(PGraphics graphics) - : graphics(graphics) + PipelineLayout(PGraphics graphics, Gfx::PPipelineLayout baseLayout) + : Gfx::PipelineLayout(baseLayout) + , graphics(graphics) , layoutHash(0) , layoutHandle(VK_NULL_HANDLE) - { - } + {} virtual ~PipelineLayout(); virtual void create(); virtual void reset(); diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp index 2a8d98d..9096b7e 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp @@ -14,6 +14,11 @@ using namespace Seele::Vulkan; +thread_local PCommandBufferManager Seele::Vulkan::Graphics::graphicsCommands = nullptr; +thread_local PCommandBufferManager Seele::Vulkan::Graphics::computeCommands = nullptr; +thread_local PCommandBufferManager Seele::Vulkan::Graphics::transferCommands = nullptr; +thread_local PCommandBufferManager Seele::Vulkan::Graphics::dedicatedTransferCommands = nullptr; + Graphics::Graphics() : instance(VK_NULL_HANDLE) , handle(VK_NULL_HANDLE) @@ -52,7 +57,7 @@ Gfx::PWindow Graphics::createWindow(const WindowCreateInfo &createInfo) Gfx::PViewport Graphics::createViewport(Gfx::PWindow owner, const ViewportCreateInfo &viewportInfo) { PViewport result = new Viewport(this, owner, viewportInfo); - std::unique_lock lock(viewportLock); + std::scoped_lock lock(viewportLock); viewports.add(result); return result; } @@ -67,7 +72,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) uint32 framebufferHash = rp->getFramebufferHash(); PFramebuffer framebuffer; { - std::unique_lock lock(allocatedFrameBufferLock); + std::scoped_lock lock(allocatedFrameBufferLock); auto found = allocatedFramebuffers.find(framebufferHash); if (found == allocatedFramebuffers.end()) { @@ -80,12 +85,18 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) } } getGraphicsCommands()->getCommands()->beginRenderPass(rp, framebuffer); + std::scoped_lock lock(renderPassLock); + activeRenderPass = rp; + activeFramebuffer = framebuffer; } void Graphics::endRenderPass() { getGraphicsCommands()->getCommands()->endRenderPass(); getGraphicsCommands()->submitCommands(); + std::scoped_lock lock(renderPassLock); + activeRenderPass = nullptr; + activeFramebuffer = nullptr; } void Graphics::executeCommands(const Array& commands) @@ -128,7 +139,7 @@ Gfx::PIndexBuffer Graphics::createIndexBuffer(const IndexBufferCreateInfo &bulkD } Gfx::PRenderCommand Graphics::createRenderCommand(const std::string& name) { - PRenderCommand cmdBuffer = getGraphicsCommands()->createRenderCommand(name); + PRenderCommand cmdBuffer = getGraphicsCommands()->createRenderCommand(activeRenderPass, activeFramebuffer, name); return cmdBuffer; } @@ -206,9 +217,9 @@ Gfx::PDescriptorLayout Graphics::createDescriptorLayout(const std::string& name) PDescriptorLayout layout = new DescriptorLayout(this, name); return layout; } -Gfx::PPipelineLayout Graphics::createPipelineLayout() +Gfx::PPipelineLayout Graphics::createPipelineLayout(Gfx::PPipelineLayout baseLayout) { - PPipelineLayout layout = new PipelineLayout(this); + PPipelineLayout layout = new PipelineLayout(this, baseLayout); return layout; } @@ -295,49 +306,37 @@ PCommandBufferManager Graphics::getQueueCommands(Gfx::QueueType queueType) throw new std::logic_error("invalid queue type"); } } -std::mutex graphicsCommandLock; PCommandBufferManager Graphics::getGraphicsCommands() { - std::unique_lock lock(graphicsCommandLock); - auto id = std::this_thread::get_id(); - if(graphicsCommands.find(id) == graphicsCommands.end()) + if(graphicsCommands == nullptr) { - graphicsCommands[id] = new CommandBufferManager(this, graphicsQueue); + graphicsCommands = new CommandBufferManager(this, graphicsQueue); } - return graphicsCommands[id]; + return graphicsCommands; } -std::mutex computeCommandLock; PCommandBufferManager Graphics::getComputeCommands() { - std::unique_lock lock(computeCommandLock); - auto id = std::this_thread::get_id(); - if(computeCommands.find(id) == computeCommands.end()) + if(computeCommands == nullptr) { - computeCommands[id] = new CommandBufferManager(this, computeQueue); + computeCommands = new CommandBufferManager(this, computeQueue); } - return computeCommands[id]; + return computeCommands; } -std::mutex transferCommandLock; PCommandBufferManager Graphics::getTransferCommands() { - std::unique_lock lock(transferCommandLock); - auto id = std::this_thread::get_id(); - if(transferCommands.find(id) == transferCommands.end()) + if(transferCommands == nullptr) { - transferCommands[id] = new CommandBufferManager(this, transferQueue); + transferCommands = new CommandBufferManager(this, transferQueue); } - return transferCommands[id]; + return transferCommands; } -std::mutex dedicatedCommandLock; PCommandBufferManager Graphics::getDedicatedTransferCommands() { - std::unique_lock lock(dedicatedCommandLock); - auto id = std::this_thread::get_id(); - if(dedicatedTransferCommands.find(id) == dedicatedTransferCommands.end()) + if(dedicatedTransferCommands == dedicatedTransferCommands) { - dedicatedTransferCommands[id] = new CommandBufferManager(this, dedicatedTransferQueue); + dedicatedTransferCommands = new CommandBufferManager(this, dedicatedTransferQueue); } - return dedicatedTransferCommands[id]; + return dedicatedTransferCommands; } PAllocator Graphics::getAllocator() { diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.h b/src/Engine/Graphics/Vulkan/VulkanGraphics.h index 4dcd5f1..5a57c34 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.h @@ -11,6 +11,7 @@ DECLARE_REF(Allocator) DECLARE_REF(StagingManager) DECLARE_REF(CommandBufferManager) DECLARE_REF(Queue) +DECLARE_REF(RenderPass) DECLARE_REF(Framebuffer) DECLARE_REF(RenderCommand) DECLARE_REF(PipelineCache) @@ -63,7 +64,7 @@ public: virtual Gfx::PSamplerState createSamplerState(const SamplerCreateInfo& createInfo) override; virtual Gfx::PDescriptorLayout createDescriptorLayout(const std::string& name = "") override; - virtual Gfx::PPipelineLayout createPipelineLayout() override; + virtual Gfx::PPipelineLayout createPipelineLayout(Gfx::PPipelineLayout baseLayout = nullptr) override; virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override; protected: @@ -82,10 +83,13 @@ protected: PQueue transferQueue; PQueue dedicatedTransferQueue; PPipelineCache pipelineCache; - Map graphicsCommands; - Map computeCommands; - Map transferCommands; - Map dedicatedTransferCommands; + std::mutex renderPassLock; + PRenderPass activeRenderPass; + PFramebuffer activeFramebuffer; + thread_local static PCommandBufferManager graphicsCommands; + thread_local static PCommandBufferManager computeCommands; + thread_local static PCommandBufferManager transferCommands; + thread_local static PCommandBufferManager dedicatedTransferCommands; VkPhysicalDeviceProperties props; VkPhysicalDeviceFeatures features; VkDebugReportCallbackEXT callback; diff --git a/src/Engine/Graphics/Vulkan/VulkanInitializer.cpp b/src/Engine/Graphics/Vulkan/VulkanInitializer.cpp index 30f00f6..fb2b9b1 100644 --- a/src/Engine/Graphics/Vulkan/VulkanInitializer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanInitializer.cpp @@ -296,6 +296,8 @@ VkBufferMemoryBarrier init::BufferMemoryBarrier() VkBufferMemoryBarrier bufferMemoryBarrier = {}; bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; bufferMemoryBarrier.pNext = NULL; + bufferMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + bufferMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; return bufferMemoryBarrier; } diff --git a/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp index 47b64dc..de59b04 100644 --- a/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp @@ -323,7 +323,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo uint32 hash = crc.checksum(); VkPipeline pipelineHandle; - std::unique_lock lock(createdPipelinesLock); + std::scoped_lock lock(createdPipelinesLock); auto foundPipeline = createdPipelines.find(hash); if (foundPipeline != createdPipelines.end()) { diff --git a/src/Engine/Graphics/Vulkan/VulkanQueue.cpp b/src/Engine/Graphics/Vulkan/VulkanQueue.cpp index 350fbbe..4dae95e 100644 --- a/src/Engine/Graphics/Vulkan/VulkanQueue.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanQueue.cpp @@ -22,7 +22,7 @@ Queue::~Queue() void Queue::submitCommandBuffer(PCmdBuffer cmdBuffer, uint32 numSignalSemaphores, VkSemaphore *signalSemaphores) { - std::unique_lock lck(queueLock); + std::scoped_lock lck(queueLock); assert(cmdBuffer->state == CmdBuffer::State::Ended); PFence fence = cmdBuffer->fence; diff --git a/src/Engine/Material/MaterialAsset.cpp b/src/Engine/Material/MaterialAsset.cpp index 78bb2e7..103c7af 100644 --- a/src/Engine/Material/MaterialAsset.cpp +++ b/src/Engine/Material/MaterialAsset.cpp @@ -185,6 +185,6 @@ const Gfx::ShaderCollection* MaterialAsset::getShaders(Gfx::RenderPassType rende Gfx::ShaderCollection& MaterialAsset::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput) { - std::unique_lock lock(shaderMapLock); + std::scoped_lock lock(shaderMapLock); return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false); } diff --git a/src/Engine/MinimalEngine.h b/src/Engine/MinimalEngine.h index 21fdaa9..4848c94 100644 --- a/src/Engine/MinimalEngine.h +++ b/src/Engine/MinimalEngine.h @@ -49,7 +49,7 @@ public: ~RefObject() { { - std::unique_lock lock(registeredObjectsLock); + std::scoped_lock lock(registeredObjectsLock); registeredObjects.erase(handle); } // #pragma warning( disable: 4150) @@ -114,7 +114,7 @@ public: } RefPtr(T *ptr, Deleter deleter = Deleter()) { - std::unique_lock l(registeredObjectsLock); + std::scoped_lock l(registeredObjectsLock); auto registeredObj = registeredObjects.find(ptr); // get here for thread safetly auto registeredEnd = registeredObjects.end(); @@ -249,6 +249,10 @@ public: { return object->getHandle(); } + RefPtr clone() + { + return RefPtr(new T(*getHandle())); + } private: RefObject *object; diff --git a/src/Engine/Scene/Actor/Actor.cpp b/src/Engine/Scene/Actor/Actor.cpp index dcc7dba..0dc19e8 100644 --- a/src/Engine/Scene/Actor/Actor.cpp +++ b/src/Engine/Scene/Actor/Actor.cpp @@ -12,8 +12,36 @@ Actor::~Actor() { } -void Actor::tick(float) + +void Actor::launchStart() { + rootComponent->launchStart(); + for(auto child : children) + { + child->launchStart(); + } + start(); +} +Array Actor::launchTick(float deltaTime) const +{ + Array result = rootComponent->launchTick(deltaTime); + for(auto child : children) + { + result.addAll(child->launchTick(deltaTime)); + } + result.add(tick(deltaTime)); + return result; +} + +Array Actor::launchUpdate() +{ + Array result = rootComponent->launchUpdate(); + for(auto child : children) + { + result.addAll(child->launchUpdate()); + } + result.add(update()); + return result; } void Actor::notifySceneAttach(PScene scene) { diff --git a/src/Engine/Scene/Actor/Actor.h b/src/Engine/Scene/Actor/Actor.h index 5080b8a..424ee1e 100644 --- a/src/Engine/Scene/Actor/Actor.h +++ b/src/Engine/Scene/Actor/Actor.h @@ -1,6 +1,7 @@ #pragma once #include "MinimalEngine.h" #include "Math/Transform.h" +#include "ThreadPool.h" namespace Seele { @@ -12,8 +13,12 @@ class Actor public: Actor(); virtual ~Actor(); - - void tick(float deltaTime); + virtual void launchStart(); + virtual void start() {} + Array launchTick(float deltaTime) const; + virtual Job tick(float deltaTime) const { co_return; } + Array launchUpdate(); + virtual Job update() { co_return; } void notifySceneAttach(PScene scene); PScene getScene(); diff --git a/src/Engine/Scene/CMakeLists.txt b/src/Engine/Scene/CMakeLists.txt index a592c30..1d102c6 100644 --- a/src/Engine/Scene/CMakeLists.txt +++ b/src/Engine/Scene/CMakeLists.txt @@ -1,5 +1,6 @@ target_sources(SeeleEngine PRIVATE + Util.h Scene.cpp Scene.h) diff --git a/src/Engine/Scene/Components/CMakeLists.txt b/src/Engine/Scene/Components/CMakeLists.txt index fb05eb3..15bd041 100644 --- a/src/Engine/Scene/Components/CMakeLists.txt +++ b/src/Engine/Scene/Components/CMakeLists.txt @@ -4,6 +4,10 @@ target_sources(SeeleEngine CameraComponent.cpp Component.h Component.cpp + MyComponent.h + MyComponent.cpp + MyOtherComponent.h + MyOtherComponent.cpp PrimitiveComponent.cpp PrimitiveComponent.h PrimitiveUniformBufferLayout.h) \ No newline at end of file diff --git a/src/Engine/Scene/Components/CameraComponent.cpp b/src/Engine/Scene/Components/CameraComponent.cpp index c6fad56..e876562 100644 --- a/src/Engine/Scene/Components/CameraComponent.cpp +++ b/src/Engine/Scene/Components/CameraComponent.cpp @@ -5,11 +5,16 @@ using namespace Seele; -CameraComponent::CameraComponent() - : bNeedsViewBuild(true) +CameraComponent::CameraComponent() + : aspectRatio(0) + , fieldOfView(0) + , bNeedsViewBuild(true) , bNeedsProjectionBuild(true) , originPoint(0, 0, 0) , cameraPosition(0, 0, 50) + , eye(Vector()) + , projectionMatrix(Matrix4()) + , viewMatrix(Matrix4()) { distance = 50; rotationX = 0; diff --git a/src/Engine/Scene/Components/Component.cpp b/src/Engine/Scene/Components/Component.cpp index b0be1b8..b97785f 100644 --- a/src/Engine/Scene/Components/Component.cpp +++ b/src/Engine/Scene/Components/Component.cpp @@ -13,9 +13,38 @@ Component::Component() Component::~Component() { } -void Component::tick(float) + +void Component::launchStart() { + for(auto child : children) + { + child->launchStart(); + } + start(); } + +Array Component::launchTick(float deltaTime) const +{ + Array result; + for(auto child : children) + { + result.addAll(child->launchTick(deltaTime)); + } + result.add(tick(deltaTime)); + return result; +} + +Array Component::launchUpdate() +{ + Array result; + for(auto child : children) + { + result.addAll(child->launchUpdate()); + } + result.add(update()); + return result; +} + PComponent Component::getParent() { return parent; @@ -32,6 +61,25 @@ PActor Component::getOwner() } return nullptr; } +const Array& Component::getChildComponents() +{ + return children; +} + +void Component::setParent(PComponent newParent) +{ + parent = newParent; +} + +void Component::setOwner(PActor newOwner) +{ + owner = newOwner; +} + +void Component::addChildComponent(PComponent component) +{ + children.add(component); +} void Component::notifySceneAttach(PScene scene) { @@ -118,16 +166,6 @@ Transform Component::getTransform() const return transform; } -void Component::setParent(PComponent newParent) -{ - parent = newParent; -} - -void Component::setOwner(PActor newOwner) -{ - owner = newOwner; -} - void Component::internalSetTransform(Vector newLocation, Quaternion newRotation) { if (parent != nullptr) diff --git a/src/Engine/Scene/Components/Component.h b/src/Engine/Scene/Components/Component.h index b1062ad..95dae38 100644 --- a/src/Engine/Scene/Components/Component.h +++ b/src/Engine/Scene/Components/Component.h @@ -1,6 +1,8 @@ #pragma once #include "MinimalEngine.h" #include "Math/Transform.h" +#include "Scene/Util.h" +#include "ThreadPool.h" namespace Seele { @@ -12,11 +14,18 @@ class Component public: Component(); virtual ~Component(); - void tick(float deltaTime); + void launchStart(); + virtual void start() {}; + Array launchTick(float deltaTime) const; + virtual Job tick(float deltaTime) const { co_return; } + Array launchUpdate(); + virtual Job update() { co_return; } PComponent getParent(); PActor getOwner(); + const Array& getChildComponents(); void setParent(PComponent parent); void setOwner(PActor owner); + void addChildComponent(PComponent component); virtual void notifySceneAttach(PScene scene); void setWorldLocation(Vector location); @@ -35,7 +44,30 @@ public: Transform getTransform() const; + template + RefPtr getComponent() + { + return tryFindComponent(); + } private: + template + RefPtr tryFindComponent() + { + for(auto child : children) + { + RefPtr result = child.cast(); + if(result != nullptr) + { + return result; + } + result = parent->tryFindComponent(); + if(result != nullptr) + { + return result; + } + } + return nullptr; + } void internalSetTransform(Vector newLocation, Quaternion newRotation); void propagateTransformUpdate(); void updateComponentTransform(Quaternion relativeRotationQuat); diff --git a/src/Engine/Scene/Components/MyComponent.cpp b/src/Engine/Scene/Components/MyComponent.cpp new file mode 100644 index 0000000..9d75e23 --- /dev/null +++ b/src/Engine/Scene/Components/MyComponent.cpp @@ -0,0 +1,26 @@ +#include "MyComponent.h" + +using namespace Seele; + +MyComponent::MyComponent() +{ +} + +void MyComponent::start() +{ + otherComp = getComponent(); + otherComp.update(); +} + +Job MyComponent::tick(float deltatime) const +{ + writable++; + otherComp->data = *writable; + co_return; +} + +Job MyComponent::update() +{ + writable.update(); + co_return; +} diff --git a/src/Engine/Scene/Components/MyComponent.h b/src/Engine/Scene/Components/MyComponent.h new file mode 100644 index 0000000..0e5fa0c --- /dev/null +++ b/src/Engine/Scene/Components/MyComponent.h @@ -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 otherComp; + Writable writable = Writable(0); + uint32 notWritable = 10; +}; +DECLARE_REF(MyComponent); +} // namespace Seele diff --git a/src/Engine/Scene/Components/MyOtherComponent.cpp b/src/Engine/Scene/Components/MyOtherComponent.cpp new file mode 100644 index 0000000..e930585 --- /dev/null +++ b/src/Engine/Scene/Components/MyOtherComponent.cpp @@ -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; +} diff --git a/src/Engine/Scene/Components/MyOtherComponent.h b/src/Engine/Scene/Components/MyOtherComponent.h new file mode 100644 index 0000000..51793ad --- /dev/null +++ b/src/Engine/Scene/Components/MyOtherComponent.h @@ -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 data = Writable(0); +private: +}; +DEFINE_REF(MyOtherComponent); +} // namespace Seele diff --git a/src/Engine/Scene/Components/PrimitiveComponent.cpp b/src/Engine/Scene/Components/PrimitiveComponent.cpp index 3d11d30..aefba4d 100644 --- a/src/Engine/Scene/Components/PrimitiveComponent.cpp +++ b/src/Engine/Scene/Components/PrimitiveComponent.cpp @@ -26,7 +26,7 @@ PrimitiveComponent::PrimitiveComponent(PMeshAsset asset) batch.useReverseCulling = false; batch.useWireframe = false; batch.vertexInput = assetMeshes[i]->vertexInput; - auto& batchElement = batch.elements.add(); + MeshBatchElement batchElement; batchElement.baseVertexIndex = 0; batchElement.firstIndex = 0; batchElement.indexBuffer = assetMeshes[i]->indexBuffer; @@ -35,6 +35,7 @@ PrimitiveComponent::PrimitiveComponent(PMeshAsset asset) batchElement.isInstanced = false; batchElement.numInstances = 1; batchElement.numPrimitives = assetMeshes[i]->indexBuffer->getNumIndices() / 3; //TODO: hardcoded + batch.elements.push_back(batchElement); } } diff --git a/src/Engine/Scene/Components/PrimitiveComponent.h b/src/Engine/Scene/Components/PrimitiveComponent.h index 9a42ef2..1e17932 100644 --- a/src/Engine/Scene/Components/PrimitiveComponent.h +++ b/src/Engine/Scene/Components/PrimitiveComponent.h @@ -16,14 +16,14 @@ public: ~PrimitiveComponent(); virtual void notifySceneAttach(PScene scene) override; Matrix4 getRenderMatrix(); - const Array& getStaticMeshes() + std::vector& getStaticMeshes() { return staticMeshes; } private: - Array materials; + std::vector materials; Gfx::PUniformBuffer uniformBuffer; - Array staticMeshes; + std::vector staticMeshes; friend class Scene; }; DEFINE_REF(PrimitiveComponent) diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index be75c53..ce5778b 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -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(deltaTime))); + } +} + +Job Scene::commitUpdate() +{ + for(auto actor : rootActors) + { + co_await Job::all(actor->launchUpdate()); + } } void Scene::addActor(PActor actor) { - rootActors.add(actor); + rootActors.push_back(actor); actor->notifySceneAttach(this); } void Scene::addPrimitiveComponent(PPrimitiveComponent comp) { - primitives.add(comp); + primitives.push_back(comp); for(auto& batch : comp->getStaticMeshes()) { PrimitiveUniformBuffer data; @@ -62,6 +82,6 @@ void Scene::addPrimitiveComponent(PPrimitiveComponent comp) { element.uniformBuffer = uniformBuffer; } - staticMeshes.add(batch); + staticMeshes.push_back(batch); } } diff --git a/src/Engine/Scene/Scene.h b/src/Engine/Scene/Scene.h index d023eca..cdd491e 100644 --- a/src/Engine/Scene/Scene.h +++ b/src/Engine/Scene/Scene.h @@ -38,17 +38,19 @@ class Scene public: Scene(Gfx::PGraphics graphics); ~Scene(); - void tick(double deltaTime); + void start(); + Job beginUpdate(double deltaTime); + Job commitUpdate(); void addActor(PActor actor); void addPrimitiveComponent(PPrimitiveComponent comp); - const Array& getPrimitives() const { return primitives; } - const Array& getStaticMeshes() const { return staticMeshes; } + const std::vector& getPrimitives() const { return primitives; } + const std::vector& getStaticMeshes() const { return staticMeshes; } const LightEnv& getLightBuffer() const { return lightEnv; } private: - Array staticMeshes; - Array rootActors; - Array primitives; + std::vector staticMeshes; + std::vector rootActors; + std::vector primitives; LightEnv lightEnv; Gfx::PGraphics graphics; }; diff --git a/src/Engine/Scene/SceneUpdater.cpp b/src/Engine/Scene/SceneUpdater.cpp index a5f0879..98991ba 100644 --- a/src/Engine/Scene/SceneUpdater.cpp +++ b/src/Engine/Scene/SceneUpdater.cpp @@ -26,25 +26,25 @@ SceneUpdater::~SceneUpdater() void SceneUpdater::registerComponentUpdate(PComponent component) { - std::unique_lock lck(pendingUpdatesLock); + std::scoped_lock lck(pendingUpdatesLock); updatesRan.add([component](float delta) mutable { component->tick(delta); }); } void SceneUpdater::registerActorUpdate(PActor actor) { - std::unique_lock lck(pendingUpdatesLock); + std::scoped_lock lck(pendingUpdatesLock); updatesRan.add([actor](float delta) mutable { actor->tick(delta); }); } void SceneUpdater::runUpdates(float delta) { - std::unique_lock pendingLock(pendingUpdatesLock); + std::scoped_lock pendingLock(pendingUpdatesLock); frameDelta = delta; pendingUpdates = std::move(updatesRan); updatesRan = List>(); - std::unique_lock lck(frameFinishedLock); + std::scoped_lock lck(frameFinishedLock); pendingLock.unlock(); pendingUpdatesSem.release(pendingUpdates.size()); frameFinishedCV.wait(lck); @@ -57,18 +57,18 @@ void SceneUpdater::work() pendingUpdatesSem.acquire(); std::function function; { - std::unique_lock lck(pendingUpdatesLock); + std::scoped_lock lck(pendingUpdatesLock); function = std::move(pendingUpdates.front()); pendingUpdates.popFront(); if(pendingUpdates.empty()) { - std::unique_lock lck(frameFinishedLock); + std::scoped_lock lck(frameFinishedLock); frameFinishedCV.notify_all(); } } function(frameDelta); { - std::unique_lock lck(pendingUpdatesLock); + std::scoped_lock lck(pendingUpdatesLock); updatesRan.add(std::move(function)); } } diff --git a/src/Engine/Scene/Util.h b/src/Engine/Scene/Util.h new file mode 100644 index 0000000..3c8b191 --- /dev/null +++ b/src/Engine/Scene/Util.h @@ -0,0 +1,149 @@ +#pragma once +#include "MinimalEngine.h" + +namespace Seele +{ +template +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 + const Writable& operator+(Other&& other) const + { + deferWrite(data + std::forward(other)); + return *this; + } + template + const Writable& operator-(Other&& other) const + { + deferWrite(data - std::forward(other)); + return *this; + } + template + const Writable& operator*(Other&& other) const + { + deferWrite(data * std::forward(other)); + return *this; + } + template + const Writable& operator/(Other&& other) const + { + deferWrite(data / std::forward(other)); + return *this; + } + template + const Writable& operator%(Other&& other) const + { + deferWrite(data % std::forward(other)); + return *this; + } + template + const Writable& operator^(Other&& other) const + { + deferWrite(data ^ std::forward(other)); + return *this; + } + template + const Writable& operator&(Other&& other) const + { + deferWrite(data & std::forward(other)); + return *this; + } + template + const Writable& operator|(Other&& other) const + { + deferWrite(data | std::forward(other)); + return *this; + } + template + bool operator==(Type other) const + { + return data == other.data; + } + template + 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 + void deferWrite(Type&& newValue) const + { + std::scoped_lock lock(dataLock); + assert(!dirty); + toBeWritten = std::forward(newValue); + dirty = true; + } + mutable bool dirty = false; + mutable std::mutex dataLock; + mutable T toBeWritten; + T data; +}; +template +concept writable = requires(A&& a) +{ + a.update(); +}; +} // namespace Seele diff --git a/src/Engine/ThreadPool.cpp b/src/Engine/ThreadPool.cpp index 44e77e1..9638f20 100644 --- a/src/Engine/ThreadPool.cpp +++ b/src/Engine/ThreadPool.cpp @@ -6,7 +6,7 @@ using namespace Seele; std::atomic_uint64_t Seele::globalCounter; Event::Event() - : flag(new std::atomic_bool()) + : flag(std::make_shared()) { } @@ -16,7 +16,8 @@ Event::Event(nullptr_t) } Event::Event(const std::string &name) - : name(name), flag(new std::atomic_bool()) + : name(name) + , flag(std::make_shared()) { } @@ -48,75 +49,80 @@ ThreadPool::ThreadPool(uint32 threadCount) ThreadPool::~ThreadPool() { running.store(false); + { + std::scoped_lock lock(jobQueueLock); + jobQueueCV.notify_all(); + } + { + std::scoped_lock lock(mainJobLock); + mainJobCV.notify_all(); + } for (auto &thread : workers) { thread.join(); } + workers.clear(); + waitingJobs.clear(); + waitingMainJobs.clear(); } void ThreadPool::enqueueWaiting(Event &event, Promise* job) { assert(!job->done()); - if(event == nullptr) - { - std::unique_lock lock(jobQueueLock); - //std::cout << "Queueing job " << job->finishedEvent.name << std::endl; - jobQueue.add(job); - jobQueueCV.notify_one(); - } - else - { - std::unique_lock lock(waitingLock); - //std::cout << "Job " << job->finishedEvent.name << " waiting on event " << event.name << std::endl; - waitingJobs[event].add(job); - } + std::scoped_lock lock(waitingLock); + //std::cout << "Job " << job->finishedEvent.name << " waiting on event " << event.name << std::endl; + waitingJobs[event].push_back(job); } void ThreadPool::enqueueWaiting(Event &event, MainPromise* job) { assert(!job->done()); - if(event == nullptr || event) - { - std::unique_lock lock(mainJobLock); - //std::cout << "Queueing job " << job->finishedEvent.name << std::endl; - mainJobs.add(job); - mainJobCV.notify_one(); - } - else - { - std::unique_lock lock(waitingMainLock); - //std::cout << job->finishedEvent.name << " waiting on event " << event.name << std::endl; - waitingMainJobs[event].add(job); - } + std::scoped_lock lock(waitingMainLock); + //std::cout << job->finishedEvent.name << " waiting on event " << event.name << std::endl; + waitingMainJobs[event].push_back(job); +} +void ThreadPool::scheduleJob(Promise* job) +{ + assert(!job->done()); + std::scoped_lock lock(jobQueueLock); + //std::cout << "Queueing job " << job->finishedEvent.name << std::endl; + jobQueue.push_back(job); + jobQueueCV.notify_one(); +} +void ThreadPool::scheduleJob(MainPromise* job) +{ + assert(!job->done()); + std::scoped_lock lock(mainJobLock); + //std::cout << "Queueing job " << job->finishedEvent.name << std::endl; + mainJobs.push_back(job); + mainJobCV.notify_one(); } void ThreadPool::notify(Event &event) { //std::cout << "Event " << event.name << " raised" << std::endl; { - std::unique_lock lock(jobQueueLock); - std::unique_lock lock2(waitingLock); - List &jobs = waitingJobs[event]; + std::scoped_lock lock(jobQueueLock, waitingLock); + std::list jobs = std::move(waitingJobs[event]); + waitingJobs.erase(event); for (auto &job : jobs) { //assert(job.id != -1ull); //std::cout << "Waking up " << job->finishedEvent.name << std::endl; job->state = Promise::State::SCHEDULED; - jobQueue.add(job); + jobQueue.push_back(job); jobQueueCV.notify_one(); } - waitingJobs.erase(event); } { - std::unique_lock lock(mainJobLock); - std::unique_lock lock2(waitingMainLock); - List &jobs = waitingMainJobs[event]; + std::scoped_lock lock(mainJobLock, waitingMainLock); + std::list jobs = std::move(waitingMainJobs[event]); + waitingMainJobs.erase(event); for (auto &job : jobs) { //assert(job.id != -1ull); //std::cout << "Waking up main " << job->finishedEvent.name << std::endl; job->state = MainPromise::State::SCHEDULED; - mainJobs.add(job); + mainJobs.push_back(job); mainJobCV.notify_one(); } - waitingMainJobs.erase(event); } } void ThreadPool::threadLoop(const bool mainThread) @@ -134,7 +140,8 @@ void ThreadPool::threadLoop(const bool mainThread) } if (!mainJobs.empty()) { - job = mainJobs.retrieve(); + job = mainJobs.front(); + mainJobs.pop_front(); } else { @@ -144,7 +151,7 @@ void ThreadPool::threadLoop(const bool mainThread) job->resume(); if (job->done()) { - job->raise(); + job->finalize(); } } else @@ -158,7 +165,8 @@ void ThreadPool::threadLoop(const bool mainThread) } if (!jobQueue.empty()) { - job = jobQueue.retrieve(); + job = jobQueue.front(); + jobQueue.pop_front(); } else { @@ -167,9 +175,9 @@ void ThreadPool::threadLoop(const bool mainThread) } //std::cout << "Starting job " << job.id << std::endl; job->resume(); - if (job->done()) + if(job->done()) { - job->raise(); + job->finalize(); } } } diff --git a/src/Engine/ThreadPool.h b/src/Engine/ThreadPool.h index acc1751..2a908a2 100644 --- a/src/Engine/ThreadPool.h +++ b/src/Engine/ThreadPool.h @@ -16,6 +16,7 @@ public: Event(); Event(nullptr_t); Event(const std::string& name); + ~Event() = default; auto operator<=>(const Event& other) const { return flag <=> other.flag; @@ -41,7 +42,7 @@ public: constexpr void await_resume() {} private: std::string name; - RefPtr flag; + std::shared_ptr flag; friend class ThreadPool; }; @@ -65,6 +66,13 @@ struct JobPromiseBase id = globalCounter++; finishedEvent = Event(std::format("Job {}", id)); } + ~JobPromiseBase() + { + if (handle) + { + handle.destroy(); + } + } JobBase get_return_object() noexcept; inline auto initial_suspend() noexcept; @@ -78,7 +86,6 @@ struct JobPromiseBase void resume() { - std::unique_lock lock(promiseLock); if(!handle || handle.done() || executing()) { return; @@ -88,10 +95,9 @@ struct JobPromiseBase } void setContinuation(JobPromiseBase* cont) { - std::unique_lock lock(promiseLock); - std::unique_lock lock2(cont->promiseLock); + std::scoped_lock lock(promiseLock, cont->promiseLock); continuation = cont->handle; - cont->precondition = finishedEvent; + cont->state = State::SCHEDULED; } bool done() { @@ -113,15 +119,15 @@ struct JobPromiseBase { return state == State::READY; } - void raise() + void finalize() { - std::unique_lock lock(promiseLock); + std::scoped_lock lock(promiseLock); state = State::DONE; finishedEvent.raise(); } void reset() { - std::unique_lock lock(promiseLock); + std::scoped_lock lock(promiseLock); finishedEvent.reset(); } void enqueue(Event& event) @@ -136,13 +142,12 @@ struct JobPromiseBase } void schedule() { - std::unique_lock lock(promiseLock); + std::scoped_lock lock(promiseLock); if(!handle || done() || !ready()) { return; } - state = (precondition == nullptr) ? State::SCHEDULED : State::WAITING; - getGlobalThreadPool().enqueueWaiting(precondition, this); + getGlobalThreadPool().scheduleJob(this); } std::mutex promiseLock; @@ -150,7 +155,6 @@ struct JobPromiseBase std::coroutine_handle<> continuation = std::noop_coroutine(); uint64 id; Event finishedEvent; - Event precondition = nullptr; State state = State::READY; }; @@ -193,13 +197,9 @@ public: { return promise->done(); } - void raise() + void finalize() { - promise->raise(); - } - void reset() - { - promise->reset(); + promise->finalize(); } Event operator co_await() { @@ -245,30 +245,32 @@ using Promise = JobPromiseBase; class ThreadPool { public: - ThreadPool(uint32 threadCount = std::thread::hardware_concurrency()); + ThreadPool(uint32 threadCount = 1); virtual ~ThreadPool(); - // Adds a job to the waiting queue for event, or directly to the job queue if event is nullptr + // Adds a job to the waiting queue for event void enqueueWaiting(Event& event, Promise* job); - // Adds a job to the waiting queue for event, or directly to the job queue if event is nullptr + // Adds a job to the waiting queue for event void enqueueWaiting(Event& event, MainPromise* job); + void scheduleJob(Promise* job); + void scheduleJob(MainPromise* job); void notify(Event& event); void threadLoop(const bool isMainThread); private: std::atomic_bool running; std::vector workers; - List mainJobs; + std::list mainJobs; std::mutex mainJobLock; std::condition_variable mainJobCV; - List jobQueue; + std::list jobQueue; std::mutex jobQueueLock; std::condition_variable jobQueueCV; - std::map> waitingMainJobs; + std::map> waitingMainJobs; std::mutex waitingMainLock; - std::map> waitingJobs; + std::map> waitingJobs; std::mutex waitingLock; }; @@ -283,6 +285,7 @@ inline auto JobPromiseBase::initial_suspend() noexcept { return std::suspend_always{}; } + template inline auto JobPromiseBase::final_suspend() const noexcept { diff --git a/src/Engine/UI/Elements/Element.cpp b/src/Engine/UI/Elements/Element.cpp index f56625e..cc0bc2b 100644 --- a/src/Engine/UI/Elements/Element.cpp +++ b/src/Engine/UI/Elements/Element.cpp @@ -5,6 +5,8 @@ using namespace Seele; using namespace Seele::UI; Element::Element() + : dirty(false) + , enabled(false) { } diff --git a/src/Engine/UI/RenderHierarchy.cpp b/src/Engine/UI/RenderHierarchy.cpp index ad6e7d5..a94ac56 100644 --- a/src/Engine/UI/RenderHierarchy.cpp +++ b/src/Engine/UI/RenderHierarchy.cpp @@ -31,7 +31,7 @@ RenderHierarchy::~RenderHierarchy() void RenderHierarchy::addElement(PElement addedElement) { - std::unique_lock lock(updateLock); + std::scoped_lock lock(updateLock); updates.add(new AddElementRenderHierarchyUpdate{ addedElement.getHandle(), addedElement->getParent().getHandle() @@ -40,7 +40,7 @@ void RenderHierarchy::addElement(PElement addedElement) void RenderHierarchy::removeElement(PElement elementToRemove) { - std::unique_lock lock(updateLock); + std::scoped_lock lock(updateLock); updates.add(new RemoveElementRenderHierarchyUpdate{ elementToRemove.getHandle(), }); @@ -48,7 +48,7 @@ void RenderHierarchy::removeElement(PElement elementToRemove) void RenderHierarchy::moveElement(PElement elementToMove, PElement newParent) { - std::unique_lock lock(updateLock); + std::scoped_lock lock(updateLock); updates.add(new AddElementRenderHierarchyUpdate{ elementToMove.getHandle(), newParent.getHandle() @@ -62,7 +62,7 @@ void RenderHierarchy::updateHierarchy() { List localUpdates; { // make a local copy of the updates so we dont hold the lock for too long - std::unique_lock lock(updateLock); + std::scoped_lock lock(updateLock); localUpdates = updates; updates.clear(); } diff --git a/src/Engine/Window/InspectorView.cpp b/src/Engine/Window/InspectorView.cpp index 83b1c9c..4f954bb 100644 --- a/src/Engine/Window/InspectorView.cpp +++ b/src/Engine/Window/InspectorView.cpp @@ -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() diff --git a/src/Engine/Window/InspectorView.h b/src/Engine/Window/InspectorView.h index dd7227a..db62bf5 100644 --- a/src/Engine/Window/InspectorView.h +++ b/src/Engine/Window/InspectorView.h @@ -13,8 +13,8 @@ public: InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo); virtual ~InspectorView(); - virtual void beginUpdate() override; - virtual void update() override; + virtual Job beginUpdate() override; + virtual Job update() override; virtual void commitUpdate() override; virtual void prepareRender() override; diff --git a/src/Engine/Window/SceneView.cpp b/src/Engine/Window/SceneView.cpp index f16135a..a04d8e6 100644 --- a/src/Engine/Window/SceneView.cpp +++ b/src/Engine/Window/SceneView.cpp @@ -6,6 +6,8 @@ #include "Asset/AssetRegistry.h" #include "Scene/Actor/CameraActor.h" #include "Scene/Components/CameraComponent.h" +#include "Scene/Components/MyComponent.h" +#include "Scene/Components/MyOtherComponent.h" using namespace Seele; @@ -28,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\\Cube\\cube.obj"); AssetRegistry::importFile("C:\\Users\\Dynamitos\\TestSeeleProject\\Assets\\Plane\\plane.fbx"); - srand(time(NULL)); - for(uint32 i = 0; i < 100; ++i) - { - PPrimitiveComponent ayaka = new PrimitiveComponent(AssetRegistry::findMesh("Ayaka")); - ayaka->addWorldTranslation(Vector(((float)rand() / RAND_MAX) * 100, 0, ((float)rand()/RAND_MAX) * 100)); - ayaka->setWorldScale(Vector(10, 10, 10)); - scene->addPrimitiveComponent(ayaka); - } + + PPrimitiveComponent ayaka = new PrimitiveComponent(AssetRegistry::findMesh("Ayaka")); + ayaka->addWorldTranslation(Vector(0, 0, 0)); + ayaka->setWorldScale(Vector(10, 10, 10)); + scene->addPrimitiveComponent(ayaka); PPrimitiveComponent plane = new PrimitiveComponent(AssetRegistry::findMesh("plane")); plane->setWorldScale(Vector(100, 100, 100)); scene->addPrimitiveComponent(plane); + + PMyComponent myComp = new MyComponent(); + PMyOtherComponent myOtherComp = new MyOtherComponent(); + PActor actor = new Actor(); + actor->setRootComponent(myComp); + myComp->addChildComponent(myOtherComp); + scene->addActor(actor); + scene->start(); PRenderGraphResources resources = new RenderGraphResources(); depthPrepass.setResources(resources); @@ -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() diff --git a/src/Engine/Window/SceneView.h b/src/Engine/Window/SceneView.h index b6b0ef7..015552d 100644 --- a/src/Engine/Window/SceneView.h +++ b/src/Engine/Window/SceneView.h @@ -13,8 +13,8 @@ class SceneView : public View public: SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo); ~SceneView(); - virtual void beginUpdate() override; - virtual void update() override; + virtual Job beginUpdate() override; + virtual Job update() override; virtual void commitUpdate() override; virtual void prepareRender() override; diff --git a/src/Engine/Window/View.h b/src/Engine/Window/View.h index f9a0b2b..79eb0ad 100644 --- a/src/Engine/Window/View.h +++ b/src/Engine/Window/View.h @@ -13,8 +13,8 @@ public: virtual ~View(); // These are called from the view thread, and handle updating game data - virtual void beginUpdate() = 0; - virtual void update() = 0; + virtual Job beginUpdate() = 0; + virtual Job update() = 0; // End frame is called with a lock, so it is safe to write to shared memory virtual void commitUpdate() = 0; diff --git a/src/Engine/Window/Window.cpp b/src/Engine/Window/Window.cpp index 6672715..e2c9574 100644 --- a/src/Engine/Window/Window.cpp +++ b/src/Engine/Window/Window.cpp @@ -32,7 +32,7 @@ MainJob Window::render() co_await windowView->updateFinished; windowView->updateFinished.reset(); { - std::unique_lock lock(windowView->workerMutex); + std::scoped_lock lock(windowView->workerMutex); windowView->view->prepareRender(); } windowView->view->render(); @@ -78,7 +78,7 @@ Job Window::viewWorker(size_t viewIndex) windowView->view->beginUpdate(); windowView->view->update(); { - std::unique_lock lock(windowView->workerMutex); + std::scoped_lock lock(windowView->workerMutex); windowView->view->commitUpdate(); } //std::cout << "Update completed" << std::endl; diff --git a/src/Engine/Window/WindowManager.cpp b/src/Engine/Window/WindowManager.cpp index 283e098..57447e8 100644 --- a/src/Engine/Window/WindowManager.cpp +++ b/src/Engine/Window/WindowManager.cpp @@ -41,7 +41,7 @@ void WindowManager::notifyWindowClosed(PWindow window) windows.remove(windows.find(window)); if(windows.empty()) { - std::unique_lock lock(windowsLock); + std::scoped_lock lock(windowsLock); windowsCV.notify_all(); } } diff --git a/test/Engine/Containers/Array.cpp b/test/Engine/Containers/Array.cpp index e56bdd9..9a8b7e7 100644 --- a/test/Engine/Containers/Array.cpp +++ b/test/Engine/Containers/Array.cpp @@ -12,131 +12,170 @@ BOOST_AUTO_TEST_SUITE(Array_Suite) BOOST_AUTO_TEST_CASE(empty_constructur) { - Array array; - BOOST_CHECK_EQUAL(array.size(), 0); + Array array; + BOOST_CHECK_EQUAL(array.size(), 0); } BOOST_AUTO_TEST_CASE(initialial_size) { - Array array(3); - BOOST_CHECK_EQUAL(array.size(), 3); + Array array(3); + BOOST_CHECK_EQUAL(array.size(), 3); } BOOST_AUTO_TEST_CASE(resize) { - Array array; - array.add(2); - array.add(3); - BOOST_CHECK_EQUAL(array.size(), 2); - array.resize(5); - BOOST_CHECK_EQUAL(array.size(), 5); + Array array; + array.add(2); + array.add(3); + BOOST_CHECK_EQUAL(array.size(), 2); + array.resize(5); + BOOST_CHECK_EQUAL(array.size(), 5); } BOOST_AUTO_TEST_CASE(clear) { - Array array; - array.add(3); - array.add(2); - array.add(6); - BOOST_CHECK_EQUAL(array.size(), 3); - array.clear(); - BOOST_CHECK_EQUAL(array.size(), 0); + Array array; + array.add(3); + array.add(2); + array.add(6); + BOOST_CHECK_EQUAL(array.size(), 3); + array.clear(); + BOOST_CHECK_EQUAL(array.size(), 0); + array.add(2); } BOOST_AUTO_TEST_CASE(remove_keeporder) { - Array array; - array.add(1); - array.add(2); - array.add(3); - array.add(4); - array.add(5); - array.remove(1); - BOOST_CHECK_EQUAL(array[1], 3); - BOOST_CHECK_EQUAL(array[2], 4); - BOOST_CHECK_EQUAL(array[3], 5); - BOOST_CHECK_EQUAL(array.size(), 4); + Array array; + array.add(1); + array.add(2); + array.add(3); + array.add(4); + array.add(5); + array.remove(1); + BOOST_CHECK_EQUAL(array[1], 3); + BOOST_CHECK_EQUAL(array[2], 4); + BOOST_CHECK_EQUAL(array[3], 5); + BOOST_CHECK_EQUAL(array.size(), 4); } BOOST_AUTO_TEST_CASE(remove_swap) { - Array array; - array.add(1); - array.add(2); - array.add(3); - array.add(4); - array.add(5); - array.remove(1, false); - BOOST_CHECK_EQUAL(array[1], 5); - BOOST_CHECK_EQUAL(array[2], 3); - BOOST_CHECK_EQUAL(array[3], 4); - BOOST_CHECK_EQUAL(array.size(), 4); + Array array; + array.add(1); + array.add(2); + array.add(3); + array.add(4); + array.add(5); + array.remove(1, false); + BOOST_CHECK_EQUAL(array[1], 5); + BOOST_CHECK_EQUAL(array[2], 3); + BOOST_CHECK_EQUAL(array[3], 4); + BOOST_CHECK_EQUAL(array.size(), 4); } BOOST_AUTO_TEST_CASE(remove_iterator) { - Array array; - array.add(1); - array.add(2); - array.add(3); - array.add(4); - array.add(5); - array.remove(array.find(1), false); - BOOST_CHECK_EQUAL(array[0], 5); - BOOST_CHECK_EQUAL(array[1], 2); - BOOST_CHECK_EQUAL(array[2], 3); - BOOST_CHECK_EQUAL(array[3], 4); - BOOST_CHECK_EQUAL(array.size(), 4); + Array array; + array.add(1); + array.add(2); + array.add(3); + array.add(4); + array.add(5); + array.remove(array.find(1), false); + BOOST_CHECK_EQUAL(array[0], 5); + BOOST_CHECK_EQUAL(array[1], 2); + BOOST_CHECK_EQUAL(array[2], 3); + BOOST_CHECK_EQUAL(array[3], 4); + BOOST_CHECK_EQUAL(array.size(), 4); } BOOST_AUTO_TEST_CASE(remove_iterator_keep_order) { - Array array; - array.add(1); - array.add(2); - array.add(3); - array.add(4); - array.add(5); - array.remove(array.find(1)); - BOOST_CHECK_EQUAL(array[0], 2); - BOOST_CHECK_EQUAL(array[1], 3); - BOOST_CHECK_EQUAL(array[2], 4); - BOOST_CHECK_EQUAL(array[3], 5); - BOOST_CHECK_EQUAL(array.size(), 4); + Array array; + array.add(1); + array.add(2); + array.add(3); + array.add(4); + array.add(5); + array.remove(array.find(1)); + BOOST_CHECK_EQUAL(array[0], 2); + BOOST_CHECK_EQUAL(array[1], 3); + BOOST_CHECK_EQUAL(array[2], 4); + BOOST_CHECK_EQUAL(array[3], 5); + BOOST_CHECK_EQUAL(array.size(), 4); } BOOST_AUTO_TEST_CASE(random_access) { - Array array; - array.add(4); - array.add(5); - array.add(6); - BOOST_CHECK_EQUAL(array[2], 6); - BOOST_CHECK_EQUAL(array[0], 4); + Array array; + array.add(4); + array.add(5); + array.add(6); + BOOST_CHECK_EQUAL(array[2], 6); + BOOST_CHECK_EQUAL(array[0], 4); +} + +BOOST_AUTO_TEST_CASE(copy) +{ + Array array; + array.add(0); + array.add(1); + array.add(2); + array.add(3); + Array copy = array; + BOOST_CHECK_EQUAL_COLLECTIONS(array.begin(), array.end(), copy.begin(), copy.end()); + Array copy2(copy); + BOOST_CHECK_EQUAL_COLLECTIONS(array.begin(), array.end(), copy2.begin(), copy2.end()); +} + +class BaseElement +{ + uint64 test; +}; + +class BaseContainer +{ + Array elements; +}; + +class DerivedContainer : public BaseContainer +{ + uint64 test; +}; + +BOOST_AUTO_TEST_CASE(virtual_classes) +{ + Array array(64); + for(uint32 i = 0; i < 100; ++i) + { + Array copy = array; + BOOST_CHECK_EQUAL(array.size(), copy.size()); + } } class TestStruct { public: - uint32 data; - ~TestStruct() - { - data = 1; - } + uint32 data; + ~TestStruct() + { + data = 1; + } }; DECLARE_REF(TestStruct); BOOST_AUTO_TEST_CASE(refptr_interaction) { - uint32* dataPtr; - { - PTestStruct test = new TestStruct(); - test->data = 32123; - dataPtr = &test->data; - { - Array arr(1); - arr[0] = test; - } - BOOST_CHECK_EQUAL(test->data, 32123); - } + uint32* dataPtr; + { + PTestStruct test = new TestStruct(); + test->data = 32123; + dataPtr = &test->data; + { + Array arr(1); + arr[0] = test; + } + BOOST_CHECK_EQUAL(test->data, 32123); + } } BOOST_AUTO_TEST_SUITE_END() @@ -146,25 +185,25 @@ BOOST_AUTO_TEST_SUITE(StaticArray_Suite) BOOST_AUTO_TEST_CASE(empty_constructur) { - StaticArray array; - BOOST_CHECK_EQUAL(array.size(), 2); + StaticArray array; + BOOST_CHECK_EQUAL(array.size(), 2); } BOOST_AUTO_TEST_CASE(initialial_size) { - StaticArray array(3); - BOOST_CHECK_EQUAL(array.size(), 3); - BOOST_CHECK_EQUAL(array[1], 3); + StaticArray array(3); + BOOST_CHECK_EQUAL(array.size(), 3); + BOOST_CHECK_EQUAL(array[1], 3); } BOOST_AUTO_TEST_CASE(random_access) { - StaticArray array; - array[0] = 4; - array[1] = 5; - array[2] = 6; - BOOST_CHECK_EQUAL(array[0], 4); - BOOST_CHECK_EQUAL(array[2], 6); + StaticArray array; + array[0] = 4; + array[1] = 5; + array[2] = 6; + BOOST_CHECK_EQUAL(array[0], 4); + BOOST_CHECK_EQUAL(array[2], 6); } BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/test/Engine/EngineTest.h b/test/Engine/EngineTest.h index a927a0a..e525c5c 100644 --- a/test/Engine/EngineTest.h +++ b/test/Engine/EngineTest.h @@ -1,4 +1,6 @@ #pragma once +#include +#include "ThreadPool.h" namespace Seele { @@ -6,6 +8,7 @@ namespace Seele { GlobalFixture() { + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); } ~GlobalFixture() { diff --git a/test/Engine/ThreadPool.cpp b/test/Engine/ThreadPool.cpp index a19da35..40b13eb 100644 --- a/test/Engine/ThreadPool.cpp +++ b/test/Engine/ThreadPool.cpp @@ -23,13 +23,18 @@ Job basicThenThird() co_return; } -BOOST_AUTO_TEST_CASE(basic_then) +Job basicThenBase() { - basicThenFirst() - .then(basicThenSecond()) - .then(basicThenThird()); + co_await basicThenFirst(); + co_await basicThenSecond(); + co_await basicThenThird(); } +BOOST_AUTO_TEST_CASE(basic_then) +{ + basicThenBase(); +} +/* uint64 basicAllState1 = 0; uint64 basicAllState2 = 0; Job basicAllFirst() @@ -69,6 +74,6 @@ BOOST_AUTO_TEST_CASE(basic_callable) BOOST_REQUIRE_EQUAL(basicCallable, 10); co_return; }); -} +}*/ BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file