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:
Turánszki János
2021-12-09 18:58:27 +01:00
committed by GitHub
parent bb2fae64b0
commit c4c582d739
40 changed files with 787 additions and 403 deletions
+1 -1
View File
@@ -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);
}
+3 -3
View File
@@ -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;
+1
View File
@@ -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: ");
+1 -1
View File
@@ -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));
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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>
+2 -2
View File
@@ -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();
+1 -2
View File
@@ -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);
}
+13 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
-2
View File
@@ -14,8 +14,6 @@
namespace wi::gui
{
void Initialize();
class Widget;
class GUI
+4 -4
View File
@@ -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
{
+1 -1
View File
@@ -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
+36 -39
View File
@@ -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:
+15 -3
View File
@@ -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
+12
View File
@@ -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);
-10
View File
@@ -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);
}
}
+27 -20
View File
@@ -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();
}
}
}
+21 -1
View File
@@ -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);
}
+21 -17
View File
@@ -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
+2 -2
View File
@@ -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
+1 -2
View File
@@ -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;
-2
View File
@@ -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);
-9
View File
@@ -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>();
-5
View File
@@ -6,11 +6,6 @@
namespace wi::network
{
void Initialize()
{
wi::backlog::post("TODO wi::network_UWP");
}
bool CreateSocket(Socket* sock)
{
return false;
+22 -21
View File
@@ -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);
+18 -24
View File
@@ -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
+5 -5
View File
@@ -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; } }
+83 -68
View File
@@ -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
-1
View File
@@ -6,7 +6,6 @@
namespace wi::shadercompiler
{
void Initialize();
enum class Flags
{
+1 -1
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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);
+16
View File
@@ -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&lt;*&gt;">
<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>