From 7027ce2db7f17ec295a78b5094c424bdbbc77404 Mon Sep 17 00:00:00 2001 From: mrq Date: Wed, 21 Oct 2020 00:00:00 -0500 Subject: [PATCH] Commit for 2020.10.21.7z --- Makefile | 26 +- bin/data/shaders/raytracing.comp.glsl | 2 + .../uf/engine/instantiator/instantiator.inl | 4 +- engine/inc/uf/ext/vulkan/device.h | 2 + engine/inc/uf/ext/vulkan/graphic.h | 1 + engine/inc/uf/ext/vulkan/rendermode.h | 12 +- .../uf/ext/vulkan/rendermodes/rendertarget.h | 1 + engine/inc/uf/utils/audio/audio.h | 3 + engine/inc/uf/utils/math/math.h | 8 +- engine/inc/uf/utils/string/io.h | 1 + engine/inc/uf/utils/thread/thread.h | 3 + engine/src/engine/object/behavior.cpp | 5 +- .../src/engine/object/behaviors/loading.cpp | 1 + engine/src/ext/oal/oal.cpp | 19 +- engine/src/ext/openvr/openvr.cpp | 10 +- engine/src/ext/vulkan/device.cpp | 12 +- engine/src/ext/vulkan/graphic.cpp | 45 +- engine/src/ext/vulkan/rendermode.cpp | 81 ++- engine/src/ext/vulkan/rendermodes/base.cpp | 4 +- engine/src/ext/vulkan/rendermodes/compute.cpp | 31 +- .../src/ext/vulkan/rendermodes/deferred.cpp | 7 +- .../ext/vulkan/rendermodes/rendertarget.cpp | 10 +- .../rendermodes/stereoscopic_deferred.cpp | 2 +- engine/src/ext/vulkan/texture.cpp | 2 +- engine/src/ext/vulkan/vulkan.cpp | 17 +- engine/src/utils/audio/audio.cpp | 55 +- engine/src/utils/string/io.cpp | 13 + engine/src/utils/thread/thread.cpp | 40 +- ext/behaviors/light/behavior.cpp | 2 +- ext/behaviors/scene/behavior.cpp | 64 ++- ext/behaviors/spine/behavior.cpp | 528 ------------------ ext/behaviors/spine/behavior.h | 25 - ext/behaviors/staticemitter/behavior.cpp | 8 +- ext/gui/behavior.cpp | 2 +- ext/main.cpp | 5 +- ext/scenes/raytrace/behavior.cpp | 4 +- 36 files changed, 352 insertions(+), 703 deletions(-) delete mode 100644 ext/behaviors/spine/behavior.cpp delete mode 100644 ext/behaviors/spine/behavior.h diff --git a/Makefile b/Makefile index b9643606..b713f53e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: win64 + .PHONY: win64 TARGET_NAME = program BIN_DIR = ./bin @@ -15,19 +15,19 @@ UF_LIBS = # EXT_LIBS = -lpng16 -lz -lassimp -lsfml-main -lsfml-system -lsfml-window -lsfml-graphics -llua52 # EXT_LIBS = -lpng16 -lz -lassimp -ljsoncpp -lopenal32 -lalut -lvorbis -lvorbisfile -logg -lfreetype EXT_LIBS = -#FLAGS = -Og -DUF_DISABLE_ALIGNAS -std=c++20 -Wno-c++11-narrowing -Wno-narrowing -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW -FLAGS = -std=c++20 -Wno-c++11-narrowing -Wno-narrowing -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW +#FLAGS = -std=c++0x -Wall -g -DUF_USE_JSON -DUF_USE_NCURSES -DUF_USE_OPENGL -DUF_USE_GLEW +FLAGS = -Og -std=c++17 -g -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN -DGLM_ENABLE_EXPERIMENTAL -DUF_USE_JSON -DUF_USE_OPENAL -DUF_USE_VORBIS -DUF_USE_FREETYPE -DUSE_OPENVR_MINGW #-march=native LIB_NAME = uf EXT_LIB_NAME = ext -#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.101.0/ -#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.108.0/ -#VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.1.114.0/ +#VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.101.0/ +#VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.108.0/ +#VULKAN_WIN64_SDK_PATH = /cygdrive/c/VulkanSDK/1.1.114.0/ #VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.141.2/ VULKAN_WIN64_SDK_PATH = /c/VulkanSDK/1.2.154.0/ -WIN64_CC = g++ +WIN64_CC = /opt/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin/g++ WIN64_GLSL_VALIDATOR = $(VULKAN_WIN64_SDK_PATH)/Bin32/glslangValidator # Base Engine's DLL WIN64_INC_DIR = $(ENGINE_INC_DIR)/win64 @@ -39,8 +39,8 @@ WIN64_FLAGS = $(FLAGS) -g #-Wl,-subsystem,windows WIN64_LIB_DIR = $(ENGINE_LIB_DIR)/win64/ -WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include -WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib +WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include -I/mingw64/include +WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib -L/mingw64/lib SRCS_WIN64_DLL = $(wildcard $(ENGINE_SRC_DIR)/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(ENGINE_SRC_DIR)/*/*/*/*/*.cpp) OBJS_WIN64_DLL = $(patsubst %.cpp,%.win64.o,$(SRCS_WIN64_DLL)) @@ -56,8 +56,8 @@ EXT_WIN64_FLAGS = $(FLAGS) #-Wl,-subsystem,windows EXT_WIN64_LIB_DIR = $(ENGINE_LIB_DIR)/win64/ -EXT_WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(EXT_WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include -EXT_WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(EXT_WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib +EXT_WIN64_INCS = -I$(ENGINE_INC_DIR) -I$(EXT_WIN64_INC_DIR) -I$(VULKAN_WIN64_SDK_PATH)/include -I/mingw64/include +EXT_WIN64_LIBS = -L$(ENGINE_LIB_DIR) -L$(EXT_WIN64_LIB_DIR) -L$(VULKAN_WIN64_SDK_PATH)/Lib -L/mingw64/lib SRCS_EXT_WIN64_DLL = $(wildcard $(EXT_SRC_DIR)/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*.cpp) $(wildcard $(EXT_SRC_DIR)/*/*/*/*/*.cpp) OBJS_EXT_WIN64_DLL = $(patsubst %.cpp,%.win64.o,$(SRCS_EXT_WIN64_DLL)) @@ -72,10 +72,6 @@ TARGET_WIN64 = $(BIN_DIR)/$(TARGET_NAME).exe SRCS_SHADERS = $(wildcard bin/data/shaders/*.glsl) TARGET_SHADERS = $(patsubst %.glsl,%.spv,$(SRCS_SHADERS)) -# clang-win64: WIN64_CC=clang++ -# make -# gcc-win64: WIN64_CC=g++ -# make win64: $(EX_WIN64_DLL) $(EXT_EX_WIN64_DLL) $(TARGET_WIN64) $(TARGET_SHADERS) rm-exe64: diff --git a/bin/data/shaders/raytracing.comp.glsl b/bin/data/shaders/raytracing.comp.glsl index b288af7d..ed6d7abe 100644 --- a/bin/data/shaders/raytracing.comp.glsl +++ b/bin/data/shaders/raytracing.comp.glsl @@ -32,6 +32,7 @@ struct Light { vec3 color; float power; vec2 type; + vec2 padding; mat4 view; mat4 projection; }; @@ -44,6 +45,7 @@ struct State { struct Fog { vec2 range; + vec2 padding; vec4 color; }; diff --git a/engine/inc/uf/engine/instantiator/instantiator.inl b/engine/inc/uf/engine/instantiator/instantiator.inl index fc773e49..539d7f29 100644 --- a/engine/inc/uf/engine/instantiator/instantiator.inl +++ b/engine/inc/uf/engine/instantiator/instantiator.inl @@ -1,10 +1,10 @@ template -pod::NamedTypes::type_t pod::NamedTypes::getType( const std::string& name ) { +typename pod::NamedTypes::type_t pod::NamedTypes::getType( const std::string& name ) { for ( auto pair : names ) if ( pair.second == name ) return pair.first; return getType(); } template -template pod::NamedTypes::type_t pod::NamedTypes::getType() { +template typename pod::NamedTypes::type_t pod::NamedTypes::getType() { return std::type_index(typeid(T)); } template diff --git a/engine/inc/uf/ext/vulkan/device.h b/engine/inc/uf/ext/vulkan/device.h index 510feaa1..8f421abe 100644 --- a/engine/inc/uf/ext/vulkan/device.h +++ b/engine/inc/uf/ext/vulkan/device.h @@ -97,6 +97,8 @@ namespace ext { }; VkQueue& getQueue( QueueEnum ); VkCommandPool& getCommandPool( QueueEnum ); + VkQueue& getQueue( QueueEnum, std::thread::id ); + VkCommandPool& getCommandPool( QueueEnum, std::thread::id ); // RAII void initialize(); diff --git a/engine/inc/uf/ext/vulkan/graphic.h b/engine/inc/uf/ext/vulkan/graphic.h index 4d34f176..679c8863 100644 --- a/engine/inc/uf/ext/vulkan/graphic.h +++ b/engine/inc/uf/ext/vulkan/graphic.h @@ -104,6 +104,7 @@ namespace ext { Pipeline& getPipeline( Descriptor& descriptor ); void record( VkCommandBuffer commandBuffer ); + void record( VkCommandBuffer commandBuffer, Descriptor& descriptor ); }; } } diff --git a/engine/inc/uf/ext/vulkan/rendermode.h b/engine/inc/uf/ext/vulkan/rendermode.h index 58e32511..48685e7c 100644 --- a/engine/inc/uf/ext/vulkan/rendermode.h +++ b/engine/inc/uf/ext/vulkan/rendermode.h @@ -8,6 +8,7 @@ namespace ext { struct UF_API RenderMode { bool execute = false; + bool rebuild = false; uint32_t width = 0, height = 0; std::string name = ""; @@ -16,18 +17,25 @@ namespace ext { VkSemaphore renderCompleteSemaphore; std::vector fences; - std::vector commands; + + typedef std::vector commands_container_t; + std::thread::id mostRecentCommandPoolId; + std::unordered_map commands; // virtual ~RenderMode(); // RAII virtual std::string getType() const; - const std::string& getName() const; + const std::string& getName( bool = false ) const; virtual RenderTarget& getRenderTarget(size_t = 0); virtual const RenderTarget& getRenderTarget(size_t = 0) const; + + virtual commands_container_t& getCommands(); + virtual commands_container_t& getCommands( std::thread::id ); virtual void initialize( Device& device ); virtual void createCommandBuffers(); virtual void createCommandBuffers( const std::vector& graphics ); + virtual void bindPipelines( const std::vector& graphics ); virtual void tick(); virtual void render(); virtual void destroy(); diff --git a/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h b/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h index d56866e7..693e29b7 100644 --- a/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h +++ b/engine/inc/uf/ext/vulkan/rendermodes/rendertarget.h @@ -14,6 +14,7 @@ namespace ext { // RAII virtual std::string getType() const; + virtual const std::string& getName( bool ) const; virtual void createCommandBuffers( const std::vector& graphics ); virtual void initialize( Device& device ); diff --git a/engine/inc/uf/utils/audio/audio.h b/engine/inc/uf/utils/audio/audio.h index bc01a757..cc186da9 100644 --- a/engine/inc/uf/utils/audio/audio.h +++ b/engine/inc/uf/utils/audio/audio.h @@ -25,8 +25,11 @@ namespace uf { Audio( Audio&& ); Audio( const Audio& ); */ + ~Audio(); + bool initialized(); bool playing(); + void destroy(); void load( const std::string& = "" ); void play(); diff --git a/engine/inc/uf/utils/math/math.h b/engine/inc/uf/utils/math/math.h index 0947ecd5..979c445a 100644 --- a/engine/inc/uf/utils/math/math.h +++ b/engine/inc/uf/utils/math/math.h @@ -10,13 +10,11 @@ namespace { // Sometimes uint isn't declared typedef unsigned int uint; } -/* namespace uf { namespace math { template - T lerp( const T& from, const T& to, double delta ) { - + T lerp( const T& a, const T& b, double f ) { + return a + f * (b - a); } } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/engine/inc/uf/utils/string/io.h b/engine/inc/uf/utils/string/io.h index f4846256..061a45a7 100644 --- a/engine/inc/uf/utils/string/io.h +++ b/engine/inc/uf/utils/string/io.h @@ -6,6 +6,7 @@ namespace uf { namespace io { + std::string UF_API absolute( const std::string& ); std::string UF_API filename( const std::string& ); std::string UF_API extension( const std::string& ); std::string UF_API directory( const std::string& ); diff --git a/engine/inc/uf/utils/thread/thread.h b/engine/inc/uf/utils/thread/thread.h index 5c84c384..8a2528f0 100644 --- a/engine/inc/uf/utils/thread/thread.h +++ b/engine/inc/uf/utils/thread/thread.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace pod { struct UF_API Thread { @@ -22,6 +23,7 @@ namespace pod { bool running, terminates; std::mutex* mutex; + std::condition_variable condition; std::thread thread; pod::Thread::queue_t temps; @@ -45,6 +47,7 @@ namespace uf { // void UF_API tick( pod::Thread&, const std::function& = NULL ); pod::Thread& UF_API fetchWorker( const std::string& name = "Aux" ); + void UF_API batchWorkers( const std::vector&, bool = true, const std::string& name = "Aux" ); void UF_API add( pod::Thread&, const pod::Thread::function_t&, bool = false ); void UF_API process( pod::Thread& ); diff --git a/engine/src/engine/object/behavior.cpp b/engine/src/engine/object/behavior.cpp index 5ab4f2ec..bd094656 100644 --- a/engine/src/engine/object/behavior.cpp +++ b/engine/src/engine/object/behavior.cpp @@ -31,6 +31,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { // { size_t assets = metadata["system"]["assets"].size(); + if ( metadata["system"]["load"]["ignore"].isBool() ) assets = 0; metadata["system"]["load"]["progress"] = 0; metadata["system"]["load"]["total"] = assets; if ( assets == 0 ) { @@ -62,6 +63,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{ uf::Serializer json = event; std::string filename = json["filename"].asString(); + bool initialize = json["initialize"].isNull() ? true : json["initialize"].asBool(); if ( uf::io::extension(filename) != "json" ) return "false"; @@ -72,7 +74,8 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { json["root"] = uf::io::directory(filename); json["source"] = filename; // uf::io::filename(filename) json["hot reload"]["mtime"] = uf::io::mtime( filename ) + 10; - if ( this->loadChildUid(json) == -1 ) return "false"; + + if ( this->loadChildUid(json, initialize) == -1 ) return "false"; return "true"; }); diff --git a/engine/src/engine/object/behaviors/loading.cpp b/engine/src/engine/object/behaviors/loading.cpp index 7864dad3..0b0d9126 100644 --- a/engine/src/engine/object/behaviors/loading.cpp +++ b/engine/src/engine/object/behaviors/loading.cpp @@ -87,6 +87,7 @@ void uf::LoadingBehavior::tick( uf::Object& self ) { std::function filter = [&]( uf::Entity* entity ) { if ( !entity || entity->getUid() == 0 || !entity->hasComponent() ) return; auto& metadata = entity->getComponent(); + if ( metadata["system"]["load"]["ignore"].isBool() ) return; if ( metadata["system"]["load"].isNull() ) return; ++loading; if ( metadata["system"]["load"]["progress"].asInt() < metadata["system"]["load"]["total"].asInt() ) return; diff --git a/engine/src/ext/oal/oal.cpp b/engine/src/ext/oal/oal.cpp index e154f49e..0323115f 100644 --- a/engine/src/ext/oal/oal.cpp +++ b/engine/src/ext/oal/oal.cpp @@ -31,9 +31,11 @@ bool UF_API_CALL ext::AL::initialize() { } return this->m_initialized = true; */ - bool res = this->m_initialized = (alutInit(NULL, NULL) == AL_TRUE); + this->m_initialized = alutInit(NULL, NULL) == AL_TRUE; + auto error = alutGetError(); + std::cout << alutGetErrorString(error) << std::endl; this->checkError(__FUNCTION__, __LINE__); - return res; + return this->m_initialized; } bool UF_API_CALL ext::AL::terminate() { /* @@ -46,7 +48,9 @@ bool UF_API_CALL ext::AL::terminate() { } void UF_API_CALL ext::AL::checkError( const std::string& function, int line, const std::string& aux ) const { std::string error = this->getError(); - // if ( error != "AL_NO_ERROR" ) std::cerr << "AL error @ " << function << ":" << line << ": "<<(aux!=""?"("+aux+") ":"")<< error << std::endl; + if ( error != "AL_NO_ERROR" ) std::cerr << "AL error @ " << function << ":" << line << ": "<<(aux!=""?"("+aux+") ":"")<< error << std::endl; + error = alutGetErrorString(alutGetError()); + if ( error != "No ALUT error found" ) std::cerr << "AL error @ " << function << ":" << line << ": "<<(aux!=""?"("+aux+") ":"")<< error << std::endl; } std::string UF_API_CALL ext::AL::getError() const { ALCenum error = alGetError(); @@ -58,7 +62,7 @@ std::string UF_API_CALL ext::AL::getError() const { case AL_INVALID_OPERATION: return "AL_INVALID_OPERATION"; // the requested operation is not valid case AL_OUT_OF_MEMORY: return "AL_OUT_OF_MEMORY"; // the requested operation resulted in OpenAL running out ofmemory } - return "AL_UNKNOWN"; + return "AL_UNKNOWN(" + std::to_string(error) + ")"; } void UF_API_CALL ext::AL::listener( ALenum name, std::vector parameters ) { switch ( parameters.size() ) { @@ -86,13 +90,12 @@ ext::al::Source::~Source() { void UF_API_CALL ext::al::Source::generate() { if ( this->m_index ) this->destroy(); - alGenSources(1, &this->m_index); - ext::oal.checkError(__FUNCTION__, __LINE__); + alGenSources(1, &this->m_index); ext::oal.checkError(__FUNCTION__, __LINE__); } void UF_API_CALL ext::al::Source::destroy() { if ( this->m_index && alIsSource(this->m_index) ) { - alDeleteSources(1, &this->m_index); - ext::oal.checkError(__FUNCTION__, __LINE__); + if ( this->playing() ) this->stop(); + alDeleteSources(1, &this->m_index); ext::oal.checkError(__FUNCTION__, __LINE__); } this->m_index = 0; } diff --git a/engine/src/ext/openvr/openvr.cpp b/engine/src/ext/openvr/openvr.cpp index 06b42381..d28ab1b1 100644 --- a/engine/src/ext/openvr/openvr.cpp +++ b/engine/src/ext/openvr/openvr.cpp @@ -1,12 +1,11 @@ #include #include #include +#include #include #include - -#include - +#include #define DEBUG_MARKER 0 vr::IVRSystem* ext::openvr::context; @@ -156,10 +155,7 @@ bool ext::openvr::initialize( int stage ) { // load manifest { - std::filesystem::path p = ext::openvr::driver.manifest; - p = std::filesystem::absolute( p ); - ext::openvr::driver.manifest = p.string(); - VR_CHECK_INPUT_RESULT( vr::VRInput()->SetActionManifestPath( ext::openvr::driver.manifest.c_str() ) ); + VR_CHECK_INPUT_RESULT( vr::VRInput()->SetActionManifestPath( uf::io::absolute(ext::openvr::driver.manifest).c_str() ) ); // configure action handles { uf::Serializer manifest; diff --git a/engine/src/ext/vulkan/device.cpp b/engine/src/ext/vulkan/device.cpp index f82720fb..cc2ee39c 100644 --- a/engine/src/ext/vulkan/device.cpp +++ b/engine/src/ext/vulkan/device.cpp @@ -435,11 +435,16 @@ VkResult ext::vulkan::Device::createBuffer( // Attach the memory to the buffer object return buffer.bind(); } -VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum ) { +VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum) { + return this->getCommandPool( queueEnum, std::this_thread::get_id() ); +} +VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum ) { + return this->getQueue( queueEnum, std::this_thread::get_id() ); +} +VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum, std::thread::id id ) { uint32_t index = 0; VkCommandPool* pool = NULL; bool exists = false; - auto id = std::this_thread::get_id(); switch ( queueEnum ) { case QueueEnum::GRAPHICS: index = device.queueFamilyIndices.graphics; @@ -468,11 +473,10 @@ VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEn } return *pool; } -VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum ) { +VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum, std::thread::id id ) { uint32_t index = 0; VkQueue* queue = NULL; bool exists = false; - auto id = std::this_thread::get_id(); switch ( queueEnum ) { case QueueEnum::GRAPHICS: index = device.queueFamilyIndices.graphics; diff --git a/engine/src/ext/vulkan/graphic.cpp b/engine/src/ext/vulkan/graphic.cpp index ce8890c3..17884262 100644 --- a/engine/src/ext/vulkan/graphic.cpp +++ b/engine/src/ext/vulkan/graphic.cpp @@ -479,6 +479,9 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) { // generate fallback empty texture auto& emptyTexture = Texture2D::empty; + RenderMode& renderMode = ext::vulkan::getRenderMode(graphic.descriptor.renderMode, true); + auto& renderTarget = renderMode.getRenderTarget(graphic.descriptor.renderTarget ); + std::vector writeDescriptorSets; std::vector descriptorSetLayoutBindings; std::vector inputDescriptors; @@ -488,9 +491,6 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) { descriptorSetLayoutBindings.insert( descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.begin(), shader.descriptorSetLayoutBindings.end() ); } - RenderMode& renderMode = ext::vulkan::getRenderMode(graphic.descriptor.renderMode, true); - auto& renderTarget = renderMode.getRenderTarget(graphic.descriptor.renderTarget ); - if ( graphic.descriptor.subpass < renderTarget.passes.size() ) { auto& subpass = renderTarget.passes[graphic.descriptor.subpass]; for ( auto& input : subpass.inputs ) { @@ -563,6 +563,8 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) { if ( d.imageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL ) d.imageLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + } else { + // std::cout << "textures == graphic.material.textures.end()" << std::endl; } imageInfos.push_back( d ); } @@ -668,19 +670,35 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) { for ( auto& descriptor : writeDescriptorSets ) { if ( descriptor.pBufferInfo ) { // std::cout << descriptor.pBufferInfo->offset << std::endl; - if ( descriptor.pBufferInfo->offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) { - // std::cout << "Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.pBufferInfo->offset << std::endl; - std::cout << "Invalid descriptor for buffer: " << descriptor.pBufferInfo->buffer << " " << descriptor.pBufferInfo->offset << " " << descriptor.pBufferInfo->range << ", invalidating..." << std::endl; - auto pointer = const_cast(descriptor.pBufferInfo); - pointer->offset = 0; - pointer->range = 0; - pointer->buffer = VK_NULL_HANDLE; + for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) { + if ( descriptor.pBufferInfo[i].offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) { + // std::cout << "Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.pBufferInfo[i].offset << std::endl; + std::cout << "Invalid descriptor for buffer: " << descriptor.pBufferInfo[i].buffer << " " << descriptor.pBufferInfo[i].offset << " " << descriptor.pBufferInfo[i].range << ", invalidating..." << std::endl; + auto pointer = const_cast(&descriptor.pBufferInfo[i]); + pointer->offset = 0; + pointer->range = 0; + pointer->buffer = VK_NULL_HANDLE; - // const_cast(descriptor.pBufferInfo)->offset = 0; + // const_cast(descriptor.pBufferInfo)->offset = 0; + } } } } + // render mode's command buffer is in flight, queue a rebuild + // ext::vulkan::rebuild = true; + // renderMode.synchronize(); + renderMode.rebuild = true; +/* + std::cout << this << ": " << renderMode.getName() << ": " << renderMode.getType() << " " << descriptorSet << std::endl; + for ( auto& descriptor : writeDescriptorSets ) { + for ( size_t i = 0; i < descriptor.descriptorCount; ++i ) { + if ( descriptor.pImageInfo ) { + std::cout << "[" << i << "]: " << descriptor.pImageInfo[i].imageView << std::endl; + } + } + } +*/ vkUpdateDescriptorSets( *device, writeDescriptorSets.size(), @@ -780,12 +798,15 @@ ext::vulkan::Pipeline& ext::vulkan::Graphic::getPipeline( Descriptor& descriptor return pipelines[descriptor.hash()]; } void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer ) { + return this->record( commandBuffer, descriptor ); +} +void ext::vulkan::Graphic::record( VkCommandBuffer commandBuffer, Descriptor& descriptor ) { if ( !this->hasPipeline( descriptor ) ) { std::cout << this << ": has no valid pipeline" << std::endl; return; } - auto& pipeline = this->getPipeline(); + auto& pipeline = this->getPipeline( descriptor ); assert( buffers.size() >= 2 ); Buffer& vertexBuffer = buffers.at(0); diff --git a/engine/src/ext/vulkan/rendermode.cpp b/engine/src/ext/vulkan/rendermode.cpp index 633e917c..615c0d71 100644 --- a/engine/src/ext/vulkan/rendermode.cpp +++ b/engine/src/ext/vulkan/rendermode.cpp @@ -17,7 +17,7 @@ ext::vulkan::RenderMode::~RenderMode() { std::string ext::vulkan::RenderMode::getType() const { return ""; } -const std::string& ext::vulkan::RenderMode::getName() const { +const std::string& ext::vulkan::RenderMode::getName( bool ) const { return this->name; } ext::vulkan::RenderTarget& ext::vulkan::RenderMode::getRenderTarget( size_t i ) { @@ -52,13 +52,78 @@ void ext::vulkan::RenderMode::createCommandBuffers() { } this->synchronize(); - //VK_CHECK_RESULT(vkWaitForFences(*device, fences.size(), fences.data(), VK_TRUE, UINT64_MAX)); + bindPipelines( graphics ); createCommandBuffers( graphics ); + this->mostRecentCommandPoolId = std::this_thread::get_id(); + this->rebuild = false; +} +ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getCommands() { + return getCommands( std::this_thread::get_id() ); +} +ext::vulkan::RenderMode::commands_container_t& ext::vulkan::RenderMode::getCommands( std::thread::id id ) { + bool exists = this->commands.count(id) > 0; + auto& commands = this->commands[id]; + if ( !exists ) { + commands.resize( swapchain.buffers ); + + VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo( + this->getType() == "Compute" ? device->getCommandPool(Device::QueueEnum::COMPUTE) : device->getCommandPool(Device::QueueEnum::GRAPHICS), + VK_COMMAND_BUFFER_LEVEL_PRIMARY, + static_cast(commands.size()) + ); + + VK_CHECK_RESULT(vkAllocateCommandBuffers(*device, &cmdBufAllocateInfo, commands.data())); + } + return commands; +/* + VkCommandPool* pool = NULL; + switch ( queueEnum ) { + case QueueEnum::GRAPHICS: + index = device.queueFamilyIndices.graphics; + if ( commandPool.graphics.count(id) > 0 ) exists = true; + pool = &commandPool.graphics[id]; + break; + case QueueEnum::COMPUTE: + index = device.queueFamilyIndices.compute; + if ( commandPool.compute.count(id) > 0 ) exists = true; + pool = &commandPool.compute[id]; + break; + case QueueEnum::TRANSFER: + index = device.queueFamilyIndices.transfer; + if ( commandPool.transfer.count(id) > 0 ) exists = true; + pool = &commandPool.transfer[id]; + break; + } + if ( !exists ) { + VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + VkCommandPoolCreateInfo cmdPoolInfo = {}; + cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + cmdPoolInfo.queueFamilyIndex = index; + cmdPoolInfo.flags = createFlags; + if ( vkCreateCommandPool( this->logicalDevice, &cmdPoolInfo, nullptr, pool ) != VK_SUCCESS ) + throw std::runtime_error("failed to create command pool for graphics!"); + } + return *pool; +*/ } void ext::vulkan::RenderMode::createCommandBuffers( const std::vector& graphics ) { + +} +void ext::vulkan::RenderMode::bindPipelines( const std::vector& graphics ) { + for ( auto* pointer : graphics ) { + auto& graphic = *pointer; + // copy descriptor + ext::vulkan::Graphic::Descriptor descriptor = graphic.descriptor; + // bind to this render mode + descriptor.renderMode = this->getName(); + // ignore if pipeline exists for this render mode + if ( graphic.hasPipeline( descriptor ) ) continue; + graphic.initializePipeline( descriptor ); + } } void ext::vulkan::RenderMode::render() { + auto& commands = getCommands( this->mostRecentCommandPoolId ); // Get next image in the swap chain (back/front buffer) VK_CHECK_RESULT(swapchain.acquireNextImage(¤tBuffer, swapchain.presentCompleteSemaphore)); @@ -101,6 +166,7 @@ void ext::vulkan::RenderMode::initialize( Device& device ) { } // Create command buffers +/* { commands.resize( swapchain.buffers ); @@ -112,6 +178,7 @@ void ext::vulkan::RenderMode::initialize( Device& device ) { VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufAllocateInfo, commands.data())); } +*/ // Set sync objects { // Fences (Used to check draw command buffer completion) @@ -119,7 +186,7 @@ void ext::vulkan::RenderMode::initialize( Device& device ) { fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; // Create in signaled state so we don't wait on first render of each command buffer fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - fences.resize( commands.size() ); + fences.resize( swapchain.buffers ); for ( auto& fence : fences ) { VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &fence)); } @@ -143,12 +210,16 @@ void ext::vulkan::RenderMode::destroy() { this->synchronize(); renderTarget.destroy(); - +/* if ( commands.size() > 0 ) { vkFreeCommandBuffers( *device, this->getType() == "Compute" ? device->getCommandPool(Device::QueueEnum::COMPUTE) : device->getCommandPool(Device::QueueEnum::GRAPHICS), static_cast(commands.size()), commands.data()); } commands.clear(); - +*/ + for ( auto& pair : this->commands ) { + vkFreeCommandBuffers( *device, device->getCommandPool(this->getType() == "Compute" ? Device::QueueEnum::COMPUTE : Device::QueueEnum::GRAPHICS, pair.first), static_cast(pair.second.size()), pair.second.data()); + pair.second.clear(); + } if ( renderCompleteSemaphore != VK_NULL_HANDLE ) { vkDestroySemaphore( *device, renderCompleteSemaphore, nullptr); renderCompleteSemaphore = VK_NULL_HANDLE; diff --git a/engine/src/ext/vulkan/rendermodes/base.cpp b/engine/src/ext/vulkan/rendermodes/base.cpp index 6193cb7d..f23cbdca 100644 --- a/engine/src/ext/vulkan/rendermodes/base.cpp +++ b/engine/src/ext/vulkan/rendermodes/base.cpp @@ -18,9 +18,6 @@ ext::vulkan::BaseRenderMode::~BaseRenderMode() { std::string ext::vulkan::BaseRenderMode::getType() const { return "Swapchain"; } -const std::string& ext::vulkan::BaseRenderMode::getName() const { - return this->name; -} void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector& graphics ) { if ( ext::vulkan::renderModes.size() > 1 ) return; @@ -47,6 +44,7 @@ void ext::vulkan::BaseRenderMode::createCommandBuffers( const std::vector(); auto& shader = compute.material.shaders.front(); - /* + struct SpecializationConstant { - int32_t eyes = 2; - int32_t maxLights = 16; - }; - auto& specializationConstants = shader.specializationConstants.get(); - specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["max lights"].asUInt64(); - specializationConstants.eyes = ext::openvr::context ? 2 : 1; - */ - struct SpecializationConstant { - uint32_t eyes = 2; uint32_t maxLights = 16; + uint32_t eyes = 2; }; auto* specializationConstants = (SpecializationConstant*) &shader.specializationConstants[0]; specializationConstants->maxLights = metadata["system"]["config"]["engine"]["scenes"]["max lights"].asUInt64(); specializationConstants->eyes = ext::openvr::context ? 2 : 1; for ( auto& binding : shader.descriptorSetLayoutBindings ) { - if ( binding.descriptorCount > 1 ) - binding.descriptorCount = specializationConstants->maxLights; + if ( binding.descriptorCount > 1 ) { + binding.descriptorCount = specializationConstants->eyes; + } } } @@ -106,6 +99,7 @@ void ext::vulkan::ComputeRenderMode::initialize( Device& device ) { void ext::vulkan::ComputeRenderMode::render() { if ( compute.buffers.empty() ) return; + auto& commands = getCommands( this->mostRecentCommandPoolId ); // Submit compute commands // Use a fence to ensure that compute command buffer has finished executing before using it again VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX )); @@ -143,13 +137,10 @@ void ext::vulkan::ComputeRenderMode::tick() { texture = computeTexture; texture.device = NULL; } - auto& pipeline = blitter.getPipeline(); - pipeline.update( blitter ); + blitter.getPipeline().update( blitter ); } - // if ( compute.initialized ) { if ( !compute.buffers.empty() ) { - auto& pipeline = compute.getPipeline(); - pipeline.update( compute ); + compute.getPipeline().update( compute ); } } } @@ -212,14 +203,16 @@ void ext::vulkan::ComputeRenderMode::createCommandBuffers( ) { float width = this->width > 0 ? this->width : ext::vulkan::width; float height = this->height > 0 ? this->height : ext::vulkan::height; - if ( compute.buffers.empty() ) return; - VkCommandBufferBeginInfo cmdBufInfo = ext::vulkan::initializers::commandBufferBeginInfo(); auto& pipeline = compute.getPipeline(); + auto& commands = getCommands(); + if ( compute.buffers.empty() ) return; for (size_t i = 0; i < commands.size(); ++i) { VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); pipeline.record(compute, commands[i]); vkCmdDispatch(commands[i], width / dispatchSize.x, height / dispatchSize.y, 1); VK_CHECK_RESULT(vkEndCommandBuffer(commands[i])); } + + this->mostRecentCommandPoolId = std::this_thread::get_id(); } \ No newline at end of file diff --git a/engine/src/ext/vulkan/rendermodes/deferred.cpp b/engine/src/ext/vulkan/rendermodes/deferred.cpp index dc369b0e..55778b8c 100644 --- a/engine/src/ext/vulkan/rendermodes/deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/deferred.cpp @@ -11,7 +11,7 @@ #include -std::string ext::vulkan::DeferredRenderMode::getType() const { +std::string ext::vulkan::DeferredRenderMode::getType( ) const { return "Deferred"; } @@ -160,9 +160,7 @@ void ext::vulkan::DeferredRenderMode::tick() { renderTarget.initialize( *renderTarget.device ); // update blitter descriptor set if ( blitter.initialized ) { - auto& pipeline = blitter.getPipeline(); - pipeline.update( blitter ); - ext::vulkan::rebuild = true; + blitter.getPipeline().update( blitter ); } } } @@ -193,6 +191,7 @@ void ext::vulkan::DeferredRenderMode::createCommandBuffers( const std::vector layers = ext::vulkan::getRenderModes(std::vector{"RenderTarget", "Compute"}, false); auto& scene = uf::scene::getCurrentScene(); auto& metadata = scene.getComponent(); + auto& commands = getCommands(); for (size_t i = 0; i < commands.size(); ++i) { VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); // Fill GBuffer diff --git a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp index 4eea32d8..aef37379 100644 --- a/engine/src/ext/vulkan/rendermodes/rendertarget.cpp +++ b/engine/src/ext/vulkan/rendermodes/rendertarget.cpp @@ -8,6 +8,9 @@ std::string ext::vulkan::RenderTargetRenderMode::getType() const { return "RenderTarget"; } +const std::string& ext::vulkan::RenderTargetRenderMode::getName( bool wantsTarget ) const { + return wantsTarget ? this->target : this->name; +} void ext::vulkan::RenderTargetRenderMode::initialize( Device& device ) { ext::vulkan::RenderMode::initialize( device ); @@ -125,6 +128,7 @@ void ext::vulkan::RenderTargetRenderMode::destroy() { blitter.destroy(); } void ext::vulkan::RenderTargetRenderMode::render() { + auto& commands = getCommands( this->mostRecentCommandPoolId ); // Submit commands // Use a fence to ensure that command buffer has finished executing before using it again VK_CHECK_RESULT(vkWaitForFences( *device, 1, &fences[currentBuffer], VK_TRUE, UINT64_MAX )); @@ -219,7 +223,7 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto VkCommandBufferBeginInfo cmdBufInfo = {}; cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdBufInfo.pNext = nullptr; - + auto& commands = getCommands(); for (size_t i = 0; i < commands.size(); ++i) { VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); { @@ -265,7 +269,9 @@ void ext::vulkan::RenderTargetRenderMode::createCommandBuffers( const std::vecto vkCmdSetScissor(commands[i], 0, 1, &scissor); for ( auto graphic : graphics ) { if ( graphic->descriptor.renderMode != this->target ) continue; - graphic->record(commands[i] ); + ext::vulkan::Graphic::Descriptor descriptor = graphic->descriptor; + descriptor.renderMode = this->name; + graphic->record(commands[i], descriptor ); } vkCmdNextSubpass(commands[i], VK_SUBPASS_CONTENTS_INLINE); vkCmdEndRenderPass(commands[i]); diff --git a/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp b/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp index fc802f46..a44555a3 100644 --- a/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp +++ b/engine/src/ext/vulkan/rendermodes/stereoscopic_deferred.cpp @@ -196,7 +196,7 @@ void ext::vulkan::StereoscopicDeferredRenderMode::createCommandBuffers( const st auto& scene = uf::scene::getCurrentScene(); auto& metadata = scene.getComponent(); - + auto& commands = getCommands(); for (size_t i = 0; i < commands.size(); ++i) { VK_CHECK_RESULT(vkBeginCommandBuffer(commands[i], &cmdBufInfo)); struct EYES { diff --git a/engine/src/ext/vulkan/texture.cpp b/engine/src/ext/vulkan/texture.cpp index 180ca1eb..19dd8cfa 100644 --- a/engine/src/ext/vulkan/texture.cpp +++ b/engine/src/ext/vulkan/texture.cpp @@ -443,7 +443,7 @@ void ext::vulkan::Texture2D::asRenderTarget( Device& device, uint32_t width, uin imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; imageCreateInfo.format = format; imageCreateInfo.extent = { width, height, 1 }; - imageCreateInfo.mipLevels = 1; + imageCreateInfo.mipLevels = this->mips = 1; imageCreateInfo.arrayLayers = 1; imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; diff --git a/engine/src/ext/vulkan/vulkan.cpp b/engine/src/ext/vulkan/vulkan.cpp index 535d3de6..3403a0e8 100644 --- a/engine/src/ext/vulkan/vulkan.cpp +++ b/engine/src/ext/vulkan/vulkan.cpp @@ -7,6 +7,7 @@ #include #include +#include uint32_t ext::vulkan::width = 1280; uint32_t ext::vulkan::height = 720; @@ -302,11 +303,23 @@ void ext::vulkan::tick() { } renderMode->tick(); } + + std::vector> jobs; for ( auto& renderMode : renderModes ) { if ( !renderMode ) continue; - if ( ext::vulkan::rebuild ) - renderMode->createCommandBuffers(); + if ( ext::vulkan::rebuild || renderMode->rebuild ) { + jobs.emplace_back([&]{ + renderMode->createCommandBuffers(); + return 0; + }); + } } + if ( !jobs.empty() ) { + // std::cout << "Batching " << jobs.size() << " command buffer jobs" << std::endl; + uf::thread::batchWorkers( jobs ); + // std::cout << "Done" << std::endl; + } + ext::vulkan::rebuild = false; ext::vulkan::resized = false; ext::vulkan::mutex.unlock(); diff --git a/engine/src/utils/audio/audio.cpp b/engine/src/utils/audio/audio.cpp index a87d9b33..672089e6 100644 --- a/engine/src/utils/audio/audio.cpp +++ b/engine/src/utils/audio/audio.cpp @@ -3,6 +3,7 @@ #if defined(UF_USE_OPENAL) #include +#include #endif /* UF_API uf::Audio::Audio( const std::string& filename ) : m_filename(filename) { @@ -20,11 +21,19 @@ UF_API uf::Audio::Audio( const uf::Audio& copy ) : { } */ +uf::Audio::~Audio() { + this->destroy(); +} + bool UF_API uf::Audio::initialized() { if ( !this->m_source.getIndex() ) return false; if ( !this->m_buffer.getIndex() ) return false; return true; } +void UF_API uf::Audio::destroy() { + this->m_source.destroy(); + this->m_buffer.destroy(); +} bool UF_API uf::Audio::playing() { if ( !this->initialized() ) return false; if ( !this->m_source.playing() ) return false; @@ -42,22 +51,24 @@ void UF_API uf::Audio::load( const std::string& filename ) { if ( filename != "" frequency = vorbis.getFrequency(); this->m_duration = vorbis.getDuration(); - this->m_buffer.generate(); - this->m_source.generate(); + this->m_buffer.generate(); ext::oal.checkError(__FUNCTION__, __LINE__); + this->m_source.generate(); ext::oal.checkError(__FUNCTION__, __LINE__); - this->m_buffer.buffer( format, &buffer[0], buffer.size(), frequency ); - this->m_source.source( "BUFFER", std::vector{ this->m_buffer.getIndex() } ); + this->m_buffer.buffer( format, &buffer[0], buffer.size(), frequency ); ext::oal.checkError(__FUNCTION__, __LINE__); + this->m_source.source( "BUFFER", std::vector{ this->m_buffer.getIndex() } ); ext::oal.checkError(__FUNCTION__, __LINE__); - this->m_source.source( "PITCH", std::vector{ 1 } ); - this->m_source.source( "GAIN", std::vector{ 1 } ); - this->m_source.source( "LOOPING", std::vector{ AL_FALSE } ); + this->m_source.source( "PITCH", std::vector{ 1 } ); ext::oal.checkError(__FUNCTION__, __LINE__); + this->m_source.source( "GAIN", std::vector{ 1 } ); ext::oal.checkError(__FUNCTION__, __LINE__); + this->m_source.source( "LOOPING", std::vector{ AL_FALSE } ); ext::oal.checkError(__FUNCTION__, __LINE__); } } void UF_API uf::Audio::play() { + if ( !this->initialized() ) return; this->m_source.play(); } void UF_API uf::Audio::stop() { + if ( !this->initialized() ) return; this->m_source.stop(); } const std::string& UF_API uf::Audio::getFilename() const { @@ -66,64 +77,64 @@ const std::string& UF_API uf::Audio::getFilename() const { float uf::Audio::getDuration() const { return this->m_duration; } -#include ALfloat UF_API uf::Audio::getTime() { - if ( this->playing() ) return 0; + if ( !this->playing() ) return 0; ALfloat pos; alGetSourcef(this->m_source.getIndex(), AL_SEC_OFFSET, &pos ); ext::oal.checkError(__FUNCTION__, __LINE__); return pos; } void UF_API uf::Audio::setTime( ALfloat pos ) { - if ( this->playing() ) return; + if ( !this->initialized() ) return; this->m_source.source("SEC_OFFSET", std::vector{ pos } ); } ALfloat UF_API uf::Audio::getPitch() { - if ( this->playing() ) return 0; + if ( !this->initialized() ) return 0; ALfloat pitch; alGetSourcef(this->m_source.getIndex(), AL_PITCH, &pitch ); ext::oal.checkError(__FUNCTION__, __LINE__); return pitch; } void UF_API uf::Audio::setPitch( ALfloat pitch ) { - if ( this->playing() ) return; + if ( !this->initialized() ) return; this->m_source.source("PITCH", std::vector{ pitch } ); } ALfloat UF_API uf::Audio::getGain() { - if ( this->playing() ) return 0; + if ( !this->initialized() ) return 0; ALfloat gain; alGetSourcef(this->m_source.getIndex(), AL_GAIN, &gain ); ext::oal.checkError(__FUNCTION__, __LINE__); return gain; } void UF_API uf::Audio::setGain( ALfloat gain ) { - if ( this->playing() ) return; + if ( !this->initialized() ) return; this->m_source.source("GAIN", std::vector{ gain } ); } ALfloat UF_API uf::Audio::getRolloffFactor() { - if ( this->playing() ) return 0; + if ( !this->initialized() ) return 0; ALfloat rolloffFactor; alGetSourcef(this->m_source.getIndex(), AL_ROLLOFF_FACTOR, &rolloffFactor ); ext::oal.checkError(__FUNCTION__, __LINE__); return rolloffFactor; } void UF_API uf::Audio::setRolloffFactor( ALfloat rolloffFactor ) { - if ( this->playing() ) return; + if ( !this->initialized() ) return; this->m_source.source("ROLLOFF_FACTOR", std::vector{ rolloffFactor } ); } ALfloat UF_API uf::Audio::getMaxDistance() { - if ( this->playing() ) return 0; + if ( !this->initialized() ) return 0; ALfloat maxDistance; alGetSourcef(this->m_source.getIndex(), AL_MAX_DISTANCE, &maxDistance ); ext::oal.checkError(__FUNCTION__, __LINE__); return maxDistance; } void UF_API uf::Audio::setMaxDistance( ALfloat maxDistance ) { - if ( this->playing() ) return; + if ( !this->initialized() ) return; this->m_source.source("MAX_DISTANCE", std::vector{ maxDistance } ); } void UF_API uf::Audio::setPosition( const pod::Vector3& position ) { + if ( !this->initialized() ) return; this->m_source.source("POSITION", std::vector{position.x, position.y, position.z} ); } void UF_API uf::Audio::setOrientation( const pod::Quaternion<>& orientation ) { @@ -164,9 +175,9 @@ const uf::SoundEmitter::container_t& UF_API uf::SoundEmitter::get() const { } void UF_API uf::SoundEmitter::cleanup( bool purge ) { -/* - for ( uf::Audio& k : this->m_container ) { - if ( !k.playing() ) this->m_container.erase(k); + for ( auto& pair : this->m_container ) { + if ( !pair.second.playing() ) { + this->m_container.erase(pair.first); + } } -*/ } \ No newline at end of file diff --git a/engine/src/utils/string/io.cpp b/engine/src/utils/string/io.cpp index f008fe23..9f797c9e 100644 --- a/engine/src/utils/string/io.cpp +++ b/engine/src/utils/string/io.cpp @@ -7,6 +7,19 @@ #include #include +#ifdef WINDOWS + #include + #define GetCurrentDir _getcwd +#else + #include + #define GetCurrentDir getcwd +#endif + +std::string UF_API uf::io::absolute( const std::string& path ) { + char buff[FILENAME_MAX]; + GetCurrentDir( buff, FILENAME_MAX ); + return std::string(buff) + path; +} std::string UF_API uf::io::filename( const std::string& str ) { return str.substr( str.find_last_of('/') + 1 ); } diff --git a/engine/src/utils/thread/thread.cpp b/engine/src/utils/thread/thread.cpp index bafad6a0..ea274236 100644 --- a/engine/src/utils/thread/thread.cpp +++ b/engine/src/utils/thread/thread.cpp @@ -54,7 +54,7 @@ pod::Thread& UF_API uf::thread::fetchWorker( const std::string& name ) { std::string thread = name; if ( current > 0 ) thread += " " + std::to_string(current); bool exists = uf::thread::has(thread); - auto& pod = exists ? uf::thread::get(thread) : uf::thread::create( thread, true, false ); + auto& pod = exists ? uf::thread::get(thread) : uf::thread::create( thread, true ); if ( !exists ) { /* pod.affinity = (current + 1) % threads; @@ -66,7 +66,17 @@ pod::Thread& UF_API uf::thread::fetchWorker( const std::string& name ) { } return pod; } - +void UF_API uf::thread::batchWorkers( const std::vector& functions, bool wait, const std::string& name ) { + std::vector workers; + for ( auto& function : functions ) { + auto& worker = uf::thread::fetchWorker( name ); + workers.emplace_back(&worker); + uf::thread::add( worker, function, true ); + } + if ( wait ) + for ( auto& worker : workers ) + uf::thread::wait( *worker ); +} /* void UF_API uf::thread::tick( pod::Thread& thread, const std::function& callback ) { while ( thread.running ) { @@ -82,6 +92,7 @@ void UF_API uf::thread::add( pod::Thread& thread, const pod::Thread::function_t& if ( thread.mutex != NULL ) thread.mutex->unlock(); } void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(uf::thread::uid(thread)) ) { if ( UF_THREAD_ANNOUNCE ) uf::iostream << "Bad Thread: " << thread.uid << " " << thread.name << "\n"; return; } //ops +/* std::function temps = [&] { int i = 0; while ( !thread.temps.empty() ) { @@ -100,17 +111,40 @@ void UF_API uf::thread::process( pod::Thread& thread ) { if ( !uf::thread::has(u } return i; }; - if ( thread.mutex != NULL ) thread.mutex->lock(); temps(); consts(); if ( thread.mutex != NULL ) thread.mutex->unlock(); +*/ + size_t temps = 0; + size_t consts = 0; + while ( !thread.temps.empty() ) { + auto& function = thread.temps.front(); + if ( function ) function(); + thread.temps.pop(); + ++temps; + } + for ( auto function : thread.consts ) { + function(); + ++consts; + } + thread.condition.notify_one(); } void UF_API uf::thread::wait( pod::Thread& thread ) { + if ( thread.mutex != NULL ) { + std::unique_lock lock(*thread.mutex); + thread.condition.wait(lock, [&]{return thread.temps.empty();}); + return; + } + while ( !thread.temps.empty() ); +/* if ( thread.mutex != NULL ) { thread.mutex->lock(); thread.mutex->unlock(); + return; } + while ( !thread.temps.empty() ); +*/ } const std::string& UF_API uf::thread::name( const pod::Thread& thread ) { diff --git a/ext/behaviors/light/behavior.cpp b/ext/behaviors/light/behavior.cpp index 4d5667fd..b2598961 100644 --- a/ext/behaviors/light/behavior.cpp +++ b/ext/behaviors/light/behavior.cpp @@ -99,7 +99,7 @@ void ext::LightBehavior::tick( uf::Object& self ) { float delta = metadata["light"]["fade"]["timer"].asFloat(); delta = std::clamp( delta, 0.f, 1.f ); if ( metadata["light"]["fade"]["power"].isNumeric() ) { - metadata["light"]["power"] = std::lerp( metadata["light"]["backup"]["power"].asFloat(), metadata["light"]["fade"]["power"].asFloat(), delta ); + metadata["light"]["power"] = uf::math::lerp( metadata["light"]["backup"]["power"].asFloat(), metadata["light"]["fade"]["power"].asFloat(), delta ); } if ( metadata["light"]["fade"]["color"].isArray() ) { pod::Vector3f fadeColor; { diff --git a/ext/behaviors/scene/behavior.cpp b/ext/behaviors/scene/behavior.cpp index 52e090d7..5f7a3a24 100644 --- a/ext/behaviors/scene/behavior.cpp +++ b/ext/behaviors/scene/behavior.cpp @@ -271,6 +271,29 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { uint32_t maxLights = 32; } specializationConstants; + std::vector entities; + { + std::function filter = [&]( uf::Entity* entity ) { + if ( !entity || entity->getName() != "Light" ) return; + entities.push_back(entity); + }; + for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue; + scene->process(filter); + } + { + const pod::Vector3& position = controller.getComponent>().position; + std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){ + if ( !l ) return false; if ( !r ) return true; + if ( !l->hasComponent>() ) return false; if ( !r->hasComponent>() ) return true; + return uf::vector::magnitude( uf::vector::subtract( l->getComponent>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent>().position, position ) ); + } ); + } + + { + uf::Serializer& metadata = controller.getComponent(); + if ( metadata["light"]["should"].asBool() ) entities.push_back(&controller); + } + } for ( size_t _ = 0; _ < blitters.size(); ++_ ) { auto& blitter = *blitters[_]; @@ -284,7 +307,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { buffer = (uint8_t*) (void*) userdata; len = userdata.data().len; shader = &_; - // specializationConstants = _.specializationConstants.get(); specializationConstants = *((SpecializationConstant*) &_.specializationConstants[0]); } @@ -323,27 +345,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { } } { - std::vector entities; - std::function filter = [&]( uf::Entity* entity ) { - if ( !entity || entity->getName() != "Light" ) return; - entities.push_back(entity); - }; - for ( uf::Scene* scene : uf::renderer::scenes ) { if ( !scene ) continue; - scene->process(filter); - } - { - const pod::Vector3& position = controller.getComponent>().position; - std::sort( entities.begin(), entities.end(), [&]( const uf::Entity* l, const uf::Entity* r ){ - if ( !l ) return false; if ( !r ) return true; - if ( !l->hasComponent>() ) return false; if ( !r->hasComponent>() ) return true; - return uf::vector::magnitude( uf::vector::subtract( l->getComponent>().position, position ) ) < uf::vector::magnitude( uf::vector::subtract( r->getComponent>().position, position ) ); - } ); - } - - { - uf::Serializer& metadata = controller.getComponent(); - if ( metadata["light"]["should"].asBool() ) entities.push_back(&controller); - } UniformDescriptor::Light* lights = (UniformDescriptor::Light*) &buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Light)]; for ( size_t i = 0; i < specializationConstants.maxLights; ++i ) { UniformDescriptor::Light& light = lights[i]; @@ -353,6 +354,10 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { light.depthBias = 0; } + std::vector previousTextures; + for ( auto& texture : blitter.material.textures ) { + previousTextures.emplace_back(texture.image); + } blitter.material.textures.clear(); for ( size_t i = 0; i < specializationConstants.maxLights && i < entities.size(); ++i ) { @@ -390,7 +395,6 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { uint8_t i = 0; for ( auto& attachment : renderTarget.attachments ) { if ( !(attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; - // if ( (attachment.usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) continue; if ( (attachment.layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) ) continue; auto& texture = blitter.material.textures.emplace_back(); texture.aliasAttachment(attachment); @@ -399,9 +403,21 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { } } } + size_t i = 0; + bool shouldUpdate = blitter.material.textures.size() != previousTextures.size(); + while ( !shouldUpdate && i < blitter.material.textures.size() ) { + auto& texture = blitter.material.textures[i]; + auto& previousTexture = previousTextures[i]; + if ( texture.image != previousTexture ) shouldUpdate = true; + ++i; + } + // check if we actually do need to update our pipeline, to avoid the command buffer rebuild cost + if ( shouldUpdate ) { + blitter.getPipeline().update( blitter ); + } } - blitter.getPipeline().update( blitter ); shader->updateBuffer( (void*) buffer, len, 0, false ); + } } } diff --git a/ext/behaviors/spine/behavior.cpp b/ext/behaviors/spine/behavior.cpp deleted file mode 100644 index 9d8245bf..00000000 --- a/ext/behaviors/spine/behavior.cpp +++ /dev/null @@ -1,528 +0,0 @@ -#include "behavior.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include "../../scenes/worldscape//battle.h" -#include "../../scenes/worldscape//.h" - -#include - -#define PRINT_VECTOR2(v)\ - std::cout << #v << ": " << v.x << ", " << v.y << std::endl; - -namespace { - pod::Vector3f AXIS_OF_ROTATION = { 0, 0, 1 }; - struct Bone { - std::string name = ""; - std::string parent = ""; - float length = 0; - - pod::Vector2f position = { 0, 0 }; - float rotation = 0; - }; - struct AtlasPiece { - std::string name = ""; - struct { - pod::Vector2f min = { 0, 0 }; - pod::Vector2f max = { 0, 0 }; - } uv; - struct { - pod::Vector2f topLeft = {-0.5f, 0.5f}; - pod::Vector2f topRight = { 0.5f, 0.5f}; - pod::Vector2f bottomLeft = {-0.5f, -0.5f}; - pod::Vector2f bottomRight = { 0.5f, -0.5f}; - } position; - pod::Vector2f scale = { 1, 1 }; - pod::Vector2f size = { 0, 0 }; - pod::Quaternion<> orientation = { 0, 0, 0, 1 }; - float rotation = 0; - }; - struct { - uf::Serializer animation; - uf::Serializer atlas; - uf::Serializer overrides; - } manifests; - struct { - std::unordered_map skeleton; - std::unordered_map attachments; - std::unordered_map skins; - std::unordered_map slots; - } maps; - - float getRotation( const std::string& boneName, bool flatten = false, float start = 0 ) { - if ( manifests.overrides[boneName]["rotation"].isNumeric() ) { - return manifests.overrides[boneName]["rotation"].asFloat(); - } - float rotation = start; - if ( maps.skeleton.count(boneName) < 0 ) { - std::cout << "Bone not in skeleton: " << boneName << std::endl; - return rotation; - } - Bone* bone = &maps.skeleton[boneName]; - do { - rotation += bone->rotation; - if ( bone->parent == "" ) break; - bone = &maps.skeleton[bone->parent]; - } while ( flatten ); - return rotation; - } - pod::Quaternion<> getOrientation( const std::string& boneName, bool flatten = false, float start = 0 ) { - float rotation = getRotation( boneName, flatten, start ); - return uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f ); - } - pod::Vector3f getPosition( const std::string& boneName, bool flatten = false ) { - if ( manifests.overrides[boneName]["position"].isArray() ) { - return pod::Vector3f{ - manifests.overrides[boneName]["position"][0].asFloat(), - manifests.overrides[boneName]["position"][1].asFloat(), - 0, - }; - } - pod::Vector3f position = { 0, 0, 0 }; - if ( maps.skeleton.count(boneName) < 0 ) { - std::cout << "Bone not in skeleton: " << boneName << std::endl; - return position; - } - Bone* bone = &maps.skeleton[boneName]; - std::vector positions; - do { - if ( bone->parent == "" ) break; - float rotation = getRotation( bone->parent, flatten ); - pod::Quaternion<> orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f ); - position += uf::quaternion::rotate( orientation, pod::Vector3f{ bone->position.x, bone->position.y, 0 } ); - bone = &maps.skeleton[bone->parent]; - } while ( flatten ); - return position; - } - pod::Matrix4f getMatrix( const std::string& boneName, bool flatten = false, float start = 0 ) { - pod::Matrix4f matrix = uf::matrix::identity(); - if ( start > 0.0f ) { - matrix = matrix * uf::quaternion::matrix( uf::quaternion::axisAngle( AXIS_OF_ROTATION, start ) ); - } - if ( maps.skeleton.count(boneName) < 0 ) { - std::cout << "Bone not in skeleton: " << boneName << std::endl; - return matrix; - } - Bone* bone = &maps.skeleton[boneName]; - do { - pod::Matrix4f translation = uf::matrix::translate( uf::matrix::identity(), {bone->position.x, bone->position.y, 0} ); - pod::Matrix4f rotation = uf::quaternion::matrix( uf::quaternion::axisAngle( AXIS_OF_ROTATION, bone->rotation ) ); - matrix = matrix * translation * rotation; - if ( bone->parent == "" ) break; - bone = &maps.skeleton[bone->parent]; - } while ( flatten ); - return matrix; - } - uf::Serializer getSkin( const uf::Serializer& slot ) { - uf::Serializer json; - std::string name = slot["name"].asString(); - std::string attachment = slot["attachment"].asString(); - if ( !maps.skins["default"][name][attachment].isNull() ) json = maps.skins["default"][name][attachment]; - else if ( !maps.skins["normal"][name][attachment].isNull() ) json = maps.skins["normal"][name][attachment]; - return json; - } -} - -EXT_BEHAVIOR_REGISTER_CPP(LahSpineBehavior) -#define this (&self) -void ext::LahSpineBehavior::initialize( uf::Object& self ) { - uf::Scene& scene = uf::scene::getCurrentScene(); - uf::Serializer& metadata = this->getComponent(); - uf::Serializer& masterdata = scene.getComponent(); - uf::Asset& assetLoader = scene.getComponent(); - - manifests.atlas.readFromFile(metadata["system"]["root"].asString() + "atlas.json"); - manifests.animation.readFromFile(metadata["system"]["root"].asString() + "animation.json"); - - this->addHook( "graphics:Assign.%UID%", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - std::string filename = json["filename"].asString(); - metadata["system"]["control"] = false; - - if ( uf::io::extension(filename) != "png" ) return "false"; - - uf::Scene& scene = this->getRootParent(); - uf::Asset& assetLoader = scene.getComponent(); - const uf::Image* imagePointer = NULL; - try { imagePointer = &assetLoader.get(filename); } catch ( ... ) {} - if ( !imagePointer ) return "false"; - - uf::Image image = *imagePointer; - // test overrides - { - manifests.overrides = metadata["atlas"]["overrides"]; - } - // assemble skeleton - { - auto& manifest = manifests.animation; - for ( int i = 0; i < manifest["bones"].size(); ++i ) { - auto& entry = manifest["bones"][i]; - std::string name = entry["name"].asString(); - - auto& bone = maps.skeleton[name]; - bone.name = name; - if ( entry["parent"].isString() ) bone.parent = entry["parent"].asString(); - if ( entry["x"].isNumeric() ) bone.position.x = entry["x"].asFloat(); - if ( entry["y"].isNumeric() ) bone.position.y = entry["y"].asFloat(); - if ( entry["length"].isNumeric() ) bone.length = entry["length"].asFloat(); - if ( entry["rotation"].isNumeric() ) bone.rotation = entry["rotation"].asFloat(); // * 3.14159f / 180.0f; - } - } - // create sprite attachments - { - auto& manifest = manifests.animation; - for ( int i = 0; i < manifest["skins"].size(); ++i ) { - std::string skinName = manifest["skins"][i]["name"].asString(); - if ( skinName == "damage" ) continue; - maps.skins[skinName] = manifest["skins"][i]["attachments"]; - } - } - // register slots - { - auto& manifest = manifests.animation; - for ( int i = 0; i < manifest["slots"].size(); ++i ) { - std::string slotName = manifest["slots"][i]["name"].asString(); - maps.slots[slotName] = manifest["slots"][i]; - } - } - // parse atlas - { - auto& manifest = manifests.atlas; - for ( auto it = manifest["pieces"].begin() ; it != manifest["pieces"].end() ; ++it ) { - std::string name = it.key().asString(); - pod::Vector2f sheetSize = { manifest["size"][0].asFloat(), manifest["size"][1].asFloat() }; - pod::Vector2f xy = { manifest["pieces"][name]["xy"][0].asFloat(), manifest["pieces"][name]["xy"][1].asFloat() }; - pod::Vector2f size = { manifest["pieces"][name]["size"][0].asFloat(), manifest["pieces"][name]["size"][1].asFloat() }; - float rotation = 0.0f; - auto& piece = maps.attachments[name]; - piece.size = size; - if ( manifest["pieces"][name]["rotate"].isNumeric() ) { - auto& rotation = piece.rotation; - auto& orientation = piece.orientation; - - rotation = manifest["pieces"][name]["rotate"].asFloat(); // * 3.14159f / 180.0f; - orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, rotation * 3.14159f / 180.0f ); - - pod::Vector3f rotated; - { - rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ size.x, size.y, 0 } ); - size.x = fabs(rotated.x); - size.y = fabs(rotated.y); - } - orientation = uf::quaternion::axisAngle( AXIS_OF_ROTATION, (rotation + 90) * 3.14159f / 180.0f ); - { - rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ size.x, size.y, 0 } ); - piece.size.x = fabs(rotated.x); - piece.size.y = fabs(rotated.y); - } - { - rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.topLeft.x, piece.position.topLeft.y, 0 } ); - piece.position.topLeft.x = rotated.x; - piece.position.topLeft.y = rotated.y; - } - { - rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.topRight.x, piece.position.topRight.y, 0 } ); - piece.position.topRight.x = rotated.x; - piece.position.topRight.y = rotated.y; - } - { - rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.bottomLeft.x, piece.position.bottomLeft.y, 0 } ); - piece.position.bottomLeft.x = rotated.x; - piece.position.bottomLeft.y = rotated.y; - } - { - rotated = uf::quaternion::rotate( orientation, pod::Vector3f{ piece.position.bottomRight.x, piece.position.bottomRight.y, 0 } ); - piece.position.bottomRight.x = rotated.x; - piece.position.bottomRight.y = rotated.y; - } - } - - piece.name = name; - piece.uv.min = ( xy ) / sheetSize; - piece.uv.max = ( xy + size ) / sheetSize; - piece.scale = size / sheetSize; - } - } - { - std::vector whitelist = {}; - for ( int i = 0; i < metadata["atlas"]["whitelist"].size(); ++i ) { - whitelist.emplace_back(metadata["atlas"]["whitelist"][i].asString()); - } - auto& manifest = manifests.atlas; - for ( auto it = manifest["pieces"].begin() ; it != manifest["pieces"].end() ; ++it ) { - std::string name = it.key().asString(); - if ( !whitelist.empty() && std::find( whitelist.begin(), whitelist.end(), name ) == whitelist.end() ) continue; - - auto& child = uf::instantiator::instantiate(); - uf::instantiator::bind( "LahSpinePieceBehavior", child ); - this->addChild(child); - child.initialize(); - - uf::Serializer payload; - payload["attachment"]["name"] = name; - payload["attachment"]["useMatrix"] = metadata["atlas"]["useMatrix"]; - payload["filename"] = json["filename"]; - child.queueHook("graphics:Assign.%UID%", payload); - - metadata["attachments"][name] = child.getUid(); - } - } - - return "true"; - }); - this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{ - this->queueHook("graphics:Assign.%UID%", event, 0.0f); - return "true"; - }); -} -void ext::LahSpineBehavior::tick( uf::Object& self ) {} -void ext::LahSpineBehavior::render( uf::Object& self ){ -} -void ext::LahSpineBehavior::destroy( uf::Object& self ){} -#undef this - -EXT_BEHAVIOR_REGISTER_CPP(LahSpinePieceBehavior) -#define this (&self) -void ext::LahSpinePieceBehavior::initialize( uf::Object& self ) { - uf::Scene& scene = uf::scene::getCurrentScene(); - uf::Serializer& metadata = this->getComponent(); - uf::Serializer& masterdata = scene.getComponent(); - uf::Asset& assetLoader = scene.getComponent(); - - this->addHook( "graphics:Assign.%UID%", [&](const std::string& event)->std::string{ - uf::Serializer json = event; - std::string filename = json["filename"].asString(); - metadata["system"]["control"] = false; - - if ( uf::io::extension(filename) != "png" ) return "false"; - - uf::Scene& scene = this->getRootParent(); - uf::Asset& assetLoader = scene.getComponent(); - const uf::Image* imagePointer = NULL; - try { imagePointer = &assetLoader.get(filename); } catch ( ... ) {} - if ( !imagePointer ) return "false"; - - uf::Image image = *imagePointer; - uf::Mesh& mesh = this->getComponent(); - auto& graphic = this->getComponent(); - auto& transform = this->getComponent>(); - - metadata["attachment"] = json["attachment"]; - - metadata["color"][0] = 1; - metadata["color"][1] = 1; - metadata["color"][2] = 1; - metadata["color"][3] = 1; - - std::string name = metadata["attachment"]["name"].asString(); - auto& attachment = maps.attachments[name]; - auto& slot = maps.slots[name]; - // transform.scale = { attachment.scale.x, attachment.scale.y, 1 }; - transform.scale = { 1.0f / 512.0f, 1.0f / 512.0f, 1 }; - - std::string boneName = slot["bone"].asString(); - transform.position = getPosition( boneName, true ); - transform.orientation = getOrientation( boneName, true ); - std::cout << "\"" << name << "\": {\"position\": [ " << transform.position.x << ", " << transform.position.y << " ], \"rotation\": " << getRotation( name, true ) << " }," << std::endl; - transform.position *= transform.scale; - struct { - pod::Vector2f position; - pod::Vector2f uv; - } topLeft, topRight, bottomLeft, bottomRight; - - { - topLeft.position = attachment.size * attachment.position.topLeft; - topRight.position = attachment.size * attachment.position.topRight; - bottomLeft.position = attachment.size * attachment.position.bottomLeft; - bottomRight.position = attachment.size * attachment.position.bottomRight; - } - { - topLeft.uv = { attachment.uv.min.x, 1.0f - attachment.uv.min.y }; - topRight.uv = { attachment.uv.max.x, 1.0f - attachment.uv.min.y }; - bottomLeft.uv = { attachment.uv.min.x, 1.0f - attachment.uv.max.y }; - bottomRight.uv = { attachment.uv.max.x, 1.0f - attachment.uv.max.y }; - } - - mesh.vertices = { - { { topLeft.position.x, topLeft.position.y, 0.0f }, topLeft.uv, { 0.0f, 0.0f, -1.0f } }, - { { topRight.position.x, topRight.position.y, 0.0f }, topRight.uv,{ 0.0f, 0.0f, -1.0f } }, - { { bottomRight.position.x, bottomRight.position.y, 0.0f }, bottomRight.uv, { 0.0f, 0.0f, -1.0f } }, - - { { bottomRight.position.x, bottomRight.position.y, 0.0f }, bottomRight.uv, { 0.0f, 0.0f, -1.0f } }, - { { bottomLeft.position.x, bottomLeft.position.y, 0.0f }, bottomLeft.uv, { 0.0f, 0.0f, -1.0f } }, - { { topLeft.position.x, topLeft.position.y, 0.0f }, topLeft.uv, { 0.0f, 0.0f, -1.0f } }, - }; - { - std::cout << name << ". Slot: " << slot << std::endl; - auto skin = getSkin( slot ); - struct WeightedVertex { - int boneId; - float weight; - pod::Vector2f position; - }; - struct SkinnedVertex { - std::vector weights; - pod::Vector2f position; - pod::Vector2f uv; - }; - std::vector skinnedVertices; - - std::cout << name << ", Vertices?:\n"; - for ( int i = 0; i < skin["vertices"].size(); ) { - int read = skin["vertices"][i++].asInt(); - auto& skinVertex = skinnedVertices.emplace_back(); - for ( int j = 0; j < read; ++j ) { - auto& weightedVertex = skinVertex.weights.emplace_back(); - weightedVertex.boneId = skin["vertices"][i++].asInt(); - weightedVertex.position.x = skin["vertices"][i++].asFloat(); - weightedVertex.position.y = skin["vertices"][i++].asFloat(); - weightedVertex.weight = skin["vertices"][i++].asFloat(); - } - } - for ( int i = 0; i < skinnedVertices.size(); ++i ) { - auto& skinVertex = skinnedVertices.at(i); - skinVertex.uv.x = skin["uvs"][(i*2+0)].asFloat(); - skinVertex.uv.y = skin["uvs"][(i*2+1)].asFloat(); - - // average - for ( auto& weightedVertex : skinVertex.weights ) { - std::string boneName = manifests.animation["bones"][weightedVertex.boneId]["name"].asString(); - auto bonePosition = getPosition( boneName, true ); - auto boneOrientation = getOrientation( boneName, true ); - - bonePosition = uf::quaternion::rotate( boneOrientation, bonePosition ); - auto rotatedVertex = uf::quaternion::rotate( boneOrientation, pod::Vector3f{ weightedVertex.position.x, weightedVertex.position.y, 0 } ); - skinVertex.position.x += (rotatedVertex.x + bonePosition.x) * weightedVertex.weight; - skinVertex.position.y += (rotatedVertex.y + bonePosition.y) * weightedVertex.weight; - // wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight; - } - } - for ( int i = 0; i < skinnedVertices.size(); ++i ) { - auto& skinVertex = skinnedVertices.at(i); - std::cout << "Index " << i << ":\n"; - for ( auto& weightedVertex : skinVertex.weights ) { - std::string boneName = manifests.animation["bones"][weightedVertex.boneId]["name"].asString(); - std::cout << "\tPosition: " << weightedVertex.position.x << ", " << weightedVertex.position.y << " | Bone ID: " << weightedVertex.boneId << " | Bone Name: " << boneName << " | Weight: " << weightedVertex.weight << "\n"; - } - std::cout << "\tUV: " << skinVertex.uv.x << ", " << skinVertex.uv.y << "\n"; - std::cout << "\tWeighted Position: " << skinVertex.position.x << ", " << skinVertex.position.y << "\n"; - } - - std::cout << std::endl; - std::cout << name << ", Triangles:\n"; - - mesh.vertices.clear(); - - for ( auto i = 0; i < skin["triangles"].size(); ) { - std::cout << "Triangle:\n"; - for ( int j = 0; j < 3; ++j ) { - int index = skin["triangles"][i++].asInt(); - auto& skinVertex = skinnedVertices.at(index); - struct { - pod::Vector2f interp; - } position, uv; - - uv.interp.x = std::lerp( attachment.uv.min.x, attachment.uv.max.x, skinVertex.uv.x ); - uv.interp.y = std::lerp( attachment.uv.min.y, attachment.uv.max.y, skinVertex.uv.y ); - - // uv.interp = skinVertex.uv; - position.interp.x = (uv.interp.x - 0.5f) * attachment.size.x; - position.interp.y = (uv.interp.y - 0.5f) * attachment.size.y; - - std::cout << "\tIndex: " << index << "\tUV: " << uv.interp.x << ", " << uv.interp.y << "\tPosition: " << position.interp.x << ", " << position.interp.y << "\n"; - - auto& vertex = mesh.vertices.emplace_back(); - // vertex.position.x = position.interp.x; - // vertex.position.y = position.interp.y; - - vertex.position.x = skinVertex.position.x; - vertex.position.y = skinVertex.position.y; - - vertex.position.z = 0; - vertex.uv.x = uv.interp.x; - vertex.uv.y = 1.0f - uv.interp.y; - vertex.normal = { 0, 0, -1 }; - } - std::cout << std::endl; - } - /* - std::cout << name << ", Triangles:\n"; - for ( auto i = 0; i < skin["triangles"].size(); i += 3 ) { - // std::cout << "\t" << skin["triangles"][i+0].asInt() << " " << skin["triangles"][i+1].asInt() << " " << skin["triangles"][i+2].asInt() << std::endl; - std::cout << "\t" << skin["uvs"][skin["triangles"][i+0].asInt()].asFloat() << " " << skin["uvs"][skin["triangles"][i+1].asInt()].asFloat() << " " << skin["uvs"][skin["triangles"][i+2].asInt()].asFloat() - } - */ - std::cout << name << ", " - << "UVs: " << skin["uvs"].size() << ", " - << "Positions: " << skin["vertices"].size() << ", " - << "Triangles: " << skin["triangles"].size() << ", " - << "Edges: " << skin["edges"].size() << ", " - << "Hull: " << skin["hull"] - << std::endl; - } - - graphic.initialize( "Gui" ); - graphic.initializeGeometry( mesh ); - - auto& texture = graphic.material.textures.emplace_back(); - texture.loadFromImage( image ); - - graphic.material.attachShader("./data/shaders/base.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT); - graphic.material.attachShader("./data/shaders/base.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT); - - metadata["system"]["control"] = true; - metadata["system"]["loaded"] = true; - - return "true"; - }); -} -void ext::LahSpinePieceBehavior::tick( uf::Object& self ) {} -void ext::LahSpinePieceBehavior::render( uf::Object& self ){ - uf::Serializer& metadata = this->getComponent(); - if ( !metadata["system"]["loaded"].asBool() ) return; - - /* Update uniforms */ if ( this->hasComponent() ) { - auto& mesh = this->getComponent(); - auto& scene = uf::scene::getCurrentScene(); - auto& graphic = this->getComponent(); - auto& transform = this->getComponent>(); - auto& camera = scene.getController().getComponent(); - if ( !graphic.initialized ) return; - auto& uniforms = graphic.material.shaders.front().uniforms.front().get(); - auto translation = uf::matrix::translate( uf::matrix::identity(), transform.position ); - auto rotation = uf::quaternion::matrix( transform.orientation ); - auto scale = uf::matrix::scale( uf::matrix::identity(), transform.scale ); - auto model = translation * rotation * scale; - - std::string name = metadata["attachment"]["name"].asString(); - auto& attachment = maps.attachments[name]; - auto bone = getMatrix( name, true ); - - uniforms.matrices.model = metadata["attachment"]["useMatrix"].asBool() ? bone : model; - - for ( std::size_t i = 0; i < 2; ++i ) { - uniforms.matrices.view[i] = camera.getView( i ); - uniforms.matrices.projection[i] = camera.getProjection( i ); - } - - uniforms.color[0] = metadata["color"][0].asFloat(); - uniforms.color[1] = metadata["color"][1].asFloat(); - uniforms.color[2] = metadata["color"][2].asFloat(); - uniforms.color[3] = metadata["color"][3].asFloat(); - graphic.material.shaders.front().updateBuffer( uniforms, 0, false ); - }; -} -void ext::LahSpinePieceBehavior::destroy( uf::Object& self ){} -#undef this \ No newline at end of file diff --git a/ext/behaviors/spine/behavior.h b/ext/behaviors/spine/behavior.h deleted file mode 100644 index a82dd486..00000000 --- a/ext/behaviors/spine/behavior.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace ext { - class EXT_API LahSpineBehavior { - public: - static void attach( uf::Object& ); - static void initialize( uf::Object& ); - static void tick( uf::Object& ); - static void render( uf::Object& ); - static void destroy( uf::Object& ); - }; - class EXT_API LahSpinePieceBehavior { - public: - static void attach( uf::Object& ); - static void initialize( uf::Object& ); - static void tick( uf::Object& ); - static void render( uf::Object& ); - static void destroy( uf::Object& ); - }; -} \ No newline at end of file diff --git a/ext/behaviors/staticemitter/behavior.cpp b/ext/behaviors/staticemitter/behavior.cpp index 6b19b69a..74567c21 100644 --- a/ext/behaviors/staticemitter/behavior.cpp +++ b/ext/behaviors/staticemitter/behavior.cpp @@ -11,8 +11,12 @@ EXT_BEHAVIOR_REGISTER_CPP(StaticEmitterBehavior) #define this ((uf::Object*) &self) void ext::StaticEmitterBehavior::initialize( uf::Object& self ) { auto& metadata = this->getComponent(); - auto* hud = this->loadChildPointer("/hud.json", true); - metadata["hud"]["uid"] = hud->getUid(); +// this->addHook( "system:Load.Finished.%UID%", [&](const std::string& event)->std::string{ +// uf::Serializer json = event; + auto* hud = this->loadChildPointer("/hud.json", true); + metadata["hud"]["uid"] = hud->getUid(); +// return "true"; +// }); } void ext::StaticEmitterBehavior::tick( uf::Object& self ) { auto& scene = uf::scene::getCurrentScene(); diff --git a/ext/gui/behavior.cpp b/ext/gui/behavior.cpp index 3e3187ee..396ee1f5 100644 --- a/ext/gui/behavior.cpp +++ b/ext/gui/behavior.cpp @@ -825,7 +825,7 @@ void ext::GuiBehavior::initialize( uf::Object& self ) { // graphic.descriptor.indices = 0; graphic.initializeGeometry( mesh ); graphic.getPipeline().update( graphic ); - uf::renderer::rebuild = true; + // uf::renderer::rebuild = true; /* graphic.destroy(); diff --git a/ext/main.cpp b/ext/main.cpp index f3e998b0..ddf22e9e 100644 --- a/ext/main.cpp +++ b/ext/main.cpp @@ -253,9 +253,8 @@ void EXT_API ext::initialize() { uf::renderer::initialize(); } /* */ { - pod::Thread& threadMain = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false, true ); - // pod::Thread& threadAux = uf::thread::has("Aux") ? uf::thread::get("Aux") : uf::thread::create( "Aux", true, false ); - pod::Thread& threadPhysics = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true, false ); + pod::Thread& threadMain = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false ); + pod::Thread& threadPhysics = uf::thread::has("Physics") ? uf::thread::get("Physics") : uf::thread::create( "Physics", true ); } /* Discord */ if ( ::config["engine"]["ex"]["discord"]["enabled"].asBool() ) { diff --git a/ext/scenes/raytrace/behavior.cpp b/ext/scenes/raytrace/behavior.cpp index ae0da4d8..6cbd9842 100644 --- a/ext/scenes/raytrace/behavior.cpp +++ b/ext/scenes/raytrace/behavior.cpp @@ -89,20 +89,22 @@ void ext::RayTracingSceneBehavior::tick( uf::Object& self ) { alignas(16) pod::Vector4f ambient; struct { alignas(8) pod::Vector2f range; + alignas(8) pod::Vector2f padding; alignas(16) pod::Vector4f color; } fog; struct Light { alignas(16) pod::Vector4f position; alignas(16) pod::Vector4f color; alignas(8) pod::Vector2i type; + alignas(8) pod::Vector2i padding; alignas(16) pod::Matrix4f view; alignas(16) pod::Matrix4f projection; } lights; }; struct SpecializationConstant { - uint32_t eyes = 2; uint32_t maxLights = 16; + uint32_t eyes = 2; } specializationConstants; auto& shader = renderMode.compute.material.shaders.front();