diff --git a/Content/Documentation/ScriptingAPI-Documentation.md b/Content/Documentation/ScriptingAPI-Documentation.md index 4dfe71a10..cbd927e9f 100644 --- a/Content/Documentation/ScriptingAPI-Documentation.md +++ b/Content/Documentation/ScriptingAPI-Documentation.md @@ -610,9 +610,13 @@ This is the main entry point and manages the lifetime of the application. Even t - SetFrameSkip(bool enabled) -- enable/disable frame skipping in fixed update - SetTargetFrameRate(float fps) -- set target frame rate for fixed update and variable rate update when frame rate is locked - SetFrameRateLock(bool enabled) -- if enabled, variable rate update will use a fixed delta time -- SetInfoDisplay(bool active) -- SetWatermarkDisplay(bool active) -- SetFPSDisplay(bool active) +- SetInfoDisplay(bool active) -- if enabled, information display will be visible in the top left corner of the application +- SetWatermarkDisplay(bool active) -- toggle display of engine watermark, version number, etc. if info display is enabled +- SetFPSDisplay(bool active) -- toggle display of frame rate if info display is enabled +- SetResolutionDisplay(bool active) -- toggle display of resolution if info display is enabled +- SetLogicalSizeDisplay(bool active) -- toggle display of logical size of canvas if info display is enabled +- SetPipelineCountDisplay(bool active) -- toggle display of active graphics pipeline count if info display is enabled +- SetHeapAllocationCountDisplay(bool active) -- toggle display of heap allocation statistics if info display is enabled - GetCanvas() : Canvas canvas - [outer]SetProfilerEnabled(bool enabled) diff --git a/Content/Documentation/WickedEngine-Documentation.md b/Content/Documentation/WickedEngine-Documentation.md index 11145a9a2..0709c76dc 100644 --- a/Content/Documentation/WickedEngine-Documentation.md +++ b/Content/Documentation/WickedEngine-Documentation.md @@ -1107,7 +1107,7 @@ The controller force feedback features that might be supported. Can be provided ### Touch A touch contact point. Currently it is supported in UWP (Universal Windows Platform) applications. - GetTouches
-Get a std::vector containing current Touch contact points +Get a vector containing current Touch contact points ### wiXInput [[Header]](../../WickedEngine/wiXInput.h) [[Cpp]](../../WickedEngine/wiXInput.cpp) @@ -1261,6 +1261,7 @@ This is the place for tools that use engine-level systems ### wiBackLog [[Header]](../../WickedEngine/wiBacklog.h) [[Cpp]](../../WickedEngine/wiBackLog.cpp) Used to log any messages by any system, from any thread. It can draw itself to the screen. It can execute Lua scripts. +If there was a `wiBackLog::LogLevel::Error` or higher severity message posted on the backlog, the contents of the log will be saved to the temporary user directory as wiBackLog.txt. ### wiProfiler [[Header]](../../WickedEngine/wiProfiler.h) [[Cpp]](../../WickedEngine/wiProfiler.cpp) Used to time specific ranges in execution. Support CPU and GPU timing. Can write the result to the screen as simple text at this time. diff --git a/Editor/AnimationWindow.cpp b/Editor/AnimationWindow.cpp index d16cdcf21..27d0ad65b 100644 --- a/Editor/AnimationWindow.cpp +++ b/Editor/AnimationWindow.cpp @@ -2,8 +2,6 @@ #include "AnimationWindow.h" #include "Editor.h" -#include - using namespace wiECS; using namespace wiScene; diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 7111b98e8..22785aa94 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -5,7 +5,7 @@ #include "ModelImporter.h" #include "Translator.h" -#include +#include #include #include #include @@ -680,19 +680,24 @@ void EditorComponent::Load() saveButton.SetColor(wiColor(0, 255, 140, 255), wiWidget::WIDGETSTATE::FOCUS); saveButton.OnClick([&](wiEventArgs args) { + const bool dump_to_header = saveModeComboBox.GetSelected() == 2; + wiHelper::FileDialogParams params; params.type = wiHelper::FileDialogParams::SAVE; - params.description = "Wicked Scene"; - params.extensions.push_back("wiscene"); - wiHelper::FileDialog(params, [this](std::string fileName) { + if (dump_to_header) + { + params.description = "C++ header (.h)"; + params.extensions.push_back("h"); + } + else + { + params.description = "Wicked Scene (.wiscene)"; + params.extensions.push_back("wiscene"); + } + wiHelper::FileDialog(params, [=](std::string fileName) { wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) { - std::string filename = fileName; - std::string extension = wiHelper::GetExtensionFromFileName(filename); - if (extension.compare("wiscene")) - { - filename += ".wiscene"; - } - wiArchive archive(filename, false); + std::string filename = wiHelper::ReplaceExtension(fileName, params.extensions.front()); + wiArchive archive = dump_to_header ? wiArchive() : wiArchive(filename, false); if (archive.IsOpen()) { Scene& scene = wiScene::GetScene(); @@ -702,6 +707,11 @@ void EditorComponent::Load() scene.Serialize(archive); + if (dump_to_header) + { + archive.SaveHeaderFile(filename, wiHelper::RemoveExtension(wiHelper::GetFileNameFromPath(filename))); + } + ResetHistory(); } else @@ -853,36 +863,36 @@ void EditorComponent::Load() GetGUI().AddWidget(&helpButton); { - std::stringstream ss(""); - ss << "Help:" << std::endl; - ss << "Move camera: WASD, or Contoller left stick or D-pad" << std::endl; - ss << "Look: Middle mouse button / arrow keys / controller right stick" << std::endl; - ss << "Select: Right mouse button" << std::endl; - ss << "Interact with water: Left mouse button when nothing is selected" << std::endl; - ss << "Camera speed: SHIFT button or controller R2/RT" << std::endl; - ss << "Camera up: E, down: Q" << std::endl; - ss << "Duplicate entity: Ctrl + D" << std::endl; - ss << "Select All: Ctrl + A" << std::endl; - ss << "Undo: Ctrl + Z" << std::endl; - ss << "Redo: Ctrl + Y" << std::endl; - ss << "Copy: Ctrl + C" << std::endl; - ss << "Paste: Ctrl + V" << std::endl; - ss << "Delete: DELETE button" << std::endl; - ss << "Place Instances: Ctrl + Shift + Left mouse click (place clipboard onto clicked surface)" << std::endl; - ss << "Script Console / backlog: HOME button" << std::endl; - ss << std::endl; - ss << "You can find sample scenes in the models directory. Try to load one." << std::endl; - ss << "You can also import models from .OBJ, .GLTF, .GLB files." << std::endl; - ss << "You can find a program configuration file at Editor/config.ini" << std::endl; - ss << "You can find sample LUA scripts in the scripts directory. Try to load one." << std::endl; - ss << "You can find a startup script at Editor/startup.lua (this will be executed on program start)" << std::endl; - ss << std::endl << "For questions, bug reports, feedback, requests, please open an issue at:" << std::endl; - ss << "https://github.com/turanszkij/WickedEngine" << std::endl; - ss << std::endl << "Devblog: https://wickedengine.net/" << std::endl; - ss << "Discord: https://discord.gg/CFjRYmE" << std::endl; + std::string ss; + ss += "Help:\n"; + ss += "Move camera: WASD, or Contoller left stick or D-pad\n"; + ss += "Look: Middle mouse button / arrow keys / controller right stick\n"; + ss += "Select: Right mouse button\n"; + ss += "Interact with water: Left mouse button when nothing is selected\n"; + ss += "Camera speed: SHIFT button or controller R2/RT\n"; + ss += "Camera up: E, down: Q\n"; + ss += "Duplicate entity: Ctrl + D\n"; + ss += "Select All: Ctrl + A\n"; + ss += "Undo: Ctrl + Z\n"; + ss += "Redo: Ctrl + Y\n"; + ss += "Copy: Ctrl + C\n"; + ss += "Paste: Ctrl + V\n"; + ss += "Delete: DELETE button\n"; + ss += "Place Instances: Ctrl + Shift + Left mouse click (place clipboard onto clicked surface)\n"; + ss += "Script Console / backlog: HOME button\n"; + ss += "\n"; + ss += "You can find sample scenes in the models directory. Try to load one.\n"; + ss += "You can also import models from .OBJ, .GLTF, .GLB files.\n"; + ss += "You can find a program configuration file at Editor/config.ini\n"; + ss += "You can find sample LUA scripts in the scripts directory. Try to load one.\n"; + ss += "You can find a startup script at Editor/startup.lua (this will be executed on program start)\n"; + ss += "\nFor questions, bug reports, feedback, requests, please open an issue at:\n"; + ss += "https://github.com/turanszkij/WickedEngine\n"; + ss += "\nDevblog: https://wickedengine.net/\n"; + ss += "Discord: https://discord.gg/CFjRYmE\n"; helpLabel.Create("HelpLabel"); - helpLabel.SetText(ss.str()); + helpLabel.SetText(ss); helpLabel.SetVisible(false); GetGUI().AddWidget(&helpLabel); } @@ -965,7 +975,8 @@ void EditorComponent::Load() saveModeComboBox.SetColor(wiColor(0, 255, 140, 255), wiWidget::WIDGETSTATE::FOCUS); saveModeComboBox.AddItem("Embed resources", wiResourceManager::MODE_ALLOW_RETAIN_FILEDATA); saveModeComboBox.AddItem("No embedding", wiResourceManager::MODE_ALLOW_RETAIN_FILEDATA_BUT_DISABLE_EMBEDDING); - saveModeComboBox.SetTooltip("Choose whether to embed resources (textures, sounds...) in the scene file when saving, or keep them as separate files"); + saveModeComboBox.AddItem("Dump to header", wiResourceManager::MODE_ALLOW_RETAIN_FILEDATA); + saveModeComboBox.SetTooltip("Choose whether to embed resources (textures, sounds...) in the scene file when saving, or keep them as separate files.\nThe Dump to header option will use embedding and create a C++ header file with byte data of the scene to be used with wiArchive serialization."); GetGUI().AddWidget(&saveModeComboBox); @@ -1471,7 +1482,7 @@ void EditorComponent::Update(float dt) if (!translator.selected.empty() && wiInput::Down(wiInput::KEYBOARD_BUTTON_LSHIFT)) { // Union selection: - std::vector saved = translator.selected; + wi::vector saved = translator.selected; translator.selected.clear(); for (const wiScene::PickResult& picked : saved) { @@ -1762,21 +1773,21 @@ void EditorComponent::Update(float dt) { pathtracer->setTargetSampleCount((int)pathTraceTargetSlider.GetValue()); - std::stringstream ss; - ss << "Sample count: " << pathtracer->getCurrentSampleCount() << std::endl; - ss << "Trace progress: " << int(pathtracer->getProgress() * 100) << "%" << std::endl; + std::string ss; + ss += "Sample count: " + std::to_string(pathtracer->getCurrentSampleCount()) + "\n"; + ss += "Trace progress: " + std::to_string(int(pathtracer->getProgress() * 100)) + "%\n"; if (pathtracer->isDenoiserAvailable()) { if (pathtracer->getDenoiserProgress() > 0) { - ss << "Denoiser progress: " << int(pathtracer->getDenoiserProgress() * 100) << "%" << std::endl; + ss += "Denoiser progress: " + std::to_string(int(pathtracer->getDenoiserProgress() * 100)) + "%\n"; } } else { - ss << "Denoiser not available" << std::endl; + ss += "Denoiser not available\n"; } - pathTraceStatisticsLabel.SetText(ss.str()); + pathTraceStatisticsLabel.SetText(ss); } wiProfiler::EndRange(profrange); @@ -2500,7 +2511,7 @@ void EditorComponent::ConsumeHistoryOperation(bool undo) { size_t count; archive >> count; - std::vector deletedEntities(count); + wi::vector deletedEntities(count); for (size_t i = 0; i < count; ++i) { archive >> deletedEntities[i]; @@ -2527,7 +2538,7 @@ void EditorComponent::ConsumeHistoryOperation(bool undo) { // Read selections states from archive: - std::vector selectedBEFORE; + wi::vector selectedBEFORE; size_t selectionCountBEFORE; archive >> selectionCountBEFORE; for (size_t i = 0; i < selectionCountBEFORE; ++i) @@ -2542,7 +2553,7 @@ void EditorComponent::ConsumeHistoryOperation(bool undo) selectedBEFORE.push_back(sel); } - std::vector selectedAFTER; + wi::vector selectedAFTER; size_t selectionCountAFTER; archive >> selectionCountAFTER; for (size_t i = 0; i < selectionCountAFTER; ++i) diff --git a/Editor/Editor.h b/Editor/Editor.h index a4c7bf24f..d0a5e719b 100644 --- a/Editor/Editor.h +++ b/Editor/Editor.h @@ -103,8 +103,8 @@ public: wiLabel helpLabel; wiTreeList sceneGraphView; - std::unordered_set scenegraphview_added_items; - std::unordered_set scenegraphview_opened_items; + wi::unordered_set scenegraphview_added_items; + wi::unordered_set scenegraphview_opened_items; void PushToSceneGraphView(wiECS::Entity entity, int level); void RefreshSceneGraphView(); @@ -158,7 +158,7 @@ public: wiArchive clipboard; - std::vector history; + wi::vector history; int historyPos = -1; enum HistoryOperationType { diff --git a/Editor/EmitterWindow.cpp b/Editor/EmitterWindow.cpp index 8741183e4..92f00f5d4 100644 --- a/Editor/EmitterWindow.cpp +++ b/Editor/EmitterWindow.cpp @@ -2,7 +2,7 @@ #include "EmitterWindow.h" #include "Editor.h" -#include +#include using namespace wiECS; using namespace wiScene; @@ -755,19 +755,18 @@ void EmitterWindow::UpdateData() NameComponent* name = scene.names.GetComponent(entity); NameComponent* meshName = scene.names.GetComponent(emitter->meshID); - std::stringstream ss(""); - ss.precision(2); - ss << "Emitter Mesh: " << (meshName != nullptr ? meshName->name : "NO EMITTER MESH") << " (" << emitter->meshID << ")" << std::endl; - ss << "Memort Budget: " << emitter->GetMemorySizeInBytes() / 1024.0f / 1024.0f << " MB" << std::endl; - ss << std::endl; + std::string ss; + ss += "Emitter Mesh: " + (meshName != nullptr ? meshName->name : "NO EMITTER MESH") + " (" + std::to_string(emitter->meshID) + ")\n"; + ss += "Memort Budget: " + std::to_string(emitter->GetMemorySizeInBytes() / 1024.0f / 1024.0f) + " MB\n"; + ss += "\n"; auto data = emitter->GetStatistics(); - ss << "Alive Particle Count = " << data.aliveCount << std::endl; - ss << "Dead Particle Count = " << data.deadCount << std::endl; - ss << "GPU Emit count = " << data.realEmitCount << std::endl; - ss << "Visible after frustum culling = " << data.culledCount << std::endl; + ss += "Alive Particle Count = " + std::to_string(data.aliveCount) + "\n"; + ss += "Dead Particle Count = " + std::to_string(data.deadCount) + "\n"; + ss += "GPU Emit count = " + std::to_string(data.realEmitCount) + "\n"; + ss += "Visible after frustum culling = " + std::to_string(data.culledCount) + "\n"; - infoLabel.SetText(ss.str()); + infoLabel.SetText(ss); emitterNameField.SetText(name->name); } diff --git a/Editor/MaterialWindow.cpp b/Editor/MaterialWindow.cpp index 70b89efcd..8491ea309 100644 --- a/Editor/MaterialWindow.cpp +++ b/Editor/MaterialWindow.cpp @@ -2,8 +2,6 @@ #include "MaterialWindow.h" #include "Editor.h" -#include - using namespace wiGraphics; using namespace wiECS; using namespace wiScene; diff --git a/Editor/MeshWindow.cpp b/Editor/MeshWindow.cpp index a473fee3c..38c48d97d 100644 --- a/Editor/MeshWindow.cpp +++ b/Editor/MeshWindow.cpp @@ -6,7 +6,7 @@ #include "meshoptimizer/meshoptimizer.h" -#include +#include using namespace wiECS; using namespace wiScene; @@ -366,7 +366,7 @@ void MeshWindow::Create(EditorComponent* editor) size_t index_count = mesh->indices.size(); size_t vertex_count = mesh->vertex_positions.size(); - std::vector indices(index_count); + wi::vector indices(index_count); meshopt_optimizeVertexCache(indices.data(), mesh->indices.data(), index_count, vertex_count); mesh->indices = indices; @@ -657,25 +657,25 @@ void MeshWindow::SetEntity(Entity entity, int subset) { const NameComponent& name = *scene.names.GetComponent(entity); - std::stringstream ss(""); - ss << "Mesh name: " << name.name << std::endl; - ss << "Vertex count: " << mesh->vertex_positions.size() << std::endl; - ss << "Index count: " << mesh->indices.size() << std::endl; - ss << "Subset count: " << mesh->subsets.size() << std::endl; - ss << std::endl << "Vertex buffers: "; - if (mesh->vertexBuffer_POS.IsValid()) ss << "position; "; - if (mesh->vertexBuffer_UV0.IsValid()) ss << "uvset_0; "; - if (mesh->vertexBuffer_UV1.IsValid()) ss << "uvset_1; "; - if (mesh->vertexBuffer_ATL.IsValid()) ss << "atlas; "; - if (mesh->vertexBuffer_COL.IsValid()) ss << "color; "; - if (mesh->vertexBuffer_PRE.IsValid()) ss << "previous_position; "; - if (mesh->vertexBuffer_BON.IsValid()) ss << "bone; "; - if (mesh->vertexBuffer_TAN.IsValid()) ss << "tangent; "; - if (mesh->streamoutBuffer_POS.IsValid()) ss << "streamout_position; "; - if (mesh->streamoutBuffer_TAN.IsValid()) ss << "streamout_tangents; "; - if (mesh->subsetBuffer.IsValid()) ss << "subset; "; - if (mesh->IsTerrain()) ss << std::endl << std::endl << "Terrain will use 4 blend materials and blend by vertex colors, the default one is always the subset material and uses RED vertex color channel mask, the other 3 are selectable below."; - meshInfoLabel.SetText(ss.str()); + std::string ss; + ss += "Mesh name: " + name.name + "\n"; + ss += "Vertex count: " + std::to_string(mesh->vertex_positions.size()) + "\n"; + ss += "Index count: " + std::to_string(mesh->indices.size()) + "\n"; + ss += "Subset count: " + std::to_string(mesh->subsets.size()) + "\n"; + ss += "\nVertex buffers: "; + if (mesh->vertexBuffer_POS.IsValid()) ss += "position; "; + if (mesh->vertexBuffer_UV0.IsValid()) ss += "uvset_0; "; + if (mesh->vertexBuffer_UV1.IsValid()) ss += "uvset_1; "; + if (mesh->vertexBuffer_ATL.IsValid()) ss += "atlas; "; + if (mesh->vertexBuffer_COL.IsValid()) ss += "color; "; + if (mesh->vertexBuffer_PRE.IsValid()) ss += "previous_position; "; + if (mesh->vertexBuffer_BON.IsValid()) ss += "bone; "; + if (mesh->vertexBuffer_TAN.IsValid()) ss += "tangent; "; + if (mesh->streamoutBuffer_POS.IsValid()) ss += "streamout_position; "; + if (mesh->streamoutBuffer_TAN.IsValid()) ss += "streamout_tangents; "; + if (mesh->subsetBuffer.IsValid()) ss += "subset; "; + if (mesh->IsTerrain()) ss += "\n\nTerrain will use 4 blend materials and blend by vertex colors, the default one is always the subset material and uses RED vertex color channel mask, the other 3 are selectable below."; + meshInfoLabel.SetText(ss); terrainCheckBox.SetCheck(mesh->IsTerrain()); diff --git a/Editor/ModelImporter_GLTF.cpp b/Editor/ModelImporter_GLTF.cpp index 3c0a677ab..29f8fd9c3 100644 --- a/Editor/ModelImporter_GLTF.cpp +++ b/Editor/ModelImporter_GLTF.cpp @@ -5,16 +5,16 @@ #include "Utility/stb_image.h" +#include +#include +#include + #define TINYGLTF_IMPLEMENTATION #define TINYGLTF_NO_FS #define TINYGLTF_NO_STB_IMAGE #define TINYGLTF_NO_STB_IMAGE_WRITE #include "tiny_gltf.h" -#include -#include -#include - using namespace wiGraphics; using namespace wiScene; using namespace wiECS; @@ -79,7 +79,7 @@ namespace tinygltf #endif } - bool ReadWholeFile(std::vector* out, std::string* err, + bool ReadWholeFile(wi::vector* out, std::string* err, const std::string& filepath, void*) { return wiHelper::FileRead(filepath, *out); } @@ -98,12 +98,12 @@ namespace tinygltf if (image->uri.empty()) { // Force some image resource name: - std::stringstream ss; + std::string ss; do { - ss.str(""); - ss << "gltfimport_" << wiRandom::getRandom(INT_MAX) << ".png"; - } while (wiResourceManager::Contains(ss.str())); // this is to avoid overwriting an existing imported image - image->uri = ss.str(); + ss.clear(); + ss += "gltfimport_" + std::to_string(wiRandom::getRandom(std::numeric_limits::max())) + ".png"; + } while (wiResourceManager::Contains(ss)); // this is to avoid overwriting an existing imported image + image->uri = ss; } auto resource = wiResourceManager::Load( @@ -142,7 +142,7 @@ struct LoaderState { tinygltf::Model gltfModel; Scene* scene; - std::unordered_map entityMap; // node -> entity + wi::unordered_map entityMap; // node -> entity }; // Recursively loads nodes and resolves hierarchy: @@ -278,7 +278,7 @@ void ImportModel_GLTF(const std::string& fileName, Scene& scene) LoaderState state; state.scene = &scene; - std::vector filedata; + wi::vector filedata; ret = wiHelper::FileRead(fileName, filedata); if (ret) @@ -718,7 +718,7 @@ void ImportModel_GLTF(const std::string& fileName, Scene& scene) } else { - wiBackLog::post("[KHR_materials_specular warning] specularTexture must be either in surfaceMap.a or specularColorTexture.a! specularTexture discarded!"); + wiBackLog::post("[KHR_materials_specular warning] specularTexture must be either in surfaceMap.a or specularColorTexture.a! specularTexture discarded!", wiBackLog::LogLevel::Warning); } } if (ext_specular->second.Has("specularColorTexture")) diff --git a/Editor/ModelImporter_OBJ.cpp b/Editor/ModelImporter_OBJ.cpp index 64b45a4c9..24f9edd5b 100644 --- a/Editor/ModelImporter_OBJ.cpp +++ b/Editor/ModelImporter_OBJ.cpp @@ -5,6 +5,7 @@ #define TINYOBJLOADER_IMPLEMENTATION #include "tiny_obj_loader.h" +#include #include #include @@ -26,7 +27,7 @@ public: : m_mtlBaseDir(mtl_basedir) {} virtual ~MaterialFileReader() {} virtual bool operator()(const std::string& matId, - std::vector* materials, + wi::vector* materials, std::map* matMap, std::string* err) { std::string filepath; @@ -38,13 +39,13 @@ public: filepath = matId; } - std::vector filedata; + wi::vector filedata; if (!wiHelper::FileRead(filepath, filedata)) { - std::stringstream ss; - ss << "WARN: Material file [ " << filepath << " ] not found." << std::endl; + std::string ss; + ss += "WARN: Material file [ " + filepath + " ] not found.\n"; if (err) { - (*err) += ss.str(); + (*err) += ss; } return false; } @@ -77,11 +78,11 @@ void ImportModel_OBJ(const std::string& fileName, Scene& scene) std::string name = wiHelper::GetFileNameFromPath(fileName); tinyobj::attrib_t obj_attrib; - std::vector obj_shapes; - std::vector obj_materials; + wi::vector obj_shapes; + wi::vector obj_materials; std::string obj_errors; - std::vector filedata; + wi::vector filedata; bool success = wiHelper::FileRead(fileName, filedata); if (success) @@ -98,7 +99,7 @@ void ImportModel_OBJ(const std::string& fileName, Scene& scene) if (!obj_errors.empty()) { - wiBackLog::post(obj_errors.c_str()); + wiBackLog::post(obj_errors, wiBackLog::LogLevel::Error); } if (success) @@ -108,7 +109,7 @@ void ImportModel_OBJ(const std::string& fileName, Scene& scene) scene.names.Create(rootEntity) = name; // Load material library: - std::vector materialLibrary = {}; + wi::vector materialLibrary = {}; for (auto& obj_material : obj_materials) { Entity materialEntity = scene.Entity_CreateMaterial(obj_material.name); @@ -168,8 +169,8 @@ void ImportModel_OBJ(const std::string& fileName, Scene& scene) object.meshID = meshEntity; - std::unordered_map registered_materialIndices = {}; - std::unordered_map uniqueVertices = {}; + wi::unordered_map registered_materialIndices = {}; + wi::unordered_map uniqueVertices = {}; for (size_t i = 0; i < shape.mesh.indices.size(); i += 3) { diff --git a/Editor/ObjectWindow.cpp b/Editor/ObjectWindow.cpp index 60b643645..dabb1f8a2 100644 --- a/Editor/ObjectWindow.cpp +++ b/Editor/ObjectWindow.cpp @@ -5,9 +5,7 @@ #include "xatlas.h" -#include -#include -#include +#include using namespace wiECS; using namespace wiScene; @@ -115,15 +113,15 @@ static Atlas_Dim GenerateMeshAtlas(MeshComponent& meshcomponent, uint32_t resolu // Note: we must recreate all vertex buffers, because the index buffer will be different (the atlas could have removed shared vertices) meshcomponent.indices.clear(); meshcomponent.indices.resize(mesh.indexCount); - std::vector positions(mesh.vertexCount); - std::vector atlas(mesh.vertexCount); - std::vector normals; - std::vector tangents; - std::vector uvset_0; - std::vector uvset_1; - std::vector colors; - std::vector boneindices; - std::vector boneweights; + wi::vector positions(mesh.vertexCount); + wi::vector atlas(mesh.vertexCount); + wi::vector normals; + wi::vector tangents; + wi::vector uvset_0; + wi::vector uvset_1; + wi::vector colors; + wi::vector boneindices; + wi::vector boneweights; if (!meshcomponent.vertex_normals.empty()) { normals.resize(mesh.vertexCount); @@ -651,8 +649,8 @@ void ObjectWindow::Create(EditorComponent* editor) }; UV_GEN_TYPE gen_type = (UV_GEN_TYPE)lightmapSourceUVSetComboBox.GetSelected(); - std::unordered_set gen_objects; - std::unordered_map gen_meshes; + wi::unordered_set gen_objects; + wi::unordered_map gen_meshes; for (auto& x : this->editor->translator.selected) { diff --git a/Editor/PaintToolWindow.cpp b/Editor/PaintToolWindow.cpp index e8ae7bf20..00ca9ccf3 100644 --- a/Editor/PaintToolWindow.cpp +++ b/Editor/PaintToolWindow.cpp @@ -3,7 +3,6 @@ #include "PaintToolWindow.h" #include "shaders/ShaderInterop_Renderer.h" -#include #include using namespace wiECS; @@ -179,7 +178,7 @@ void PaintToolWindow::Create(EditorComponent* editor) uint64_t sel = textureSlotComboBox.GetItemUserData(textureSlotComboBox.GetSelected()); - std::vector texturefiledata; + wi::vector texturefiledata; if (wiHelper::saveTextureToMemoryFile(editTexture, "PNG", texturefiledata)) { material->textures[sel].resource->filedata = texturefiledata; @@ -548,7 +547,7 @@ void PaintToolWindow::Update(float dt) size_t ind; float affection; }; - static std::vector paintindices; + static wi::vector paintindices; paintindices.clear(); paintindices.reserve(mesh->vertex_positions.size()); diff --git a/Editor/PaintToolWindow.h b/Editor/PaintToolWindow.h index c34563601..4708a97e4 100644 --- a/Editor/PaintToolWindow.h +++ b/Editor/PaintToolWindow.h @@ -10,7 +10,7 @@ class PaintToolWindow : public wiWindow bool history_needs_recording_start = false; bool history_needs_recording_end = false; size_t history_textureIndex = 0; - std::vector history_textures; // we'd like to keep history textures in GPU memory to avoid GPU readback + wi::vector history_textures; // we'd like to keep history textures in GPU memory to avoid GPU readback wiGraphics::Texture GetEditTextureSlot(const wiScene::MaterialComponent& material, int* uvset = nullptr); void ReplaceEditTextureSlot(wiScene::MaterialComponent& material, const wiGraphics::Texture& texture); public: diff --git a/Editor/SoundWindow.cpp b/Editor/SoundWindow.cpp index 46fd7eb43..244f73db2 100644 --- a/Editor/SoundWindow.cpp +++ b/Editor/SoundWindow.cpp @@ -3,8 +3,6 @@ #include "wiAudio.h" #include "Editor.h" -#include - using namespace wiGraphics; using namespace wiECS; using namespace wiScene; diff --git a/Editor/Translator.h b/Editor/Translator.h index 0fdbf25fd..76fea0515 100644 --- a/Editor/Translator.h +++ b/Editor/Translator.h @@ -1,8 +1,7 @@ #pragma once #include "CommonInclude.h" #include "wiCanvas.h" - -#include +#include "wiVector.h" class Translator { @@ -24,7 +23,7 @@ public: void PostTranslate(); wiScene::TransformComponent transform; - std::vector selected; + wi::vector selected; bool enabled = false; diff --git a/Editor/WeatherWindow.cpp b/Editor/WeatherWindow.cpp index 5ebbd6bb1..8458b1e2c 100644 --- a/Editor/WeatherWindow.cpp +++ b/Editor/WeatherWindow.cpp @@ -2,9 +2,6 @@ #include "WeatherWindow.h" #include "Editor.h" -#include -#include - using namespace wiECS; using namespace wiScene; using namespace wiGraphics; @@ -561,7 +558,7 @@ void WeatherWindow::Create(EditorComponent* editor) Scene& scene = wiScene::GetScene(); - std::unordered_map> conv; + wi::unordered_map> conv; for (uint32_t i = 0; i < scene.materials.GetCount(); ++i) { MaterialComponent& material = scene.materials[i]; @@ -583,7 +580,7 @@ void WeatherWindow::Create(EditorComponent* editor) if (wiHelper::saveTextureToMemory(x.second->texture, x.second->filedata)) { wiJobSystem::Execute(ctx, [&](wiJobArgs args) { - std::vector filedata_ktx2; + wi::vector filedata_ktx2; if (wiHelper::saveTextureToMemoryFile(x.second->filedata, x.second->texture.desc, "KTX2", filedata_ktx2)) { x.second = wiResourceManager::Load(x.first, wiResourceManager::IMPORT_RETAIN_FILEDATA, filedata_ktx2.data(), filedata_ktx2.size()); diff --git a/Editor/main_SDL2.cpp b/Editor/main_SDL2.cpp index 086b8a587..09df13dec 100644 --- a/Editor/main_SDL2.cpp +++ b/Editor/main_SDL2.cpp @@ -111,20 +111,23 @@ int sdl_loop(Editor &editor) break; case SDL_WINDOWEVENT_FOCUS_GAINED: editor.is_window_active = true; - std::thread([] { - wiBackLog::post("[Shader check] Started..."); - if (wiShaderCompiler::CheckRegisteredShadersOutdated()) - { - wiBackLog::post("[Shader check] Changes detected, initiating reload..."); - wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [](uint64_t userdata) { - wiRenderer::ReloadShaders(); - }); - } - else - { - wiBackLog::post("[Shader check] All up to date"); - } - }).detach(); + if (wiShaderCompiler::GetRegisteredShaderCount() > 0) + { + std::thread([] { + wiBackLog::post("[Shader check] Started checking " + std::to_string(wiShaderCompiler::GetRegisteredShaderCount()) + " registered shaders for changes..."); + if (wiShaderCompiler::CheckRegisteredShadersOutdated()) + { + wiBackLog::post("[Shader check] Changes detected, initiating reload..."); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [](uint64_t userdata) { + wiRenderer::ReloadShaders(); + }); + } + else + { + wiBackLog::post("[Shader check] All up to date"); + } + }).detach(); + } break; case SDL_WINDOWEVENT_FOCUS_LOST: editor.is_window_active = false; diff --git a/Editor/main_Windows.cpp b/Editor/main_Windows.cpp index d414f052e..44bc47cbb 100644 --- a/Editor/main_Windows.cpp +++ b/Editor/main_Windows.cpp @@ -3,6 +3,7 @@ #include "Editor.h" #include +#include #define MAX_LOADSTRING 100 @@ -247,20 +248,23 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_SETFOCUS: editor.is_window_active = true; - std::thread([] { - wiBackLog::post("[Shader check] Started..."); - if (wiShaderCompiler::CheckRegisteredShadersOutdated()) - { - wiBackLog::post("[Shader check] Changes detected, initiating reload..."); - wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [](uint64_t userdata) { - wiRenderer::ReloadShaders(); - }); - } - else - { - wiBackLog::post("[Shader check] All up to date"); - } - }).detach(); + if (wiShaderCompiler::GetRegisteredShaderCount() > 0) + { + std::thread([] { + wiBackLog::post("[Shader check] Started checking " + std::to_string(wiShaderCompiler::GetRegisteredShaderCount()) + " registered shaders for changes..."); + if (wiShaderCompiler::CheckRegisteredShadersOutdated()) + { + wiBackLog::post("[Shader check] Changes detected, initiating reload..."); + wiEvent::Subscribe_Once(SYSTEM_EVENT_THREAD_SAFE_POINT, [](uint64_t userdata) { + wiRenderer::ReloadShaders(); + }); + } + else + { + wiBackLog::post("[Shader check] All up to date"); + } + }).detach(); + } break; case WM_PAINT: { diff --git a/Example_ImGui/Example_ImGui.cpp b/Example_ImGui/Example_ImGui.cpp index 9f55b4484..0b62e37a0 100644 --- a/Example_ImGui/Example_ImGui.cpp +++ b/Example_ImGui/Example_ImGui.cpp @@ -10,8 +10,6 @@ #include "ImGui/imgui_impl_sdl.h" #endif -#include -#include #include #include diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp index 7eb5ebdcb..7371633ed 100644 --- a/Tests/Tests.cpp +++ b/Tests/Tests.cpp @@ -2,9 +2,9 @@ #include "Tests.h" #include -#include #include #include +#include using namespace wiECS; using namespace wiScene; @@ -120,6 +120,7 @@ void TestsRenderer::Load() testSelector.AddItem("Controller Test"); testSelector.AddItem("Inverse Kinematics"); testSelector.AddItem("65k Instances"); + testSelector.AddItem("unordered_map perf"); testSelector.SetMaxVisibleItemCount(10); testSelector.OnSelect([=](wiEventArgs args) { @@ -293,6 +294,10 @@ void TestsRenderer::Load() } break; + case 19: + RunUnorderedMapTest(); + break; + default: assert(0); break; @@ -403,13 +408,13 @@ void TestsRenderer::RunJobSystemTest() // This will simulate going over a big dataset first in a simple loop, then with the Job System and compare timings uint32_t itemCount = 1000000; - std::stringstream ss(""); - ss << "Job System performance test:" << std::endl; - ss << "You can find out more in Tests.cpp, RunJobSystemTest() function." << std::endl << std::endl; + std::string ss; + ss += "Job System performance test:\n"; + ss += "You can find out more in Tests.cpp, RunJobSystemTest() function.\n\n"; - ss << "wiJobSystem was created with " << wiJobSystem::GetThreadCount() << " worker threads." << std::endl << std::endl; + ss += "wiJobSystem was created with " + std::to_string(wiJobSystem::GetThreadCount()) + " worker threads.\n\n"; - ss << "1) Execute() test:" << std::endl; + ss += "1) Execute() test:\n"; // Serial test { @@ -419,7 +424,7 @@ void TestsRenderer::RunJobSystemTest() wiHelper::Spin(100); wiHelper::Spin(100); double time = timer.elapsed(); - ss << "Serial took " << time << " milliseconds" << std::endl; + ss += "Serial took " + std::to_string(time) + " milliseconds\n"; } // Execute test { @@ -430,38 +435,37 @@ void TestsRenderer::RunJobSystemTest() wiJobSystem::Execute(ctx, [](wiJobArgs args){ wiHelper::Spin(100); }); wiJobSystem::Wait(ctx); double time = timer.elapsed(); - ss << "wiJobSystem::Execute() took " << time << " milliseconds" << std::endl; + ss += "wiJobSystem::Execute() took " + std::to_string(time) + " milliseconds\n"; } - ss << std::endl; - ss << "2) Dispatch() test:" << std::endl; + ss += "\n2) Dispatch() test:\n"; // Simple loop test: { - std::vector dataSet(itemCount); + wi::vector dataSet(itemCount); timer.record(); for (uint32_t i = 0; i < itemCount; ++i) { dataSet[i].UpdateCamera(); } double time = timer.elapsed(); - ss << "Simple loop took " << time << " milliseconds" << std::endl; + ss += "Simple loop took " + std::to_string(time) + " milliseconds\n"; } // Dispatch test: { - std::vector dataSet(itemCount); + wi::vector dataSet(itemCount); timer.record(); wiJobSystem::Dispatch(ctx, itemCount, 1000, [&](wiJobArgs args) { dataSet[args.jobIndex].UpdateCamera(); }); wiJobSystem::Wait(ctx); double time = timer.elapsed(); - ss << "wiJobSystem::Dispatch() took " << time << " milliseconds" << std::endl; + ss += "wiJobSystem::Dispatch() took " + std::to_string(time) + " milliseconds\n"; } static wiSpriteFont font; - font = wiSpriteFont(ss.str()); + font = wiSpriteFont(ss); font.params.posX = GetLogicalWidth() / 2; font.params.posY = GetLogicalHeight() / 2; font.params.h_align = WIFALIGN_CENTER; @@ -509,7 +513,7 @@ void TestsRenderer::RunFontTest() font_aligned2.SetText("Right aligned, purple shadow"); AddFont(&font_aligned2); - std::stringstream ss(""); + std::string ss; std::ifstream file("font_test.txt"); if (file.is_open()) { @@ -517,7 +521,7 @@ void TestsRenderer::RunFontTest() { std::string s; file >> s; - ss << s << "\t"; + ss += s + "\t"; } } static wiSpriteFont font_japanese; @@ -527,7 +531,7 @@ void TestsRenderer::RunFontTest() font_japanese.params.shadowColor = wiColor::Transparent(); font_japanese.params.h_align = WIFALIGN_CENTER; font_japanese.params.size = 34; - font_japanese.SetText(ss.str()); + font_japanese.SetText(ss); AddFont(&font_japanese); static wiSpriteFont font_colored; @@ -926,3 +930,55 @@ void TestsRenderer::RunNetworkTest() font.params.size = 24; AddFont(&font); } +void TestsRenderer::RunUnorderedMapTest() +{ + wiTimer timer; + + const size_t elements = 1000000; +#define shuffle(i) (i * 345734667877) % 98787546343 + + std::string ss = "Unordered map test for " + std::to_string(elements) + " elements:"; + + std::unordered_map std_map; + { + timer.record(); + for (size_t i = 0; i < elements; ++i) + { + std_map[shuffle(i)] = i; + } + ss += "\n\nstd::unordered_map insertion: " + std::to_string(timer.elapsed_milliseconds()) + " ms\n"; + + timer.record(); + for (size_t i = 0; i < std_map.size(); ++i) + { + std_map[shuffle(i)] = 0; + } + ss += "std::unordered_map access: " + std::to_string(timer.elapsed_milliseconds()) + " ms"; + } + + wi::unordered_map wi_map; + { + timer.record(); + for (size_t i = 0; i < elements; ++i) + { + wi_map[shuffle(i)] = i; + } + ss += "\n\nwi::unordered_map insertion: " + std::to_string(timer.elapsed_milliseconds()) + " ms\n"; + + timer.record(); + for (size_t i = 0; i < wi_map.size(); ++i) + { + wi_map[shuffle(i)] = 0; + } + ss += "wi::unordered_map access: " + std::to_string(timer.elapsed_milliseconds()) + " ms"; + } + + static wiSpriteFont font; + font = wiSpriteFont(ss); + font.params.posX = GetLogicalWidth() / 2; + font.params.posY = GetLogicalHeight() / 2; + font.params.h_align = WIFALIGN_CENTER; + font.params.v_align = WIFALIGN_CENTER; + font.params.size = 24; + this->AddFont(&font); +} diff --git a/Tests/Tests.h b/Tests/Tests.h index 654fc1a6d..61f1abe1a 100644 --- a/Tests/Tests.h +++ b/Tests/Tests.h @@ -16,6 +16,7 @@ public: void RunFontTest(); void RunSpriteTest(); void RunNetworkTest(); + void RunUnorderedMapTest(); }; class Tests : public MainComponent diff --git a/WickedEngine/LoadingScreen.h b/WickedEngine/LoadingScreen.h index d43190675..08a6b5c5b 100644 --- a/WickedEngine/LoadingScreen.h +++ b/WickedEngine/LoadingScreen.h @@ -2,6 +2,7 @@ #include "RenderPath2D.h" #include "wiColor.h" #include "wiJobSystem.h" +#include "wiVector.h" #include @@ -12,7 +13,7 @@ class LoadingScreen : { private: wiJobSystem::context ctx; - std::vector> tasks; + wi::vector> tasks; std::function finish; public: diff --git a/WickedEngine/MainComponent.cpp b/WickedEngine/MainComponent.cpp index 3b8adff42..9d6511fe0 100644 --- a/WickedEngine/MainComponent.cpp +++ b/WickedEngine/MainComponent.cpp @@ -19,13 +19,14 @@ #include "wiGraphicsDevice_DX12.h" #include "wiGraphicsDevice_Vulkan.h" -#include +#include #include #include #include #include std::atomic number_of_heap_allocations{ 0 }; +std::atomic size_of_heap_allocations{ 0 }; using namespace wiGraphics; @@ -218,6 +219,8 @@ void MainComponent::Update(float dt) wiLua::SetDeltaTime(double(dt)); wiLua::Update(); + wiBackLog::Update(canvas, dt); + if (GetActivePath() != nullptr) { GetActivePath()->Update(dt); @@ -229,7 +232,6 @@ void MainComponent::Update(float dt) void MainComponent::FixedUpdate() { - wiBackLog::Update(canvas); wiLua::FixedUpdate(); if (GetActivePath() != nullptr) @@ -274,71 +276,73 @@ void MainComponent::Compose(CommandList cmd) // Draw the information display if (infoDisplay.active) { - std::stringstream ss(""); + infodisplay_str.clear(); if (infoDisplay.watermark) { - ss << "Wicked Engine " << wiVersion::GetVersionString() << " "; + infodisplay_str += "Wicked Engine "; + infodisplay_str += wiVersion::GetVersionString(); + infodisplay_str += " "; #if defined(_ARM) - ss << "[ARM]"; + infodisplay_str += "[ARM]"; #elif defined(_WIN64) - ss << "[64-bit]"; + infodisplay_str += "[64-bit]"; #elif defined(_WIN32) - ss << "[32-bit]"; + infodisplay_str += "[32-bit]"; #endif #ifdef PLATFORM_UWP - ss << "[UWP]"; + infodisplay_str += "[UWP]"; #endif #ifdef WICKEDENGINE_BUILD_DX12 if (dynamic_cast(graphicsDevice.get())) { - ss << "[DX12]"; + infodisplay_str += "[DX12]"; } #endif #ifdef WICKEDENGINE_BUILD_VULKAN if (dynamic_cast(graphicsDevice.get())) { - ss << "[Vulkan]"; + infodisplay_str += "[Vulkan]"; } #endif #ifdef _DEBUG - ss << "[DEBUG]"; + infodisplay_str += "[DEBUG]"; #endif if (graphicsDevice->IsDebugDevice()) { - ss << "[debugdevice]"; + infodisplay_str += "[debugdevice]"; } - ss << std::endl; + infodisplay_str += "\n"; } if (infoDisplay.resolution) { - ss << "Resolution: " << canvas.GetPhysicalWidth() << " x " << canvas.GetPhysicalHeight() << " (" << canvas.GetDPI() << " dpi)" << std::endl; + infodisplay_str += "Resolution: " + std::to_string(canvas.GetPhysicalWidth()) + " x " + std::to_string(canvas.GetPhysicalHeight()) + " (" + std::to_string(int(canvas.GetDPI())) + " dpi)\n"; } if (infoDisplay.logical_size) { - ss << "Logical Size: " << canvas.GetLogicalWidth() << " x " << canvas.GetLogicalHeight() << std::endl; + infodisplay_str += "Logical Size: " + std::to_string(int(canvas.GetLogicalWidth())) + " x " + std::to_string(int(canvas.GetLogicalHeight())) + "\n"; } if (infoDisplay.colorspace) { - ss << "Color Space: "; + infodisplay_str += "Color Space: "; ColorSpace colorSpace = graphicsDevice->GetSwapChainColorSpace(&swapChain); switch (colorSpace) { default: case wiGraphics::ColorSpace::SRGB: - ss << "sRGB"; + infodisplay_str += "sRGB"; break; case wiGraphics::ColorSpace::HDR10_ST2084: - ss << "ST.2084 (HDR10)"; + infodisplay_str += "ST.2084 (HDR10)"; break; case wiGraphics::ColorSpace::HDR_LINEAR: - ss << "Linear (HDR)"; + infodisplay_str += "Linear (HDR)"; break; } - ss << std::endl; + infodisplay_str += "\n"; } if (infoDisplay.fpsinfo) { @@ -354,29 +358,28 @@ void MainComponent::Compose(CommandList cmd) displaydeltatime = avg_time / arraysize(deltatimes); } - ss.precision(2); - ss << std::fixed << 1.0f / displaydeltatime << " FPS" << std::endl; + infodisplay_str += std::to_string(int(std::round(1.0f / displaydeltatime))) + " FPS\n"; } if (infoDisplay.heap_allocation_counter) { - ss << "Heap allocations per frame: " << number_of_heap_allocations.load() << std::endl; + infodisplay_str += "Heap allocations per frame: " + std::to_string(number_of_heap_allocations.load()) + " (" + std::to_string(size_of_heap_allocations.load()) + " bytes)\n"; number_of_heap_allocations.store(0); + size_of_heap_allocations.store(0); } if (infoDisplay.pipeline_count) { - ss << "Graphics pipelines active: " << graphicsDevice->GetActivePipelineCount() << std::endl; + infodisplay_str += "Graphics pipelines active: " + std::to_string(graphicsDevice->GetActivePipelineCount()) + "\n"; } #ifdef _DEBUG - ss << "Warning: This is a [DEBUG] build, performance will be slow!" << std::endl; + infodisplay_str += "Warning: This is a [DEBUG] build, performance will be slow!\n"; #endif if (graphicsDevice->IsDebugDevice()) { - ss << "Warning: Graphics is in [debugdevice] mode, performance will be slow!" << std::endl; + infodisplay_str += "Warning: Graphics is in [debugdevice] mode, performance will be slow!\n"; } - ss.precision(2); - wiFont::Draw(ss.str(), wiFontParams(4, 4, infoDisplay.size, WIFALIGN_LEFT, WIFALIGN_TOP, wiColor(255,255,255,255), wiColor(0,0,0,255)), cmd); + wiFont::Draw(infodisplay_str, wiFontParams(4, 4, infoDisplay.size, WIFALIGN_LEFT, WIFALIGN_TOP, wiColor(255,255,255,255), wiColor(0,0,0,255)), cmd); if (infoDisplay.colorgrading_helper) { @@ -424,7 +427,7 @@ void MainComponent::SetWindow(wiPlatform::window_type window, bool fullscreen) #elif defined(WICKEDENGINE_BUILD_VULKAN) use_vulkan = true; #else - wiBackLog::post("No rendering backend is enabled! Please enable at least one so we can use it as default"); + wiBackLog::post("No rendering backend is enabled! Please enable at least one so we can use it as default", wiBackLog::LogLevel::Error); assert(false); #endif } @@ -500,22 +503,26 @@ void MainComponent::SetWindow(wiPlatform::window_type window, bool fullscreen) void* operator new(std::size_t size) { number_of_heap_allocations.fetch_add(1); + size_of_heap_allocations.fetch_add(size); void* p = malloc(size); if (!p) throw std::bad_alloc(); return p; } void* operator new[](std::size_t size) { number_of_heap_allocations.fetch_add(1); + size_of_heap_allocations.fetch_add(size); void* p = malloc(size); if (!p) throw std::bad_alloc(); return p; } void* operator new[](std::size_t size, const std::nothrow_t&) throw() { number_of_heap_allocations.fetch_add(1); + size_of_heap_allocations.fetch_add(size); return malloc(size); } void* operator new(std::size_t size, const std::nothrow_t&) throw() { number_of_heap_allocations.fetch_add(1); + size_of_heap_allocations.fetch_add(size); return malloc(size); } void operator delete(void* ptr) throw() { free(ptr); } diff --git a/WickedEngine/MainComponent.h b/WickedEngine/MainComponent.h index 14666f4d5..fc07d58ad 100644 --- a/WickedEngine/MainComponent.h +++ b/WickedEngine/MainComponent.h @@ -9,6 +9,7 @@ #include "wiCanvas.h" #include +#include class RenderPath; @@ -38,6 +39,8 @@ protected: wiGraphics::Texture rendertarget; wiGraphics::RenderPass renderpass; + std::string infodisplay_str; + public: virtual ~MainComponent() = default; diff --git a/WickedEngine/MainComponent_BindLua.cpp b/WickedEngine/MainComponent_BindLua.cpp index 6f872cc74..dc27291dd 100644 --- a/WickedEngine/MainComponent_BindLua.cpp +++ b/WickedEngine/MainComponent_BindLua.cpp @@ -17,7 +17,9 @@ Luna::FunctionType MainComponent_BindLua::methods[] = { lunamethod(MainComponent_BindLua, SetWatermarkDisplay), lunamethod(MainComponent_BindLua, SetFPSDisplay), lunamethod(MainComponent_BindLua, SetResolutionDisplay), + lunamethod(MainComponent_BindLua, SetLogicalSizeDisplay), lunamethod(MainComponent_BindLua, SetPipelineCountDisplay), + lunamethod(MainComponent_BindLua, SetHeapAllocationCountDisplay), lunamethod(MainComponent_BindLua, GetCanvas), { NULL, NULL } }; @@ -257,6 +259,22 @@ int MainComponent_BindLua::SetResolutionDisplay(lua_State *L) wiLua::SError(L, "SetResolutionDisplay(bool active) not enough arguments!"); return 0; } +int MainComponent_BindLua::SetLogicalSizeDisplay(lua_State* L) +{ + if (component == nullptr) + { + wiLua::SError(L, "SetLogicalSizeDisplay() component is empty!"); + return 0; + } + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + component->infoDisplay.logical_size = wiLua::SGetBool(L, 1); + } + else + wiLua::SError(L, "SetLogicalSizeDisplay(bool active) not enough arguments!"); + return 0; +} int MainComponent_BindLua::SetPipelineCountDisplay(lua_State *L) { if (component == nullptr) @@ -273,6 +291,22 @@ int MainComponent_BindLua::SetPipelineCountDisplay(lua_State *L) wiLua::SError(L, "SetPipelineCountDisplay(bool active) not enough arguments!"); return 0; } +int MainComponent_BindLua::SetHeapAllocationCountDisplay(lua_State* L) +{ + if (component == nullptr) + { + wiLua::SError(L, "SetHeapAllocationCountDisplay() component is empty!"); + return 0; + } + int argc = wiLua::SGetArgCount(L); + if (argc > 0) + { + component->infoDisplay.heap_allocation_counter = wiLua::SGetBool(L, 1); + } + else + wiLua::SError(L, "SetHeapAllocationCountDisplay(bool active) not enough arguments!"); + return 0; +} int MainComponent_BindLua::GetCanvas(lua_State* L) { diff --git a/WickedEngine/MainComponent_BindLua.h b/WickedEngine/MainComponent_BindLua.h index 0c4cc580f..a64f862a2 100644 --- a/WickedEngine/MainComponent_BindLua.h +++ b/WickedEngine/MainComponent_BindLua.h @@ -44,8 +44,10 @@ public: int SetInfoDisplay(lua_State *L); int SetWatermarkDisplay(lua_State *L); int SetFPSDisplay(lua_State *L); - int SetResolutionDisplay(lua_State *L); + int SetResolutionDisplay(lua_State* L); + int SetLogicalSizeDisplay(lua_State *L); int SetPipelineCountDisplay(lua_State* L); + int SetHeapAllocationCountDisplay(lua_State* L); int GetCanvas(lua_State* L); diff --git a/WickedEngine/RenderPath2D.cpp b/WickedEngine/RenderPath2D.cpp index aacd6e6b0..e3a6df56b 100644 --- a/WickedEngine/RenderPath2D.cpp +++ b/WickedEngine/RenderPath2D.cpp @@ -536,7 +536,7 @@ void RenderPath2D::CleanLayers() { continue; } - std::vector itemsToRetain(0); + wi::vector itemsToRetain(0); for (auto& y : x.items) { if (y.sprite != nullptr || y.font!=nullptr) diff --git a/WickedEngine/RenderPath2D.h b/WickedEngine/RenderPath2D.h index b8b8edc8d..728dd82ec 100644 --- a/WickedEngine/RenderPath2D.h +++ b/WickedEngine/RenderPath2D.h @@ -1,6 +1,7 @@ #pragma once #include "RenderPath.h" #include "wiGUI.h" +#include "wiVector.h" #include @@ -23,7 +24,7 @@ struct RenderItem2D }; struct RenderLayer2D { - std::vector items; + wi::vector items; std::string name; int order = 0; }; @@ -76,7 +77,7 @@ public: void ClearFonts(); int GetFontOrder(wiSpriteFont* font); - std::vector layers{ 1 }; + wi::vector layers{ 1 }; void AddLayer(const std::string& name); void SetLayerOrder(const std::string& name, int order); void SetSpriteOrder(wiSprite* sprite, int order); diff --git a/WickedEngine/RenderPath2D_BindLua.cpp b/WickedEngine/RenderPath2D_BindLua.cpp index 4eab50d16..4508043ca 100644 --- a/WickedEngine/RenderPath2D_BindLua.cpp +++ b/WickedEngine/RenderPath2D_BindLua.cpp @@ -2,7 +2,7 @@ #include "wiSprite_BindLua.h" #include "wiSpriteFont_BindLua.h" -#include +#include const char RenderPath2D_BindLua::className[] = "RenderPath2D"; @@ -302,12 +302,12 @@ int RenderPath2D_BindLua::GetLayers(lua_State* L) RenderPath2D* ccomp = dynamic_cast(component); if (ccomp != nullptr) { - std::stringstream ss(""); + std::string ss; for (auto& x : ccomp->layers) { - ss << x.name << std::endl; + ss += x.name + "\n"; } - wiLua::SSetString(L, ss.str()); + wiLua::SSetString(L, ss); return 1; } else diff --git a/WickedEngine/RenderPath3D_PathTracing.cpp b/WickedEngine/RenderPath3D_PathTracing.cpp index 5a2fc8a8d..477524468 100644 --- a/WickedEngine/RenderPath3D_PathTracing.cpp +++ b/WickedEngine/RenderPath3D_PathTracing.cpp @@ -215,7 +215,7 @@ void RenderPath3D_PathTracing::Update(float dt) auto error = device.getError(errorMessage); if (error != oidn::Error::None && error != oidn::Error::Cancelled) { - wiBackLog::post((std::string("[OpenImageDenoise error] ") + errorMessage).c_str()); + wiBackLog::post(std::string("[OpenImageDenoise error] ") + errorMessage); } } diff --git a/WickedEngine/RenderPath3D_PathTracing.h b/WickedEngine/RenderPath3D_PathTracing.h index 4644a26d3..7fe4c6223 100644 --- a/WickedEngine/RenderPath3D_PathTracing.h +++ b/WickedEngine/RenderPath3D_PathTracing.h @@ -1,6 +1,6 @@ #pragma once #include "RenderPath3D.h" - +#include "wiVector.h" class RenderPath3D_PathTracing : public RenderPath3D @@ -10,10 +10,10 @@ protected: int target = 1024; wiGraphics::Texture traceResult; - std::vector texturedata_src; - std::vector texturedata_dst; - std::vector texturedata_albedo; - std::vector texturedata_normal; + wi::vector texturedata_src; + wi::vector texturedata_dst; + wi::vector texturedata_albedo; + wi::vector texturedata_normal; wiGraphics::Texture denoiserAlbedo; wiGraphics::Texture denoiserNormal; wiGraphics::Texture denoiserResult; diff --git a/WickedEngine/Utility/flat_hash_map.hpp b/WickedEngine/Utility/flat_hash_map.hpp new file mode 100644 index 000000000..633bd4b47 --- /dev/null +++ b/WickedEngine/Utility/flat_hash_map.hpp @@ -0,0 +1,1497 @@ +// Copyright Malte Skarupke 2017. +// Distributed under the Boost Software License, Version 1.0. +// (See http://www.boost.org/LICENSE_1_0.txt) + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define SKA_NOINLINE(...) __declspec(noinline) __VA_ARGS__ +#else +#define SKA_NOINLINE(...) __VA_ARGS__ __attribute__((noinline)) +#endif + +namespace ska +{ +struct prime_number_hash_policy; +struct power_of_two_hash_policy; +struct fibonacci_hash_policy; + +namespace detailv3 +{ +template +struct functor_storage : Functor +{ + functor_storage() = default; + functor_storage(const Functor & functor) + : Functor(functor) + { + } + template + Result operator()(Args &&... args) + { + return static_cast(*this)(std::forward(args)...); + } + template + Result operator()(Args &&... args) const + { + return static_cast(*this)(std::forward(args)...); + } +}; +template +struct functor_storage +{ + typedef Result (*function_ptr)(Args...); + function_ptr function; + functor_storage(function_ptr function) + : function(function) + { + } + Result operator()(Args... args) const + { + return function(std::forward(args)...); + } + operator function_ptr &() + { + return function; + } + operator const function_ptr &() + { + return function; + } +}; +template +struct KeyOrValueHasher : functor_storage +{ + typedef functor_storage hasher_storage; + KeyOrValueHasher() = default; + KeyOrValueHasher(const hasher & hash) + : hasher_storage(hash) + { + } + size_t operator()(const key_type & key) + { + return static_cast(*this)(key); + } + size_t operator()(const key_type & key) const + { + return static_cast(*this)(key); + } + size_t operator()(const value_type & value) + { + return static_cast(*this)(value.first); + } + size_t operator()(const value_type & value) const + { + return static_cast(*this)(value.first); + } + template + size_t operator()(const std::pair & value) + { + return static_cast(*this)(value.first); + } + template + size_t operator()(const std::pair & value) const + { + return static_cast(*this)(value.first); + } +}; +template +struct KeyOrValueEquality : functor_storage +{ + typedef functor_storage equality_storage; + KeyOrValueEquality() = default; + KeyOrValueEquality(const key_equal & equality) + : equality_storage(equality) + { + } + bool operator()(const key_type & lhs, const key_type & rhs) + { + return static_cast(*this)(lhs, rhs); + } + bool operator()(const key_type & lhs, const value_type & rhs) + { + return static_cast(*this)(lhs, rhs.first); + } + bool operator()(const value_type & lhs, const key_type & rhs) + { + return static_cast(*this)(lhs.first, rhs); + } + bool operator()(const value_type & lhs, const value_type & rhs) + { + return static_cast(*this)(lhs.first, rhs.first); + } + template + bool operator()(const key_type & lhs, const std::pair & rhs) + { + return static_cast(*this)(lhs, rhs.first); + } + template + bool operator()(const std::pair & lhs, const key_type & rhs) + { + return static_cast(*this)(lhs.first, rhs); + } + template + bool operator()(const value_type & lhs, const std::pair & rhs) + { + return static_cast(*this)(lhs.first, rhs.first); + } + template + bool operator()(const std::pair & lhs, const value_type & rhs) + { + return static_cast(*this)(lhs.first, rhs.first); + } + template + bool operator()(const std::pair & lhs, const std::pair & rhs) + { + return static_cast(*this)(lhs.first, rhs.first); + } +}; +static constexpr int8_t min_lookups = 4; +template +struct sherwood_v3_entry +{ + sherwood_v3_entry() + { + } + sherwood_v3_entry(int8_t distance_from_desired) + : distance_from_desired(distance_from_desired) + { + } + ~sherwood_v3_entry() + { + } + static sherwood_v3_entry * empty_default_table() + { + static sherwood_v3_entry result[min_lookups] = { {}, {}, {}, {special_end_value} }; + return result; + } + + bool has_value() const + { + return distance_from_desired >= 0; + } + bool is_empty() const + { + return distance_from_desired < 0; + } + bool is_at_desired_position() const + { + return distance_from_desired <= 0; + } + template + void emplace(int8_t distance, Args &&... args) + { + new (std::addressof(value)) T(std::forward(args)...); + distance_from_desired = distance; + } + + void destroy_value() + { + value.~T(); + distance_from_desired = -1; + } + + int8_t distance_from_desired = -1; + static constexpr int8_t special_end_value = 0; + union { T value; }; +}; + +inline int8_t log2(size_t value) +{ + static constexpr int8_t table[64] = + { + 63, 0, 58, 1, 59, 47, 53, 2, + 60, 39, 48, 27, 54, 33, 42, 3, + 61, 51, 37, 40, 49, 18, 28, 20, + 55, 30, 34, 11, 43, 14, 22, 4, + 62, 57, 46, 52, 38, 26, 32, 41, + 50, 36, 17, 19, 29, 10, 13, 21, + 56, 45, 25, 31, 35, 16, 9, 12, + 44, 24, 15, 8, 23, 7, 6, 5 + }; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + value |= value >> 32; + return table[((value - (value >> 1)) * 0x07EDD5E59A4E28C2) >> 58]; +} + +template +struct AssignIfTrue +{ + void operator()(T & lhs, const T & rhs) + { + lhs = rhs; + } + void operator()(T & lhs, T && rhs) + { + lhs = std::move(rhs); + } +}; +template +struct AssignIfTrue +{ + void operator()(T &, const T &) + { + } + void operator()(T &, T &&) + { + } +}; + +inline size_t next_power_of_two(size_t i) +{ + --i; + i |= i >> 1; + i |= i >> 2; + i |= i >> 4; + i |= i >> 8; + i |= i >> 16; + i |= i >> 32; + ++i; + return i; +} + +template using void_t = void; + +template +struct HashPolicySelector +{ + typedef fibonacci_hash_policy type; +}; +template +struct HashPolicySelector> +{ + typedef typename T::hash_policy type; +}; + +template +class sherwood_v3_table : private EntryAlloc, private Hasher, private Equal +{ + using Entry = detailv3::sherwood_v3_entry; + using AllocatorTraits = std::allocator_traits; + using EntryPointer = typename AllocatorTraits::pointer; + struct convertible_to_iterator; + +public: + + using value_type = T; + using size_type = size_t; + using difference_type = std::ptrdiff_t; + using hasher = ArgumentHash; + using key_equal = ArgumentEqual; + using allocator_type = EntryAlloc; + using reference = value_type &; + using const_reference = const value_type &; + using pointer = value_type *; + using const_pointer = const value_type *; + + sherwood_v3_table() + { + } + explicit sherwood_v3_table(size_type bucket_count, const ArgumentHash & hash = ArgumentHash(), const ArgumentEqual & equal = ArgumentEqual(), const ArgumentAlloc & alloc = ArgumentAlloc()) + : EntryAlloc(alloc), Hasher(hash), Equal(equal) + { + rehash(bucket_count); + } + sherwood_v3_table(size_type bucket_count, const ArgumentAlloc & alloc) + : sherwood_v3_table(bucket_count, ArgumentHash(), ArgumentEqual(), alloc) + { + } + sherwood_v3_table(size_type bucket_count, const ArgumentHash & hash, const ArgumentAlloc & alloc) + : sherwood_v3_table(bucket_count, hash, ArgumentEqual(), alloc) + { + } + explicit sherwood_v3_table(const ArgumentAlloc & alloc) + : EntryAlloc(alloc) + { + } + template + sherwood_v3_table(It first, It last, size_type bucket_count = 0, const ArgumentHash & hash = ArgumentHash(), const ArgumentEqual & equal = ArgumentEqual(), const ArgumentAlloc & alloc = ArgumentAlloc()) + : sherwood_v3_table(bucket_count, hash, equal, alloc) + { + insert(first, last); + } + template + sherwood_v3_table(It first, It last, size_type bucket_count, const ArgumentAlloc & alloc) + : sherwood_v3_table(first, last, bucket_count, ArgumentHash(), ArgumentEqual(), alloc) + { + } + template + sherwood_v3_table(It first, It last, size_type bucket_count, const ArgumentHash & hash, const ArgumentAlloc & alloc) + : sherwood_v3_table(first, last, bucket_count, hash, ArgumentEqual(), alloc) + { + } + sherwood_v3_table(std::initializer_list il, size_type bucket_count = 0, const ArgumentHash & hash = ArgumentHash(), const ArgumentEqual & equal = ArgumentEqual(), const ArgumentAlloc & alloc = ArgumentAlloc()) + : sherwood_v3_table(bucket_count, hash, equal, alloc) + { + if (bucket_count == 0) + rehash(il.size()); + insert(il.begin(), il.end()); + } + sherwood_v3_table(std::initializer_list il, size_type bucket_count, const ArgumentAlloc & alloc) + : sherwood_v3_table(il, bucket_count, ArgumentHash(), ArgumentEqual(), alloc) + { + } + sherwood_v3_table(std::initializer_list il, size_type bucket_count, const ArgumentHash & hash, const ArgumentAlloc & alloc) + : sherwood_v3_table(il, bucket_count, hash, ArgumentEqual(), alloc) + { + } + sherwood_v3_table(const sherwood_v3_table & other) + : sherwood_v3_table(other, AllocatorTraits::select_on_container_copy_construction(other.get_allocator())) + { + } + sherwood_v3_table(const sherwood_v3_table & other, const ArgumentAlloc & alloc) + : EntryAlloc(alloc), Hasher(other), Equal(other), _max_load_factor(other._max_load_factor) + { + rehash_for_other_container(other); + try + { + insert(other.begin(), other.end()); + } + catch(...) + { + clear(); + deallocate_data(entries, num_slots_minus_one, max_lookups); + throw; + } + } + sherwood_v3_table(sherwood_v3_table && other) noexcept + : EntryAlloc(std::move(other)), Hasher(std::move(other)), Equal(std::move(other)) + { + swap_pointers(other); + } + sherwood_v3_table(sherwood_v3_table && other, const ArgumentAlloc & alloc) noexcept + : EntryAlloc(alloc), Hasher(std::move(other)), Equal(std::move(other)) + { + swap_pointers(other); + } + sherwood_v3_table & operator=(const sherwood_v3_table & other) + { + if (this == std::addressof(other)) + return *this; + + clear(); + if (AllocatorTraits::propagate_on_container_copy_assignment::value) + { + if (static_cast(*this) != static_cast(other)) + { + reset_to_empty_state(); + } + AssignIfTrue()(*this, other); + } + _max_load_factor = other._max_load_factor; + static_cast(*this) = other; + static_cast(*this) = other; + rehash_for_other_container(other); + insert(other.begin(), other.end()); + return *this; + } + sherwood_v3_table & operator=(sherwood_v3_table && other) noexcept + { + if (this == std::addressof(other)) + return *this; + else if (AllocatorTraits::propagate_on_container_move_assignment::value) + { + clear(); + reset_to_empty_state(); + AssignIfTrue()(*this, std::move(other)); + swap_pointers(other); + } + else if (static_cast(*this) == static_cast(other)) + { + swap_pointers(other); + } + else + { + clear(); + _max_load_factor = other._max_load_factor; + rehash_for_other_container(other); + for (T & elem : other) + emplace(std::move(elem)); + other.clear(); + } + static_cast(*this) = std::move(other); + static_cast(*this) = std::move(other); + return *this; + } + ~sherwood_v3_table() + { + clear(); + deallocate_data(entries, num_slots_minus_one, max_lookups); + } + + const allocator_type & get_allocator() const + { + return static_cast(*this); + } + const ArgumentEqual & key_eq() const + { + return static_cast(*this); + } + const ArgumentHash & hash_function() const + { + return static_cast(*this); + } + + template + struct templated_iterator + { + templated_iterator() = default; + templated_iterator(EntryPointer current) + : current(current) + { + } + EntryPointer current = EntryPointer(); + + using iterator_category = std::forward_iterator_tag; + using value_type = ValueType; + using difference_type = ptrdiff_t; + using pointer = ValueType *; + using reference = ValueType &; + + friend bool operator==(const templated_iterator & lhs, const templated_iterator & rhs) + { + return lhs.current == rhs.current; + } + friend bool operator!=(const templated_iterator & lhs, const templated_iterator & rhs) + { + return !(lhs == rhs); + } + + templated_iterator & operator++() + { + do + { + ++current; + } + while(current->is_empty()); + return *this; + } + templated_iterator operator++(int) + { + templated_iterator copy(*this); + ++*this; + return copy; + } + + ValueType & operator*() const + { + return current->value; + } + ValueType * operator->() const + { + return std::addressof(current->value); + } + + operator templated_iterator() const + { + return { current }; + } + }; + using iterator = templated_iterator; + using const_iterator = templated_iterator; + + iterator begin() + { + for (EntryPointer it = entries;; ++it) + { + if (it->has_value()) + return { it }; + } + } + const_iterator begin() const + { + for (EntryPointer it = entries;; ++it) + { + if (it->has_value()) + return { it }; + } + } + const_iterator cbegin() const + { + return begin(); + } + iterator end() + { + return { entries + static_cast(num_slots_minus_one + max_lookups) }; + } + const_iterator end() const + { + return { entries + static_cast(num_slots_minus_one + max_lookups) }; + } + const_iterator cend() const + { + return end(); + } + + iterator find(const FindKey & key) + { + size_t index = hash_policy.index_for_hash(hash_object(key), num_slots_minus_one); + EntryPointer it = entries + ptrdiff_t(index); + for (int8_t distance = 0; it->distance_from_desired >= distance; ++distance, ++it) + { + if (compares_equal(key, it->value)) + return { it }; + } + return end(); + } + const_iterator find(const FindKey & key) const + { + return const_cast(this)->find(key); + } + size_t count(const FindKey & key) const + { + return find(key) == end() ? 0 : 1; + } + std::pair equal_range(const FindKey & key) + { + iterator found = find(key); + if (found == end()) + return { found, found }; + else + return { found, std::next(found) }; + } + std::pair equal_range(const FindKey & key) const + { + const_iterator found = find(key); + if (found == end()) + return { found, found }; + else + return { found, std::next(found) }; + } + + template + std::pair emplace(Key && key, Args &&... args) + { + size_t index = hash_policy.index_for_hash(hash_object(key), num_slots_minus_one); + EntryPointer current_entry = entries + ptrdiff_t(index); + int8_t distance_from_desired = 0; + for (; current_entry->distance_from_desired >= distance_from_desired; ++current_entry, ++distance_from_desired) + { + if (compares_equal(key, current_entry->value)) + return { { current_entry }, false }; + } + return emplace_new_key(distance_from_desired, current_entry, std::forward(key), std::forward(args)...); + } + + std::pair insert(const value_type & value) + { + return emplace(value); + } + std::pair insert(value_type && value) + { + return emplace(std::move(value)); + } + template + iterator emplace_hint(const_iterator, Args &&... args) + { + return emplace(std::forward(args)...).first; + } + iterator insert(const_iterator, const value_type & value) + { + return emplace(value).first; + } + iterator insert(const_iterator, value_type && value) + { + return emplace(std::move(value)).first; + } + + template + void insert(It begin, It end) + { + for (; begin != end; ++begin) + { + emplace(*begin); + } + } + void insert(std::initializer_list il) + { + insert(il.begin(), il.end()); + } + + void rehash(size_t num_buckets) + { + num_buckets = std::max(num_buckets, static_cast(std::ceil(num_elements / static_cast(_max_load_factor)))); + if (num_buckets == 0) + { + reset_to_empty_state(); + return; + } + auto new_prime_index = hash_policy.next_size_over(num_buckets); + if (num_buckets == bucket_count()) + return; + int8_t new_max_lookups = compute_max_lookups(num_buckets); + EntryPointer new_buckets(AllocatorTraits::allocate(*this, num_buckets + new_max_lookups)); + EntryPointer special_end_item = new_buckets + static_cast(num_buckets + new_max_lookups - 1); + for (EntryPointer it = new_buckets; it != special_end_item; ++it) + it->distance_from_desired = -1; + special_end_item->distance_from_desired = Entry::special_end_value; + std::swap(entries, new_buckets); + std::swap(num_slots_minus_one, num_buckets); + --num_slots_minus_one; + hash_policy.commit(new_prime_index); + int8_t old_max_lookups = max_lookups; + max_lookups = new_max_lookups; + num_elements = 0; + for (EntryPointer it = new_buckets, end = it + static_cast(num_buckets + old_max_lookups); it != end; ++it) + { + if (it->has_value()) + { + emplace(std::move(it->value)); + it->destroy_value(); + } + } + deallocate_data(new_buckets, num_buckets, old_max_lookups); + } + + void reserve(size_t num_elements) + { + size_t required_buckets = num_buckets_for_reserve(num_elements); + if (required_buckets > bucket_count()) + rehash(required_buckets); + } + + // the return value is a type that can be converted to an iterator + // the reason for doing this is that it's not free to find the + // iterator pointing at the next element. if you care about the + // next iterator, turn the return value into an iterator + convertible_to_iterator erase(const_iterator to_erase) + { + EntryPointer current = to_erase.current; + current->destroy_value(); + --num_elements; + for (EntryPointer next = current + ptrdiff_t(1); !next->is_at_desired_position(); ++current, ++next) + { + current->emplace(next->distance_from_desired - 1, std::move(next->value)); + next->destroy_value(); + } + return { to_erase.current }; + } + + iterator erase(const_iterator begin_it, const_iterator end_it) + { + if (begin_it == end_it) + return { begin_it.current }; + for (EntryPointer it = begin_it.current, end = end_it.current; it != end; ++it) + { + if (it->has_value()) + { + it->destroy_value(); + --num_elements; + } + } + if (end_it == this->end()) + return this->end(); + ptrdiff_t num_to_move = std::min(static_cast(end_it.current->distance_from_desired), end_it.current - begin_it.current); + EntryPointer to_return = end_it.current - num_to_move; + for (EntryPointer it = end_it.current; !it->is_at_desired_position();) + { + EntryPointer target = it - num_to_move; + target->emplace(it->distance_from_desired - num_to_move, std::move(it->value)); + it->destroy_value(); + ++it; + num_to_move = std::min(static_cast(it->distance_from_desired), num_to_move); + } + return { to_return }; + } + + size_t erase(const FindKey & key) + { + auto found = find(key); + if (found == end()) + return 0; + else + { + erase(found); + return 1; + } + } + + void clear() + { + for (EntryPointer it = entries, end = it + static_cast(num_slots_minus_one + max_lookups); it != end; ++it) + { + if (it->has_value()) + it->destroy_value(); + } + num_elements = 0; + } + + void shrink_to_fit() + { + rehash_for_other_container(*this); + } + + void swap(sherwood_v3_table & other) + { + using std::swap; + swap_pointers(other); + swap(static_cast(*this), static_cast(other)); + swap(static_cast(*this), static_cast(other)); + if (AllocatorTraits::propagate_on_container_swap::value) + swap(static_cast(*this), static_cast(other)); + } + + size_t size() const + { + return num_elements; + } + size_t max_size() const + { + return (AllocatorTraits::max_size(*this)) / sizeof(Entry); + } + size_t bucket_count() const + { + return num_slots_minus_one ? num_slots_minus_one + 1 : 0; + } + size_type max_bucket_count() const + { + return (AllocatorTraits::max_size(*this) - min_lookups) / sizeof(Entry); + } + size_t bucket(const FindKey & key) const + { + return hash_policy.index_for_hash(hash_object(key), num_slots_minus_one); + } + float load_factor() const + { + size_t buckets = bucket_count(); + if (buckets) + return static_cast(num_elements) / bucket_count(); + else + return 0; + } + void max_load_factor(float value) + { + _max_load_factor = value; + } + float max_load_factor() const + { + return _max_load_factor; + } + + bool empty() const + { + return num_elements == 0; + } + +private: + EntryPointer entries = Entry::empty_default_table(); + size_t num_slots_minus_one = 0; + typename HashPolicySelector::type hash_policy; + int8_t max_lookups = detailv3::min_lookups - 1; + float _max_load_factor = 0.5f; + size_t num_elements = 0; + + static int8_t compute_max_lookups(size_t num_buckets) + { + int8_t desired = detailv3::log2(num_buckets); + return std::max(detailv3::min_lookups, desired); + } + + size_t num_buckets_for_reserve(size_t num_elements) const + { + return static_cast(std::ceil(num_elements / std::min(0.5, static_cast(_max_load_factor)))); + } + void rehash_for_other_container(const sherwood_v3_table & other) + { + rehash(std::min(num_buckets_for_reserve(other.size()), other.bucket_count())); + } + + void swap_pointers(sherwood_v3_table & other) + { + using std::swap; + swap(hash_policy, other.hash_policy); + swap(entries, other.entries); + swap(num_slots_minus_one, other.num_slots_minus_one); + swap(num_elements, other.num_elements); + swap(max_lookups, other.max_lookups); + swap(_max_load_factor, other._max_load_factor); + } + + template + SKA_NOINLINE(std::pair) emplace_new_key(int8_t distance_from_desired, EntryPointer current_entry, Key && key, Args &&... args) + { + using std::swap; + if (num_slots_minus_one == 0 || distance_from_desired == max_lookups || num_elements + 1 > (num_slots_minus_one + 1) * static_cast(_max_load_factor)) + { + grow(); + return emplace(std::forward(key), std::forward(args)...); + } + else if (current_entry->is_empty()) + { + current_entry->emplace(distance_from_desired, std::forward(key), std::forward(args)...); + ++num_elements; + return { { current_entry }, true }; + } + value_type to_insert(std::forward(key), std::forward(args)...); + swap(distance_from_desired, current_entry->distance_from_desired); + swap(to_insert, current_entry->value); + iterator result = { current_entry }; + for (++distance_from_desired, ++current_entry;; ++current_entry) + { + if (current_entry->is_empty()) + { + current_entry->emplace(distance_from_desired, std::move(to_insert)); + ++num_elements; + return { result, true }; + } + else if (current_entry->distance_from_desired < distance_from_desired) + { + swap(distance_from_desired, current_entry->distance_from_desired); + swap(to_insert, current_entry->value); + ++distance_from_desired; + } + else + { + ++distance_from_desired; + if (distance_from_desired == max_lookups) + { + swap(to_insert, result.current->value); + grow(); + return emplace(std::move(to_insert)); + } + } + } + } + + void grow() + { + rehash(std::max(size_t(4), 2 * bucket_count())); + } + + void deallocate_data(EntryPointer begin, size_t num_slots_minus_one, int8_t max_lookups) + { + if (begin != Entry::empty_default_table()) + { + AllocatorTraits::deallocate(*this, begin, num_slots_minus_one + max_lookups + 1); + } + } + + void reset_to_empty_state() + { + deallocate_data(entries, num_slots_minus_one, max_lookups); + entries = Entry::empty_default_table(); + num_slots_minus_one = 0; + hash_policy.reset(); + max_lookups = detailv3::min_lookups - 1; + } + + template + size_t hash_object(const U & key) + { + return static_cast(*this)(key); + } + template + size_t hash_object(const U & key) const + { + return static_cast(*this)(key); + } + template + bool compares_equal(const L & lhs, const R & rhs) + { + return static_cast(*this)(lhs, rhs); + } + + struct convertible_to_iterator + { + EntryPointer it; + + operator iterator() + { + if (it->has_value()) + return { it }; + else + return ++iterator{it}; + } + operator const_iterator() + { + if (it->has_value()) + return { it }; + else + return ++const_iterator{it}; + } + }; + +}; +} + +struct prime_number_hash_policy +{ + static size_t mod0(size_t) { return 0llu; } + static size_t mod2(size_t hash) { return hash % 2llu; } + static size_t mod3(size_t hash) { return hash % 3llu; } + static size_t mod5(size_t hash) { return hash % 5llu; } + static size_t mod7(size_t hash) { return hash % 7llu; } + static size_t mod11(size_t hash) { return hash % 11llu; } + static size_t mod13(size_t hash) { return hash % 13llu; } + static size_t mod17(size_t hash) { return hash % 17llu; } + static size_t mod23(size_t hash) { return hash % 23llu; } + static size_t mod29(size_t hash) { return hash % 29llu; } + static size_t mod37(size_t hash) { return hash % 37llu; } + static size_t mod47(size_t hash) { return hash % 47llu; } + static size_t mod59(size_t hash) { return hash % 59llu; } + static size_t mod73(size_t hash) { return hash % 73llu; } + static size_t mod97(size_t hash) { return hash % 97llu; } + static size_t mod127(size_t hash) { return hash % 127llu; } + static size_t mod151(size_t hash) { return hash % 151llu; } + static size_t mod197(size_t hash) { return hash % 197llu; } + static size_t mod251(size_t hash) { return hash % 251llu; } + static size_t mod313(size_t hash) { return hash % 313llu; } + static size_t mod397(size_t hash) { return hash % 397llu; } + static size_t mod499(size_t hash) { return hash % 499llu; } + static size_t mod631(size_t hash) { return hash % 631llu; } + static size_t mod797(size_t hash) { return hash % 797llu; } + static size_t mod1009(size_t hash) { return hash % 1009llu; } + static size_t mod1259(size_t hash) { return hash % 1259llu; } + static size_t mod1597(size_t hash) { return hash % 1597llu; } + static size_t mod2011(size_t hash) { return hash % 2011llu; } + static size_t mod2539(size_t hash) { return hash % 2539llu; } + static size_t mod3203(size_t hash) { return hash % 3203llu; } + static size_t mod4027(size_t hash) { return hash % 4027llu; } + static size_t mod5087(size_t hash) { return hash % 5087llu; } + static size_t mod6421(size_t hash) { return hash % 6421llu; } + static size_t mod8089(size_t hash) { return hash % 8089llu; } + static size_t mod10193(size_t hash) { return hash % 10193llu; } + static size_t mod12853(size_t hash) { return hash % 12853llu; } + static size_t mod16193(size_t hash) { return hash % 16193llu; } + static size_t mod20399(size_t hash) { return hash % 20399llu; } + static size_t mod25717(size_t hash) { return hash % 25717llu; } + static size_t mod32401(size_t hash) { return hash % 32401llu; } + static size_t mod40823(size_t hash) { return hash % 40823llu; } + static size_t mod51437(size_t hash) { return hash % 51437llu; } + static size_t mod64811(size_t hash) { return hash % 64811llu; } + static size_t mod81649(size_t hash) { return hash % 81649llu; } + static size_t mod102877(size_t hash) { return hash % 102877llu; } + static size_t mod129607(size_t hash) { return hash % 129607llu; } + static size_t mod163307(size_t hash) { return hash % 163307llu; } + static size_t mod205759(size_t hash) { return hash % 205759llu; } + static size_t mod259229(size_t hash) { return hash % 259229llu; } + static size_t mod326617(size_t hash) { return hash % 326617llu; } + static size_t mod411527(size_t hash) { return hash % 411527llu; } + static size_t mod518509(size_t hash) { return hash % 518509llu; } + static size_t mod653267(size_t hash) { return hash % 653267llu; } + static size_t mod823117(size_t hash) { return hash % 823117llu; } + static size_t mod1037059(size_t hash) { return hash % 1037059llu; } + static size_t mod1306601(size_t hash) { return hash % 1306601llu; } + static size_t mod1646237(size_t hash) { return hash % 1646237llu; } + static size_t mod2074129(size_t hash) { return hash % 2074129llu; } + static size_t mod2613229(size_t hash) { return hash % 2613229llu; } + static size_t mod3292489(size_t hash) { return hash % 3292489llu; } + static size_t mod4148279(size_t hash) { return hash % 4148279llu; } + static size_t mod5226491(size_t hash) { return hash % 5226491llu; } + static size_t mod6584983(size_t hash) { return hash % 6584983llu; } + static size_t mod8296553(size_t hash) { return hash % 8296553llu; } + static size_t mod10453007(size_t hash) { return hash % 10453007llu; } + static size_t mod13169977(size_t hash) { return hash % 13169977llu; } + static size_t mod16593127(size_t hash) { return hash % 16593127llu; } + static size_t mod20906033(size_t hash) { return hash % 20906033llu; } + static size_t mod26339969(size_t hash) { return hash % 26339969llu; } + static size_t mod33186281(size_t hash) { return hash % 33186281llu; } + static size_t mod41812097(size_t hash) { return hash % 41812097llu; } + static size_t mod52679969(size_t hash) { return hash % 52679969llu; } + static size_t mod66372617(size_t hash) { return hash % 66372617llu; } + static size_t mod83624237(size_t hash) { return hash % 83624237llu; } + static size_t mod105359939(size_t hash) { return hash % 105359939llu; } + static size_t mod132745199(size_t hash) { return hash % 132745199llu; } + static size_t mod167248483(size_t hash) { return hash % 167248483llu; } + static size_t mod210719881(size_t hash) { return hash % 210719881llu; } + static size_t mod265490441(size_t hash) { return hash % 265490441llu; } + static size_t mod334496971(size_t hash) { return hash % 334496971llu; } + static size_t mod421439783(size_t hash) { return hash % 421439783llu; } + static size_t mod530980861(size_t hash) { return hash % 530980861llu; } + static size_t mod668993977(size_t hash) { return hash % 668993977llu; } + static size_t mod842879579(size_t hash) { return hash % 842879579llu; } + static size_t mod1061961721(size_t hash) { return hash % 1061961721llu; } + static size_t mod1337987929(size_t hash) { return hash % 1337987929llu; } + static size_t mod1685759167(size_t hash) { return hash % 1685759167llu; } + static size_t mod2123923447(size_t hash) { return hash % 2123923447llu; } + static size_t mod2675975881(size_t hash) { return hash % 2675975881llu; } + static size_t mod3371518343(size_t hash) { return hash % 3371518343llu; } + static size_t mod4247846927(size_t hash) { return hash % 4247846927llu; } + static size_t mod5351951779(size_t hash) { return hash % 5351951779llu; } + static size_t mod6743036717(size_t hash) { return hash % 6743036717llu; } + static size_t mod8495693897(size_t hash) { return hash % 8495693897llu; } + static size_t mod10703903591(size_t hash) { return hash % 10703903591llu; } + static size_t mod13486073473(size_t hash) { return hash % 13486073473llu; } + static size_t mod16991387857(size_t hash) { return hash % 16991387857llu; } + static size_t mod21407807219(size_t hash) { return hash % 21407807219llu; } + static size_t mod26972146961(size_t hash) { return hash % 26972146961llu; } + static size_t mod33982775741(size_t hash) { return hash % 33982775741llu; } + static size_t mod42815614441(size_t hash) { return hash % 42815614441llu; } + static size_t mod53944293929(size_t hash) { return hash % 53944293929llu; } + static size_t mod67965551447(size_t hash) { return hash % 67965551447llu; } + static size_t mod85631228929(size_t hash) { return hash % 85631228929llu; } + static size_t mod107888587883(size_t hash) { return hash % 107888587883llu; } + static size_t mod135931102921(size_t hash) { return hash % 135931102921llu; } + static size_t mod171262457903(size_t hash) { return hash % 171262457903llu; } + static size_t mod215777175787(size_t hash) { return hash % 215777175787llu; } + static size_t mod271862205833(size_t hash) { return hash % 271862205833llu; } + static size_t mod342524915839(size_t hash) { return hash % 342524915839llu; } + static size_t mod431554351609(size_t hash) { return hash % 431554351609llu; } + static size_t mod543724411781(size_t hash) { return hash % 543724411781llu; } + static size_t mod685049831731(size_t hash) { return hash % 685049831731llu; } + static size_t mod863108703229(size_t hash) { return hash % 863108703229llu; } + static size_t mod1087448823553(size_t hash) { return hash % 1087448823553llu; } + static size_t mod1370099663459(size_t hash) { return hash % 1370099663459llu; } + static size_t mod1726217406467(size_t hash) { return hash % 1726217406467llu; } + static size_t mod2174897647073(size_t hash) { return hash % 2174897647073llu; } + static size_t mod2740199326961(size_t hash) { return hash % 2740199326961llu; } + static size_t mod3452434812973(size_t hash) { return hash % 3452434812973llu; } + static size_t mod4349795294267(size_t hash) { return hash % 4349795294267llu; } + static size_t mod5480398654009(size_t hash) { return hash % 5480398654009llu; } + static size_t mod6904869625999(size_t hash) { return hash % 6904869625999llu; } + static size_t mod8699590588571(size_t hash) { return hash % 8699590588571llu; } + static size_t mod10960797308051(size_t hash) { return hash % 10960797308051llu; } + static size_t mod13809739252051(size_t hash) { return hash % 13809739252051llu; } + static size_t mod17399181177241(size_t hash) { return hash % 17399181177241llu; } + static size_t mod21921594616111(size_t hash) { return hash % 21921594616111llu; } + static size_t mod27619478504183(size_t hash) { return hash % 27619478504183llu; } + static size_t mod34798362354533(size_t hash) { return hash % 34798362354533llu; } + static size_t mod43843189232363(size_t hash) { return hash % 43843189232363llu; } + static size_t mod55238957008387(size_t hash) { return hash % 55238957008387llu; } + static size_t mod69596724709081(size_t hash) { return hash % 69596724709081llu; } + static size_t mod87686378464759(size_t hash) { return hash % 87686378464759llu; } + static size_t mod110477914016779(size_t hash) { return hash % 110477914016779llu; } + static size_t mod139193449418173(size_t hash) { return hash % 139193449418173llu; } + static size_t mod175372756929481(size_t hash) { return hash % 175372756929481llu; } + static size_t mod220955828033581(size_t hash) { return hash % 220955828033581llu; } + static size_t mod278386898836457(size_t hash) { return hash % 278386898836457llu; } + static size_t mod350745513859007(size_t hash) { return hash % 350745513859007llu; } + static size_t mod441911656067171(size_t hash) { return hash % 441911656067171llu; } + static size_t mod556773797672909(size_t hash) { return hash % 556773797672909llu; } + static size_t mod701491027718027(size_t hash) { return hash % 701491027718027llu; } + static size_t mod883823312134381(size_t hash) { return hash % 883823312134381llu; } + static size_t mod1113547595345903(size_t hash) { return hash % 1113547595345903llu; } + static size_t mod1402982055436147(size_t hash) { return hash % 1402982055436147llu; } + static size_t mod1767646624268779(size_t hash) { return hash % 1767646624268779llu; } + static size_t mod2227095190691797(size_t hash) { return hash % 2227095190691797llu; } + static size_t mod2805964110872297(size_t hash) { return hash % 2805964110872297llu; } + static size_t mod3535293248537579(size_t hash) { return hash % 3535293248537579llu; } + static size_t mod4454190381383713(size_t hash) { return hash % 4454190381383713llu; } + static size_t mod5611928221744609(size_t hash) { return hash % 5611928221744609llu; } + static size_t mod7070586497075177(size_t hash) { return hash % 7070586497075177llu; } + static size_t mod8908380762767489(size_t hash) { return hash % 8908380762767489llu; } + static size_t mod11223856443489329(size_t hash) { return hash % 11223856443489329llu; } + static size_t mod14141172994150357(size_t hash) { return hash % 14141172994150357llu; } + static size_t mod17816761525534927(size_t hash) { return hash % 17816761525534927llu; } + static size_t mod22447712886978529(size_t hash) { return hash % 22447712886978529llu; } + static size_t mod28282345988300791(size_t hash) { return hash % 28282345988300791llu; } + static size_t mod35633523051069991(size_t hash) { return hash % 35633523051069991llu; } + static size_t mod44895425773957261(size_t hash) { return hash % 44895425773957261llu; } + static size_t mod56564691976601587(size_t hash) { return hash % 56564691976601587llu; } + static size_t mod71267046102139967(size_t hash) { return hash % 71267046102139967llu; } + static size_t mod89790851547914507(size_t hash) { return hash % 89790851547914507llu; } + static size_t mod113129383953203213(size_t hash) { return hash % 113129383953203213llu; } + static size_t mod142534092204280003(size_t hash) { return hash % 142534092204280003llu; } + static size_t mod179581703095829107(size_t hash) { return hash % 179581703095829107llu; } + static size_t mod226258767906406483(size_t hash) { return hash % 226258767906406483llu; } + static size_t mod285068184408560057(size_t hash) { return hash % 285068184408560057llu; } + static size_t mod359163406191658253(size_t hash) { return hash % 359163406191658253llu; } + static size_t mod452517535812813007(size_t hash) { return hash % 452517535812813007llu; } + static size_t mod570136368817120201(size_t hash) { return hash % 570136368817120201llu; } + static size_t mod718326812383316683(size_t hash) { return hash % 718326812383316683llu; } + static size_t mod905035071625626043(size_t hash) { return hash % 905035071625626043llu; } + static size_t mod1140272737634240411(size_t hash) { return hash % 1140272737634240411llu; } + static size_t mod1436653624766633509(size_t hash) { return hash % 1436653624766633509llu; } + static size_t mod1810070143251252131(size_t hash) { return hash % 1810070143251252131llu; } + static size_t mod2280545475268481167(size_t hash) { return hash % 2280545475268481167llu; } + static size_t mod2873307249533267101(size_t hash) { return hash % 2873307249533267101llu; } + static size_t mod3620140286502504283(size_t hash) { return hash % 3620140286502504283llu; } + static size_t mod4561090950536962147(size_t hash) { return hash % 4561090950536962147llu; } + static size_t mod5746614499066534157(size_t hash) { return hash % 5746614499066534157llu; } + static size_t mod7240280573005008577(size_t hash) { return hash % 7240280573005008577llu; } + static size_t mod9122181901073924329(size_t hash) { return hash % 9122181901073924329llu; } + static size_t mod11493228998133068689(size_t hash) { return hash % 11493228998133068689llu; } + static size_t mod14480561146010017169(size_t hash) { return hash % 14480561146010017169llu; } + static size_t mod18446744073709551557(size_t hash) { return hash % 18446744073709551557llu; } + + using mod_function = size_t (*)(size_t); + + mod_function next_size_over(size_t & size) const + { + // prime numbers generated by the following method: + // 1. start with a prime p = 2 + // 2. go to wolfram alpha and get p = NextPrime(2 * p) + // 3. repeat 2. until you overflow 64 bits + // you now have large gaps which you would hit if somebody called reserve() with an unlucky number. + // 4. to fill the gaps for every prime p go to wolfram alpha and get ClosestPrime(p * 2^(1/3)) and ClosestPrime(p * 2^(2/3)) and put those in the gaps + // 5. get PrevPrime(2^64) and put it at the end + static constexpr const size_t prime_list[] = + { + 2llu, 3llu, 5llu, 7llu, 11llu, 13llu, 17llu, 23llu, 29llu, 37llu, 47llu, + 59llu, 73llu, 97llu, 127llu, 151llu, 197llu, 251llu, 313llu, 397llu, + 499llu, 631llu, 797llu, 1009llu, 1259llu, 1597llu, 2011llu, 2539llu, + 3203llu, 4027llu, 5087llu, 6421llu, 8089llu, 10193llu, 12853llu, 16193llu, + 20399llu, 25717llu, 32401llu, 40823llu, 51437llu, 64811llu, 81649llu, + 102877llu, 129607llu, 163307llu, 205759llu, 259229llu, 326617llu, + 411527llu, 518509llu, 653267llu, 823117llu, 1037059llu, 1306601llu, + 1646237llu, 2074129llu, 2613229llu, 3292489llu, 4148279llu, 5226491llu, + 6584983llu, 8296553llu, 10453007llu, 13169977llu, 16593127llu, 20906033llu, + 26339969llu, 33186281llu, 41812097llu, 52679969llu, 66372617llu, + 83624237llu, 105359939llu, 132745199llu, 167248483llu, 210719881llu, + 265490441llu, 334496971llu, 421439783llu, 530980861llu, 668993977llu, + 842879579llu, 1061961721llu, 1337987929llu, 1685759167llu, 2123923447llu, + 2675975881llu, 3371518343llu, 4247846927llu, 5351951779llu, 6743036717llu, + 8495693897llu, 10703903591llu, 13486073473llu, 16991387857llu, + 21407807219llu, 26972146961llu, 33982775741llu, 42815614441llu, + 53944293929llu, 67965551447llu, 85631228929llu, 107888587883llu, + 135931102921llu, 171262457903llu, 215777175787llu, 271862205833llu, + 342524915839llu, 431554351609llu, 543724411781llu, 685049831731llu, + 863108703229llu, 1087448823553llu, 1370099663459llu, 1726217406467llu, + 2174897647073llu, 2740199326961llu, 3452434812973llu, 4349795294267llu, + 5480398654009llu, 6904869625999llu, 8699590588571llu, 10960797308051llu, + 13809739252051llu, 17399181177241llu, 21921594616111llu, 27619478504183llu, + 34798362354533llu, 43843189232363llu, 55238957008387llu, 69596724709081llu, + 87686378464759llu, 110477914016779llu, 139193449418173llu, + 175372756929481llu, 220955828033581llu, 278386898836457llu, + 350745513859007llu, 441911656067171llu, 556773797672909llu, + 701491027718027llu, 883823312134381llu, 1113547595345903llu, + 1402982055436147llu, 1767646624268779llu, 2227095190691797llu, + 2805964110872297llu, 3535293248537579llu, 4454190381383713llu, + 5611928221744609llu, 7070586497075177llu, 8908380762767489llu, + 11223856443489329llu, 14141172994150357llu, 17816761525534927llu, + 22447712886978529llu, 28282345988300791llu, 35633523051069991llu, + 44895425773957261llu, 56564691976601587llu, 71267046102139967llu, + 89790851547914507llu, 113129383953203213llu, 142534092204280003llu, + 179581703095829107llu, 226258767906406483llu, 285068184408560057llu, + 359163406191658253llu, 452517535812813007llu, 570136368817120201llu, + 718326812383316683llu, 905035071625626043llu, 1140272737634240411llu, + 1436653624766633509llu, 1810070143251252131llu, 2280545475268481167llu, + 2873307249533267101llu, 3620140286502504283llu, 4561090950536962147llu, + 5746614499066534157llu, 7240280573005008577llu, 9122181901073924329llu, + 11493228998133068689llu, 14480561146010017169llu, 18446744073709551557llu + }; + static constexpr size_t (* const mod_functions[])(size_t) = + { + &mod0, &mod2, &mod3, &mod5, &mod7, &mod11, &mod13, &mod17, &mod23, &mod29, &mod37, + &mod47, &mod59, &mod73, &mod97, &mod127, &mod151, &mod197, &mod251, &mod313, &mod397, + &mod499, &mod631, &mod797, &mod1009, &mod1259, &mod1597, &mod2011, &mod2539, &mod3203, + &mod4027, &mod5087, &mod6421, &mod8089, &mod10193, &mod12853, &mod16193, &mod20399, + &mod25717, &mod32401, &mod40823, &mod51437, &mod64811, &mod81649, &mod102877, + &mod129607, &mod163307, &mod205759, &mod259229, &mod326617, &mod411527, &mod518509, + &mod653267, &mod823117, &mod1037059, &mod1306601, &mod1646237, &mod2074129, + &mod2613229, &mod3292489, &mod4148279, &mod5226491, &mod6584983, &mod8296553, + &mod10453007, &mod13169977, &mod16593127, &mod20906033, &mod26339969, &mod33186281, + &mod41812097, &mod52679969, &mod66372617, &mod83624237, &mod105359939, &mod132745199, + &mod167248483, &mod210719881, &mod265490441, &mod334496971, &mod421439783, + &mod530980861, &mod668993977, &mod842879579, &mod1061961721, &mod1337987929, + &mod1685759167, &mod2123923447, &mod2675975881, &mod3371518343, &mod4247846927, + &mod5351951779, &mod6743036717, &mod8495693897, &mod10703903591, &mod13486073473, + &mod16991387857, &mod21407807219, &mod26972146961, &mod33982775741, &mod42815614441, + &mod53944293929, &mod67965551447, &mod85631228929, &mod107888587883, &mod135931102921, + &mod171262457903, &mod215777175787, &mod271862205833, &mod342524915839, + &mod431554351609, &mod543724411781, &mod685049831731, &mod863108703229, + &mod1087448823553, &mod1370099663459, &mod1726217406467, &mod2174897647073, + &mod2740199326961, &mod3452434812973, &mod4349795294267, &mod5480398654009, + &mod6904869625999, &mod8699590588571, &mod10960797308051, &mod13809739252051, + &mod17399181177241, &mod21921594616111, &mod27619478504183, &mod34798362354533, + &mod43843189232363, &mod55238957008387, &mod69596724709081, &mod87686378464759, + &mod110477914016779, &mod139193449418173, &mod175372756929481, &mod220955828033581, + &mod278386898836457, &mod350745513859007, &mod441911656067171, &mod556773797672909, + &mod701491027718027, &mod883823312134381, &mod1113547595345903, &mod1402982055436147, + &mod1767646624268779, &mod2227095190691797, &mod2805964110872297, &mod3535293248537579, + &mod4454190381383713, &mod5611928221744609, &mod7070586497075177, &mod8908380762767489, + &mod11223856443489329, &mod14141172994150357, &mod17816761525534927, + &mod22447712886978529, &mod28282345988300791, &mod35633523051069991, + &mod44895425773957261, &mod56564691976601587, &mod71267046102139967, + &mod89790851547914507, &mod113129383953203213, &mod142534092204280003, + &mod179581703095829107, &mod226258767906406483, &mod285068184408560057, + &mod359163406191658253, &mod452517535812813007, &mod570136368817120201, + &mod718326812383316683, &mod905035071625626043, &mod1140272737634240411, + &mod1436653624766633509, &mod1810070143251252131, &mod2280545475268481167, + &mod2873307249533267101, &mod3620140286502504283, &mod4561090950536962147, + &mod5746614499066534157, &mod7240280573005008577, &mod9122181901073924329, + &mod11493228998133068689, &mod14480561146010017169, &mod18446744073709551557 + }; + const size_t * found = std::lower_bound(std::begin(prime_list), std::end(prime_list) - 1, size); + size = *found; + return mod_functions[1 + found - prime_list]; + } + void commit(mod_function new_mod_function) + { + current_mod_function = new_mod_function; + } + void reset() + { + current_mod_function = &mod0; + } + + size_t index_for_hash(size_t hash, size_t /*num_slots_minus_one*/) const + { + return current_mod_function(hash); + } + size_t keep_in_range(size_t index, size_t num_slots_minus_one) const + { + return index > num_slots_minus_one ? current_mod_function(index) : index; + } + +private: + mod_function current_mod_function = &mod0; +}; + +struct power_of_two_hash_policy +{ + size_t index_for_hash(size_t hash, size_t num_slots_minus_one) const + { + return hash & num_slots_minus_one; + } + size_t keep_in_range(size_t index, size_t num_slots_minus_one) const + { + return index_for_hash(index, num_slots_minus_one); + } + int8_t next_size_over(size_t & size) const + { + size = detailv3::next_power_of_two(size); + return 0; + } + void commit(int8_t) + { + } + void reset() + { + } + +}; + +struct fibonacci_hash_policy +{ + size_t index_for_hash(size_t hash, size_t /*num_slots_minus_one*/) const + { + return (11400714819323198485ull * hash) >> shift; + } + size_t keep_in_range(size_t index, size_t num_slots_minus_one) const + { + return index & num_slots_minus_one; + } + + int8_t next_size_over(size_t & size) const + { + size = std::max(size_t(2), detailv3::next_power_of_two(size)); + return 64 - detailv3::log2(size); + } + void commit(int8_t shift) + { + this->shift = shift; + } + void reset() + { + shift = 63; + } + +private: + int8_t shift = 63; +}; + +template, typename E = std::equal_to, typename A = std::allocator > > +class flat_hash_map + : public detailv3::sherwood_v3_table + < + std::pair, + K, + H, + detailv3::KeyOrValueHasher, H>, + E, + detailv3::KeyOrValueEquality, E>, + A, + typename std::allocator_traits::template rebind_alloc>> + > +{ + using Table = detailv3::sherwood_v3_table + < + std::pair, + K, + H, + detailv3::KeyOrValueHasher, H>, + E, + detailv3::KeyOrValueEquality, E>, + A, + typename std::allocator_traits::template rebind_alloc>> + >; +public: + + using key_type = K; + using mapped_type = V; + + using Table::Table; + flat_hash_map() + { + } + + inline V & operator[](const K & key) + { + return emplace(key, convertible_to_value()).first->second; + } + inline V & operator[](K && key) + { + return emplace(std::move(key), convertible_to_value()).first->second; + } + V & at(const K & key) + { + auto found = this->find(key); + if (found == this->end()) + throw std::out_of_range("Argument passed to at() was not in the map."); + return found->second; + } + const V & at(const K & key) const + { + auto found = this->find(key); + if (found == this->end()) + throw std::out_of_range("Argument passed to at() was not in the map."); + return found->second; + } + + using Table::emplace; + std::pair emplace() + { + return emplace(key_type(), convertible_to_value()); + } + template + std::pair insert_or_assign(const key_type & key, M && m) + { + auto emplace_result = emplace(key, std::forward(m)); + if (!emplace_result.second) + emplace_result.first->second = std::forward(m); + return emplace_result; + } + template + std::pair insert_or_assign(key_type && key, M && m) + { + auto emplace_result = emplace(std::move(key), std::forward(m)); + if (!emplace_result.second) + emplace_result.first->second = std::forward(m); + return emplace_result; + } + template + typename Table::iterator insert_or_assign(typename Table::const_iterator, const key_type & key, M && m) + { + return insert_or_assign(key, std::forward(m)).first; + } + template + typename Table::iterator insert_or_assign(typename Table::const_iterator, key_type && key, M && m) + { + return insert_or_assign(std::move(key), std::forward(m)).first; + } + + friend bool operator==(const flat_hash_map & lhs, const flat_hash_map & rhs) + { + if (lhs.size() != rhs.size()) + return false; + for (const typename Table::value_type & value : lhs) + { + auto found = rhs.find(value.first); + if (found == rhs.end()) + return false; + else if (value.second != found->second) + return false; + } + return true; + } + friend bool operator!=(const flat_hash_map & lhs, const flat_hash_map & rhs) + { + return !(lhs == rhs); + } + +private: + struct convertible_to_value + { + operator V() const + { + return V(); + } + }; +}; + +template, typename E = std::equal_to, typename A = std::allocator > +class flat_hash_set + : public detailv3::sherwood_v3_table + < + T, + T, + H, + detailv3::functor_storage, + E, + detailv3::functor_storage, + A, + typename std::allocator_traits::template rebind_alloc> + > +{ + using Table = detailv3::sherwood_v3_table + < + T, + T, + H, + detailv3::functor_storage, + E, + detailv3::functor_storage, + A, + typename std::allocator_traits::template rebind_alloc> + >; +public: + + using key_type = T; + + using Table::Table; + flat_hash_set() + { + } + + template + std::pair emplace(Args &&... args) + { + return Table::emplace(T(std::forward(args)...)); + } + std::pair emplace(const key_type & arg) + { + return Table::emplace(arg); + } + std::pair emplace(key_type & arg) + { + return Table::emplace(arg); + } + std::pair emplace(const key_type && arg) + { + return Table::emplace(std::move(arg)); + } + std::pair emplace(key_type && arg) + { + return Table::emplace(std::move(arg)); + } + + friend bool operator==(const flat_hash_set & lhs, const flat_hash_set & rhs) + { + if (lhs.size() != rhs.size()) + return false; + for (const T & value : lhs) + { + if (rhs.find(value) == rhs.end()) + return false; + } + return true; + } + friend bool operator!=(const flat_hash_set & lhs, const flat_hash_set & rhs) + { + return !(lhs == rhs); + } +}; + + +template +struct power_of_two_std_hash : std::hash +{ + typedef ska::power_of_two_hash_policy hash_policy; +}; + +} // end namespace ska diff --git a/WickedEngine/WickedEngine.h b/WickedEngine/WickedEngine.h index 376928a71..d807ce361 100644 --- a/WickedEngine/WickedEngine.h +++ b/WickedEngine/WickedEngine.h @@ -61,6 +61,10 @@ #include "wiEvent.h" #include "wiShaderCompiler.h" #include "wiCanvas.h" +#include "wiAllocator.h" +#include "wiUnorderedMap.h" +#include "wiUnorderedSet.h" +#include "wiVector.h" #ifdef _WIN32 #ifdef PLATFORM_UWP diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems b/WickedEngine/WickedEngine_SOURCE.vcxitems index 20175956c..e85487550 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems @@ -239,6 +239,7 @@ + @@ -261,6 +262,7 @@ + @@ -351,6 +353,8 @@ + + diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters index 1451c38ce..447e2a4cf 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters @@ -1074,6 +1074,18 @@ ENGINE\High level interface + + UTILITY + + + ENGINE\Helpers + + + ENGINE\Helpers + + + ENGINE\Helpers + diff --git a/WickedEngine/offlineshadercompiler.cpp b/WickedEngine/offlineshadercompiler.cpp index c9b796d5d..0a6cf61b8 100644 --- a/WickedEngine/offlineshadercompiler.cpp +++ b/WickedEngine/offlineshadercompiler.cpp @@ -1,22 +1,20 @@ #include "WickedEngine.h" #include -#include #include #include -#include -#include +#include std::mutex locker; -std::vector shaders[static_cast(wiGraphics::ShaderStage::Count)]; -std::unordered_map minshadermodels; +wi::vector shaders[static_cast(wiGraphics::ShaderStage::Count)]; +wi::unordered_map minshadermodels; struct Target { wiGraphics::ShaderFormat format; std::string dir; }; -std::vector targets; -std::unordered_map results; +wi::vector targets; +wi::unordered_map results; bool rebuild = false; bool shaderdump_enabled = false; @@ -497,8 +495,8 @@ int main(int argc, char* argv[]) { std::cout << "[Wicked Engine Offline Shader Compiler] Creating ShaderDump..." << std::endl; timer.record(); - std::stringstream ss; - ss << "namespace wiShaderDump {" << std::endl; + std::string ss; + ss += "namespace wiShaderDump {\n"; for (auto& x : results) { auto& name = x.first; @@ -507,15 +505,15 @@ int main(int argc, char* argv[]) std::string name_repl = name; std::replace(name_repl.begin(), name_repl.end(), '/', '_'); std::replace(name_repl.begin(), name_repl.end(), '.', '_'); - ss << "const uint8_t " << name_repl << "[] = {"; + ss += "const uint8_t " + name_repl + "[] = {"; for (size_t i = 0; i < output.shadersize; ++i) { - ss << (uint32_t)output.shaderdata[i] << ","; + ss += std::to_string((uint32_t)output.shaderdata[i]) + ","; } - ss << "};" << std::endl; + ss += "};\n"; } - ss << "struct ShaderDumpEntry{const uint8_t* data; size_t size;};" << std::endl; - ss << "const std::unordered_map shaderdump = {" << std::endl; + ss += "struct ShaderDumpEntry{const uint8_t* data; size_t size;};\n"; + ss += "const wi::unordered_map shaderdump = {\n"; for (auto& x : results) { auto& name = x.first; @@ -524,11 +522,11 @@ int main(int argc, char* argv[]) std::string name_repl = name; std::replace(name_repl.begin(), name_repl.end(), '/', '_'); std::replace(name_repl.begin(), name_repl.end(), '.', '_'); - ss << "std::pair(\"" << name << "\", {" << name_repl << ",sizeof(" << name_repl << ")})," << std::endl; + ss += "std::pair(\"" + name + "\", {" + name_repl + ",sizeof(" + name_repl + ")}),\n"; } - ss << "};" << std::endl; // map end - ss << "}" << std::endl; // namespace end - wiHelper::FileWrite("wiShaderDump.h", (uint8_t*)ss.str().c_str(), ss.str().length()); + ss += "};\n"; // map end + ss += "}\n"; // namespace end + wiHelper::FileWrite("wiShaderDump.h", (uint8_t*)ss.c_str(), ss.length()); std::cout << "[Wicked Engine Offline Shader Compiler] ShaderDump written to wiShaderDump.h in " << std::setprecision(4) << timer.elapsed_seconds() << " seconds" << std::endl; } diff --git a/WickedEngine/wiAllocator.h b/WickedEngine/wiAllocator.h index 2a6b868ab..751630689 100644 --- a/WickedEngine/wiAllocator.h +++ b/WickedEngine/wiAllocator.h @@ -1,10 +1,8 @@ #pragma once #include "wiSpinLock.h" -#include #include #include -#include namespace wiAllocator { diff --git a/WickedEngine/wiArchive.cpp b/WickedEngine/wiArchive.cpp index 6cfe3f634..eaab9bfc9 100644 --- a/WickedEngine/wiArchive.cpp +++ b/WickedEngine/wiArchive.cpp @@ -27,14 +27,12 @@ wiArchive::wiArchive(const std::string& fileName, bool readMode) : fileName(file (*this) >> version; if (version < __archiveVersionBarrier) { - std::string ss = "The archive version (" + std::to_string(version) + ") is no longer supported!"; - wiHelper::messageBox(ss, "Error!"); + wiHelper::messageBox("The archive version (" + std::to_string(version) + ") is no longer supported!", "Error!"); Close(); } if (version > __archiveVersion) { - std::string ss = "The archive version (" + std::to_string(version) + ") is higher than the program's (" + std::to_string(__archiveVersion) + ")!"; - wiHelper::messageBox(ss, "Error!"); + wiHelper::messageBox("The archive version (" + std::to_string(version) + ") is higher than the program's (" + std::to_string(__archiveVersion) + ")!", "Error!"); Close(); } } diff --git a/WickedEngine/wiArchive.h b/WickedEngine/wiArchive.h index baa34cb4f..7b19a88dc 100644 --- a/WickedEngine/wiArchive.h +++ b/WickedEngine/wiArchive.h @@ -1,17 +1,21 @@ #pragma once #include "CommonInclude.h" #include "wiMath.h" +#include "wiVector.h" #include -#include +// This is a data container used for serialization purposes. +// It can be used to READ or WRITE data, but not both at the same time. +// An archive that was created in WRITE mode can be changed to read mode and vica-versa +// The data flow is always FIFO (first in, first out) class wiArchive { private: uint64_t version = 0; // the version number is used for maintaining backwards compatibility with earlier archive versions bool readMode = false; // archive can be either read or write mode, but not both size_t pos = 0; // position of the next memory operation, relative to the data's beginning - std::vector DATA; // data suitable for read/write operations + wi::vector DATA; // data suitable for read/write operations const uint8_t* data_ptr = nullptr; // this can either be a memory mapped pointer (read only), or the DATA's pointer std::string fileName; // save to this file on closing if not empty @@ -165,13 +169,15 @@ public: } inline wiArchive& operator<<(const std::string& data) { - uint64_t len = (uint64_t)data.length(); - _write(len); - _write(*data.data(), len); + (*this) << data.length(); + for (const auto& x : data) + { + (*this) << x; + } return *this; } template - inline wiArchive& operator<<(const std::vector& data) + inline wiArchive& operator<<(const wi::vector& data) { // Here we will use the << operator so that non-specified types will have compile error! (*this) << data.size(); @@ -304,9 +310,12 @@ public: inline wiArchive& operator>>(std::string& data) { uint64_t len; - _read(len); + (*this) >> len; data.resize(len); - _read(*data.data(), len); + for (size_t i = 0; i < len; ++i) + { + (*this) >> data[i]; + } if (!data.empty() && GetVersion() < 73) { // earlier versions of archive saved the strings with 0 terminator @@ -315,7 +324,7 @@ public: return *this; } template - inline wiArchive& operator>>(std::vector& data) + inline wiArchive& operator>>(wi::vector& data) { // Here we will use the >> operator so that non-specified types will have compile error! size_t count; @@ -338,33 +347,28 @@ private: // Write data using memory operations template - inline void _write(const T& data, uint64_t count = 1) + inline void _write(const T& data) { assert(!readMode); assert(!DATA.empty()); - if (count == 0) - return; - size_t _size = (size_t)(sizeof(data)*count); - size_t _right = pos + _size; + const size_t _right = pos + sizeof(data); if (_right > DATA.size()) { DATA.resize(_right * 2); data_ptr = DATA.data(); } - std::memcpy(DATA.data() + pos, &data, _size); + *(T*)(DATA.data() + pos) = data; pos = _right; } // Read data using memory operations template - inline void _read(T& data, uint64_t count = 1) + inline void _read(T& data) { assert(readMode); assert(data_ptr != nullptr); - if (count == 0) - return; - std::memcpy(&data, data_ptr + pos, (size_t)(sizeof(data)*count)); - pos += (size_t)(sizeof(data)*count); + data = *(const T*)(data_ptr + pos); + pos += (size_t)(sizeof(data)); } }; diff --git a/WickedEngine/wiAudio.cpp b/WickedEngine/wiAudio.cpp index 4387d284a..73c27a379 100644 --- a/WickedEngine/wiAudio.cpp +++ b/WickedEngine/wiAudio.cpp @@ -2,8 +2,7 @@ #include "wiBackLog.h" #include "wiHelper.h" #include "wiTimer.h" - -#include +#include "wiVector.h" #define STB_VORBIS_HEADER_ONLY #include "Utility/stb_vorbis.c" @@ -165,7 +164,7 @@ namespace wiAudio { std::shared_ptr audio; WAVEFORMATEX wfx = {}; - std::vector audioData; + wi::vector audioData; }; struct SoundInstanceInternal { @@ -173,8 +172,8 @@ namespace wiAudio std::shared_ptr soundinternal; IXAudio2SourceVoice* sourceVoice = nullptr; XAUDIO2_VOICE_DETAILS voiceDetails = {}; - std::vector outputMatrix; - std::vector channelAzimuths; + wi::vector outputMatrix; + wi::vector channelAzimuths; XAUDIO2_BUFFER buffer = {}; ~SoundInstanceInternal() @@ -256,17 +255,13 @@ namespace wiAudio bool CreateSound(const std::string& filename, Sound* sound) { - std::vector filedata; + wi::vector filedata; bool success = wiHelper::FileRead(filename, filedata); if (!success) { return false; } - return CreateSound(filedata, sound); - } - bool CreateSound(const std::vector& data, Sound* sound) - { - return CreateSound(data.data(), data.size(), sound); + return CreateSound(filedata.data(), filedata.size(), sound); } bool CreateSound(const uint8_t* data, size_t size, Sound* sound) { @@ -682,15 +677,15 @@ namespace wiAudio struct SoundInternal{ std::shared_ptr audio; FAudioWaveFormatEx wfx = {}; - std::vector audioData; + wi::vector audioData; }; struct SoundInstanceInternal{ std::shared_ptr audio; std::shared_ptr soundinternal; FAudioSourceVoice* sourceVoice = nullptr; FAudioVoiceDetails voiceDetails = {}; - std::vector outputMatrix; - std::vector channelAzimuths; + wi::vector outputMatrix; + wi::vector channelAzimuths; FAudioBuffer buffer = {}; ~SoundInstanceInternal(){ @@ -769,16 +764,13 @@ namespace wiAudio } bool CreateSound(const std::string& filename, Sound* sound) { - std::vector filedata; + wi::vector filedata; bool success = wiHelper::FileRead(filename, filedata); if (!success) { return false; } - return CreateSound(filedata, sound); - } - bool CreateSound(const std::vector& data, Sound* sound) { - return CreateSound(data.data(), data.size(), sound); + return CreateSound(filedata.data(), filedata.size(), sound); } bool CreateSound(const uint8_t* data, size_t size, Sound* sound) { std::shared_ptr soundinternal = std::make_shared(); @@ -1049,7 +1041,6 @@ namespace wiAudio void Initialize() {} bool CreateSound(const std::string& filename, Sound* sound) { return false; } - bool CreateSound(const std::vector& data, Sound* sound) { return false; } bool CreateSound(const uint8_t* data, size_t size, Sound* sound) { return false; } bool CreateSoundInstance(const Sound* sound, SoundInstance* instance) { return false; } diff --git a/WickedEngine/wiAudio.h b/WickedEngine/wiAudio.h index 7cff005df..6c4f674bf 100644 --- a/WickedEngine/wiAudio.h +++ b/WickedEngine/wiAudio.h @@ -4,7 +4,7 @@ #include #include -#include + #ifdef SDL2 #include #endif @@ -50,7 +50,6 @@ namespace wiAudio }; bool CreateSound(const std::string& filename, Sound* sound); - bool CreateSound(const std::vector& data, Sound* sound); bool CreateSound(const uint8_t* data, size_t size, Sound* sound); #ifdef SDL2 bool CreateSound(SDL_RWops* data, Sound* sound); diff --git a/WickedEngine/wiBackLog.cpp b/WickedEngine/wiBackLog.cpp index 55497e31e..815141001 100644 --- a/WickedEngine/wiBackLog.cpp +++ b/WickedEngine/wiBackLog.cpp @@ -9,43 +9,62 @@ #include "wiLua.h" #include "wiInput.h" #include "wiPlatform.h" +#include "wiHelper.h" #include #include #include +#include +#include using namespace wiGraphics; - namespace wiBackLog { - bool enabled = false; - std::deque stream; - std::deque history; - const float speed = 50.0f; - unsigned int deletefromline = 500; - float pos = std::numeric_limits::lowest(); - float scroll = 0; - std::string inputArea; - int historyPos = 0; - wiSpriteFont font; - wiSpinLock logLock; - Texture backgroundTex; - bool refitscroll = false; + static bool enabled = false; + static std::deque stream; + static std::deque history; + static const float speed = 4000.0f; + static const size_t deletefromline = 500; + static float pos = std::numeric_limits::lowest(); + static float scroll = 0; + static std::string inputArea; + static int historyPos = 0; + static wiSpriteFont font; + static wiSpinLock logLock; + static Texture backgroundTex; + static bool refitscroll = false; - bool locked = false; - bool blockLuaExec = false; - LogLevel logLevel = LogLevel::Default; + static bool locked = false; + static bool blockLuaExec = false; + static LogLevel logLevel = LogLevel::Default; + + static void write_logfile() + { + std::string filename = wiHelper::GetTempDirectoryPath() + "wiBackLog.txt"; + std::string text = getText(); // will lock mutex + wiHelper::FileWrite(filename, (const uint8_t*)text.c_str(), text.length()); + } + + // The logwriter object will automatically write out the backlog to the temp folder when it's destroyed + // Should happen on application exit + struct LogWriter + { + ~LogWriter() + { + write_logfile(); + } + } static logwriter; void Toggle() { enabled = !enabled; } - void Scroll(int dir) + void Scroll(float dir) { scroll += dir; } - void Update(const wiCanvas& canvas) + void Update(const wiCanvas& canvas, float dt) { if (!locked) { @@ -70,22 +89,22 @@ namespace wiBackLog } if (wiInput::Down(wiInput::KEYBOARD_BUTTON_PAGEUP)) { - Scroll(10); + Scroll(1000.0f * dt); } if (wiInput::Down(wiInput::KEYBOARD_BUTTON_PAGEDOWN)) { - Scroll(-10); + Scroll(-1000.0f * dt); } } } if (enabled) { - pos += speed; + pos += speed * dt; } else { - pos -= speed; + pos -= speed * dt; } pos = wiMath::Clamp(pos, -canvas.GetLogicalHeight(), 0); } @@ -103,8 +122,11 @@ namespace wiBackLog fx.pos = XMFLOAT3(0, pos, 0); fx.opacity = wiMath::Lerp(1, 0, -pos / canvas.GetLogicalHeight()); wiImage::Draw(&backgroundTex, fx, cmd); - wiFont::Draw(inputArea, wiFontParams(10, canvas.GetLogicalHeight() - 10, WIFONTSIZE_DEFAULT, WIFALIGN_LEFT, WIFALIGN_BOTTOM), cmd); + wiFontParams params = wiFontParams(10, canvas.GetLogicalHeight() - 10, WIFONTSIZE_DEFAULT, WIFALIGN_LEFT, WIFALIGN_BOTTOM); + params.h_wrap = canvas.GetLogicalWidth() - params.posX; + params.v_align = WIFALIGN_BOTTOM; + wiFont::Draw(inputArea, params, cmd); font.SetText(getText()); if (refitscroll) @@ -119,6 +141,7 @@ namespace wiBackLog } font.params.posX = 50; font.params.posY = pos + scroll; + font.params.h_wrap = canvas.GetLogicalWidth() - font.params.posX; Rect rect; rect.left = 0; rect.right = (int32_t)canvas.GetPhysicalWidth(); @@ -126,10 +149,10 @@ namespace wiBackLog rect.bottom = int32_t(canvas.GetPhysicalHeight() * 0.9f); wiGraphics::GetDevice()->BindScissorRects(1, &rect, cmd); font.Draw(cmd); - rect.left = -INT_MAX; - rect.right = INT_MAX; - rect.top = -INT_MAX; - rect.bottom = INT_MAX; + rect.left = -std::numeric_limits::max(); + rect.right = std::numeric_limits::max(); + rect.top = -std::numeric_limits::max(); + rect.bottom = std::numeric_limits::max(); wiGraphics::GetDevice()->BindScissorRects(1, &rect, cmd); } } @@ -137,61 +160,83 @@ namespace wiBackLog std::string getText() { - logLock.lock(); + std::scoped_lock lock(logLock); std::string retval; for (auto& x : stream) { retval += x; } - logLock.unlock(); return retval; } void clear() { - logLock.lock(); + std::scoped_lock lock(logLock); stream.clear(); scroll = 0; - logLock.unlock(); } void post(const std::string& input, LogLevel level) { - if (logLevel < level) + if (logLevel > level) { return; } - logLock.lock(); - std::string str; - switch (level) + + // This is explicitly scoped for scoped_lock! { - default: - case LogLevel::Default: - str = ""; - break; - case LogLevel::Warning: - str = "[Warning] "; - break; - case LogLevel::Error: - str = "[Error] "; - break; - } - str += input; - str += '\n'; - stream.push_back(str); - if (stream.size() > deletefromline) - { - stream.pop_front(); - } - refitscroll = true; - logLock.unlock(); + std::scoped_lock lock(logLock); + + std::string str; + switch (level) + { + default: + case LogLevel::Default: + str = ""; + break; + case LogLevel::Warning: + str = "[Warning] "; + break; + case LogLevel::Error: + str = "[Error] "; + break; + } + str += input; + str += '\n'; + stream.push_back(str); + if (stream.size() > deletefromline) + { + stream.pop_front(); + } + refitscroll = true; #ifdef _WIN32 - OutputDebugStringA(str.c_str()); + OutputDebugStringA(str.c_str()); #endif // _WIN32 - std::cout << str; + switch (level) + { + default: + case LogLevel::Default: + std::cout << str; + break; + case LogLevel::Warning: + std::clog << str; + break; + case LogLevel::Error: + std::cerr << str; + break; + } + + // lock released on block end + } + + if (level >= LogLevel::Error) + { + write_logfile(); // will lock mutex + } } void input(const char input) { + std::scoped_lock lock(logLock); inputArea += input; } void acceptInput() @@ -199,7 +244,8 @@ namespace wiBackLog historyPos = 0; post(inputArea.c_str()); history.push_back(inputArea); - if (history.size() > deletefromline) { + if (history.size() > deletefromline) + { history.pop_front(); } if (!blockLuaExec) @@ -214,25 +260,34 @@ namespace wiBackLog } void deletefromInput() { - if(!inputArea.empty()) + std::scoped_lock lock(logLock); + if (!inputArea.empty()) + { inputArea.pop_back(); + } } void historyPrev() { + std::scoped_lock lock(logLock); if (!history.empty()) { inputArea = history[history.size() - 1 - historyPos]; if ((size_t)historyPos < history.size() - 1) + { historyPos++; + } } } void historyNext() { + std::scoped_lock lock(logLock); if (!history.empty()) { if (historyPos > 0) + { historyPos--; + } inputArea = history[history.size() - 1 - historyPos]; } } diff --git a/WickedEngine/wiBackLog.h b/WickedEngine/wiBackLog.h index 11ab971d7..a2c7a7f61 100644 --- a/WickedEngine/wiBackLog.h +++ b/WickedEngine/wiBackLog.h @@ -4,21 +4,21 @@ #include "wiCanvas.h" #include -#include namespace wiBackLog { - enum LogLevel + // Do not modify the order, as this is exposed to LUA scripts as int! + enum class LogLevel { None, Default, Warning, - Error + Error, }; void Toggle(); void Scroll(int direction); - void Update(const wiCanvas& canvas); + void Update(const wiCanvas& canvas, float dt = 1.0f / 60.0f); void Draw(const wiCanvas& canvas, wiGraphics::CommandList cmd); std::string getText(); diff --git a/WickedEngine/wiBackLog_BindLua.cpp b/WickedEngine/wiBackLog_BindLua.cpp index d9169d10b..eb2aead25 100644 --- a/WickedEngine/wiBackLog_BindLua.cpp +++ b/WickedEngine/wiBackLog_BindLua.cpp @@ -2,7 +2,7 @@ #include "wiBackLog.h" #include "wiLua.h" -#include +#include namespace wiBackLog_BindLua { @@ -15,15 +15,17 @@ namespace wiBackLog_BindLua { int argc = wiLua::SGetArgCount(L); - std::stringstream ss(""); + std::string ss; for (int i = 1; i <= argc; i++) { - ss << wiLua::SGetString(L, i); + ss += wiLua::SGetString(L, i); } - if (!ss.str().empty()) - wiBackLog::post(ss.str().c_str()); + if (!ss.empty()) + { + wiBackLog::post(ss); + } return 0; } diff --git a/WickedEngine/wiECS.h b/WickedEngine/wiECS.h index 7528ba326..2ab750cec 100644 --- a/WickedEngine/wiECS.h +++ b/WickedEngine/wiECS.h @@ -3,11 +3,11 @@ #include "wiArchive.h" #include "wiJobSystem.h" +#include "wiUnorderedMap.h" +#include "wiVector.h" #include #include -#include -#include #include namespace wiECS @@ -24,7 +24,7 @@ namespace wiECS struct EntitySerializer { wiJobSystem::context ctx; // allow components to spawn serialization subtasks - std::unordered_map remap; + wi::unordered_map remap; bool allow_remap = true; ~EntitySerializer() @@ -325,11 +325,11 @@ namespace wiECS private: // This is a linear array of alive components - std::vector components; + wi::vector components; // This is a linear array of entities corresponding to each alive component - std::vector entities; + wi::vector entities; // This is a lookup table for entities - std::unordered_map lookup; + wi::unordered_map lookup; // Disallow this to be copied by mistake ComponentManager(const ComponentManager&) = delete; diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index 370c6e4ec..bb90d3d86 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -11,6 +11,7 @@ #include "wiBackLog.h" #include "wiEvent.h" #include "wiTimer.h" +#include "wiVector.h" #include @@ -83,7 +84,7 @@ void wiEmittedParticle::CreateSelfBuffers() device->SetName(&culledIndirectionBuffer2, "culledIndirectionBuffer2"); // Dead index list: - std::vector indices(MAX_PARTICLES); + wi::vector indices(MAX_PARTICLES); for (uint32_t i = 0; i < MAX_PARTICLES; ++i) { indices[i] = i; @@ -99,7 +100,7 @@ void wiEmittedParticle::CreateSelfBuffers() } bd.stride = sizeof(MeshComponent::Vertex_POS); bd.size = bd.stride * 4 * MAX_PARTICLES; - std::vector positionData(4 * MAX_PARTICLES); + wi::vector positionData(4 * MAX_PARTICLES); std::fill(positionData.begin(), positionData.end(), MeshComponent::Vertex_POS()); device->CreateBuffer(&bd, positionData.data(), &vertexBuffer_POS); device->SetName(&vertexBuffer_POS, "vertexBuffer_POS"); @@ -131,7 +132,7 @@ void wiEmittedParticle::CreateSelfBuffers() bd.format = Format::R32_UINT; bd.stride = sizeof(uint); bd.size = bd.stride * 6 * MAX_PARTICLES; - std::vector primitiveData(6 * MAX_PARTICLES); + wi::vector primitiveData(6 * MAX_PARTICLES); for (uint particleID = 0; particleID < MAX_PARTICLES; ++particleID) { uint v0 = particleID * 4; @@ -156,7 +157,7 @@ void wiEmittedParticle::CreateSelfBuffers() bd.misc_flags = ResourceMiscFlag::BUFFER_STRUCTURED; bd.stride = sizeof(float); bd.size = bd.stride * MAX_PARTICLES; - std::vector distances(MAX_PARTICLES); + wi::vector distances(MAX_PARTICLES); std::fill(distances.begin(), distances.end(), 0.0f); device->CreateBuffer(&bd, distances.data(), &distanceBuffer); device->SetName(&distanceBuffer, "distanceBuffer"); diff --git a/WickedEngine/wiEvent.cpp b/WickedEngine/wiEvent.cpp index 0841182ef..04f1048ad 100644 --- a/WickedEngine/wiEvent.cpp +++ b/WickedEngine/wiEvent.cpp @@ -1,8 +1,7 @@ #include "wiEvent.h" +#include "wiUnorderedMap.h" +#include "wiVector.h" -#include -#include -#include #include #include @@ -10,8 +9,8 @@ namespace wiEvent { struct EventManager { - std::unordered_map*>> subscribers; - std::unordered_map>> subscribers_once; + wi::unordered_map*>> subscribers; + wi::unordered_map>> subscribers_once; std::mutex locker; }; std::shared_ptr manager = std::make_shared(); diff --git a/WickedEngine/wiFont.cpp b/WickedEngine/wiFont.cpp index 0144008fc..5aa2dbfa1 100644 --- a/WickedEngine/wiFont.cpp +++ b/WickedEngine/wiFont.cpp @@ -10,16 +10,15 @@ #include "wiPlatform.h" #include "wiEvent.h" #include "wiTimer.h" +#include "wiUnorderedMap.h" +#include "wiUnorderedSet.h" +#include "wiVector.h" #include "Utility/arial.h" #include "Utility/stb_truetype.h" #include #include -#include -#include -#include -#include using namespace wiGraphics; using namespace wiRectPacker; @@ -56,8 +55,8 @@ namespace wiFont_Internal uint16_t tc_top; uint16_t tc_bottom; }; - std::unordered_map glyph_lookup; - std::unordered_map rect_lookup; + wi::unordered_map glyph_lookup; + wi::unordered_map rect_lookup; // pack glyph identifiers to a 32-bit hash: // height: 10 bits (height supported: 0 - 1023) // style: 6 bits (number of font styles supported: 0 - 63) @@ -66,13 +65,13 @@ namespace wiFont_Internal constexpr int codefromhash(int64_t hash) { return int((hash >> 16) & 0xFFFF); } constexpr int stylefromhash(int64_t hash) { return int((hash >> 10) & 0x3F); } constexpr int heightfromhash(int64_t hash) { return int((hash >> 0) & 0x3FF); } - std::unordered_set pendingGlyphs; + wi::unordered_set pendingGlyphs; wiSpinLock glyphLock; struct wiFontStyle { std::string name; - std::vector fontBuffer; // only used if loaded from file, need to keep alive + wi::vector fontBuffer; // only used if loaded from file, need to keep alive stbtt_fontinfo fontInfo; int ascent, descent, lineGap; void Create(const std::string& newName, const uint8_t* data, size_t size) @@ -82,8 +81,7 @@ namespace wiFont_Internal if (!stbtt_InitFont(&fontInfo, data, offset)) { - std::string error = "Failed to load font: " + name + " (file was unrecognized, it must be a .ttf file)"; - wiBackLog::post(error.c_str()); + wiBackLog::post("Failed to load font: " + name + " (file was unrecognized, it must be a .ttf file)"); } stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap); @@ -96,12 +94,11 @@ namespace wiFont_Internal } else { - std::string error = "Failed to load font: " + name + " (file could not be opened)"; - wiBackLog::post(error.c_str()); + wiBackLog::post("Failed to load font: " + name + " (file could not be opened)"); } } }; - std::vector fontStyles; + wi::vector fontStyles; struct FontVertex { @@ -166,14 +163,12 @@ namespace wiFont_Internal { word_wrap(); pos += WHITESPACE_SIZE; - start_new_word = true; code_prev = 0; } else if (code == '\t') { word_wrap(); pos += TAB_SIZE; - start_new_word = true; code_prev = 0; } else @@ -377,7 +372,7 @@ void UpdatePendingGlyphs() pendingGlyphs.clear(); // This reference array will be used for packing: - std::vector out_rects; + wi::vector out_rects; out_rects.reserve(rect_lookup.size()); for (auto& it : rect_lookup) { @@ -385,7 +380,7 @@ void UpdatePendingGlyphs() } // Perform packing and process the result if successful: - std::vector bins; + wi::vector bins; if (pack(out_rects.data(), (int)out_rects.size(), 4096, bins)) { assert(bins.size() == 1 && "The regions won't fit into one texture!"); @@ -397,7 +392,7 @@ void UpdatePendingGlyphs() const float inv_height = 1.0f / bitmapHeight; // Create the CPU-side texture atlas and fill with transparency (0): - std::vector bitmap(size_t(bitmapWidth) * size_t(bitmapHeight)); + wi::vector bitmap(size_t(bitmapWidth) * size_t(bitmapHeight)); std::fill(bitmap.begin(), bitmap.end(), 0); // Iterate all packed glyph rectangles: @@ -489,6 +484,7 @@ float textWidth_internal(const T* text, const wiFontParams& params) return 0; } + // TODO: account for word wrap float maxWidth = 0; float currentLineWidth = 0; size_t i = 0; @@ -534,6 +530,7 @@ float textHeight_internal(const T* text, const wiFontParams& params) return 0; } + // TODO: account for word wrap float height = LINEBREAK_SIZE; size_t i = 0; while (text[i] != 0) diff --git a/WickedEngine/wiGPUBVH.cpp b/WickedEngine/wiGPUBVH.cpp index 4f4dc4d4a..8e4cbdff7 100644 --- a/WickedEngine/wiGPUBVH.cpp +++ b/WickedEngine/wiGPUBVH.cpp @@ -11,9 +11,6 @@ #include "wiTimer.h" //#define BVH_VALIDATE // slow but great for debug! -#ifdef BVH_VALIDATE -#include -#endif // BVH_VALIDATE using namespace wiGraphics; using namespace wiScene; diff --git a/WickedEngine/wiGPUBVH.h b/WickedEngine/wiGPUBVH.h index cc3ab8885..beca46bef 100644 --- a/WickedEngine/wiGPUBVH.h +++ b/WickedEngine/wiGPUBVH.h @@ -2,13 +2,6 @@ #include "CommonInclude.h" #include "wiGraphicsDevice.h" #include "wiScene_Decl.h" -#include "wiRectPacker.h" -#include "shaders/ShaderInterop_Renderer.h" -#include "wiResourceManager.h" - -#include -#include -#include struct wiGPUBVH { diff --git a/WickedEngine/wiGUI.h b/WickedEngine/wiGUI.h index d93862c2f..4baec249c 100644 --- a/WickedEngine/wiGUI.h +++ b/WickedEngine/wiGUI.h @@ -3,13 +3,12 @@ #include "wiGraphicsDevice.h" #include "wiCanvas.h" #include "wiWidget.h" - -#include +#include "wiVector.h" class wiGUI { private: - std::vector widgets; + wi::vector widgets; bool focus = false; bool visible = true; public: diff --git a/WickedEngine/wiGraphics.h b/WickedEngine/wiGraphics.h index a9a15b423..91a0176cd 100644 --- a/WickedEngine/wiGraphics.h +++ b/WickedEngine/wiGraphics.h @@ -1,9 +1,9 @@ #pragma once #include "CommonInclude.h" +#include "wiVector.h" #include #include -#include #include #include @@ -414,7 +414,7 @@ namespace wiGraphics uint32_t aligned_byte_offset = APPEND_ALIGNED_ELEMENT; InputClassification input_slot_class = InputClassification::PER_VERTEX_DATA; }; - std::vector elements; + wi::vector elements; }; union ClearValue @@ -719,7 +719,7 @@ namespace wiGraphics ALLOW_UAV_WRITES = 1 << 0, }; Flags flags = Flags::EMPTY; - std::vector attachments; + wi::vector attachments; }; struct SwapChainDesc @@ -798,7 +798,7 @@ namespace wiGraphics struct Shader : public GraphicsDeviceChild { ShaderStage stage = ShaderStage::Count; - std::vector auto_samplers; // ability to set static samplers without explicit root signature + wi::vector auto_samplers; // ability to set static samplers without explicit root signature }; struct GPUResource : public GraphicsDeviceChild @@ -924,7 +924,7 @@ namespace wiGraphics } aabbs; }; - std::vector geometries; + wi::vector geometries; } bottom_level; struct TopLevel @@ -987,8 +987,8 @@ namespace wiGraphics }; struct RaytracingPipelineStateDesc { - std::vector shader_libraries; - std::vector hit_groups; + wi::vector shader_libraries; + wi::vector hit_groups; uint32_t max_trace_recursion_depth = 1; uint32_t max_attribute_size_in_bytes = 0; uint32_t max_payload_size_in_bytes = 0; diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index d8cb8d49e..0a5bca58b 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -1,10 +1,10 @@ #include "wiGraphicsDevice_DX12.h" #ifdef WICKEDENGINE_BUILD_DX12 - #include "wiHelper.h" #include "wiBackLog.h" #include "wiTimer.h" +#include "wiUnorderedSet.h" #include "Utility/dx12/d3dx12.h" #include "Utility/D3D12MemAlloc.h" @@ -13,7 +13,6 @@ #include "Utility/dx12/d3d12shader.h" #include -#include #include @@ -1216,8 +1215,8 @@ namespace DX12_Internal ComPtr resource; SingleDescriptor srv; SingleDescriptor uav; - std::vector subresources_srv; - std::vector subresources_uav; + wi::vector subresources_srv; + wi::vector subresources_uav; D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint; @@ -1250,8 +1249,8 @@ namespace DX12_Internal { SingleDescriptor rtv = {}; SingleDescriptor dsv = {}; - std::vector subresources_rtv; - std::vector subresources_dsv; + wi::vector subresources_rtv; + wi::vector subresources_dsv; ~Texture_DX12() override { @@ -1304,21 +1303,21 @@ namespace DX12_Internal ComPtr resource; ComPtr rootSignature; - std::vector root_cbvs; - std::vector resources; - std::vector samplers; + wi::vector root_cbvs; + wi::vector resources; + wi::vector samplers; uint32_t resource_binding_count_unrolled = 0; uint32_t sampler_binding_count_unrolled = 0; - std::vector resource_bindings; + wi::vector resource_bindings; - std::vector bindless_res; - std::vector bindless_sam; + wi::vector bindless_res; + wi::vector bindless_sam; D3D12_ROOT_PARAMETER1 rootconstants; - std::vector staticsamplers; + wi::vector staticsamplers; uint32_t bindpoint_rootconstant = 0; uint32_t bindpoint_rootdescriptor = 0; @@ -1326,8 +1325,8 @@ namespace DX12_Internal uint32_t bindpoint_sam = 0; uint32_t bindpoint_bindless = 0; - std::vector shadercode; - std::vector input_elements; + wi::vector shadercode; + wi::vector input_elements; D3D_PRIMITIVE_TOPOLOGY primitiveTopology; struct PSO_STREAM @@ -1371,7 +1370,7 @@ namespace DX12_Internal struct BVH_DX12 : public Resource_DX12 { D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS desc = {}; - std::vector geometries; + wi::vector geometries; D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO info = {}; GPUBuffer scratch; }; @@ -1380,11 +1379,11 @@ namespace DX12_Internal std::shared_ptr allocationhandler; ComPtr resource; - std::vector export_strings; - std::vector exports; - std::vector library_descs; - std::vector group_strings; - std::vector hitgroup_descs; + wi::vector export_strings; + wi::vector exports; + wi::vector library_descs; + wi::vector group_strings; + wi::vector hitgroup_descs; ~RTPipelineState_DX12() { @@ -1414,8 +1413,8 @@ namespace DX12_Internal { std::shared_ptr allocationhandler; Microsoft::WRL::ComPtr swapChain; - std::vector> backBuffers; - std::vector backbufferRTV; + wi::vector> backBuffers; + wi::vector backbufferRTV; Texture dummyTexture; RenderPass renderpass; @@ -3256,16 +3255,16 @@ using namespace DX12_Internal; if (pInitialData != nullptr) { uint32_t dataCount = pDesc->array_size * std::max(1u, pDesc->mip_levels); - std::vector data(dataCount); + wi::vector data(dataCount); for (uint32_t slice = 0; slice < dataCount; ++slice) { data[slice] = _ConvertSubresourceData(pInitialData[slice]); } UINT64 RequiredSize = 0; - std::vector layouts(dataCount); - std::vector rowSizesInBytes(dataCount); - std::vector numRows(dataCount); + wi::vector layouts(dataCount); + wi::vector rowSizesInBytes(dataCount); + wi::vector numRows(dataCount); device->GetCopyableFootprints(&desc, 0, dataCount, 0, layouts.data(), numRows.data(), rowSizesInBytes.data(), &RequiredSize); auto cmd = copyAllocator.allocate(RequiredSize); @@ -3330,7 +3329,7 @@ using namespace DX12_Internal; HRESULT hr = (internal_state->shadercode.empty() ? E_FAIL : S_OK); assert(SUCCEEDED(hr)); - std::unordered_set library_binding_resolver; + wi::unordered_set library_binding_resolver; { auto insert_descriptor = [&](const D3D12_SHADER_INPUT_BIND_DESC& desc, const D3D12_SHADER_BUFFER_DESC& bufferdesc) @@ -3669,7 +3668,7 @@ using namespace DX12_Internal; if (stage == ShaderStage::CS || stage == ShaderStage::LIB) { - std::vector params; + wi::vector params; internal_state->bindpoint_rootconstant = (uint32_t)params.size(); if (internal_state->rootconstants.Constants.Num32BitValues > 0) @@ -3680,8 +3679,8 @@ using namespace DX12_Internal; // Split resources into root descriptors and tables: { - std::vector resources; - std::vector bindings; + wi::vector resources; + wi::vector bindings; int i = 0; for (auto& x : internal_state->resources) { @@ -4073,7 +4072,7 @@ using namespace DX12_Internal; insert_shader(pDesc->ds); insert_shader(pDesc->gs); - std::vector params; + wi::vector params; internal_state->bindpoint_rootconstant = (uint32_t)params.size(); if (internal_state->rootconstants.Constants.Num32BitValues > 0) @@ -4084,8 +4083,8 @@ using namespace DX12_Internal; // Split resources into root descriptors and tables: { - std::vector resources; - std::vector bindings; + wi::vector resources; + wi::vector bindings; int i = 0; for (auto& x : internal_state->resources) { @@ -4851,7 +4850,7 @@ using namespace DX12_Internal; D3D12_STATE_OBJECT_DESC desc = {}; desc.Type = D3D12_STATE_OBJECT_TYPE_RAYTRACING_PIPELINE; - std::vector subobjects; + wi::vector subobjects; D3D12_RAYTRACING_PIPELINE_CONFIG pipeline_config = {}; { @@ -5546,9 +5545,8 @@ using namespace DX12_Internal; hr = device->CreateCommandList1(0, queues[queue].desc.Type, D3D12_COMMAND_LIST_FLAG_NONE, IID_PPV_ARGS(&commandLists[cmd][queue])); assert(SUCCEEDED(hr)); - std::wstringstream wss; - wss << "cmd" << cmd; - commandLists[cmd][queue]->SetName(wss.str().c_str()); + std::wstring ws = L"cmd" + std::to_wstring(cmd); + commandLists[cmd][queue]->SetName(ws.c_str()); binders[cmd].init(this); } @@ -6456,7 +6454,7 @@ using namespace DX12_Internal; desc.Inputs = dst_internal->desc; // Make a copy of geometries, don't overwrite internal_state (thread safety) - std::vector geometries; + wi::vector geometries; geometries = dst_internal->geometries; desc.Inputs.pGeometryDescs = geometries.data(); diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h index 6c5cb02eb..4e2717d88 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.h +++ b/WickedEngine/wiGraphicsDevice_DX12.h @@ -8,6 +8,8 @@ #ifdef WICKEDENGINE_BUILD_DX12 #include "wiGraphicsDevice.h" +#include "wiUnorderedMap.h" +#include "wiVector.h" #include #include // ComPtr @@ -16,7 +18,6 @@ #define D3D12MA_D3D12_HEADERS_ALREADY_INCLUDED #include "Utility/D3D12MemAlloc.h" -#include #include #include #include @@ -61,7 +62,7 @@ namespace wiGraphics D3D12_CPU_DESCRIPTOR_HANDLE nullUAV_texture2darray = {}; D3D12_CPU_DESCRIPTOR_HANDLE nullUAV_texture3d = {}; - std::vector common_samplers; + wi::vector common_samplers; struct CommandQueue { @@ -85,7 +86,7 @@ namespace wiGraphics Microsoft::WRL::ComPtr fence; GPUBuffer uploadbuffer; }; - std::vector freelist; + wi::vector freelist; void init(GraphicsDevice_DX12* device); void destroy(); @@ -105,7 +106,7 @@ namespace wiGraphics struct CommandListMetadata { QUEUE_TYPE queue = {}; - std::vector waits; + wi::vector waits; } cmd_meta[COMMANDLIST_COUNT]; Microsoft::WRL::ComPtr commandLists[COMMANDLIST_COUNT][QUEUE_COUNT]; @@ -136,15 +137,15 @@ namespace wiGraphics }; DescriptorBinder binders[COMMANDLIST_COUNT]; - std::vector frame_barriers[COMMANDLIST_COUNT]; + wi::vector frame_barriers[COMMANDLIST_COUNT]; D3D_PRIMITIVE_TOPOLOGY prev_pt[COMMANDLIST_COUNT] = {}; - mutable std::unordered_map> rootsignature_cache; + mutable wi::unordered_map> rootsignature_cache; mutable std::mutex rootsignature_cache_mutex; - std::unordered_map> pipelines_global; - std::vector>> pipelines_worker[COMMANDLIST_COUNT]; + wi::unordered_map> pipelines_global; + wi::vector>> pipelines_worker[COMMANDLIST_COUNT]; size_t prev_pipeline_hash[COMMANDLIST_COUNT] = {}; const PipelineState* active_pso[COMMANDLIST_COUNT] = {}; const Shader* active_cs[COMMANDLIST_COUNT] = {}; @@ -153,7 +154,7 @@ namespace wiGraphics const ID3D12RootSignature* active_rootsig_compute[COMMANDLIST_COUNT] = {}; const RenderPass* active_renderpass[COMMANDLIST_COUNT] = {}; ShadingRate prev_shadingrate[COMMANDLIST_COUNT] = {}; - std::vector swapchains[COMMANDLIST_COUNT]; + wi::vector swapchains[COMMANDLIST_COUNT]; Microsoft::WRL::ComPtr active_backbuffer[COMMANDLIST_COUNT]; struct DeferredPushConstantData @@ -295,9 +296,9 @@ namespace wiGraphics GraphicsDevice_DX12* device = nullptr; std::mutex locker; D3D12_DESCRIPTOR_HEAP_DESC desc = {}; - std::vector> heaps; + wi::vector> heaps; uint32_t descriptor_size = 0; - std::vector freelist; + wi::vector freelist; void init(GraphicsDevice_DX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type) { @@ -344,8 +345,8 @@ namespace wiGraphics DescriptorAllocator descriptors_rtv; DescriptorAllocator descriptors_dsv; - std::vector free_bindless_res; - std::vector free_bindless_sam; + wi::vector free_bindless_res; + wi::vector free_bindless_sam; std::deque> destroyer_allocations; std::deque, uint64_t>> destroyer_resources; diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 80a552f3d..05be8db3a 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -5,6 +5,7 @@ #include "wiBackLog.h" #include "wiVersion.h" #include "wiTimer.h" +#include "wiUnorderedSet.h" #define VOLK_IMPLEMENTATION #include "Utility/volk.h" @@ -19,11 +20,9 @@ #include "sdl2.h" #endif -#include -#include +#include #include #include -#include #include // These shifts are made so that Vulkan resource bindings slots don't interfere with each other across shader stages: @@ -521,7 +520,7 @@ namespace Vulkan_Internal } - bool checkExtensionSupport(const char* checkExtension, const std::vector& available_extensions) + bool checkExtensionSupport(const char* checkExtension, const wi::vector& available_extensions) { for (const auto& x : available_extensions) { @@ -533,8 +532,8 @@ namespace Vulkan_Internal return false; } - bool ValidateLayers(const std::vector& required, - const std::vector& available) + bool ValidateLayers(const wi::vector& required, + const wi::vector& available) { for (auto layer : required) { @@ -557,9 +556,9 @@ namespace Vulkan_Internal return true; } - std::vector GetOptimalValidationLayers(const std::vector& supported_instance_layers) + wi::vector GetOptimalValidationLayers(const wi::vector& supported_instance_layers) { - std::vector> validationLayerPriorityList = + wi::vector> validationLayerPriorityList = { // The preferred validation layer is "VK_LAYER_KHRONOS_validation" {"VK_LAYER_KHRONOS_validation"}, @@ -598,23 +597,22 @@ namespace Vulkan_Internal const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { - // Log debug messge - std::stringstream ss(""); + // Log debug message + std::string ss; if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { - ss << "[Vulkan Warning]: " << callback_data->pMessage << std::endl; + ss += "[Vulkan Warning]: "; + ss += callback_data->pMessage; + wiBackLog::post(ss, wiBackLog::LogLevel::Warning); } else if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { - ss << "[Vulkan Error]: " << callback_data->pMessage << std::endl; + ss += "[Vulkan Error]: "; + ss += callback_data->pMessage; + wiBackLog::post(ss, wiBackLog::LogLevel::Error); } - std::clog << ss.str(); -#ifdef _WIN32 - OutputDebugStringA(ss.str().c_str()); -#endif - return VK_FALSE; } @@ -629,10 +627,10 @@ namespace Vulkan_Internal int srv_index = -1; VkBufferView uav = VK_NULL_HANDLE; int uav_index = -1; - std::vector subresources_srv; - std::vector subresources_srv_index; - std::vector subresources_uav; - std::vector subresources_uav_index; + wi::vector subresources_srv; + wi::vector subresources_srv_index; + wi::vector subresources_uav; + wi::vector subresources_uav_index; VkDeviceAddress address = 0; bool is_typedbuffer = false; @@ -695,13 +693,13 @@ namespace Vulkan_Internal VkImageView rtv = VK_NULL_HANDLE; VkImageView dsv = VK_NULL_HANDLE; uint32_t framebuffer_layercount = 0; - std::vector subresources_srv; - std::vector subresources_srv_index; - std::vector subresources_uav; - std::vector subresources_uav_index; - std::vector subresources_rtv; - std::vector subresources_dsv; - std::vector subresources_framebuffer_layercount; + wi::vector subresources_srv; + wi::vector subresources_srv_index; + wi::vector subresources_uav; + wi::vector subresources_uav_index; + wi::vector subresources_rtv; + wi::vector subresources_dsv; + wi::vector subresources_framebuffer_layercount; VkSubresourceLayout subresourcelayout = {}; @@ -786,11 +784,11 @@ namespace Vulkan_Internal VkPipelineShaderStageCreateInfo stageInfo = {}; VkPipelineLayout pipelineLayout_cs = VK_NULL_HANDLE; // no lifetime management here VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; // no lifetime management here - std::vector layoutBindings; - std::vector imageViewTypes; + wi::vector layoutBindings; + wi::vector imageViewTypes; - std::vector bindlessBindings; - std::vector bindlessSets; + wi::vector bindlessBindings; + wi::vector bindlessSets; uint32_t bindlessFirstSet = 0; VkPushConstantRange pushconstants = {}; @@ -813,11 +811,11 @@ namespace Vulkan_Internal std::shared_ptr allocationhandler; VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; // no lifetime management here VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; // no lifetime management here - std::vector layoutBindings; - std::vector imageViewTypes; + wi::vector layoutBindings; + wi::vector imageViewTypes; - std::vector bindlessBindings; - std::vector bindlessSets; + wi::vector bindlessBindings; + wi::vector bindlessSets; uint32_t bindlessFirstSet = 0; VkPushConstantRange pushconstants = {}; @@ -866,8 +864,8 @@ namespace Vulkan_Internal VkAccelerationStructureBuildGeometryInfoKHR buildInfo = {}; VkAccelerationStructureBuildSizesInfoKHR sizeInfo = {}; VkAccelerationStructureCreateInfoKHR createInfo = {}; - std::vector geometries; - std::vector primitiveCounts; + wi::vector geometries; + wi::vector primitiveCounts; VkDeviceAddress scratch_address = 0; VkDeviceAddress as_address = 0; @@ -904,9 +902,9 @@ namespace Vulkan_Internal VkSwapchainKHR swapChain = VK_NULL_HANDLE; VkFormat swapChainImageFormat; VkExtent2D swapChainExtent; - std::vector swapChainImages; - std::vector swapChainImageViews; - std::vector swapChainFramebuffers; + wi::vector swapChainImages; + wi::vector swapChainImageViews; + wi::vector swapChainFramebuffers; RenderPass renderpass; VkSurfaceKHR surface = VK_NULL_HANDLE; @@ -1016,7 +1014,7 @@ namespace Vulkan_Internal res = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, internal_state->surface, &formatCount, nullptr); assert(res == VK_SUCCESS); - std::vector swapchain_formats(formatCount); + wi::vector swapchain_formats(formatCount); res = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, internal_state->surface, &formatCount, swapchain_formats.data()); assert(res == VK_SUCCESS); @@ -1024,7 +1022,7 @@ namespace Vulkan_Internal res = vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, internal_state->surface, &presentModeCount, nullptr); assert(res == VK_SUCCESS); - std::vector swapchain_presentModes(presentModeCount); + wi::vector swapchain_presentModes(presentModeCount); swapchain_presentModes.resize(presentModeCount); res = vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, internal_state->surface, &presentModeCount, swapchain_presentModes.data()); assert(res == VK_SUCCESS); @@ -2117,8 +2115,8 @@ using namespace Vulkan_Internal; // Input layout: VkPipelineVertexInputStateCreateInfo vertexInputInfo = {}; vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - std::vector bindings; - std::vector attributes; + wi::vector bindings; + wi::vector attributes; if (pso->desc.il != nullptr) { uint32_t lastBinding = 0xFFFFFFFF; @@ -2235,9 +2233,7 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - std::stringstream ss(""); - ss << "volkInitialize failed! ERROR: " << res; - wiHelper::messageBox(ss.str(), "Error!"); + wiHelper::messageBox("volkInitialize failed! ERROR: " + std::to_string(res), "Error!"); wiPlatform::Exit(); } @@ -2254,19 +2250,19 @@ using namespace Vulkan_Internal; uint32_t instanceLayerCount; res = vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr); assert(res == VK_SUCCESS); - std::vector availableInstanceLayers(instanceLayerCount); + wi::vector availableInstanceLayers(instanceLayerCount); res = vkEnumerateInstanceLayerProperties(&instanceLayerCount, availableInstanceLayers.data()); assert(res == VK_SUCCESS); uint32_t extensionCount = 0; res = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); assert(res == VK_SUCCESS); - std::vector availableInstanceExtensions(extensionCount); + wi::vector availableInstanceExtensions(extensionCount); res = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, availableInstanceExtensions.data()); assert(res == VK_SUCCESS); - std::vector instanceLayers; - std::vector instanceExtensions; + wi::vector instanceLayers; + wi::vector instanceExtensions; for (auto& availableExtension : availableInstanceExtensions) { @@ -2293,7 +2289,7 @@ using namespace Vulkan_Internal; { uint32_t extensionCount; SDL_Vulkan_GetInstanceExtensions(window, &extensionCount, nullptr); - std::vector extensionNames_sdl(extensionCount); + wi::vector extensionNames_sdl(extensionCount); SDL_Vulkan_GetInstanceExtensions(window, &extensionCount, extensionNames_sdl.data()); instanceExtensions.reserve(instanceExtensions.size() + extensionNames_sdl.size()); instanceExtensions.insert(instanceExtensions.begin(), @@ -2304,7 +2300,7 @@ using namespace Vulkan_Internal; if (debuglayer) { // Determine the optimal validation layers to enable that are necessary for useful debugging - std::vector optimalValidationLyers = GetOptimalValidationLayers(availableInstanceLayers); + wi::vector optimalValidationLyers = GetOptimalValidationLayers(availableInstanceLayers); instanceLayers.insert(instanceLayers.end(), optimalValidationLyers.begin(), optimalValidationLyers.end()); } @@ -2332,9 +2328,7 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - std::stringstream ss(""); - ss << "vkCreateInstance failed! ERROR: " << res; - wiHelper::messageBox(ss.str(), "Error!"); + wiHelper::messageBox("vkCreateInstance failed! ERROR: " + std::to_string(res), "Error!"); wiPlatform::Exit(); } @@ -2359,14 +2353,14 @@ using namespace Vulkan_Internal; wiPlatform::Exit(); } - std::vector devices(deviceCount); + wi::vector devices(deviceCount); res = vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); assert(res == VK_SUCCESS); - const std::vector required_deviceExtensions = { + const wi::vector required_deviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, }; - std::vector enabled_deviceExtensions; + wi::vector enabled_deviceExtensions; for (const auto& dev : devices) { @@ -2375,7 +2369,7 @@ using namespace Vulkan_Internal; uint32_t extensionCount; VkResult res = vkEnumerateDeviceExtensionProperties(dev, nullptr, &extensionCount, nullptr); assert(res == VK_SUCCESS); - std::vector available_deviceExtensions(extensionCount); + wi::vector available_deviceExtensions(extensionCount); res = vkEnumerateDeviceExtensionProperties(dev, nullptr, &extensionCount, available_deviceExtensions.data()); assert(res == VK_SUCCESS); @@ -2628,8 +2622,8 @@ using namespace Vulkan_Internal; familyIndex++; } - std::vector queueCreateInfos; - std::set uniqueQueueFamilies = { graphicsFamily, copyFamily, computeFamily }; + wi::vector queueCreateInfos; + wi::unordered_set uniqueQueueFamilies = { graphicsFamily, copyFamily, computeFamily }; float queuePriority = 1.0f; for (uint32_t queueFamily : uniqueQueueFamilies) @@ -2656,9 +2650,7 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - std::stringstream ss(""); - ss << "vkCreateDevice failed! ERROR: " << res; - wiHelper::messageBox(ss.str(), "Error!"); + wiHelper::messageBox("vkCreateDevice failed! ERROR: " + std::to_string(res), "Error!"); wiPlatform::Exit(); } @@ -2689,18 +2681,14 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - std::stringstream ss(""); - ss << "vkCreateSemaphore[QUEUE_GRAPHICS] failed! ERROR: " << res; - wiHelper::messageBox(ss.str(), "Error!"); + wiHelper::messageBox("vkCreateSemaphore[QUEUE_GRAPHICS] failed! ERROR: " + std::to_string(res), "Error!"); wiPlatform::Exit(); } res = vkCreateSemaphore(device, &createInfo, nullptr, &queues[QUEUE_COMPUTE].semaphore); assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - std::stringstream ss(""); - ss << "vkCreateSemaphore[QUEUE_COMPUTE] failed! ERROR: " << res; - wiHelper::messageBox(ss.str(), "Error!"); + wiHelper::messageBox("vkCreateSemaphore[QUEUE_COMPUTE] failed! ERROR: " + std::to_string(res), "Error!"); wiPlatform::Exit(); } } @@ -2723,9 +2711,7 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - std::stringstream ss(""); - ss << "vmaCreateAllocator failed! ERROR: " << res; - wiHelper::messageBox(ss.str(), "Error!"); + wiHelper::messageBox("vmaCreateAllocator failed! ERROR: " + std::to_string(res), "Error!"); wiPlatform::Exit(); } @@ -2743,9 +2729,7 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - std::stringstream ss(""); - ss << "vkCreateFence[FRAME] failed! ERROR: " << res; - wiHelper::messageBox(ss.str(), "Error!"); + wiHelper::messageBox("vkCreateFence[FRAME] failed! ERROR: " + std::to_string(res), "Error!"); wiPlatform::Exit(); } } @@ -2761,9 +2745,7 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - std::stringstream ss(""); - ss << "vkCreateCommandPool[FRAME_INIT] failed! ERROR: " << res; - wiHelper::messageBox(ss.str(), "Error!"); + wiHelper::messageBox("vkCreateCommandPool[FRAME_INIT] failed! ERROR: " + std::to_string(res), "Error!"); wiPlatform::Exit(); } @@ -2777,9 +2759,7 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - std::stringstream ss(""); - ss << "vkAllocateCommandBuffers[FRAME_INIT] failed! ERROR: " << res; - wiHelper::messageBox(ss.str(), "Error!"); + wiHelper::messageBox("vkAllocateCommandBuffers[FRAME_INIT] failed! ERROR: " + std::to_string(res), "Error!"); wiPlatform::Exit(); } @@ -2792,9 +2772,7 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); if (res != VK_SUCCESS) { - std::stringstream ss(""); - ss << "vkBeginCommandBuffer[FRAME_INIT] failed! ERROR: " << res; - wiHelper::messageBox(ss.str(), "Error!"); + wiHelper::messageBox("vkBeginCommandBuffer[FRAME_INIT] failed! ERROR: " + std::to_string(res), "Error!"); wiPlatform::Exit(); } } @@ -3021,7 +2999,7 @@ using namespace Vulkan_Internal; // Pipeline Cache { // Try to read pipeline cache file if exists. - std::vector pipelineData; + wi::vector pipelineData; std::string cachePath = GetCachePath(); if (!wiHelper::FileRead(cachePath, pipelineData)) @@ -3159,7 +3137,7 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); // Get data of pipeline cache - std::vector data(size); + wi::vector data(size); res = vkGetPipelineCacheData(device, pipelineCache, &size, data.data()); assert(res == VK_SUCCESS); @@ -3613,7 +3591,7 @@ using namespace Vulkan_Internal; { auto cmd = copyAllocator.allocate(internal_state->allocation->GetSize()); - std::vector copyRegions; + wi::vector copyRegions; VkDeviceSize copyOffset = 0; uint32_t initDataIdx = 0; @@ -3829,7 +3807,7 @@ using namespace Vulkan_Internal; ); assert(result == SPV_REFLECT_RESULT_SUCCESS); - std::vector bindings(binding_count); + wi::vector bindings(binding_count); result = spvReflectEnumerateDescriptorBindings( &module, &binding_count, bindings.data() ); @@ -3839,11 +3817,11 @@ using namespace Vulkan_Internal; result = spvReflectEnumeratePushConstantBlocks(&module, &push_count, nullptr); assert(result == SPV_REFLECT_RESULT_SUCCESS); - std::vector pushconstants(push_count); + wi::vector pushconstants(push_count); result = spvReflectEnumeratePushConstantBlocks(&module, &push_count, pushconstants.data()); assert(result == SPV_REFLECT_RESULT_SUCCESS); - std::vector staticsamplers; + wi::vector staticsamplers; for (auto& x : pushconstants) { @@ -3982,7 +3960,7 @@ using namespace Vulkan_Internal; pso_layout_cache_mutex.lock(); if (pso_layout_cache[internal_state->binding_hash].pipelineLayout == VK_NULL_HANDLE) { - std::vector layouts; + wi::vector layouts; { VkDescriptorSetLayoutCreateInfo descriptorSetlayoutInfo = {}; @@ -4491,7 +4469,7 @@ using namespace Vulkan_Internal; pso_layout_cache_mutex.lock(); if (pso_layout_cache[internal_state->binding_hash].pipelineLayout == VK_NULL_HANDLE) { - std::vector layouts; + wi::vector layouts; { VkDescriptorSetLayoutCreateInfo descriptorSetlayoutInfo = {}; descriptorSetlayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; @@ -5305,7 +5283,7 @@ using namespace Vulkan_Internal; info.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; info.flags = 0; - std::vector stages; + wi::vector stages; for (auto& x : pDesc->shader_libraries) { stages.emplace_back(); @@ -5337,7 +5315,7 @@ using namespace Vulkan_Internal; info.stageCount = (uint32_t)stages.size(); info.pStages = stages.data(); - std::vector groups; + wi::vector groups; groups.reserve(pDesc->hit_groups.size()); for (auto& x : pDesc->hit_groups) { @@ -6252,7 +6230,7 @@ using namespace Vulkan_Internal; VkResult res = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, internal_state->surface, &formatCount, nullptr); if (res == VK_SUCCESS) { - std::vector swapchain_formats(formatCount); + wi::vector swapchain_formats(formatCount); res = vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, internal_state->surface, &formatCount, swapchain_formats.data()); if (res == VK_SUCCESS) { @@ -7100,8 +7078,8 @@ using namespace Vulkan_Internal; info.srcAccelerationStructure = src_internal->resource; } - std::vector geometries = dst_internal->geometries; // copy! - std::vector ranges; + wi::vector geometries = dst_internal->geometries; // copy! + wi::vector ranges; info.type = dst_internal->createInfo.type; info.geometryCount = (uint32_t)geometries.size(); diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index dba11b4ce..5d629e3cd 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -8,6 +8,8 @@ #ifdef WICKEDENGINE_BUILD_VULKAN #include "wiGraphicsDevice.h" +#include "wiUnorderedMap.h" +#include "wiVector.h" #ifdef _WIN32 #define VK_USE_PLATFORM_WIN32_KHR @@ -18,8 +20,6 @@ #include "Utility/volk.h" #include "Utility/vk_mem_alloc.h" -#include -#include #include #include #include @@ -36,11 +36,11 @@ namespace wiGraphics VkDebugUtilsMessengerEXT debugUtilsMessenger = VK_NULL_HANDLE; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkDevice device = VK_NULL_HANDLE; - std::vector queueFamilies; + wi::vector queueFamilies; uint32_t graphicsFamily = VK_QUEUE_FAMILY_IGNORED; uint32_t computeFamily = VK_QUEUE_FAMILY_IGNORED; uint32_t copyFamily = VK_QUEUE_FAMILY_IGNORED; - std::vector families; + wi::vector families; VkQueue graphicsQueue = VK_NULL_HANDLE; VkQueue computeQueue = VK_NULL_HANDLE; VkQueue copyQueue = VK_NULL_HANDLE; @@ -65,7 +65,7 @@ namespace wiGraphics VkPhysicalDeviceConditionalRenderingFeaturesEXT conditional_rendering_features = {}; VkPhysicalDeviceDepthClipEnableFeaturesEXT depth_clip_enable_features = {}; - std::vector pso_dynamicStates; + wi::vector pso_dynamicStates; VkPipelineDynamicStateCreateInfo dynamicStateInfo = {}; VkBuffer nullBuffer = VK_NULL_HANDLE; @@ -90,15 +90,15 @@ namespace wiGraphics { VkQueue queue = VK_NULL_HANDLE; VkSemaphore semaphore = VK_NULL_HANDLE; - std::vector swapchain_updates; - std::vector submit_swapchains; - std::vector submit_swapChainImageIndices; - std::vector submit_waitStages; - std::vector submit_waitSemaphores; - std::vector submit_waitValues; - std::vector submit_signalSemaphores; - std::vector submit_signalValues; - std::vector submit_cmds; + wi::vector swapchain_updates; + wi::vector submit_swapchains; + wi::vector submit_swapChainImageIndices; + wi::vector submit_waitStages; + wi::vector submit_waitSemaphores; + wi::vector submit_waitValues; + wi::vector submit_signalSemaphores; + wi::vector submit_signalValues; + wi::vector submit_cmds; void submit(GraphicsDevice_Vulkan* device, VkFence fence); @@ -118,9 +118,9 @@ namespace wiGraphics uint64_t target = 0; GPUBuffer uploadbuffer; }; - std::vector freelist; // available - std::vector worklist; // in progress - std::vector submit_cmds; // for next submit + wi::vector freelist; // available + wi::vector worklist; // in progress + wi::vector submit_cmds; // for next submit uint64_t submit_wait = 0; // last submit wait value void init(GraphicsDevice_Vulkan* device); @@ -161,7 +161,7 @@ namespace wiGraphics struct CommandListMetadata { QUEUE_TYPE queue = {}; - std::vector waits; + wi::vector waits; } cmd_meta[COMMANDLIST_COUNT]; inline VkCommandBuffer GetCommandList(CommandList::index_type cmd) @@ -174,11 +174,11 @@ namespace wiGraphics DescriptorBindingTable table; GraphicsDevice_Vulkan* device; - std::vector descriptorWrites; - std::vector bufferInfos; - std::vector imageInfos; - std::vector texelBufferViews; - std::vector accelerationStructureViews; + wi::vector descriptorWrites; + wi::vector bufferInfos; + wi::vector imageInfos; + wi::vector texelBufferViews; + wi::vector accelerationStructureViews; bool dirty = false; void init(GraphicsDevice_Vulkan* device); @@ -187,30 +187,30 @@ namespace wiGraphics }; DescriptorBinder binders[COMMANDLIST_COUNT]; - std::vector frame_memoryBarriers[COMMANDLIST_COUNT]; - std::vector frame_imageBarriers[COMMANDLIST_COUNT]; - std::vector frame_bufferBarriers[COMMANDLIST_COUNT]; + wi::vector frame_memoryBarriers[COMMANDLIST_COUNT]; + wi::vector frame_imageBarriers[COMMANDLIST_COUNT]; + wi::vector frame_bufferBarriers[COMMANDLIST_COUNT]; struct PSOLayout { VkPipelineLayout pipelineLayout = VK_NULL_HANDLE; VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; - std::vector bindlessSets; + wi::vector bindlessSets; uint32_t bindlessFirstSet = 0; }; - mutable std::unordered_map pso_layout_cache; + mutable wi::unordered_map pso_layout_cache; mutable std::mutex pso_layout_cache_mutex; VkPipelineCache pipelineCache = VK_NULL_HANDLE; - std::unordered_map pipelines_global; - std::vector> pipelines_worker[COMMANDLIST_COUNT]; + wi::unordered_map pipelines_global; + wi::vector> pipelines_worker[COMMANDLIST_COUNT]; size_t prev_pipeline_hash[COMMANDLIST_COUNT] = {}; const PipelineState* active_pso[COMMANDLIST_COUNT] = {}; const Shader* active_cs[COMMANDLIST_COUNT] = {}; const RaytracingPipelineState* active_rt[COMMANDLIST_COUNT] = {}; const RenderPass* active_renderpass[COMMANDLIST_COUNT] = {}; ShadingRate prev_shadingrate[COMMANDLIST_COUNT] = {}; - std::vector prev_swapchains[COMMANDLIST_COUNT]; + wi::vector prev_swapchains[COMMANDLIST_COUNT]; uint32_t vb_strides[COMMANDLIST_COUNT][8] = {}; size_t vb_hash[COMMANDLIST_COUNT] = {}; @@ -231,7 +231,7 @@ namespace wiGraphics std::atomic cmd_count{ 0 }; - std::vector common_samplers; + wi::vector common_samplers; public: GraphicsDevice_Vulkan(wiPlatform::window_type window, bool debuglayer = false); @@ -338,7 +338,7 @@ namespace wiGraphics VkDescriptorSetLayout descriptorSetLayout = VK_NULL_HANDLE; VkDescriptorPool descriptorPool = VK_NULL_HANDLE; VkDescriptorSet descriptorSet = VK_NULL_HANDLE; - std::vector freelist; + wi::vector freelist; std::mutex locker; void init(VkDevice device, VkDescriptorType type, uint32_t descriptorCount) diff --git a/WickedEngine/wiHairParticle.cpp b/WickedEngine/wiHairParticle.cpp index 8578d3b83..34f4a640c 100644 --- a/WickedEngine/wiHairParticle.cpp +++ b/WickedEngine/wiHairParticle.cpp @@ -94,7 +94,7 @@ void wiHairParticle::UpdateCPU(const TransformComponent& transform, const MeshCo bd.format = Format::R32_UINT; bd.stride = sizeof(uint); bd.size = bd.stride * 6 * particleCount; - std::vector primitiveData(6 * particleCount); + wi::vector primitiveData(6 * particleCount); for (uint particleID = 0; particleID < particleCount; ++particleID) { uint v0 = particleID * 4; @@ -149,7 +149,7 @@ void wiHairParticle::UpdateCPU(const TransformComponent& transform, const MeshCo if (!vertex_lengths.empty()) { - std::vector ulengths; + wi::vector ulengths; ulengths.reserve(vertex_lengths.size()); for (auto& x : vertex_lengths) { diff --git a/WickedEngine/wiHairParticle.h b/WickedEngine/wiHairParticle.h index 41a589cd0..96da168dc 100644 --- a/WickedEngine/wiHairParticle.h +++ b/WickedEngine/wiHairParticle.h @@ -6,6 +6,7 @@ #include "wiECS.h" #include "wiScene_Decl.h" #include "wiIntersect.h" +#include "wiVector.h" #include @@ -52,7 +53,7 @@ public: float stiffness = 10.0f; float randomness = 0.2f; float viewDistance = 200; - std::vector vertex_lengths; + wi::vector vertex_lengths; // Sprite sheet properties: uint32_t framesX = 1; @@ -64,7 +65,7 @@ public: XMFLOAT4X4 world; XMFLOAT4X4 worldPrev; AABB aabb; - std::vector indices; // it is dependent on vertex_lengths and contains triangles with non-zero lengths + wi::vector indices; // it is dependent on vertex_lengths and contains triangles with non-zero lengths uint32_t layerMask = ~0u; mutable bool regenerate_frame = true; diff --git a/WickedEngine/wiHelper.cpp b/WickedEngine/wiHelper.cpp index 9e8140b00..1b277821d 100644 --- a/WickedEngine/wiHelper.cpp +++ b/WickedEngine/wiHelper.cpp @@ -95,12 +95,11 @@ namespace wiHelper if (result) { - std::string msg = "Screenshot saved: " + filename; - wiBackLog::post(msg.c_str()); + wiBackLog::post("Screenshot saved: " + filename); } } - bool saveTextureToMemory(const wiGraphics::Texture& texture, std::vector& texturedata) + bool saveTextureToMemory(const wiGraphics::Texture& texture, wi::vector& texturedata) { using namespace wiGraphics; @@ -175,11 +174,11 @@ namespace wiHelper return stagingTex.mapped_data != nullptr; } - bool saveTextureToMemoryFile(const wiGraphics::Texture& texture, const std::string& fileExtension, std::vector& filedata) + bool saveTextureToMemoryFile(const wiGraphics::Texture& texture, const std::string& fileExtension, wi::vector& filedata) { using namespace wiGraphics; TextureDesc desc = texture.GetDesc(); - std::vector texturedata; + wi::vector texturedata; if (saveTextureToMemory(texture, texturedata)) { return saveTextureToMemoryFile(texturedata, desc, fileExtension, filedata); @@ -187,7 +186,7 @@ namespace wiHelper return false; } - bool saveTextureToMemoryFile(const std::vector& texturedata, const wiGraphics::TextureDesc& desc, const std::string& fileExtension, std::vector& filedata) + bool saveTextureToMemoryFile(const wi::vector& texturedata, const wiGraphics::TextureDesc& desc, const std::string& fileExtension, wi::vector& filedata) { using namespace wiGraphics; uint32_t data_count = desc.width * desc.height; @@ -385,7 +384,7 @@ namespace wiHelper filedata.clear(); stbi_write_func* func = [](void* context, void* data, int size) { - std::vector& filedata = *(std::vector*)context; + wi::vector& filedata = *(wi::vector*)context; for (int i = 0; i < size; ++i) { filedata.push_back(*((uint8_t*)data + i)); @@ -426,7 +425,7 @@ namespace wiHelper { using namespace wiGraphics; TextureDesc desc = texture.GetDesc(); - std::vector data; + wi::vector data; if (saveTextureToMemory(texture, data)) { return saveTextureToFile(data, desc, fileName); @@ -434,12 +433,12 @@ namespace wiHelper return false; } - bool saveTextureToFile(const std::vector& texturedata, const wiGraphics::TextureDesc& desc, const std::string& fileName) + bool saveTextureToFile(const wi::vector& texturedata, const wiGraphics::TextureDesc& desc, const std::string& fileName) { using namespace wiGraphics; std::string ext = GetExtensionFromFileName(fileName); - std::vector filedata; + wi::vector filedata; if (saveTextureToMemoryFile(texturedata, desc, ext, filedata)) { return FileWrite(fileName, filedata.data(), filedata.size()); @@ -512,12 +511,24 @@ namespace wiHelper { size_t idx = filename.rfind('.'); - if (idx != std::string::npos) + if (idx == std::string::npos) { - return filename.substr(0, idx + 1) + extension; + // extension not found, append it: + return filename + "." + extension; } + return filename.substr(0, idx + 1) + extension; + } - return filename; + std::string RemoveExtension(const std::string& filename) + { + size_t idx = filename.rfind('.'); + + if (idx == std::string::npos) + { + // extension not found: + return filename; + } + return filename.substr(0, idx); } void MakePathRelative(const std::string& rootdir, std::string& path) @@ -557,7 +568,7 @@ namespace wiHelper std::filesystem::create_directories(path); } - bool FileRead(const std::string& fileName, std::vector& data) + bool FileRead(const std::string& fileName, wi::vector& data) { #ifndef PLATFORM_UWP #ifdef SDL_FILESYSTEM_UNIX @@ -605,7 +616,7 @@ namespace wiHelper switch (ex.code()) { case E_ACCESSDENIED: - wiBackLog::post(("Opening file failed: " + fileName + " | Reason: Permission Denied!").c_str()); + wiBackLog::post("Opening file failed: " + fileName + " | Reason: Permission Denied!"); break; default: break; @@ -630,7 +641,7 @@ namespace wiHelper #endif // PLATFORM_UWP - wiBackLog::post(("File not found: " + fileName).c_str()); + wiBackLog::post("File not found: " + fileName); return false; } @@ -680,7 +691,7 @@ namespace wiHelper switch (ex.code()) { case E_ACCESSDENIED: - wiBackLog::post(("Opening file failed: " + fileName + " | Reason: Permission Denied!").c_str()); + wiBackLog::post("Opening file failed: " + fileName + " | Reason: Permission Denied!"); break; default: break; @@ -753,7 +764,7 @@ namespace wiHelper // Second string is extensions, each separated by ';' and at the end of all, a '\0' // Then the whole container string is closed with an other '\0' // For example: "model files\0*.model;*.obj;\0" <-- this string literal has "model files" as description and two accepted extensions "model" and "obj" - std::vector filter; + wi::vector filter; filter.reserve(256); { for (auto& x : params.description) @@ -887,7 +898,7 @@ namespace wiHelper std::cerr << message << std::endl; } - std::vector extensions = {params.description, ""}; + wi::vector extensions = {params.description, ""}; for (auto& x : params.extensions) { extensions[1] += "*." + x + " "; @@ -895,7 +906,7 @@ namespace wiHelper switch (params.type) { case FileDialogParams::OPEN: { - std::vector selection = pfd::open_file( + wi::vector selection = pfd::open_file( "Open file", std::filesystem::current_path().string(), extensions @@ -924,18 +935,20 @@ namespace wiHelper bool Bin2H(const uint8_t* data, size_t size, const std::string& dst_filename, const char* dataName) { - std::stringstream ss; - ss << "const uint8_t " << dataName << "[] = {"; + std::string ss; + ss += "const uint8_t "; + ss += dataName ; + ss += "[] = {"; for (size_t i = 0; i < size; ++i) { if (i % 32 == 0) { - ss << std::endl; + ss += "\n"; } - ss << (uint32_t)data[i] << ","; + ss += std::to_string((uint32_t)data[i]) + ","; } - ss << std::endl << "};" << std::endl; - return FileWrite(dst_filename, (uint8_t*)ss.str().c_str(), ss.str().length()); + ss += "\n};\n"; + return FileWrite(dst_filename, (uint8_t*)ss.c_str(), ss.length()); } void StringConvert(const std::string& from, std::wstring& to) diff --git a/WickedEngine/wiHelper.h b/WickedEngine/wiHelper.h index 009633785..a4fea7b90 100644 --- a/WickedEngine/wiHelper.h +++ b/WickedEngine/wiHelper.h @@ -1,9 +1,9 @@ #pragma once #include "CommonInclude.h" #include "wiGraphicsDevice.h" +#include "wiVector.h" #include -#include #include namespace wiHelper @@ -38,19 +38,19 @@ namespace wiHelper void screenshot(const wiGraphics::SwapChain& swapchain, const std::string& name = ""); // Save raw pixel data from the texture to memory - bool saveTextureToMemory(const wiGraphics::Texture& texture, std::vector& texturedata); + bool saveTextureToMemory(const wiGraphics::Texture& texture, wi::vector& texturedata); // Save texture to memory as a file format - bool saveTextureToMemoryFile(const wiGraphics::Texture& texture, const std::string& fileExtension, std::vector& filedata); + bool saveTextureToMemoryFile(const wiGraphics::Texture& texture, const std::string& fileExtension, wi::vector& filedata); // Save raw texture data to memory as file format - bool saveTextureToMemoryFile(const std::vector& textureData, const wiGraphics::TextureDesc& desc, const std::string& fileExtension, std::vector& filedata); + bool saveTextureToMemoryFile(const wi::vector& textureData, const wiGraphics::TextureDesc& desc, const std::string& fileExtension, wi::vector& filedata); // Save texture to file format bool saveTextureToFile(const wiGraphics::Texture& texture, const std::string& fileName); // Save raw texture data to file format - bool saveTextureToFile(const std::vector& texturedata, const wiGraphics::TextureDesc& desc, const std::string& fileName); + bool saveTextureToFile(const wi::vector& texturedata, const wiGraphics::TextureDesc& desc, const std::string& fileName); std::string getCurrentDateTimeAsString(); @@ -64,13 +64,15 @@ namespace wiHelper std::string ReplaceExtension(const std::string& filename, const std::string& extension); + std::string RemoveExtension(const std::string& filename); + void MakePathRelative(const std::string& rootdir, std::string& path); void MakePathAbsolute(std::string& path); void DirectoryCreate(const std::string& path); - bool FileRead(const std::string& fileName, std::vector& data); + bool FileRead(const std::string& fileName, wi::vector& data); bool FileWrite(const std::string& fileName, const uint8_t* data, size_t size); @@ -87,7 +89,7 @@ namespace wiHelper SAVE, } type = OPEN; std::string description; - std::vector extensions; + wi::vector extensions; }; void FileDialog(const FileDialogParams& params, std::function onSuccess); diff --git a/WickedEngine/wiInitializer.cpp b/WickedEngine/wiInitializer.cpp index 560f78864..dd6ea1672 100644 --- a/WickedEngine/wiInitializer.cpp +++ b/WickedEngine/wiInitializer.cpp @@ -2,7 +2,6 @@ #include "WickedEngine.h" #include -#include #include namespace wiInitializer @@ -22,10 +21,12 @@ namespace wiInitializer initializationStarted = true; - std::stringstream ss; - ss << std::endl << "[wiInitializer] Initializing Wicked Engine, please wait..." << std::endl; - ss << "Version: " << wiVersion::GetVersionString() << std::endl; - wiBackLog::post(ss.str().c_str()); + std::string ss; + ss += "\n[wiInitializer] Initializing Wicked Engine, please wait...\n"; + ss += "Version: "; + ss += wiVersion::GetVersionString(); + ss += "\n"; + wiBackLog::post(ss); wiJobSystem::Initialize(); wiShaderCompiler::Initialize(); @@ -33,7 +34,7 @@ namespace wiInitializer size_t shaderdump_count = wiRenderer::GetShaderDumpCount(); if (shaderdump_count > 0) { - wiBackLog::post(("Embedded shaders found: " + std::to_string(shaderdump_count)).c_str()); + wiBackLog::post("Embedded shaders found: " + std::to_string(shaderdump_count)); } wiBackLog::post(""); diff --git a/WickedEngine/wiInput.cpp b/WickedEngine/wiInput.cpp index 29f9a894d..c6da05a50 100644 --- a/WickedEngine/wiInput.cpp +++ b/WickedEngine/wiInput.cpp @@ -45,6 +45,7 @@ namespace wiInput KeyboardState keyboard; MouseState mouse; + const KeyboardState& GetKeyboardState() { return keyboard; } const MouseState& GetMouseState() { return mouse; } struct Input @@ -62,7 +63,7 @@ namespace wiInput }; }; std::map inputs; - std::vector touches; + wi::vector touches; struct Controller { @@ -77,7 +78,7 @@ namespace wiInput int deviceIndex; ControllerState state; }; - std::vector controllers; + wi::vector controllers; std::atomic_bool initialized{ false }; void Initialize() @@ -110,7 +111,7 @@ namespace wiInput #ifdef _WIN32 wiRawInput::GetMouseState(&mouse); // currently only the relative data can be used from this - wiRawInput::GetKeyboardState(&keyboard); // it contains pressed buttons as "keyboard/typewriter" like, so no continuous presses + wiRawInput::GetKeyboardState(&keyboard); // apparently checking the mouse here instead of Down() avoids missing the button presses (review!) mouse.left_button_press |= KEY_DOWN(VK_LBUTTON); @@ -838,7 +839,7 @@ namespace wiInput } } - const std::vector& GetTouches() + const wi::vector& GetTouches() { return touches; } diff --git a/WickedEngine/wiInput.h b/WickedEngine/wiInput.h index 831f0b046..42661f996 100644 --- a/WickedEngine/wiInput.h +++ b/WickedEngine/wiInput.h @@ -2,8 +2,7 @@ #include "CommonInclude.h" #include "wiPlatform.h" #include "wiColor.h" - -#include +#include "wiVector.h" namespace wiInput { @@ -80,7 +79,7 @@ namespace wiInput struct KeyboardState { - bool buttons[256] = {}; + bool buttons[256] = {}; // it contains pressed buttons as "keyboard/typewriter" like, so no continuous presses }; struct MouseState { @@ -113,6 +112,7 @@ namespace wiInput // call once per frame void Update(wiPlatform::window_type window); + const KeyboardState& GetKeyboardState(); const MouseState& GetMouseState(); // check if a button is down @@ -144,7 +144,7 @@ namespace wiInput // current position of touch XMFLOAT2 pos; }; - const std::vector& GetTouches(); + const wi::vector& GetTouches(); }; diff --git a/WickedEngine/wiJobSystem.cpp b/WickedEngine/wiJobSystem.cpp index 466cc9199..c59e0962d 100644 --- a/WickedEngine/wiJobSystem.cpp +++ b/WickedEngine/wiJobSystem.cpp @@ -28,6 +28,8 @@ namespace wiJobSystem struct WorkerState { std::atomic_bool alive{ true }; + std::condition_variable wakeCondition; + std::mutex wakeMutex; }; // This structure is responsible to stop worker thread loops. @@ -38,13 +40,11 @@ namespace wiJobSystem uint32_t numCores = 0; uint32_t numThreads = 0; std::shared_ptr worker_state = std::make_shared(); // kept alive by both threads and internal_state - std::condition_variable wakeCondition; - std::mutex wakeMutex; wiAllocator::ThreadSafeRingBuffer jobQueue; ~InternalState() { worker_state->alive.store(false); - wakeCondition.notify_all(); // wakes up sleeping worker threads + worker_state->wakeCondition.notify_all(); // wakes up sleeping worker threads } } static internal_state; @@ -100,8 +100,8 @@ namespace wiJobSystem if (!work()) { // no job, put thread to sleep - std::unique_lock lock(internal_state.wakeMutex); - internal_state.wakeCondition.wait(lock); + std::unique_lock lock(worker_state->wakeMutex); + worker_state->wakeCondition.wait(lock); } } @@ -171,10 +171,10 @@ namespace wiJobSystem job.sharedmemory_size = 0; // Try to push a new job until it is pushed successfully: - while (!internal_state.jobQueue.push_back(job)) { internal_state.wakeCondition.notify_all(); work(); } + while (!internal_state.jobQueue.push_back(job)) { internal_state.worker_state->wakeCondition.notify_all(); work(); } // Wake any one thread that might be sleeping: - internal_state.wakeCondition.notify_one(); + internal_state.worker_state->wakeCondition.notify_one(); } void Dispatch(context& ctx, uint32_t jobCount, uint32_t groupSize, const std::function& task, size_t sharedmemory_size) @@ -202,11 +202,11 @@ namespace wiJobSystem job.groupJobEnd = std::min(job.groupJobOffset + groupSize, jobCount); // Try to push a new job until it is pushed successfully: - while (!internal_state.jobQueue.push_back(job)) { internal_state.wakeCondition.notify_all(); work(); } + while (!internal_state.jobQueue.push_back(job)) { internal_state.worker_state->wakeCondition.notify_all(); work(); } } // Wake any threads that might be sleeping: - internal_state.wakeCondition.notify_all(); + internal_state.worker_state->wakeCondition.notify_all(); } uint32_t DispatchGroupCount(uint32_t jobCount, uint32_t groupSize) @@ -224,7 +224,7 @@ namespace wiJobSystem void Wait(const context& ctx) { // Wake any threads that might be sleeping: - internal_state.wakeCondition.notify_all(); + internal_state.worker_state->wakeCondition.notify_all(); // Waiting will also put the current thread to good use by working on an other job if it can: while (IsBusy(ctx)) { work(); } diff --git a/WickedEngine/wiLua.cpp b/WickedEngine/wiLua.cpp index 8a11a83e2..2e9450714 100644 --- a/WickedEngine/wiLua.cpp +++ b/WickedEngine/wiLua.cpp @@ -22,10 +22,9 @@ #include "wiNetwork_BindLua.h" #include "wiIntersect_BindLua.h" #include "wiTimer.h" +#include "wiVector.h" -#include #include -#include #define WILUA_ERROR_PREFIX "[Lua Error] " @@ -56,7 +55,7 @@ namespace wiLua std::string filename = SGetString(L, 1); filename = script_path + filename; script_path = wiHelper::GetDirectoryFromPath(filename); - std::vector filedata; + wi::vector filedata; if (wiHelper::FileRead(filename, filedata)) { std::string command = std::string(filedata.begin(), filedata.end()); @@ -72,9 +71,10 @@ namespace wiLua if (str == nullptr) return 0; - std::stringstream ss(""); - ss << WILUA_ERROR_PREFIX << str; - wiBackLog::post(ss.str().c_str()); + std::string ss; + ss += WILUA_ERROR_PREFIX; + ss += str; + wiBackLog::post(ss, wiBackLog::LogLevel::Error); lua_pop(L, 1); // remove error message } } @@ -154,16 +154,17 @@ namespace wiLua const char* str = lua_tostring(luainternal.m_luaState, -1); if (str == nullptr) return; - std::stringstream ss(""); - ss << WILUA_ERROR_PREFIX << str; - wiBackLog::post(ss.str().c_str()); + std::string ss; + ss += WILUA_ERROR_PREFIX; + ss += str; + wiBackLog::post(ss, wiBackLog::LogLevel::Error); lua_pop(luainternal.m_luaState, 1); // remove error message } } bool RunFile(const std::string& filename) { script_path = wiHelper::GetDirectoryFromPath(filename); - std::vector filedata; + wi::vector filedata; if (wiHelper::FileRead(filename, filedata)) { return RunText(std::string(filedata.begin(), filedata.end())); @@ -250,28 +251,28 @@ namespace wiLua SSetDouble(luainternal.m_luaState, dt); lua_call(luainternal.m_luaState, 1, 0); } + + inline void SignalHelper(lua_State* L, const char* str) + { + lua_getglobal(L, "signal"); + lua_pushstring(L, str); + lua_call(L, 1, 0); + } void FixedUpdate() { - Signal("wickedengine_fixed_update_tick"); + SignalHelper(luainternal.m_luaState, "wickedengine_fixed_update_tick"); } void Update() { - Signal("wickedengine_update_tick"); + SignalHelper(luainternal.m_luaState, "wickedengine_update_tick"); } void Render() { - Signal("wickedengine_render_tick"); - } - - inline void SignalHelper(lua_State* L, const std::string& name) - { - lua_getglobal(L, "signal"); - SSetString(L, name.c_str()); - lua_call(L, 1, 0); + SignalHelper(luainternal.m_luaState, "wickedengine_render_tick"); } void Signal(const std::string& name) { - SignalHelper(luainternal.m_luaState, name); + SignalHelper(luainternal.m_luaState, name.c_str()); } void KillProcesses() @@ -402,13 +403,14 @@ namespace wiLua lua_getinfo(L, "nSl", &ar); int line = ar.currentline; - std::stringstream ss(""); - ss << WILUA_ERROR_PREFIX << "Line " << line << ": "; + std::string ss; + ss += WILUA_ERROR_PREFIX; + ss += "Line " + std::to_string(line) + ": "; if (!error.empty()) { - ss << error; + ss += error; } - wiBackLog::post(ss.str().c_str()); + wiBackLog::post(ss); } void SAddMetatable(lua_State* L, const std::string& name) diff --git a/WickedEngine/wiNetwork_Linux.cpp b/WickedEngine/wiNetwork_Linux.cpp index f33b11909..dbe6313d8 100644 --- a/WickedEngine/wiNetwork_Linux.cpp +++ b/WickedEngine/wiNetwork_Linux.cpp @@ -5,6 +5,7 @@ #include "wiBackLog.h" #include "wiTimer.h" +#include #include #include @@ -53,10 +54,9 @@ namespace wiNetwork socketinternal->handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if(socketinternal->handle == -1){ - std::stringstream ss; - ss << "wiNetwork_Linux error in CreateSocket: Could not create socket"; - wiBackLog::post(ss.str().c_str()); + if(socketinternal->handle == -1) + { + wiBackLog::post("wiNetwork_Linux error in CreateSocket: Could not create socket"); return false; } @@ -80,9 +80,7 @@ namespace wiNetwork int result = sendto(socketinternal->handle, (const char*)data, (int)dataSize, 0, (const sockaddr*)&target, sizeof(target)); if (result < 0) { - std::stringstream ss; - ss << "wiNetwork_Linux error in Send: (Error Code: " + std::to_string(result) + ") " + strerror(result); - wiBackLog::post(ss.str().c_str()); + wiBackLog::post("wiNetwork_Linux error in Send: (Error Code: " + std::to_string(result) + ") " + std::string(strerror(result))); return false; } @@ -104,9 +102,7 @@ namespace wiNetwork int result = bind(socketinternal->handle, (struct sockaddr *)&target , sizeof(target)); if (result < 0) { - std::stringstream ss; - ss << "wiNetwork_Linux error in Send: (Error Code: " + std::to_string(result) + ") " + strerror(result); - wiBackLog::post(ss.str().c_str()); + wiBackLog::post("wiNetwork_Linux error in Send: (Error Code: " + std::to_string(result) + ") " + std::string(strerror(result))); return false; } @@ -130,9 +126,7 @@ namespace wiNetwork int result = select(0, &readfds, NULL, NULL, &timeout); if (result < 0) { - std::stringstream ss; - ss << "wiNetwork_Linux error in Send: (Error Code: " + std::to_string(result) + ") " + strerror(result); - wiBackLog::post(ss.str().c_str()); + wiBackLog::post("wiNetwork_Linux error in Send: (Error Code: " + std::to_string(result) + ") " + std::string(strerror(result))); assert(0); return false; } @@ -152,9 +146,7 @@ namespace wiNetwork int result = recvfrom(socketinternal->handle, (char*)data, (int)dataSize, 0, (sockaddr*)& sender, (socklen_t*)&targetsize); if (result < 0) { - std::stringstream ss; - ss << "wiNetwork_Linux error in Send: (Error Code: " + std::to_string(result) + ") " + strerror(result); - wiBackLog::post(ss.str().c_str()); + wiBackLog::post("wiNetwork_Linux error in Send: (Error Code: " + std::to_string(result) + ") " + std::string(strerror(result))); assert(0); return false; } diff --git a/WickedEngine/wiNetwork_Windows.cpp b/WickedEngine/wiNetwork_Windows.cpp index b4b66d810..4d476e245 100644 --- a/WickedEngine/wiNetwork_Windows.cpp +++ b/WickedEngine/wiNetwork_Windows.cpp @@ -5,7 +5,7 @@ #include "wiBackLog.h" #include "wiTimer.h" -#include +#include #include #pragma comment(lib,"ws2_32.lib") @@ -55,9 +55,7 @@ namespace wiNetwork if (result) { int error = WSAGetLastError(); - std::stringstream ss(""); - ss << "wiNetwork Initialization FAILED with error: " << error; - wiBackLog::post(ss.str().c_str()); + wiBackLog::post("wiNetwork Initialization FAILED with error: " + std::to_string(error)); assert(0); } @@ -74,9 +72,7 @@ namespace wiNetwork if (socketinternal->handle == INVALID_SOCKET) { int error = WSAGetLastError(); - std::stringstream ss; - ss << "wiNetwork error in CreateSocket: " << error; - wiBackLog::post(ss.str().c_str()); + wiBackLog::post("wiNetwork error in CreateSocket: " + std::to_string(error)); return false; } @@ -101,9 +97,7 @@ namespace wiNetwork if (result == SOCKET_ERROR) { int error = WSAGetLastError(); - std::stringstream ss; - ss << "wiNetwork error in Send: " << error; - wiBackLog::post(ss.str().c_str()); + wiBackLog::post("wiNetwork error in Send: " + std::to_string(error)); return false; } @@ -127,9 +121,7 @@ namespace wiNetwork if (result == SOCKET_ERROR) { int error = WSAGetLastError(); - std::stringstream ss; - ss << "wiNetwork error in ListenPort: " << error; - wiBackLog::post(ss.str().c_str()); + wiBackLog::post("wiNetwork error in ListenPort: " + std::to_string(error)); return false; } @@ -153,9 +145,8 @@ namespace wiNetwork int result = select(0, &readfds, NULL, NULL, &timeout); if (result < 0) { - std::stringstream ss; - ss << "wiNetwork error in CanReceive: " << WSAGetLastError(); - wiBackLog::post(ss.str().c_str()); + int error = WSAGetLastError(); + wiBackLog::post("wiNetwork error in CanReceive: " + std::to_string(error)); assert(0); return false; } @@ -177,9 +168,7 @@ namespace wiNetwork if (result == SOCKET_ERROR) { int error = WSAGetLastError(); - std::stringstream ss; - ss << "wiNetwork error in Receive: " << error; - wiBackLog::post(ss.str().c_str()); + wiBackLog::post("wiNetwork error in Receive: " + std::to_string(error)); return false; } diff --git a/WickedEngine/wiOcean.cpp b/WickedEngine/wiOcean.cpp index cce541327..850115c22 100644 --- a/WickedEngine/wiOcean.cpp +++ b/WickedEngine/wiOcean.cpp @@ -6,9 +6,9 @@ #include "wiBackLog.h" #include "wiEvent.h" #include "wiTimer.h" +#include "wiVector.h" #include -#include using namespace wiGraphics; using namespace wiScene; @@ -106,8 +106,8 @@ void wiOcean::Create(const OceanParameters& params) // Height map H(0) int height_map_size = (params.dmap_dim + 4) * (params.dmap_dim + 1); - std::vector h0_data(height_map_size); - std::vector omega_data(height_map_size); + wi::vector h0_data(height_map_size); + wi::vector omega_data(height_map_size); initHeightMap(params, h0_data.data(), omega_data.data()); int hmap_dim = params.dmap_dim; @@ -117,7 +117,7 @@ void wiOcean::Create(const OceanParameters& params) int output_size = hmap_dim * hmap_dim; // For filling the buffer with zeroes. - std::vector zero_data(3 * output_size * sizeof(float) * 2); + wi::vector zero_data(3 * output_size * sizeof(float) * 2); std::fill(zero_data.begin(), zero_data.end(), 0); GPUBufferDesc buf_desc; diff --git a/WickedEngine/wiOcean.h b/WickedEngine/wiOcean.h index 3bb4db194..be37ed3df 100644 --- a/WickedEngine/wiOcean.h +++ b/WickedEngine/wiOcean.h @@ -5,8 +5,6 @@ #include "wiScene_Decl.h" #include "wiMath.h" -#include - class wiOcean { public: diff --git a/WickedEngine/wiPlatform.h b/WickedEngine/wiPlatform.h index c9097b3d3..190da894f 100644 --- a/WickedEngine/wiPlatform.h +++ b/WickedEngine/wiPlatform.h @@ -1,11 +1,6 @@ #pragma once // This file includes platform, os specific libraries and supplies common platform specific resources -#include -#include -#include -#include - #ifdef _WIN32 #ifndef NOMINMAX @@ -87,8 +82,8 @@ namespace wiPlatform dest->dpi = (float)GetDpiForWindow(window); RECT rect; GetClientRect(window, &rect); - dest->width = uint32_t(rect.right - rect.left); - dest->height = uint32_t(rect.bottom - rect.top); + dest->width = int(rect.right - rect.left); + dest->height = int(rect.bottom - rect.top); #endif // WINDOWS_DESKTOP #ifdef PLATFORM_UWP diff --git a/WickedEngine/wiProfiler.cpp b/WickedEngine/wiProfiler.cpp index ada7c8237..17d9c89ec 100644 --- a/WickedEngine/wiProfiler.cpp +++ b/WickedEngine/wiProfiler.cpp @@ -5,9 +5,9 @@ #include "wiTimer.h" #include "wiTextureHelper.h" #include "wiHelper.h" +#include "wiUnorderedMap.h" #include -#include #include #include #include @@ -43,7 +43,7 @@ namespace wiProfiler bool IsCPURange() const { return cmd == INVALID_COMMANDLIST; } }; - std::unordered_map ranges; + wi::unordered_map ranges; void BeginFrame() { @@ -233,8 +233,8 @@ namespace wiProfiler uint32_t num_hits = 0; float total_time = 0; }; - std::unordered_map time_cache_cpu; - std::unordered_map time_cache_gpu; + wi::unordered_map time_cache_cpu; + wi::unordered_map time_cache_gpu; void DrawData(const wiCanvas& canvas, float x, float y, CommandList cmd) { if (!ENABLED || !initialized) diff --git a/WickedEngine/wiRawInput.cpp b/WickedEngine/wiRawInput.cpp index 3497f9b05..660f909ae 100644 --- a/WickedEngine/wiRawInput.cpp +++ b/WickedEngine/wiRawInput.cpp @@ -2,10 +2,9 @@ #include "wiPlatform.h" #if defined(_WIN32) && !defined(PLATFORM_UWP) +#include "wiVector.h" -#include #include - #include #pragma comment(lib,"Hid.lib") @@ -78,7 +77,7 @@ namespace wiRawInput }; AlignedLinearAllocator allocator; - std::vector input_messages; + wi::vector input_messages; wiInput::KeyboardState keyboard; wiInput::MouseState mouse; @@ -90,7 +89,7 @@ namespace wiRawInput std::wstring name; wiInput::ControllerState state; }; - std::vector controllers; + wi::vector controllers; void Initialize() { @@ -148,7 +147,11 @@ namespace wiRawInput const RAWKEYBOARD& rawkeyboard = raw.data.keyboard; if (rawkeyboard.VKey < arraysize(keyboard.buttons)) { - keyboard.buttons[rawkeyboard.VKey] = true; + if (rawkeyboard.Flags == RI_KEY_MAKE) + { + // key down + keyboard.buttons[rawkeyboard.VKey] = true; + } } else { diff --git a/WickedEngine/wiRectPacker.cpp b/WickedEngine/wiRectPacker.cpp index 5decc9b83..94c12879c 100644 --- a/WickedEngine/wiRectPacker.cpp +++ b/WickedEngine/wiRectPacker.cpp @@ -127,7 +127,7 @@ namespace wiRectPacker } }; - rect_wh _rect2D(rect_xywh* const * v, int n, int max_s, std::vector& succ, std::vector& unsucc) { + rect_wh _rect2D(rect_xywh* const * v, int n, int max_s, wi::vector& succ, wi::vector& unsucc) { node root; const int funcs = (sizeof(cmpf) / sizeof(bool(*)(rect_xywh*, rect_xywh*))); @@ -223,13 +223,13 @@ namespace wiRectPacker } - bool pack(rect_xywh* const * v, int n, int max_s, std::vector& bins) { + bool pack(rect_xywh* const * v, int n, int max_s, wi::vector& bins) { rect_wh _rect(max_s, max_s); for (int i = 0; i < n; ++i) if (!v[i]->fits(_rect)) return false; - std::vector vec[2], *p[2] = { vec, vec + 1 }; + wi::vector vec[2], *p[2] = { vec, vec + 1 }; vec[0].resize(n); vec[1].clear(); memcpy(&vec[0][0], v, sizeof(rect_xywh*)*n); diff --git a/WickedEngine/wiRectPacker.h b/WickedEngine/wiRectPacker.h index 670037807..28bd0a6c6 100644 --- a/WickedEngine/wiRectPacker.h +++ b/WickedEngine/wiRectPacker.h @@ -1,8 +1,6 @@ #pragma once #include "CommonInclude.h" -#include - // NOTE: // This is based on the rectpack2D library hosted here: https://github.com/TeamHypersomnia/rectpack2D @@ -13,7 +11,7 @@ members: int x, y, w, h; 2. bin - structure representing resultant bin object -3. bool pack(rect_xywh* const * v, int n, int max_side, std::std::vector& bins) - actual packing function +3. bool pack(rect_xywh* const * v, int n, int max_side, wi::vector& bins) - actual packing function Arguments: input/output: v - pointer to array of pointers to your rectangles (const here means that the pointers will point to the same rectangles after the call) input: n - rectangles count @@ -38,6 +36,8 @@ For description how to tune the algorithm and how it actually works see the .cpp */ +#include "wiVector.h" + namespace wiRectPacker { @@ -74,9 +74,9 @@ namespace wiRectPacker struct bin { rect_wh size; - std::vector rects; + wi::vector rects; }; - bool pack(rect_xywh* const * v, int n, int max_side, std::vector& bins); + bool pack(rect_xywh* const * v, int n, int max_side, wi::vector& bins); } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 27a9fad2b..6f60c0bdc 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -20,6 +20,7 @@ #include "wiSheenLUT.h" #include "wiShaderCompiler.h" #include "wiTimer.h" +#include "wiUnorderedMap.h" // leave it here for shader dump! #include "shaders/ShaderInterop_Postprocess.h" #include "shaders/ShaderInterop_Raytracing.h" @@ -62,7 +63,7 @@ inline LinearAllocator& GetRenderFrameAllocator(CommandList cmd) return renderFrameAllocators[cmd]; } -std::vector barrier_stack[COMMANDLIST_COUNT]; +wi::vector barrier_stack[COMMANDLIST_COUNT]; void barrier_stack_flush(CommandList cmd) { if (barrier_stack[cmd].empty()) @@ -125,21 +126,21 @@ Texture shadowMapArray_2D; Texture shadowMapArray_Cube; Texture shadowMapArray_Transparent_2D; Texture shadowMapArray_Transparent_Cube; -std::vector renderpasses_shadow2D; -std::vector renderpasses_shadowCube; +wi::vector renderpasses_shadow2D; +wi::vector renderpasses_shadowCube; -std::vector> renderableBoxes; -std::vector> renderableSpheres; -std::vector> renderableCapsules; -std::vector renderableLines; -std::vector renderableLines2D; -std::vector renderablePoints; -std::vector renderableTriangles_solid; -std::vector renderableTriangles_wireframe; -std::vector paintrads; +wi::vector> renderableBoxes; +wi::vector> renderableSpheres; +wi::vector> renderableCapsules; +wi::vector renderableLines; +wi::vector renderableLines2D; +wi::vector renderablePoints; +wi::vector renderableTriangles_solid; +wi::vector renderableTriangles_wireframe; +wi::vector paintrads; wiSpinLock deferredMIPGenLock; -std::vector, bool>> deferredMIPGens; +wi::vector, bool>> deferredMIPGens; bool volumetric_clouds_precomputed = false; @@ -276,14 +277,14 @@ PipelineState PSO_object_terrain[RENDERPASS_COUNT]; PipelineState PSO_object_wire; PipelineState PSO_object_wire_tessellation; -std::vector customShaders; +wi::vector customShaders; int RegisterCustomShader(const CustomShader& customShader) { int result = (int)customShaders.size(); customShaders.push_back(customShader); return result; } -const std::vector& GetCustomShaders() +const wi::vector& GetCustomShaders() { return customShaders; } @@ -627,7 +628,7 @@ bool LoadShader(ShaderStage stage, Shader& shader, const std::string& filename, } else { - wiBackLog::post(("shader dump doesn't contain shader: " + shaderbinaryfilename).c_str()); + wiBackLog::post("shader dump doesn't contain shader: " + shaderbinaryfilename); } #endif // SHADERDUMP_ENABLED @@ -655,18 +656,18 @@ bool LoadShader(ShaderStage stage, Shader& shader, const std::string& filename, if (!output.error_message.empty()) { - wiBackLog::post(output.error_message.c_str()); + wiBackLog::post(output.error_message); } - wiBackLog::post(("shader compiled: " + shaderbinaryfilename).c_str()); + wiBackLog::post("shader compiled: " + shaderbinaryfilename); return device->CreateShader(stage, output.shaderdata, output.shadersize, &shader); } else { - wiBackLog::post(("shader compile FAILED: " + shaderbinaryfilename + "\n" + output.error_message).c_str()); + wiBackLog::post("shader compile FAILED: " + shaderbinaryfilename + "\n" + output.error_message); } } - std::vector buffer; + wi::vector buffer; if (wiHelper::FileRead(shaderbinaryfilename, buffer)) { return device->CreateShader(stage, buffer.data(), buffer.size(), &shader); @@ -5451,7 +5452,7 @@ void DrawDebugWorld( XMFLOAT4 position; XMFLOAT4 color; }; - std::vector vertices; + wi::vector vertices; const int segmentcount = 36; Vertex vert; @@ -5485,7 +5486,7 @@ void DrawDebugWorld( bd.bind_flags = BindFlag::VERTEX_BUFFER; device->CreateBuffer(&bd, vertices.data(), &wiresphereVB); - std::vector indices; + wi::vector indices; for (int i = 0; i < segmentcount; ++i) { indices.push_back(uint16_t(i)); diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 48eb41e76..c6d6204dd 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -8,6 +8,7 @@ #include "wiCanvas.h" #include "wiMath.h" #include "shaders/ShaderInterop_Renderer.h" +#include "wiVector.h" #include #include @@ -97,11 +98,11 @@ namespace wiRenderer // wiRenderer::UpdateVisibility() fills these: Frustum frustum; - std::vector visibleObjects; - std::vector visibleDecals; - std::vector visibleEnvProbes; - std::vector visibleEmitters; - std::vector visibleHairs; + wi::vector visibleObjects; + wi::vector visibleDecals; + wi::vector visibleEnvProbes; + wi::vector visibleEmitters; + wi::vector visibleHairs; struct VisibleLight { @@ -111,7 +112,7 @@ namespace wiRenderer return uint32_t(index | (uint32_t(distance) << 16)) < uint32_t(other.index | (uint32_t(other.distance) << 16)); } }; - std::vector visibleLights; + wi::vector visibleLights; std::atomic object_counter; std::atomic light_counter; @@ -840,7 +841,7 @@ namespace wiRenderer // Registers a custom shader that can be set to materials. // Returns the ID of the custom shader that can be used with MaterialComponent::SetCustomShaderID() int RegisterCustomShader(const CustomShader& customShader); - const std::vector& GetCustomShaders(); + const wi::vector& GetCustomShaders(); }; diff --git a/WickedEngine/wiResourceManager.cpp b/WickedEngine/wiResourceManager.cpp index c0c159e9a..66892d49b 100644 --- a/WickedEngine/wiResourceManager.cpp +++ b/WickedEngine/wiResourceManager.cpp @@ -2,6 +2,7 @@ #include "wiRenderer.h" #include "wiHelper.h" #include "wiTextureHelper.h" +#include "wiUnorderedMap.h" #include "Utility/stb_image.h" #include "Utility/tinyddsloader.h" @@ -9,13 +10,14 @@ extern basist::etc1_global_selector_codebook g_basis_global_codebook; #include +#include using namespace wiGraphics; namespace wiResourceManager { std::mutex locker; - std::unordered_map> resources; + wi::unordered_map> resources; MODE mode = MODE_DISCARD_FILEDATA_AFTER_LOAD; void SetMode(MODE param) @@ -27,7 +29,7 @@ namespace wiResourceManager return mode; } - static const std::unordered_map types = { + static const wi::unordered_map types = { std::make_pair("BASIS", wiResource::IMAGE), std::make_pair("KTX2", wiResource::IMAGE), std::make_pair("JPG", wiResource::IMAGE), @@ -39,9 +41,9 @@ namespace wiResourceManager std::make_pair("WAV", wiResource::SOUND), std::make_pair("OGG", wiResource::SOUND), }; - std::vector GetSupportedImageExtensions() + wi::vector GetSupportedImageExtensions() { - std::vector ret; + wi::vector ret; for (auto& x : types) { if (x.second == wiResource::IMAGE) @@ -51,9 +53,9 @@ namespace wiResourceManager } return ret; } - std::vector GetSupportedSoundExtensions() + wi::vector GetSupportedSoundExtensions() { - std::vector ret; + wi::vector ret; for (auto& x : types) { if (x.second == wiResource::SOUND) @@ -175,9 +177,9 @@ namespace wiResourceManager } } } - std::vector transcoded_data(transcoded_data_size); + wi::vector transcoded_data(transcoded_data_size); - std::vector InitData; + wi::vector InitData; size_t transcoded_data_offset = 0; for (uint32_t layer = 0; layer < std::max(1u, transcoder.get_layers()); ++layer) { @@ -260,9 +262,9 @@ namespace wiResourceManager transcoded_data_size += level_info.m_total_blocks * bytes_per_block; } } - std::vector transcoded_data(transcoded_data_size); + wi::vector transcoded_data(transcoded_data_size); - std::vector InitData; + wi::vector InitData; size_t transcoded_data_offset = 0; for (uint32_t mip = 0; mip < desc.mip_levels; ++mip) { @@ -391,7 +393,7 @@ namespace wiResourceManager break; } - std::vector InitData; + wi::vector InitData; for (uint32_t arrayIndex = 0; arrayIndex < desc.array_size; ++arrayIndex) { for (uint32_t mip = 0; mip < desc.mip_levels; ++mip) @@ -502,7 +504,7 @@ namespace wiResourceManager desc.layout = ResourceState::SHADER_RESOURCE; uint32_t mipwidth = width; - std::vector InitData(desc.mip_levels); + wi::vector InitData(desc.mip_levels); for (uint32_t mip = 0; mip < desc.mip_levels; ++mip) { InitData[mip].data_ptr = rgb; // attention! we don't fill the mips here correctly, just always point to the mip0 data by default. Mip levels will be created using compute shader when needed! @@ -596,9 +598,9 @@ namespace wiResourceManager { std::string name; uint32_t flags = 0; - std::vector filedata; + wi::vector filedata; }; - std::vector temp_resources; + wi::vector temp_resources; temp_resources.resize(serializable_count); wiJobSystem::context ctx; diff --git a/WickedEngine/wiResourceManager.h b/WickedEngine/wiResourceManager.h index 910786f22..24a1b5481 100644 --- a/WickedEngine/wiResourceManager.h +++ b/WickedEngine/wiResourceManager.h @@ -4,10 +4,9 @@ #include "wiAudio.h" #include "wiArchive.h" #include "wiJobSystem.h" +#include "wiVector.h" #include -#include -#include struct wiResource { @@ -22,7 +21,7 @@ struct wiResource } type = EMPTY; uint32_t flags = 0; - std::vector filedata; + wi::vector filedata; }; namespace wiResourceManager @@ -35,8 +34,8 @@ namespace wiResourceManager }; void SetMode(MODE param); MODE GetMode(); - std::vector GetSupportedImageExtensions(); - std::vector GetSupportedSoundExtensions(); + wi::vector GetSupportedImageExtensions(); + wi::vector GetSupportedSoundExtensions(); // Order of these must not change as the flags can be serialized! enum FLAGS @@ -64,7 +63,7 @@ namespace wiResourceManager struct ResourceSerializer { - std::vector> resources; + wi::vector> resources; }; // Serializes all resources that are compatible // Compatible resources are those whose file data is kept around using the IMPORT_RETAIN_FILEDATA flag when loading. diff --git a/WickedEngine/wiSDLInput.cpp b/WickedEngine/wiSDLInput.cpp index 3e9b7b8ae..d22df7794 100644 --- a/WickedEngine/wiSDLInput.cpp +++ b/WickedEngine/wiSDLInput.cpp @@ -5,29 +5,20 @@ #include "CommonInclude.h" #include "wiBackLog.h" #include "wiInput.h" +#include "wiVector.h" + #include #include #include #include #include #include -#include namespace wiSDLInput { wiInput::KeyboardState keyboard; wiInput::MouseState mouse; - //TODO controllers - //struct Internal_ControllerState - //{ - // HANDLE handle = NULL; - // bool is_xinput = false; - // std::wstring name; - // wiInput::ControllerState state; - //}; - //std::vector controllers; - struct Internal_ControllerState { Sint32 portID; @@ -35,7 +26,7 @@ namespace wiSDLInput SDL_GameController* controller; wiInput::ControllerState state; }; - std::vector controllers; + wi::vector controllers; int numSticks = 0; int to_wiInput(const SDL_Scancode &key); @@ -93,7 +84,7 @@ namespace wiSDLInput RemoveController(); } - std::vector events(1000); + wi::vector events(1000); // This removes the only the inputs events from the event queue, leaving audio and window events for other // section of the code @@ -325,4 +316,4 @@ namespace wiSDLInput bool GetControllerState(wiInput::ControllerState* state, int index) { return false; } void SetControllerFeedback(const wiInput::ControllerFeedback& data, int index) {} } -#endif // _WIN32 \ No newline at end of file +#endif // _WIN32 diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index f5032ef3b..ebc07be5f 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -10,11 +10,11 @@ #include "wiRenderer.h" #include "wiBackLog.h" #include "wiTimer.h" +#include "wiUnorderedMap.h" #include "shaders/ShaderInterop_SurfelGI.h" #include -#include using namespace wiECS; using namespace wiGraphics; @@ -423,7 +423,7 @@ namespace wiScene bd.format = Format::R16_UINT; bd.size = uint32_t(sizeof(uint16_t) * indices.size()); - std::vector gpuIndexData(indices.size()); + wi::vector gpuIndexData(indices.size()); std::copy(indices.begin(), indices.end(), gpuIndexData.begin()); device->CreateBuffer(&bd, gpuIndexData.data(), &indexBuffer); @@ -443,7 +443,7 @@ namespace wiScene dirty_morph = true; } - std::vector vertices(vertex_positions.size()); + wi::vector vertices(vertex_positions.size()); for (size_t i = 0; i < vertices.size(); ++i) { const XMFLOAT3& pos = vertex_positions[i]; @@ -545,7 +545,7 @@ namespace wiScene } - std::vector vertices(vertex_tangents.size()); + wi::vector vertices(vertex_tangents.size()); for (size_t i = 0; i < vertex_tangents.size(); ++i) { vertices[i].FromFULL(vertex_tangents[i]); @@ -567,7 +567,7 @@ namespace wiScene // skinning buffers: if (!vertex_boneindices.empty()) { - std::vector vertices(vertex_boneindices.size()); + wi::vector vertices(vertex_boneindices.size()); for (size_t i = 0; i < vertices.size(); ++i) { XMFLOAT4& wei = vertex_boneweights[i]; @@ -613,7 +613,7 @@ namespace wiScene // vertexBuffer - UV SET 0 if(!vertex_uvset_0.empty()) { - std::vector vertices(vertex_uvset_0.size()); + wi::vector vertices(vertex_uvset_0.size()); for (size_t i = 0; i < vertices.size(); ++i) { vertices[i].FromFULL(vertex_uvset_0[i]); @@ -632,7 +632,7 @@ namespace wiScene // vertexBuffer - UV SET 1 if (!vertex_uvset_1.empty()) { - std::vector vertices(vertex_uvset_1.size()); + wi::vector vertices(vertex_uvset_1.size()); for (size_t i = 0; i < vertices.size(); ++i) { vertices[i].FromFULL(vertex_uvset_1[i]); @@ -664,7 +664,7 @@ namespace wiScene // vertexBuffer - ATLAS if (!vertex_atlas.empty()) { - std::vector vertices(vertex_atlas.size()); + wi::vector vertices(vertex_atlas.size()); for (size_t i = 0; i < vertices.size(); ++i) { vertices[i].FromFULL(vertex_atlas[i]); @@ -782,15 +782,15 @@ namespace wiScene // Right now they are always computed even before smooth setting - std::vector newIndexBuffer; - std::vector newPositionsBuffer; - std::vector newNormalsBuffer; - std::vector newUV0Buffer; - std::vector newUV1Buffer; - std::vector newAtlasBuffer; - std::vector newBoneIndicesBuffer; - std::vector newBoneWeightsBuffer; - std::vector newColorsBuffer; + wi::vector newIndexBuffer; + wi::vector newPositionsBuffer; + wi::vector newNormalsBuffer; + wi::vector newUV0Buffer; + wi::vector newUV1Buffer; + wi::vector newAtlasBuffer; + wi::vector newBoneIndicesBuffer; + wi::vector newBoneWeightsBuffer; + wi::vector newColorsBuffer; for (size_t face = 0; face < indices.size() / 3; face++) { @@ -1177,7 +1177,7 @@ namespace wiScene #ifdef OPEN_IMAGE_DENOISE if (success) { - std::vector texturedata_dst(lightmapTextureData.size()); + wi::vector texturedata_dst(lightmapTextureData.size()); size_t width = (size_t)lightmapWidth; size_t height = (size_t)lightmapHeight; @@ -1207,7 +1207,7 @@ namespace wiScene auto error = device.getError(errorMessage); if (error != oidn::Error::None && error != oidn::Error::Cancelled) { - wiBackLog::post((std::string("[OpenImageDenoise error] ") + errorMessage).c_str()); + wiBackLog::post(std::string("[OpenImageDenoise error] ") + errorMessage); } } @@ -1237,7 +1237,7 @@ namespace wiScene static_assert(lightmap_blocksize == 4u); const uint32_t bc6_width = lightmapWidth / lightmap_blocksize; const uint32_t bc6_height = lightmapHeight / lightmap_blocksize; - std::vector bc6_data; + wi::vector bc6_data; bc6_data.resize(sizeof(XMFLOAT4) * bc6_width * bc6_height); const XMFLOAT4* raw_data = (const XMFLOAT4*)lightmapTextureData.data(); @@ -1278,7 +1278,7 @@ namespace wiScene // Simple compression to R11G11B10_FLOAT format: using namespace PackedVector; - std::vector packed_data; + wi::vector packed_data; packed_data.resize(sizeof(XMFLOAT3PK) * lightmapWidth * lightmapHeight); XMFLOAT3PK* packed_ptr = (XMFLOAT3PK*)packed_data.data(); XMFLOAT4* raw_ptr = (XMFLOAT4*)lightmapTextureData.data(); @@ -1334,7 +1334,7 @@ namespace wiScene if(physicsToGraphicsVertexMapping.empty()) { // Create a mapping that maps unique vertex positions to all vertex indices that share that. Unique vertex positions will make up the physics mesh: - std::unordered_map uniquePositions; + wi::unordered_map uniquePositions; graphicsToPhysicsVertexMapping.resize(mesh.vertex_positions.size()); physicsToGraphicsVertexMapping.clear(); weights.clear(); @@ -1713,7 +1713,7 @@ namespace wiScene device->CreateBuffer(&desc, nullptr, &surfelAliveBuffer[1]); device->SetName(&surfelAliveBuffer[1], "surfelAliveBuffer[1]"); - std::vector dead_indices(SURFEL_CAPACITY); + wi::vector dead_indices(SURFEL_CAPACITY); for (uint32_t i = 0; i < dead_indices.size(); ++i) { dead_indices[i] = uint32_t(dead_indices.size() - 1 - i); diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 2f5b1276e..409096423 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -13,12 +13,11 @@ #include "wiOcean.h" #include "wiSprite.h" #include "wiMath.h" - #include "wiECS.h" #include "wiScene_Decl.h" +#include "wiVector.h" #include -#include #include #include @@ -328,17 +327,17 @@ namespace wiScene }; uint32_t _flags = RENDERABLE; - std::vector vertex_positions; - std::vector vertex_normals; - std::vector vertex_tangents; - std::vector vertex_uvset_0; - std::vector vertex_uvset_1; - std::vector vertex_boneindices; - std::vector vertex_boneweights; - std::vector vertex_atlas; - std::vector vertex_colors; - std::vector vertex_windweights; - std::vector indices; + wi::vector vertex_positions; + wi::vector vertex_normals; + wi::vector vertex_tangents; + wi::vector vertex_uvset_0; + wi::vector vertex_uvset_1; + wi::vector vertex_boneindices; + wi::vector vertex_boneweights; + wi::vector vertex_atlas; + wi::vector vertex_colors; + wi::vector vertex_windweights; + wi::vector indices; struct MeshSubset { @@ -349,7 +348,7 @@ namespace wiScene // Non-serialized attributes: uint32_t materialIndex = 0; }; - std::vector subsets; + wi::vector subsets; float tessellationFactor = 0.0f; wiECS::Entity armatureID = wiECS::INVALID_ENTITY; @@ -366,11 +365,11 @@ namespace wiScene // Morph Targets struct MeshMorphTarget { - std::vector vertex_positions; - std::vector vertex_normals; + wi::vector vertex_positions; + wi::vector vertex_normals; float_t weight; }; - std::vector targets; + wi::vector targets; // Non-serialized attributes: AABB aabb; @@ -385,7 +384,7 @@ namespace wiScene wiGraphics::GPUBuffer vertexBuffer_PRE; wiGraphics::GPUBuffer streamoutBuffer_POS; wiGraphics::GPUBuffer streamoutBuffer_TAN; - std::vector vertex_subsets; + wi::vector vertex_subsets; wiGraphics::GPUBuffer subsetBuffer; wiGraphics::RaytracingAccelerationStructure BLAS; @@ -576,7 +575,7 @@ namespace wiScene }; // Non serialized attributes: - std::vector vertex_positions_morphed; + wi::vector vertex_positions_morphed; }; @@ -595,7 +594,7 @@ namespace wiScene AABB aabb; XMFLOAT4 color; float fadeThresholdRadius; - std::vector instances; + wi::vector instances; mutable bool render_dirty = false; inline void SetDirty(bool value = true) { if (value) { _flags |= DIRTY; } else { _flags &= ~DIRTY; } } @@ -626,7 +625,7 @@ namespace wiScene uint32_t lightmapWidth = 0; uint32_t lightmapHeight = 0; - std::vector lightmapTextureData; + wi::vector lightmapTextureData; uint8_t userStencilRef = 0; @@ -756,16 +755,16 @@ namespace wiScene float mass = 1.0f; float friction = 0.5f; float restitution = 0.0f; - std::vector physicsToGraphicsVertexMapping; // maps graphics vertex index to physics vertex index of the same position - std::vector graphicsToPhysicsVertexMapping; // maps a physics vertex index to first graphics vertex index of the same position - std::vector weights; // weight per physics vertex controlling the mass. (0: disable weight (no physics, only animation), 1: default weight) + wi::vector physicsToGraphicsVertexMapping; // maps graphics vertex index to physics vertex index of the same position + wi::vector graphicsToPhysicsVertexMapping; // maps a physics vertex index to first graphics vertex index of the same position + wi::vector weights; // weight per physics vertex controlling the mass. (0: disable weight (no physics, only animation), 1: default weight) // Non-serialized attributes: void* physicsobject = nullptr; XMFLOAT4X4 worldMatrix = IDENTITYMATRIX; - std::vector vertex_positions_simulation; // graphics vertices after simulation (world space) - std::vectorvertex_tangents_tmp; - std::vector vertex_tangents_simulation; + wi::vector vertex_positions_simulation; // graphics vertices after simulation (world space) + wi::vectorvertex_tangents_tmp; + wi::vector vertex_tangents_simulation; AABB aabb; inline void SetDisableDeactivation(bool value) { if (value) { _flags |= DISABLE_DEACTIVATION; } else { _flags &= ~DISABLE_DEACTIVATION; } } @@ -786,13 +785,13 @@ namespace wiScene }; uint32_t _flags = EMPTY; - std::vector boneCollection; - std::vector inverseBindMatrices; + wi::vector boneCollection; + wi::vector inverseBindMatrices; // Non-serialized attributes: AABB aabb; - std::vector boneData; + wi::vector boneData; wiGraphics::GPUBuffer boneBuffer; void CreateRenderData(); @@ -830,7 +829,7 @@ namespace wiScene float range_local = 10.0f; float fov = XM_PIDIV4; - std::vector lensFlareNames; + wi::vector lensFlareNames; // Non-serialized attributes: XMFLOAT3 position; @@ -842,7 +841,7 @@ namespace wiScene XMFLOAT3 right; mutable int occlusionquery = -1; - std::vector> lensFlareRimTextures; + wi::vector> lensFlareRimTextures; inline void SetCastShadow(bool value) { if (value) { _flags |= CAST_SHADOW; } else { _flags &= ~CAST_SHADOW; } } inline void SetVolumetricsEnabled(bool value) { if (value) { _flags |= VOLUMETRICS; } else { _flags &= ~VOLUMETRICS; } } @@ -1010,8 +1009,8 @@ namespace wiScene }; uint32_t _flags = EMPTY; - std::vector keyframe_times; - std::vector keyframe_data; + wi::vector keyframe_times; + wi::vector keyframe_data; void Serialize(wiArchive& archive, wiECS::EntitySerializer& seri); }; @@ -1073,11 +1072,11 @@ namespace wiScene // The data is now not part of the sampler, so it can be shared. This is kept only for backwards compatibility with previous versions. AnimationDataComponent backwards_compatibility_data; }; - std::vector channels; - std::vector samplers; + wi::vector channels; + wi::vector samplers; // Non-serialzied attributes: - std::vector morph_weights_temp; + wi::vector morph_weights_temp; inline bool IsPlaying() const { return _flags & PLAYING; } inline bool IsLooped() const { return _flags & LOOPED; } @@ -1177,8 +1176,6 @@ namespace wiScene inline void SetLooped(bool value = true) { if (value) { _flags |= LOOPED; } else { _flags &= ~LOOPED; } } inline void SetDisable3D(bool value = true) { if (value) { _flags |= DISABLE_3D; } else { _flags &= ~DISABLE_3D; } } - void LoadAssets(const std::string& content_dir = ""); - void Serialize(wiArchive& archive, wiECS::EntitySerializer& seri); }; @@ -1277,7 +1274,7 @@ namespace wiScene wiSpinLock locker; AABB bounds; - std::vector parallel_bounds; + wi::vector parallel_bounds; WeatherComponent weather; wiGraphics::RaytracingAccelerationStructure TLAS; wiGraphics::GPUBuffer TLAS_instancesUpload[wiGraphics::GraphicsDevice::GetBufferCount()]; @@ -1294,6 +1291,7 @@ namespace wiScene // contains in order: // 1) objects // 2) hair particles + // 3) emitted particles wiGraphics::GPUBuffer instanceUploadBuffer[wiGraphics::GraphicsDevice::GetBufferCount()]; ShaderMeshInstance* instanceArrayMapped = nullptr; size_t instanceArraySize = 0; @@ -1303,6 +1301,7 @@ namespace wiScene // contains in order: // 1) meshes // 2) hair particles + // 3) emitted particles wiGraphics::GPUBuffer meshUploadBuffer[wiGraphics::GraphicsDevice::GetBufferCount()]; ShaderMesh* meshArrayMapped = nullptr; size_t meshArraySize = 0; @@ -1338,14 +1337,14 @@ namespace wiScene static constexpr uint32_t envmapMIPs = 8; wiGraphics::Texture envrenderingDepthBuffer; wiGraphics::Texture envmapArray; - std::vector renderpasses_envmap; + wi::vector renderpasses_envmap; // Impostor texture array state: static constexpr uint32_t maxImpostorCount = 8; static constexpr uint32_t impostorTextureDim = 128; wiGraphics::Texture impostorDepthStencil; wiGraphics::Texture impostorArray; - std::vector renderpasses_impostor; + wi::vector renderpasses_impostor; mutable std::atomic_bool lightmap_refresh_needed{ false }; @@ -1354,7 +1353,7 @@ namespace wiScene void OceanRegenerate() { ocean.Create(weather.oceanParameters); } // Simple water ripple sprites: - mutable std::vector waterRipples; + mutable wi::vector waterRipples; void PutWaterRipple(const std::string& image, const XMFLOAT3& pos); // Update all components by a given timestep (in seconds): diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp index ff3a9856b..ca42a31b8 100644 --- a/WickedEngine/wiScene_Serializers.cpp +++ b/WickedEngine/wiScene_Serializers.cpp @@ -5,9 +5,7 @@ #include "wiHelper.h" #include "wiBackLog.h" #include "wiTimer.h" - -#include -#include +#include "wiVector.h" using namespace wiECS; @@ -611,7 +609,7 @@ namespace wiScene if (archive.GetVersion() >= 29 && archive.GetVersion() < 34) { - std::vector temp; + wi::vector temp; archive >> temp; } @@ -2021,7 +2019,7 @@ namespace wiScene if (archive.GetVersion() >= 72) { // Recursive serialization for all children: - std::vector children; + wi::vector children; for (size_t i = 0; i < hierarchy.GetCount(); ++i) { const HierarchyComponent& hier = hierarchy[i]; diff --git a/WickedEngine/wiShaderCompiler.cpp b/WickedEngine/wiShaderCompiler.cpp index 6a3d8dc57..ce28bbfb1 100644 --- a/WickedEngine/wiShaderCompiler.cpp +++ b/WickedEngine/wiShaderCompiler.cpp @@ -3,12 +3,11 @@ #include "wiPlatform.h" #include "wiHelper.h" #include "wiArchive.h" +#include "wiUnorderedSet.h" #include -#include #include - #ifdef PLATFORM_WINDOWS_DESKTOP #define SHADERCOMPILER_ENABLED #define SHADERCOMPILER_ENABLED_DXCOMPILER @@ -48,7 +47,7 @@ namespace wiShaderCompiler return; } - std::vector shadersourcedata; + wi::vector shadersourcedata; if (!wiHelper::FileRead(input.shadersourcefilename, shadersourcedata)) { return; @@ -56,7 +55,7 @@ namespace wiShaderCompiler // https://github.com/microsoft/DirectXShaderCompiler/wiki/Using-dxc.exe-and-dxcompiler.dll#dxcompiler-dll-interface - std::vector args = { + wi::vector args = { L"-res-may-alias", L"-flegacy-macro-expansion", //L"-no-legacy-cbuf-layout", @@ -318,7 +317,7 @@ namespace wiShaderCompiler return; } - std::vector wstrings; + wi::vector wstrings; wstrings.reserve(input.defines.size() + input.include_directories.size()); for (auto& x : input.defines) @@ -464,7 +463,7 @@ namespace wiShaderCompiler return; } - std::vector shadersourcedata; + wi::vector shadersourcedata; if (!wiHelper::FileRead(input.shadersourcefilename, shadersourcedata)) { return; @@ -509,7 +508,7 @@ namespace wiShaderCompiler { const CompilerInput* input = nullptr; CompilerOutput* output = nullptr; - std::vector> filedatas; + wi::vector> filedatas; HRESULT Open(D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID* ppData, UINT* pBytes) override { @@ -518,7 +517,7 @@ namespace wiShaderCompiler std::string filename = x + pFileName; if (!wiHelper::FileExists(filename)) continue; - std::vector& filedata = filedatas.emplace_back(); + wi::vector& filedata = filedatas.emplace_back(); if (wiHelper::FileRead(filename, filedata)) { output->dependencies.push_back(filename); @@ -672,7 +671,7 @@ namespace wiShaderCompiler if (dependencyLibrary.IsOpen()) { std::string rootdir = dependencyLibrary.GetSourceDirectory(); - std::vector dependencies = output.dependencies; + wi::vector dependencies = output.dependencies; for (auto& x : dependencies) { wiHelper::MakePathRelative(rootdir, x); @@ -709,7 +708,7 @@ namespace wiShaderCompiler if (dependencyLibrary.IsOpen()) { std::string rootdir = dependencyLibrary.GetSourceDirectory(); - std::vector dependencies; + wi::vector dependencies; dependencyLibrary >> dependencies; for (auto& x : dependencies) @@ -733,15 +732,19 @@ namespace wiShaderCompiler } std::mutex locker; - std::unordered_set registered_shaders; + wi::unordered_set registered_shaders; void RegisterShader(const std::string& shaderfilename) { #ifdef SHADERCOMPILER_ENABLED - locker.lock(); + std::scoped_lock lock(locker); registered_shaders.insert(shaderfilename); - locker.unlock(); #endif // SHADERCOMPILER_ENABLED } + size_t GetRegisteredShaderCount() + { + std::scoped_lock lock(locker); + return registered_shaders.size(); + } bool CheckRegisteredShadersOutdated() { #ifdef SHADERCOMPILER_ENABLED diff --git a/WickedEngine/wiShaderCompiler.h b/WickedEngine/wiShaderCompiler.h index 77ad10013..0728a15e3 100644 --- a/WickedEngine/wiShaderCompiler.h +++ b/WickedEngine/wiShaderCompiler.h @@ -1,7 +1,7 @@ #pragma once #include "wiGraphics.h" +#include "wiVector.h" -#include #include namespace wiShaderCompiler @@ -23,8 +23,8 @@ namespace wiShaderCompiler wiGraphics::ShaderModel minshadermodel = wiGraphics::ShaderModel::SM_5_0; std::string shadersourcefilename; std::string entrypoint = "main"; - std::vector include_directories; - std::vector defines; + wi::vector include_directories; + wi::vector defines; }; struct CompilerOutput { @@ -33,9 +33,9 @@ namespace wiShaderCompiler const uint8_t* shaderdata = nullptr; size_t shadersize = 0; - std::vector shaderhash; + wi::vector shaderhash; std::string error_message; - std::vector dependencies; + wi::vector dependencies; }; void Compile(const CompilerInput& input, CompilerOutput& output); @@ -43,5 +43,6 @@ namespace wiShaderCompiler bool IsShaderOutdated(const std::string& shaderfilename); void RegisterShader(const std::string& shaderfilename); + size_t GetRegisteredShaderCount(); bool CheckRegisteredShadersOutdated(); } diff --git a/WickedEngine/wiSpriteFont.cpp b/WickedEngine/wiSpriteFont.cpp index d998de6a2..6f37dae8e 100644 --- a/WickedEngine/wiSpriteFont.cpp +++ b/WickedEngine/wiSpriteFont.cpp @@ -34,10 +34,18 @@ void wiSpriteFont::SetText(const std::string& value) { wiHelper::StringConvert(value, text); } +void wiSpriteFont::SetText(std::string&& value) +{ + wiHelper::StringConvert(value, text); +} void wiSpriteFont::SetText(const std::wstring& value) { text = value; } +void wiSpriteFont::SetText(std::wstring&& value) +{ + text = value; +} std::string wiSpriteFont::GetTextA() const { diff --git a/WickedEngine/wiSpriteFont.h b/WickedEngine/wiSpriteFont.h index 2c2a4dc0b..2aace38bb 100644 --- a/WickedEngine/wiSpriteFont.h +++ b/WickedEngine/wiSpriteFont.h @@ -36,7 +36,9 @@ public: float textHeight() const; void SetText(const std::string& value); + void SetText(std::string&& value); void SetText(const std::wstring& value); + void SetText(std::wstring&& value); std::string GetTextA() const; const std::wstring& GetText() const; diff --git a/WickedEngine/wiStartupArguments.cpp b/WickedEngine/wiStartupArguments.cpp index e7a3183ed..ca02bc1e8 100644 --- a/WickedEngine/wiStartupArguments.cpp +++ b/WickedEngine/wiStartupArguments.cpp @@ -1,14 +1,13 @@ #include "wiStartupArguments.h" #include "wiHelper.h" +#include "wiUnorderedSet.h" -#include #include #include -#include namespace wiStartupArguments { - std::set params; + wi::unordered_set params; void Parse(const wchar_t* args) { @@ -28,10 +27,10 @@ namespace wiStartupArguments void Parse(int argc, char *argv[]) { - for (int i=1; i +#include "wiUnorderedMap.h" using namespace wiGraphics; @@ -26,7 +25,7 @@ namespace wiTextureHelper HELPERTEXTURE_COUNT }; wiGraphics::Texture helperTextures[HELPERTEXTURE_COUNT]; - std::unordered_map colorTextures; + wi::unordered_map colorTextures; wiSpinLock colorlock; void Initialize() diff --git a/WickedEngine/wiTimer.h b/WickedEngine/wiTimer.h index 5cd74a6e2..d1cb4a838 100644 --- a/WickedEngine/wiTimer.h +++ b/WickedEngine/wiTimer.h @@ -5,12 +5,7 @@ struct wiTimer { - std::chrono::high_resolution_clock::time_point timestamp; - - wiTimer() - { - record(); - } + std::chrono::high_resolution_clock::time_point timestamp = std::chrono::high_resolution_clock::now(); // Record a reference timestamp inline void record() diff --git a/WickedEngine/wiUnorderedMap.h b/WickedEngine/wiUnorderedMap.h new file mode 100644 index 000000000..8c5a6dc04 --- /dev/null +++ b/WickedEngine/wiUnorderedMap.h @@ -0,0 +1,25 @@ +#ifndef WI_UNORDERED_MAP_REPLACEMENT +#define WI_UNORDERED_MAP_REPLACEMENT +// This file is used to allow replacement of std::unordered_map + +#ifndef WI_UNORDERED_MAP_TYPE +#define WI_UNORDERED_MAP_TYPE 1 +#endif // WI_UNORDERED_MAP_TYPE + +#if WI_UNORDERED_MAP_TYPE == 1 +#include "Utility/flat_hash_map.hpp" +#else +#include +#endif // WI_UNORDERED_MAP_TYPE + +namespace wi +{ + template +#if WI_UNORDERED_MAP_TYPE == 1 + using unordered_map = ska::flat_hash_map; +#else + using unordered_map = std::unordered_map; +#endif // WI_UNORDERED_MAP_TYPE +} + +#endif // WI_UNORDERED_MAP_REPLACEMENT diff --git a/WickedEngine/wiUnorderedSet.h b/WickedEngine/wiUnorderedSet.h new file mode 100644 index 000000000..c341739ba --- /dev/null +++ b/WickedEngine/wiUnorderedSet.h @@ -0,0 +1,25 @@ +#ifndef WI_UNORDERED_SET_REPLACEMENT +#define WI_UNORDERED_SET_REPLACEMENT +// This file is used to allow replacement of std::unordered_set + +#ifndef WI_UNORDERED_SET_TYPE +#define WI_UNORDERED_SET_TYPE 1 +#endif // WI_UNORDERED_SET_TYPE + +#if WI_UNORDERED_SET_TYPE == 1 +#include "Utility/flat_hash_map.hpp" +#else +#include +#endif // WI_UNORDERED_SET_TYPE + +namespace wi +{ + template +#if WI_UNORDERED_SET_TYPE == 1 + using unordered_set = ska::flat_hash_set; +#else + using unordered_set = std::unordered_set; +#endif // WI_UNORDERED_SET_TYPE +} + +#endif // WI_UNORDERED_SET_REPLACEMENT diff --git a/WickedEngine/wiVector.h b/WickedEngine/wiVector.h new file mode 100644 index 000000000..74c03c448 --- /dev/null +++ b/WickedEngine/wiVector.h @@ -0,0 +1,13 @@ +#ifndef WI_VECTOR_REPLACEMENT +#define WI_VECTOR_REPLACEMENT +// This file is used to allow replacement of std::vector + +#include + +namespace wi +{ + template + using vector = std::vector; +} + +#endif // WI_VECTOR_REPLACEMENT diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 9d367960a..2e762968b 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates, breaking compatibility changes const int minor = 59; // minor bug fixes, alterations, refactors, updates - const int revision = 10; + const int revision = 11; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision); diff --git a/WickedEngine/wiWidget.cpp b/WickedEngine/wiWidget.cpp index 15cd5b143..dab5f1442 100644 --- a/WickedEngine/wiWidget.cpp +++ b/WickedEngine/wiWidget.cpp @@ -9,12 +9,12 @@ #include "wiBackLog.h" #include "wiTimer.h" +#include #include using namespace wiGraphics; using namespace wiScene; - static wiGraphics::PipelineState PSO_colored; wiWidget::wiWidget() @@ -153,15 +153,12 @@ void wiWidget::SetName(const std::string& value) if (value.length() <= 0) { static std::atomic widgetID{ 0 }; - std::stringstream ss(""); - ss << "widget_" << widgetID.fetch_add(1); - name = ss.str(); + name = "widget_" + std::to_string(widgetID.fetch_add(1)); } else { name = value; } - } const std::string wiWidget::GetText() const { @@ -171,14 +168,26 @@ void wiWidget::SetText(const std::string& value) { font.SetText(value); } +void wiWidget::SetText(std::string&& value) +{ + font.SetText(value); +} void wiWidget::SetTooltip(const std::string& value) { tooltip = value; } +void wiWidget::SetTooltip(std::string&& value) +{ + tooltip = value; +} void wiWidget::SetScriptTip(const std::string& value) { scriptTip = value; } +void wiWidget::SetScriptTip(std::string&& value) +{ + scriptTip = value; +} void wiWidget::SetPos(const XMFLOAT2& value) { SetDirty(); @@ -1436,7 +1445,7 @@ void wiComboBox::AddItem(const std::string& name, uint64_t userdata) } void wiComboBox::RemoveItem(int index) { - std::vector newItems(0); + wi::vector newItems(0); newItems.reserve(items.size()); for (size_t i = 0; i < items.size(); ++i) { @@ -2256,7 +2265,7 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const static wiGraphics::GPUBuffer vb_picker_hue; static wiGraphics::GPUBuffer vb_preview; - static std::vector vertices_saturation; + static wi::vector vertices_saturation; static bool buffersComplete = false; if (!buffersComplete) @@ -2285,7 +2294,7 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const // hue { const float edge = 2.0f; - std::vector vertices; + wi::vector vertices; uint32_t segment_count = 100; // inner alpha blended edge for (uint32_t i = 0; i <= segment_count; ++i) @@ -2348,7 +2357,7 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const { float _radius = 3; float _width = 3; - std::vector vertices; + wi::vector vertices; uint32_t segment_count = 100; for (uint32_t i = 0; i <= segment_count; ++i) { diff --git a/WickedEngine/wiWidget.h b/WickedEngine/wiWidget.h index 905f2555a..d720fd80f 100644 --- a/WickedEngine/wiWidget.h +++ b/WickedEngine/wiWidget.h @@ -7,9 +7,9 @@ #include "wiSprite.h" #include "wiSpriteFont.h" #include "wiMath.h" +#include "wiVector.h" #include -#include #include struct wiEventArgs @@ -55,8 +55,11 @@ public: void SetName(const std::string& value); const std::string GetText() const; void SetText(const std::string& value); + void SetText(std::string&& value); void SetTooltip(const std::string& value); + void SetTooltip(std::string&& value); void SetScriptTip(const std::string& value); + void SetScriptTip(std::string&& value); void SetPos(const XMFLOAT2& value); void SetSize(const XMFLOAT2& value); WIDGETSTATE GetState() const; @@ -240,7 +243,7 @@ protected: std::string name; uint64_t userdata = 0; }; - std::vector items; + wi::vector items; float GetItemOffset(int index) const; public: @@ -275,7 +278,7 @@ protected: wiButton resizeDragger_BottomRight; wiButton moveDragger; wiLabel label; - std::vector widgets; + wi::vector widgets; bool minimized = false; public: void Create(const std::string& name, bool window_controls = true); @@ -365,7 +368,7 @@ protected: Hitbox2D GetHitbox_Item(int visible_count, int level) const; Hitbox2D GetHitbox_ItemOpener(int visible_count, int level) const; - std::vector items; + wi::vector items; float GetItemOffset(int index) const; public: diff --git a/third_party_software.txt b/third_party_software.txt index 634b93b23..3863bcc2c 100644 --- a/third_party_software.txt +++ b/third_party_software.txt @@ -428,6 +428,34 @@ FNA-XNA/FAudio 21.09: https://github.com/FNA-XNA/FAudio * */ + ############################################################################################################################### + +Flat hash map: https://github.com/skarupke/flat_hash_map + +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + ###############################################################################################################################