diff --git a/CMakeLists.txt b/CMakeLists.txt index 524f8c9..9835ffa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,9 @@ -cmake_minimum_required(VERSION 3.7 FATAL_ERROR) +cmake_minimum_required(VERSION 3.16 FATAL_ERROR) -find_package(ECM REQUIRED NO_MODULE) -set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) +if(NOT WIN32) + find_package(ECM REQUIRED NO_MODULE) + set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) +endif() #set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin") @@ -55,11 +57,12 @@ include_directories(external/assimp) IF(WIN32) find_library(ASSIMP_LIBRARIES NAMES assimp libassimp.dll.a PATHS ${CMAKE_SOURCE_DIR}/libs/assimp) ELSE(WIN32) - find_package(ASSIMP REQUIRED) + find_package(assimp REQUIRED) ENDIF(WIN32) -target_sources(openVulkanoCpp PRIVATE openVulkanoCpp/Vulkan/FrameBuffer.cpp openVulkanoCpp/Base/Logger.cpp openVulkanoCpp/Scene/Drawable.cpp openVulkanoCpp/Scene/Node.cpp) +target_sources(openVulkanoCpp PRIVATE openVulkanoCpp/Vulkan/FrameBuffer.cpp openVulkanoCpp/Base/Logger.cpp openVulkanoCpp/Scene/Drawable.cpp openVulkanoCpp/Scene/Node.cpp openVulkanoCpp/Host/GLFW/InputProviderGLFW.cpp) # copy shaders file(GLOB SHADERS "openVulkanoCpp/Shader/*.spv") -file(COPY ${SHADERS} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/Shader/) \ No newline at end of file +file(COPY ${SHADERS} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}/Shader/) +file(COPY ${SHADERS} DESTINATION ${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}/Shader/) \ No newline at end of file diff --git a/cmake/modules/FindWayland.cmake b/cmake/modules/FindWayland.cmake new file mode 100644 index 0000000..f93218b --- /dev/null +++ b/cmake/modules/FindWayland.cmake @@ -0,0 +1,66 @@ +# Try to find Wayland on a Unix system +# +# This will define: +# +# WAYLAND_FOUND - True if Wayland is found +# WAYLAND_LIBRARIES - Link these to use Wayland +# WAYLAND_INCLUDE_DIR - Include directory for Wayland +# WAYLAND_DEFINITIONS - Compiler flags for using Wayland +# +# In addition the following more fine grained variables will be defined: +# +# WAYLAND_CLIENT_FOUND WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES +# WAYLAND_SERVER_FOUND WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES +# WAYLAND_EGL_FOUND WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES +# +# Copyright (c) 2013 Martin Gräßlin +# +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +IF (NOT WIN32) + IF (WAYLAND_INCLUDE_DIR AND WAYLAND_LIBRARIES) + # In the cache already + SET(WAYLAND_FIND_QUIETLY TRUE) + ENDIF () + + # Use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + FIND_PACKAGE(PkgConfig) + PKG_CHECK_MODULES(PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl wayland-cursor) + + SET(WAYLAND_DEFINITIONS ${PKG_WAYLAND_CFLAGS}) + + FIND_PATH(WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) + FIND_PATH(WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) + FIND_PATH(WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) + FIND_PATH(WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS ${PKG_WAYLAND_INCLUDE_DIRS}) + + FIND_LIBRARY(WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) + FIND_LIBRARY(WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) + FIND_LIBRARY(WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) + FIND_LIBRARY(WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS ${PKG_WAYLAND_LIBRARY_DIRS}) + + set(WAYLAND_INCLUDE_DIR ${WAYLAND_CLIENT_INCLUDE_DIR} ${WAYLAND_SERVER_INCLUDE_DIR} ${WAYLAND_EGL_INCLUDE_DIR} ${WAYLAND_CURSOR_INCLUDE_DIR}) + + set(WAYLAND_LIBRARIES ${WAYLAND_CLIENT_LIBRARIES} ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_EGL_LIBRARIES} ${WAYLAND_CURSOR_LIBRARIES}) + + list(REMOVE_DUPLICATES WAYLAND_INCLUDE_DIR) + + include(FindPackageHandleStandardArgs) + + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CLIENT DEFAULT_MSG WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_SERVER DEFAULT_MSG WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_EGL DEFAULT_MSG WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND_CURSOR DEFAULT_MSG WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR) + + MARK_AS_ADVANCED( + WAYLAND_INCLUDE_DIR WAYLAND_LIBRARIES + WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES + WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES + WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES + WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES + ) + +ENDIF () diff --git a/openVulkanoCpp/Host/GLFW/InputProviderGLFW.hpp b/openVulkanoCpp/Host/GLFW/InputProviderGLFW.hpp index 3a80443..23a0f22 100644 --- a/openVulkanoCpp/Host/GLFW/InputProviderGLFW.hpp +++ b/openVulkanoCpp/Host/GLFW/InputProviderGLFW.hpp @@ -22,6 +22,7 @@ namespace openVulkanoCpp MouseGLFW mouse; KeyboardGLFW keyboard; uint8_t mouseButtons = 0; + bool activeWindowChanged = false; public: void Init() override; @@ -45,11 +46,16 @@ namespace openVulkanoCpp controller.Tick(); } mouse.UpdateButtons(mouseButtons); + if (activeWindowChanged) + { + mouse.ClearAxes(); + activeWindowChanged = false; + } } void SetMouseButton(int button, bool state) { - uint8_t bit = 1 << button; + const uint8_t bit = 1 << button; if (state) { mouseButtons |= bit; @@ -64,6 +70,7 @@ namespace openVulkanoCpp void MouseEnterExitWindow(IWindow* window) { + activeWindowChanged = true; mouse.UpdateActiveWindow(window); keyboard.UpdateActiveWindow(window); } diff --git a/openVulkanoCpp/Host/GLFW/WindowGLFW.hpp b/openVulkanoCpp/Host/GLFW/WindowGLFW.hpp index 492d5c6..252c8e4 100644 --- a/openVulkanoCpp/Host/GLFW/WindowGLFW.hpp +++ b/openVulkanoCpp/Host/GLFW/WindowGLFW.hpp @@ -263,7 +263,7 @@ namespace openVulkanoCpp { VkSurfaceKHR rawSurface; const auto result = static_cast(glfwCreateWindowSurface(static_cast(instance), window, reinterpret_cast(pAllocator), &rawSurface)); - return createResultValue(result, rawSurface, "vk::CommandBuffer::begin"); + return std::move(rawSurface);//createResultValue(result, rawSurface, "vk::CommandBuffer::begin"); } std::vector GetRequiredInstanceExtensions() override diff --git a/openVulkanoCpp/Input/InputDeviceMouse.hpp b/openVulkanoCpp/Input/InputDeviceMouse.hpp index 64b464d..3e6f739 100644 --- a/openVulkanoCpp/Input/InputDeviceMouse.hpp +++ b/openVulkanoCpp/Input/InputDeviceMouse.hpp @@ -35,7 +35,7 @@ namespace openVulkanoCpp lastPressedButtons = pressedButtons; pressedButtons = newPressedButtons; if (lastPressedButtons != pressedButtons) - Logger::INPUT->info("Mouse button state changed {0:08b}", pressedButtons); + Logger::INPUT->debug("Mouse button state changed {0:08b}", pressedButtons); } void UpdatePosition(double posX, double posY) @@ -44,20 +44,19 @@ namespace openVulkanoCpp axes[InputKey::Mouse::AXIS_Y] = static_cast(posY - mousePosY); mousePosX = posX; mousePosY = posY; - Logger::INPUT->info("Mouse moved posX: {0} posY: {1}, relativeX: {2}, relativeY: {3}", posX, posY, axes[InputKey::Mouse::AXIS_X], axes[InputKey::Mouse::AXIS_Y]); + Logger::INPUT->debug("Mouse moved posX: {0} posY: {1}, relativeX: {2}, relativeY: {3}", posX, posY, axes[InputKey::Mouse::AXIS_X], axes[InputKey::Mouse::AXIS_Y]); } void UpdateWheel(float wheelX, float wheelY) { axes[InputKey::Mouse::AXIS_WHEEL_X] = wheelX; axes[InputKey::Mouse::AXIS_WHEEL_Y] = wheelY; - Logger::INPUT->info("Mouse scrolled x: {0} y: {1}", wheelX, wheelY); + Logger::INPUT->debug("Mouse scrolled x: {0} y: {1}", wheelX, wheelY); } void UpdateActiveWindow(IWindow* window) { - axes[InputKey::Mouse::AXIS_X] = 0; - axes[InputKey::Mouse::AXIS_Y] = 0; + ClearAxes(); lastWindow = window; } diff --git a/openVulkanoCpp/Vulkan/Device.hpp b/openVulkanoCpp/Vulkan/Device.hpp index 32495cd..e1d6d01 100644 --- a/openVulkanoCpp/Vulkan/Device.hpp +++ b/openVulkanoCpp/Vulkan/Device.hpp @@ -268,6 +268,11 @@ namespace openVulkanoCpp return result; } + vk::MemoryPropertyFlags GetMemoryFlags(uint32_t memoryType) const + { + return memoryProperties.memoryTypes[memoryType].propertyFlags; + } + void Close() override { diff --git a/openVulkanoCpp/Vulkan/Resources/IShaderOwner.hpp b/openVulkanoCpp/Vulkan/Resources/IShaderOwner.hpp index 9af850f..3760603 100644 --- a/openVulkanoCpp/Vulkan/Resources/IShaderOwner.hpp +++ b/openVulkanoCpp/Vulkan/Resources/IShaderOwner.hpp @@ -10,6 +10,8 @@ namespace openVulkanoCpp class IShaderOwner { public: + virtual ~IShaderOwner() = default; + virtual void RemoveShader(VulkanShader* shader) = 0; }; } diff --git a/openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp b/openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp index 0b0c8da..2fe1ae4 100644 --- a/openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp @@ -1,4 +1,7 @@ #pragma once + +#define CRASH_ON_MULTIPLE_MAPPINGS_TO_SAME_ALLOCATION + #include namespace openVulkanoCpp @@ -8,21 +11,83 @@ namespace openVulkanoCpp struct MemoryAllocation { vk::DeviceMemory memory; - size_t used, size; - uint32_t type; + size_t used; + const size_t size; + const uint32_t type; + const vk::Device device; + void* mapped; - MemoryAllocation(size_t size, uint32_t type) + private: + uint32_t mappedCount; + static constexpr uint32_t CHILD_MAPPED_FLAG = 1u << 31; + + public: + MemoryAllocation(size_t size, uint32_t type, vk::Device device): + memory(nullptr), used(0), size(size), type(type), device(device), mapped(nullptr), mappedCount(0) { - memory = nullptr; - this->size = size; - used = 0; - this->type = type; } size_t FreeSpace() const { return size - used; } + + void HandleChildMappingValidation() const + { + if (IsChildMapped()) + { + Logger::RENDER->error("A single memory allocation should only be mapped once! Mapping a single allocation multiple times might not work or might not work reliable with all driver implementations."); +#ifdef CRASH_ON_MULTIPLE_MAPPINGS_TO_SAME_ALLOCATION + throw std::runtime_error("A single memory allocation should only be mapped once!"); +#endif + } + } + + void* Map() + { + HandleChildMappingValidation(); + if (!mapped) + { + mapped = device.mapMemory(memory, 0, size, vk::MemoryMapFlags()); + } + mappedCount++; + return mapped; + } + + void UnMap() + { + if (mappedCount > 0) + { + mappedCount--; + if (mappedCount == 0) + { + device.unmapMemory(memory); + } + } + } + + bool IsChildMapped() const + { + return mappedCount & CHILD_MAPPED_FLAG; + } + + void* MapChild(size_t offset, vk::DeviceSize size) + { + HandleChildMappingValidation(); + mappedCount |= CHILD_MAPPED_FLAG; + mappedCount++; + return device.mapMemory(memory, offset, size, vk::MemoryMapFlags()); + } + + void UnMapChild() + { + mappedCount &= ~CHILD_MAPPED_FLAG; + mappedCount--; + if (mappedCount == 0) + { + device.unmapMemory(memory); + } + } }; struct ManagedBuffer @@ -32,27 +97,43 @@ namespace openVulkanoCpp vk::Buffer buffer; vk::BufferUsageFlags usage; vk::MemoryPropertyFlags properties; - vk::Device device; void* mapped = nullptr; - bool IsLast() + bool IsLast() const { return (offset + size == allocation->used); } + bool IsMapped() const + { + return mapped || allocation->mapped; + } + /** * \brief Maps the buffer into the memory of the host. * \tparam T The type of the buffers data. * \param offset The offset from where to map the buffer. * \param size The size to be mapped. VK_WHOLE_SIZE to map the whole buffer. + * \pparam longTermMapping If the mapping is intended to be held long term. Short term mappings must be freed before mapping a different region in the same memory allocation for them to work reliable with all drivers. * \return The pointer to the mapped buffer. */ template - T* Map(size_t offset = 0, vk::DeviceSize size = VK_WHOLE_SIZE) + T* Map(size_t offset = 0, vk::DeviceSize size = VK_WHOLE_SIZE, bool longTermMapping = true) { - if (size == VK_WHOLE_SIZE) size = this->size; - mapped = device.mapMemory(allocation->memory, this->offset + offset, size, vk::MemoryMapFlags()); - return static_cast(mapped); + if (!mapped) + { + if (allocation->mapped || longTermMapping) + { + mapped = static_cast(allocation->Map()) + offset + this->offset; + } + else + { + if (size == VK_WHOLE_SIZE) size = this->size; + mapped = allocation->MapChild(this->offset + offset, size); + } + + return static_cast(mapped); + } } /** @@ -60,32 +141,42 @@ namespace openVulkanoCpp */ void UnMap() { - device.unmapMemory(allocation->memory); - mapped = nullptr; + if (mapped) + { + if (allocation->mapped) + { + allocation->UnMap(); + } + else + { + allocation->UnMapChild(); + } + mapped = nullptr; + } } - void Copy(void* data) const + void Copy(void* data) { - if(mapped) + if (mapped) { memcpy(mapped, data, size); } else { - void* dataMapped = device.mapMemory(allocation->memory, offset, size); + void* dataMapped = Map(0, VK_WHOLE_SIZE, false); memcpy(dataMapped, data, size); - device.unmapMemory(allocation->memory); + UnMap(); } } - void Copy(void* data, uint32_t size, uint32_t offset) const + void Copy(void* data, uint32_t size, uint32_t offset) { if(mapped) memcpy(static_cast(mapped) + offset, data, size); else { - void* dataMapped = device.mapMemory(allocation->memory, this->offset + offset, size); + void* dataMapped = Map(offset, size, false); memcpy(dataMapped, data, size); - device.unmapMemory(allocation->memory); + UnMap(); } } }; diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp index 47ba50a..f7fb963 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp @@ -217,12 +217,12 @@ namespace openVulkanoCpp uint32_t offset = allocation->used; device.bindBufferMemory(buffer, allocation->memory, offset); allocation->used += memoryRequirements.size; - return new ManagedBuffer{ allocation, offset, size, buffer, usage, properties, device, nullptr }; + return new ManagedBuffer{ allocation, offset, size, buffer, usage, properties, nullptr }; } MemoryAllocation* CreateMemoryAllocation(size_t size, uint32_t type, bool addToCache = true) { - MemoryAllocation* alloc = new MemoryAllocation(size, type); + MemoryAllocation* alloc = new MemoryAllocation(size, type, device); const vk::MemoryAllocateInfo allocInfo = { size, type }; alloc->memory = device.allocateMemory(allocInfo); if (addToCache) allocations.push_back(alloc); diff --git a/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp b/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp index 1a91157..da762e0 100644 --- a/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp +++ b/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp @@ -22,15 +22,15 @@ namespace openVulkanoCpp this->allocSizeFrame = allocSizeFrame; vk::DescriptorPoolSize poolSize = { vk::DescriptorType::eUniformBufferDynamic, 1 }; const vk::DescriptorPoolCreateInfo poolCreateInfo = { {}, 1, 1, &poolSize }; - descPool = buffer->device.createDescriptorPool(poolCreateInfo); + descPool = buffer->allocation->device.createDescriptorPool(poolCreateInfo); const vk::DescriptorSetAllocateInfo descSetAllocInfo = { descPool, 1, descriptorSetLayout }; - descSet = buffer->device.allocateDescriptorSets(descSetAllocInfo)[0]; + descSet = buffer->allocation->device.allocateDescriptorSets(descSetAllocInfo)[0]; vk::DescriptorBufferInfo bufferInfo = { buffer->buffer, 0, allocSizeFrame }; vk::WriteDescriptorSet writeDescriptorSet = { descSet }; writeDescriptorSet.descriptorCount = 1; writeDescriptorSet.descriptorType = vk::DescriptorType::eUniformBufferDynamic; writeDescriptorSet.pBufferInfo = &bufferInfo; - buffer->device.updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr); + buffer->allocation->device.updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr); } void Record(vk::CommandBuffer& cmdBuffer, uint32_t bufferId) override @@ -47,7 +47,7 @@ namespace openVulkanoCpp void Close() override { - buffer->device.destroyDescriptorPool(descPool); + buffer->allocation->device.destroyDescriptorPool(descPool); } }; } diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp index 46de025..e6c0f36 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp @@ -75,7 +75,7 @@ namespace openVulkanoCpp vk::GraphicsPipelineCreateInfo pipelineCreateInfo = { {}, static_cast(shaderStageCreateInfos.size()), shaderStageCreateInfos.data(), &pipelineVertexInputStateCreateInfo, &inputAssembly, nullptr, &viewportStateCreateInfo, &rasterizer, &msaa, &depth, &colorInfo, nullptr, context->pipeline.pipelineLayout, context->swapChainRenderPass.renderPass }; - pipeline = this->device.createGraphicsPipeline({}, pipelineCreateInfo); + pipeline = this->device.createGraphicsPipeline({}, pipelineCreateInfo).value; }