diff --git a/ECSAPI/ECS/test/test_conf.hpp b/ECSAPI/ECS/test/test_conf.hpp index 4aded49..5e6ec9e 100644 --- a/ECSAPI/ECS/test/test_conf.hpp +++ b/ECSAPI/ECS/test/test_conf.hpp @@ -11,12 +11,12 @@ struct WorldBenchmark : testing::Test { for (int16_t i = 0; i < 1000; i++) { - ee_economy::Container resources = {.capacity = 100.0}; + ee_economy::Container resources {.capacity = 100.0}; resources.add(ee_economy::RESOURCE_TYPE::COAL, 100.0); entt::entity state = world.registerState(i, resources); - ee_economy::EnterpriseDefaults miner = { - .container = {.capacity = 100.0}, + ee_economy::EnterpriseDefaults miner { + .container {.capacity = 100.0}, .resourceTarget = ee_economy::RESOURCE_TYPE::GOLD, .baseEfficiency = 1.0 }; diff --git a/ECSAPI/ECS/test/world.cpp b/ECSAPI/ECS/test/world.cpp index 3171c71..01d17ef 100644 --- a/ECSAPI/ECS/test/world.cpp +++ b/ECSAPI/ECS/test/world.cpp @@ -7,7 +7,7 @@ TEST(WorldTest, RegisterState) { ee_ecs::World world; - ee_economy::Container res = {.capacity = 100.0}; + ee_economy::Container res {.capacity = 100.0}; res.add(ee_economy::RESOURCE_TYPE::COAL, 98.0); entt::entity state = world.registerState(10, res); @@ -37,8 +37,8 @@ TEST(WorldTest, SpawnMiner) world.getRegistry().emplace(state, (int16_t)0); world.getRegistry().emplace(state, 100.0); - ee_economy::EnterpriseDefaults defaults = { - .container = {.capacity = 100.0 }, + ee_economy::EnterpriseDefaults defaults { + .container {.capacity = 100.0 }, .resourceTarget = ee_economy::RESOURCE_TYPE::COAL, .baseEfficiency = 1.0, }; @@ -62,8 +62,8 @@ TEST(WorldTest, SpawnDeliverer) world.getRegistry().emplace(state, (int16_t)0); world.getRegistry().emplace(state, 100.0); - ee_economy::EnterpriseDefaults defaults = { - .container = {.capacity = 100.0 }, + ee_economy::EnterpriseDefaults defaults { + .container {.capacity = 100.0 }, .resourceTarget = ee_economy::RESOURCE_TYPE::COAL, .baseEfficiency = 1.0, }; diff --git a/assets/shaders/helloworld.frag.spv b/assets/shaders/helloworld.frag.spv new file mode 100644 index 0000000..e14329e Binary files /dev/null and b/assets/shaders/helloworld.frag.spv differ diff --git a/assets/shaders/helloworld.vert.spv b/assets/shaders/helloworld.vert.spv new file mode 100644 index 0000000..428182b Binary files /dev/null and b/assets/shaders/helloworld.vert.spv differ diff --git a/frontend/include/AssetData.hpp b/frontend/include/AssetData.hpp index 2f449bd..a6924f6 100644 --- a/frontend/include/AssetData.hpp +++ b/frontend/include/AssetData.hpp @@ -12,4 +12,5 @@ struct AssetBinary : AssetData AssetBinary(uint8_t* &source, size_t sourceSize); ~AssetBinary(); -}; \ No newline at end of file +}; +typedef AssetBinary AssetShader; \ No newline at end of file diff --git a/frontend/include/AssetManager.hpp b/frontend/include/AssetManager.hpp index de0ec41..dd4ec23 100644 --- a/frontend/include/AssetManager.hpp +++ b/frontend/include/AssetManager.hpp @@ -27,6 +27,7 @@ public: BINARY, SHADER, + MATERIAL, IMAGE } type = BINARY; @@ -82,6 +83,8 @@ public: void Request(const AssetStreamCommand &command); void Request(const AssetStreamCommand::Type &type); + void LoadShaders(); + void LoadAsync(AssetInfo::Type type, const std::filesystem::path &path); AssetHandle& Find(const std::filesystem::path &path); void Redirect(AssetHandle &handle, void *resource); @@ -96,7 +99,7 @@ private: IFileSystem *diskSystem; std::vector activeAssets; - std::unordered_map assetsMapping; + std::unordered_map assetsMapping; std::vector freeAssetSlots; std::vector loadingEntries; @@ -111,7 +114,7 @@ private: template T& AssetManager::Get(const AssetHandle &handle) { std::atomic result; - AssetStreamCommand command = { + AssetStreamCommand command { .type = AssetStreamCommand::GET, .target = handle, .out = &result diff --git a/frontend/include/FileSystem.hpp b/frontend/include/FileSystem.hpp index 81c6e01..1df5a35 100644 --- a/frontend/include/FileSystem.hpp +++ b/frontend/include/FileSystem.hpp @@ -46,11 +46,13 @@ public: virtual FileHandle& Open(const std::filesystem::path &path, const uint32_t flags) = 0; virtual void ReadAsync(FileHandle &file, const uint32_t bufferSize, const uint32_t flags) = 0; virtual bool PollReady(FileHandle &file) = 0; - virtual void Close(const FileHandle &file) = 0; + virtual void Close(FileHandle &file) = 0; + + ~IFileSystem(); protected: - std::vector activeFiles; - std::vector failedFiles; + std::vector activeFiles; + std::vector failedFiles; std::vector freeFileSlots; }; @@ -60,7 +62,7 @@ public: FileHandle& Open(const std::filesystem::path &path, const uint32_t flags) override; void ReadAsync(FileHandle &file, const uint32_t bufferSize, uint32_t flags) override; bool PollReady(FileHandle &file) override; - void Close(const FileHandle &file) override; + void Close(FileHandle &file) override; private: diff --git a/frontend/src/AssetManager.cpp b/frontend/src/AssetManager.cpp index a1e7a03..adb6c62 100644 --- a/frontend/src/AssetManager.cpp +++ b/frontend/src/AssetManager.cpp @@ -1,6 +1,7 @@ #include "AssetManager.hpp" #include "allocator.hpp" #include "Logger.h" +#include AssetInfo::AssetInfo(void *resource) { @@ -81,7 +82,7 @@ void AssetManager::Request(const AssetStreamCommand::Type &type) void AssetManager::LoadAsync(AssetInfo::Type type, const std::filesystem::path &path) { - AssetStreamCommand command = { + AssetStreamCommand command { .type = AssetStreamCommand::LOAD, .targetPath = path, .targetType = type @@ -92,7 +93,7 @@ void AssetManager::LoadAsync(AssetInfo::Type type, const std::filesystem::path & AssetHandle& AssetManager::Find(const std::filesystem::path &path) { std::atomic result; - AssetStreamCommand command = { + AssetStreamCommand command { .type = AssetStreamCommand::FIND, .targetPath = path, .out = &result @@ -104,7 +105,7 @@ AssetHandle& AssetManager::Find(const std::filesystem::path &path) void AssetManager::Start() { - if (isRunning) throw std::exception("Asset Streaming can be started only once"); + if (isRunning) throw std::logic_error("Asset Streaming can be started only once"); isRunning.store(true); streamingThread = std::jthread([this](std::stop_token stop) { @@ -156,7 +157,7 @@ void AssetManager::Loop() //TODO: functions for each type switch (asset.type) { - case AssetInfo::SHADER: + case AssetInfo::MATERIAL: { break; } @@ -166,6 +167,7 @@ void AssetManager::Loop() break; } + case AssetInfo::SHADER: case AssetInfo::BINARY: default: { @@ -176,8 +178,13 @@ void AssetManager::Loop() } } - asset.isReady.store(true); + entry.fileOwner->Close(*entry.file); +#ifndef NDEBUG + auto path = entry.file->debugPath.c_str(); + LOG(INFO, "Asset loaded: [%s]", path); +#endif entry.file = nullptr; + asset.isReady.store(true); } } @@ -192,7 +199,7 @@ void AssetManager::ProcessCommand(AssetStreamCommand &command) { case AssetStreamCommand::LOAD: { - LOG(INFO, "LOAD command"); + LOG(INFO, "LOAD command: [%s]", command.targetPath.c_str()); /* TODO: process path to select FS */ /* TODO: select between async load and sync job task */ @@ -202,7 +209,7 @@ void AssetManager::ProcessCommand(AssetStreamCommand &command) diskSystem->ReadAsync(file, static_cast(file.size), FILE_READ_SEQUENTIAL); - AssetHandle handle; + AssetHandle* handle = Allocate(); AssetInfo asset(nullptr); asset.type = command.targetType; @@ -218,11 +225,11 @@ void AssetManager::ProcessCommand(AssetStreamCommand &command) activeAssets.push_back(std::move(asset)); assetPos = activeAssets.size() - 1; } - handle.id = assetPos; + handle->id = assetPos; assetsMapping[command.targetPath] = handle; - AssetLoadingEntry loadingEntry = { - .handle = handle, + AssetLoadingEntry loadingEntry { + .handle = *handle, .file = &file, .fileOwner = diskSystem }; @@ -234,12 +241,12 @@ void AssetManager::ProcessCommand(AssetStreamCommand &command) case AssetStreamCommand::FIND: { - std::unordered_map::iterator mapping = assetsMapping.find(command.targetPath); + std::unordered_map::iterator mapping = assetsMapping.find(command.targetPath); if (mapping == assetsMapping.end()) break; - command.out->store(&mapping->second); + command.out->store(mapping->second); command.type = AssetStreamCommand::COMPLETED; break; @@ -280,6 +287,20 @@ void AssetManager::Release() } activeAssets.clear(); + for (auto &mapping : assetsMapping) + Deallocate(mapping.second); + assetsMapping.clear(); + LOG(INFO, "Asset Streaming is released"); isRunning.store(false); +} + +void AssetManager::LoadShaders() +{ + std::filesystem::path shadersRoot = "assets/shaders"; + for (const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(shadersRoot)) + { + if (entry.is_directory()) continue; + LoadAsync(AssetInfo::SHADER, entry.path()); + } } \ No newline at end of file diff --git a/frontend/src/FileSystem.cpp b/frontend/src/FileSystem.cpp index 5823320..df92285 100644 --- a/frontend/src/FileSystem.cpp +++ b/frontend/src/FileSystem.cpp @@ -1,15 +1,24 @@ #include "FileSystem.hpp" #include "Logger.h" #include "allocator.hpp" +#include + +IFileSystem::~IFileSystem() +{ + for (FileHandle* handle : activeFiles) + Deallocate(handle); + for (FileHandle* handle : failedFiles) + Deallocate(handle); +} #ifdef _WIN32 FileHandle& NativeFileSystem::Open(const std::filesystem::path &path, const uint32_t flags) { - FileHandle result; + FileHandle* result = Allocate(); #ifndef NDEBUG - result.debugPath = path; + result->debugPath = path; #endif DWORD createFileMode = 0; @@ -33,78 +42,126 @@ FileHandle& NativeFileSystem::Open(const std::filesystem::path &path, const uint { LOG(ERROR, "Failed to open file %s. Error: %d", path.c_str(), GetLastError()); failedFiles.push_back(result); - return failedFiles[result.id]; + return *result; } - result.win32Handle = file; - result.size = GetFileSize(file, NULL); - if (result.size == INVALID_FILE_SIZE) + result->win32Handle = file; + result->size = GetFileSize(file, NULL); + if (result->size == INVALID_FILE_SIZE) LOG(ERROR, "Failed to get size of file %s. Error: %d", path.c_str(), GetLastError()); if (freeFileSlots.size() > 0) { - activeFiles[freeFileSlots.back()] = result; - result.id = freeFileSlots.back(); + size_t pos = freeFileSlots.back(); + result->id = pos; + activeFiles[pos] = result; freeFileSlots.pop_back(); } else { + result->id = activeFiles.size(); activeFiles.push_back(result); - result.id = activeFiles.size() - 1; } - return activeFiles[result.id]; + return *result; } void NativeFileSystem::ReadAsync(FileHandle &file, const uint32_t bufferSize, const uint32_t flags) { - file.overlapped = {}; + file.overlapped = { + .hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr) + }; file.buffer = AllocateArray(bufferSize); - ReadFile( + BOOL isSync = ReadFile( file.win32Handle, file.buffer, bufferSize, NULL, &file.overlapped ); + + if (isSync || GetLastError() != ERROR_IO_PENDING) + LOG(ERROR, "File reading is synchronious while asynchronious is awaited"); } bool NativeFileSystem::PollReady(FileHandle &file) { - DWORD transferredSize = 0L; - BOOL status = GetOverlappedResult( - file.win32Handle, - &file.overlapped, - &transferredSize, - FALSE - ); - if (!status && GetLastError() != ERROR_IO_INCOMPLETE) - { - LOG(ERROR, "Error in file status. Code: %d", GetLastError()); - return false; - } + // DWORD transferredSize = 0L; + // BOOL status = GetOverlappedResult( + // file.win32Handle, + // &file.overlapped, + // &transferredSize, + // FALSE + // ); + + // DWORD error = GetLastError(); + // if (!status && error != ERROR_IO_INCOMPLETE) + // { + // LOG(CRITICAL, "Error in reading file status. Code: %d", error); + // throw std::runtime_error("Error in reading file status"); + // } - if (file.size == transferredSize) - { - file.data = file.buffer; - } - else - { - /* TODO: reserve size for data, shift and move */ - } - file.buffer = nullptr; + // if (file.size == transferredSize) + // { + // file.data = file.buffer; + // } + // else + // { + // /* TODO: reserve size for data, shift and move */ + // } + // file.buffer = nullptr; - return status; + DWORD status = WaitForSingleObject(file.overlapped.hEvent, 0); + + switch (status) + { + case WAIT_OBJECT_0: + { + if (file.size == file.bufferSize) + { + file.data = file.buffer; + } + else + { + /* TODO: reserve size for data, shift and move */ + } + + break; + } + + case WAIT_ABANDONED: + case WAIT_TIMEOUT: + return false; + + default: + { + LOG(CRITICAL, "Failed to get file status. Error: %d", GetLastError()); + throw std::runtime_error("Failed to get file status"); + } + } + + return true; } -void NativeFileSystem::Close(const FileHandle &file) +void NativeFileSystem::Close(FileHandle &file) { - DeallocateArray(file.buffer); - DeallocateArray(file.data); + if (file.buffer != nullptr) + { + DeallocateArray(file.buffer); + file.buffer = nullptr; + } + if (file.data != nullptr) + { + DeallocateArray(file.data); + file.data = nullptr; + } - CloseHandle(file.win32Handle); - activeFiles[file.id].win32Handle = INVALID_HANDLE_VALUE; + if (file.win32Handle != INVALID_HANDLE_VALUE) + { + CloseHandle(file.win32Handle); + file.win32Handle = INVALID_HANDLE_VALUE; + } freeFileSlots.push_back(file.id); } diff --git a/frontend/src/Renderer.cpp b/frontend/src/Renderer.cpp index f84a806..80bdca9 100644 --- a/frontend/src/Renderer.cpp +++ b/frontend/src/Renderer.cpp @@ -6,8 +6,8 @@ #include "Logger.h" #include #include -#include #include +#include Renderer::Renderer(SDL_Window *window) : isRunning(false) { @@ -228,7 +228,7 @@ void Renderer::SetupDevice() if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) priority += GPU_DISCRETE_PRIORITY; - for (VkSurfaceFormatKHR format : surfaceInfoBuffer.availableFormats) + for (const VkSurfaceFormatKHR &format : surfaceInfoBuffer.availableFormats) { surfaceInfoBuffer.format = format; if (format.format == VK_FORMAT_B8G8R8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) @@ -239,7 +239,7 @@ void Renderer::SetupDevice() } surfaceInfoBuffer.presentMode = VK_PRESENT_MODE_FIFO_KHR; - for (VkPresentModeKHR presentMode : surfaceInfoBuffer.availablePresentModes) + for (const VkPresentModeKHR &presentMode : surfaceInfoBuffer.availablePresentModes) { if (presentMode == VK_PRESENT_MODE_FIFO_RELAXED_KHR) { @@ -265,7 +265,7 @@ void Renderer::SetupDevice() // Define queues std::vector queuesCreateConfigs; - std::set uniqueQueueFamilies = { + std::set uniqueQueueFamilies { queueFamilies.graphics, queueFamilies.present }; @@ -284,11 +284,11 @@ void Renderer::SetupDevice() } // Create logical device - std::vector deviceExtensions = { + std::vector deviceExtensions { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; - VkDeviceCreateInfo deviceInfo = { + VkDeviceCreateInfo deviceInfo { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = nullptr, .queueCreateInfoCount = static_cast(queuesCreateConfigs.size()), @@ -355,7 +355,7 @@ void Renderer::SetupSwapchain() if (queueFamilies.graphics != queueFamilies.present) { - uint32_t queueFamiliesShare[] = {queueFamilies.graphics, queueFamilies.present}; + uint32_t queueFamiliesShare[] {queueFamilies.graphics, queueFamilies.present}; swapchainCreateConfig.imageSharingMode = VK_SHARING_MODE_CONCURRENT; swapchainCreateConfig.queueFamilyIndexCount = 2; swapchainCreateConfig.pQueueFamilyIndices = queueFamiliesShare; @@ -386,13 +386,13 @@ void Renderer::SetupSwapchain() .image = frames[i], .viewType = VK_IMAGE_VIEW_TYPE_2D, .format = surfaceInfo.format.format, - .components = { + .components { .r = VK_COMPONENT_SWIZZLE_IDENTITY, .g = VK_COMPONENT_SWIZZLE_IDENTITY, .b = VK_COMPONENT_SWIZZLE_IDENTITY, .a = VK_COMPONENT_SWIZZLE_IDENTITY }, - .subresourceRange = { + .subresourceRange { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .baseMipLevel = 0, .levelCount = 1, @@ -413,7 +413,7 @@ void Renderer::Start() if (isRunning) { LOG(CRITICAL, "Renderer can be started only once"); - throw std::exception("Renderer can be started only once"); + throw std::logic_error("Renderer can be started only once"); } isRunning.store(true); @@ -493,7 +493,7 @@ void Renderer::Request(const RenderCommand::Type &type) void Renderer::Release() { - for (VkImageView frameView : frameViews) + for (VkImageView &frameView : frameViews) { vkDestroyImageView(device, frameView, nullptr); } diff --git a/frontend/src/main.cpp b/frontend/src/main.cpp index 3e3d5c4..7ebd423 100644 --- a/frontend/src/main.cpp +++ b/frontend/src/main.cpp @@ -43,6 +43,7 @@ int SDL_main(int argc, char **argv) // Setup assets AssetManager assetManager; assetManager.Start(); + assetManager.LoadShaders(); // Setup Renderer Renderer renderer(window); diff --git a/shaders/helloworld/helloworld.frag b/shaders/helloworld/helloworld.frag new file mode 100644 index 0000000..9e32b50 --- /dev/null +++ b/shaders/helloworld/helloworld.frag @@ -0,0 +1,8 @@ +#version 330 +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) out vec4 outColor; + +void main() { + outColor = vec4(1.0, 0.0, 0.0, 1.0); +} \ No newline at end of file diff --git a/shaders/helloworld/helloworld.vert b/shaders/helloworld/helloworld.vert new file mode 100644 index 0000000..d83cd4c --- /dev/null +++ b/shaders/helloworld/helloworld.vert @@ -0,0 +1,12 @@ +#version 330 + +vec2 positions[3] = vec2[]( + vec2(-1.0, 1.0), + vec2(0.0, -1.0), + vec2(1.0, 1.0) +); + +void main() +{ + gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); +} \ No newline at end of file