From ad60a17da935449fc4bef8382cc8df70c90e16da Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Tue, 14 Nov 2023 07:07:43 +0100 Subject: [PATCH] fixing rendering issues --- Makefile | 7 ++- src/core/application.cpp | 4 +- src/core/graphics.cpp | 14 ++++- src/renderer/buffers/vk_buffer.cpp | 52 ++++++++++++------- src/renderer/buffers/vk_buffer.h | 15 +++--- src/renderer/buffers/vk_ibo.h | 6 +-- src/renderer/buffers/vk_ubo.cpp | 8 +-- src/renderer/buffers/vk_ubo.h | 4 +- src/renderer/buffers/vk_vbo.h | 6 +-- src/renderer/core/memory.cpp | 40 +++++++++++--- src/renderer/core/memory.h | 8 +-- src/renderer/core/render_core.h | 4 +- src/renderer/core/vk_device.cpp | 6 +-- .../descriptors/vk_descriptor_set.cpp | 2 +- src/renderer/images/texture.cpp | 22 ++++---- src/renderer/images/texture.h | 5 +- src/renderer/images/texture_atlas.cpp | 19 +++---- src/renderer/images/texture_atlas.h | 4 +- src/renderer/images/vk_image.cpp | 27 ++++++---- src/renderer/images/vk_image.h | 5 +- src/renderer/pixel_put.cpp | 6 +-- src/renderer/renderer.cpp | 4 +- src/renderer/text_library.cpp | 6 +-- src/renderer/text_pipeline.cpp | 4 +- test/.gdb_history | 10 ---- 25 files changed, 171 insertions(+), 117 deletions(-) delete mode 100644 test/.gdb_history diff --git a/Makefile b/Makefile index 25852ed..b098f54 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: maldavid +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2022/10/04 16:43:41 by maldavid #+# #+# # -# Updated: 2023/11/10 23:55:12 by maldavid ### ########.fr # +# Updated: 2023/11/13 06:08:16 by maldavid ### ########.fr # # # # **************************************************************************** # @@ -24,6 +24,7 @@ DEBUG ?= false TOOLCHAIN ?= clang IMAGES_OPTIMIZED ?= true FORCE_INTEGRATED_GPU ?= false +GRAPHICS_MEMORY_DUMP ?= false CXX = clang++ @@ -52,6 +53,10 @@ ifeq ($(IMAGES_OPTIMIZED), true) CXXFLAGS += -D IMAGE_OPTIMIZED endif +ifeq ($(GRAPHICS_MEMORY_DUMP), true) + CXXFLAGS += -D GRAPHICS_MEMORY_DUMP +endif + RM = rm -f %.o: %.cpp diff --git a/src/core/application.cpp b/src/core/application.cpp index adb3ccf..f717ecd 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 22:10:52 by maldavid #+# #+# */ -/* Updated: 2023/11/10 09:06:44 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 03:20:40 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -44,7 +44,7 @@ namespace mlx::core void* Application::newTexture(int w, int h) { - _textures.emplace_front().create(nullptr, w, h, VK_FORMAT_R8G8B8A8_UNORM); + _textures.emplace_front().create(nullptr, w, h, VK_FORMAT_R8G8B8A8_UNORM, "__mlx_unamed_user_texture"); return &_textures.front(); } diff --git a/src/core/graphics.cpp b/src/core/graphics.cpp index 8bee267..fd052ef 100644 --- a/src/core/graphics.cpp +++ b/src/core/graphics.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/04/02 15:13:55 by maldavid #+# #+# */ -/* Updated: 2023/11/08 21:02:22 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 06:59:12 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -54,11 +54,21 @@ namespace mlx sets[1] = _text_put_pipeline->getDescriptorSet(); vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, _renderer->getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr); _text_put_pipeline->render(); - + _renderer->endFrame(); for(auto& data : _textures_to_render) data.texture->resetUpdate(); + + #ifdef GRAPHICS_MEMORY_DUMP + // dump memory to file every two seconds + static uint64_t timer = SDL_GetTicks64(); + if(SDL_GetTicks64() - timer > 2000) + { + Render_Core::get().getAllocator().dumpMemoryToJson(); + timer += 2000; + } + #endif } GraphicsSupport::~GraphicsSupport() diff --git a/src/renderer/buffers/vk_buffer.cpp b/src/renderer/buffers/vk_buffer.cpp index 67ad5c7..7cacb41 100644 --- a/src/renderer/buffers/vk_buffer.cpp +++ b/src/renderer/buffers/vk_buffer.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 18:55:57 by maldavid #+# #+# */ -/* Updated: 2023/11/11 03:27:31 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 07:06:17 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,11 +19,9 @@ namespace mlx { - void Buffer::create(Buffer::kind type, VkDeviceSize size, VkBufferUsageFlags usage, const void* data) + void Buffer::create(Buffer::kind type, VkDeviceSize size, VkBufferUsageFlags usage, const char* name, const void* data) { _usage = usage; - VmaAllocationCreateInfo alloc_info{}; - alloc_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; if(type == Buffer::kind::constant) { if(data == nullptr) @@ -32,22 +30,20 @@ namespace mlx return; } _usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST; } - else if(type == Buffer::kind::uniform) - alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_HOST; - else - alloc_info.usage = VMA_MEMORY_USAGE_AUTO; - createBuffer(_usage, alloc_info, size); + VmaAllocationCreateInfo alloc_info{}; + alloc_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; + alloc_info.usage = VMA_MEMORY_USAGE_AUTO; - if(type == Buffer::kind::constant || data != nullptr) + createBuffer(_usage, alloc_info, size, name); + + if(data != nullptr) { void* mapped = nullptr; mapMem(&mapped); std::memcpy(mapped, data, size); unmapMem(); - if(type == Buffer::kind::constant) pushToGPU(); } @@ -60,7 +56,7 @@ namespace mlx Render_Core::get().getAllocator().destroyBuffer(_allocation, _buffer); } - void Buffer::createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size) + void Buffer::createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size, const char* name) { VkBufferCreateInfo bufferInfo{}; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; @@ -68,7 +64,15 @@ namespace mlx bufferInfo.usage = usage; bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - _allocation = Render_Core::get().getAllocator().createBuffer(&bufferInfo, &info, _buffer, _alloc_infos); + _name = name; + if(usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) + _name.append("_index_buffer"); + else if(usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) + _name.append("_vertex_buffer"); + else if((usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) != 1) + _name.append("_buffer"); + _allocation = Render_Core::get().getAllocator().createBuffer(&bufferInfo, &info, _buffer, _name.c_str()); + _size = size; } void Buffer::pushToGPU() noexcept @@ -76,9 +80,11 @@ namespace mlx VmaAllocationCreateInfo alloc_info{}; alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; + std::string new_name = _name + "_GPU"; + Buffer newBuffer; newBuffer._usage = (_usage & 0xFFFFFFFC) | VK_BUFFER_USAGE_TRANSFER_DST_BIT; - newBuffer.createBuffer(newBuffer._usage, alloc_info, _alloc_infos.size); + newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, new_name.c_str()); CmdPool cmdpool; cmdpool.init(); @@ -100,7 +106,7 @@ namespace mlx vkBeginCommandBuffer(commandBuffer, &beginInfo); VkBufferCopy copyRegion{}; - copyRegion.size = _alloc_infos.size; + copyRegion.size = _size; vkCmdCopyBuffer(commandBuffer, _buffer, newBuffer._buffer, 1, ©Region); vkEndCommandBuffer(commandBuffer); @@ -128,9 +134,17 @@ namespace mlx _buffer = buffer._buffer; buffer._buffer = temp_b; - VmaAllocationInfo temp_i = _alloc_infos; - _alloc_infos = buffer._alloc_infos; - buffer._alloc_infos = temp_i; + VmaAllocation temp_a = buffer._allocation; + buffer._allocation = _allocation; + _allocation = temp_a; + + VkDeviceSize temp_size = buffer._size; + buffer._size = _size; + _size = temp_size; + + VkDeviceSize temp_offset = buffer._offset; + buffer._offset = _offset; + _offset = temp_offset; VkBufferUsageFlags temp_u = _usage; _usage = buffer._usage; diff --git a/src/renderer/buffers/vk_buffer.h b/src/renderer/buffers/vk_buffer.h index f881d5a..c45f3be 100644 --- a/src/renderer/buffers/vk_buffer.h +++ b/src/renderer/buffers/vk_buffer.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 23:18:52 by maldavid #+# #+# */ -/* Updated: 2023/11/11 03:29:40 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 03:24:12 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,18 +23,18 @@ namespace mlx public: enum class kind { dynamic, uniform, constant }; - void create(kind type, VkDeviceSize size, VkBufferUsageFlags usage, const void* data = nullptr); + void create(kind type, VkDeviceSize size, VkBufferUsageFlags usage, const char* name, const void* data = nullptr); void destroy() noexcept; - inline void mapMem(void** data = nullptr) noexcept { Render_Core::get().getAllocator().mapMemory(_allocation, data); _is_mapped = true; } + inline void mapMem(void** data) noexcept { Render_Core::get().getAllocator().mapMemory(_allocation, data); _is_mapped = true; } inline bool isMapped() const noexcept { return _is_mapped; } - inline void unmapMem() noexcept { Render_Core::get().getAllocator().unmapMemory(_allocation);_is_mapped = false; } + inline void unmapMem() noexcept { Render_Core::get().getAllocator().unmapMemory(_allocation); _is_mapped = false; } void flush(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0); inline VkBuffer& operator()() noexcept { return _buffer; } inline VkBuffer& get() noexcept { return _buffer; } - inline VkDeviceSize getSize() const noexcept { return _alloc_infos.size; } + inline VkDeviceSize getSize() const noexcept { return _size; } inline VkDeviceSize getOffset() const noexcept { return _offset; } protected: @@ -43,14 +43,15 @@ namespace mlx protected: VmaAllocation _allocation; - VmaAllocationInfo _alloc_infos; VkBuffer _buffer = VK_NULL_HANDLE; VkDeviceSize _offset = 0; + VkDeviceSize _size = 0; private: - void createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size); + void createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size, const char* name); private: + std::string _name; VkBufferUsageFlags _usage = 0; bool _is_mapped = false; }; diff --git a/src/renderer/buffers/vk_ibo.h b/src/renderer/buffers/vk_ibo.h index 016c097..92f8c09 100644 --- a/src/renderer/buffers/vk_ibo.h +++ b/src/renderer/buffers/vk_ibo.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/25 15:05:05 by maldavid #+# #+# */ -/* Updated: 2023/11/11 03:08:10 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 03:25:59 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,8 +22,8 @@ namespace mlx class C_IBO : public Buffer { public: - inline void create(uint32_t size, const uint16_t* data) { Buffer::create(Buffer::kind::constant, size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, data); } - inline void bind(Renderer& renderer) noexcept { vkCmdBindIndexBuffer(renderer.getActiveCmdBuffer().get(), _buffer, 0, VK_INDEX_TYPE_UINT16); } + inline void create(uint32_t size, const uint16_t* data, const char* name) { Buffer::create(Buffer::kind::constant, size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, name, data); } + inline void bind(Renderer& renderer) noexcept { vkCmdBindIndexBuffer(renderer.getActiveCmdBuffer().get(), _buffer, _offset, VK_INDEX_TYPE_UINT16); } }; } diff --git a/src/renderer/buffers/vk_ubo.cpp b/src/renderer/buffers/vk_ubo.cpp index 48506e4..fbc0927 100644 --- a/src/renderer/buffers/vk_ubo.cpp +++ b/src/renderer/buffers/vk_ubo.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:45:52 by maldavid #+# #+# */ -/* Updated: 2023/11/10 07:54:48 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 03:27:08 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,13 +16,15 @@ namespace mlx { - void UBO::create(Renderer* renderer, uint32_t size) + void UBO::create(Renderer* renderer, uint32_t size, const char* name) { _renderer = renderer; for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - _buffers[i].create(Buffer::kind::uniform, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + std::string name_frame = name; + name_frame.append(std::to_string(i)); + _buffers[i].create(Buffer::kind::uniform, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, name_frame.c_str()); _buffers[i].mapMem(&_maps[i]); if(_maps[i] == nullptr) core::error::report(e_kind::fatal_error, "Vulkan : unable to map a uniform buffer"); diff --git a/src/renderer/buffers/vk_ubo.h b/src/renderer/buffers/vk_ubo.h index f527dd4..f1ca457 100644 --- a/src/renderer/buffers/vk_ubo.h +++ b/src/renderer/buffers/vk_ubo.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:45:29 by maldavid #+# #+# */ -/* Updated: 2023/11/10 07:54:29 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 03:26:10 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,7 +22,7 @@ namespace mlx class UBO { public: - void create(class Renderer* renderer, uint32_t size); + void create(class Renderer* renderer, uint32_t size, const char* name); void setData(uint32_t size, const void* data); void setDynamicData(uint32_t size, const void* data); diff --git a/src/renderer/buffers/vk_vbo.h b/src/renderer/buffers/vk_vbo.h index 2e1f67b..a8c942c 100644 --- a/src/renderer/buffers/vk_vbo.h +++ b/src/renderer/buffers/vk_vbo.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:27:38 by maldavid #+# #+# */ -/* Updated: 2023/11/11 03:22:44 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 04:53:36 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,7 +21,7 @@ namespace mlx class VBO : public Buffer { public: - inline void create(uint32_t size) { Buffer::create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); } + inline void create(uint32_t size, const char* name) { Buffer::create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name); } void setData(uint32_t size, const void* data); inline void bind(Renderer& renderer) noexcept { vkCmdBindVertexBuffers(renderer.getActiveCmdBuffer().get(), 0, 1, &_buffer, &_offset); } }; @@ -29,7 +29,7 @@ namespace mlx class C_VBO : public Buffer { public: - inline void create(uint32_t size, const void* data) { Buffer::create(Buffer::kind::constant, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, data); } + inline void create(uint32_t size, const void* data, const char* name) { Buffer::create(Buffer::kind::constant, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name, data); } inline void bind(Renderer& renderer) noexcept { vkCmdBindVertexBuffers(renderer.getActiveCmdBuffer().get(), 0, 1, &_buffer, &_offset); } }; } diff --git a/src/renderer/core/memory.cpp b/src/renderer/core/memory.cpp index 1104e15..0f9616c 100644 --- a/src/renderer/core/memory.cpp +++ b/src/renderer/core/memory.cpp @@ -6,7 +6,7 @@ /* By: kbz_8 +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/10/20 22:02:37 by kbz_8 #+# #+# */ -/* Updated: 2023/11/10 23:29:56 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 06:25:19 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,6 +28,7 @@ #endif #include +#include namespace mlx { @@ -65,44 +66,52 @@ namespace mlx allocatorCreateInfo.pVulkanFunctions = &vma_vulkan_func; if(vmaCreateAllocator(&allocatorCreateInfo, &_allocator) != VK_SUCCESS) - core::error::report(e_kind::fatal_error, "Vulkan : failed to create allocator"); + core::error::report(e_kind::fatal_error, "Vulkan : failed to create graphics memory allocator"); #ifdef DEBUG core::error::report(e_kind::message, "Vulkan : created new allocator"); #endif } - VmaAllocation GPUallocator::createBuffer(const VkBufferCreateInfo* binfo, const VmaAllocationCreateInfo* vinfo, VkBuffer& buffer, VmaAllocationInfo& allocinfo) noexcept + VmaAllocation GPUallocator::createBuffer(const VkBufferCreateInfo* binfo, const VmaAllocationCreateInfo* vinfo, VkBuffer& buffer, const char* name) noexcept { VmaAllocation allocation; if(vmaCreateBuffer(_allocator, binfo, vinfo, &buffer, &allocation, nullptr) != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan : failed to allocate a buffer"); + if(name != nullptr) + vmaSetAllocationName(_allocator, allocation, name); #ifdef DEBUG core::error::report(e_kind::message, "Graphics Allocator : created new buffer"); #endif - vmaGetAllocationInfo(_allocator, allocation, &allocinfo); return allocation; } void GPUallocator::destroyBuffer(VmaAllocation allocation, VkBuffer buffer) noexcept { vmaDestroyBuffer(_allocator, buffer, allocation); + #ifdef DEBUG + core::error::report(e_kind::message, "Graphics Allocator : destroyed buffer"); + #endif } - VmaAllocation GPUallocator::createImage(const VkImageCreateInfo* iminfo, const VmaAllocationCreateInfo* vinfo, VkImage& image, VmaAllocationInfo& allocinfo) noexcept + VmaAllocation GPUallocator::createImage(const VkImageCreateInfo* iminfo, const VmaAllocationCreateInfo* vinfo, VkImage& image, const char* name) noexcept { VmaAllocation allocation; if(vmaCreateImage(_allocator, iminfo, vinfo, &image, &allocation, nullptr) != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan : failed to allocate an image"); + if(name != nullptr) + vmaSetAllocationName(_allocator, allocation, name); #ifdef DEBUG core::error::report(e_kind::message, "Graphics Allocator : created new image"); #endif - vmaGetAllocationInfo(_allocator, allocation, &allocinfo); return allocation; } void GPUallocator::destroyImage(VmaAllocation allocation, VkImage image) noexcept { vmaDestroyImage(_allocator, image, allocation); + #ifdef DEBUG + core::error::report(e_kind::message, "Graphics Allocator : destroyed image"); + #endif } void GPUallocator::mapMemory(VmaAllocation allocation, void** data) noexcept @@ -115,6 +124,25 @@ namespace mlx { vmaUnmapMemory(_allocator, allocation); } + + void GPUallocator::dumpMemoryToJson() + { + static uint32_t id = 0; + std::string name("memory_dump"); + name.append(std::to_string(id) + ".json"); + std::ofstream file(name); + if(!file.is_open()) + { + core::error::report(e_kind::error, "Graphics allocator : unable to dump memory to a json file"); + return; + } + char* str = nullptr; + vmaBuildStatsString(_allocator, &str, true); + file << str; + vmaFreeStatsString(_allocator, str); + file.close(); + id++; + } void GPUallocator::flush(VmaAllocation allocation, VkDeviceSize size, VkDeviceSize offset) noexcept { diff --git a/src/renderer/core/memory.h b/src/renderer/core/memory.h index 20a62a7..ef3c637 100644 --- a/src/renderer/core/memory.h +++ b/src/renderer/core/memory.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/10/20 02:13:03 by maldavid #+# #+# */ -/* Updated: 2023/11/10 08:14:06 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 03:12:59 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,15 +27,17 @@ namespace mlx void init() noexcept; void destroy() noexcept; - VmaAllocation createBuffer(const VkBufferCreateInfo* binfo, const VmaAllocationCreateInfo* vinfo, VkBuffer& buffer, VmaAllocationInfo& allocinfo) noexcept; + VmaAllocation createBuffer(const VkBufferCreateInfo* binfo, const VmaAllocationCreateInfo* vinfo, VkBuffer& buffer, const char* name = nullptr) noexcept; void destroyBuffer(VmaAllocation allocation, VkBuffer buffer) noexcept; - VmaAllocation createImage(const VkImageCreateInfo* iminfo, const VmaAllocationCreateInfo* vinfo, VkImage& image, VmaAllocationInfo& allocinfo) noexcept; + VmaAllocation createImage(const VkImageCreateInfo* iminfo, const VmaAllocationCreateInfo* vinfo, VkImage& image, const char* name = nullptr) noexcept; void destroyImage(VmaAllocation allocation, VkImage image) noexcept; void mapMemory(VmaAllocation allocation, void** data) noexcept; void unmapMemory(VmaAllocation allocation) noexcept; + void dumpMemoryToJson(); + void flush(VmaAllocation allocation, VkDeviceSize size, VkDeviceSize offset) noexcept; ~GPUallocator() = default; diff --git a/src/renderer/core/render_core.h b/src/renderer/core/render_core.h index dd8ffe4..1695ff1 100644 --- a/src/renderer/core/render_core.h +++ b/src/renderer/core/render_core.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:16:32 by maldavid #+# #+# */ -/* Updated: 2023/10/21 00:04:39 by kbz_8 ### ########.fr */ +/* Updated: 2023/11/14 05:00:44 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -40,7 +40,7 @@ namespace mlx const std::vector validationLayers = { "VK_LAYER_KHRONOS_validation" }; - constexpr const int MAX_FRAMES_IN_FLIGHT = 2; + constexpr const int MAX_FRAMES_IN_FLIGHT = 3; class Render_Core : public Singleton { diff --git a/src/renderer/core/vk_device.cpp b/src/renderer/core/vk_device.cpp index 4aaa523..e0d89d5 100644 --- a/src/renderer/core/vk_device.cpp +++ b/src/renderer/core/vk_device.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:14:29 by maldavid #+# #+# */ -/* Updated: 2023/11/11 02:14:58 by maldavid ### ########.fr */ +/* Updated: 2023/11/11 10:38:01 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -101,9 +101,9 @@ namespace mlx if(_physicalDevice == VK_NULL_HANDLE) core::error::report(e_kind::fatal_error, "Vulkan : failed to find a suitable GPU"); - VkPhysicalDeviceProperties props; - vkGetPhysicalDeviceProperties(_physicalDevice, &props); #ifdef DEBUG + VkPhysicalDeviceProperties props; + vkGetPhysicalDeviceProperties(_physicalDevice, &props); core::error::report(e_kind::message, "Vulkan : picked a physical device, %s", props.deviceName); #endif } diff --git a/src/renderer/descriptors/vk_descriptor_set.cpp b/src/renderer/descriptors/vk_descriptor_set.cpp index 63417d4..bde9e16 100644 --- a/src/renderer/descriptors/vk_descriptor_set.cpp +++ b/src/renderer/descriptors/vk_descriptor_set.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/23 18:40:44 by maldavid #+# #+# */ -/* Updated: 2023/11/08 20:16:32 by maldavid ### ########.fr */ +/* Updated: 2023/11/12 01:14:52 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/renderer/images/texture.cpp b/src/renderer/images/texture.cpp index ff7592f..496bb97 100644 --- a/src/renderer/images/texture.cpp +++ b/src/renderer/images/texture.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/31 18:03:35 by maldavid #+# #+# */ -/* Updated: 2023/08/09 13:51:35 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 04:57:55 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -29,13 +29,9 @@ namespace mlx { - void Texture::create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format) + void Texture::create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format, const char* name, bool dedicated_memory) { - Image::create(width, height, format, TILING, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - { VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT } - ); - + Image::create(width, height, format, TILING, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, name, dedicated_memory); Image::createImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); Image::createSampler(); @@ -48,17 +44,18 @@ namespace mlx std::vector indexData = { 0, 1, 2, 2, 3, 0 }; - _vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data()); - _ibo.create(sizeof(uint16_t) * indexData.size(), indexData.data()); + _vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data(), name); + _ibo.create(sizeof(uint16_t) * indexData.size(), indexData.data(), name); if(pixels != nullptr) { Buffer staging_buffer; std::size_t size = width * height * formatSize(format); - staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, pixels); + staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, name, pixels); Image::copyFromBuffer(staging_buffer); staging_buffer.destroy(); } + _name = name; } void Texture::setPixel(int x, int y, uint32_t color) noexcept @@ -89,10 +86,9 @@ namespace mlx #ifdef DEBUG core::error::report(e_kind::message, "Texture : enabling CPU mapping"); #endif - std::size_t size = getWidth() * getHeight() * formatSize(getFormat()); _buf_map.emplace(); - _buf_map->create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); + _buf_map->create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, _name.c_str()); Image::copyToBuffer(*_buf_map); _buf_map->mapMem(&_map); _cpu_map = std::vector(getWidth() * getHeight(), 0); @@ -139,7 +135,7 @@ namespace mlx if(stbi_is_hdr(filename.c_str())) core::error::report(e_kind::fatal_error, "Texture : unsupported image format '%s'", filename.c_str()); data = stbi_load(filename.c_str(), w, h, &channels, 4); - texture.create(data, *w, *h, VK_FORMAT_R8G8B8A8_UNORM); + texture.create(data, *w, *h, VK_FORMAT_R8G8B8A8_UNORM, filename.c_str()); stbi_image_free(data); return texture; } diff --git a/src/renderer/images/texture.h b/src/renderer/images/texture.h index 199d6a9..536975a 100644 --- a/src/renderer/images/texture.h +++ b/src/renderer/images/texture.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/08 02:24:58 by maldavid #+# #+# */ -/* Updated: 2023/08/02 12:32:27 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 04:57:39 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -29,7 +29,7 @@ namespace mlx public: Texture() = default; - void create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format); + void create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format, const char* name, bool dedicated_memory = false); void render(class Renderer& renderer, int x, int y); void destroy() noexcept override; @@ -50,6 +50,7 @@ namespace mlx private: C_VBO _vbo; C_IBO _ibo; + std::string _name; DescriptorSet _set; std::vector _cpu_map; std::optional _buf_map = std::nullopt; diff --git a/src/renderer/images/texture_atlas.cpp b/src/renderer/images/texture_atlas.cpp index 1a414c4..f129baf 100644 --- a/src/renderer/images/texture_atlas.cpp +++ b/src/renderer/images/texture_atlas.cpp @@ -6,22 +6,23 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/04/07 16:40:09 by maldavid #+# #+# */ -/* Updated: 2023/04/23 12:55:22 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 05:36:46 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #include +#ifdef IMAGE_OPTIMIZED + #define TILING VK_IMAGE_TILING_OPTIMAL +#else + #define TILING VK_IMAGE_TILING_LINEAR +#endif + namespace mlx { - void TextureAtlas::create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format) + void TextureAtlas::create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format, const char* name, bool dedicated_memory) { - Image::create(width, height, format, - VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, - { VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT } - ); - + Image::create(width, height, format, TILING, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, name, dedicated_memory); Image::createImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); Image::createSampler(); @@ -29,7 +30,7 @@ namespace mlx { Buffer staging_buffer; std::size_t size = width * height * formatSize(format); - staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, pixels); + staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, name, pixels); Image::copyFromBuffer(staging_buffer); staging_buffer.destroy(); } diff --git a/src/renderer/images/texture_atlas.h b/src/renderer/images/texture_atlas.h index dc9f004..db142c2 100644 --- a/src/renderer/images/texture_atlas.h +++ b/src/renderer/images/texture_atlas.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/04/07 16:36:33 by maldavid #+# #+# */ -/* Updated: 2023/04/11 12:04:16 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 05:36:30 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,7 +24,7 @@ namespace mlx public: TextureAtlas() = default; - void create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format); + void create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format, const char* name, bool dedicated_memory = false); void render(class Renderer& renderer, int x, int y, uint32_t ibo_size); void destroy() noexcept override; diff --git a/src/renderer/images/vk_image.cpp b/src/renderer/images/vk_image.cpp index 890ddb0..5ccf45f 100644 --- a/src/renderer/images/vk_image.cpp +++ b/src/renderer/images/vk_image.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/25 11:59:07 by maldavid #+# #+# */ -/* Updated: 2023/11/10 08:24:11 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 03:15:33 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,7 +18,7 @@ namespace mlx { - void Image::create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, std::vector properties) + void Image::create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool dedicated_memory) { _width = width; _height = height; @@ -41,9 +41,14 @@ namespace mlx imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VmaAllocationCreateInfo alloc_info{}; - alloc_info.usage = VMA_MEMORY_USAGE_GPU_ONLY; + alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; + if(dedicated_memory) + { + alloc_info.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; + alloc_info.priority = 1.0f; + } - _allocation = Render_Core::get().getAllocator().createImage(&imageInfo, &alloc_info, _image, _alloc_infos); + _allocation = Render_Core::get().getAllocator().createImage(&imageInfo, &alloc_info, _image, name); _pool.init(); } @@ -67,7 +72,7 @@ namespace mlx void Image::createSampler() noexcept { - VkSamplerCreateInfo info = {}; + VkSamplerCreateInfo info{}; info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; info.magFilter = VK_FILTER_NEAREST; info.minFilter = VK_FILTER_NEAREST; @@ -92,7 +97,7 @@ namespace mlx _transfer_cmd.reset(); _transfer_cmd.beginRecord(); - VkImageMemoryBarrier copy_barrier = {}; + VkImageMemoryBarrier copy_barrier{}; copy_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; copy_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; copy_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -105,7 +110,7 @@ namespace mlx copy_barrier.subresourceRange.layerCount = 1; vkCmdPipelineBarrier(_transfer_cmd.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, ©_barrier); - VkBufferImageCopy region = {}; + VkBufferImageCopy region{}; region.bufferOffset = 0; region.bufferRowLength = 0; region.bufferImageHeight = 0; @@ -118,7 +123,7 @@ namespace mlx vkCmdCopyBufferToImage(_transfer_cmd.get(), buffer.get(), _image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - VkImageMemoryBarrier use_barrier = {}; + VkImageMemoryBarrier use_barrier{}; use_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; use_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; use_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; @@ -144,7 +149,7 @@ namespace mlx _transfer_cmd.reset(); _transfer_cmd.beginRecord(); - VkImageMemoryBarrier copy_barrier = {}; + VkImageMemoryBarrier copy_barrier{}; copy_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; copy_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; copy_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -157,7 +162,7 @@ namespace mlx copy_barrier.subresourceRange.layerCount = 1; vkCmdPipelineBarrier(_transfer_cmd.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, ©_barrier); - VkBufferImageCopy region = {}; + VkBufferImageCopy region{}; region.bufferOffset = 0; region.bufferRowLength = 0; region.bufferImageHeight = 0; @@ -170,7 +175,7 @@ namespace mlx vkCmdCopyImageToBuffer(_transfer_cmd.get(), _image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer.get(), 1, ®ion); - VkImageMemoryBarrier use_barrier = {}; + VkImageMemoryBarrier use_barrier{}; use_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; use_barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; use_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; diff --git a/src/renderer/images/vk_image.h b/src/renderer/images/vk_image.h index a4b315a..22f4924 100644 --- a/src/renderer/images/vk_image.h +++ b/src/renderer/images/vk_image.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/01/25 11:54:21 by maldavid #+# #+# */ -/* Updated: 2023/11/10 08:23:59 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 03:15:18 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -28,7 +28,7 @@ namespace mlx public: Image() = default; - void create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, std::vector properties); + void create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool decated_memory = false); void createImageView(VkImageViewType type, VkImageAspectFlags aspectFlags) noexcept; void createSampler() noexcept; void copyFromBuffer(class Buffer& buffer); @@ -50,7 +50,6 @@ namespace mlx CmdBuffer _transfer_cmd; CmdPool _pool; VmaAllocation _allocation; - VmaAllocationInfo _alloc_infos; VkImage _image = VK_NULL_HANDLE; VkImageView _image_view = VK_NULL_HANDLE; VkSampler _sampler = VK_NULL_HANDLE; diff --git a/src/renderer/pixel_put.cpp b/src/renderer/pixel_put.cpp index ce66b92..bb57994 100644 --- a/src/renderer/pixel_put.cpp +++ b/src/renderer/pixel_put.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/03/31 15:14:50 by maldavid #+# #+# */ -/* Updated: 2023/08/02 05:28:49 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 04:58:13 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,10 +17,10 @@ namespace mlx { void PixelPutPipeline::init(uint32_t width, uint32_t height, Renderer& renderer) noexcept { - _texture.create(nullptr, width, height, VK_FORMAT_R8G8B8A8_UNORM); + _texture.create(nullptr, width, height, VK_FORMAT_R8G8B8A8_UNORM, "__mlx_pixel_put_pipeline_texture", true); _texture.setDescriptor(renderer.getFragDescriptorSet().duplicate()); - _buffer.create(Buffer::kind::dynamic, sizeof(uint32_t) * (width * height), VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + _buffer.create(Buffer::kind::dynamic, sizeof(uint32_t) * (width * height), VK_BUFFER_USAGE_TRANSFER_SRC_BIT, "__mlx_pixel_put_pipeline_texture"); _buffer.mapMem(&_buffer_map); _cpu_map = std::vector(height * width, 0); _width = width; diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index f007f6a..d40676c 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/18 17:25:16 by maldavid #+# #+# */ -/* Updated: 2023/04/21 20:56:51 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 04:59:38 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,7 +27,7 @@ namespace mlx _semaphores[i].init(); _uniform_buffer.reset(new UBO); - _uniform_buffer->create(this, sizeof(glm::mat4)); + _uniform_buffer->create(this, sizeof(glm::mat4), "__mlx_matrices_uniform_buffer_"); VkDescriptorPoolSize pool_sizes[] = { { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 4096 }, diff --git a/src/renderer/text_library.cpp b/src/renderer/text_library.cpp index ae3c527..78d1bda 100644 --- a/src/renderer/text_library.cpp +++ b/src/renderer/text_library.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/04/10 11:59:57 by maldavid #+# #+# */ -/* Updated: 2023/04/19 13:43:43 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 05:39:40 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,8 +20,8 @@ namespace mlx void TextData::init(std::string text, std::vector vbo_data, std::vector ibo_data) { _text = std::move(text); - _vbo.create(sizeof(Vertex) * vbo_data.size(), vbo_data.data()); - _ibo.create(sizeof(uint16_t) * ibo_data.size(), ibo_data.data()); + _vbo.create(sizeof(Vertex) * vbo_data.size(), vbo_data.data(), _text.c_str()); + _ibo.create(sizeof(uint16_t) * ibo_data.size(), ibo_data.data(), _text.c_str()); } void TextData::bind(Renderer& renderer) noexcept diff --git a/src/renderer/text_pipeline.cpp b/src/renderer/text_pipeline.cpp index 588bb9a..e91ae8e 100644 --- a/src/renderer/text_pipeline.cpp +++ b/src/renderer/text_pipeline.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2023/04/06 16:41:13 by maldavid #+# #+# */ -/* Updated: 2023/04/19 13:43:49 by maldavid ### ########.fr */ +/* Updated: 2023/11/14 05:36:09 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -74,7 +74,7 @@ namespace mlx vulkan_bitmap[j + 2] = tmp_bitmap[i]; vulkan_bitmap[j + 3] = tmp_bitmap[i]; } - _atlas.create(vulkan_bitmap, 512, 512, VK_FORMAT_R8G8B8A8_UNORM); + _atlas.create(vulkan_bitmap, 512, 512, VK_FORMAT_R8G8B8A8_UNORM, "__mlx_texts_pipeline_texture_atlas", true); _atlas.setDescriptor(renderer->getFragDescriptorSet().duplicate()); } diff --git a/test/.gdb_history b/test/.gdb_history deleted file mode 100644 index aae9e21..0000000 --- a/test/.gdb_history +++ /dev/null @@ -1,10 +0,0 @@ -b mlx::Buffer::create -run -q -b mlx::Buffer::create -run -bt -n -tui e -n -q