Provisional multithreading framework
This commit is contained in:
Vendored
+2
-2
@@ -12,8 +12,8 @@
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceRoot}/bin/Debug",
|
||||
"console": "internalConsole",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"symbolSearchPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.25.28610\\lib\\x64",
|
||||
"requireExactSource": false,
|
||||
"logging": {
|
||||
@@ -30,9 +30,9 @@
|
||||
"program": "${workspaceRoot}/bin/Debug/Seele_unit_tests.exe",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"console": "internalConsole",
|
||||
"cwd": "${workspaceRoot}/bin/Debug",
|
||||
"environment": [],
|
||||
"externalConsole": false
|
||||
},
|
||||
]
|
||||
}
|
||||
+6
-5
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
# Handle superbuild first
|
||||
option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON)
|
||||
@@ -27,6 +27,8 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin/${CMAKE_BUILD
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/bin/Debug)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/bin/Release)
|
||||
|
||||
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)
|
||||
|
||||
if (USE_SUPERBUILD)
|
||||
project (SUPERBUILD NONE)
|
||||
# execute the superbuild (this script will be invoked again without the
|
||||
@@ -52,13 +54,12 @@ find_package(SLang REQUIRED)
|
||||
include_directories(${GLM_INCLUDE_DIRS})
|
||||
include_directories(${STB_INCLUDE_DIRS})
|
||||
include_directories(${Vulkan_INCLUDE_DIR})
|
||||
include_directories(${SPIRV_INCLUDE_DIRS})
|
||||
#include_directories(${SPIRV_INCLUDE_DIRS})
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
include_directories(${GLFW_INCLUDE_DIRS})
|
||||
include_directories(${SLANG_INCLUDE_DIRS})
|
||||
include_directories(${ASSIMP_INCLUDE_DIRS})
|
||||
include_directories(${JSON_INCLUDE_DIRS})
|
||||
include_directories(${SPIRV_INCLUDE_DIRS})
|
||||
include_directories(${ENGINE_ROOT})
|
||||
include_directories(src/Engine)
|
||||
add_definitions(${Vulkan_DEFINITIONS})
|
||||
@@ -77,7 +78,7 @@ target_link_libraries(SeeleEngine ${GLFW_LIBRARIES})
|
||||
target_link_libraries(SeeleEngine ${SLANG_LIBRARIES})
|
||||
target_link_libraries(SeeleEngine ${ASSIMP_LIBRARIES})
|
||||
target_link_libraries(SeeleEngine ${JSON_LIBRARY})
|
||||
target_link_libraries(SeeleEngine ${SPIRV_LIBRARIES})
|
||||
#target_link_libraries(SeeleEngine ${SPIRV_LIBRARIES})
|
||||
|
||||
#target_precompile_headers(SeeleEngine
|
||||
# PRIVATE
|
||||
|
||||
+4
-4
@@ -6,17 +6,17 @@
|
||||
"debug": {
|
||||
"short": "Debug",
|
||||
"long": "Enable debugging and validation",
|
||||
"buildType": "Debug",
|
||||
"settings": {
|
||||
"CMAKE_DEBUG_POSTFIX": "d"
|
||||
"CMAKE_DEBUG_POSTFIX": "d",
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
"release": {
|
||||
"short": "Release",
|
||||
"long": "Optimize binary for speed",
|
||||
"buildType": "Release",
|
||||
"settings": {
|
||||
"CMAKE_DEBUG_POSTFIX": ""
|
||||
"CMAKE_DEBUG_POSTFIX": "",
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ if (WIN32)
|
||||
NAMES assimp-vc${MSVC_TOOLSET_VERSION}-mt${CMAKE_DEBUG_POSTFIX}.lib
|
||||
PATHS
|
||||
$ENV{PROGRAMFILES}/lib
|
||||
${ASSIMP_ROOT}/lib/)
|
||||
${ASSIMP_ROOT}/lib
|
||||
${ASSIMP_ROOT}/lib/${CMAKE_BUILD_TYPE})
|
||||
|
||||
find_file(
|
||||
ASSIMP_BINARY
|
||||
|
||||
+11
-8
@@ -5,8 +5,11 @@ set(EXTRA_CMAKE_ARGS)
|
||||
#------------ASSIMP---------------
|
||||
list(APPEND DEPENDENCIES assimp)
|
||||
set(ASSIMP_BUILD_TESTS OFF CACHE INTERNAL "")
|
||||
set(ASSIMP_BUILD_SAMPLES OFF CACHE INTERNAL "")
|
||||
set(ASSIMP_BUILD_OVERALLS OFF CACHE INTERNAL "")
|
||||
set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE INTERNAL "")
|
||||
set(ASSIMP_INSTALL OFF CACHE INTERNAL "")
|
||||
set(ASSIMP_BUILD_ZLIB OFF CACHE INTERNAL "")
|
||||
set(BUILD_SHARED_LIBS ON CACHE INTERNAL "")
|
||||
|
||||
add_subdirectory(${ASSIMP_ROOT} ${ASSIMP_ROOT})
|
||||
@@ -74,14 +77,14 @@ ExternalProject_Add(slang
|
||||
endif()
|
||||
|
||||
#----------------SPIR-V-CROSS--------------------
|
||||
list(APPEND DEPENDENCIES spirv-cross-reflect)
|
||||
set(SPIRV_CROSS_ENABLE_HLSL OFF CACHE BOOL "")
|
||||
set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE BOOL "")
|
||||
set(SPIRV_CROSS_CLI OFF CACHE BOOL "")
|
||||
set(SPIRV_CROSS_ENABLE_C_API OFF CACHE BOOL "")
|
||||
set(SPIRV_CROSS_ENABLE_UTIL OFF CACHE BOOL "")
|
||||
set(SPIRV_CROSS_SKIP_INSTALL ON CACHE BOOL "")
|
||||
add_subdirectory(${SPIRV_ROOT})
|
||||
# list(APPEND DEPENDENCIES spirv-cross-reflect)
|
||||
# set(SPIRV_CROSS_ENABLE_HLSL OFF CACHE BOOL "")
|
||||
# set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE BOOL "")
|
||||
# set(SPIRV_CROSS_CLI OFF CACHE BOOL "")
|
||||
# set(SPIRV_CROSS_ENABLE_C_API OFF CACHE BOOL "")
|
||||
# set(SPIRV_CROSS_ENABLE_UTIL OFF CACHE BOOL "")
|
||||
# set(SPIRV_CROSS_SKIP_INSTALL ON CACHE BOOL "")
|
||||
# add_subdirectory(${SPIRV_ROOT})
|
||||
|
||||
|
||||
#-----------------SeeleEngine--------------------
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
This file needs to be here because otherwise git will delete the folder and the engine can't automatically generate it
|
||||
@@ -0,0 +1 @@
|
||||
add_subdirectory(x64/)
|
||||
@@ -29,8 +29,7 @@ MeshLoader::~MeshLoader()
|
||||
|
||||
void MeshLoader::importAsset(const std::filesystem::path &path)
|
||||
{
|
||||
//futures.add(std::async(std::launch::async, &MeshLoader::import, this, path));
|
||||
import(path);
|
||||
futures.add(std::async(std::launch::async, &MeshLoader::import, this, path));
|
||||
}
|
||||
|
||||
void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials, Gfx::PGraphics graphics)
|
||||
@@ -118,7 +117,7 @@ VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gf
|
||||
vbInfo.vertexSize = sizeof(Vector);
|
||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
vbInfo.resourceData.size = sizeof(Vector) * buffer.size();
|
||||
vbInfo.resourceData.size = sizeof(Vector) * (uint32)buffer.size();
|
||||
return VertexStreamComponent(graphics->createVertexBuffer(vbInfo), 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT);
|
||||
}
|
||||
VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics)
|
||||
@@ -133,7 +132,7 @@ VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gf
|
||||
vbInfo.vertexSize = sizeof(Vector2);
|
||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
vbInfo.resourceData.size = sizeof(Vector2) * buffer.size();
|
||||
vbInfo.resourceData.size = sizeof(Vector2) * (uint32)buffer.size();
|
||||
return VertexStreamComponent(graphics->createVertexBuffer(vbInfo), 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT);
|
||||
}
|
||||
void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials, Gfx::PGraphics graphics)
|
||||
@@ -180,7 +179,7 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMesh
|
||||
idxInfo.indexType = Gfx::SE_INDEX_TYPE_UINT32;
|
||||
idxInfo.resourceData.data = (uint8 *)indices.data();
|
||||
idxInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
idxInfo.resourceData.size = sizeof(uint32) * indices.size();
|
||||
idxInfo.resourceData.size = sizeof(uint32) * (uint32)indices.size();
|
||||
Gfx::PIndexBuffer indexBuffer = graphics->createIndexBuffer(idxInfo);
|
||||
indexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ target_sources(SeeleEngine
|
||||
main.cpp)
|
||||
|
||||
add_subdirectory(Asset/)
|
||||
add_subdirectory(Arch/)
|
||||
add_subdirectory(Containers/)
|
||||
add_subdirectory(Fibers/)
|
||||
add_subdirectory(Graphics/)
|
||||
add_subdirectory(Material/)
|
||||
add_subdirectory(Math/)
|
||||
|
||||
+126
-100
@@ -25,12 +25,12 @@ namespace Seele
|
||||
//std::memset(_data, 0, sizeof(T) * DEFAULT_ALLOC_SIZE);
|
||||
refreshIterators();
|
||||
}
|
||||
Array(uint32 size, T value = T())
|
||||
Array(size_t size, T value = T())
|
||||
: allocated(size), arraySize(size)
|
||||
{
|
||||
_data = new T[size];
|
||||
assert(_data != nullptr);
|
||||
for (uint32 i = 0; i < size; ++i)
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
assert(i < size);
|
||||
_data[i] = value;
|
||||
@@ -38,7 +38,7 @@ namespace Seele
|
||||
refreshIterators();
|
||||
}
|
||||
Array(std::initializer_list<T> init)
|
||||
: allocated((uint32)init.size()), arraySize((uint32)init.size())
|
||||
: allocated(init.size()), arraySize(init.size())
|
||||
{
|
||||
_data = new T[init.size()];
|
||||
auto it = init.begin();
|
||||
@@ -194,6 +194,17 @@ namespace Seele
|
||||
}
|
||||
return endIt;
|
||||
}
|
||||
Iterator find(T&& item)
|
||||
{
|
||||
for (uint32 i = 0; i < arraySize; ++i)
|
||||
{
|
||||
if (_data[i] == item)
|
||||
{
|
||||
return Iterator(&_data[i]);
|
||||
}
|
||||
}
|
||||
return endIt;
|
||||
}
|
||||
Iterator begin() const
|
||||
{
|
||||
return beginIt;
|
||||
@@ -215,11 +226,11 @@ namespace Seele
|
||||
{
|
||||
if (arraySize == allocated)
|
||||
{
|
||||
uint32 newSize = arraySize + 1;
|
||||
size_t newSize = arraySize + 1;
|
||||
allocated = calculateGrowth(newSize);
|
||||
T *tempArray = new T[allocated];
|
||||
assert(tempArray != nullptr);
|
||||
for (uint32 i = 0; i < arraySize; ++i)
|
||||
for (size_t i = 0; i < arraySize; ++i)
|
||||
{
|
||||
tempArray[i] = _data[i];
|
||||
}
|
||||
@@ -230,6 +241,25 @@ namespace Seele
|
||||
refreshIterators();
|
||||
return _data[arraySize - 1];
|
||||
}
|
||||
T &add(T&& item)
|
||||
{
|
||||
if (arraySize == allocated)
|
||||
{
|
||||
size_t newSize = arraySize + 1;
|
||||
allocated = calculateGrowth(newSize);
|
||||
T *tempArray = new T[allocated];
|
||||
assert(tempArray != nullptr);
|
||||
for (size_t i = 0; i < arraySize; ++i)
|
||||
{
|
||||
tempArray[i] = std::move(_data[i]);
|
||||
}
|
||||
delete[] _data;
|
||||
_data = tempArray;
|
||||
}
|
||||
_data[arraySize++] = std::move(item);
|
||||
refreshIterators();
|
||||
return _data[arraySize - 1];
|
||||
}
|
||||
T &addUnique(const T &item = T())
|
||||
{
|
||||
Iterator it;
|
||||
@@ -240,22 +270,22 @@ namespace Seele
|
||||
return add(item);
|
||||
}
|
||||
template<typename... args>
|
||||
T &emplace(args...)
|
||||
T &emplace(args... arguments)
|
||||
{
|
||||
if (arraySize == allocated)
|
||||
{
|
||||
uint32 newSize = arraySize + 1;
|
||||
size_t newSize = arraySize + 1;
|
||||
allocated = calculateGrowth(newSize);
|
||||
T *tempArray = new T[allocated];
|
||||
assert(tempArray != nullptr);
|
||||
for (uint32 i = 0; i < arraySize; ++i)
|
||||
for (size_t i = 0; i < arraySize; ++i)
|
||||
{
|
||||
tempArray[i] = _data[i];
|
||||
}
|
||||
delete[] _data;
|
||||
_data = tempArray;
|
||||
}
|
||||
_data[arraySize++] = T(args...);
|
||||
_data[arraySize++] = T(arguments...);
|
||||
refreshIterators();
|
||||
return _data[arraySize - 1];
|
||||
}
|
||||
@@ -271,7 +301,7 @@ namespace Seele
|
||||
}
|
||||
else
|
||||
{
|
||||
_data[index] = _data[arraySize - 1];
|
||||
_data[index] = std::move(_data[arraySize - 1]);
|
||||
}
|
||||
arraySize--;
|
||||
}
|
||||
@@ -283,7 +313,7 @@ namespace Seele
|
||||
allocated = 0;
|
||||
refreshIterators();
|
||||
}
|
||||
void resize(uint32 newSize)
|
||||
void resize(size_t newSize)
|
||||
{
|
||||
if (newSize < allocated)
|
||||
{
|
||||
@@ -301,27 +331,31 @@ namespace Seele
|
||||
}
|
||||
refreshIterators();
|
||||
}
|
||||
inline uint32 indexOf(Iterator iterator)
|
||||
inline size_t indexOf(Iterator iterator)
|
||||
{
|
||||
return iterator - beginIt;
|
||||
}
|
||||
inline uint32 indexOf(ConstIterator iterator) const
|
||||
inline size_t indexOf(ConstIterator iterator) const
|
||||
{
|
||||
return iterator.p - beginIt.p;
|
||||
}
|
||||
inline uint32 indexOf(T& t)
|
||||
inline size_t indexOf(T& t)
|
||||
{
|
||||
return indexOf(find(t));
|
||||
}
|
||||
inline uint32 indexOf(const T& t) const
|
||||
inline size_t indexOf(const T& t) const
|
||||
{
|
||||
return indexOf(find(t));
|
||||
}
|
||||
inline uint32 size() const
|
||||
inline size_t size() const
|
||||
{
|
||||
return arraySize;
|
||||
}
|
||||
inline uint32 capacity() const
|
||||
inline size_t empty() const
|
||||
{
|
||||
return arraySize == 0;
|
||||
}
|
||||
inline size_t capacity() const
|
||||
{
|
||||
return allocated;
|
||||
}
|
||||
@@ -338,44 +372,27 @@ namespace Seele
|
||||
arraySize--;
|
||||
refreshIterators();
|
||||
}
|
||||
T &operator[](uint32 index)
|
||||
T &operator[](size_t index)
|
||||
{
|
||||
assert(index < arraySize);
|
||||
return _data[index];
|
||||
}
|
||||
inline T &operator[](size_t index)
|
||||
{
|
||||
return this->operator[]((uint32)index);
|
||||
}
|
||||
inline T &operator[](int32 index)
|
||||
{
|
||||
return this->operator[]((uint32)index);
|
||||
}
|
||||
const T &operator[](uint32 index) const
|
||||
const T &operator[](size_t index) const
|
||||
{
|
||||
assert(index < arraySize);
|
||||
return _data[index];
|
||||
}
|
||||
inline const T &operator[](size_t index) const
|
||||
{
|
||||
return this->operator[]((uint32)index);
|
||||
}
|
||||
inline const T &operator[](int32 index) const
|
||||
{
|
||||
return this->operator[]((uint32)index);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 calculateGrowth(uint32 newSize) const
|
||||
size_t calculateGrowth(size_t newSize) const
|
||||
{
|
||||
const uint32 oldCapacity = capacity();
|
||||
const size_t oldCapacity = capacity();
|
||||
|
||||
if (oldCapacity > UINT32_MAX - oldCapacity / 2)
|
||||
if (oldCapacity > SIZE_MAX - oldCapacity / 2)
|
||||
{
|
||||
return newSize; // geometric growth would overflow
|
||||
}
|
||||
|
||||
const uint32 geometric = oldCapacity + oldCapacity / 2;
|
||||
const size_t geometric = oldCapacity + oldCapacity / 2;
|
||||
|
||||
if (geometric < newSize)
|
||||
{
|
||||
@@ -395,71 +412,30 @@ namespace Seele
|
||||
{
|
||||
ar & arraySize;
|
||||
ar & allocated;
|
||||
for(uint32 i = 0; i < arraySize; ++i)
|
||||
for(size_t i = 0; i < arraySize; ++i)
|
||||
ar & _data[i];
|
||||
refreshIterators();
|
||||
}
|
||||
uint32 arraySize;
|
||||
uint32 allocated;
|
||||
size_t arraySize;
|
||||
size_t allocated;
|
||||
Iterator beginIt;
|
||||
Iterator endIt;
|
||||
T *_data;
|
||||
};
|
||||
|
||||
template <typename T, uint32 N>
|
||||
template <typename T, size_t N>
|
||||
struct StaticArray
|
||||
{
|
||||
public:
|
||||
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 uint32 size() const
|
||||
{
|
||||
return N;
|
||||
}
|
||||
inline T *data()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
inline const T *data() const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
T &operator[](int index)
|
||||
{
|
||||
assert(index >= 0 && index < N);
|
||||
return _data[index];
|
||||
}
|
||||
const T &operator[](int index) const
|
||||
{
|
||||
assert(index >= 0 && index < N);
|
||||
return _data[index];
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename X>
|
||||
class IteratorBase
|
||||
{
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef X value_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef X &reference;
|
||||
typedef X *pointer;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = X;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using reference = X&;
|
||||
using pointer = X*;
|
||||
|
||||
IteratorBase(X *x = nullptr)
|
||||
: p(x)
|
||||
@@ -500,36 +476,86 @@ namespace Seele
|
||||
private:
|
||||
X *p;
|
||||
};
|
||||
typedef IteratorBase<T> Iterator;
|
||||
typedef IteratorBase<const T> ConstIterator;
|
||||
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&;
|
||||
|
||||
Iterator begin()
|
||||
using iterator = IteratorBase<T>;
|
||||
using const_iterator = IteratorBase<const T>;
|
||||
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_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 >= 0 && index < N);
|
||||
return _data[index];
|
||||
}
|
||||
constexpr const_reference operator[](size_type index) const noexcept
|
||||
{
|
||||
assert(index >= 0 && index < N);
|
||||
return _data[index];
|
||||
}
|
||||
iterator begin()
|
||||
{
|
||||
return beginIt;
|
||||
}
|
||||
Iterator end()
|
||||
iterator end()
|
||||
{
|
||||
return endIt;
|
||||
}
|
||||
ConstIterator begin() const
|
||||
const_iterator begin() const
|
||||
{
|
||||
return beginIt;
|
||||
}
|
||||
ConstIterator end() const
|
||||
const_iterator end() const
|
||||
{
|
||||
return beginIt;
|
||||
}
|
||||
private:
|
||||
T _data[N];
|
||||
Iterator beginIt;
|
||||
Iterator endIt;
|
||||
iterator beginIt;
|
||||
iterator endIt;
|
||||
friend class boost::serialization::access;
|
||||
template<class Archive>
|
||||
void serialize(Archive& ar, const unsigned int version)
|
||||
{
|
||||
ar & N;
|
||||
ar & _data;
|
||||
refreshIterators();
|
||||
}
|
||||
};
|
||||
} // namespace Seele
|
||||
@@ -250,6 +250,14 @@ public:
|
||||
refreshIterators();
|
||||
return Iterator(next);
|
||||
}
|
||||
void popBack()
|
||||
{
|
||||
remove(Iterator(tail->prev));
|
||||
}
|
||||
void popFront()
|
||||
{
|
||||
remove(Iterator(root));
|
||||
}
|
||||
Iterator insert(Iterator pos, const T &value)
|
||||
{
|
||||
_size++;
|
||||
|
||||
+56
-26
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <utility>
|
||||
#include "Array.h"
|
||||
|
||||
namespace Seele
|
||||
@@ -9,12 +10,15 @@ struct Pair
|
||||
public:
|
||||
Pair()
|
||||
: key(K()), value(V())
|
||||
{
|
||||
}
|
||||
Pair(K key, V value)
|
||||
: key(key), value(value)
|
||||
{
|
||||
}
|
||||
{}
|
||||
template<class KeyType>
|
||||
explicit Pair(KeyType&& key)
|
||||
: key(key), value(V())
|
||||
{}
|
||||
template<class KeyType, class ValueType>
|
||||
explicit Pair(KeyType&& key, ValueType&& value)
|
||||
: key(std::move(key)), value(std::move(value))
|
||||
{}
|
||||
K key;
|
||||
V value;
|
||||
};
|
||||
@@ -28,11 +32,12 @@ private:
|
||||
Node *leftChild;
|
||||
Node *rightChild;
|
||||
Node()
|
||||
: leftChild(nullptr), rightChild(nullptr), pair(K(), V())
|
||||
: leftChild(nullptr), rightChild(nullptr), pair()
|
||||
{
|
||||
}
|
||||
Node(const K &key)
|
||||
: leftChild(nullptr), rightChild(nullptr), pair(key, V())
|
||||
template<class KeyType, class ValueType>
|
||||
explicit Node(KeyType&& key, ValueType&& value)
|
||||
: leftChild(nullptr), rightChild(nullptr), pair(key, value)
|
||||
{
|
||||
}
|
||||
Node(const Node& other)
|
||||
@@ -242,7 +247,7 @@ public:
|
||||
Iterator operator--(int)
|
||||
{
|
||||
Iterator tmp(*this);
|
||||
++*this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
Iterator operator++(int)
|
||||
@@ -256,8 +261,7 @@ public:
|
||||
Node *node;
|
||||
Array<Node *> traversal;
|
||||
};
|
||||
|
||||
V &operator[](const K &key)
|
||||
V &operator[](const K& key)
|
||||
{
|
||||
root = splay(root, key);
|
||||
if (root == nullptr || root->pair.key < key || key < root->pair.key)
|
||||
@@ -268,7 +272,18 @@ public:
|
||||
}
|
||||
return root->pair.value;
|
||||
}
|
||||
Iterator find(const K &key)
|
||||
V &operator[](K&& key)
|
||||
{
|
||||
root = splay(root, std::forward<K>(key));
|
||||
if (root == nullptr || root->pair.key < key || key < root->pair.key)
|
||||
{
|
||||
root = insert(root, std::forward<K>(key));
|
||||
_size++;
|
||||
refreshIterators();
|
||||
}
|
||||
return root->pair.value;
|
||||
}
|
||||
Iterator find(const K& key)
|
||||
{
|
||||
root = splay(root, key);
|
||||
if (root == nullptr || root->pair.key != key)
|
||||
@@ -277,10 +292,25 @@ public:
|
||||
}
|
||||
return Iterator(root);
|
||||
}
|
||||
Iterator erase(const K &key)
|
||||
Iterator find(K&& key)
|
||||
{
|
||||
root = splay(root, std::move(key));
|
||||
if (root == nullptr || root->pair.key != key)
|
||||
{
|
||||
return endIt;
|
||||
}
|
||||
return Iterator(root);
|
||||
}
|
||||
Iterator erase(const K& key)
|
||||
{
|
||||
root = remove(root, key);
|
||||
refreshIterators();
|
||||
return Iterator(root);
|
||||
}
|
||||
Iterator erase(K&& key)
|
||||
{
|
||||
root = remove(root, std::move(key));
|
||||
refreshIterators();
|
||||
return Iterator(root);
|
||||
}
|
||||
void clear()
|
||||
@@ -290,9 +320,9 @@ public:
|
||||
_size = 0;
|
||||
refreshIterators();
|
||||
}
|
||||
bool exists(const K &key)
|
||||
bool exists(K&& key)
|
||||
{
|
||||
return find(key) != endIt;
|
||||
return find(std::forward<K>(key)) != endIt;
|
||||
}
|
||||
Iterator begin() const
|
||||
{
|
||||
@@ -365,21 +395,19 @@ private:
|
||||
y->leftChild = node;
|
||||
return y;
|
||||
}
|
||||
Node *makeNode(const K &key)
|
||||
{
|
||||
return new Node(key);
|
||||
}
|
||||
Node *insert(Node *r, const K &key)
|
||||
template<class KeyType>
|
||||
Node *insert(Node *r, KeyType&& key)
|
||||
{
|
||||
if (r == nullptr)
|
||||
return makeNode(key);
|
||||
|
||||
{
|
||||
return new Node(std::forward<KeyType>(key), V());
|
||||
}
|
||||
r = splay(r, key);
|
||||
|
||||
if (!(r->pair.key < key || key < r->pair.key))
|
||||
return r;
|
||||
|
||||
Node *newNode = makeNode(key);
|
||||
Node *newNode = new Node(std::forward<KeyType>(key), V());
|
||||
|
||||
if (key < r->pair.key)
|
||||
{
|
||||
@@ -395,7 +423,8 @@ private:
|
||||
}
|
||||
return newNode;
|
||||
}
|
||||
Node *remove(Node *r, const K &key)
|
||||
template<class KeyType>
|
||||
Node *remove(Node *r, KeyType&& key)
|
||||
{
|
||||
Node *temp;
|
||||
if (!r)
|
||||
@@ -424,7 +453,8 @@ private:
|
||||
delete temp;
|
||||
return r;
|
||||
}
|
||||
Node *splay(Node *r, const K &key)
|
||||
template<class KeyType>
|
||||
Node *splay(Node *r, KeyType&& key)
|
||||
{
|
||||
if (r == nullptr || !(r->pair.key < key || key < r->pair.key))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
target_sources(SeeleEngine
|
||||
PRIVATE
|
||||
Fibers.h
|
||||
Fibers.cpp
|
||||
JobQueue.h
|
||||
JobQueue.cpp)
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "Fibers.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Fibers;
|
||||
|
||||
std::atomic_uint64_t FiberJob::jobIDGenerator;
|
||||
|
||||
Counter::Counter()
|
||||
{
|
||||
count.store(0);
|
||||
}
|
||||
|
||||
Counter::Counter(uint64 initialValue)
|
||||
{
|
||||
count.store(initialValue);
|
||||
}
|
||||
|
||||
Counter::~Counter()
|
||||
{
|
||||
}
|
||||
|
||||
AwaitCounter&& FiberTask::promise_type::await_transform(AwaitCounter&& awaitCounter)
|
||||
{
|
||||
counter = awaitCounter.counter;
|
||||
target = awaitCounter.target;
|
||||
priority = awaitCounter.priority;
|
||||
return std::move(awaitCounter);
|
||||
}
|
||||
|
||||
FiberJob::FiberJob()
|
||||
{
|
||||
}
|
||||
|
||||
FiberJob::~FiberJob()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "JobQueue.h"
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Fibers
|
||||
{
|
||||
class Counter
|
||||
{
|
||||
public:
|
||||
Counter();
|
||||
Counter(uint64 initialValue);
|
||||
~Counter();
|
||||
inline void increment()
|
||||
{
|
||||
count++;
|
||||
}
|
||||
inline void decrement()
|
||||
{
|
||||
count--;
|
||||
}
|
||||
inline void setValue(uint64 value)
|
||||
{
|
||||
count.store(value);
|
||||
}
|
||||
inline uint64 getValue()
|
||||
{
|
||||
return count.load();
|
||||
}
|
||||
inline bool greaterEqual(uint64 target)
|
||||
{
|
||||
return count.load() >= target;
|
||||
}
|
||||
inline bool greaterThan(uint64 target)
|
||||
{
|
||||
return count.load() > target;
|
||||
}
|
||||
inline bool lessEqual(uint64 target)
|
||||
{
|
||||
return count.load() <= target;
|
||||
}
|
||||
inline bool lessThan(uint64 target)
|
||||
{
|
||||
return count.load() < target;
|
||||
}
|
||||
inline bool equals(uint64 target)
|
||||
{
|
||||
return count.load() == target;
|
||||
}
|
||||
friend std::strong_ordering operator<=>(const Counter& counter, uint64 other)
|
||||
{
|
||||
return counter.count.load() <=> other;
|
||||
}
|
||||
friend std::ostream& operator<<(std::ostream& stream, const Counter* counter)
|
||||
{
|
||||
stream << counter->count;
|
||||
return stream;
|
||||
}
|
||||
friend std::ostream& operator<<(std::ostream& stream, PCounter counter)
|
||||
{
|
||||
stream << counter->count;
|
||||
return stream;
|
||||
}
|
||||
private:
|
||||
std::atomic_uint64_t count;
|
||||
};
|
||||
DEFINE_REF(Counter);
|
||||
struct AwaitCounter
|
||||
{
|
||||
PCounter counter;
|
||||
uint64 target;
|
||||
JobPriority priority = JobPriority::MEDIUM;
|
||||
bool await_ready() { return counter->greaterEqual(target); }
|
||||
void await_suspend(std::coroutine_handle<> h) {
|
||||
}
|
||||
void await_resume() {}
|
||||
};
|
||||
struct AwaitCounter;
|
||||
class FiberTask
|
||||
{
|
||||
public:
|
||||
struct promise_type;
|
||||
using handle_type = std::coroutine_handle<promise_type>;
|
||||
private:
|
||||
promise_type* promise;
|
||||
public:
|
||||
FiberTask() = default;
|
||||
explicit FiberTask(promise_type* promise)
|
||||
: promise(promise) {}
|
||||
FiberTask(const FiberTask& other)
|
||||
: promise(other.promise) {}
|
||||
FiberTask(FiberTask&& other)
|
||||
: promise(std::move(other.promise)) {}
|
||||
FiberTask& operator=(const FiberTask& other)
|
||||
{
|
||||
promise = other.promise;
|
||||
return *this;
|
||||
}
|
||||
FiberTask& operator=(FiberTask&& other)
|
||||
{
|
||||
promise = std::move(other.promise);
|
||||
return *this;
|
||||
}
|
||||
inline void resume() { promise->resume(); }
|
||||
inline void destroy() { promise->destroy(); }
|
||||
inline bool done() { return promise->done(); }
|
||||
inline PCounter getCounter() const { return promise->counter; }
|
||||
inline uint64 getTarget() const { return promise->target; }
|
||||
inline JobPriority getPriority() const { return promise->priority; }
|
||||
struct promise_type
|
||||
{
|
||||
promise_type()
|
||||
{
|
||||
handle = handle_type::from_promise(*this);
|
||||
}
|
||||
~promise_type() = default;
|
||||
promise_type(const promise_type&) = delete;
|
||||
promise_type(promise_type&&) = delete;
|
||||
promise_type &operator=(const promise_type&) = delete;
|
||||
promise_type &operator=(promise_type&&) = delete;
|
||||
FiberTask get_return_object()
|
||||
{
|
||||
return FiberTask(this);
|
||||
}
|
||||
auto initial_suspend() { return std::suspend_never{}; }
|
||||
auto final_suspend() noexcept { return std::suspend_always{}; }
|
||||
auto return_void() {}
|
||||
void unhandled_exception() { std::exit(1); }
|
||||
AwaitCounter&& await_transform(AwaitCounter&& awaitCounter);
|
||||
inline void resume() { handle.resume(); }
|
||||
inline void destroy() { handle.destroy(); }
|
||||
inline bool done() { return handle.done(); }
|
||||
private:
|
||||
handle_type handle;
|
||||
PCounter counter;
|
||||
uint64 target;
|
||||
JobPriority priority;
|
||||
friend class FiberTask;
|
||||
};
|
||||
};
|
||||
class FiberJob
|
||||
{
|
||||
public:
|
||||
FiberJob();
|
||||
template<typename func, typename... args>
|
||||
FiberJob(PCounter counter, func function, args... arg)
|
||||
: counter(counter), function(std::bind(function, arg...))
|
||||
{
|
||||
jobID = jobIDGenerator.fetch_add(1);
|
||||
}
|
||||
template<typename func, typename...args>
|
||||
FiberJob(PCounter counter, JobPriority priority, func function, args... arg)
|
||||
: counter(counter), priority(priority), function(std::bind(function, arg...))
|
||||
{
|
||||
}
|
||||
FiberJob(const FiberJob& other) = delete;
|
||||
FiberJob(FiberJob&& other)
|
||||
: counter(std::move(other.counter))
|
||||
, jobID(std::move(other.jobID))
|
||||
, priority(std::move(other.priority))
|
||||
, function(std::move(other.function))
|
||||
{
|
||||
}
|
||||
~FiberJob();
|
||||
FiberJob& operator=(const FiberJob& other) = delete;
|
||||
FiberJob& operator=(FiberJob&& other)
|
||||
{
|
||||
if(this != &other)
|
||||
{
|
||||
counter = std::move(other.counter);
|
||||
jobID = std::move(other.jobID);
|
||||
priority = std::move(other.priority);
|
||||
function = std::move(other.function);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
void operator()()
|
||||
{
|
||||
FiberTask task = function();
|
||||
if(!task.done())
|
||||
{
|
||||
JobQueue::suspendJob(std::move(task));
|
||||
}
|
||||
else
|
||||
{
|
||||
counter->increment();
|
||||
task.destroy();
|
||||
}
|
||||
}
|
||||
inline JobPriority getPriority()
|
||||
{
|
||||
return priority;
|
||||
}
|
||||
private:
|
||||
PCounter counter;
|
||||
uint64 jobID;
|
||||
static std::atomic_uint64_t jobIDGenerator;
|
||||
JobPriority priority = JobPriority::MEDIUM;
|
||||
std::function<FiberTask()> function;
|
||||
};
|
||||
} // namespace Fibers
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,134 @@
|
||||
#include "JobQueue.h"
|
||||
#include "Fibers.h"
|
||||
#include <Windows.h>
|
||||
#include <processthreadsapi.h>
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Fibers;
|
||||
|
||||
std::wstring toString(JobPriority priority)
|
||||
{
|
||||
switch (priority)
|
||||
{
|
||||
case JobPriority::HIGH:
|
||||
return L"HIGH";
|
||||
case JobPriority::MEDIUM:
|
||||
return L"MEDIUM";
|
||||
case JobPriority::LOW:
|
||||
return L"LOW";
|
||||
case JobPriority::IO:
|
||||
return L"IO";
|
||||
default:
|
||||
return L"Illegal Priority";
|
||||
}
|
||||
}
|
||||
|
||||
Array<JobQueue*> JobQueue::workers;
|
||||
StaticArray<JobPriorityInfo, (size_t)JobPriority::NUM_PRIORITIES> JobQueue::priorityQueues;
|
||||
|
||||
JobQueue::JobQueue(JobPriority priority)
|
||||
: priority(priority)
|
||||
{
|
||||
threadHandle = std::thread(&JobQueue::work, this);
|
||||
SetThreadDescription(threadHandle.native_handle(), toString(priority).c_str());
|
||||
}
|
||||
|
||||
JobQueue::~JobQueue()
|
||||
{
|
||||
running = false;
|
||||
threadHandle.join();
|
||||
}
|
||||
|
||||
void JobQueue::initJobQueues()
|
||||
{
|
||||
// TODO: make this dependent on actual cores
|
||||
JobPriority priorities[16] = {
|
||||
JobPriority::IO, JobPriority::IO,
|
||||
JobPriority::LOW, JobPriority::LOW, JobPriority::LOW, JobPriority::LOW,
|
||||
JobPriority::MEDIUM, JobPriority::MEDIUM, JobPriority::MEDIUM, JobPriority::MEDIUM, JobPriority::MEDIUM,
|
||||
JobPriority::HIGH, JobPriority::HIGH, JobPriority::HIGH, JobPriority::HIGH, JobPriority::HIGH};
|
||||
|
||||
for(uint32 i = 0; i < 16; ++i)
|
||||
{
|
||||
workers.add(new JobQueue(priorities[i]));
|
||||
}
|
||||
}
|
||||
void JobQueue::cleanupJobQueues()
|
||||
{
|
||||
for(auto worker : workers)
|
||||
{
|
||||
delete worker;
|
||||
}
|
||||
}
|
||||
|
||||
void JobQueue::runJobs(FiberJob* jobs, uint32 numJobs)
|
||||
{
|
||||
for(uint32 i = 0; i < numJobs; ++i)
|
||||
{
|
||||
JobPriorityInfo& info = priorityQueues[(size_t)jobs[i].getPriority()];
|
||||
std::unique_lock lock(info.jobQueueLock);
|
||||
info.jobQueue.add(std::move(jobs[i]));
|
||||
//info.jobQueueCV.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void JobQueue::waitForCounter(PCounter counter, uint32 waitFor)
|
||||
{
|
||||
while(counter->lessThan(waitFor))
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
void JobQueue::suspendJob(FiberTask&& task)
|
||||
{
|
||||
JobPriorityInfo& info = priorityQueues[(size_t)task.getPriority()];
|
||||
std::unique_lock lock(info.jobQueueLock);
|
||||
info.waiterQueue[task.getCounter()].add(task);
|
||||
}
|
||||
void JobQueue::refreshWaiterQueue()
|
||||
{
|
||||
JobPriorityInfo& info = priorityQueues[(size_t)priority];
|
||||
//shortcut to avoid iterator creation
|
||||
if(info.waiterQueue.empty())
|
||||
return;
|
||||
for(auto it : info.waiterQueue)
|
||||
{
|
||||
auto& entries = info.waiterQueue[it.key];
|
||||
for(uint32 i = 0; i < entries.size(); ++i)
|
||||
{
|
||||
if(it.key->greaterEqual(entries[i].getTarget()))
|
||||
{
|
||||
info.resumableTasks.add(std::move(entries[i]));
|
||||
entries.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JobQueue::work()
|
||||
{
|
||||
JobPriorityInfo& targetInfo = priorityQueues[(size_t)priority];
|
||||
auto& jobQueue = targetInfo.jobQueue;
|
||||
auto& resumableTasks = targetInfo.resumableTasks;
|
||||
while(running)
|
||||
{
|
||||
std::unique_lock lock(targetInfo.jobQueueLock);
|
||||
refreshWaiterQueue();
|
||||
if(resumableTasks.size() > 0)
|
||||
{
|
||||
FiberTask task = std::move(resumableTasks.front());
|
||||
resumableTasks.popFront();
|
||||
lock.unlock();
|
||||
task.resume();
|
||||
lock.lock();
|
||||
}
|
||||
if(jobQueue.size() > 0)
|
||||
{
|
||||
FiberJob job = std::move(jobQueue.front());
|
||||
jobQueue.popFront();
|
||||
lock.unlock();
|
||||
job();
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Containers/List.h"
|
||||
#include <coroutine>
|
||||
namespace Seele
|
||||
{
|
||||
namespace Fibers
|
||||
{
|
||||
class FiberJob;
|
||||
DECLARE_REF(Counter);
|
||||
enum class JobPriority : size_t
|
||||
{
|
||||
HIGH = 0,
|
||||
MEDIUM,
|
||||
LOW,
|
||||
IO,
|
||||
NUM_PRIORITIES
|
||||
};
|
||||
struct AtomicJobQueue
|
||||
{
|
||||
};
|
||||
class FiberTask;
|
||||
struct JobPriorityInfo
|
||||
{
|
||||
List<FiberJob> jobQueue;
|
||||
Map<PCounter, Array<FiberTask>> waiterQueue;
|
||||
List<FiberTask> resumableTasks;
|
||||
std::mutex jobQueueLock;
|
||||
};
|
||||
class JobQueue
|
||||
{
|
||||
public:
|
||||
JobQueue(JobPriority priority);
|
||||
JobQueue(const JobQueue& other) = delete;
|
||||
JobQueue(JobQueue&& other) = delete;
|
||||
JobQueue& operator=(const JobQueue& other) = delete;
|
||||
JobQueue& operator=(JobQueue&& other) = delete;
|
||||
~JobQueue();
|
||||
static void initJobQueues();
|
||||
static void cleanupJobQueues();
|
||||
static void runJobs(FiberJob* jobs, uint32 numJobs);
|
||||
//This does in fact not do any coroutine stuff, but is a simple busy wait
|
||||
//For coroutine waits, you have to be in a coroutine, and
|
||||
static void waitForCounter(PCounter counter, uint32 waitFor);
|
||||
static void suspendJob(FiberTask&& task);
|
||||
void refreshWaiterQueue();
|
||||
private:
|
||||
void work();
|
||||
static Array<JobQueue*> workers;
|
||||
static StaticArray<JobPriorityInfo, (size_t)JobPriority::NUM_PRIORITIES> priorityQueues;
|
||||
std::thread threadHandle;
|
||||
JobPriority priority;
|
||||
bool running = true;
|
||||
};
|
||||
} // namespace Fibers
|
||||
} // namespace Seele
|
||||
@@ -57,7 +57,7 @@ private:
|
||||
template<class Archive>
|
||||
void serialize(Archive& ar, const unsigned int version)
|
||||
{
|
||||
ar & referencedMaterial->getFullPath();
|
||||
//ar & referencedMaterial->getFullPath();
|
||||
//TODO:
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,7 +91,7 @@ Gfx::VertexElement VertexShaderInput::accessStreamComponent(const VertexStreamCo
|
||||
vertexStream.stride = component.stride;
|
||||
vertexStream.offset = component.offset;
|
||||
|
||||
return Gfx::VertexElement(streams.indexOf(streams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride);
|
||||
return Gfx::VertexElement((uint8)streams.indexOf(streams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride);
|
||||
}
|
||||
|
||||
Gfx::VertexElement VertexShaderInput::accessPositionStreamComponent(const VertexStreamComponent& component, uint8 attributeIndex)
|
||||
@@ -101,7 +101,7 @@ Gfx::VertexElement VertexShaderInput::accessPositionStreamComponent(const Vertex
|
||||
vertexStream.stride = component.stride;
|
||||
vertexStream.offset = component.offset;
|
||||
|
||||
return Gfx::VertexElement(streams.indexOf(streams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride);
|
||||
return Gfx::VertexElement((uint8)streams.indexOf(streams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride);
|
||||
}
|
||||
|
||||
void VertexShaderInput::initDeclaration(Gfx::PGraphics graphics, Array<Gfx::VertexElement>& elements)
|
||||
|
||||
@@ -65,7 +65,7 @@ void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFrame
|
||||
|
||||
VkRenderPassBeginInfo beginInfo =
|
||||
init::RenderPassBeginInfo();
|
||||
beginInfo.clearValueCount = renderPass->getClearValueCount();
|
||||
beginInfo.clearValueCount = (uint32)renderPass->getClearValueCount();
|
||||
beginInfo.pClearValues = renderPass->getClearValues();
|
||||
beginInfo.renderArea = renderPass->getRenderArea();
|
||||
beginInfo.renderPass = renderPass->getHandle();
|
||||
@@ -95,7 +95,7 @@ void CmdBuffer::executeCommands(Array<Gfx::PRenderCommand> commands)
|
||||
}
|
||||
cmdBuffers[i] = command->getHandle();
|
||||
}
|
||||
vkCmdExecuteCommands(handle, cmdBuffers.size(), cmdBuffers.data());
|
||||
vkCmdExecuteCommands(handle, (uint32)cmdBuffers.size(), cmdBuffers.data());
|
||||
}
|
||||
|
||||
void CmdBuffer::addWaitSemaphore(VkPipelineStageFlags flags, PSemaphore semaphore)
|
||||
@@ -212,7 +212,7 @@ void SecondaryCmdBuffer::bindDescriptor(const Array<Gfx::PDescriptorSet>& descri
|
||||
boundDescriptors.add(descriptorSet);
|
||||
sets[descriptorSet->getSetIndex()] = descriptorSet->getHandle();
|
||||
}
|
||||
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, descriptorSets.size(), sets, 0, nullptr);
|
||||
vkCmdBindDescriptorSets(handle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->getLayout(), 0, (uint32)descriptorSets.size(), sets, 0, nullptr);
|
||||
delete[] sets;
|
||||
}
|
||||
void SecondaryCmdBuffer::bindVertexBuffer(const Array<VertexInputStream>& streams)
|
||||
@@ -225,7 +225,7 @@ void SecondaryCmdBuffer::bindVertexBuffer(const Array<VertexInputStream>& stream
|
||||
buffers[i] = buf->getHandle();
|
||||
offsets[i] = streams[i].offset;
|
||||
};
|
||||
vkCmdBindVertexBuffers(handle, 0, streams.size(), buffers.data(), offsets.data());
|
||||
vkCmdBindVertexBuffers(handle, 0, (uint32)streams.size(), buffers.data(), offsets.data());
|
||||
}
|
||||
void SecondaryCmdBuffer::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ void DescriptorLayout::create()
|
||||
binding.pImmutableSamplers = nullptr;
|
||||
}
|
||||
VkDescriptorSetLayoutCreateInfo createInfo =
|
||||
init::DescriptorSetLayoutCreateInfo(bindings.data(), bindings.size());
|
||||
init::DescriptorSetLayoutCreateInfo(bindings.data(), (uint32)bindings.size());
|
||||
VK_CHECK(vkCreateDescriptorSetLayout(graphics->getDevice(), &createInfo, nullptr, &layoutHandle));
|
||||
|
||||
allocator = new DescriptorAllocator(graphics, *this);
|
||||
@@ -75,7 +75,7 @@ void PipelineLayout::create()
|
||||
}
|
||||
|
||||
VkPipelineLayoutCreateInfo createInfo =
|
||||
init::PipelineLayoutCreateInfo(vulkanDescriptorLayouts.data(), vulkanDescriptorLayouts.size());
|
||||
init::PipelineLayoutCreateInfo(vulkanDescriptorLayouts.data(), (uint32)vulkanDescriptorLayouts.size());
|
||||
Array<VkPushConstantRange> vkPushConstants(pushConstants.size());
|
||||
for (size_t i = 0; i < pushConstants.size(); i++)
|
||||
{
|
||||
@@ -83,7 +83,7 @@ void PipelineLayout::create()
|
||||
vkPushConstants[i].size = pushConstants[i].size;
|
||||
vkPushConstants[i].stageFlags = cast((VkShaderStageFlagBits)pushConstants[i].stageFlags);
|
||||
}
|
||||
createInfo.pushConstantRangeCount = vkPushConstants.size();
|
||||
createInfo.pushConstantRangeCount = (uint32)vkPushConstants.size();
|
||||
createInfo.pPushConstantRanges = vkPushConstants.data();
|
||||
|
||||
boost::crc_32_type result;
|
||||
@@ -198,7 +198,7 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::
|
||||
bool DescriptorSet::operator<(Gfx::PDescriptorSet other)
|
||||
{
|
||||
PDescriptorSet otherSet = other.cast<DescriptorSet>();
|
||||
return setHandle < otherSet->setHandle;
|
||||
return this < otherSet.getHandle();
|
||||
}
|
||||
|
||||
void DescriptorSet::writeChanges()
|
||||
@@ -210,7 +210,7 @@ void DescriptorSet::writeChanges()
|
||||
currentlyBound->getManager()->waitForCommands(currentlyBound);
|
||||
currentlyBound = nullptr;
|
||||
}
|
||||
vkUpdateDescriptorSets(graphics->getDevice(), writeDescriptors.size(), writeDescriptors.data(), 0, nullptr);
|
||||
vkUpdateDescriptorSets(graphics->getDevice(), (uint32)writeDescriptors.size(), writeDescriptors.data(), 0, nullptr);
|
||||
writeDescriptors.clear();
|
||||
imageInfos.clear();
|
||||
bufferInfos.clear();
|
||||
@@ -241,7 +241,7 @@ DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout &l
|
||||
poolSizes.add(size);
|
||||
}
|
||||
}
|
||||
VkDescriptorPoolCreateInfo createInfo = init::DescriptorPoolCreateInfo(poolSizes.size(), poolSizes.data(), maxSets);
|
||||
VkDescriptorPoolCreateInfo createInfo = init::DescriptorPoolCreateInfo((uint32)poolSizes.size(), poolSizes.data(), maxSets);
|
||||
VK_CHECK(vkCreateDescriptorPool(graphics->getDevice(), &createInfo, nullptr, &poolHandle));
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRende
|
||||
VkFramebufferCreateInfo createInfo =
|
||||
init::FramebufferCreateInfo(
|
||||
renderPass->getHandle(),
|
||||
attachments.size(),
|
||||
(uint32)attachments.size(),
|
||||
attachments.data(),
|
||||
renderPass->getRenderArea().extent.width,
|
||||
renderPass->getRenderArea().extent.height,
|
||||
|
||||
@@ -215,9 +215,9 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
std::memcpy(hashStruct.attribs, attributes.data(), attributes.size() * sizeof(VkVertexInputAttributeDescription));
|
||||
|
||||
vertexInput.pVertexBindingDescriptions = bindings.data();
|
||||
vertexInput.vertexBindingDescriptionCount = bindings.size();
|
||||
vertexInput.vertexBindingDescriptionCount = (uint32)bindings.size();
|
||||
vertexInput.pVertexAttributeDescriptions = attributes.data();
|
||||
vertexInput.vertexAttributeDescriptionCount = attributes.size();
|
||||
vertexInput.vertexAttributeDescriptionCount = (uint32)attributes.size();
|
||||
|
||||
VkPipelineInputAssemblyStateCreateInfo assemblyInfo =
|
||||
init::PipelineInputAssemblyStateCreateInfo(
|
||||
@@ -291,7 +291,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
}
|
||||
VkPipelineColorBlendStateCreateInfo blendState =
|
||||
init::PipelineColorBlendStateCreateInfo(
|
||||
blendAttachments.size(),
|
||||
(uint32)blendAttachments.size(),
|
||||
blendAttachments.data()
|
||||
);
|
||||
blendState.logicOpEnable = gfxInfo.colorBlend.logicOpEnable;
|
||||
|
||||
@@ -91,10 +91,10 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::PRenderTargetLayout layout)
|
||||
VkSubpassDescription subPassDesc =
|
||||
init::SubpassDescription(
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
colorRefs.size(),
|
||||
(uint32)colorRefs.size(),
|
||||
colorRefs.data(),
|
||||
&depthRef,
|
||||
inputRefs.size(),
|
||||
(uint32)inputRefs.size(),
|
||||
inputRefs.data());
|
||||
VkSubpassDependency dependency = {};
|
||||
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||
@@ -108,7 +108,7 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::PRenderTargetLayout layout)
|
||||
|
||||
VkRenderPassCreateInfo info =
|
||||
init::RenderPassCreateInfo(
|
||||
attachments.size(),
|
||||
(uint32)attachments.size(),
|
||||
attachments.data(),
|
||||
1,
|
||||
&subPassDesc,
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
{
|
||||
return renderPass;
|
||||
}
|
||||
inline uint32 getClearValueCount() const
|
||||
inline size_t getClearValueCount() const
|
||||
{
|
||||
return clearValues.size();
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ void Shader::create(const ShaderCreateInfo& createInfo)
|
||||
spAddSearchPath(request, "shaders/lib/");
|
||||
spAddSearchPath(request, "shaders/generated/");
|
||||
|
||||
spSetGlobalGenericArgs(request, createInfo.typeParameter.size(), createInfo.typeParameter.data());
|
||||
spSetGlobalGenericArgs(request, (int)createInfo.typeParameter.size(), createInfo.typeParameter.data());
|
||||
|
||||
int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type));
|
||||
if(spCompile(request))
|
||||
|
||||
@@ -65,7 +65,7 @@ void Material::compile()
|
||||
for(auto param : j["params"].items())
|
||||
{
|
||||
std::string type = param.value()["type"].get<std::string>();
|
||||
auto default = param.value().find("default");
|
||||
auto defaultValue = param.value().find("default");
|
||||
if(type.compare("float") == 0)
|
||||
{
|
||||
PFloatParameter p = new FloatParameter(param.key(), uniformBufferOffset, 0);
|
||||
@@ -76,9 +76,9 @@ void Material::compile()
|
||||
uniformBinding = bindingCounter++;
|
||||
}
|
||||
uniformBufferOffset += 4;
|
||||
if(default != param.value().end())
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
p->data = std::stof(default.value().get<std::string>());
|
||||
p->data = std::stof(defaultValue.value().get<std::string>());
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
@@ -92,9 +92,9 @@ void Material::compile()
|
||||
uniformBinding = bindingCounter++;
|
||||
}
|
||||
uniformBufferOffset += 12;
|
||||
if(default != param.value().end())
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
p->data = parseVector(default.value().get<std::string>().c_str());
|
||||
p->data = parseVector(defaultValue.value().get<std::string>().c_str());
|
||||
}
|
||||
parameters.add(p);
|
||||
}
|
||||
@@ -102,9 +102,9 @@ void Material::compile()
|
||||
{
|
||||
PTextureParameter p = new TextureParameter(param.key(), 0, bindingCounter);
|
||||
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
|
||||
if(default != param.value().end())
|
||||
if(defaultValue != param.value().end())
|
||||
{
|
||||
p->data = AssetRegistry::findTexture(default.value().get<std::string>());
|
||||
p->data = AssetRegistry::findTexture(defaultValue.value().get<std::string>());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ public:
|
||||
Transform();
|
||||
Transform(const Transform &other);
|
||||
Transform(Transform &&other);
|
||||
Transform(Vector position);
|
||||
explicit Transform(Vector position);
|
||||
Transform(Vector position, Quaternion rotation);
|
||||
Transform(Vector position, Quaternion rotation, Vector scale);
|
||||
Transform(Quaternion rotation, Vector scale);
|
||||
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
|
||||
private:
|
||||
T *handle;
|
||||
uint64 refCount;
|
||||
std::atomic_uint64_t refCount;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -15,7 +15,7 @@ Scene::Scene(Gfx::PGraphics graphics)
|
||||
lightEnv.directionalLights[0].intensity = Vector4(1, 1, 1, 1);
|
||||
lightEnv.numDirectionalLights = 1;
|
||||
lightEnv.numPointLights = 0;
|
||||
srand(time(NULL));
|
||||
srand((unsigned int)time(NULL));
|
||||
}
|
||||
|
||||
Scene::~Scene()
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#include "Graphics/RenderCore.h"
|
||||
#include "Window/SceneView.h"
|
||||
#include "Asset/AssetRegistry.h"
|
||||
#include "Fibers/Fibers.h"
|
||||
#include <queue>
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
int main()
|
||||
{
|
||||
RenderCore core;
|
||||
|
||||
@@ -5,5 +5,6 @@ target_sources(Seele_unit_tests
|
||||
EngineTest.cpp)
|
||||
target_include_directories(Seele_unit_tests PUBLIC ./)
|
||||
add_subdirectory(Containers/)
|
||||
add_subdirectory(Fibers/)
|
||||
add_subdirectory(Graphics/)
|
||||
add_subdirectory(Math/)
|
||||
@@ -31,7 +31,7 @@ BOOST_AUTO_TEST_CASE(for_each)
|
||||
map[6] = 4;
|
||||
map[4] = 7;
|
||||
int count = 0;
|
||||
for(auto it = map.begin(); it != map.end(); ++it)
|
||||
for(auto it : map)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
BOOST_TEST_GLOBAL_FIXTURE(GlobalFixture);
|
||||
BOOST_AUTO_TEST_SUITE(RefPtr)
|
||||
|
||||
struct TestStruct
|
||||
|
||||
@@ -1 +1,23 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include "Fibers/JobQueue.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
struct GlobalFixture
|
||||
{
|
||||
GlobalFixture()
|
||||
{
|
||||
}
|
||||
~GlobalFixture()
|
||||
{
|
||||
}
|
||||
void setup()
|
||||
{
|
||||
Fibers::JobQueue::initJobQueues();
|
||||
}
|
||||
void teardown()
|
||||
{
|
||||
Fibers::JobQueue::cleanupJobQueues();
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
target_sources(Seele_unit_tests
|
||||
PRIVATE
|
||||
../../../src/Engine/Fibers/JobQueue.cpp
|
||||
../../../src/Engine/Fibers/Fibers.cpp
|
||||
Fibers.cpp)
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "EngineTest.h"
|
||||
#include "MinimalEngine.h"
|
||||
#include "Fibers/Fibers.h"
|
||||
#include <coroutine>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Fibers;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Fibers_Suite)
|
||||
|
||||
FiberTask basicFiberSync1(PCounter syncCounter)
|
||||
{
|
||||
syncCounter->increment();
|
||||
std::cout << "basicFiberSync1 start" << std::endl;
|
||||
co_await AwaitCounter{syncCounter, 2};
|
||||
std::cout << "basicFiberSync1 has resumed, counter is " << syncCounter << std::endl;
|
||||
co_return;
|
||||
}
|
||||
|
||||
FiberTask basicFiberSync2(PCounter syncCounter)
|
||||
{
|
||||
syncCounter->increment();
|
||||
std::cout << "basicFiberSync2 start" << std::endl;
|
||||
co_await AwaitCounter(syncCounter, 3);
|
||||
std::cout << "basicFiberSync2 has resumed, counter is " << syncCounter << std::endl;
|
||||
co_return;
|
||||
}
|
||||
BOOST_AUTO_TEST_CASE(basicFiberSync)
|
||||
{
|
||||
PCounter syncCounter = new Counter(1);
|
||||
PCounter counter1 = new Counter();
|
||||
FiberJob job1 = FiberJob(counter1, &basicFiberSync1, syncCounter);
|
||||
JobQueue::runJobs(&job1, 1);
|
||||
FiberJob job2 = FiberJob(counter1, &basicFiberSync2, syncCounter);
|
||||
JobQueue::runJobs(&job2, 1);
|
||||
while(counter1->lessThan(2))
|
||||
std::this_thread::yield();
|
||||
BOOST_CHECK_EQUAL(syncCounter->getValue(), 3);
|
||||
}
|
||||
FiberTask incrementJob(PCounter localCounter)
|
||||
{
|
||||
localCounter->increment();
|
||||
co_return;
|
||||
}
|
||||
BOOST_AUTO_TEST_CASE(jobBatch)
|
||||
{
|
||||
PCounter localCounter = new Counter();
|
||||
PCounter jobCounter = new Counter();
|
||||
FiberJob jobs[256];
|
||||
for(int i = 0; i < 256; ++i)
|
||||
{
|
||||
jobs[i] = FiberJob(jobCounter, JobPriority::HIGH, &incrementJob, localCounter);
|
||||
}
|
||||
JobQueue::runJobs(jobs, 256);
|
||||
while(jobCounter->lessThan(256))
|
||||
std::this_thread::yield();
|
||||
BOOST_CHECK_EQUAL(localCounter->getValue(), 256);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
Reference in New Issue
Block a user