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
This commit is contained in:
@@ -79,7 +79,7 @@ namespace tinygltf
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ReadWholeFile(wi::vector<unsigned char>* out, std::string* err,
|
||||
bool ReadWholeFile(std::vector<unsigned char>* out, std::string* err,
|
||||
const std::string& filepath, void*) {
|
||||
return wi::helper::FileRead(filepath, *out);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
: m_mtlBaseDir(mtl_basedir) {}
|
||||
virtual ~MaterialFileReader() {}
|
||||
virtual bool operator()(const std::string& matId,
|
||||
wi::vector<tinyobj::material_t>* materials,
|
||||
std::vector<tinyobj::material_t>* materials,
|
||||
std::map<std::string, int>* 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<tinyobj::shape_t> obj_shapes;
|
||||
wi::vector<tinyobj::material_t> obj_materials;
|
||||
std::vector<tinyobj::shape_t> obj_shapes;
|
||||
std::vector<tinyobj::material_t> obj_materials;
|
||||
std::string obj_errors;
|
||||
|
||||
wi::vector<uint8_t> filedata;
|
||||
|
||||
@@ -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: ");
|
||||
|
||||
@@ -577,7 +577,7 @@ void WeatherWindow::Create(EditorComponent* editor)
|
||||
wi::jobsystem::context ctx;
|
||||
for (auto& x : conv)
|
||||
{
|
||||
std::vector<uint8_t> filedata;
|
||||
wi::vector<uint8_t> filedata;
|
||||
if (wi::helper::saveTextureToMemory(x.second.GetTexture(), filedata))
|
||||
{
|
||||
x.second.SetFileData(std::move(filedata));
|
||||
|
||||
@@ -99,8 +99,6 @@ void Example_ImGui::Initialize()
|
||||
{
|
||||
// Compile shaders
|
||||
{
|
||||
wi::shadercompiler::Initialize();
|
||||
|
||||
auto shaderPath = wi::renderer::GetShaderSourcePath();
|
||||
wi::renderer::SetShaderSourcePath(wi::helper::GetCurrentPath() + "/");
|
||||
|
||||
|
||||
+52
-7
@@ -5,6 +5,7 @@
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
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<size_t, size_t> 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<CameraComponent> 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<CameraComponent> 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);
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ public:
|
||||
void RunFontTest();
|
||||
void RunSpriteTest();
|
||||
void RunNetworkTest();
|
||||
void RunUnorderedMapTest();
|
||||
void ContainerTest();
|
||||
};
|
||||
|
||||
class Tests : public wi::Application
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="wickedengine.natvis" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{06163DCB-B183-4ED9-9C62-13EF1658E049}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Natvis Include="wickedengine.natvis" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
+62
-64
@@ -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<AudioInternal> audio;
|
||||
static std::shared_ptr<AudioInternal> audio_internal;
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
audio_internal = std::make_shared<AudioInternal>();
|
||||
}
|
||||
|
||||
struct SoundInternal
|
||||
{
|
||||
@@ -191,18 +201,6 @@ namespace wi::audio
|
||||
return static_cast<SoundInstanceInternal*>(param->internal_state.get());
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
wi::Timer timer;
|
||||
|
||||
audio = std::make_shared<AudioInternal>();
|
||||
|
||||
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> soundinternal = std::make_shared<SoundInternal>();
|
||||
soundinternal->audio = audio;
|
||||
soundinternal->audio = audio_internal;
|
||||
sound->internal_state = soundinternal;
|
||||
|
||||
DWORD dwChunkSize;
|
||||
@@ -342,19 +340,19 @@ namespace wi::audio
|
||||
std::shared_ptr<SoundInstanceInternal> instanceinternal = std::make_shared<SoundInstanceInternal>();
|
||||
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<AudioInternal> audio;
|
||||
static std::shared_ptr<AudioInternal> audio_internal;
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
audio_internal = std::make_shared<AudioInternal>();
|
||||
}
|
||||
|
||||
struct SoundInternal{
|
||||
std::shared_ptr<AudioInternal> audio;
|
||||
@@ -694,16 +704,6 @@ namespace wi::audio
|
||||
}
|
||||
};
|
||||
|
||||
void Initialize() {
|
||||
wi::Timer timer;
|
||||
|
||||
audio = std::make_shared<AudioInternal>();
|
||||
|
||||
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<SoundInternal*>(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> soundinternal = std::make_shared<SoundInternal>();
|
||||
soundinternal->audio = audio;
|
||||
soundinternal->audio = audio_internal;
|
||||
sound->internal_state = soundinternal;
|
||||
|
||||
uint32_t dwChunkSize;
|
||||
@@ -849,12 +849,12 @@ namespace wi::audio
|
||||
std::shared_ptr<SoundInstanceInternal> instanceinternal = std::make_shared<SoundInstanceInternal>();
|
||||
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; }
|
||||
|
||||
+28
-28
@@ -21,25 +21,25 @@ using namespace wi::graphics;
|
||||
|
||||
namespace wi::backlog
|
||||
{
|
||||
static bool enabled = false;
|
||||
static std::deque<std::string> stream;
|
||||
static std::deque<std::string> history;
|
||||
static const float speed = 4000.0f;
|
||||
static const size_t deletefromline = 500;
|
||||
static float pos = std::numeric_limits<float>::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<std::string> stream;
|
||||
std::deque<std::string> history;
|
||||
const float speed = 4000.0f;
|
||||
const size_t deletefromline = 500;
|
||||
float pos = std::numeric_limits<float>::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)
|
||||
{
|
||||
|
||||
+1
-11
@@ -18,7 +18,6 @@
|
||||
#include "Utility/stb_truetype.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <atomic>
|
||||
|
||||
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<typename T>
|
||||
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;
|
||||
}
|
||||
|
||||
+38
-30
@@ -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;
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
namespace wi::gui
|
||||
{
|
||||
void Initialize();
|
||||
|
||||
class Widget;
|
||||
|
||||
class GUI
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -556,41 +556,6 @@ namespace vulkan_internal
|
||||
return true;
|
||||
}
|
||||
|
||||
wi::vector<const char*> GetOptimalValidationLayers(const wi::vector<VkLayerProperties>& supported_instance_layers)
|
||||
{
|
||||
wi::vector<wi::vector<const char*>> 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<const char *> 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<const char*> optimalValidationLyers = GetOptimalValidationLayers(availableInstanceLayers);
|
||||
instanceLayers.insert(instanceLayers.end(), optimalValidationLyers.begin(), optimalValidationLyers.end());
|
||||
static const wi::vector<const char*> 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:
|
||||
|
||||
@@ -17,6 +17,7 @@ extern basist::etc1_global_selector_codebook g_basis_global_codebook;
|
||||
#include <sstream>
|
||||
#include <codecvt> // string conversion
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
@@ -568,7 +569,8 @@ namespace wi::helper
|
||||
std::filesystem::create_directories(path);
|
||||
}
|
||||
|
||||
bool FileRead(const std::string& fileName, wi::vector<uint8_t>& data)
|
||||
template<template<typename T, typename A> typename vector_interface>
|
||||
bool FileRead_Impl(const std::string& fileName, vector_interface<uint8_t, std::allocator<uint8_t>>& 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<uint8_t>& data)
|
||||
{
|
||||
return FileRead_Impl(fileName, data);
|
||||
}
|
||||
#if WI_VECTOR_TYPE
|
||||
bool FileRead(const std::string& fileName, std::vector<uint8_t>& 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<std::string> extensions = {params.description, ""};
|
||||
std::vector<std::string> 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<std::string> selection = pfd::open_file(
|
||||
std::vector<std::string> selection = pfd::open_file(
|
||||
"Open file",
|
||||
std::filesystem::current_path().string(),
|
||||
extensions
|
||||
|
||||
@@ -6,6 +6,13 @@
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
#if WI_VECTOR_TYPE
|
||||
namespace std
|
||||
{
|
||||
template < typename, typename > class vector;
|
||||
}
|
||||
#endif // WI_VECTOR_TYPE
|
||||
|
||||
namespace wi::helper
|
||||
{
|
||||
template <class T>
|
||||
@@ -74,6 +81,11 @@ namespace wi::helper
|
||||
|
||||
bool FileRead(const std::string& fileName, wi::vector<uint8_t>& data);
|
||||
|
||||
#if WI_VECTOR_TYPE
|
||||
// This version is provided if std::vector != wi::vector
|
||||
bool FileRead(const std::string& fileName, std::vector<uint8_t>& data);
|
||||
#endif // WI_VECTOR_TYPE
|
||||
|
||||
bool FileWrite(const std::string& fileName, const uint8_t* data, size_t size);
|
||||
|
||||
bool FileExists(const std::string& fileName);
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
#include "wiEventHandler.h"
|
||||
#include "wiTimer.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -25,10 +25,9 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#define WILUA_ERROR_PREFIX "[Lua Error] "
|
||||
|
||||
namespace wi::lua
|
||||
{
|
||||
static const char* WILUA_ERROR_PREFIX = "[Lua Error] ";
|
||||
struct LuaInternal
|
||||
{
|
||||
lua_State* m_luaState = NULL;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -38,15 +38,6 @@ namespace wi::network
|
||||
return static_cast<SocketInternal*>(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> socketinternal = std::make_shared<SocketInternal>();
|
||||
|
||||
@@ -6,11 +6,6 @@
|
||||
|
||||
namespace wi::network
|
||||
{
|
||||
void Initialize()
|
||||
{
|
||||
wi::backlog::post("TODO wi::network_UWP");
|
||||
}
|
||||
|
||||
bool CreateSocket(Socket* sock)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -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> networkinternal;
|
||||
inline std::shared_ptr<NetworkInternal>& network_internal()
|
||||
{
|
||||
static std::shared_ptr<NetworkInternal> internal_state = std::make_shared<NetworkInternal>();
|
||||
return internal_state;
|
||||
}
|
||||
|
||||
struct SocketInternal
|
||||
{
|
||||
@@ -43,29 +63,10 @@ namespace wi::network
|
||||
return static_cast<SocketInternal*>(param->internal_state.get());
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
wi::Timer timer;
|
||||
|
||||
int result;
|
||||
|
||||
networkinternal = std::make_shared<NetworkInternal>();
|
||||
|
||||
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> socketinternal = std::make_shared<SocketInternal>();
|
||||
socketinternal->networkinternal = networkinternal;
|
||||
socketinternal->networkinternal = network_internal();
|
||||
sock->internal_state = socketinternal;
|
||||
|
||||
socketinternal->handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace wi::physics
|
||||
btSoftBodyRigidBodyCollisionConfiguration collisionConfiguration;
|
||||
btDbvtBroadphase overlappingPairCache;
|
||||
btSequentialImpulseConstraintSolver solver;
|
||||
std::unique_ptr<btCollisionDispatcher> dispatcher;
|
||||
std::unique_ptr<btDynamicsWorld> 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<btCollisionDispatcher>(&collisionConfiguration);
|
||||
dynamicsWorld = std::make_unique<btSoftRigidDynamicsWorld>(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
|
||||
|
||||
@@ -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; } }
|
||||
|
||||
@@ -33,14 +33,85 @@ using namespace wi::graphics;
|
||||
|
||||
namespace wi::shadercompiler
|
||||
{
|
||||
struct InternalState
|
||||
{
|
||||
#ifdef SHADERCOMPILER_ENABLED_DXCOMPILER
|
||||
CComPtr<IDxcUtils> dxcUtils;
|
||||
CComPtr<IDxcCompiler3> dxcCompiler;
|
||||
CComPtr<IDxcIncludeHandler> 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<IDxcUtils> dxcUtils;
|
||||
CComPtr<IDxcCompiler3> dxcCompiler;
|
||||
CComPtr<IDxcIncludeHandler> 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<IDxcResult> 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<ID3DBlob> code;
|
||||
CComPtr<ID3DBlob> 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
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
namespace wi::shadercompiler
|
||||
{
|
||||
void Initialize();
|
||||
|
||||
enum class Flags
|
||||
{
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace wi
|
||||
}
|
||||
void SpriteFont::SetText(std::wstring&& value)
|
||||
{
|
||||
text = value;
|
||||
text = std::move(value);
|
||||
}
|
||||
|
||||
std::string SpriteFont::GetTextA() const
|
||||
|
||||
+289
-2
@@ -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 <cassert>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <initializer_list>
|
||||
#include <new>
|
||||
#else
|
||||
#include <vector>
|
||||
#endif // WI_VECTOR_TYPE
|
||||
|
||||
namespace wi
|
||||
{
|
||||
template<typename T>
|
||||
using vector = std::vector<T>;
|
||||
template<typename T, typename A = std::allocator<T>>
|
||||
#if WI_VECTOR_TYPE == 0
|
||||
using vector = std::vector<T, A>;
|
||||
#elif WI_VECTOR_TYPE == 1
|
||||
class vector
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
inline vector(size_t size = 0)
|
||||
{
|
||||
resize(size);
|
||||
}
|
||||
inline vector(const vector<T>& other)
|
||||
{
|
||||
copy_from(other);
|
||||
}
|
||||
inline vector(vector<T>&& other) noexcept
|
||||
{
|
||||
move_from(std::move(other));
|
||||
}
|
||||
inline vector(std::initializer_list<T> 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<T>& operator=(const vector<T>& other)
|
||||
{
|
||||
copy_from(other);
|
||||
return *this;
|
||||
}
|
||||
inline vector<T>& operator=(vector<T>&& 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<typename... ARG>
|
||||
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<ARG>(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<T>& 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<T>&& 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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
|
||||
<Type Name="wi::vector<*>">
|
||||
<DisplayString>{{ size={m_size} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="[size]" ExcludeView="simple">m_size</Item>
|
||||
<Item Name="[capacity]" ExcludeView="simple">m_capacity</Item>
|
||||
<ArrayItems>
|
||||
<Size>m_size</Size>
|
||||
<ValuePointer>m_data</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
</AutoVisualizer>
|
||||
Reference in New Issue
Block a user