diff --git a/includes/mlx.h b/includes/mlx.h index d64434a..2619fd1 100644 --- a/includes/mlx.h +++ b/includes/mlx.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 16:56:35 by maldavid #+# #+# */ -/* Updated: 2023/04/01 17:25:25 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 22:23:25 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,7 +20,7 @@ extern "C" { void* mlx_init(); void* mlx_new_window(void* mlx, int w, int h, const char* title); -int mlx_loop_hook(void* mlx, int (*f)(void*), void* param); +int mlx_loop_hook(void* mlx, int (*f)(), void* param); int mlx_loop(void* mlx); int mlx_loop_end(void* mlx); @@ -31,16 +31,20 @@ int mlx_mouse_get_pos(void* mlx, int* x, int* y); int mlx_pixel_put(void* mlx, void* win_ptr, int x, int y, int color); -int mlx_put_image_to_window(void* mlx_ptr, void* win_ptr, void* img_ptr, int x, int y); -int mlx_destroy_image(void* mlx_ptr, void* img_ptr); +void* mlx_new_image(void* mlx, int width, int height); +char* mlx_get_data_addr(void* mlx, void* img_ptr, int* bits_per_pixel, int* size_line, int* endian); +int mlx_put_image_to_window(void* mlx, void* win_ptr, void* img_ptr, int x, int y); +int mlx_destroy_image(void* mlx, void* img_ptr); -void* mlx_png_file_to_image(void* mlx_ptr, char* filename, int* width, int* height); +void* mlx_png_file_to_image(void* mlx, char* filename, int* width, int* height); -int mlx_clear_window(void* mlx_ptr, void* win_ptr); +int mlx_clear_window(void* mlx, void* win_ptr); int mlx_destroy_window(void* mlx, void* win_ptr); int mlx_destroy_display(void* mlx); +int mlx_get_screens_size(void* mlx, int* w, int* h); + #ifdef __cplusplus } #endif diff --git a/src/core/application.cpp b/src/core/application.cpp index cf7f9b2..dcc8a18 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -6,13 +6,14 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 22:10:52 by maldavid #+# #+# */ -/* Updated: 2023/04/02 15:11:53 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 23:49:03 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #include "application.h" #include #include +#include // for LSBFirst namespace mlx::core { @@ -32,6 +33,15 @@ namespace mlx::core } } + void* Application::newTexture(int w, int h) + { + std::shared_ptr texture = std::make_shared(); + texture->create(nullptr, w, h, VK_FORMAT_R8G8B8A8_UNORM); + TextureID id = _texture_lib.addTextureToLibrary(texture); + _texture_ids.push_back(id); + return &_texture_ids.back(); + } + void* Application::newStbTexture(char* file, int* w, int* h) { std::shared_ptr texture = std::make_shared(stbTextureLoad(file, w, h)); @@ -40,6 +50,17 @@ namespace mlx::core return &_texture_ids.back(); } + char* Application::mapTexture(void* img, int* bits_per_pixel, int* size_line, int* endian) + { + TextureID id = *static_cast(img); + std::shared_ptr texture = _texture_lib.getTexture(id); + char* map = static_cast(texture->openCPUmap()); + *bits_per_pixel = sizeof(uint32_t) * 8; + *size_line = texture->getWidth(); + *endian = LSBFirst; + return map; + } + void Application::destroyTexture(void* ptr) { vkDeviceWaitIdle(Render_Core::get().getDevice().get()); diff --git a/src/core/application.h b/src/core/application.h index b5fa048..0335fcc 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -6,14 +6,14 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 21:49:46 by maldavid #+# #+# */ -/* Updated: 2023/04/02 15:38:47 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 23:38:05 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef __MLX_APPLICATION__ #define __MLX_APPLICATION__ -#include +#include #include #include #include @@ -35,13 +35,17 @@ namespace mlx::core inline void getMousePos(int* x, int* y) noexcept; inline void mouseMove(void* win_ptr, int x, int y) noexcept; + inline void getScreenSize(int* w, int* h) noexcept; + inline void* newGraphicsSuport(std::size_t w, std::size_t h, std::string title); inline void clearGraphicsSupport(void* win_ptr); inline void destroyGraphicsSupport(void* win_ptr); inline void pixelPut(void* win_ptr, int x, int y, int color) const noexcept; + void* newTexture(int w, int h); void* newStbTexture(char* file, int* w, int* h); // stb textures are format managed by stb image (png, jpg, bpm, ...) + char* mapTexture(void* img_ptr, int* bits_per_pixel, int* size_line, int* endian); inline void texturePut(void* win_ptr, void* img, int x, int y); void destroyTexture(void* ptr); @@ -55,7 +59,7 @@ namespace mlx::core private: Input _in; TextureLibrary _texture_lib; - std::vector _texture_ids; + std::list _texture_ids; std::vector> _graphics; std::function _loop_hook; void* _param = nullptr; diff --git a/src/core/application.inl b/src/core/application.inl index 4dc0eea..5c65faa 100644 --- a/src/core/application.inl +++ b/src/core/application.inl @@ -27,6 +27,14 @@ namespace mlx::core SDL_FlushEvent(SDL_MOUSEMOTION); } + void Application::getScreenSize(int* w, int* h) noexcept + { + SDL_DisplayMode DM; + SDL_GetDesktopDisplayMode(0, &DM); + *w = DM.w; + *h = DM.h; + } + void* Application::newGraphicsSuport(std::size_t w, std::size_t h, std::string title) { _graphics.emplace_back(std::make_unique(w, h, std::move(title), _graphics.size())); @@ -50,7 +58,8 @@ namespace mlx::core void Application::texturePut(void* win_ptr, void* img, int x, int y) { - std::shared_ptr texture = _texture_lib.getTexture(*static_cast(img)); + TextureID id = *static_cast(img); + std::shared_ptr texture = _texture_lib.getTexture(id); _graphics[*static_cast(win_ptr)]->texturePut(texture, x, y); } diff --git a/src/core/bridge.cpp b/src/core/bridge.cpp index 053ee13..ee502ef 100644 --- a/src/core/bridge.cpp +++ b/src/core/bridge.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 17:35:20 by maldavid #+# #+# */ -/* Updated: 2023/04/02 15:10:44 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 22:23:40 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -68,6 +68,16 @@ extern "C" return 0; } + void* mlx_new_image(void* mlx, int width, int height) + { + return static_cast(mlx)->newTexture(width, height); + } + + char* mlx_get_data_addr(void* mlx, void* img_ptr, int* bits_per_pixel, int* size_line, int* endian) + { + return static_cast(mlx)->mapTexture(img_ptr, bits_per_pixel, size_line, endian); + } + int mlx_put_image_to_window(void* mlx_ptr, void* win_ptr, void* img_ptr, int x, int y) { static_cast(mlx_ptr)->texturePut(win_ptr, img_ptr, x, y); @@ -109,4 +119,10 @@ extern "C" mlx::Render_Core::get().destroy(); return 0; } + + int mlx_get_screens_size(void* mlx, int* w, int* h) + { + static_cast(mlx)->getScreenSize(w, h); + return 0; + } } diff --git a/src/renderer/command/cmd_manager.cpp b/src/renderer/command/cmd_manager.cpp new file mode 100644 index 0000000..37524a5 --- /dev/null +++ b/src/renderer/command/cmd_manager.cpp @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cmd_manager.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/02 17:50:52 by maldavid #+# #+# */ +/* Updated: 2023/04/02 17:51:46 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +namespace mlx +{ + void CmdManager::init() noexcept + { + _cmd_pool.init(); + for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + _cmd_buffers[i].init(this); + } + + void CmdManager::beginRecord(int active_image_index) + { + _cmd_buffers[active_image_index].beginRecord(); + } + + void CmdManager::endRecord(int active_image_index) + { + _cmd_buffers[active_image_index].endRecord(); + } + + void CmdManager::destroy() noexcept + { + for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + _cmd_buffers[i].destroy(); + _cmd_pool.destroy(); + } +} diff --git a/src/renderer/command/cmd_manager.h b/src/renderer/command/cmd_manager.h new file mode 100644 index 0000000..4920d69 --- /dev/null +++ b/src/renderer/command/cmd_manager.h @@ -0,0 +1,46 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* cmd_manager.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/02 17:48:52 by maldavid #+# #+# */ +/* Updated: 2023/04/02 17:50:48 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __MLX_COMMAND_MANAGER__ +#define __MLX_COMMAND_MANAGER__ + +#include + +#include +#include +#include +#include + +namespace mlx +{ + class CmdManager + { + public: + CmdManager() = default; + + void init() noexcept; + void beginRecord(int active_image_index); + void endRecord(int active_image_index); + void destroy() noexcept; + + inline CmdPool& getCmdPool() noexcept { return _cmd_pool; } + inline CmdBuffer& getCmdBuffer(int i) noexcept { return _cmd_buffers[i]; } + + ~CmdManager() = default; + + private: + std::array _cmd_buffers; + CmdPool _cmd_pool; + }; +} + +#endif diff --git a/src/renderer/command/vk_cmd_buffer.cpp b/src/renderer/command/vk_cmd_buffer.cpp index 3e93e02..f9572ad 100644 --- a/src/renderer/command/vk_cmd_buffer.cpp +++ b/src/renderer/command/vk_cmd_buffer.cpp @@ -6,28 +6,31 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:26:06 by maldavid #+# #+# */ -/* Updated: 2022/12/18 20:33:04 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 18:13:38 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ #include "vk_cmd_buffer.h" #include -#include +#include +#include namespace mlx { - void CmdBuffer::init(Renderer* renderer) + void CmdBuffer::init(CmdManager* manager) { - _renderer = renderer; + _manager = manager; VkCommandBufferAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = renderer->getCmdPool().get(); + allocInfo.commandPool = manager->getCmdPool().get(); allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.commandBufferCount = 1; if(vkAllocateCommandBuffers(Render_Core::get().getDevice().get(), &allocInfo, &_cmd_buffer) != VK_SUCCESS) core::error::report(e_kind::fatal_error, "Vulkan : failed to allocate command buffer"); + + _fence.init(); } void CmdBuffer::beginRecord(VkCommandBufferUsageFlags usage) @@ -54,8 +57,29 @@ namespace mlx _is_recording = false; } + void CmdBuffer::submit(Semaphore& semaphores) noexcept + { + VkSemaphore signalSemaphores[] = { semaphores.getRenderImageSemaphore() }; + VkSemaphore waitSemaphores[] = { semaphores.getImageSemaphore() }; + VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitDstStageMask = waitStages; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &_cmd_buffer; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = signalSemaphores; + + if(vkQueueSubmit(Render_Core::get().getQueue().getGraphic(), 1, &submitInfo, _fence.get()) != VK_SUCCESS) + core::error::report(e_kind::fatal_error, "Vulkan error : failed to submit draw command buffer"); + } + void CmdBuffer::destroy() noexcept { - vkFreeCommandBuffers(Render_Core::get().getDevice().get(), _renderer->getCmdPool().get(), 1, &_cmd_buffer); + vkFreeCommandBuffers(Render_Core::get().getDevice().get(), _manager->getCmdPool().get(), 1, &_cmd_buffer); + _fence.destroy(); } } diff --git a/src/renderer/command/vk_cmd_buffer.h b/src/renderer/command/vk_cmd_buffer.h index e1e21f9..b94db94 100644 --- a/src/renderer/command/vk_cmd_buffer.h +++ b/src/renderer/command/vk_cmd_buffer.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/06 18:25:42 by maldavid #+# #+# */ -/* Updated: 2022/12/18 20:32:45 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 17:57:26 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,24 +14,31 @@ #define __MLX_VK_CMD_BUFFER__ #include +#include namespace mlx { class CmdBuffer { public: - void init(class Renderer* renderer); + void init(class CmdManager* manager); void destroy() noexcept; void beginRecord(VkCommandBufferUsageFlags usage = 0); + void submit(class Semaphore& semaphores) noexcept; + inline void waitForExecution() noexcept { _fence.waitAndReset(); } + inline void reset() noexcept { vkResetCommandBuffer(_cmd_buffer, 0); } void endRecord(); + inline bool isRecording() const noexcept { return _is_recording; } + inline VkCommandBuffer& operator()() noexcept { return _cmd_buffer; } inline VkCommandBuffer& get() noexcept { return _cmd_buffer; } private: + Fence _fence; VkCommandBuffer _cmd_buffer = VK_NULL_HANDLE; - class Renderer* _renderer = nullptr; + class CmdManager* _manager = nullptr; bool _is_recording = false; }; } diff --git a/src/renderer/core/vk_fence.cpp b/src/renderer/core/vk_fence.cpp new file mode 100644 index 0000000..c48e011 --- /dev/null +++ b/src/renderer/core/vk_fence.cpp @@ -0,0 +1,44 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* vk_fence.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/02 17:53:06 by maldavid #+# #+# */ +/* Updated: 2023/04/02 17:54:14 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include + +namespace mlx +{ + void Fence::init() + { + VkSemaphoreCreateInfo semaphoreInfo{}; + semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkFenceCreateInfo fenceInfo{}; + fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + if(vkCreateFence(Render_Core::get().getDevice().get(), &fenceInfo, nullptr, &_fence) != VK_SUCCESS) + core::error::report(e_kind::fatal_error, "Vulkan : failed to create CPU synchronization object"); + } + + void Fence::wait() noexcept + { + vkWaitForFences(Render_Core::get().getDevice().get(), 1, &_fence, VK_TRUE, UINT64_MAX); + } + + void Fence::reset() noexcept + { + vkResetFences(Render_Core::get().getDevice().get(), 1, &_fence); + } + + void Fence::destroy() noexcept + { + vkDestroyFence(Render_Core::get().getDevice().get(), _fence, nullptr); + } +} diff --git a/src/renderer/core/vk_fence.h b/src/renderer/core/vk_fence.h new file mode 100644 index 0000000..a72cd02 --- /dev/null +++ b/src/renderer/core/vk_fence.h @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* vk_fence.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maldavid +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/04/02 17:52:09 by maldavid #+# #+# */ +/* Updated: 2023/04/02 17:52:59 by maldavid ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef __MLX_VK_FENCE__ +#define __MLX_VK_FENCE__ + +#include +#include + +namespace mlx +{ + class Fence + { + public: + Fence() = default; + + void init(); + + inline VkFence& get() noexcept { return _fence; } + void wait() noexcept; + void reset() noexcept; + inline void waitAndReset() noexcept { wait(); reset(); } + + void destroy() noexcept; + + ~Fence() = default; + + private: + VkFence _fence = VK_NULL_HANDLE; + }; +} + +#endif diff --git a/src/renderer/core/vk_semaphore.cpp b/src/renderer/core/vk_semaphore.cpp index 46c1157..7ca2857 100644 --- a/src/renderer/core/vk_semaphore.cpp +++ b/src/renderer/core/vk_semaphore.cpp @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 19:01:08 by maldavid #+# #+# */ -/* Updated: 2022/12/18 20:12:40 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 17:55:58 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,36 +16,19 @@ namespace mlx { - void Semaphore::init(Renderer& renderer) + void Semaphore::init() { - _imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT); - _renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT); - _inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); - _imagesInFlight.resize(renderer.getSwapChain().getImagesNumber(), VK_NULL_HANDLE); - VkSemaphoreCreateInfo semaphoreInfo{}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - VkFenceCreateInfo fenceInfo{}; - fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - for(size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - { - if(vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_imageAvailableSemaphores[i]) != VK_SUCCESS || - vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_renderFinishedSemaphores[i]) != VK_SUCCESS || - vkCreateFence(Render_Core::get().getDevice().get(), &fenceInfo, nullptr, &_inFlightFences[i]) != VK_SUCCESS) - core::error::report(e_kind::fatal_error, "Vulkan : failed to create synchronization objects for a frame"); - } + if( vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_imageAvailableSemaphores) != VK_SUCCESS || + vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_renderFinishedSemaphores) != VK_SUCCESS) + core::error::report(e_kind::fatal_error, "Vulkan : failed to create GPU synchronization object"); } void Semaphore::destroy() noexcept { - for(size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - { - vkDestroySemaphore(Render_Core::get().getDevice().get(), _renderFinishedSemaphores[i], nullptr); - vkDestroySemaphore(Render_Core::get().getDevice().get(), _imageAvailableSemaphores[i], nullptr); - vkDestroyFence(Render_Core::get().getDevice().get(), _inFlightFences[i], nullptr); - } + vkDestroySemaphore(Render_Core::get().getDevice().get(), _renderFinishedSemaphores, nullptr); + vkDestroySemaphore(Render_Core::get().getDevice().get(), _imageAvailableSemaphores, nullptr); } } diff --git a/src/renderer/core/vk_semaphore.h b/src/renderer/core/vk_semaphore.h index b9733f2..8c1371e 100644 --- a/src/renderer/core/vk_semaphore.h +++ b/src/renderer/core/vk_semaphore.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/08 18:59:38 by maldavid #+# #+# */ -/* Updated: 2022/12/18 19:50:10 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 17:55:10 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,19 +21,15 @@ namespace mlx class Semaphore { public: - void init(class Renderer& renderer); + void init(); void destroy() noexcept; - inline VkSemaphore& getImageSemaphore(int i) noexcept { return _imageAvailableSemaphores[i]; } - inline VkSemaphore& getRenderImageSemaphore(int i) noexcept { return _renderFinishedSemaphores[i]; } - inline VkFence& getInFlightFence(int i) noexcept { return _inFlightFences[i]; } - inline VkFence& getInFlightImage(int i) noexcept { return _imagesInFlight[i]; } + inline VkSemaphore& getImageSemaphore() noexcept { return _imageAvailableSemaphores; } + inline VkSemaphore& getRenderImageSemaphore() noexcept { return _renderFinishedSemaphores; } private: - std::vector _imageAvailableSemaphores; - std::vector _renderFinishedSemaphores; - std::vector _inFlightFences; - std::vector _imagesInFlight; + VkSemaphore _imageAvailableSemaphores = VK_NULL_HANDLE; + VkSemaphore _renderFinishedSemaphores = VK_NULL_HANDLE; }; } diff --git a/src/renderer/images/texture.cpp b/src/renderer/images/texture.cpp index a7fa89d..05cca7c 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/04/02 15:47:49 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 23:50:31 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,6 +14,7 @@ #include #include #include +#include #define STB_IMAGE_IMPLEMENTATION #include @@ -24,7 +25,7 @@ namespace mlx { Image::create(width, height, format, VK_IMAGE_TILING_OPTIMAL, - VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ); @@ -48,13 +49,32 @@ namespace mlx Buffer staging_buffer; std::size_t size = width * height * (format == VK_FORMAT_R32G32B32A32_SFLOAT ? 16 : 4); staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, pixels); - Image::copyBuffer(staging_buffer); + Image::copyFromBuffer(staging_buffer); staging_buffer.destroy(); } + _cpu_map = nullptr; + _cpu_map_adress = nullptr; + } + + void* Texture::openCPUmap() + { + if(_cpu_map == nullptr) + { + _cpu_map = std::make_shared(); + _cpu_map->create(Buffer::kind::dynamic, sizeof(uint32_t) * (getWidth() * getHeight()), VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); + Image::copyToBuffer(*_cpu_map); + } + if(!_cpu_map->isMapped()) + _cpu_map->mapMem(&_cpu_map_adress); + if(_cpu_map_adress == nullptr) + core::error::report(e_kind::fatal_error, "Texture : CPU memory mappind failed"); + return _cpu_map_adress; } void Texture::render(Renderer& renderer, int x, int y) { + if(_cpu_map_adress != nullptr) + Image::copyFromBuffer(*_cpu_map); auto cmd = renderer.getActiveCmdBuffer().get(); _vbo.bind(renderer); _ibo.bind(renderer); @@ -66,6 +86,8 @@ namespace mlx void Texture::destroy() noexcept { Image::destroy(); + if(_cpu_map != nullptr) + _cpu_map->destroy(); _vbo.destroy(); _ibo.destroy(); } diff --git a/src/renderer/images/texture.h b/src/renderer/images/texture.h index f8a241e..6a9c724 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/04/02 17:33:26 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 22:36:52 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -32,6 +32,8 @@ namespace mlx void render(class Renderer& renderer, int x, int y); void destroy() noexcept override; + void* openCPUmap(); + inline void setDescriptor(DescriptorSet set) noexcept { _set = std::move(set); } inline VkDescriptorSet getSet() noexcept { return _set.isInit() ? _set.get() : VK_NULL_HANDLE; } inline void updateSet(int binding) noexcept { _set.writeDescriptor(binding, getImageView(), getSampler()); _has_been_updated = true; } @@ -44,6 +46,8 @@ namespace mlx C_VBO _vbo; C_IBO _ibo; DescriptorSet _set; + std::shared_ptr _cpu_map; + void* _cpu_map_adress; bool _has_been_updated = false; }; diff --git a/src/renderer/images/vk_image.cpp b/src/renderer/images/vk_image.cpp index 369c4df..dd7dfa6 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/04/01 16:05:03 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 22:54:18 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -106,7 +106,7 @@ namespace mlx core::error::report(e_kind::fatal_error, "Vulkan : failed to create an image"); } - void Image::copyBuffer(Buffer& buffer) + void Image::copyFromBuffer(Buffer& buffer) { CmdPool cmdpool; cmdpool.init(); @@ -185,6 +185,85 @@ namespace mlx cmdpool.destroy(); } + void Image::copyToBuffer(Buffer& buffer) + { + CmdPool cmdpool; + cmdpool.init(); + auto device = Render_Core::get().getDevice().get(); + + VkCommandBufferAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandPool = cmdpool.get(); + allocInfo.commandBufferCount = 1; + + VkCommandBuffer cmdBuffer; + vkAllocateCommandBuffers(device, &allocInfo, &cmdBuffer); + + VkCommandBufferBeginInfo beginInfo{}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + vkBeginCommandBuffer(cmdBuffer, &beginInfo); + + 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; + copy_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + copy_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + copy_barrier.image = _image; + copy_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copy_barrier.subresourceRange.levelCount = 1; + copy_barrier.subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, ©_barrier); + + VkBufferImageCopy region = {}; + region.bufferOffset = 0; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + region.imageOffset = {0, 0, 0}; + region.imageExtent = { + _width, + _height, + 1 + }; + vkCmdCopyImageToBuffer(cmdBuffer, _image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer.get(), 1, ®ion); + + 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; + use_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + use_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + use_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + use_barrier.image = _image; + use_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + use_barrier.subresourceRange.levelCount = 1; + use_barrier.subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &use_barrier); + + vkEndCommandBuffer(cmdBuffer); + + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &cmdBuffer; + + auto graphicsQueue = Render_Core::get().getQueue().getGraphic(); + + vkQueueSubmit(graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE); + vkQueueWaitIdle(graphicsQueue); + + cmdpool.destroy(); + } + void Image::destroy() noexcept { if(_sampler != VK_NULL_HANDLE) diff --git a/src/renderer/images/vk_image.h b/src/renderer/images/vk_image.h index bfda3d0..08a6359 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/04/01 15:22:43 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 20:20:55 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -29,7 +29,8 @@ namespace mlx void create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties); void createImageView(VkImageViewType type, VkImageAspectFlags aspectFlags) noexcept; void createSampler() noexcept; - void copyBuffer(class Buffer& buffer); + void copyFromBuffer(class Buffer& buffer); + void copyToBuffer(class Buffer& buffer); virtual void destroy() noexcept; inline VkImage get() noexcept { return _image; } @@ -38,6 +39,8 @@ namespace mlx inline VkImageView getImageView() noexcept { return _image_view; } inline VkFormat getFormat() noexcept { return _format; } inline VkSampler getSampler() noexcept { return _sampler; } + inline uint32_t getWidth() const noexcept { return _width; } + inline uint32_t getHeight() const noexcept { return _height; } virtual ~Image() = default; diff --git a/src/renderer/pixel_put.cpp b/src/renderer/pixel_put.cpp index cb860f3..4de8a6a 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/04/01 17:30:54 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 20:02:30 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -65,7 +65,7 @@ namespace mlx { if(_impl->buffer.isMapped()) _impl->buffer.unmapMem(); - _impl->texture.copyBuffer(_impl->buffer); + _impl->texture.copyFromBuffer(_impl->buffer); _impl->texture.updateSet(0); } diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index c5c2bb4..64dd62b 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/02 15:24:40 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 18:10:01 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,12 +22,9 @@ namespace mlx _swapchain.init(this); _pass.init(this); _swapchain.initFB(); - _cmd_pool.init(); - + _cmd.init(); for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - _cmd_buffers[i].init(this); - - _semaphore.init(*this); + _semaphores[i].init(); _uniform_buffer.reset(new UBO); _uniform_buffer->create(this, sizeof(glm::mat4)); @@ -59,10 +56,10 @@ namespace mlx { auto device = Render_Core::get().getDevice().get(); - vkWaitForFences(device, 1, &_semaphore.getInFlightFence(_active_image_index), VK_TRUE, UINT64_MAX); + _cmd.getCmdBuffer(_active_image_index).waitForExecution(); + _cmd.getCmdBuffer(_active_image_index).reset(); - _image_index = 0; - VkResult result = vkAcquireNextImageKHR(device, _swapchain(), UINT64_MAX, _semaphore.getImageSemaphore(_active_image_index), VK_NULL_HANDLE, &_image_index); + VkResult result = vkAcquireNextImageKHR(device, _swapchain(), UINT64_MAX, _semaphores[_active_image_index].getImageSemaphore(), VK_NULL_HANDLE, &_image_index); if(result == VK_ERROR_OUT_OF_DATE_KHR) { @@ -72,14 +69,10 @@ namespace mlx else if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) core::error::report(e_kind::fatal_error, "Vulkan error : failed to acquire swapchain image"); - vkResetFences(device, 1, &_semaphore.getInFlightFence(_active_image_index)); - - vkResetCommandBuffer(_cmd_buffers[_active_image_index].get(), 0); - - _cmd_buffers[_active_image_index].beginRecord(); + _cmd.getCmdBuffer(_active_image_index).beginRecord(); _pass.begin(); - _pipeline.bindPipeline(_cmd_buffers[_active_image_index]); + _pipeline.bindPipeline(_cmd.getCmdBuffer(_active_image_index)); VkViewport viewport{}; viewport.x = 0.0f; @@ -88,12 +81,12 @@ namespace mlx viewport.height = (float)_swapchain._swapChainExtent.height; viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; - vkCmdSetViewport(_cmd_buffers[_active_image_index].get(), 0, 1, &viewport); + vkCmdSetViewport(_cmd.getCmdBuffer(_active_image_index).get(), 0, 1, &viewport); VkRect2D scissor{}; scissor.offset = { 0, 0 }; scissor.extent = _swapchain._swapChainExtent; - vkCmdSetScissor(_cmd_buffers[_active_image_index].get(), 0, 1, &scissor); + vkCmdSetScissor(_cmd.getCmdBuffer(_active_image_index).get(), 0, 1, &scissor); return true; } @@ -101,36 +94,18 @@ namespace mlx void Renderer::endFrame() { _pass.end(); - _cmd_buffers[_active_image_index].endRecord(); + _cmd.getCmdBuffer(_active_image_index).endRecord(); + _cmd.getCmdBuffer(_active_image_index).submit(_semaphores[_active_image_index]); - VkSubmitInfo submitInfo{}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - - VkSemaphore waitSemaphores[] = { _semaphore.getImageSemaphore(_active_image_index) }; - VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = waitSemaphores; - submitInfo.pWaitDstStageMask = waitStages; - - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &_cmd_buffers[_active_image_index].get(); - - VkSemaphore signalSemaphores[] = { _semaphore.getRenderImageSemaphore(_active_image_index) }; - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = signalSemaphores; - - if(vkQueueSubmit(Render_Core::get().getQueue().getGraphic(), 1, &submitInfo, _semaphore.getInFlightFence(_active_image_index)) != VK_SUCCESS) - core::error::report(e_kind::fatal_error, "Vulkan error : failed to submit draw command buffer"); + VkSwapchainKHR swapchain = _swapchain(); + VkSemaphore signalSemaphores[] = { _semaphores[_active_image_index].getRenderImageSemaphore() }; VkPresentInfoKHR presentInfo{}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = signalSemaphores; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = &_swapchain(); - + presentInfo.pSwapchains = &swapchain; presentInfo.pImageIndices = &_image_index; VkResult result = vkQueuePresentKHR(Render_Core::get().getQueue().getPresent(), &presentInfo); @@ -150,19 +125,17 @@ namespace mlx { vkDeviceWaitIdle(Render_Core::get().getDevice().get()); - for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) - _cmd_buffers[i].destroy(); - _pipeline.destroy(); _uniform_buffer->destroy(); _vert_layout.destroy(); _frag_layout.destroy(); + _cmd.destroy(); _desc_pool.destroy(); _swapchain.destroyFB(); _pass.destroy(); _swapchain.destroy(); - _semaphore.destroy(); - _cmd_pool.destroy(); + for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + _semaphores[i].destroy(); _surface.destroy(); } } diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index 0ec5fc2..2e90bfc 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/12/18 17:14:45 by maldavid #+# #+# */ -/* Updated: 2023/04/02 15:26:59 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 18:09:14 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,8 +23,7 @@ #include #include #include -#include -#include +#include #include #include #include @@ -92,14 +91,14 @@ namespace mlx inline void setWindow(class MLX_Window* window) { _window = window; } inline Surface& getSurface() noexcept { return _surface; } - inline CmdPool& getCmdPool() noexcept { return _cmd_pool; } + inline CmdPool& getCmdPool() noexcept { return _cmd.getCmdPool(); } inline UBO* getUniformBuffer() noexcept { return _uniform_buffer.get(); } inline SwapChain& getSwapChain() noexcept { return _swapchain; } - inline Semaphore& getSemaphore() noexcept { return _semaphore; } + inline Semaphore& getSemaphore(int i) noexcept { return _semaphores[i]; } inline RenderPass& getRenderPass() noexcept { return _pass; } - inline CmdBuffer& getCmdBuffer(int i) noexcept { return _cmd_buffers[i]; } inline GraphicPipeline& getPipeline() noexcept { return _pipeline; } - inline CmdBuffer& getActiveCmdBuffer() noexcept { return _cmd_buffers[_active_image_index]; } + inline CmdBuffer& getCmdBuffer(int i) noexcept { return _cmd.getCmdBuffer(i); } + inline CmdBuffer& getActiveCmdBuffer() noexcept { return _cmd.getCmdBuffer(_active_image_index); } inline DescriptorSet& getVertDescriptorSet() noexcept { return _vert_set; } inline DescriptorSet& getFragDescriptorSet() noexcept { return _frag_set; } inline DescriptorSetLayout& getVertDescriptorSetLayout() noexcept { return _vert_layout; } @@ -113,11 +112,11 @@ namespace mlx private: GraphicPipeline _pipeline; + CmdManager _cmd; RenderPass _pass; Surface _surface; - CmdPool _cmd_pool; SwapChain _swapchain; - Semaphore _semaphore; + std::array _semaphores; DescriptorPool _desc_pool; @@ -127,7 +126,6 @@ namespace mlx DescriptorSet _vert_set; DescriptorSet _frag_set; - std::array _cmd_buffers; std::unique_ptr _uniform_buffer; class MLX_Window* _window = nullptr; diff --git a/test/main.c b/test/main.c index ab2c444..2382020 100644 --- a/test/main.c +++ b/test/main.c @@ -6,7 +6,7 @@ /* By: maldavid +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/10/04 17:55:21 by maldavid #+# #+# */ -/* Updated: 2023/04/02 15:50:40 by maldavid ### ########.fr */ +/* Updated: 2023/04/02 23:58:57 by maldavid ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,6 +25,7 @@ int update(t_mlx *mlx) static int i = 0; int j; + mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo, 100, 100); j = 0; while (j < 400) { @@ -40,20 +41,47 @@ int update(t_mlx *mlx) return (0); } +void *create_image(t_mlx *mlx) +{ + int ignore[3]; + void *img; + char *addr; + int i; + + img = mlx_new_image(mlx->mlx, 100, 100); + addr = mlx_get_data_addr(mlx->mlx, img, &ignore[0], &ignore[1], &ignore[2]); + i = 0; + while (i < (100 * 100) * 4) + { + if (i < 10000 || i > 20000) + { + addr[i + 0] = 0xFF; + addr[i + 1] = 0xFF; + addr[i + 2] = 0x00; + addr[i + 3] = 0xFF; + } + i += 4; + } + return (img); +} + int main(void) { t_mlx mlx; int w; int h; + void *img; mlx.mlx = mlx_init(); mlx.win = mlx_new_window(mlx.mlx, 400, 400, "My window"); mlx.logo = mlx_png_file_to_image(mlx.mlx, "42_logo.png", &w, &h); mlx_pixel_put(mlx.mlx, mlx.win, 200, 10, 0xFFFF00FF); - mlx_put_image_to_window(mlx.mlx, mlx.win, mlx.logo, 100, 100); mlx_put_image_to_window(mlx.mlx, mlx.win, mlx.logo, 200, 200); + img = create_image(&mlx); + mlx_put_image_to_window(mlx.mlx, mlx.win, img, 200, 20); mlx_loop_hook(mlx.mlx, update, &mlx); mlx_loop(mlx.mlx); + mlx_destroy_image(mlx.mlx, img); mlx_destroy_image(mlx.mlx, mlx.logo); mlx_destroy_window(mlx.mlx, mlx.win); mlx_destroy_display(mlx.mlx);