From c4c582d7395cf81f1cf71b4d1890143c362edd3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Thu, 9 Dec 2021 18:58:27 +0100 Subject: [PATCH] general improvements (#368) * custom implementation for wi::vector * fix * sdl vulkan fix * linux fix * fix * vector fix * shader compiler and job system will be initialized automatically on first use * vector improvements * updates * update * network and audio will be auto initializing on first use only * fix * for now, use std::vector * vector refactor minor * backlog: access safety * shader clearcoat fix * gui initialization on demand * initializer updates * job system will be explicitly initialized --- Editor/ModelImporter_GLTF.cpp | 2 +- Editor/ModelImporter_OBJ.cpp | 6 +- Editor/PaintToolWindow.cpp | 1 + Editor/WeatherWindow.cpp | 2 +- Example_ImGui/Example_ImGui.cpp | 2 - Tests/Tests.cpp | 59 +++- Tests/Tests.h | 2 +- WickedEngine/WickedEngine_Windows.vcxproj | 3 + .../WickedEngine_Windows.vcxproj.filters | 6 +- WickedEngine/offlineshadercompiler.cpp | 4 +- WickedEngine/shaders/objectHF.hlsli | 3 +- WickedEngine/wiApplication.cpp | 23 +- WickedEngine/wiAudio.cpp | 126 ++++---- WickedEngine/wiBacklog.cpp | 56 ++-- WickedEngine/wiFont.cpp | 12 +- WickedEngine/wiGUI.cpp | 68 ++-- WickedEngine/wiGUI.h | 2 - WickedEngine/wiGraphics.h | 8 +- WickedEngine/wiGraphicsDevice.h | 2 +- WickedEngine/wiGraphicsDevice_Vulkan.cpp | 75 +++-- WickedEngine/wiHelper.cpp | 18 +- WickedEngine/wiHelper.h | 12 + WickedEngine/wiImage.cpp | 10 - WickedEngine/wiInitializer.cpp | 47 +-- WickedEngine/wiInitializer.h | 22 +- WickedEngine/wiJobSystem.cpp | 38 ++- WickedEngine/wiJobSystem.h | 4 +- WickedEngine/wiLua.cpp | 3 +- WickedEngine/wiNetwork.h | 2 - WickedEngine/wiNetwork_Linux.cpp | 9 - WickedEngine/wiNetwork_UWP.cpp | 5 - WickedEngine/wiNetwork_Windows.cpp | 43 +-- WickedEngine/wiPhysics_Bullet.cpp | 42 ++- WickedEngine/wiScene.h | 10 +- WickedEngine/wiShaderCompiler.cpp | 151 +++++---- WickedEngine/wiShaderCompiler.h | 1 - WickedEngine/wiSpriteFont.cpp | 2 +- WickedEngine/wiVector.h | 291 +++++++++++++++++- WickedEngine/wiVersion.cpp | 2 +- WickedEngine/wickedengine.natvis | 16 + 40 files changed, 787 insertions(+), 403 deletions(-) create mode 100644 WickedEngine/wickedengine.natvis diff --git a/Editor/ModelImporter_GLTF.cpp b/Editor/ModelImporter_GLTF.cpp index a96d526b5..e2821130a 100644 --- a/Editor/ModelImporter_GLTF.cpp +++ b/Editor/ModelImporter_GLTF.cpp @@ -79,7 +79,7 @@ namespace tinygltf #endif } - bool ReadWholeFile(wi::vector* out, std::string* err, + bool ReadWholeFile(std::vector* out, std::string* err, const std::string& filepath, void*) { return wi::helper::FileRead(filepath, *out); } diff --git a/Editor/ModelImporter_OBJ.cpp b/Editor/ModelImporter_OBJ.cpp index 209dc5f23..1f1b8e40a 100644 --- a/Editor/ModelImporter_OBJ.cpp +++ b/Editor/ModelImporter_OBJ.cpp @@ -27,7 +27,7 @@ public: : m_mtlBaseDir(mtl_basedir) {} virtual ~MaterialFileReader() {} virtual bool operator()(const std::string& matId, - wi::vector* materials, + std::vector* materials, std::map* matMap, std::string* err) { std::string filepath; @@ -78,8 +78,8 @@ void ImportModel_OBJ(const std::string& fileName, Scene& scene) std::string name = wi::helper::GetFileNameFromPath(fileName); tinyobj::attrib_t obj_attrib; - wi::vector obj_shapes; - wi::vector obj_materials; + std::vector obj_shapes; + std::vector obj_materials; std::string obj_errors; wi::vector filedata; diff --git a/Editor/PaintToolWindow.cpp b/Editor/PaintToolWindow.cpp index a3250052c..103e5e922 100644 --- a/Editor/PaintToolWindow.cpp +++ b/Editor/PaintToolWindow.cpp @@ -88,6 +88,7 @@ void PaintToolWindow::Create(EditorComponent* editor) infoLabel.SetPos(XMFLOAT2(10, y)); infoLabel.SetColor(wi::Color::Transparent()); AddWidget(&infoLabel); + y += infoLabel.GetScale().y - step + 5; radiusSlider.Create(1.0f, 500.0f, 50, 10000, "Brush Radius: "); diff --git a/Editor/WeatherWindow.cpp b/Editor/WeatherWindow.cpp index bdd538f79..dd9b3ebf9 100644 --- a/Editor/WeatherWindow.cpp +++ b/Editor/WeatherWindow.cpp @@ -577,7 +577,7 @@ void WeatherWindow::Create(EditorComponent* editor) wi::jobsystem::context ctx; for (auto& x : conv) { - std::vector filedata; + wi::vector filedata; if (wi::helper::saveTextureToMemory(x.second.GetTexture(), filedata)) { x.second.SetFileData(std::move(filedata)); diff --git a/Example_ImGui/Example_ImGui.cpp b/Example_ImGui/Example_ImGui.cpp index 180ffd142..57992015d 100644 --- a/Example_ImGui/Example_ImGui.cpp +++ b/Example_ImGui/Example_ImGui.cpp @@ -99,8 +99,6 @@ void Example_ImGui::Initialize() { // Compile shaders { - wi::shadercompiler::Initialize(); - auto shaderPath = wi::renderer::GetShaderSourcePath(); wi::renderer::SetShaderSourcePath(wi::helper::GetCurrentPath() + "/"); diff --git a/Tests/Tests.cpp b/Tests/Tests.cpp index 07f175c8d..f4034aff9 100644 --- a/Tests/Tests.cpp +++ b/Tests/Tests.cpp @@ -5,6 +5,7 @@ #include #include #include +#include using namespace wi::ecs; using namespace wi::scene; @@ -120,7 +121,7 @@ void TestsRenderer::Load() testSelector.AddItem("Controller Test"); testSelector.AddItem("Inverse Kinematics"); testSelector.AddItem("65k Instances"); - testSelector.AddItem("unordered_map perf"); + testSelector.AddItem("Container perf"); testSelector.SetMaxVisibleItemCount(10); testSelector.OnSelect([=](wi::gui::EventArgs args) { @@ -295,7 +296,7 @@ void TestsRenderer::Load() break; case 19: - RunUnorderedMapTest(); + ContainerTest(); break; default: @@ -930,15 +931,16 @@ void TestsRenderer::RunNetworkTest() font.params.size = 24; AddFont(&font); } -void TestsRenderer::RunUnorderedMapTest() +void TestsRenderer::ContainerTest() { wi::Timer 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::string ss = "Container test for " + std::to_string(elements) + " elements:\n"; +#if WI_UNORDERED_MAP_TYPE std::unordered_map std_map; { timer.record(); @@ -946,7 +948,7 @@ void TestsRenderer::RunUnorderedMapTest() { std_map[shuffle(i)] = i; } - ss += "\n\nstd::unordered_map insertion: " + std::to_string(timer.elapsed_milliseconds()) + " ms\n"; + ss += "\nstd::unordered_map insertion: " + std::to_string(timer.elapsed_milliseconds()) + " ms\n"; timer.record(); for (size_t i = 0; i < std_map.size(); ++i) @@ -963,15 +965,58 @@ void TestsRenderer::RunUnorderedMapTest() { wi_map[shuffle(i)] = i; } - ss += "\n\nwi::unordered_map insertion: " + std::to_string(timer.elapsed_milliseconds()) + " ms\n"; + ss += "\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"; + ss += "wi::unordered_map access: " + std::to_string(timer.elapsed_milliseconds()) + " ms\n"; } +#else + ss += "wi::unordered_map implementation uses std::unordered_map. There is nothing to test."; +#endif // WI_UNORDERED_MAP_TYPE + + ss += "\n"; + +#if WI_VECTOR_TYPE + std::vector std_vector; + { + timer.record(); + for (size_t i = 0; i < elements; ++i) + { + std_vector.emplace_back(); + } + ss += "\nstd::vector append: " + std::to_string(timer.elapsed_milliseconds()) + " ms\n"; + + timer.record(); + for (auto& x : std_vector) + { + x.aperture_size = 8; + } + ss += "std::vector access: " + std::to_string(timer.elapsed_milliseconds()) + " ms"; + } + + wi::vector wi_vector; + { + timer.record(); + for (size_t i = 0; i < elements; ++i) + { + wi_vector.emplace_back(); + } + ss += "\nwi::vector append: " + std::to_string(timer.elapsed_milliseconds()) + " ms\n"; + + timer.record(); + for (auto& x : wi_vector) + { + x.aperture_size = 8; + } + ss += "wi::vector access: " + std::to_string(timer.elapsed_milliseconds()) + " ms\n"; + } +#else + ss += "wi::vector implementation uses std::vector. There is nothing to test."; +#endif // WI_VECTOR_TYPE static wi::SpriteFont font; font = wi::SpriteFont(ss); diff --git a/Tests/Tests.h b/Tests/Tests.h index dda7f9008..763a8e86c 100644 --- a/Tests/Tests.h +++ b/Tests/Tests.h @@ -16,7 +16,7 @@ public: void RunFontTest(); void RunSpriteTest(); void RunNetworkTest(); - void RunUnorderedMapTest(); + void ContainerTest(); }; class Tests : public wi::Application diff --git a/WickedEngine/WickedEngine_Windows.vcxproj b/WickedEngine/WickedEngine_Windows.vcxproj index 3c82cb514..59a7c46e1 100644 --- a/WickedEngine/WickedEngine_Windows.vcxproj +++ b/WickedEngine/WickedEngine_Windows.vcxproj @@ -10,6 +10,9 @@ x64 + + + {06163DCB-B183-4ED9-9C62-13EF1658E049} Win32Proj diff --git a/WickedEngine/WickedEngine_Windows.vcxproj.filters b/WickedEngine/WickedEngine_Windows.vcxproj.filters index 9cd851056..fd233b2aa 100644 --- a/WickedEngine/WickedEngine_Windows.vcxproj.filters +++ b/WickedEngine/WickedEngine_Windows.vcxproj.filters @@ -1,2 +1,6 @@  - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/WickedEngine/offlineshadercompiler.cpp b/WickedEngine/offlineshadercompiler.cpp index 5f0485fe9..008932ad0 100644 --- a/WickedEngine/offlineshadercompiler.cpp +++ b/WickedEngine/offlineshadercompiler.cpp @@ -31,6 +31,8 @@ int main(int argc, char* argv[]) std::cout << "\tshaderdump : \tShaders will be saved to wiShaderDump.h C++ header file (rebuild is assumed)" << std::endl; std::cout << "Command arguments used: "; + wi::jobsystem::Initialize(); + wi::arguments::Parse(argc, argv); if (wi::arguments::HasArgument("hlsl5")) @@ -399,8 +401,6 @@ int main(int argc, char* argv[]) minshadermodels["rtaoCS.hlsl"] = ShaderModel::SM_6_5; minshadermodels["surfel_raytraceCS_rtapi.hlsl"] = ShaderModel::SM_6_5; - wi::shadercompiler::Initialize(); - wi::jobsystem::Initialize(); wi::jobsystem::context ctx; std::string SHADERSOURCEPATH = wi::renderer::GetShaderSourcePath(); diff --git a/WickedEngine/shaders/objectHF.hlsli b/WickedEngine/shaders/objectHF.hlsli index 2af6c4c14..1800c0cbb 100644 --- a/WickedEngine/shaders/objectHF.hlsli +++ b/WickedEngine/shaders/objectHF.hlsli @@ -1554,8 +1554,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_Target if (GetMaterial().uvset_clearcoatNormalMap >= 0) { const float2 uvset_clearcoatNormalMap = GetMaterial().uvset_clearcoatNormalMap == 0 ? input.uvsets.xy : input.uvsets.zw; - float3 clearcoatNormalMap = texture_clearcoatnormalmap.Sample(sampler_objectshader, uvset_clearcoatNormalMap).rgb; - clearcoatNormalMap.b = clearcoatNormalMap.b == 0 ? 1 : clearcoatNormalMap.b; // fix for missing blue channel + float3 clearcoatNormalMap = float3(texture_clearcoatnormalmap.Sample(sampler_objectshader, uvset_clearcoatNormalMap).rg, 1); clearcoatNormalMap = clearcoatNormalMap * 2 - 1; surface.clearcoat.N = mul(clearcoatNormalMap, TBN); } diff --git a/WickedEngine/wiApplication.cpp b/WickedEngine/wiApplication.cpp index dd75968ac..00a749171 100644 --- a/WickedEngine/wiApplication.cpp +++ b/WickedEngine/wiApplication.cpp @@ -84,22 +84,25 @@ namespace wi CommandList cmd = graphicsDevice->BeginCommandList(); graphicsDevice->RenderPassBegin(&swapChain, cmd); wi::image::SetCanvas(canvas, cmd); - wi::font::SetCanvas(canvas, cmd); Viewport viewport; viewport.width = (float)swapChain.desc.width; viewport.height = (float)swapChain.desc.height; graphicsDevice->BindViewports(1, &viewport, cmd); - wi::font::Params params; - params.posX = 5.f; - params.posY = 5.f; - std::string text = wi::backlog::getText(); - float textheight = wi::font::TextHeight(text, params); - float screenheight = canvas.GetLogicalHeight(); - if (textheight > screenheight) + if (wi::initializer::IsInitializeFinished(wi::initializer::INITIALIZED_SYSTEM_FONT)) { - params.posY = screenheight - textheight; + wi::font::SetCanvas(canvas, cmd); + wi::font::Params params; + params.posX = 5.f; + params.posY = 5.f; + std::string text = wi::backlog::getText(); + float textheight = wi::font::TextHeight(text, params); + float screenheight = canvas.GetLogicalHeight(); + if (textheight > screenheight) + { + params.posY = screenheight - textheight; + } + wi::font::Draw(text, params, cmd); } - wi::font::Draw(text, params, cmd); graphicsDevice->RenderPassEnd(cmd); graphicsDevice->SubmitCommandLists(); return; diff --git a/WickedEngine/wiAudio.cpp b/WickedEngine/wiAudio.cpp index f3dfc955c..1b93e13d0 100644 --- a/WickedEngine/wiAudio.cpp +++ b/WickedEngine/wiAudio.cpp @@ -72,6 +72,8 @@ namespace wi::audio AudioInternal() { + wi::Timer timer; + HRESULT hr; hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); assert(SUCCEEDED(hr)); @@ -136,7 +138,10 @@ namespace wi::audio assert(SUCCEEDED(hr)); } - success = SUCCEEDED(hr); + if (SUCCEEDED(hr)) + { + wi::backlog::post("wi::audio Initialized [XAudio2] (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); + } } ~AudioInternal() { @@ -158,7 +163,12 @@ namespace wi::audio CoUninitialize(); } }; - std::shared_ptr audio; + static std::shared_ptr audio_internal; + + void Initialize() + { + audio_internal = std::make_shared(); + } struct SoundInternal { @@ -191,18 +201,6 @@ namespace wi::audio return static_cast(param->internal_state.get()); } - void Initialize() - { - wi::Timer timer; - - audio = std::make_shared(); - - if (audio->success) - { - wi::backlog::post("wi::audio Initialized [XAudio2] (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); - } - } - bool FindChunk(const uint8_t* data, DWORD fourcc, DWORD& dwChunkSize, DWORD& dwChunkDataPosition) { size_t pos = 0; @@ -266,7 +264,7 @@ namespace wi::audio bool CreateSound(const uint8_t* data, size_t size, Sound* sound) { std::shared_ptr soundinternal = std::make_shared(); - soundinternal->audio = audio; + soundinternal->audio = audio_internal; sound->internal_state = soundinternal; DWORD dwChunkSize; @@ -342,19 +340,19 @@ namespace wi::audio std::shared_ptr instanceinternal = std::make_shared(); instance->internal_state = instanceinternal; - instanceinternal->audio = audio; + instanceinternal->audio = audio_internal; instanceinternal->soundinternal = soundinternal; XAUDIO2_SEND_DESCRIPTOR SFXSend[] = { - { XAUDIO2_SEND_USEFILTER, audio->submixVoices[instance->type] }, - { XAUDIO2_SEND_USEFILTER, audio->reverbSubmix }, // this should be last to enable/disable reverb simply + { XAUDIO2_SEND_USEFILTER, instanceinternal->audio->submixVoices[instance->type] }, + { XAUDIO2_SEND_USEFILTER, instanceinternal->audio->reverbSubmix }, // this should be last to enable/disable reverb simply }; XAUDIO2_VOICE_SENDS SFXSendList = { instance->IsEnableReverb() ? arraysize(SFXSend) : 1, SFXSend }; - hr = audio->audioEngine->CreateSourceVoice(&instanceinternal->sourceVoice, &soundinternal->wfx, + hr = instanceinternal->audio->audioEngine->CreateSourceVoice(&instanceinternal->sourceVoice, &soundinternal->wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, NULL, &SFXSendList, NULL); if (FAILED(hr)) { @@ -364,7 +362,7 @@ namespace wi::audio instanceinternal->sourceVoice->GetVoiceDetails(&instanceinternal->voiceDetails); - instanceinternal->outputMatrix.resize(size_t(instanceinternal->voiceDetails.InputChannels) * size_t(audio->masteringVoiceDetails.InputChannels)); + instanceinternal->outputMatrix.resize(size_t(instanceinternal->voiceDetails.InputChannels) * size_t(instanceinternal->audio->masteringVoiceDetails.InputChannels)); instanceinternal->channelAzimuths.resize(instanceinternal->voiceDetails.InputChannels); for (size_t i = 0; i < instanceinternal->channelAzimuths.size(); ++i) { @@ -375,8 +373,8 @@ namespace wi::audio instanceinternal->buffer.pAudioData = soundinternal->audioData.data(); instanceinternal->buffer.Flags = XAUDIO2_END_OF_STREAM; instanceinternal->buffer.LoopCount = XAUDIO2_LOOP_INFINITE; - instanceinternal->buffer.LoopBegin = UINT32(instance->loop_begin * audio->masteringVoiceDetails.InputSampleRate); - instanceinternal->buffer.LoopLength = UINT32(instance->loop_length * audio->masteringVoiceDetails.InputSampleRate); + instanceinternal->buffer.LoopBegin = UINT32(instance->loop_begin * instanceinternal->audio->masteringVoiceDetails.InputSampleRate); + instanceinternal->buffer.LoopLength = UINT32(instance->loop_length * instanceinternal->audio->masteringVoiceDetails.InputSampleRate); hr = instanceinternal->sourceVoice->SubmitSourceBuffer(&instanceinternal->buffer); if (FAILED(hr)) @@ -422,7 +420,7 @@ namespace wi::audio { if (instance == nullptr || !instance->IsValid()) { - HRESULT hr = audio->masteringVoice->SetVolume(volume); + HRESULT hr = audio_internal->masteringVoice->SetVolume(volume); assert(SUCCEEDED(hr)); } else @@ -437,7 +435,7 @@ namespace wi::audio float volume = 0; if (instance == nullptr || !instance->IsValid()) { - audio->masteringVoice->GetVolume(&volume); + audio_internal->masteringVoice->GetVolume(&volume); } else { @@ -458,13 +456,13 @@ namespace wi::audio void SetSubmixVolume(SUBMIX_TYPE type, float volume) { - HRESULT hr = audio->submixVoices[type]->SetVolume(volume); + HRESULT hr = audio_internal->submixVoices[type]->SetVolume(volume); assert(SUCCEEDED(hr)); } float GetSubmixVolume(SUBMIX_TYPE type) { float volume; - audio->submixVoices[type]->GetVolume(&volume); + audio_internal->submixVoices[type]->GetVolume(&volume); return volume; } @@ -506,10 +504,10 @@ namespace wi::audio X3DAUDIO_DSP_SETTINGS settings = {}; settings.SrcChannelCount = instanceinternal->voiceDetails.InputChannels; - settings.DstChannelCount = audio->masteringVoiceDetails.InputChannels; + settings.DstChannelCount = instanceinternal->audio->masteringVoiceDetails.InputChannels; settings.pMatrixCoefficients = instanceinternal->outputMatrix.data(); - X3DAudioCalculate(audio->audio3D, &listener, &emitter, flags, &settings); + X3DAudioCalculate(instanceinternal->audio->audio3D, &listener, &emitter, flags, &settings); HRESULT hr; @@ -517,7 +515,7 @@ namespace wi::audio assert(SUCCEEDED(hr)); hr = instanceinternal->sourceVoice->SetOutputMatrix( - audio->submixVoices[instance->type], + instanceinternal->audio->submixVoices[instance->type], settings.SrcChannelCount, settings.DstChannelCount, settings.pMatrixCoefficients @@ -525,15 +523,15 @@ namespace wi::audio assert(SUCCEEDED(hr)); XAUDIO2_FILTER_PARAMETERS FilterParametersDirect = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI / 6.0f * settings.LPFDirectCoefficient), 1.0f }; - hr = instanceinternal->sourceVoice->SetOutputFilterParameters(audio->submixVoices[instance->type], &FilterParametersDirect); + hr = instanceinternal->sourceVoice->SetOutputFilterParameters(instanceinternal->audio->submixVoices[instance->type], &FilterParametersDirect); assert(SUCCEEDED(hr)); if (instance->IsEnableReverb()) { - hr = instanceinternal->sourceVoice->SetOutputMatrix(audio->reverbSubmix, settings.SrcChannelCount, 1, &settings.ReverbLevel); + hr = instanceinternal->sourceVoice->SetOutputMatrix(instanceinternal->audio->reverbSubmix, settings.SrcChannelCount, 1, &settings.ReverbLevel); assert(SUCCEEDED(hr)); XAUDIO2_FILTER_PARAMETERS FilterParametersReverb = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI / 6.0f * settings.LPFReverbCoefficient), 1.0f }; - hr = instanceinternal->sourceVoice->SetOutputFilterParameters(audio->reverbSubmix, &FilterParametersReverb); + hr = instanceinternal->sourceVoice->SetOutputFilterParameters(instanceinternal->audio->reverbSubmix, &FilterParametersReverb); assert(SUCCEEDED(hr)); } } @@ -543,7 +541,7 @@ namespace wi::audio { XAUDIO2FX_REVERB_PARAMETERS native; ReverbConvertI3DL2ToNative(&reverbPresets[preset], &native); - HRESULT hr = audio->reverbSubmix->SetEffectParameters(0, &native, sizeof(native)); + HRESULT hr = audio_internal->reverbSubmix->SetEffectParameters(0, &native, sizeof(native)); assert(SUCCEEDED(hr)); } } @@ -608,6 +606,8 @@ namespace wi::audio FAudioSubmixVoice* reverbSubmix = nullptr; AudioInternal(){ + wi::Timer timer; + uint32_t res; res = FAudioCreate(&audioEngine, 0, FAUDIO_DEFAULT_PROCESSOR); assert(res == 0); @@ -656,6 +656,11 @@ namespace wi::audio nullptr, &effectChain); } + + if (success) + { + wi::backlog::post("wi::audio Initialized [FAudio] (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); + } } ~AudioInternal(){ if(reverbSubmix != nullptr) @@ -672,7 +677,12 @@ namespace wi::audio FAudio_StopEngine(audioEngine); } }; - std::shared_ptr audio; + static std::shared_ptr audio_internal; + + void Initialize() + { + audio_internal = std::make_shared(); + } struct SoundInternal{ std::shared_ptr audio; @@ -694,16 +704,6 @@ namespace wi::audio } }; - void Initialize() { - wi::Timer timer; - - audio = std::make_shared(); - - if (audio->success) - { - wi::backlog::post("wi::audio Initialized [FAudio] (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); - } - } SoundInternal* to_internal(const Sound* param) { return static_cast(param->internal_state.get()); @@ -774,7 +774,7 @@ namespace wi::audio } bool CreateSound(const uint8_t* data, size_t size, Sound* sound) { std::shared_ptr soundinternal = std::make_shared(); - soundinternal->audio = audio; + soundinternal->audio = audio_internal; sound->internal_state = soundinternal; uint32_t dwChunkSize; @@ -849,12 +849,12 @@ namespace wi::audio std::shared_ptr instanceinternal = std::make_shared(); instance->internal_state = instanceinternal; - instanceinternal->audio = audio; + instanceinternal->audio = audio_internal; instanceinternal->soundinternal = soundinternal; FAudioSendDescriptor SFXSend[] = { - { FAUDIO_SEND_USEFILTER, audio->submixVoices[instance->type] }, - { FAUDIO_SEND_USEFILTER, audio->reverbSubmix }, // this should be last to enable/disable reverb simply + { FAUDIO_SEND_USEFILTER, instanceinternal->audio->submixVoices[instance->type] }, + { FAUDIO_SEND_USEFILTER, instanceinternal->audio->reverbSubmix }, // this should be last to enable/disable reverb simply }; FAudioVoiceSends SFXSendList = { @@ -870,7 +870,7 @@ namespace wi::audio } FAudioVoice_GetVoiceDetails(instanceinternal->sourceVoice, &instanceinternal->voiceDetails); - instanceinternal->outputMatrix.resize(size_t(instanceinternal->voiceDetails.InputChannels) * size_t(audio->masteringVoiceDetails.InputChannels)); + instanceinternal->outputMatrix.resize(size_t(instanceinternal->voiceDetails.InputChannels) * size_t(instanceinternal->audio->masteringVoiceDetails.InputChannels)); instanceinternal->channelAzimuths.resize(instanceinternal->voiceDetails.InputChannels); for (size_t i = 0; i < instanceinternal->channelAzimuths.size(); ++i) { @@ -881,8 +881,8 @@ namespace wi::audio instanceinternal->buffer.pAudioData = soundinternal->audioData.data(); instanceinternal->buffer.Flags = FAUDIO_END_OF_STREAM; instanceinternal->buffer.LoopCount = FAUDIO_LOOP_INFINITE; - instanceinternal->buffer.LoopBegin = uint32_t(instance->loop_begin * audio->masteringVoiceDetails.InputSampleRate); - instanceinternal->buffer.LoopLength = uint32_t(instance->loop_length * audio->masteringVoiceDetails.InputSampleRate); + instanceinternal->buffer.LoopBegin = uint32_t(instance->loop_begin * instanceinternal->audio->masteringVoiceDetails.InputSampleRate); + instanceinternal->buffer.LoopLength = uint32_t(instance->loop_length * instanceinternal->audio->masteringVoiceDetails.InputSampleRate); res = FAudioSourceVoice_SubmitSourceBuffer(instanceinternal->sourceVoice, &(instanceinternal->buffer), nullptr); if(res != 0){ @@ -920,7 +920,7 @@ namespace wi::audio } void SetVolume(float volume, SoundInstance* instance) { if (instance == nullptr || !instance->IsValid()){ - uint32_t res = FAudioVoice_SetVolume(audio->masteringVoice, volume, FAUDIO_COMMIT_NOW); + uint32_t res = FAudioVoice_SetVolume(audio_internal->masteringVoice, volume, FAUDIO_COMMIT_NOW); assert(res == 0); } else { @@ -932,7 +932,7 @@ namespace wi::audio float GetVolume(const SoundInstance* instance) { float volume = 0; if (instance == nullptr || !instance->IsValid()){ - FAudioVoice_GetVolume(audio->masteringVoice, &volume); + FAudioVoice_GetVolume(audio_internal->masteringVoice, &volume); } else { auto instanceinternal = to_internal(instance); @@ -949,12 +949,12 @@ namespace wi::audio } void SetSubmixVolume(SUBMIX_TYPE type, float volume) { - uint32_t res = FAudioVoice_SetVolume(audio->submixVoices[type], volume, FAUDIO_COMMIT_NOW); + uint32_t res = FAudioVoice_SetVolume(audio_internal->submixVoices[type], volume, FAUDIO_COMMIT_NOW); assert(res == 0); } float GetSubmixVolume(SUBMIX_TYPE type) { float volume; - FAudioVoice_GetVolume(audio->submixVoices[type], &volume); + FAudioVoice_GetVolume(audio_internal->submixVoices[type], &volume); return volume; } @@ -993,10 +993,10 @@ namespace wi::audio F3DAUDIO_DSP_SETTINGS settings = {}; settings.SrcChannelCount = instanceinternal->voiceDetails.InputChannels; - settings.DstChannelCount = audio->masteringVoiceDetails.InputChannels; + settings.DstChannelCount = instanceinternal->audio->masteringVoiceDetails.InputChannels; settings.pMatrixCoefficients = instanceinternal->outputMatrix.data(); - F3DAudioCalculate(audio->audio3D, &listener, &emitter, flags, &settings); + F3DAudioCalculate(instanceinternal->audio->audio3D, &listener, &emitter, flags, &settings); uint32_t res; @@ -1005,7 +1005,7 @@ namespace wi::audio res = FAudioVoice_SetOutputMatrix( instanceinternal->sourceVoice, - audio->submixVoices[instance->type], + instanceinternal->audio->submixVoices[instance->type], settings.SrcChannelCount, settings.DstChannelCount, settings.pMatrixCoefficients, @@ -1013,14 +1013,14 @@ namespace wi::audio assert(res == 0); FAudioFilterParameters FilterParametersDirect = { FAudioLowPassFilter, 2.0f * sinf(F3DAUDIO_PI / 6.0f * settings.LPFDirectCoefficient), 1.0f }; - res = FAudioVoice_SetOutputFilterParameters(instanceinternal->sourceVoice, audio->submixVoices[instance->type], &FilterParametersDirect, FAUDIO_COMMIT_NOW); + res = FAudioVoice_SetOutputFilterParameters(instanceinternal->sourceVoice, instanceinternal->audio->submixVoices[instance->type], &FilterParametersDirect, FAUDIO_COMMIT_NOW); assert(res == 0); if(instance->IsEnableReverb()){ - res = FAudioVoice_SetOutputMatrix(instanceinternal->sourceVoice, audio->reverbSubmix, settings.SrcChannelCount, 1, &settings.ReverbLevel, FAUDIO_COMMIT_NOW); + res = FAudioVoice_SetOutputMatrix(instanceinternal->sourceVoice, instanceinternal->audio->reverbSubmix, settings.SrcChannelCount, 1, &settings.ReverbLevel, FAUDIO_COMMIT_NOW); assert(res == 0); FAudioFilterParameters FilterParametersReverb = { FAudioLowPassFilter, 2.0f * sinf(F3DAUDIO_PI / 6.0f * settings.LPFReverbCoefficient), 1.0f }; - res = FAudioVoice_SetOutputFilterParameters(instanceinternal->sourceVoice, audio->reverbSubmix, &FilterParametersReverb, FAUDIO_COMMIT_NOW); + res = FAudioVoice_SetOutputFilterParameters(instanceinternal->sourceVoice, instanceinternal->audio->reverbSubmix, &FilterParametersReverb, FAUDIO_COMMIT_NOW); assert(res == 0); } } @@ -1029,7 +1029,7 @@ namespace wi::audio void SetReverb(REVERB_PRESET preset) { FAudioFXReverbParameters native; ReverbConvertI3DL2ToNative(&reverbPresets[preset], &native); - uint32_t res = FAudioVoice_SetEffectParameters(audio->reverbSubmix, 0, &native, sizeof(native), FAUDIO_COMMIT_NOW); + uint32_t res = FAudioVoice_SetEffectParameters(audio_internal->reverbSubmix, 0, &native, sizeof(native), FAUDIO_COMMIT_NOW); assert(res == 0); } } @@ -1038,8 +1038,6 @@ namespace wi::audio namespace wi::audio { - void Initialize() {} - bool CreateSound(const std::string& filename, 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/wiBacklog.cpp b/WickedEngine/wiBacklog.cpp index 96e3eb6d1..f85d6b852 100644 --- a/WickedEngine/wiBacklog.cpp +++ b/WickedEngine/wiBacklog.cpp @@ -21,25 +21,25 @@ using namespace wi::graphics; namespace wi::backlog { - 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 wi::SpriteFont font; - static wi::SpinLock logLock; - static Texture backgroundTex; - static bool refitscroll = false; + bool enabled = false; + std::deque stream; + std::deque history; + const float speed = 4000.0f; + const size_t deletefromline = 500; + float pos = std::numeric_limits::lowest(); + float scroll = 0; + std::string inputArea; + int historyPos = 0; + wi::SpriteFont font; + wi::SpinLock logLock; + Texture backgroundTex; + bool refitscroll = false; - static bool locked = false; - static bool blockLuaExec = false; - static LogLevel logLevel = LogLevel::Default; + bool locked = false; + bool blockLuaExec = false; + LogLevel logLevel = LogLevel::Default; - static void write_logfile() + void write_logfile() { std::string filename = wi::helper::GetTempDirectoryPath() + "wiBacklog.txt"; std::string text = getText(); // will lock mutex @@ -54,13 +54,13 @@ namespace wi::backlog { write_logfile(); } - } static logwriter; + } logwriter; - void Toggle() + void Toggle() { enabled = !enabled; } - void Scroll(float dir) + void Scroll(float dir) { scroll += dir; } @@ -168,7 +168,7 @@ namespace wi::backlog } return retval; } - void clear() + void clear() { std::scoped_lock lock(logLock); stream.clear(); @@ -234,12 +234,12 @@ namespace wi::backlog write_logfile(); // will lock mutex } } - void input(const char input) + void input(const char input) { std::scoped_lock lock(logLock); inputArea += input; } - void acceptInput() + void acceptInput() { historyPos = 0; post(inputArea.c_str()); @@ -258,7 +258,7 @@ namespace wi::backlog } inputArea.clear(); } - void deletefromInput() + void deletefromInput() { std::scoped_lock lock(logLock); if (!inputArea.empty()) @@ -267,10 +267,10 @@ namespace wi::backlog } } - void historyPrev() + void historyPrev() { std::scoped_lock lock(logLock); - if (!history.empty()) + if (!history.empty()) { inputArea = history[history.size() - 1 - historyPos]; if ((size_t)historyPos < history.size() - 1) @@ -279,10 +279,10 @@ namespace wi::backlog } } } - void historyNext() + void historyNext() { std::scoped_lock lock(logLock); - if (!history.empty()) + if (!history.empty()) { if (historyPos > 0) { diff --git a/WickedEngine/wiFont.cpp b/WickedEngine/wiFont.cpp index 56f27dbe3..3f0731ac1 100644 --- a/WickedEngine/wiFont.cpp +++ b/WickedEngine/wiFont.cpp @@ -18,7 +18,6 @@ #include "Utility/stb_truetype.h" #include -#include using namespace wi::graphics; using namespace wi::rectpacker; @@ -42,8 +41,6 @@ namespace wi::font wi::Canvas canvases[COMMANDLIST_COUNT]; - std::atomic_bool initialized{ false }; - Texture texture; struct Glyph @@ -258,11 +255,6 @@ namespace wi::font } void Initialize() { - if (initialized) - { - return; - } - wi::Timer timer; // add default font if there is none yet: @@ -318,9 +310,7 @@ namespace wi::font static wi::eventhandler::Handle handle1 = wi::eventhandler::Subscribe(wi::eventhandler::EVENT_RELOAD_SHADERS, [](uint64_t userdata) { LoadShaders(); }); LoadShaders(); - wi::backlog::post("wi::font Initialized (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); - initialized.store(true); } void UpdatePendingGlyphs() @@ -546,7 +536,7 @@ namespace wi::font template void Draw_internal(const T* text, size_t text_length, const Params& params, CommandList cmd) { - if (text_length <= 0 || !initialized.load()) + if (text_length <= 0) { return; } diff --git a/WickedEngine/wiGUI.cpp b/WickedEngine/wiGUI.cpp index bb1e5b798..ffc17d236 100644 --- a/WickedEngine/wiGUI.cpp +++ b/WickedEngine/wiGUI.cpp @@ -17,29 +17,37 @@ using namespace wi::primitive; namespace wi::gui { - static wi::graphics::PipelineState PSO_colored; - - void LoadShaders() + struct InternalState { - PipelineStateDesc desc; - desc.vs = wi::renderer::GetShader(wi::enums::VSTYPE_VERTEXCOLOR); - desc.ps = wi::renderer::GetShader(wi::enums::PSTYPE_VERTEXCOLOR); - desc.il = wi::renderer::GetInputLayout(wi::enums::ILTYPE_VERTEXCOLOR); - desc.dss = wi::renderer::GetDepthStencilState(wi::enums::DSSTYPE_DEPTHDISABLED); - desc.bs = wi::renderer::GetBlendState(wi::enums::BSTYPE_TRANSPARENT); - desc.rs = wi::renderer::GetRasterizerState(wi::enums::RSTYPE_DOUBLESIDED); - desc.pt = PrimitiveTopology::TRIANGLESTRIP; - wi::graphics::GetDevice()->CreatePipelineState(&desc, &PSO_colored); - } + wi::graphics::PipelineState PSO_colored; - void Initialize() + InternalState() + { + wi::Timer timer; + + static wi::eventhandler::Handle handle = wi::eventhandler::Subscribe(wi::eventhandler::EVENT_RELOAD_SHADERS, [this](uint64_t userdata) { LoadShaders(); }); + LoadShaders(); + + wi::backlog::post("wi::gui Initialized (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); + } + + void LoadShaders() + { + PipelineStateDesc desc; + desc.vs = wi::renderer::GetShader(wi::enums::VSTYPE_VERTEXCOLOR); + desc.ps = wi::renderer::GetShader(wi::enums::PSTYPE_VERTEXCOLOR); + desc.il = wi::renderer::GetInputLayout(wi::enums::ILTYPE_VERTEXCOLOR); + desc.dss = wi::renderer::GetDepthStencilState(wi::enums::DSSTYPE_DEPTHDISABLED); + desc.bs = wi::renderer::GetBlendState(wi::enums::BSTYPE_TRANSPARENT); + desc.rs = wi::renderer::GetRasterizerState(wi::enums::RSTYPE_DOUBLESIDED); + desc.pt = PrimitiveTopology::TRIANGLESTRIP; + wi::graphics::GetDevice()->CreatePipelineState(&desc, &PSO_colored); + } + }; + inline InternalState& gui_internal() { - wi::Timer timer; - - static wi::eventhandler::Handle handle = wi::eventhandler::Subscribe(wi::eventhandler::EVENT_RELOAD_SHADERS, [](uint64_t userdata) { LoadShaders(); }); - LoadShaders(); - - wi::backlog::post("wi::gui Initialized (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); + static InternalState internal_state; + return internal_state; } @@ -115,9 +123,9 @@ namespace wi::gui device->EventBegin("GUI", cmd); // Rendering is back to front: - for (auto it = widgets.rbegin(); it != widgets.rend(); ++it) + for (size_t i = 0; i < widgets.size(); ++i) { - const Widget* widget = (*it); + const Widget* widget = widgets[widgets.size() - i - 1]; device->BindScissorRects(1, &scissorRect, cmd); widget->Render(canvas, cmd); } @@ -328,7 +336,7 @@ namespace wi::gui } void Widget::SetText(std::string&& value) { - font.SetText(value); + font.SetText(std::move(value)); } void Widget::SetTooltip(const std::string& value) { @@ -336,7 +344,7 @@ namespace wi::gui } void Widget::SetTooltip(std::string&& value) { - tooltip = value; + tooltip = std::move(value); } void Widget::SetScriptTip(const std::string& value) { @@ -344,7 +352,7 @@ namespace wi::gui } void Widget::SetScriptTip(std::string&& value) { - scriptTip = value; + scriptTip = std::move(value); } void Widget::SetPos(const XMFLOAT2& value) { @@ -1462,7 +1470,7 @@ namespace wi::gui // control-arrow-triangle { - device->BindPipelineState(&PSO_colored, cmd); + device->BindPipelineState(&gui_internal().PSO_colored, cmd); MiscCB cb; cb.g_xColor = sprites[ACTIVE].params.color; @@ -1960,9 +1968,9 @@ namespace wi::gui sprites[state].Draw(cmd); } - for (auto it = widgets.rbegin(); it != widgets.rend(); ++it) + for (size_t i = 0; i < widgets.size(); ++i) { - const Widget* widget = (*it); + const Widget* widget = widgets[widgets.size() - i - 1]; ApplyScissor(canvas, scissorRect, cmd); widget->Render(canvas, cmd); } @@ -2568,7 +2576,7 @@ namespace wi::gui const XMMATRIX Projection = canvas.GetProjection(); - device->BindPipelineState(&PSO_colored, cmd); + device->BindPipelineState(&gui_internal().PSO_colored, cmd); ApplyScissor(canvas, scissorRect, cmd); @@ -3104,7 +3112,7 @@ namespace wi::gui // opened flag triangle: { - device->BindPipelineState(&PSO_colored, cmd); + device->BindPipelineState(&gui_internal().PSO_colored, cmd); MiscCB cb; cb.g_xColor = opener_highlight == i ? wi::Color::White().toFloat4() : sprites[FOCUS].params.color; diff --git a/WickedEngine/wiGUI.h b/WickedEngine/wiGUI.h index d7535c970..1382ac159 100644 --- a/WickedEngine/wiGUI.h +++ b/WickedEngine/wiGUI.h @@ -14,8 +14,6 @@ namespace wi::gui { - void Initialize(); - class Widget; class GUI diff --git a/WickedEngine/wiGraphics.h b/WickedEngine/wiGraphics.h index 6e8ae0d7c..4486de090 100644 --- a/WickedEngine/wiGraphics.h +++ b/WickedEngine/wiGraphics.h @@ -982,10 +982,10 @@ namespace wi::graphics PROCEDURAL, } type = Type::TRIANGLES; std::string name; - uint32_t general_shader = ~0; - uint32_t closest_hit_shader = ~0; - uint32_t any_hit_shader = ~0; - uint32_t intersection_shader = ~0; + uint32_t general_shader = ~0u; + uint32_t closest_hit_shader = ~0u; + uint32_t any_hit_shader = ~0u; + uint32_t intersection_shader = ~0u; }; struct RaytracingPipelineStateDesc { diff --git a/WickedEngine/wiGraphicsDevice.h b/WickedEngine/wiGraphicsDevice.h index 641bbf943..fe542e843 100644 --- a/WickedEngine/wiGraphicsDevice.h +++ b/WickedEngine/wiGraphicsDevice.h @@ -16,7 +16,7 @@ namespace wi::graphics struct CommandList { using index_type = uint8_t; - index_type index = ~0; + index_type index = 0xFF; constexpr operator index_type() const { return index; } }; static constexpr CommandList::index_type COMMANDLIST_COUNT = 32; // If you increase command list count, more memory will be statically allocated for per-command list resources diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index f935694f6..a225791f7 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -556,41 +556,6 @@ namespace vulkan_internal return true; } - wi::vector GetOptimalValidationLayers(const wi::vector& supported_instance_layers) - { - wi::vector> validationLayerPriorityList = - { - // The preferred validation layer is "VK_LAYER_KHRONOS_validation" - {"VK_LAYER_KHRONOS_validation"}, - - // Otherwise we fallback to using the LunarG meta layer - {"VK_LAYER_LUNARG_standard_validation"}, - - // Otherwise we attempt to enable the individual layers that compose the LunarG meta layer since it doesn't exist - { - "VK_LAYER_GOOGLE_threading", - "VK_LAYER_LUNARG_parameter_validation", - "VK_LAYER_LUNARG_object_tracker", - "VK_LAYER_LUNARG_core_validation", - "VK_LAYER_GOOGLE_unique_objects", - }, - - // Otherwise as a last resort we fallback to attempting to enable the LunarG core layer - {"VK_LAYER_LUNARG_core_validation"} - }; - - for (auto& validationLayers : validationLayerPriorityList) - { - if (ValidateLayers(validationLayers, supported_instance_layers)) - { - return validationLayers; - } - } - - // Else return nothing - return {}; - } - VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsMessengerCallback( VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT message_type, @@ -2292,16 +2257,48 @@ using namespace vulkan_internal; wi::vector extensionNames_sdl(extensionCount); SDL_Vulkan_GetInstanceExtensions(window, &extensionCount, extensionNames_sdl.data()); instanceExtensions.reserve(instanceExtensions.size() + extensionNames_sdl.size()); - instanceExtensions.insert(instanceExtensions.begin(), - extensionNames_sdl.cbegin(), extensionNames_sdl.cend()); + for (auto& x : extensionNames_sdl) + { + instanceExtensions.push_back(x); + } } #endif // _WIN32 if (debuglayer) { // Determine the optimal validation layers to enable that are necessary for useful debugging - wi::vector optimalValidationLyers = GetOptimalValidationLayers(availableInstanceLayers); - instanceLayers.insert(instanceLayers.end(), optimalValidationLyers.begin(), optimalValidationLyers.end()); + static const wi::vector validationLayerPriorityList[] = + { + // The preferred validation layer is "VK_LAYER_KHRONOS_validation" + {"VK_LAYER_KHRONOS_validation"}, + + // Otherwise we fallback to using the LunarG meta layer + {"VK_LAYER_LUNARG_standard_validation"}, + + // Otherwise we attempt to enable the individual layers that compose the LunarG meta layer since it doesn't exist + { + "VK_LAYER_GOOGLE_threading", + "VK_LAYER_LUNARG_parameter_validation", + "VK_LAYER_LUNARG_object_tracker", + "VK_LAYER_LUNARG_core_validation", + "VK_LAYER_GOOGLE_unique_objects", + }, + + // Otherwise as a last resort we fallback to attempting to enable the LunarG core layer + {"VK_LAYER_LUNARG_core_validation"} + }; + + for (auto& validationLayers : validationLayerPriorityList) + { + if (ValidateLayers(validationLayers, availableInstanceLayers)) + { + for (auto& x : validationLayers) + { + instanceLayers.push_back(x); + } + break; + } + } } // Create instance: diff --git a/WickedEngine/wiHelper.cpp b/WickedEngine/wiHelper.cpp index f1ac9ef33..dd5553725 100644 --- a/WickedEngine/wiHelper.cpp +++ b/WickedEngine/wiHelper.cpp @@ -17,6 +17,7 @@ extern basist::etc1_global_selector_codebook g_basis_global_codebook; #include #include // string conversion #include +#include #ifdef _WIN32 #include @@ -568,7 +569,8 @@ namespace wi::helper std::filesystem::create_directories(path); } - bool FileRead(const std::string& fileName, wi::vector& data) + template typename vector_interface> + bool FileRead_Impl(const std::string& fileName, vector_interface>& data) { #ifndef PLATFORM_UWP #ifdef SDL_FILESYSTEM_UNIX @@ -644,6 +646,16 @@ namespace wi::helper wi::backlog::post("File not found: " + fileName); return false; } + bool FileRead(const std::string& fileName, wi::vector& data) + { + return FileRead_Impl(fileName, data); + } +#if WI_VECTOR_TYPE + bool FileRead(const std::string& fileName, std::vector& data) + { + return FileRead_Impl(fileName, data); + } +#endif // WI_VECTOR_TYPE bool FileWrite(const std::string& fileName, const uint8_t* data, size_t size) { @@ -898,7 +910,7 @@ namespace wi::helper std::cerr << message << std::endl; } - wi::vector extensions = {params.description, ""}; + std::vector extensions = {params.description, ""}; for (auto& x : params.extensions) { extensions[1] += "*." + x + " "; @@ -906,7 +918,7 @@ namespace wi::helper switch (params.type) { case FileDialogParams::OPEN: { - wi::vector selection = pfd::open_file( + std::vector selection = pfd::open_file( "Open file", std::filesystem::current_path().string(), extensions diff --git a/WickedEngine/wiHelper.h b/WickedEngine/wiHelper.h index 66f91f58b..577ed798c 100644 --- a/WickedEngine/wiHelper.h +++ b/WickedEngine/wiHelper.h @@ -6,6 +6,13 @@ #include #include +#if WI_VECTOR_TYPE +namespace std +{ + template < typename, typename > class vector; +} +#endif // WI_VECTOR_TYPE + namespace wi::helper { template @@ -74,6 +81,11 @@ namespace wi::helper bool FileRead(const std::string& fileName, wi::vector& data); +#if WI_VECTOR_TYPE + // This version is provided if std::vector != wi::vector + bool FileRead(const std::string& fileName, std::vector& data); +#endif // WI_VECTOR_TYPE + bool FileWrite(const std::string& fileName, const uint8_t* data, size_t size); bool FileExists(const std::string& fileName); diff --git a/WickedEngine/wiImage.cpp b/WickedEngine/wiImage.cpp index 312243643..f0c53d05c 100644 --- a/WickedEngine/wiImage.cpp +++ b/WickedEngine/wiImage.cpp @@ -7,8 +7,6 @@ #include "wiEventHandler.h" #include "wiTimer.h" -#include - using namespace wi::graphics; using namespace wi::enums; @@ -31,8 +29,6 @@ namespace wi::image Texture backgroundTextures[COMMANDLIST_COUNT]; wi::Canvas canvases[COMMANDLIST_COUNT]; - std::atomic_bool initialized{ false }; - void SetBackground(const Texture& texture, CommandList cmd) { backgroundTextures[cmd] = texture; @@ -45,11 +41,6 @@ namespace wi::image void Draw(const Texture* texture, const Params& params, CommandList cmd) { - if (!initialized.load()) - { - return; - } - GraphicsDevice* device = wi::graphics::GetDevice(); device->EventBegin("Image", cmd); @@ -428,7 +419,6 @@ namespace wi::image LoadShaders(); wi::backlog::post("wi::image Initialized (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); - initialized.store(true); } } diff --git a/WickedEngine/wiInitializer.cpp b/WickedEngine/wiInitializer.cpp index 148aae85c..690933464 100644 --- a/WickedEngine/wiInitializer.cpp +++ b/WickedEngine/wiInitializer.cpp @@ -3,12 +3,14 @@ #include #include +#include namespace wi::initializer { bool initializationStarted = false; wi::jobsystem::context ctx; wi::Timer timer; + static std::atomic_bool systems[INITIALIZED_SYSTEM_COUNT]{}; void InitializeComponentsImmediate() { @@ -25,12 +27,8 @@ namespace wi::initializer ss += "\n[wi::initializer] Initializing Wicked Engine, please wait...\n"; ss += "Version: "; ss += wi::version::GetVersionString(); - ss += "\n"; wi::backlog::post(ss); - wi::jobsystem::Initialize(); - wi::shadercompiler::Initialize(); - size_t shaderdump_count = wi::renderer::GetShaderDumpCount(); if (shaderdump_count > 0) { @@ -38,22 +36,24 @@ namespace wi::initializer } wi::backlog::post(""); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::font::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::image::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::input::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::renderer::Initialize(); wi::gui::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::audio::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::network::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::texturehelper::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::HairParticleSystem::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::EmittedParticleSystem::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::Ocean::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::gpusortlib::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::GPUBVH::Initialize(); }); - wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::physics::Initialize(); }); + wi::jobsystem::Initialize(); + + wi::backlog::post(""); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::font::Initialize(); systems[INITIALIZED_SYSTEM_FONT].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::image::Initialize(); systems[INITIALIZED_SYSTEM_IMAGE].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::input::Initialize(); systems[INITIALIZED_SYSTEM_INPUT].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::renderer::Initialize(); systems[INITIALIZED_SYSTEM_RENDERER].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::texturehelper::Initialize(); systems[INITIALIZED_SYSTEM_TEXTUREHELPER].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::HairParticleSystem::Initialize(); systems[INITIALIZED_SYSTEM_HAIRPARTICLESYSTEM].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::EmittedParticleSystem::Initialize(); systems[INITIALIZED_SYSTEM_EMITTEDPARTICLESYSTEM].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::Ocean::Initialize(); systems[INITIALIZED_SYSTEM_OCEAN].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::gpusortlib::Initialize(); systems[INITIALIZED_SYSTEM_GPUSORTLIB].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::GPUBVH::Initialize(); systems[INITIALIZED_SYSTEM_GPUBVH].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::physics::Initialize(); systems[INITIALIZED_SYSTEM_PHYSICS].store(true); }); + wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { wi::audio::Initialize(); systems[INITIALIZED_SYSTEM_AUDIO].store(true); }); // Initialize this immediately: - wi::lua::Initialize(); + wi::lua::Initialize(); systems[INITIALIZED_SYSTEM_LUA].store(true); std::thread([] { wi::jobsystem::Wait(ctx); @@ -62,8 +62,15 @@ namespace wi::initializer } - bool IsInitializeFinished() + bool IsInitializeFinished(INITIALIZED_SYSTEM system) { - return initializationStarted && !wi::jobsystem::IsBusy(ctx); + if (system == INITIALIZED_SYSTEM_COUNT) + { + return initializationStarted && !wi::jobsystem::IsBusy(ctx); + } + else + { + return systems[system].load(); + } } } diff --git a/WickedEngine/wiInitializer.h b/WickedEngine/wiInitializer.h index 62e651cb2..b0cfef1c0 100644 --- a/WickedEngine/wiInitializer.h +++ b/WickedEngine/wiInitializer.h @@ -2,10 +2,30 @@ namespace wi::initializer { + enum INITIALIZED_SYSTEM + { + INITIALIZED_SYSTEM_FONT, + INITIALIZED_SYSTEM_IMAGE, + INITIALIZED_SYSTEM_INPUT, + INITIALIZED_SYSTEM_RENDERER, + INITIALIZED_SYSTEM_TEXTUREHELPER, + INITIALIZED_SYSTEM_HAIRPARTICLESYSTEM, + INITIALIZED_SYSTEM_EMITTEDPARTICLESYSTEM, + INITIALIZED_SYSTEM_OCEAN, + INITIALIZED_SYSTEM_GPUSORTLIB, + INITIALIZED_SYSTEM_GPUBVH, + INITIALIZED_SYSTEM_PHYSICS, + INITIALIZED_SYSTEM_LUA, + INITIALIZED_SYSTEM_AUDIO, + + INITIALIZED_SYSTEM_COUNT + }; + // Initializes systems and blocks CPU until it is complete void InitializeComponentsImmediate(); // Begins initializing systems, but doesn't block CPU. Check completion status with IsInitializeFinished() void InitializeComponentsAsync(); // Check if systems have been initialized or not - bool IsInitializeFinished(); + // system : specify to check a specific system, or leave default to check all systems + bool IsInitializeFinished(INITIALIZED_SYSTEM system = INITIALIZED_SYSTEM_COUNT); } diff --git a/WickedEngine/wiJobSystem.cpp b/WickedEngine/wiJobSystem.cpp index b0051fa8c..837c489c2 100644 --- a/WickedEngine/wiJobSystem.cpp +++ b/WickedEngine/wiJobSystem.cpp @@ -126,15 +126,19 @@ namespace wi::jobsystem return false; } - void Initialize() + void Initialize(uint32_t maxThreadCount) { + if (internal_state.numThreads > 0) + return; + maxThreadCount = std::max(1u, maxThreadCount); + wi::Timer timer; // Retrieve the number of hardware threads in this system: internal_state.numCores = std::thread::hardware_concurrency(); // Calculate the actual number of worker threads we want (-1 main thread): - internal_state.numThreads = std::max(1u, internal_state.numCores - 1); + internal_state.numThreads = std::min(maxThreadCount, std::max(1u, internal_state.numCores - 1)); for (uint32_t threadID = 0; threadID < internal_state.numThreads; ++threadID) { @@ -151,7 +155,7 @@ namespace wi::jobsystem } } - }); + }); #ifdef _WIN32 // Do Windows-specific thread setup: @@ -167,28 +171,28 @@ namespace wi::jobsystem //assert(priority_result != 0); // Name the thread: - std::wstring wthreadname = L"wi::jobsystem_" + std::to_wstring(threadID); + std::wstring wthreadname = L"wi::jobsystem_" + std::to_wstring(threadID); HRESULT hr = SetThreadDescription(handle, wthreadname.c_str()); assert(SUCCEEDED(hr)); #elif defined(PLATFORM_LINUX) #define handle_error_en(en, msg) \ do { errno = en; perror(msg); } while (0) - int ret; - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - size_t cpusetsize = sizeof (cpuset); + int ret; + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + size_t cpusetsize = sizeof(cpuset); - CPU_SET(threadID, &cpuset); - ret = pthread_setaffinity_np(worker.native_handle(), cpusetsize, &cpuset); - if(ret != 0) - handle_error_en(ret, std::string(" pthread_setaffinity_np[" + std::to_string(threadID) + ']').c_str()); + CPU_SET(threadID, &cpuset); + ret = pthread_setaffinity_np(worker.native_handle(), cpusetsize, &cpuset); + if (ret != 0) + handle_error_en(ret, std::string(" pthread_setaffinity_np[" + std::to_string(threadID) + ']').c_str()); - // Name the thread - std::string thread_name = "wi::jobsystem_" + std::to_string(threadID); - ret = pthread_setname_np(worker.native_handle(), thread_name.c_str()); - if(ret != 0) - handle_error_en(ret, std::string(" pthread_setname_np[" + std::to_string(threadID) + ']').c_str()); + // Name the thread + std::string thread_name = "wi::jobsystem_" + std::to_string(threadID); + ret = pthread_setname_np(worker.native_handle(), thread_name.c_str()); + if (ret != 0) + handle_error_en(ret, std::string(" pthread_setname_np[" + std::to_string(threadID) + ']').c_str()); #undef handle_error_en #endif // _WIN32 diff --git a/WickedEngine/wiJobSystem.h b/WickedEngine/wiJobSystem.h index c365ec6c3..4e8237fdc 100644 --- a/WickedEngine/wiJobSystem.h +++ b/WickedEngine/wiJobSystem.h @@ -5,6 +5,8 @@ namespace wi::jobsystem { + void Initialize(uint32_t maxThreadCount = ~0u); + struct JobArgs { uint32_t jobIndex; // job index relative to dispatch (like SV_DispatchThreadID in HLSL) @@ -15,8 +17,6 @@ namespace wi::jobsystem void* sharedmemory; // stack memory shared within the current group (jobs within a group execute serially) }; - void Initialize(); - uint32_t GetThreadCount(); // Defines a state of execution, can be waited on diff --git a/WickedEngine/wiLua.cpp b/WickedEngine/wiLua.cpp index 7e23ba369..1bbcb5eb0 100644 --- a/WickedEngine/wiLua.cpp +++ b/WickedEngine/wiLua.cpp @@ -25,10 +25,9 @@ #include -#define WILUA_ERROR_PREFIX "[Lua Error] " - namespace wi::lua { + static const char* WILUA_ERROR_PREFIX = "[Lua Error] "; struct LuaInternal { lua_State* m_luaState = NULL; diff --git a/WickedEngine/wiNetwork.h b/WickedEngine/wiNetwork.h index 43534081f..9c04d206a 100644 --- a/WickedEngine/wiNetwork.h +++ b/WickedEngine/wiNetwork.h @@ -19,8 +19,6 @@ namespace wi::network uint16_t port = DEFAULT_PORT; }; - void Initialize(); - // Creates a socket that can be used to send or receive data bool CreateSocket(Socket* sock); diff --git a/WickedEngine/wiNetwork_Linux.cpp b/WickedEngine/wiNetwork_Linux.cpp index f4edd291a..edd41935e 100644 --- a/WickedEngine/wiNetwork_Linux.cpp +++ b/WickedEngine/wiNetwork_Linux.cpp @@ -38,15 +38,6 @@ namespace wi::network return static_cast(param->internal_state.get()); } - void Initialize() - { - wi::Timer timer; - - int result; - - wi::backlog::post("wi::network_Linux Initialized (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); - } - bool CreateSocket(Socket* sock) { std::shared_ptr socketinternal = std::make_shared(); diff --git a/WickedEngine/wiNetwork_UWP.cpp b/WickedEngine/wiNetwork_UWP.cpp index c77fd985e..d4e7dcbd6 100644 --- a/WickedEngine/wiNetwork_UWP.cpp +++ b/WickedEngine/wiNetwork_UWP.cpp @@ -6,11 +6,6 @@ namespace wi::network { - void Initialize() - { - wi::backlog::post("TODO wi::network_UWP"); - } - bool CreateSocket(Socket* sock) { return false; diff --git a/WickedEngine/wiNetwork_Windows.cpp b/WickedEngine/wiNetwork_Windows.cpp index 6f95dff7b..9b5601a82 100644 --- a/WickedEngine/wiNetwork_Windows.cpp +++ b/WickedEngine/wiNetwork_Windows.cpp @@ -16,12 +16,32 @@ namespace wi::network { WSAData wsadata; + NetworkInternal() + { + wi::Timer timer; + + int result; + + result = WSAStartup(MAKEWORD(2, 2), &wsadata); + if (result) + { + int error = WSAGetLastError(); + wi::backlog::post("wi::network Initialization FAILED with error: " + std::to_string(error)); + assert(0); + } + + wi::backlog::post("wi::network Initialized (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); + } ~NetworkInternal() { WSACleanup(); } }; - std::shared_ptr networkinternal; + inline std::shared_ptr& network_internal() + { + static std::shared_ptr internal_state = std::make_shared(); + return internal_state; + } struct SocketInternal { @@ -43,29 +63,10 @@ namespace wi::network return static_cast(param->internal_state.get()); } - void Initialize() - { - wi::Timer timer; - - int result; - - networkinternal = std::make_shared(); - - result = WSAStartup(MAKEWORD(2, 2), &networkinternal->wsadata); - if (result) - { - int error = WSAGetLastError(); - wi::backlog::post("wi::network Initialization FAILED with error: " + std::to_string(error)); - assert(0); - } - - wi::backlog::post("wi::network Initialized (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); - } - bool CreateSocket(Socket* sock) { std::shared_ptr socketinternal = std::make_shared(); - socketinternal->networkinternal = networkinternal; + socketinternal->networkinternal = network_internal(); sock->internal_state = socketinternal; socketinternal->handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); diff --git a/WickedEngine/wiPhysics_Bullet.cpp b/WickedEngine/wiPhysics_Bullet.cpp index b45643824..5d5e8ff37 100644 --- a/WickedEngine/wiPhysics_Bullet.cpp +++ b/WickedEngine/wiPhysics_Bullet.cpp @@ -31,8 +31,8 @@ namespace wi::physics btSoftBodyRigidBodyCollisionConfiguration collisionConfiguration; btDbvtBroadphase overlappingPairCache; btSequentialImpulseConstraintSolver solver; - std::unique_ptr dispatcher; - std::unique_ptr dynamicsWorld; + btCollisionDispatcher dispatcher(&collisionConfiguration); + btSoftRigidDynamicsWorld dynamicsWorld(&dispatcher, &overlappingPairCache, &solver, &collisionConfiguration); class DebugDraw : public btIDebugDraw { @@ -68,17 +68,13 @@ namespace wi::physics { wi::Timer timer; - dispatcher = std::make_unique(&collisionConfiguration); - dynamicsWorld = std::make_unique(dispatcher.get(), &overlappingPairCache, &solver, &collisionConfiguration); + dynamicsWorld.getSolverInfo().m_solverMode |= SOLVER_RANDMIZE_ORDER; + dynamicsWorld.getDispatchInfo().m_enableSatConvex = true; + dynamicsWorld.getSolverInfo().m_splitImpulse = true; + dynamicsWorld.setGravity(gravity); + dynamicsWorld.setDebugDrawer(&debugDraw); - dynamicsWorld->getSolverInfo().m_solverMode |= SOLVER_RANDMIZE_ORDER; - dynamicsWorld->getDispatchInfo().m_enableSatConvex = true; - dynamicsWorld->getSolverInfo().m_splitImpulse = true; - - dynamicsWorld->setGravity(gravity); - - btSoftRigidDynamicsWorld* softRigidWorld = (btSoftRigidDynamicsWorld*)dynamicsWorld.get(); - btSoftBodyWorldInfo& softWorldInfo = softRigidWorld->getWorldInfo(); + btSoftBodyWorldInfo& softWorldInfo = dynamicsWorld.getWorldInfo(); softWorldInfo.air_density = btScalar(1.2f); softWorldInfo.water_density = 0; softWorldInfo.water_offset = 0; @@ -86,8 +82,6 @@ namespace wi::physics softWorldInfo.m_gravity.setValue(gravity.x(), gravity.y(), gravity.z()); softWorldInfo.m_sparsesdf.Initialize(); - softRigidWorld->setDebugDrawer(&debugDraw); - wi::backlog::post("wi::physics Initialized [Bullet] (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); } @@ -232,7 +226,7 @@ namespace wi::physics rigidbody->setActivationState(DISABLE_DEACTIVATION); } - dynamicsWorld->addRigidBody(rigidbody); + dynamicsWorld.addRigidBody(rigidbody); physicscomponent.physicsobject = rigidbody; } } @@ -269,7 +263,7 @@ namespace wi::physics } btSoftBody* softbody = btSoftBodyHelpers::CreateFromTriMesh( - ((btSoftRigidDynamicsWorld*)dynamicsWorld.get())->getWorldInfo() + dynamicsWorld.getWorldInfo() , btVerts , btInd , tCount @@ -328,7 +322,7 @@ namespace wi::physics softbody->setPose(true, true); - ((btSoftRigidDynamicsWorld*)dynamicsWorld.get())->addSoftBody(softbody); + dynamicsWorld.addSoftBody(softbody); physicscomponent.physicsobject = softbody; } } @@ -432,7 +426,7 @@ namespace wi::physics physicscomponent._flags &= ~SoftBodyPhysicsComponent::FORCE_RESET; if (physicscomponent.physicsobject != nullptr) { - ((btSoftRigidDynamicsWorld*)dynamicsWorld.get())->removeSoftBody((btSoftBody*)physicscomponent.physicsobject); + dynamicsWorld.removeSoftBody((btSoftBody*)physicscomponent.physicsobject); physicscomponent.physicsobject = nullptr; } } @@ -479,13 +473,13 @@ namespace wi::physics // Perform internal simulation step: if (IsSimulationEnabled()) { - dynamicsWorld->stepSimulation(dt, ACCURACY); + dynamicsWorld.stepSimulation(dt, ACCURACY); } // Feedback physics engine state to system: - for (int i = 0; i < dynamicsWorld->getCollisionObjectArray().size(); ++i) + for (int i = 0; i < dynamicsWorld.getCollisionObjectArray().size(); ++i) { - btCollisionObject* collisionobject = dynamicsWorld->getCollisionObjectArray()[i]; + btCollisionObject* collisionobject = dynamicsWorld.getCollisionObjectArray()[i]; Entity entity = (Entity)collisionobject->getUserIndex(); btRigidBody* rigidbody = btRigidBody::upcast(collisionobject); @@ -494,7 +488,7 @@ namespace wi::physics RigidBodyPhysicsComponent* physicscomponent = scene.rigidbodies.GetComponent(entity); if (physicscomponent == nullptr || physicscomponent->physicsobject != rigidbody) { - dynamicsWorld->removeRigidBody(rigidbody); + dynamicsWorld.removeRigidBody(rigidbody); i--; continue; } @@ -525,7 +519,7 @@ namespace wi::physics SoftBodyPhysicsComponent* physicscomponent = scene.softbodies.GetComponent(entity); if (physicscomponent == nullptr || physicscomponent->physicsobject != softbody) { - ((btSoftRigidDynamicsWorld*)dynamicsWorld.get())->removeSoftBody(softbody); + dynamicsWorld.removeSoftBody(softbody); i--; continue; } @@ -634,7 +628,7 @@ namespace wi::physics if (IsDebugDrawEnabled()) { - dynamicsWorld->debugDrawWorld(); + dynamicsWorld.debugDrawWorld(); } wi::profiler::EndRange(range); // Physics diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 726433dd9..fdac8b9a0 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -40,10 +40,10 @@ namespace wi::scene struct LayerComponent { - uint32_t layerMask = ~0; + uint32_t layerMask = ~0u; // Non-serialized attributes: - uint32_t propagationMask = ~0; // This shouldn't be modified by user usually + uint32_t propagationMask = ~0u; // This shouldn't be modified by user usually inline uint32_t GetLayerMask() const { return layerMask & propagationMask; } @@ -647,7 +647,7 @@ namespace wi::scene int prev_transform_index = -1; // occlusion result history bitfield (32 bit->32 frame history) - mutable uint32_t occlusionHistory = ~0; + mutable uint32_t occlusionHistory = ~0u; mutable int occlusionQueries[wi::graphics::GraphicsDevice::GetBufferCount() + 1]; inline bool IsOccluded() const @@ -1147,7 +1147,7 @@ namespace wi::scene std::string colorGradingMapName; // Non-serialized attributes: - uint32_t most_important_light_index = ~0; + uint32_t most_important_light_index = ~0u; wi::Resource skyMap; wi::Resource colorGradingMap; @@ -1192,7 +1192,7 @@ namespace wi::scene uint32_t _flags = EMPTY; wi::ecs::Entity target = wi::ecs::INVALID_ENTITY; // which entity to follow (must have a transform component) - uint32_t chain_length = ~0; // ~0 means: compute until the root + uint32_t chain_length = ~0u; // ~0 means: compute until the root uint32_t iteration_count = 1; inline void SetDisabled(bool value = true) { if (value) { _flags |= DISABLED; } else { _flags &= ~DISABLED; } } diff --git a/WickedEngine/wiShaderCompiler.cpp b/WickedEngine/wiShaderCompiler.cpp index 19413775a..c62f22be4 100644 --- a/WickedEngine/wiShaderCompiler.cpp +++ b/WickedEngine/wiShaderCompiler.cpp @@ -33,14 +33,85 @@ using namespace wi::graphics; namespace wi::shadercompiler { + struct InternalState + { +#ifdef SHADERCOMPILER_ENABLED_DXCOMPILER + CComPtr dxcUtils; + CComPtr dxcCompiler; + CComPtr dxcIncludeHandler; + DxcCreateInstanceProc DxcCreateInstance = nullptr; +#endif // SHADERCOMPILER_ENABLED_DXCOMPILER + +#ifdef SHADERCOMPILER_ENABLED_D3DCOMPILER + using PFN_D3DCOMPILE = decltype(&D3DCompile); + PFN_D3DCOMPILE D3DCompile = nullptr; +#endif // SHADERCOMPILER_ENABLED_D3DCOMPILER + + InternalState() + { +#ifdef SHADERCOMPILER_ENABLED_DXCOMPILER + if (dxcCompiler != nullptr) + { + return; // already initialized + } + +#ifdef _WIN32 +#define LIBDXCOMPILER "dxcompiler.dll" + HMODULE dxcompiler = wiLoadLibrary(LIBDXCOMPILER); +#elif defined(PLATFORM_LINUX) +#define LIBDXCOMPILER "libdxcompiler.so" + HMODULE dxcompiler = wiLoadLibrary("./" LIBDXCOMPILER); +#endif + if (dxcompiler != nullptr) + { + DxcCreateInstance = (DxcCreateInstanceProc)wiGetProcAddress(dxcompiler, "DxcCreateInstance"); + if (DxcCreateInstance != nullptr) + { + HRESULT hr = DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&dxcUtils)); + assert(SUCCEEDED(hr)); + hr = DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxcCompiler)); + assert(SUCCEEDED(hr)); + hr = dxcUtils->CreateDefaultIncludeHandler(&dxcIncludeHandler); + assert(SUCCEEDED(hr)); + wi::backlog::post("wi::shadercompiler: loaded " LIBDXCOMPILER); + } + } + else + { + wi::backlog::post("wi::shadercompiler: could not load library " LIBDXCOMPILER); + } +#endif // SHADERCOMPILER_ENABLED_DXCOMPILER + + +#ifdef SHADERCOMPILER_ENABLED_D3DCOMPILER + if (D3DCompile != nullptr) + { + return; // already initialized + } + + HMODULE d3dcompiler = wiLoadLibrary("d3dcompiler_47.dll"); + if (d3dcompiler != nullptr) + { + D3DCompile = (PFN_D3DCOMPILE)wiGetProcAddress(d3dcompiler, "D3DCompile"); + if (D3DCompile != nullptr) + { + wi::backlog::post("wi::shadercompiler: loaded d3dcompiler_47.dll"); + } + } +#endif // SHADERCOMPILER_ENABLED_D3DCOMPILER + + } + }; + inline InternalState& compiler_internal() + { + static InternalState internal_state; + return internal_state; + } + #ifdef SHADERCOMPILER_ENABLED_DXCOMPILER - CComPtr dxcUtils; - CComPtr dxcCompiler; - CComPtr dxcIncludeHandler; - DxcCreateInstanceProc DxcCreateInstance = nullptr; void Compile_DXCompiler(const CompilerInput& input, CompilerOutput& output) { - if (dxcCompiler == nullptr) + if (compiler_internal().dxcCompiler == nullptr) { return; } @@ -360,7 +431,7 @@ namespace wi::shadercompiler _COM_Outptr_result_maybenull_ IDxcBlob** ppIncludeSource // Resultant source object for included file, nullptr if not found. ) override { - HRESULT hr = dxcIncludeHandler->LoadSource(pFilename, ppIncludeSource); + HRESULT hr = compiler_internal().dxcIncludeHandler->LoadSource(pFilename, ppIncludeSource); if (SUCCEEDED(hr)) { std::string& filename = output->dependencies.emplace_back(); @@ -372,7 +443,7 @@ namespace wi::shadercompiler /* [in] */ REFIID riid, /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject) override { - return dxcIncludeHandler->QueryInterface(riid, ppvObject); + return compiler_internal().dxcIncludeHandler->QueryInterface(riid, ppvObject); } ULONG STDMETHODCALLTYPE AddRef(void) override @@ -388,7 +459,7 @@ namespace wi::shadercompiler includehandler.output = &output; CComPtr pResults; - HRESULT hr = dxcCompiler->Compile( + HRESULT hr = compiler_internal().dxcCompiler->Compile( &Source, // Source buffer. args.data(), // Array of pointers to arguments. (uint32_t)args.size(), // Number of arguments. @@ -446,11 +517,9 @@ namespace wi::shadercompiler #endif // SHADERCOMPILER_ENABLED_DXCOMPILER #ifdef SHADERCOMPILER_ENABLED_D3DCOMPILER - using PFN_D3DCOMPILE = decltype(&D3DCompile); - PFN_D3DCOMPILE D3DCompile = nullptr; void Compile_D3DCompiler(const CompilerInput& input, CompilerOutput& output) { - if (D3DCompile == nullptr) + if (compiler_internal().D3DCompile == nullptr) { return; } @@ -537,7 +606,7 @@ namespace wi::shadercompiler // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/d3dcompile-constants UINT Flags1 = 0; - if (input.flags & FLAG_DISABLE_OPTIMIZATION) + if (has_flag(input.flags, Flags::DISABLE_OPTIMIZATION)) { Flags1 |= D3DCOMPILE_SKIP_OPTIMIZATION; } @@ -545,7 +614,7 @@ namespace wi::shadercompiler CComPtr code; CComPtr errors; - HRESULT hr = D3DCompile( + HRESULT hr = compiler_internal().D3DCompile( shadersourcedata.data(), shadersourcedata.size(), input.shadersourcefilename.c_str(), @@ -578,60 +647,6 @@ namespace wi::shadercompiler } #endif // SHADERCOMPILER_ENABLED_D3DCOMPILER - void Initialize() - { -#ifdef SHADERCOMPILER_ENABLED_DXCOMPILER - if (dxcCompiler != nullptr) - { - return; // already initialized - } - -#ifdef _WIN32 -#define LIBDXCOMPILER "dxcompiler.dll" - HMODULE dxcompiler = wiLoadLibrary(LIBDXCOMPILER); -#elif defined(PLATFORM_LINUX) -#define LIBDXCOMPILER "libdxcompiler.so" - HMODULE dxcompiler = wiLoadLibrary("./" LIBDXCOMPILER); -#endif - if(dxcompiler != nullptr) - { - DxcCreateInstance = (DxcCreateInstanceProc)wiGetProcAddress(dxcompiler, "DxcCreateInstance"); - if (DxcCreateInstance != nullptr) - { - HRESULT hr = DxcCreateInstance(CLSID_DxcUtils, IID_PPV_ARGS(&dxcUtils)); - assert(SUCCEEDED(hr)); - hr = DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxcCompiler)); - assert(SUCCEEDED(hr)); - hr = dxcUtils->CreateDefaultIncludeHandler(&dxcIncludeHandler); - assert(SUCCEEDED(hr)); - wi::backlog::post("wi::shadercompiler: loaded " LIBDXCOMPILER); - } - } - else - { - wi::backlog::post("wi::shadercompiler: could not load library " LIBDXCOMPILER); - } -#endif // SHADERCOMPILER_ENABLED_DXCOMPILER - -#ifdef SHADERCOMPILER_ENABLED_D3DCOMPILER - if (D3DCompile != nullptr) - { - return; // already initialized - } - - HMODULE d3dcompiler = wiLoadLibrary("d3dcompiler_47.dll"); - if(d3dcompiler != nullptr) - { - D3DCompile = (PFN_D3DCOMPILE)wiGetProcAddress(d3dcompiler, "D3DCompile"); - if (D3DCompile != nullptr) - { - wi::backlog::post("wi::shadercompiler: loaded d3dcompiler_47.dll"); - } - } -#endif // SHADERCOMPILER_ENABLED_D3DCOMPILER - - } - void Compile(const CompilerInput& input, CompilerOutput& output) { output = CompilerOutput(); @@ -659,7 +674,7 @@ namespace wi::shadercompiler #endif // SHADERCOMPILER_ENABLED } - static constexpr const char* shadermetaextension = "wishadermeta"; + constexpr const char* shadermetaextension = "wishadermeta"; bool SaveShaderAndMetadata(const std::string& shaderfilename, const CompilerOutput& output) { #ifdef SHADERCOMPILER_ENABLED diff --git a/WickedEngine/wiShaderCompiler.h b/WickedEngine/wiShaderCompiler.h index c7f1b0005..d4401dec1 100644 --- a/WickedEngine/wiShaderCompiler.h +++ b/WickedEngine/wiShaderCompiler.h @@ -6,7 +6,6 @@ namespace wi::shadercompiler { - void Initialize(); enum class Flags { diff --git a/WickedEngine/wiSpriteFont.cpp b/WickedEngine/wiSpriteFont.cpp index 803ed5133..dde2bbb20 100644 --- a/WickedEngine/wiSpriteFont.cpp +++ b/WickedEngine/wiSpriteFont.cpp @@ -47,7 +47,7 @@ namespace wi } void SpriteFont::SetText(std::wstring&& value) { - text = value; + text = std::move(value); } std::string SpriteFont::GetTextA() const diff --git a/WickedEngine/wiVector.h b/WickedEngine/wiVector.h index 74c03c448..3668172bc 100644 --- a/WickedEngine/wiVector.h +++ b/WickedEngine/wiVector.h @@ -2,12 +2,299 @@ #define WI_VECTOR_REPLACEMENT // This file is used to allow replacement of std::vector +#ifndef WI_VECTOR_TYPE +#define WI_VECTOR_TYPE 0 +#endif // WI_VECTOR_TYPE + +#if WI_VECTOR_TYPE == 1 +#include +#include +#include +#include +#include +#include +#else #include +#endif // WI_VECTOR_TYPE namespace wi { - template - using vector = std::vector; + template> +#if WI_VECTOR_TYPE == 0 + using vector = std::vector; +#elif WI_VECTOR_TYPE == 1 + class vector + { + public: + using value_type = T; + + inline vector(size_t size = 0) + { + resize(size); + } + inline vector(const vector& other) + { + copy_from(other); + } + inline vector(vector&& other) noexcept + { + move_from(std::move(other)); + } + inline vector(std::initializer_list init) + { + reserve(init.size()); + for (auto& x : init) + { + push_back(x); + } + } + inline ~vector() + { + clear(); // need to destroy objects, not just deallocate! + if (m_data != nullptr) + { + m_allocator.deallocate(m_data, m_capacity); + } + } + inline vector& operator=(const vector& other) + { + copy_from(other); + return *this; + } + inline vector& operator=(vector&& other) + { + move_from(std::move(other)); + return *this; + } + constexpr T& operator[](size_t index) noexcept + { + assert(m_size > 0 && index < m_size); + return m_data[index]; + } + constexpr const T& operator[](size_t index) const noexcept + { + assert(m_size > 0 && index < m_size); + return m_data[index]; + } + + inline void reserve(size_t amount) + { + if (amount > m_capacity) + { + size_t old_capacity = m_capacity; + T* old_data = data_allocate(amount); + if (old_data != nullptr) + { + m_allocator.deallocate(old_data, old_capacity); + } + } + } + inline void resize(size_t amount) + { + if (amount > m_size) + { + // expand + reserve(amount); + // Construct elements with placement new: + for (size_t i = m_size; i < amount; ++i) + { + new (m_data + i) T(); + } + m_size = amount; + } + else if (amount < m_size) + { + // shrink + while (m_size > amount) + { + pop_back(); + } + } + } + inline void shrink_to_fit() + { + if (m_capacity > m_size) + { + size_t old_capacity = m_capacity; + T* old_data = data_allocate(m_size); + if (old_data != nullptr) + { + m_allocator.deallocate(old_data, old_capacity); + } + } + } + + template + inline T& emplace_back(ARG&&... args) + { + size_t old_capacity = m_capacity; + T* old_data = nullptr; + const size_t required_capacity = m_size + 1; + if (required_capacity > m_capacity) + { + old_data = data_allocate(required_capacity * 2); // *2: faster grow rate + } + + // Allocation is separate from construction, this will call object constructor: + T* ptr = new (m_data + m_size) T(std::forward(args)...); + m_size++; + + // Iterator invalidation can only happen after the new item was constructed, + // because the call stack might still contain references to the old data + if (old_data != nullptr) + { + m_allocator.deallocate(old_data, old_capacity); + } + return *ptr; + } + inline void push_back(const T& item) + { + emplace_back(item); + } + inline void push_back(T&& item) + { + emplace_back(std::move(item)); + } + + constexpr void clear() noexcept + { + for (size_t i = 0; i < m_size; ++i) + { + m_data[i].~T(); + } + m_size = 0; + } + constexpr void pop_back() noexcept + { + assert(m_size > 0); + m_data[--m_size].~T(); + } + constexpr void erase(T* pos) noexcept + { + assert(pos >= begin()); + assert(pos < end()); + while (pos != end() - 1) + { + *pos = std::move(*(pos + 1)); + pos++; + } + pop_back(); + } + + constexpr T& back() noexcept + { + assert(m_size > 0); + return m_data[m_size - 1]; + } + constexpr const T& back() const noexcept + { + assert(m_size > 0); + return m_data[m_size - 1]; + } + constexpr T& front() noexcept + { + assert(m_size > 0); + return m_data[0]; + } + constexpr const T& front() const noexcept + { + assert(m_size > 0); + return m_data[0]; + } + constexpr T* data() noexcept + { + return m_data; + } + constexpr const T* data() const noexcept + { + return m_data; + } + constexpr T& at(size_t index) noexcept + { + assert(m_size > 0 && index < m_size); + return m_data[index]; + } + constexpr const T& at(size_t index) const noexcept + { + assert(m_size > 0 && index < m_size); + return m_data[index]; + } + constexpr size_t size() const noexcept + { + return m_size; + } + constexpr bool empty() const noexcept + { + return m_size == 0; + } + constexpr T* begin() noexcept + { + return m_data; + } + constexpr const T* begin() const noexcept + { + return m_data; + } + constexpr T* end() noexcept + { + return m_data + m_size; + } + constexpr const T* end() const noexcept + { + return m_data + m_size; + } + + private: + // returns old data ptr if allocation happened. It needs to be freed. + // This function must not free it, as iterator invalidation can't happen yet. + // References to the old data could be still on current call stack. + inline T* data_allocate(size_t amount) + { + if (amount > m_size) // allocation must always fit all existing items + { + m_capacity = amount; + // We don't use new[] because we don't want to construct every item in the capacity + // Instead, placement new is used when a new object is created in the container + // Placement new is also used to realloc existing items when reservation grows + T* allocation = m_allocator.allocate(m_capacity); + for (size_t i = 0; i < m_size; ++i) + { + new (allocation + i) T(std::move(m_data[i])); + } + std::swap(m_data, allocation); + return allocation; + } + return nullptr; + } + inline void copy_from(const vector& other) + { + resize(other.size()); + for (size_t i = 0; i < m_size; ++i) + { + m_data[i] = other.m_data[i]; + } + } + inline void move_from(vector&& other) + { + clear(); + if (m_data != nullptr) + { + m_allocator.deallocate(m_data, m_capacity); + } + m_capacity = other.m_capacity; + m_size = other.m_size; + m_data = other.m_data; + other.m_data = nullptr; + other.m_size = 0; + other.m_capacity = 0; + } + + T* m_data = nullptr; + size_t m_size = 0; + size_t m_capacity = 0; + A m_allocator; + }; +#endif // WI_VECTOR_TYPE } #endif // WI_VECTOR_REPLACEMENT diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index c7e2f502e..08bf19e30 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 60; // minor bug fixes, alterations, refactors, updates - const int revision = 1; + const int revision = 2; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision); diff --git a/WickedEngine/wickedengine.natvis b/WickedEngine/wickedengine.natvis new file mode 100644 index 000000000..27c41d766 --- /dev/null +++ b/WickedEngine/wickedengine.natvis @@ -0,0 +1,16 @@ + + + + + {{ size={m_size} }} + + m_size + m_capacity + + m_size + m_data + + + + +