From 39fb83d5bd3660581db5edfd4eebac2bd4a5969c Mon Sep 17 00:00:00 2001 From: Egor Orachyov Date: Sun, 21 Jul 2024 22:17:16 +0300 Subject: [PATCH] gh-45: remove dx11 style context and introduce explicit gfx cmd list objects --- .../runtime/asset/texture_asset_loader.cpp | 2 +- engine/runtime/core/pool_vector.hpp | 2 +- engine/runtime/engine.hpp | 3 +- .../gfx/{gfx_ctx.hpp => gfx_cmd_list.hpp} | 58 +- engine/runtime/gfx/gfx_ctx.cpp | 36 -- engine/runtime/gfx/gfx_defs.hpp | 39 +- engine/runtime/gfx/gfx_driver.hpp | 79 ++- engine/runtime/gfx/gfx_dynamic_buffers.cpp | 223 ------- engine/runtime/gfx/gfx_dynamic_buffers.hpp | 216 ------- engine/runtime/gfx/gfx_render_pass.hpp | 65 +- engine/runtime/gfx/gfx_vector.hpp | 18 +- .../runtime/gfx/threaded/gfx_ctx_threaded.hpp | 53 -- .../runtime/gfx/threaded/gfx_ctx_wrapper.cpp | 200 ------ .../runtime/gfx/threaded/gfx_ctx_wrapper.hpp | 115 ---- .../gfx/threaded/gfx_driver_threaded.hpp | 52 -- .../gfx/threaded/gfx_driver_wrapper.cpp | 288 --------- .../gfx/threaded/gfx_driver_wrapper.hpp | 115 ---- engine/runtime/gfx/vulkan/vk_cmd_list.cpp | 406 ++++++++++++ .../vulkan/{vk_ctx.hpp => vk_cmd_list.hpp} | 89 +-- engine/runtime/gfx/vulkan/vk_cmd_manager.cpp | 200 ++++-- engine/runtime/gfx/vulkan/vk_cmd_manager.hpp | 52 +- engine/runtime/gfx/vulkan/vk_ctx.cpp | 578 ------------------ engine/runtime/gfx/vulkan/vk_driver.cpp | 311 ++++------ engine/runtime/gfx/vulkan/vk_driver.hpp | 142 ++--- engine/runtime/gfx/vulkan/vk_mem_manager.cpp | 38 +- engine/runtime/gfx/vulkan/vk_mem_manager.hpp | 6 +- engine/runtime/gfx/vulkan/vk_queues.cpp | 38 +- engine/runtime/gfx/vulkan/vk_queues.hpp | 27 +- engine/runtime/gfx/vulkan/vk_render_pass.cpp | 145 +---- engine/runtime/gfx/vulkan/vk_render_pass.hpp | 128 +--- .../vk_semaphore.cpp} | 71 ++- .../vk_semaphore.hpp} | 39 +- engine/runtime/gfx/vulkan/vk_texture.cpp | 28 +- engine/runtime/gfx/vulkan/vk_texture.hpp | 10 +- engine/runtime/gfx/vulkan/vk_window.cpp | 4 +- engine/runtime/grc/shader_param_block.cpp | 6 +- engine/runtime/grc/shader_param_block.hpp | 2 +- engine/runtime/grc/shader_pass.cpp | 21 +- engine/runtime/grc/shader_pass.hpp | 6 +- engine/runtime/grc/texture.cpp | 7 +- engine/runtime/grc/texture_manager.cpp | 3 +- engine/runtime/grc/texture_manager.hpp | 3 +- engine/runtime/mesh/mesh.cpp | 6 +- engine/runtime/mesh/mesh_batch.cpp | 1 - engine/runtime/mesh/mesh_batch.hpp | 10 +- engine/runtime/platform/application.cpp | 6 +- engine/runtime/render/aux_draw_manager.cpp | 40 +- engine/runtime/render/canvas.cpp | 80 ++- engine/runtime/render/deferred_pipeline.cpp | 5 - engine/runtime/render/graphics_pipeline.hpp | 2 +- engine/runtime/render/render_engine.cpp | 182 +++--- engine/runtime/render/render_queue.cpp | 72 +-- engine/runtime/render/render_queue.hpp | 4 +- engine/runtime/render/render_scene.cpp | 12 +- engine/runtime/render/render_scene.hpp | 2 +- engine/runtime/scene/scene_manager.cpp | 4 +- engine/runtime/scripting/script_instance.hpp | 2 +- engine/runtime/system/engine.cpp | 15 +- engine/runtime/system/engine.hpp | 3 +- scripts/loc.py | 4 +- template/main.cpp | 2 +- 61 files changed, 1394 insertions(+), 2982 deletions(-) rename engine/runtime/gfx/{gfx_ctx.hpp => gfx_cmd_list.hpp} (74%) delete mode 100644 engine/runtime/gfx/gfx_ctx.cpp delete mode 100644 engine/runtime/gfx/gfx_dynamic_buffers.cpp delete mode 100644 engine/runtime/gfx/gfx_dynamic_buffers.hpp delete mode 100644 engine/runtime/gfx/threaded/gfx_ctx_threaded.hpp delete mode 100644 engine/runtime/gfx/threaded/gfx_ctx_wrapper.cpp delete mode 100644 engine/runtime/gfx/threaded/gfx_ctx_wrapper.hpp delete mode 100644 engine/runtime/gfx/threaded/gfx_driver_threaded.hpp delete mode 100644 engine/runtime/gfx/threaded/gfx_driver_wrapper.cpp delete mode 100644 engine/runtime/gfx/threaded/gfx_driver_wrapper.hpp create mode 100644 engine/runtime/gfx/vulkan/vk_cmd_list.cpp rename engine/runtime/gfx/vulkan/{vk_ctx.hpp => vk_cmd_list.hpp} (66%) delete mode 100644 engine/runtime/gfx/vulkan/vk_ctx.cpp rename engine/runtime/gfx/{threaded/gfx_worker.cpp => vulkan/vk_semaphore.cpp} (59%) rename engine/runtime/gfx/{threaded/gfx_worker.hpp => vulkan/vk_semaphore.hpp} (76%) diff --git a/engine/plugins/runtime/asset/texture_asset_loader.cpp b/engine/plugins/runtime/asset/texture_asset_loader.cpp index 2fd767a20..7817bd4a9 100644 --- a/engine/plugins/runtime/asset/texture_asset_loader.cpp +++ b/engine/plugins/runtime/asset/texture_asset_loader.cpp @@ -28,7 +28,7 @@ #include "texture_asset_loader.hpp" #include "asset/texture_import_data.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_driver.hpp" #include "grc/image.hpp" #include "grc/texture.hpp" diff --git a/engine/runtime/core/pool_vector.hpp b/engine/runtime/core/pool_vector.hpp index cd6915b8e..537da2cfe 100644 --- a/engine/runtime/core/pool_vector.hpp +++ b/engine/runtime/core/pool_vector.hpp @@ -105,7 +105,7 @@ namespace wmoge { return m_i != other.m_i; } IterType& operator*() { - return (IterType*) m_nodes[m_i / NODE_CAPACITY]->items[m_i % NODE_CAPACITY].mem; + return *((IterType*) m_nodes[m_i / NODE_CAPACITY]->items[m_i % NODE_CAPACITY].mem); } void operator++() { m_i += 1; diff --git a/engine/runtime/engine.hpp b/engine/runtime/engine.hpp index d68af8848..08829b17d 100644 --- a/engine/runtime/engine.hpp +++ b/engine/runtime/engine.hpp @@ -103,11 +103,10 @@ #include "gameplay/game_token_manager.hpp" #include "gfx/gfx_buffers.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_defs.hpp" #include "gfx/gfx_desc_set.hpp" #include "gfx/gfx_driver.hpp" -#include "gfx/gfx_dynamic_buffers.hpp" #include "gfx/gfx_pipeline.hpp" #include "gfx/gfx_render_pass.hpp" #include "gfx/gfx_resource.hpp" diff --git a/engine/runtime/gfx/gfx_ctx.hpp b/engine/runtime/gfx/gfx_cmd_list.hpp similarity index 74% rename from engine/runtime/gfx/gfx_ctx.hpp rename to engine/runtime/gfx/gfx_cmd_list.hpp index 8921587b9..37181917d 100644 --- a/engine/runtime/gfx/gfx_ctx.hpp +++ b/engine/runtime/gfx/gfx_cmd_list.hpp @@ -44,24 +44,15 @@ #include "math/vec.hpp" #include "platform/window.hpp" -#include -#include -#include -#include - namespace wmoge { /** - * @class GfxCtx - * @brief Gfx context interface - * - * Context exposes gfx an environment and API for resources manipulation and rendering. - */ - class GfxCtx { + * @class GfxCmdList + * @brief List to record gfx commands for execution on device + */ + class GfxCmdList : public GfxResource { public: - virtual ~GfxCtx() = default; - - virtual void update_desc_set(const Ref& set, const GfxDescSetResources& resources) = 0; + ~GfxCmdList() override = default; virtual void update_vert_buffer(const Ref& buffer, int offset, int range, const Ref& data) = 0; virtual void update_index_buffer(const Ref& buffer, int offset, int range, const Ref& data) = 0; @@ -84,14 +75,9 @@ namespace wmoge { virtual void barrier_image(const Ref& texture, GfxTexBarrierType barrier_type) = 0; virtual void barrier_buffer(const Ref& buffer) = 0; - virtual void begin_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name = Strid()) = 0; - virtual void bind_target(const Ref& window) = 0; - virtual void bind_color_target(const Ref& texture, int target, int mip, int slice) = 0; - virtual void bind_depth_target(const Ref& texture, int mip, int slice) = 0; + virtual void begin_render_pass(const GfxRenderPassBeginInfo& pass_desc) = 0; + virtual void peek_render_pass(GfxRenderPassRef& rp) = 0; virtual void viewport(const Rect2i& viewport) = 0; - virtual void clear(int target, const Vec4f& color) = 0; - virtual void clear(float depth, int stencil) = 0; - virtual void extract_render_pass(GfxRenderPassRef& rp) = 0; virtual void bind_pso(const Ref& pipeline) = 0; virtual void bind_pso(const Ref& pipeline) = 0; virtual void bind_vert_buffer(const Ref& buffer, int index, int offset = 0) = 0; @@ -103,36 +89,12 @@ namespace wmoge { virtual void dispatch(Vec3i group_count) = 0; virtual void end_render_pass() = 0; - virtual void execute(const std::function& functor) = 0; - virtual void shutdown() = 0; - - virtual void begin_frame() = 0; - virtual void end_frame() = 0; - virtual void begin_label(const Strid& label) = 0; virtual void end_label() = 0; - [[nodiscard]] virtual const Mat4x4f& clip_matrix() const = 0; - [[nodiscard]] virtual GfxCtxType ctx_type() const = 0; - - static Vec3i group_size(int x, int y, int local_size); - }; - - /** - * @class GfxDebugLabel - * @brief Scope for debug laber - */ - struct GfxDebugLabel { - GfxDebugLabel(GfxCtx* ctx, const Strid& label) : ctx(ctx) { ctx->begin_label(label); } - ~GfxDebugLabel() { ctx->end_label(); } - GfxCtx* ctx; + virtual GfxQueueType get_queue_type() const = 0; }; -#ifndef WMOGE_RELEASE - #define WG_GFX_LABEL(ctx, label) \ - GfxDebugLabel __label_guard(ctx, label); -#else - #define WG_GFX_LABEL(ctx, label) -#endif + using GfxCmdListRef = Ref; -}// namespace wmoge \ No newline at end of file +}// namespace wmoge diff --git a/engine/runtime/gfx/gfx_ctx.cpp b/engine/runtime/gfx/gfx_ctx.cpp deleted file mode 100644 index 2d24aad8d..000000000 --- a/engine/runtime/gfx/gfx_ctx.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#include "gfx_ctx.hpp" - -namespace wmoge { - - Vec3i GfxCtx::group_size(int x, int y, int local_size) { - return Vec3i(int(Math::div_up(x, local_size)), int(Math::div_up(y, local_size)), 1); - } - -}// namespace wmoge diff --git a/engine/runtime/gfx/gfx_defs.hpp b/engine/runtime/gfx/gfx_defs.hpp index 2a370bd9f..23f607bdf 100644 --- a/engine/runtime/gfx/gfx_defs.hpp +++ b/engine/runtime/gfx/gfx_defs.hpp @@ -108,26 +108,12 @@ namespace wmoge { static constexpr int NUM_PLATFORMS = int(GfxShaderPlatform::Max); }; - /** @brief Type of gfx context behaviour */ - enum class GfxCtxType : int { - Immediate, - Deferred, - Async - }; - - /** @brief Status of the shader */ - enum class GfxShaderStatus : int { - Compiling, - Compiled, - Failed - }; - - /** @brief Status of the gfx pipeline */ - enum class GfxPipelineStatus : int { - Default, - Creating, - Created, - Failed + /** @brief Type of gfx queues for submission */ + enum class GfxQueueType : int { + Graphics = 0, + Compute, + Copy, + None }; /** @brief Type of elements in index buffer */ @@ -169,9 +155,10 @@ namespace wmoge { /** @brief Texture manual barrier type */ enum class GfxTexBarrierType : int { - RenderTarget, - Sampling, - Storage + RenderTarget,// For drawing into texture + Sampling, // For sampling from shader in read-only mode + Storage, // For read-write in compute shader + Presentation // For presentation to the screen }; /** @brief Texture type */ @@ -596,4 +583,10 @@ namespace wmoge { int uniform_block_offset_alignment = -1; }; + struct GfxUtils { + static Vec3i group_size(int x, int y, int local_size) { + return Vec3i(int(Math::div_up(x, local_size)), int(Math::div_up(y, local_size)), 1); + } + }; + }// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/gfx_driver.hpp b/engine/runtime/gfx/gfx_driver.hpp index c5ec8e2c5..13b7fae52 100644 --- a/engine/runtime/gfx/gfx_driver.hpp +++ b/engine/runtime/gfx/gfx_driver.hpp @@ -32,10 +32,9 @@ #include "core/callback_queue.hpp" #include "core/data.hpp" #include "gfx/gfx_buffers.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_defs.hpp" #include "gfx/gfx_desc_set.hpp" -#include "gfx/gfx_dynamic_buffers.hpp" #include "gfx/gfx_pipeline.hpp" #include "gfx/gfx_render_pass.hpp" #include "gfx/gfx_resource.hpp" @@ -63,51 +62,45 @@ namespace wmoge { public: virtual ~GfxDriver() = default; - virtual Ref make_vert_format(const GfxVertElements& elements, const Strid& name = Strid()) = 0; - virtual Ref make_vert_buffer(int size, GfxMemUsage usage, const Strid& name = Strid()) = 0; - virtual Ref make_index_buffer(int size, GfxMemUsage usage, const Strid& name = Strid()) = 0; - virtual Ref make_uniform_buffer(int size, GfxMemUsage usage, const Strid& name = Strid()) = 0; - virtual Ref make_storage_buffer(int size, GfxMemUsage usage, const Strid& name = Strid()) = 0; - virtual Ref make_shader(GfxShaderDesc desc, const Strid& name = Strid()) = 0; - virtual Ref make_program(GfxShaderProgramDesc desc, const Strid& name = Strid()) = 0; - virtual Ref make_texture(const GfxTextureDesc& desc, const Strid& name = Strid()) = 0; - virtual Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name = Strid()) = 0; - virtual Ref make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name = Strid()) = 0; - virtual Ref make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name = Strid()) = 0; - virtual Ref make_sampler(const GfxSamplerDesc& desc, const Strid& name = Strid()) = 0; - virtual Ref make_pso_layout(const GfxDescSetLayouts& layouts, const Strid& name = Strid()) = 0; - virtual Ref make_pso_graphics(const GfxPsoStateGraphics& state, const Strid& name = Strid()) = 0; - virtual Ref make_pso_compute(const GfxPsoStateCompute& state, const Strid& name = Strid()) = 0; - virtual Ref make_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name = Strid()) = 0; - virtual Ref make_dyn_vert_buffer(int chunk_size, const Strid& name = Strid()) = 0; - virtual Ref make_dyn_index_buffer(int chunk_size, const Strid& name = Strid()) = 0; - virtual Ref make_dyn_uniform_buffer(int chunk_size, const Strid& name = Strid()) = 0; - virtual Ref make_desc_layout(const GfxDescSetLayoutDesc& desc, const Strid& name = Strid()) = 0; - virtual Ref make_desc_set(const GfxDescSetResources& resources, const Ref& layout, const Strid& name = Strid()) = 0; - virtual Async make_shaders(const Ref& request) = 0; - virtual Async make_psos_graphics(const Ref& request) = 0; - virtual Async make_psos_compute(const Ref& request) = 0; - virtual void shutdown() = 0; - virtual void begin_frame() = 0; - virtual void end_frame() = 0; - virtual void prepare_window(const Ref& window) = 0; - virtual void swap_buffers(const Ref& window) = 0; + virtual Ref make_vert_format(const GfxVertElements& elements, const Strid& name = Strid()) = 0; + virtual Ref make_vert_buffer(int size, GfxMemUsage usage, const Strid& name = Strid()) = 0; + virtual Ref make_index_buffer(int size, GfxMemUsage usage, const Strid& name = Strid()) = 0; + virtual Ref make_uniform_buffer(int size, GfxMemUsage usage, const Strid& name = Strid()) = 0; + virtual Ref make_storage_buffer(int size, GfxMemUsage usage, const Strid& name = Strid()) = 0; + virtual Ref make_shader(GfxShaderDesc desc, const Strid& name = Strid()) = 0; + virtual Ref make_program(GfxShaderProgramDesc desc, const Strid& name = Strid()) = 0; + virtual Ref make_texture(const GfxTextureDesc& desc, const Strid& name = Strid()) = 0; + virtual Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name = Strid()) = 0; + virtual Ref make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name = Strid()) = 0; + virtual Ref make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name = Strid()) = 0; + virtual Ref make_sampler(const GfxSamplerDesc& desc, const Strid& name = Strid()) = 0; + virtual Ref make_pso_layout(const GfxDescSetLayouts& layouts, const Strid& name = Strid()) = 0; + virtual Ref make_pso_graphics(const GfxPsoStateGraphics& state, const Strid& name = Strid()) = 0; + virtual Ref make_pso_compute(const GfxPsoStateCompute& state, const Strid& name = Strid()) = 0; + virtual Ref make_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name = Strid()) = 0; + virtual Ref make_render_pass(const Ref& window, const Strid& name = Strid()) = 0; + virtual Ref make_desc_layout(const GfxDescSetLayoutDesc& desc, const Strid& name = Strid()) = 0; + virtual Ref make_desc_set(const GfxDescSetResources& resources, const Ref& layout, const Strid& name = Strid()) = 0; + virtual Async make_shaders(const Ref& request) = 0; + virtual Async make_psos_graphics(const Ref& request) = 0; + virtual Async make_psos_compute(const Ref& request) = 0; - [[nodiscard]] virtual class GfxCtx* ctx_immediate() = 0; - [[nodiscard]] virtual class GfxCtx* ctx_async() = 0; + virtual void begin_frame(std::size_t frame_id, const array_view>& windows) = 0; + virtual GfxCmdListRef acquire_cmd_list(GfxQueueType queue_type = GfxQueueType::Graphics) = 0; + virtual void submit_cmd_list(const GfxCmdListRef& cmd_list) = 0; + virtual void end_frame(bool swap_buffers = true) = 0; - [[nodiscard]] virtual const GfxDeviceCaps& device_caps() const = 0; - [[nodiscard]] virtual const Strid& driver_name() const = 0; - [[nodiscard]] virtual const std::string& pipeline_cache_path() const = 0; - [[nodiscard]] virtual const std::thread::id& thread_id() const = 0; - [[nodiscard]] virtual const Mat4x4f& clip_matrix() const = 0; - [[nodiscard]] virtual std::size_t frame_number() const = 0; - [[nodiscard]] virtual bool on_gfx_thread() const = 0; - [[nodiscard]] virtual GfxShaderLang shader_lang() const = 0; - [[nodiscard]] virtual GfxType get_gfx_type() const = 0; - [[nodiscard]] virtual GfxShaderPlatform get_shader_platform() const = 0; + [[nodiscard]] virtual const GfxDeviceCaps& device_caps() const = 0; + [[nodiscard]] virtual const Strid& driver_name() const = 0; + [[nodiscard]] virtual const std::string& pipeline_cache_path() const = 0; + [[nodiscard]] virtual const Mat4x4f& clip_matrix() const = 0; + [[nodiscard]] virtual std::size_t frame_number() const = 0; + [[nodiscard]] virtual GfxShaderLang shader_lang() const = 0; + [[nodiscard]] virtual GfxType get_gfx_type() const = 0; + [[nodiscard]] virtual GfxShaderPlatform get_shader_platform() const = 0; + [[nodiscard]] virtual const GfxCmdListRef& get_default_list() const = 0; }; }// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/gfx_dynamic_buffers.cpp b/engine/runtime/gfx/gfx_dynamic_buffers.cpp deleted file mode 100644 index 4631b0b41..000000000 --- a/engine/runtime/gfx/gfx_dynamic_buffers.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#include "gfx/gfx_dynamic_buffers.hpp" - -#include "core/log.hpp" -#include "core/string_id.hpp" -#include "core/string_utils.hpp" -#include "gfx/gfx_ctx.hpp" -#include "gfx/gfx_driver.hpp" -#include "math/math_utils.hpp" -#include "system/engine.hpp" - -#include "gfx_dynamic_buffers.hpp" -#include -#include - -namespace wmoge { - - GfxUniformPool::GfxUniformPool(const Strid& name) { - m_name = name; - } - GfxUniformBufferSetup GfxUniformPool::allocate(int constants_size, const void* mem) { - assert(constants_size > 0); - assert(mem); - - std::lock_guard guard(m_mutex); - - auto* engine = Engine::instance(); - auto* gfx_driver = engine->gfx_driver(); - auto* gfx_ctx = engine->gfx_ctx(); - - const auto size_exp = Math::ge_pow2(constants_size); - - if (size_exp.second >= m_buckets.size()) { - m_buckets.resize(size_exp.second + 1); - WG_LOG_INFO("pool new bucket size=" << size_exp.first << " id=" << size_exp.second); - } - - Bucket& bucket = m_buckets[size_exp.second]; - - if (bucket.next >= bucket.buffers.size()) { - bucket.buffers.push_back(gfx_driver->make_uniform_buffer(int(size_exp.first), GfxMemUsage::GpuLocal, SID(m_name.str() + " size=" + std::to_string(size_exp.first)))); - WG_LOG_INFO("pool new chunk size=" << size_exp.first << " id=" << size_exp.second); - } - - auto& buffer = bucket.buffers[bucket.next]; - void* host_ptr = gfx_ctx->map_uniform_buffer(buffer); - std::memcpy(host_ptr, mem, constants_size); - gfx_ctx->unmap_uniform_buffer(buffer); - - GfxUniformBufferSetup setup{}; - setup.buffer = buffer.get(); - setup.offset = 0; - setup.range = constants_size; - - bucket.next += 1; - - return setup; - } - - void GfxUniformPool::configure(GfxUniformBufferSetup& setup, int constants_size, const void* mem) { - if (!setup.buffer) { - setup = allocate(constants_size, mem); - return; - } - - auto* engine = Engine::instance(); - auto* gfx_ctx = engine->gfx_ctx(); - - auto buffer = Ref(setup.buffer); - void* host_ptr = gfx_ctx->map_uniform_buffer(buffer); - std::memcpy(host_ptr, mem, constants_size); - gfx_ctx->unmap_uniform_buffer(buffer); - } - - void GfxUniformPool::resycle_allocations() { - std::lock_guard guard(m_mutex); - - for (Bucket& bucket : m_buckets) { - bucket.next = 0; - } - } - - GfxDynBuffer::GfxDynBuffer(int size, int alignment, const Strid& name) { - m_default_chunk_size = size; - m_alignment = alignment; - m_name = name; - } - GfxDynAllocation GfxDynBuffer::allocate_base(int bytes_to_allocate) { - std::lock_guard guard(m_mutex); - - const int required_size = int(Math::align(bytes_to_allocate, m_alignment)); - - do { - if (m_current_chunk >= m_chunks.size()) { - auto& chunk = m_chunks.emplace_back(); - - int size = int(Math::ge_pow2_val(Math::max(m_default_chunk_size, required_size))); - - chunk.buffer = make_buffer(size, SID(m_name.str() + " n=" + StringUtils::from_int(m_current_chunk))); - chunk.offset = 0; - } - if (!m_chunks[m_current_chunk].mapping) { - auto& chunk = m_chunks[m_current_chunk]; - - chunk.mapping = map_buffer(chunk.buffer); - assert(chunk.mapping); - } - if (m_chunks[m_current_chunk].offset + required_size <= m_chunks[m_current_chunk].buffer->size()) { - auto& chunk = m_chunks[m_current_chunk]; - assert(chunk.mapping); - - GfxDynAllocation allocation{}; - allocation.buffer = chunk.buffer.get(); - allocation.offset = chunk.offset; - allocation.ptr = (std::uint8_t*) chunk.mapping + chunk.offset; - - chunk.offset += required_size; - - return allocation; - } - m_current_chunk += 1; - } while (true); - } - void GfxDynBuffer::flush() { - std::lock_guard guard(m_mutex); - - if (m_current_chunk < m_chunks.size()) { - for (int i = 0; i <= m_current_chunk; i++) { - auto& chunk = m_chunks[i]; - if (chunk.mapping) { - unmap_buffer(chunk.buffer); - chunk.mapping = nullptr; - } - } - - m_current_chunk += 1; - } - } - void GfxDynBuffer::recycle() { - std::lock_guard guard(m_mutex); - - m_current_chunk = 0; - - int pool_size = 0; - for (auto& chunk : m_chunks) { - chunk.offset = 0; - chunk.mapping = nullptr; - pool_size += chunk.buffer->size(); - } - - const int recycle_size = int(Math::ge_pow2_val(pool_size)); - if (pool_size > 0 && recycle_size > pool_size) { - m_chunks.clear(); - - auto& chunk = m_chunks.emplace_back(); - chunk.buffer = make_buffer(recycle_size, SID(m_name.str() + " n=" + StringUtils::from_int(m_current_chunk))); - chunk.offset = 0; - } - } - - GfxDynVertBuffer::GfxDynVertBuffer(int size, int alignment, const Strid& name) : GfxDynBuffer(size, alignment, name) { - } - Ref GfxDynVertBuffer::make_buffer(int size, const Strid& name) { - return Engine::instance()->gfx_driver()->make_vert_buffer(size, GfxMemUsage::GpuLocal, name); - } - void* GfxDynVertBuffer::map_buffer(const Ref& buffer) { - return Engine::instance()->gfx_ctx()->map_vert_buffer(buffer.cast()); - } - void GfxDynVertBuffer::unmap_buffer(const Ref& buffer) { - Engine::instance()->gfx_ctx()->unmap_vert_buffer(buffer.cast()); - } - - GfxDynIndexBuffer::GfxDynIndexBuffer(int size, int alignment, const Strid& name) : GfxDynBuffer(size, alignment, name) { - } - Ref GfxDynIndexBuffer::make_buffer(int size, const Strid& name) { - return Engine::instance()->gfx_driver()->make_index_buffer(size, GfxMemUsage::GpuLocal, name); - } - void* GfxDynIndexBuffer::map_buffer(const Ref& buffer) { - return Engine::instance()->gfx_ctx()->map_index_buffer(buffer.cast()); - } - void GfxDynIndexBuffer::unmap_buffer(const Ref& buffer) { - Engine::instance()->gfx_ctx()->unmap_index_buffer(buffer.cast()); - } - - GfxDynUniformBuffer::GfxDynUniformBuffer(int size, int alignment, const Strid& name) : GfxDynBuffer(size, alignment, name) { - } - Ref GfxDynUniformBuffer::make_buffer(int size, const Strid& name) { - return Engine::instance()->gfx_driver()->make_uniform_buffer(size, GfxMemUsage::GpuLocal, name); - } - void* GfxDynUniformBuffer::map_buffer(const Ref& buffer) { - return Engine::instance()->gfx_ctx()->map_uniform_buffer(buffer.cast()); - } - void GfxDynUniformBuffer::unmap_buffer(const Ref& buffer) { - Engine::instance()->gfx_ctx()->unmap_uniform_buffer(buffer.cast()); - } - -}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/gfx_dynamic_buffers.hpp b/engine/runtime/gfx/gfx_dynamic_buffers.hpp deleted file mode 100644 index 09efc1b25..000000000 --- a/engine/runtime/gfx/gfx_dynamic_buffers.hpp +++ /dev/null @@ -1,216 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#pragma once - -#include "core/buffered_vector.hpp" -#include "core/synchronization.hpp" -#include "gfx/gfx_buffers.hpp" -#include "gfx/gfx_defs.hpp" -#include "gfx/gfx_resource.hpp" - -#include - -namespace wmoge { - - /** - * @class GfxUniformPool - * @brief Pool for per-frame small const buffer allocations to configure render passes - */ - class GfxUniformPool : public GfxResource { - public: - GfxUniformPool(const Strid& name); - ~GfxUniformPool() override = default; - - virtual GfxUniformBufferSetup allocate(int constants_size, const void* mem); - virtual void configure(GfxUniformBufferSetup& setup, int constants_size, const void* mem); - virtual void resycle_allocations(); - - template - GfxUniformBufferSetup allocate(const ConstantsStructure& constants) { - return allocate(int(sizeof(ConstantsStructure)), &constants); - } - - template - GfxUniformBufferSetup configure(GfxUniformBufferSetup& setup, const ConstantsStructure& constants) { - return configure(setup, int(sizeof(ConstantsStructure)), &constants); - } - - private: - struct Bucket { - std::vector> buffers; - int next = 0; - }; - - buffered_vector m_buckets; - - mutable SpinMutex m_mutex; - }; - - /** - * @class GfxDynAllocation - * @brief Allocation of dynamic buffer - */ - template - struct GfxDynAllocation { - GfxBufferType* buffer = nullptr; - CpuPtrType* ptr = nullptr; - int offset = 0; - }; - - /** - * @class GfxDynBuffer - * @brief Dynamic buffer for frequently changed data - * - * Usage pattern: - * - Allocate dynamic chunk specifying required size to allocate - * - Fill data into obtained pointer which must be rendered - * - Flush all allocations - * - Use buffer for rendering before recycle is called - */ - class GfxDynBuffer : public GfxResource { - public: - GfxDynBuffer(int size, int alignment, const Strid& name); - ~GfxDynBuffer() override = default; - - virtual GfxDynAllocation allocate_base(int bytes_to_allocate); - virtual void flush(); - virtual void recycle(); - - template - GfxDynAllocation allocate_base() { - const GfxDynAllocation chunk = allocate_base(sizeof(BufferStructure)); - return {(GfxBufferType*) chunk.buffer, (BufferStructure*) chunk.ptr, chunk.offset}; - } - - template - GfxDynAllocation allocate_base_n(int num_elements) { - const GfxDynAllocation chunk = allocate_base(sizeof(ElementStructure) * num_elements); - return {(GfxBufferType*) chunk.buffer, (ElementStructure*) chunk.ptr, chunk.offset}; - } - - protected: - virtual Ref make_buffer(int size, const Strid& name) = 0; - virtual void* map_buffer(const Ref& buffer) = 0; - virtual void unmap_buffer(const Ref& buffer) = 0; - - protected: - struct Chunk { - Ref buffer; - void* mapping = nullptr; - int offset = 0; - }; - - buffered_vector m_chunks; - int m_current_chunk = 0; - int m_alignment = 0; - int m_default_chunk_size = 0; - - mutable SpinMutex m_mutex; - }; - - /** - * @class GfxDynVertBuffer - * @brief Dynamic vertex buffer for immediate and frequently changed geometry - */ - class GfxDynVertBuffer : public GfxDynBuffer { - public: - GfxDynVertBuffer(int size, int alignment, const Strid& name); - ~GfxDynVertBuffer() override = default; - - GfxDynAllocation allocate(int bytes_to_allocate) { - auto allocation = allocate_base(bytes_to_allocate); - return {(GfxVertBuffer*) allocation.buffer, allocation.ptr, allocation.offset}; - } - - template - GfxDynAllocation allocate() { - return allocate_base(); - } - - template - GfxDynAllocation allocate_n(int num_elements) { - return allocate_base_n(num_elements); - } - - protected: - Ref make_buffer(int size, const Strid& name) override; - void* map_buffer(const Ref& buffer) override; - void unmap_buffer(const Ref& buffer) override; - }; - - /** - * @class GfxDynIndexBuffer - * @brief Dynamic index buffer for immediate and frequently changed geometry - */ - class GfxDynIndexBuffer : public GfxDynBuffer { - public: - GfxDynIndexBuffer(int size, int alignment, const Strid& name); - ~GfxDynIndexBuffer() override = default; - - template - GfxDynAllocation allocate() { - return allocate_base(); - } - - template - GfxDynAllocation allocate_n(int num_elements) { - return allocate_base_n(num_elements); - } - - protected: - Ref make_buffer(int size, const Strid& name) override; - void* map_buffer(const Ref& buffer) override; - void unmap_buffer(const Ref& buffer) override; - }; - - /** - * @class GfxDynUniformBuffer - * @brief Dynamic uniform buffer for constants allocation for rendering - */ - class GfxDynUniformBuffer : public GfxDynBuffer { - public: - GfxDynUniformBuffer(int size, int alignment, const Strid& name); - ~GfxDynUniformBuffer() override = default; - - template - GfxDynAllocation allocate() { - return allocate_base(); - } - - template - GfxDynAllocation allocate_n(int num_elements) { - return allocate_base_n(num_elements); - } - - protected: - Ref make_buffer(int size, const Strid& name) override; - void* map_buffer(const Ref& buffer) override; - void unmap_buffer(const Ref& buffer) override; - }; - -}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/gfx_render_pass.hpp b/engine/runtime/gfx/gfx_render_pass.hpp index a03f11974..cd7910e50 100644 --- a/engine/runtime/gfx/gfx_render_pass.hpp +++ b/engine/runtime/gfx/gfx_render_pass.hpp @@ -29,6 +29,9 @@ #include "gfx/gfx_defs.hpp" #include "gfx/gfx_resource.hpp" +#include "gfx/gfx_texture.hpp" +#include "math/color.hpp" +#include "platform/window.hpp" #include #include @@ -53,16 +56,65 @@ namespace wmoge { /** * @class GfxRenderPassDesc - * @brief Gfx rendering pass object (for internal usage primary) + * @brief Gfx rendering pass object */ class GfxRenderPass : public GfxResource { public: - ~GfxRenderPass() override = default; - virtual const GfxRenderPassDesc& pass_desc() const = 0; + ~GfxRenderPass() override = default; + virtual const GfxRenderPassDesc& desc() const = 0; }; using GfxRenderPassRef = Ref; + /** + * @class GfxTargetInfo + * @brief Info to bind texture as a render target + */ + struct GfxTargetInfo { + Ref texture; + int slice = 0; + int mip = 0; + }; + + /** + * @class GfxFrameBufferDesc + * @brief Frame buffer desc for creation and caching + */ + struct GfxFrameBufferDesc { + GfxFrameBufferDesc() = default; + bool operator==(const GfxFrameBufferDesc& other) const; + std::size_t hash() const; + + std::array color_targets{}; // = Default + GfxTargetInfo depth_stencil_target{};// = Default + Ref render_pass; // = nullptr + }; + + /** + * @class GfxFrameBuffer + * @brief Gfx frame buffer object with complete set of targets + */ + class GfxFrameBuffer : public GfxResource { + public: + ~GfxFrameBuffer() override = default; + virtual const GfxFrameBufferDesc& desc() const = 0; + }; + + using GfxFrameBufferRef = Ref; + + /** + * @class GfxRenderPassBeginInfo + * @brief Info to start render pass + */ + struct GfxRenderPassBeginInfo { + GfxFrameBufferRef frame_buffer; + Ref window; + std::array clear_color{}; + float clear_depth = 1.0f; + int clear_stencil = 0; + Strid name; + }; + }// namespace wmoge namespace std { @@ -74,4 +126,11 @@ namespace std { } }; + template<> + struct hash { + std::size_t operator()(const wmoge::GfxFrameBufferDesc& desc) const { + return desc.hash(); + } + }; + }// namespace std \ No newline at end of file diff --git a/engine/runtime/gfx/gfx_vector.hpp b/engine/runtime/gfx/gfx_vector.hpp index f103c7247..a99219839 100644 --- a/engine/runtime/gfx/gfx_vector.hpp +++ b/engine/runtime/gfx/gfx_vector.hpp @@ -29,7 +29,7 @@ #include "core/string_utils.hpp" #include "gfx/gfx_buffers.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_driver.hpp" #include "math/math_utils.hpp" #include "system/engine.hpp" @@ -59,7 +59,7 @@ namespace wmoge { void push_back(const T& element); void resize(std::size_t size); - void flush(GfxCtx* gfx_ctx); + void flush(GfxCmdList& cmd_list); void clear(); void free(); void set_name(const Strid& name); @@ -93,18 +93,18 @@ namespace wmoge { } template - void GfxVector::flush(GfxCtx* gfx_ctx) { + void GfxVector::flush(GfxCmdList& cmd_list) { if (!m_data.empty()) { void* ptr = nullptr; if constexpr (std::is_same_v) { - ptr = gfx_ctx->map_vert_buffer(m_buffer); + ptr = cmd_list.map_vert_buffer(m_buffer); } if constexpr (std::is_same_v) { - ptr = gfx_ctx->map_index_buffer(m_buffer); + ptr = cmd_list.map_index_buffer(m_buffer); } if constexpr (std::is_same_v) { - ptr = gfx_ctx->map_storage_buffer(m_buffer); + ptr = cmd_list.map_storage_buffer(m_buffer); } assert(ptr); @@ -112,13 +112,13 @@ namespace wmoge { std::memcpy(ptr, m_data.data(), sizeof(T) * get_size()); if constexpr (std::is_same_v) { - gfx_ctx->unmap_vert_buffer(m_buffer); + cmd_list.unmap_vert_buffer(m_buffer); } if constexpr (std::is_same_v) { - gfx_ctx->unmap_index_buffer(m_buffer); + cmd_list.unmap_index_buffer(m_buffer); } if constexpr (std::is_same_v) { - gfx_ctx->unmap_storage_buffer(m_buffer); + cmd_list.unmap_storage_buffer(m_buffer); } } } diff --git a/engine/runtime/gfx/threaded/gfx_ctx_threaded.hpp b/engine/runtime/gfx/threaded/gfx_ctx_threaded.hpp deleted file mode 100644 index 516371511..000000000 --- a/engine/runtime/gfx/threaded/gfx_ctx_threaded.hpp +++ /dev/null @@ -1,53 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#pragma once - -#include "core/callback_stream.hpp" -#include "gfx/gfx_ctx.hpp" - -namespace wmoge { - - /** - * @class GfxCtxThreaded - * @brief An extension for a gfx ctx for threaded communication support - * - * Threaded context provides cmd stream for communication, so all commands - * to a context can be safely queued and transferred from any engine thread - * to a gfx thread for execution. - * - * @see GfxCtx - * @see GfxCtxWrapper - */ - class GfxCtxThreaded : public GfxCtx { - public: - ~GfxCtxThreaded() override = default; - - virtual CallbackStream* cmd_stream() = 0; - }; - -}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/threaded/gfx_ctx_wrapper.cpp b/engine/runtime/gfx/threaded/gfx_ctx_wrapper.cpp deleted file mode 100644 index 3ee18d0d4..000000000 --- a/engine/runtime/gfx/threaded/gfx_ctx_wrapper.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#include "gfx_ctx_wrapper.hpp" - -#include "profiler/profiler.hpp" - -#include - -namespace wmoge { - - GfxCtxWrapper::GfxCtxWrapper(GfxCtxThreaded* ctx) { - WG_AUTO_PROFILE_GFX("GfxCtxWrapper::GfxCtxWrapper"); - - assert(ctx); - - m_ctx = ctx; - m_stream = ctx->cmd_stream(); - m_clip_matrix = ctx->clip_matrix(); - m_ctx_type = ctx->ctx_type(); - } - - void GfxCtxWrapper::update_desc_set(const Ref& set, const GfxDescSetResources& resources) { - m_stream->push([=]() { m_ctx->update_desc_set(set, resources); }); - } - - void GfxCtxWrapper::update_vert_buffer(const Ref& buffer, int offset, int range, const Ref& data) { - m_stream->push([=]() { m_ctx->update_vert_buffer(buffer, offset, range, data); }); - } - void GfxCtxWrapper::update_index_buffer(const Ref& buffer, int offset, int range, const Ref& data) { - m_stream->push([=]() { m_ctx->update_index_buffer(buffer, offset, range, data); }); - } - void GfxCtxWrapper::update_uniform_buffer(const Ref& buffer, int offset, int range, const Ref& data) { - m_stream->push([=]() { m_ctx->update_uniform_buffer(buffer, offset, range, data); }); - } - void GfxCtxWrapper::update_storage_buffer(const Ref& buffer, int offset, int range, const Ref& data) { - m_stream->push([=]() { m_ctx->update_storage_buffer(buffer, offset, range, data); }); - } - void GfxCtxWrapper::update_texture_2d(const Ref& texture, int mip, Rect2i region, const Ref& data) { - m_stream->push([=]() { m_ctx->update_texture_2d(texture, mip, region, data); }); - } - void GfxCtxWrapper::update_texture_2d_array(const Ref& texture, int mip, int slice, Rect2i region, const Ref& data) { - m_stream->push([=]() { m_ctx->update_texture_2d_array(texture, mip, slice, region, data); }); - } - void GfxCtxWrapper::update_texture_cube(const Ref& texture, int mip, int face, Rect2i region, const Ref& data) { - m_stream->push([=]() { m_ctx->update_texture_cube(texture, mip, face, region, data); }); - } - - void* GfxCtxWrapper::map_vert_buffer(const Ref& buffer) { - void* mapped_ptr = nullptr; - m_stream->push_and_wait([&]() { mapped_ptr = m_ctx->map_vert_buffer(buffer); }); - return mapped_ptr; - } - void* GfxCtxWrapper::map_index_buffer(const Ref& buffer) { - void* mapped_ptr = nullptr; - m_stream->push_and_wait([&]() { mapped_ptr = m_ctx->map_index_buffer(buffer); }); - return mapped_ptr; - } - void* GfxCtxWrapper::map_uniform_buffer(const Ref& buffer) { - void* mapped_ptr = nullptr; - m_stream->push_and_wait([&]() { mapped_ptr = m_ctx->map_uniform_buffer(buffer); }); - return mapped_ptr; - } - void* GfxCtxWrapper::map_storage_buffer(const Ref& buffer) { - void* mapped_ptr = nullptr; - m_stream->push_and_wait([&]() { mapped_ptr = m_ctx->map_storage_buffer(buffer); }); - return mapped_ptr; - } - void GfxCtxWrapper::unmap_vert_buffer(const Ref& buffer) { - m_stream->push([=]() { m_ctx->unmap_vert_buffer(buffer); }); - } - void GfxCtxWrapper::unmap_index_buffer(const Ref& buffer) { - m_stream->push([=]() { m_ctx->unmap_index_buffer(buffer); }); - } - void GfxCtxWrapper::unmap_uniform_buffer(const Ref& buffer) { - m_stream->push([=]() { m_ctx->unmap_uniform_buffer(buffer); }); - } - void GfxCtxWrapper::unmap_storage_buffer(const Ref& buffer) { - m_stream->push([=]() { m_ctx->unmap_storage_buffer(buffer); }); - } - - void GfxCtxWrapper::barrier_image(const Ref& texture, GfxTexBarrierType barrier_type) { - m_stream->push([=]() { m_ctx->barrier_image(texture, barrier_type); }); - } - void GfxCtxWrapper::barrier_buffer(const Ref& buffer) { - m_stream->push([=]() { m_ctx->barrier_buffer(buffer); }); - } - - void GfxCtxWrapper::begin_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name) { - m_stream->push([=]() { m_ctx->begin_render_pass(pass_desc, name); }); - } - void GfxCtxWrapper::bind_target(const Ref& window) { - m_stream->push([=]() { m_ctx->bind_target(window); }); - } - void GfxCtxWrapper::bind_color_target(const Ref& texture, int target, int mip, int slice) { - m_stream->push([=]() { m_ctx->bind_color_target(texture, target, mip, slice); }); - } - void GfxCtxWrapper::bind_depth_target(const Ref& texture, int mip, int slice) { - m_stream->push([=]() { m_ctx->bind_depth_target(texture, mip, slice); }); - } - void GfxCtxWrapper::viewport(const Rect2i& viewport) { - m_stream->push([=]() { m_ctx->viewport(viewport); }); - } - void GfxCtxWrapper::clear(int target, const Vec4f& color) { - m_stream->push([=]() { m_ctx->clear(target, color); }); - } - void GfxCtxWrapper::clear(float depth, int stencil) { - m_stream->push([=]() { m_ctx->clear(depth, stencil); }); - } - void GfxCtxWrapper::extract_render_pass(GfxRenderPassRef& rp) { - m_stream->push_and_wait([&]() { m_ctx->extract_render_pass(rp); }); - } - void GfxCtxWrapper::bind_pso(const Ref& pipeline) { - m_stream->push([=]() { m_ctx->bind_pso(pipeline); }); - } - void GfxCtxWrapper::bind_pso(const Ref& pipeline) { - m_stream->push([=]() { m_ctx->bind_pso(pipeline); }); - } - void GfxCtxWrapper::bind_vert_buffer(const Ref& buffer, int index, int offset) { - m_stream->push([=]() { m_ctx->bind_vert_buffer(buffer, index, offset); }); - } - void GfxCtxWrapper::bind_index_buffer(const Ref& buffer, GfxIndexType index_type, int offset) { - m_stream->push([=]() { m_ctx->bind_index_buffer(buffer, index_type, offset); }); - } - void GfxCtxWrapper::bind_desc_set(const Ref& set, int index) { - m_stream->push([=]() { m_ctx->bind_desc_set(set, index); }); - } - void GfxCtxWrapper::bind_desc_sets(const array_view& sets, int offset) { - m_stream->push([=]() { m_ctx->bind_desc_sets(sets, offset); }); - } - void GfxCtxWrapper::draw(int vertex_count, int base_vertex, int instance_count) { - m_stream->push([=]() { m_ctx->draw(vertex_count, base_vertex, instance_count); }); - } - void GfxCtxWrapper::draw_indexed(int index_count, int base_vertex, int instance_count) { - m_stream->push([=]() { m_ctx->draw_indexed(index_count, base_vertex, instance_count); }); - } - void GfxCtxWrapper::dispatch(Vec3i group_count) { - m_stream->push([=]() { m_ctx->dispatch(group_count); }); - } - void GfxCtxWrapper::end_render_pass() { - m_stream->push([=]() { m_ctx->end_render_pass(); }); - } - - void GfxCtxWrapper::execute(const std::function& functor) { - WG_AUTO_PROFILE_GFX("GfxCtxWrapper::execute"); - - m_stream->push_and_wait([&]() { m_ctx->execute(functor); }); - } - void GfxCtxWrapper::shutdown() { - WG_AUTO_PROFILE_GFX("GfxCtxWrapper::shutdown"); - - m_stream->push_and_wait([=]() { m_ctx->shutdown(); }); - } - - void GfxCtxWrapper::begin_frame() { - m_stream->push([=]() { m_ctx->begin_frame(); }); - } - void GfxCtxWrapper::end_frame() { - m_stream->push([=]() { m_ctx->end_frame(); }); - } - - void GfxCtxWrapper::begin_label(const Strid& label) { - m_stream->push([=]() { m_ctx->begin_label(label); }); - } - void GfxCtxWrapper::end_label() { - m_stream->push([=]() { m_ctx->end_label(); }); - } - - const Mat4x4f& GfxCtxWrapper::clip_matrix() const { - return m_clip_matrix; - } - GfxCtxType GfxCtxWrapper::ctx_type() const { - return m_ctx_type; - } - -}// namespace wmoge diff --git a/engine/runtime/gfx/threaded/gfx_ctx_wrapper.hpp b/engine/runtime/gfx/threaded/gfx_ctx_wrapper.hpp deleted file mode 100644 index 3ad18da38..000000000 --- a/engine/runtime/gfx/threaded/gfx_ctx_wrapper.hpp +++ /dev/null @@ -1,115 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#pragma once - -#include "core/callback_stream.hpp" -#include "gfx/gfx_ctx.hpp" -#include "gfx/threaded/gfx_ctx_threaded.hpp" - -namespace wmoge { - - /** - * @class GfxCtxWrapper - * @brief Thread-safe wrapper for gfx context to be used from any thread - * - * Wraps GfxCtx interface. It uses commands serialization to send it - * to a separate gfx thread, responsible for GPU communication. Simple - * commands sent with no wait. Commands requiring immediate feedback - * require to wait until gfx thread process them. - * - * @see GfxCtx - * @see GfxCtxThreaded - */ - class GfxCtxWrapper : public GfxCtx { - public: - explicit GfxCtxWrapper(GfxCtxThreaded* ctx); - - ~GfxCtxWrapper() override = default; - - void update_desc_set(const Ref& set, const GfxDescSetResources& resources) override; - - void update_vert_buffer(const Ref& buffer, int offset, int range, const Ref& data) override; - void update_index_buffer(const Ref& buffer, int offset, int range, const Ref& data) override; - void update_uniform_buffer(const Ref& buffer, int offset, int range, const Ref& data) override; - void update_storage_buffer(const Ref& buffer, int offset, int range, const Ref& data) override; - void update_texture_2d(const Ref& texture, int mip, Rect2i region, const Ref& data) override; - void update_texture_2d_array(const Ref& texture, int mip, int slice, Rect2i region, const Ref& data) override; - void update_texture_cube(const Ref& texture, int mip, int face, Rect2i region, const Ref& data) override; - - void* map_vert_buffer(const Ref& buffer) override; - void* map_index_buffer(const Ref& buffer) override; - void* map_uniform_buffer(const Ref& buffer) override; - void* map_storage_buffer(const Ref& buffer) override; - - void unmap_vert_buffer(const Ref& buffer) override; - void unmap_index_buffer(const Ref& buffer) override; - void unmap_uniform_buffer(const Ref& buffer) override; - void unmap_storage_buffer(const Ref& buffer) override; - - void barrier_image(const Ref& texture, GfxTexBarrierType barrier_type) override; - void barrier_buffer(const Ref& buffer) override; - - void begin_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name) override; - void bind_target(const Ref& window) override; - void bind_color_target(const Ref& texture, int target, int mip, int slice) override; - void bind_depth_target(const Ref& texture, int mip, int slice) override; - void viewport(const Rect2i& viewport) override; - void clear(int target, const Vec4f& color) override; - void clear(float depth, int stencil) override; - void extract_render_pass(GfxRenderPassRef& rp) override; - void bind_pso(const Ref& pipeline) override; - void bind_pso(const Ref& pipeline) override; - void bind_vert_buffer(const Ref& buffer, int index, int offset) override; - void bind_index_buffer(const Ref& buffer, GfxIndexType index_type, int offset) override; - void bind_desc_set(const Ref& set, int index) override; - void bind_desc_sets(const array_view& sets, int offset) override; - void draw(int vertex_count, int base_vertex, int instance_count) override; - void draw_indexed(int index_count, int base_vertex, int instance_count) override; - void dispatch(Vec3i group_count) override; - void end_render_pass() override; - - void execute(const std::function& functor) override; - void shutdown() override; - - void begin_frame() override; - void end_frame() override; - - void begin_label(const Strid& label) override; - void end_label() override; - - [[nodiscard]] const Mat4x4f& clip_matrix() const override; - [[nodiscard]] GfxCtxType ctx_type() const override; - - private: - GfxCtxThreaded* m_ctx = nullptr; - CallbackStream* m_stream = nullptr; - Mat4x4f m_clip_matrix; - GfxCtxType m_ctx_type; - }; - -}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/threaded/gfx_driver_threaded.hpp b/engine/runtime/gfx/threaded/gfx_driver_threaded.hpp deleted file mode 100644 index 10b1fe93f..000000000 --- a/engine/runtime/gfx/threaded/gfx_driver_threaded.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#pragma once - -#include "core/callback_stream.hpp" -#include "gfx/gfx_driver.hpp" - -namespace wmoge { - - /** - * @class GfxDriverThreaded - * @brief An extension for a gfx driver for threaded communication support - * - * This interface extends gfx driver, so created resources are only constructed - * objects by gfx driver factory. Actual initialization is done only on gfx thread. - * - * @see GfxDriver - * @see GfxDriverWrapper - */ - class GfxDriverThreaded : public GfxDriver { - public: - ~GfxDriverThreaded() override = default; - - virtual CallbackStream* cmd_stream() = 0; - }; - -}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/threaded/gfx_driver_wrapper.cpp b/engine/runtime/gfx/threaded/gfx_driver_wrapper.cpp deleted file mode 100644 index 869fbf848..000000000 --- a/engine/runtime/gfx/threaded/gfx_driver_wrapper.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#include "gfx_driver_wrapper.hpp" - -#include "core/log.hpp" -#include "profiler/profiler.hpp" - -#include - -namespace wmoge { - - GfxDriverWrapper::GfxDriverWrapper(GfxDriverThreaded* driver) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::GfxDriverWrapper"); - - assert(driver); - - m_driver = driver; - m_stream = driver->cmd_stream(); - m_shader_lang = driver->shader_lang(); - m_device_caps = driver->device_caps(); - m_driver_name = driver->driver_name(); - m_thread_id = driver->thread_id(); - m_clip_matrix = driver->clip_matrix(); - m_pipeline_cache_path = driver->pipeline_cache_path(); - m_ctx_immediate = driver->ctx_immediate(); - m_ctx_async = driver->ctx_async(); - m_gfx_type = driver->get_gfx_type(); - m_shader_platform = driver->get_shader_platform(); - } - - Ref GfxDriverWrapper::make_vert_format(const GfxVertElements& elements, const Strid& name) { - Ref vert_format; - m_stream->push_and_wait([&]() { vert_format = m_driver->make_vert_format(elements, name); }); - return vert_format; - } - Ref GfxDriverWrapper::make_vert_buffer(int size, GfxMemUsage usage, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_vert_buffer"); - - Ref buffer; - m_stream->push_and_wait([&]() { buffer = m_driver->make_vert_buffer(size, usage, name); }); - return buffer; - } - Ref GfxDriverWrapper::make_index_buffer(int size, GfxMemUsage usage, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_index_buffer"); - - Ref buffer; - m_stream->push_and_wait([&]() { buffer = m_driver->make_index_buffer(size, usage, name); }); - return buffer; - } - Ref GfxDriverWrapper::make_uniform_buffer(int size, GfxMemUsage usage, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_uniform_buffer"); - - Ref buffer; - m_stream->push_and_wait([&]() { buffer = m_driver->make_uniform_buffer(size, usage, name); }); - return buffer; - } - Ref GfxDriverWrapper::make_storage_buffer(int size, GfxMemUsage usage, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_storage_buffer"); - - Ref buffer; - m_stream->push_and_wait([&]() { buffer = m_driver->make_storage_buffer(size, usage, name); }); - return buffer; - } - Ref GfxDriverWrapper::make_shader(GfxShaderDesc desc, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_shader"); - - Ref shader; - m_stream->push_and_wait([&]() { shader = m_driver->make_shader(std::move(desc), name); }); - return shader; - } - Ref GfxDriverWrapper::make_program(GfxShaderProgramDesc desc, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_program"); - - Ref program; - m_stream->push_and_wait([&]() { program = m_driver->make_program(std::move(desc), name); }); - return program; - } - Ref GfxDriverWrapper::make_texture(const GfxTextureDesc& desc, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_texture"); - - Ref texture; - m_stream->push_and_wait([&]() { texture = m_driver->make_texture(desc, name); }); - return texture; - } - Ref GfxDriverWrapper::make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_texture_2d"); - - Ref texture; - m_stream->push_and_wait([&]() { texture = m_driver->make_texture_2d(width, height, mips, format, usages, mem_usage, swizz, name); }); - return texture; - } - Ref GfxDriverWrapper::make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_texture_2d_array"); - - Ref texture; - m_stream->push_and_wait([&]() { texture = m_driver->make_texture_2d_array(width, height, mips, slices, format, usages, mem_usage, name); }); - return texture; - } - Ref GfxDriverWrapper::make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_texture_cube"); - - Ref texture; - m_stream->push_and_wait([&]() { texture = m_driver->make_texture_cube(width, height, mips, format, usages, mem_usage, name); }); - return texture; - } - Ref GfxDriverWrapper::make_sampler(const GfxSamplerDesc& desc, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_sampler"); - - Ref sampler; - m_stream->push_and_wait([&]() { sampler = m_driver->make_sampler(desc, name); }); - return sampler; - } - Ref GfxDriverWrapper::make_pso_layout(const GfxDescSetLayouts& layouts, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_pso_layout"); - - Ref pipeline_layout; - m_stream->push_and_wait([&]() { pipeline_layout = m_driver->make_pso_layout(layouts, name); }); - return pipeline_layout; - } - Ref GfxDriverWrapper::make_pso_graphics(const GfxPsoStateGraphics& state, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_pso_graphics"); - - Ref pipeline; - m_stream->push_and_wait([&]() { pipeline = m_driver->make_pso_graphics(state, name); }); - return pipeline; - } - Ref GfxDriverWrapper::make_pso_compute(const GfxPsoStateCompute& state, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_pso_compute"); - - Ref pipeline; - m_stream->push_and_wait([&]() { pipeline = m_driver->make_pso_compute(state, name); }); - return pipeline; - } - Ref GfxDriverWrapper::make_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_render_pass"); - - Ref render_pass; - m_stream->push_and_wait([&]() { render_pass = m_driver->make_render_pass(pass_desc, name); }); - return render_pass; - } - Ref GfxDriverWrapper::make_dyn_vert_buffer(int chunk_size, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_dyn_vert_buffer"); - - Ref dyn_buffer; - m_stream->push_and_wait([&]() { dyn_buffer = m_driver->make_dyn_vert_buffer(chunk_size, name); }); - return dyn_buffer; - } - Ref GfxDriverWrapper::make_dyn_index_buffer(int chunk_size, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_dyn_index_buffer"); - - Ref dyn_buffer; - m_stream->push_and_wait([&]() { dyn_buffer = m_driver->make_dyn_index_buffer(chunk_size, name); }); - return dyn_buffer; - } - Ref GfxDriverWrapper::make_dyn_uniform_buffer(int chunk_size, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_dyn_uniform_buffer"); - - Ref dyn_buffer; - m_stream->push_and_wait([&]() { dyn_buffer = m_driver->make_dyn_uniform_buffer(chunk_size, name); }); - return dyn_buffer; - } - Ref GfxDriverWrapper::make_desc_layout(const GfxDescSetLayoutDesc& desc, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_desc_layout"); - - Ref desc_layout; - m_stream->push_and_wait([&]() { desc_layout = m_driver->make_desc_layout(desc, name); }); - return desc_layout; - } - Ref GfxDriverWrapper::make_desc_set(const GfxDescSetResources& resources, const Ref& layout, const Strid& name) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_desc_set"); - - Ref desc_set; - m_stream->push_and_wait([&]() { desc_set = m_driver->make_desc_set(resources, layout, name); }); - return desc_set; - } - Async GfxDriverWrapper::make_shaders(const Ref& request) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_shaders"); - - Async result; - m_stream->push_and_wait([&]() { result = m_driver->make_shaders(request); }); - return result; - } - Async GfxDriverWrapper::make_psos_graphics(const Ref& request) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_psos_graphics"); - - Async result; - m_stream->push_and_wait([&]() { result = m_driver->make_psos_graphics(request); }); - return result; - } - Async GfxDriverWrapper::make_psos_compute(const Ref& request) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_psos_compute"); - - Async result; - m_stream->push_and_wait([&]() { result = m_driver->make_psos_compute(request); }); - return result; - } - - void GfxDriverWrapper::shutdown() { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::shutdown"); - - m_stream->push_and_wait([=]() { m_driver->shutdown(); }); - } - - void GfxDriverWrapper::begin_frame() { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::begin_frame"); - - m_stream->push([=]() { m_driver->begin_frame(); }); - } - void GfxDriverWrapper::end_frame() { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::end_frame"); - - m_stream->push([=]() { m_driver->end_frame(); }); - } - void GfxDriverWrapper::prepare_window(const Ref& window) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::prepare_window"); - - m_stream->push([=]() { m_driver->prepare_window(window); }); - } - void GfxDriverWrapper::swap_buffers(const Ref& window) { - WG_AUTO_PROFILE_GFX("GfxDriverWrapper::swap_buffers"); - - m_stream->push_and_wait([=]() { m_driver->swap_buffers(window); }); - } - - class GfxCtx* GfxDriverWrapper::ctx_immediate() { - return m_ctx_immediate; - } - class GfxCtx* GfxDriverWrapper::ctx_async() { - return m_ctx_async; - } - - const GfxDeviceCaps& GfxDriverWrapper::device_caps() const { - return m_device_caps; - } - const Strid& GfxDriverWrapper::driver_name() const { - return m_driver_name; - } - const std::string& GfxDriverWrapper::pipeline_cache_path() const { - return m_pipeline_cache_path; - } - const std::thread::id& GfxDriverWrapper::thread_id() const { - return m_thread_id; - } - const Mat4x4f& GfxDriverWrapper::clip_matrix() const { - return m_clip_matrix; - } - size_t GfxDriverWrapper::frame_number() const { - return m_driver->frame_number(); - } - bool GfxDriverWrapper::on_gfx_thread() const { - return m_thread_id == std::this_thread::get_id(); - } - GfxShaderLang GfxDriverWrapper::shader_lang() const { - return m_shader_lang; - } - GfxType GfxDriverWrapper::get_gfx_type() const { - return m_gfx_type; - } - GfxShaderPlatform GfxDriverWrapper::get_shader_platform() const { - return m_shader_platform; - } - -}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/threaded/gfx_driver_wrapper.hpp b/engine/runtime/gfx/threaded/gfx_driver_wrapper.hpp deleted file mode 100644 index 57b54e59f..000000000 --- a/engine/runtime/gfx/threaded/gfx_driver_wrapper.hpp +++ /dev/null @@ -1,115 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#pragma once - -#include "core/callback_stream.hpp" -#include "gfx/gfx_driver.hpp" -#include "gfx/threaded/gfx_driver_threaded.hpp" - -namespace wmoge { - - /** - * @class GfxDriverWrapper - * @brief Thread-safe wrapper for gfx device to used from any thread - * - * Wraps GfxDriver interface. It uses commands serialization to send it - * to a separate gfx thread, responsible for GPU communication. Simple - * commands sent with no wait. Commands requiring immediate feedback - * require to wait until gfx thread process them. - * - * @see GfxDriver - * @see GfxDriverThreaded - */ - class GfxDriverWrapper : public GfxDriver { - public: - explicit GfxDriverWrapper(GfxDriverThreaded* driver); - - ~GfxDriverWrapper() override = default; - - Ref make_vert_format(const GfxVertElements& elements, const Strid& name) override; - Ref make_vert_buffer(int size, GfxMemUsage usage, const Strid& name) override; - Ref make_index_buffer(int size, GfxMemUsage usage, const Strid& name) override; - Ref make_uniform_buffer(int size, GfxMemUsage usage, const Strid& name) override; - Ref make_storage_buffer(int size, GfxMemUsage usage, const Strid& name) override; - Ref make_shader(GfxShaderDesc desc, const Strid& name) override; - Ref make_program(GfxShaderProgramDesc desc, const Strid& name) override; - Ref make_texture(const GfxTextureDesc& desc, const Strid& name) override; - Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name) override; - Ref make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) override; - Ref make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) override; - Ref make_sampler(const GfxSamplerDesc& desc, const Strid& name) override; - Ref make_pso_layout(const GfxDescSetLayouts& layouts, const Strid& name) override; - Ref make_pso_graphics(const GfxPsoStateGraphics& state, const Strid& name) override; - Ref make_pso_compute(const GfxPsoStateCompute& state, const Strid& name) override; - Ref make_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name) override; - Ref make_dyn_vert_buffer(int chunk_size, const Strid& name) override; - Ref make_dyn_index_buffer(int chunk_size, const Strid& name) override; - Ref make_dyn_uniform_buffer(int chunk_size, const Strid& name) override; - Ref make_desc_layout(const GfxDescSetLayoutDesc& desc, const Strid& name) override; - Ref make_desc_set(const GfxDescSetResources& resources, const Ref& layout, const Strid& name) override; - Async make_shaders(const Ref& request) override; - Async make_psos_graphics(const Ref& request) override; - Async make_psos_compute(const Ref& request) override; - - void shutdown() override; - - void begin_frame() override; - void end_frame() override; - void prepare_window(const Ref& window) override; - void swap_buffers(const Ref& window) override; - - [[nodiscard]] class GfxCtx* ctx_immediate() override; - [[nodiscard]] class GfxCtx* ctx_async() override; - - [[nodiscard]] const GfxDeviceCaps& device_caps() const override; - [[nodiscard]] const Strid& driver_name() const override; - [[nodiscard]] const std::string& pipeline_cache_path() const override; - [[nodiscard]] const std::thread::id& thread_id() const override; - [[nodiscard]] const Mat4x4f& clip_matrix() const override; - [[nodiscard]] size_t frame_number() const override; - [[nodiscard]] bool on_gfx_thread() const override; - [[nodiscard]] GfxShaderLang shader_lang() const override; - [[nodiscard]] GfxType get_gfx_type() const override; - [[nodiscard]] GfxShaderPlatform get_shader_platform() const override; - - private: - GfxDriverThreaded* m_driver = nullptr; - GfxShaderLang m_shader_lang; - CallbackStream* m_stream = nullptr; - GfxDeviceCaps m_device_caps; - Strid m_driver_name; - std::thread::id m_thread_id; - Mat4x4f m_clip_matrix; - std::string m_pipeline_cache_path; - GfxType m_gfx_type; - GfxShaderPlatform m_shader_platform; - class GfxCtx* m_ctx_immediate = nullptr; - class GfxCtx* m_ctx_async = nullptr; - }; - -}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/vulkan/vk_cmd_list.cpp b/engine/runtime/gfx/vulkan/vk_cmd_list.cpp new file mode 100644 index 000000000..c303e00da --- /dev/null +++ b/engine/runtime/gfx/vulkan/vk_cmd_list.cpp @@ -0,0 +1,406 @@ +/**********************************************************************************/ +/* Wmoge game engine */ +/* Available at github https://github.com/EgorOrachyov/wmoge */ +/**********************************************************************************/ +/* MIT License */ +/* */ +/* Copyright (c) 2023 Egor Orachyov */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining a copy */ +/* of this software and associated documentation files (the "Software"), to deal */ +/* in the Software without restriction, including without limitation the rights */ +/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ +/* copies of the Software, and to permit persons to whom the Software is */ +/* furnished to do so, subject to the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be included in all */ +/* copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/**********************************************************************************/ + +#include "vk_cmd_list.hpp" + +#include "gfx/vulkan/vk_defs.hpp" +#include "gfx/vulkan/vk_driver.hpp" +#include "profiler/profiler.hpp" + +#include + +namespace wmoge { + + VKCmdList::VKCmdList(VkCommandBuffer cmd_buffer, GfxQueueType queue_type, VKDriver& driver) : VKResource(driver) { + m_cmd_buffer = cmd_buffer; + m_queue_type = queue_type; + } + + VKCmdList::~VKCmdList() { + // nothing to do: command buffer returned on submit to pool + } + + void VKCmdList::update_vert_buffer(const Ref& buffer, int offset, int range, const Ref& data) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::update_vert_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + dynamic_cast(buffer.get())->update(m_cmd_buffer, offset, range, data); + } + void VKCmdList::update_index_buffer(const Ref& buffer, int offset, int range, const Ref& data) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::update_index_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + dynamic_cast(buffer.get())->update(m_cmd_buffer, offset, range, data); + } + void VKCmdList::update_uniform_buffer(const Ref& buffer, int offset, int range, const Ref& data) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::update_uniform_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + dynamic_cast(buffer.get())->update(m_cmd_buffer, offset, range, data); + } + void VKCmdList::update_storage_buffer(const Ref& buffer, int offset, int range, const Ref& data) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::update_storage_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + dynamic_cast(buffer.get())->update(m_cmd_buffer, offset, range, data); + } + void VKCmdList::update_texture_2d(const Ref& texture, int mip, Rect2i region, const Ref& data) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::update_texture_2d"); + + assert(texture); + assert(!m_in_render_pass); + + dynamic_cast(texture.get())->update_2d(m_cmd_buffer, mip, region, data); + } + void VKCmdList::update_texture_2d_array(const Ref& texture, int mip, int slice, Rect2i region, const Ref& data) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::update_texture_2d_array"); + + assert(texture); + assert(!m_in_render_pass); + + dynamic_cast(texture.get())->update_2d_array(m_cmd_buffer, mip, slice, region, data); + } + void VKCmdList::update_texture_cube(const Ref& texture, int mip, int face, Rect2i region, const Ref& data) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::update_texture_cube"); + + assert(texture); + assert(!m_in_render_pass); + + dynamic_cast(texture.get())->update_cube(m_cmd_buffer, mip, face, region, data); + } + + void* VKCmdList::map_vert_buffer(const Ref& buffer) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::map_vert_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + return (dynamic_cast(buffer.get()))->map(); + } + void* VKCmdList::map_index_buffer(const Ref& buffer) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::map_index_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + return (dynamic_cast(buffer.get()))->map(); + } + void* VKCmdList::map_uniform_buffer(const Ref& buffer) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::map_uniform_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + return (dynamic_cast(buffer.get()))->map(); + } + void* VKCmdList::map_storage_buffer(const Ref& buffer) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::map_storage_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + return (dynamic_cast(buffer.get()))->map(); + } + void VKCmdList::unmap_vert_buffer(const Ref& buffer) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::unmap_vert_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + dynamic_cast(buffer.get())->unmap(m_cmd_buffer); + } + void VKCmdList::unmap_index_buffer(const Ref& buffer) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::unmap_index_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + dynamic_cast(buffer.get())->unmap(m_cmd_buffer); + } + void VKCmdList::unmap_uniform_buffer(const Ref& buffer) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::unmap_uniform_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + dynamic_cast(buffer.get())->unmap(m_cmd_buffer); + } + void VKCmdList::unmap_storage_buffer(const Ref& buffer) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::unmap_storage_buffer"); + + assert(buffer); + assert(!m_in_render_pass); + + dynamic_cast(buffer.get())->unmap(m_cmd_buffer); + } + + void VKCmdList::barrier_image(const Ref& texture, GfxTexBarrierType barrier_type) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::barrier_image"); + + dynamic_cast(texture.get())->transition_layout(m_cmd_buffer, barrier_type); + } + void VKCmdList::barrier_buffer(const Ref& buffer) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::barrier_buffer"); + + dynamic_cast(buffer.get())->barrier(m_cmd_buffer); + } + + void VKCmdList::begin_render_pass(const GfxRenderPassBeginInfo& pass_desc) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::begin_render_pass"); + + assert(!m_in_render_pass); + + m_in_render_pass = true; + m_pipeline_bound_compute = false; + + m_current_fbo = pass_desc.frame_buffer.cast(); + m_current_pass = m_current_fbo->desc().render_pass.cast(); + + std::array clear_values{}; + int clear_value_count = 0; + + for (int i = 0; i < m_current_pass->color_targets_count(); i++) { + VkClearColorValue value; + value.float32[0] = pass_desc.clear_color[i].x(); + value.float32[1] = pass_desc.clear_color[i].y(); + value.float32[2] = pass_desc.clear_color[i].z(); + value.float32[3] = pass_desc.clear_color[i].w(); + clear_values[clear_value_count++].color = value; + } + if (m_current_pass->has_depth_stencil()) { + VkClearDepthStencilValue value; + value.depth = pass_desc.clear_depth; + value.stencil = pass_desc.clear_stencil; + clear_values[clear_value_count++].depthStencil = value; + } + + VkRect2D render_area{}; + render_area.offset.x = 0; + render_area.offset.y = 0; + render_area.extent.width = static_cast(m_current_pass->get_size().x()); + render_area.extent.height = static_cast(m_current_pass->get_size().y()); + + VkRenderPassBeginInfo render_pass_info{}; + render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + render_pass_info.renderPass = m_current_pass->render_pass(); + render_pass_info.framebuffer = m_current_fbo->framebuffer(); + render_pass_info.renderArea = render_area; + render_pass_info.clearValueCount = clear_value_count; + render_pass_info.pClearValues = clear_values.data(); + + vkCmdBeginRenderPass(m_cmd_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); + } + void VKCmdList::peek_render_pass(GfxRenderPassRef& rp) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::peek_render_pass"); + + assert(m_in_render_pass); + + rp = m_current_pass; + } + void VKCmdList::viewport(const Rect2i& viewport) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::viewport"); + + assert(m_in_render_pass); + + m_viewport = viewport; + + VkViewport vk_viewport; + vk_viewport.x = static_cast(m_viewport.x()); + vk_viewport.y = static_cast(m_viewport.y()); + vk_viewport.width = static_cast(m_viewport.z()); + vk_viewport.height = static_cast(m_viewport.w()); + vk_viewport.minDepth = 0.0f; + vk_viewport.maxDepth = 1.0f; + vkCmdSetViewport(m_cmd_buffer, 0, 1, &vk_viewport); + + VkRect2D vk_scissor; + vk_scissor.offset.x = m_viewport.x(); + vk_scissor.offset.y = m_viewport.y(); + vk_scissor.extent.width = m_viewport.z(); + vk_scissor.extent.height = m_viewport.w(); + vkCmdSetScissor(m_cmd_buffer, 0, 1, &vk_scissor); + } + void VKCmdList::bind_pso(const Ref& pipeline) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::bind_pso"); + + assert(m_in_render_pass); + assert(pipeline); + + Ref new_pipeline = pipeline.cast(); + + vkCmdBindPipeline(m_cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, new_pipeline->pipeline()); + m_current_pso_graphics = std::move(new_pipeline); + m_current_pso_layout = m_current_pso_graphics->layout(); + m_pipeline_bound_graphics = true; + } + void VKCmdList::bind_pso(const Ref& pipeline) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::bind_pso"); + + assert(!m_in_render_pass); + assert(pipeline); + + Ref new_pipeline = pipeline.cast(); + + vkCmdBindPipeline(m_cmd_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, new_pipeline->pipeline()); + m_current_pso_compute = std::move(new_pipeline); + m_current_pso_layout = m_current_pso_compute->layout(); + m_pipeline_bound_compute = true; + } + void VKCmdList::bind_vert_buffer(const Ref& buffer, int index, int offset) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::bind_vert_buffer"); + + assert(m_pipeline_bound_graphics); + assert(buffer); + + m_current_vert_buffers[index] = buffer.cast(); + m_current_vert_buffers_offsets[index] = offset; + + VkBuffer vk_vert_buffer = m_current_vert_buffers[index]->buffer(); + VkDeviceSize vk_vert_buffer_offset = offset; + + vkCmdBindVertexBuffers(m_cmd_buffer, index, 1, &vk_vert_buffer, &vk_vert_buffer_offset); + } + void VKCmdList::bind_index_buffer(const Ref& buffer, GfxIndexType index_type, int offset) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::bind_index_buffer"); + + assert(m_pipeline_bound_graphics); + assert(buffer); + + m_current_index_buffer = buffer.cast(); + vkCmdBindIndexBuffer(m_cmd_buffer, m_current_index_buffer->buffer(), offset, VKDefs::get_index_type(index_type)); + } + void VKCmdList::bind_desc_set(const Ref& set, int index) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::bind_desc_set"); + + assert(m_pipeline_bound_graphics || m_pipeline_bound_compute); + assert(set); + + VkPipelineBindPoint bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM; + + if (m_pipeline_bound_graphics) { + bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS; + } + if (m_pipeline_bound_compute) { + bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; + } + + m_desc_sets[index] = set.cast()->set(); + vkCmdBindDescriptorSets(m_cmd_buffer, bind_point, m_current_pso_layout->layout(), index, 1, &m_desc_sets[index], 0, nullptr); + } + void VKCmdList::bind_desc_sets(const array_view& sets, int offset) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::bind_desc_sets"); + + assert(m_pipeline_bound_graphics || m_pipeline_bound_compute); + assert(!sets.empty()); + + const int count = int(sets.size()); + + for (int i = 0; i < count; i++) { + assert(i + offset < GfxLimits::MAX_DESC_SETS); + m_desc_sets[i + offset] = dynamic_cast(sets[i])->set(); + } + + VkPipelineBindPoint bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM; + + if (m_pipeline_bound_graphics) { + bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS; + } + if (m_pipeline_bound_compute) { + bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; + } + + vkCmdBindDescriptorSets(m_cmd_buffer, bind_point, m_current_pso_layout->layout(), offset, count, &m_desc_sets[offset], 0, nullptr); + } + void VKCmdList::draw(int vertex_count, int base_vertex, int instance_count) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::draw"); + + assert(m_pipeline_bound_graphics); + + vkCmdDraw(m_cmd_buffer, vertex_count, instance_count, base_vertex, 0); + } + void VKCmdList::draw_indexed(int index_count, int base_vertex, int instance_count) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::draw_indexed"); + + assert(m_pipeline_bound_graphics); + + vkCmdDrawIndexed(m_cmd_buffer, index_count, instance_count, 0, base_vertex, 0); + } + void VKCmdList::dispatch(Vec3i group_count) { + WG_AUTO_PROFILE_VULKAN("VKCmdList::dispatch"); + + assert(m_pipeline_bound_compute); + + vkCmdDispatch(m_cmd_buffer, std::uint32_t(group_count.x()), std::uint32_t(group_count.y()), std::uint32_t(group_count.z())); + } + void VKCmdList::end_render_pass() { + WG_AUTO_PROFILE_VULKAN("VKCmdList::end_render_pass"); + + assert(m_in_render_pass); + + vkCmdEndRenderPass(m_cmd_buffer); + + reset_state(); + } + + void VKCmdList::begin_label(const Strid& label) { + assert(!m_in_render_pass); + + WG_VK_BEGIN_LABEL(m_cmd_buffer, label); + } + + void VKCmdList::end_label() { + assert(!m_in_render_pass); + + WG_VK_END_LABEL(m_cmd_buffer); + } + + void VKCmdList::reset_state() { + m_current_pass.reset(); + m_current_fbo.reset(); + m_current_window.reset(); + m_current_pso_graphics.reset(); + m_current_pso_compute.reset(); + m_current_pso_layout.reset(); + m_current_index_buffer.reset(); + m_current_vert_buffers.fill(nullptr); + m_current_vert_buffers_offsets.fill(0); + m_viewport = Rect2i(0, 0, 0, 0); + + m_in_render_pass = false; + m_pipeline_bound_graphics = false; + m_pipeline_bound_compute = false; + } + +}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/vulkan/vk_ctx.hpp b/engine/runtime/gfx/vulkan/vk_cmd_list.hpp similarity index 66% rename from engine/runtime/gfx/vulkan/vk_ctx.hpp rename to engine/runtime/gfx/vulkan/vk_cmd_list.hpp index 722504317..c8dec8ce3 100644 --- a/engine/runtime/gfx/vulkan/vk_ctx.hpp +++ b/engine/runtime/gfx/vulkan/vk_cmd_list.hpp @@ -28,12 +28,9 @@ #pragma once #include "core/buffered_vector.hpp" +#include "core/data.hpp" #include "core/flat_map.hpp" - -#include "gfx/gfx_ctx.hpp" -#include "gfx/threaded/gfx_ctx_threaded.hpp" -#include "gfx/threaded/gfx_ctx_wrapper.hpp" -#include "gfx/threaded/gfx_worker.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/vulkan/vk_buffers.hpp" #include "gfx/vulkan/vk_cmd_manager.hpp" #include "gfx/vulkan/vk_defs.hpp" @@ -41,6 +38,7 @@ #include "gfx/vulkan/vk_pipeline.hpp" #include "gfx/vulkan/vk_queues.hpp" #include "gfx/vulkan/vk_render_pass.hpp" +#include "gfx/vulkan/vk_resource.hpp" #include "gfx/vulkan/vk_vert_format.hpp" #include "gfx/vulkan/vk_window.hpp" @@ -52,15 +50,13 @@ namespace wmoge { /** - * @class VKCtx - * @brief Vulkan gfx contex implementation - */ - class VKCtx final : public GfxCtxThreaded { + * @class VKCmdList + * @brief Vulkan command list object implementation + */ + class VKCmdList : public VKResource { public: - explicit VKCtx(class VKDriver& driver); - ~VKCtx() override; - - void update_desc_set(const Ref& set, const GfxDescSetResources& resources) override; + VKCmdList(VkCommandBuffer cmd_buffer, GfxQueueType queue_type, class VKDriver& driver); + ~VKCmdList() override; void update_vert_buffer(const Ref& buffer, int offset, int range, const Ref& data) override; void update_index_buffer(const Ref& buffer, int offset, int range, const Ref& data) override; @@ -74,60 +70,45 @@ namespace wmoge { void* map_index_buffer(const Ref& buffer) override; void* map_uniform_buffer(const Ref& buffer) override; void* map_storage_buffer(const Ref& buffer) override; - void unmap_vert_buffer(const Ref& buffer) override; - void unmap_index_buffer(const Ref& buffer) override; - void unmap_uniform_buffer(const Ref& buffer) override; - void unmap_storage_buffer(const Ref& buffer) override; + + void unmap_vert_buffer(const Ref& buffer) override; + void unmap_index_buffer(const Ref& buffer) override; + void unmap_uniform_buffer(const Ref& buffer) override; + void unmap_storage_buffer(const Ref& buffer) override; void barrier_image(const Ref& texture, GfxTexBarrierType barrier_type) override; void barrier_buffer(const Ref& buffer) override; - void begin_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name) override; - void bind_target(const Ref& window) override; - void bind_color_target(const Ref& texture, int target, int mip, int slice) override; - void bind_depth_target(const Ref& texture, int mip, int slice) override; + void begin_render_pass(const GfxRenderPassBeginInfo& pass_desc) override; + void peek_render_pass(GfxRenderPassRef& rp) override; void viewport(const Rect2i& viewport) override; - void clear(int target, const Vec4f& color) override; - void clear(float depth, int stencil) override; - void extract_render_pass(GfxRenderPassRef& rp) override; void bind_pso(const Ref& pipeline) override; void bind_pso(const Ref& pipeline) override; - void bind_vert_buffer(const Ref& buffer, int index, int offset) override; - void bind_index_buffer(const Ref& buffer, GfxIndexType index_type, int offset) override; + void bind_vert_buffer(const Ref& buffer, int index, int offset = 0) override; + void bind_index_buffer(const Ref& buffer, GfxIndexType index_type, int offset = 0) override; void bind_desc_set(const Ref& set, int index) override; - void bind_desc_sets(const array_view& sets, int offset) override; + void bind_desc_sets(const array_view& sets, int offset = 0) override; void draw(int vertex_count, int base_vertex, int instance_count) override; void draw_indexed(int index_count, int base_vertex, int instance_count) override; void dispatch(Vec3i group_count) override; void end_render_pass() override; - void execute(const std::function& functor) override; - void shutdown() override; - - void begin_frame() override; - void end_frame() override; - void begin_label(const Strid& label) override; void end_label() override; - [[nodiscard]] const Mat4x4f& clip_matrix() const override; - [[nodiscard]] GfxCtxType ctx_type() const override; - [[nodiscard]] CallbackStream* cmd_stream() override; - [[nodiscard]] bool check_thread_valid(); - - public: - VkCommandBuffer cmd_begin() { return m_cmd_manager->begin_buffer(); } - VkCommandBuffer cmd_end() { return m_cmd_manager->end_buffer(); } - VkCommandBuffer cmd_current() { return m_cmd_manager->current_buffer(); } + GfxQueueType get_queue_type() const override { return m_queue_type; } + VkCommandBuffer get_handle() const { return m_cmd_buffer; } private: - void prepare_render_pass(); + void reset_state(); private: - std::unique_ptr m_cmd_manager; + VkCommandBuffer m_cmd_buffer = VK_NULL_HANDLE; + GfxQueueType m_queue_type = GfxQueueType::None; - std::unique_ptr m_render_pass_binder; Ref m_current_pass; + Ref m_current_fbo; + Ref m_current_window; Ref m_current_pso_graphics; Ref m_current_pso_compute; Ref m_current_pso_layout; @@ -135,22 +116,12 @@ namespace wmoge { std::array, GfxLimits::MAX_VERT_BUFFERS> m_current_vert_buffers{}; std::array m_current_vert_buffers_offsets{}; std::array m_desc_sets{}; - std::array m_clear_color; - float m_clear_depth = 1.0f; - int m_clear_stencil = 0; Rect2i m_viewport; - bool m_in_render_pass = false; - bool m_render_pass_started = false; - bool m_pipeline_bound = false; - bool m_comp_pipeline_bound = false; - bool m_target_bound = false; - Strid m_render_pass_name; - - GfxCtxType m_ctx_type = GfxCtxType::Immediate; - Mat4x4f m_clip_matrix; - - class VKDriver& m_driver; + bool m_is_started = false; + bool m_in_render_pass = false; + bool m_pipeline_bound_graphics = false; + bool m_pipeline_bound_compute = false; }; }// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/vulkan/vk_cmd_manager.cpp b/engine/runtime/gfx/vulkan/vk_cmd_manager.cpp index 16c99cf02..382e403a0 100644 --- a/engine/runtime/gfx/vulkan/vk_cmd_manager.cpp +++ b/engine/runtime/gfx/vulkan/vk_cmd_manager.cpp @@ -28,64 +28,60 @@ #include "vk_cmd_manager.hpp" #include "gfx/vulkan/vk_driver.hpp" -#include "profiler/profiler.hpp" +#include "gfx/vulkan/vk_queues.hpp" + +#include +#include namespace wmoge { - VKCmdManager::VKCmdManager(class VKDriver& driver) : m_driver(driver) { - } - VKCmdManager::~VKCmdManager() { - WG_AUTO_PROFILE_VULKAN("VKCmdManager::~VKCmdManager"); + VKCmdManager::VKCmdManager(VKDriver& driver) : m_driver(driver) { + // Init pools and submit queues using queue info from driver - auto release_allocation = [&](Allocation allocation) { - if (allocation.buffer) { - vkFreeCommandBuffers(m_driver.device(), allocation.pool, 1, &allocation.buffer); - } - if (allocation.pool) { - vkDestroyCommandPool(m_driver.device(), allocation.pool, nullptr); - } - }; + VKQueues* queues = m_driver.queues(); + GfxQueueType queue_types[] = {GfxQueueType::Graphics, GfxQueueType::Compute, GfxQueueType::Copy}; - for (auto& allocations : m_used_allocations) { - for (auto allocation : allocations) { - release_allocation(allocation); - } - } - for (auto& allocation : m_free_allocations) { - release_allocation(allocation); + for (auto queue_type : queue_types) { + CmdBufferPool& pool = m_pools.emplace_back(); + pool.queue_type = queue_type; + pool.queue_family_index = queues->get_family_index(queue_type); + + CmdBufferQueue& queue = m_queues.emplace_back(); + queue.queue_type = queue_type; + queue.queue = queues->get_queue(queue_type); } - release_allocation(m_allocation); } - void VKCmdManager::update() { - WG_AUTO_PROFILE_VULKAN("VKCmdManager::update"); - - m_index = (m_index + 1) % GfxLimits::FRAMES_IN_FLIGHT; + VKCmdManager::~VKCmdManager() { + clear(); + } - for (auto& allocation : m_used_allocations[m_index]) { - WG_VK_CHECK(vkResetCommandPool(m_driver.device(), allocation.pool, 0)); + void VKCmdManager::update(std::size_t frame_id) { + m_frame_id = frame_id; + m_index = m_frame_id % GfxLimits::FRAMES_IN_FLIGHT; - m_free_allocations.push_back(allocation); + for (CmdBufferPool& pool : m_pools) { + for (CmdBuffer& buffer : pool.used[m_index]) { + WG_VK_CHECK(vkResetCommandPool(m_driver.device(), buffer.pool, 0)); + pool.free.push_back(buffer); + } + pool.used[m_index].clear(); } - - m_used_allocations[m_index].clear(); } - VkCommandBuffer VKCmdManager::begin_buffer() { - WG_AUTO_PROFILE_VULKAN("VKCmdManager::begin_buffer"); + VkCommandBuffer VKCmdManager::allocate(GfxQueueType queue_type) { + CmdBufferPool& pool = m_pools[static_cast(queue_type)]; - assert(m_allocation.buffer == VK_NULL_HANDLE); - - if (m_free_allocations.empty()) { - Allocation allocation{}; + if (pool.free.empty()) { + CmdBuffer allocation{}; VkCommandPoolCreateInfo pool_info{}; pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; - pool_info.queueFamilyIndex = m_driver.queues()->gfx_queue_family(); + pool_info.queueFamilyIndex = pool.queue_family_index; WG_VK_CHECK(vkCreateCommandPool(m_driver.device(), &pool_info, nullptr, &allocation.pool)); - WG_VK_NAME(m_driver.device(), allocation.pool, VK_OBJECT_TYPE_COMMAND_POOL, "cmd_pool id=" + std::to_string(m_next_id)); + WG_VK_NAME(m_driver.device(), allocation.pool, VK_OBJECT_TYPE_COMMAND_POOL, "cmd_pool id=" + std::to_string(m_next_dbg_id)); VkCommandBufferAllocateInfo buffer_info{}; buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; @@ -94,45 +90,135 @@ namespace wmoge { buffer_info.commandPool = allocation.pool; WG_VK_CHECK(vkAllocateCommandBuffers(m_driver.device(), &buffer_info, &allocation.buffer)); - WG_VK_NAME(m_driver.device(), allocation.buffer, VK_OBJECT_TYPE_COMMAND_BUFFER, "cmd_buff id=" + std::to_string(m_next_id)); + WG_VK_NAME(m_driver.device(), allocation.buffer, VK_OBJECT_TYPE_COMMAND_BUFFER, "cmd_buff id=" + std::to_string(m_next_dbg_id)); - m_next_id += 1; + pool.free.push_back(allocation); - m_free_allocations.push_back(allocation); + ++m_next_dbg_id; } - m_allocation = m_free_allocations.back(); - m_free_allocations.pop_back(); + CmdBuffer allocation = pool.free.back(); + pool.free.pop_back(); + pool.used[m_index].push_back(allocation); VkCommandBufferBeginInfo begin_info{}; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; begin_info.pInheritanceInfo = nullptr; - WG_VK_CHECK(vkBeginCommandBuffer(m_allocation.buffer, &begin_info)); + WG_VK_CHECK(vkBeginCommandBuffer(allocation.buffer, &begin_info)); + + return allocation.buffer; + } - return m_allocation.buffer; + void VKCmdManager::submit(GfxQueueType queue_type, VkCommandBuffer buffer) { + submit(queue_type, buffer, {}, {}, VK_NULL_HANDLE); } - VkCommandBuffer VKCmdManager::end_buffer() { - WG_AUTO_PROFILE_VULKAN("VKCmdManager::end_buffer"); + void VKCmdManager::submit(GfxQueueType queue_type, VkCommandBuffer buffer, array_view wait, array_view signal, VkFence fence) { + assert(buffer); + + WG_VK_CHECK(vkEndCommandBuffer(buffer)); - assert(m_allocation.buffer != VK_NULL_HANDLE); - assert(m_allocation.pool != VK_NULL_HANDLE); + CmdBufferPool& pool = m_pools[static_cast(queue_type)]; + CmdBufferQueue& queue = m_queues[static_cast(queue_type)]; - WG_VK_CHECK(vkEndCommandBuffer(m_allocation.buffer)); - m_used_allocations[m_index].push_back(m_allocation); + assert(pool.used[m_index].end() != std::find_if(pool.used[m_index].begin(), pool.used[m_index].end(), [&](const CmdBuffer& other) { + return other.buffer == buffer; + })); - VkCommandBuffer ended_buffer = m_allocation.buffer; - m_allocation = Allocation{}; + const auto id = queue.submits.size(); + const bool need_chain = !queue.submits.empty(); - return ended_buffer; + CmdBufferSubmitInfo& submit = queue.submits.emplace_back(); + submit.buffers.push_back(buffer); + submit.fence = fence; + + for (auto semaphore : signal) { + submit.signal.push_back(semaphore); + } + for (auto semaphore : wait) { + submit.wait.push_back(semaphore); + } + + if (need_chain) { + CmdBufferSubmitInfo& prev = queue.submits[id - 1]; + VkSemaphore sync_semphore = m_driver.semaphore_pool()->allocate(); + + prev.signal.push_back(sync_semphore); + submit.wait.push_back(sync_semphore); + } } - VkCommandBuffer VKCmdManager::current_buffer() const { - assert(m_allocation.buffer != VK_NULL_HANDLE); + void VKCmdManager::clear() { + auto release_allocation = [&](CmdBuffer allocation) { + vkFreeCommandBuffers(m_driver.device(), allocation.pool, 1, &allocation.buffer); + vkDestroyCommandPool(m_driver.device(), allocation.pool, nullptr); + }; - return m_allocation.buffer; + for (CmdBufferPool& pool : m_pools) { + for (auto& used : pool.used) { + for (CmdBuffer& buffer : used) { + release_allocation(buffer); + } + used.clear(); + } + for (CmdBuffer& buffer : pool.free) { + release_allocation(buffer); + } + pool.free.clear(); + } + + for (CmdBufferQueue& queue : m_queues) { + queue.submits.clear(); + } + } + + void VKCmdManager::flush(array_view wait, array_view signal) { + buffered_vector wait_flags; + + for (CmdBufferQueue& queue : m_queues) { + std::size_t num_commands = queue.submits.size(); + + const bool is_graphics_queue = queue.queue_type == GfxQueueType::Graphics; + + for (std::size_t i = 0; i < num_commands; i++) { + CmdBufferSubmitInfo& submit = queue.submits[i]; + + if (is_graphics_queue) { + const bool is_first = i == 0; + const bool is_last = (i + 1) == num_commands; + + if (is_first) { + for (auto semaphore : wait) { + submit.wait.push_back(semaphore); + } + } + if (is_last) { + for (auto semaphore : signal) { + submit.signal.push_back(semaphore); + } + } + } + + wait_flags.clear(); + wait_flags.resize(submit.wait.size(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.waitSemaphoreCount = static_cast(submit.wait.size()); + submit_info.pWaitSemaphores = submit.wait.data(); + submit_info.pWaitDstStageMask = wait_flags.data(); + submit_info.commandBufferCount = static_cast(submit.buffers.size()); + submit_info.pCommandBuffers = submit.buffers.data(); + submit_info.signalSemaphoreCount = static_cast(submit.signal.size()); + submit_info.pSignalSemaphores = submit.signal.data(); + + WG_VK_CHECK(vkQueueSubmit(queue.queue, 1, &submit_info, submit.fence)); + } + + queue.submits.clear(); + } } }// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/vulkan/vk_cmd_manager.hpp b/engine/runtime/gfx/vulkan/vk_cmd_manager.hpp index 087c5bd66..90f1fbb55 100644 --- a/engine/runtime/gfx/vulkan/vk_cmd_manager.hpp +++ b/engine/runtime/gfx/vulkan/vk_cmd_manager.hpp @@ -27,41 +27,69 @@ #pragma once +#include "core/array_view.hpp" #include "core/buffered_vector.hpp" #include "gfx/vulkan/vk_defs.hpp" -#include +#include #include namespace wmoge { /** * @class VKCmdManager - * @brief Manages creation and recycling of vulkan cmd buffers + * @brief Manages allocation and submit of command buffers for execution on GPU */ class VKCmdManager { public: explicit VKCmdManager(class VKDriver& driver); ~VKCmdManager(); - void update(); + void update(std::size_t frame_id); - VkCommandBuffer begin_buffer(); - VkCommandBuffer end_buffer(); - VkCommandBuffer current_buffer() const; + VkCommandBuffer allocate(GfxQueueType queue_type); + void submit(GfxQueueType queue_type, VkCommandBuffer buffer); + void submit(GfxQueueType queue_type, VkCommandBuffer buffer, array_view wait, array_view signal, VkFence fence); + void clear(); + void flush(array_view wait, array_view signal); private: - struct Allocation { + // Single buffer allocation + struct CmdBuffer { VkCommandPool pool = VK_NULL_HANDLE; VkCommandBuffer buffer = VK_NULL_HANDLE; }; - std::array, GfxLimits::FRAMES_IN_FLIGHT> m_used_allocations{}; - buffered_vector m_free_allocations{}; + // Pool of command buffer allocations for a specific queue + struct CmdBufferPool { + std::vector used[GfxLimits::FRAMES_IN_FLIGHT]; + std::vector free; + GfxQueueType queue_type; + uint32_t queue_family_index; + }; + + // Submit info to submit a batch of command buffers to a single queue + struct CmdBufferSubmitInfo { + buffered_vector wait; + buffered_vector signal; + buffered_vector buffers; + VkFence fence = VK_NULL_HANDLE; + }; + + // Queue to submit commnad buffers to a single gpu queue + struct CmdBufferQueue { + std::vector submits; + GfxQueueType queue_type; + VkQueue queue = VK_NULL_HANDLE; + }; + + buffered_vector m_pools; + buffered_vector m_queues; + + std::size_t m_index = 0 % GfxLimits::FRAMES_IN_FLIGHT; + std::size_t m_frame_id = 0; - Allocation m_allocation{}; - std::size_t m_index = 0 % GfxLimits::FRAMES_IN_FLIGHT; - int m_next_id = 0; + std::size_t m_next_dbg_id = 0; class VKDriver& m_driver; }; diff --git a/engine/runtime/gfx/vulkan/vk_ctx.cpp b/engine/runtime/gfx/vulkan/vk_ctx.cpp deleted file mode 100644 index 3723ae38f..000000000 --- a/engine/runtime/gfx/vulkan/vk_ctx.cpp +++ /dev/null @@ -1,578 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#include "vk_ctx.hpp" - -#include "gfx/vulkan/vk_defs.hpp" -#include "gfx/vulkan/vk_driver.hpp" -#include "profiler/profiler.hpp" - -namespace wmoge { - - VKCtx::VKCtx(class VKDriver& driver) : m_driver(driver) { - WG_AUTO_PROFILE_VULKAN("VKCtx::VKCtx"); - - m_cmd_manager = std::make_unique(driver); - m_render_pass_binder = std::make_unique(driver); - - m_clip_matrix = driver.clip_matrix(); - - cmd_begin(); - } - - VKCtx::~VKCtx() { - WG_AUTO_PROFILE_VULKAN("VKCtx::~VKCtx"); - - shutdown(); - - WG_LOG_INFO("shutdown vulkan gfx context"); - } - - void VKCtx::update_desc_set(const Ref& set, const GfxDescSetResources& resources) { - WG_AUTO_PROFILE_VULKAN("VKCtx::update_desc_set"); - - assert(check_thread_valid()); - assert(set); - assert(!m_in_render_pass); - - auto vk_desc_set = dynamic_cast(set.get()); - - vk_desc_set->update(resources); - vk_desc_set->merge(resources); - } - - void VKCtx::update_vert_buffer(const Ref& buffer, int offset, int range, const Ref& data) { - WG_AUTO_PROFILE_VULKAN("VKCtx::update_vert_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - dynamic_cast(buffer.get())->update(cmd_current(), offset, range, data); - } - void VKCtx::update_index_buffer(const Ref& buffer, int offset, int range, const Ref& data) { - WG_AUTO_PROFILE_VULKAN("VKCtx::update_index_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - dynamic_cast(buffer.get())->update(cmd_current(), offset, range, data); - } - void VKCtx::update_uniform_buffer(const Ref& buffer, int offset, int range, const Ref& data) { - WG_AUTO_PROFILE_VULKAN("VKCtx::update_uniform_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - dynamic_cast(buffer.get())->update(cmd_current(), offset, range, data); - } - void VKCtx::update_storage_buffer(const Ref& buffer, int offset, int range, const Ref& data) { - WG_AUTO_PROFILE_VULKAN("VKCtx::update_storage_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - dynamic_cast(buffer.get())->update(cmd_current(), offset, range, data); - } - void VKCtx::update_texture_2d(const Ref& texture, int mip, Rect2i region, const Ref& data) { - WG_AUTO_PROFILE_VULKAN("VKCtx::update_texture_2d"); - - assert(check_thread_valid()); - assert(texture); - assert(!m_in_render_pass); - - dynamic_cast(texture.get())->update_2d(cmd_current(), mip, region, data); - } - void VKCtx::update_texture_2d_array(const Ref& texture, int mip, int slice, Rect2i region, const Ref& data) { - WG_AUTO_PROFILE_VULKAN("VKCtx::update_texture_2d_array"); - - assert(check_thread_valid()); - assert(texture); - assert(!m_in_render_pass); - - dynamic_cast(texture.get())->update_2d_array(cmd_current(), mip, slice, region, data); - } - void VKCtx::update_texture_cube(const Ref& texture, int mip, int face, Rect2i region, const Ref& data) { - WG_AUTO_PROFILE_VULKAN("VKCtx::update_texture_cube"); - - assert(check_thread_valid()); - assert(texture); - assert(!m_in_render_pass); - - dynamic_cast(texture.get())->update_cube(cmd_current(), mip, face, region, data); - } - - void* VKCtx::map_vert_buffer(const Ref& buffer) { - WG_AUTO_PROFILE_VULKAN("VKCtx::map_vert_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - return (dynamic_cast(buffer.get()))->map(); - } - void* VKCtx::map_index_buffer(const Ref& buffer) { - WG_AUTO_PROFILE_VULKAN("VKCtx::map_index_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - return (dynamic_cast(buffer.get()))->map(); - } - void* VKCtx::map_uniform_buffer(const Ref& buffer) { - WG_AUTO_PROFILE_VULKAN("VKCtx::map_uniform_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - return (dynamic_cast(buffer.get()))->map(); - } - void* VKCtx::map_storage_buffer(const Ref& buffer) { - WG_AUTO_PROFILE_VULKAN("VKCtx::map_storage_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - return (dynamic_cast(buffer.get()))->map(); - } - void VKCtx::unmap_vert_buffer(const Ref& buffer) { - WG_AUTO_PROFILE_VULKAN("VKCtx::unmap_vert_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - dynamic_cast(buffer.get())->unmap(cmd_current()); - } - void VKCtx::unmap_index_buffer(const Ref& buffer) { - WG_AUTO_PROFILE_VULKAN("VKCtx::unmap_index_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - dynamic_cast(buffer.get())->unmap(cmd_current()); - } - void VKCtx::unmap_uniform_buffer(const Ref& buffer) { - WG_AUTO_PROFILE_VULKAN("VKCtx::unmap_uniform_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - dynamic_cast(buffer.get())->unmap(cmd_current()); - } - void VKCtx::unmap_storage_buffer(const Ref& buffer) { - WG_AUTO_PROFILE_VULKAN("VKCtx::unmap_storage_buffer"); - - assert(check_thread_valid()); - assert(buffer); - assert(!m_in_render_pass); - - dynamic_cast(buffer.get())->unmap(cmd_current()); - } - - void VKCtx::barrier_image(const Ref& texture, GfxTexBarrierType barrier_type) { - WG_AUTO_PROFILE_VULKAN("VKCtx::barrier_image"); - - dynamic_cast(texture.get())->transition_layout(cmd_current(), barrier_type); - } - void VKCtx::barrier_buffer(const Ref& buffer) { - WG_AUTO_PROFILE_VULKAN("VKCtx::barrier_buffer"); - - dynamic_cast(buffer.get())->barrier(cmd_current()); - } - - void VKCtx::begin_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name) { - WG_AUTO_PROFILE_VULKAN("VKCtx::begin_render_pass"); - - assert(check_thread_valid()); - assert(!m_in_render_pass); - assert(pass_desc == GfxRenderPassDesc{});// not supported pass desc yet - - m_render_pass_binder->start(name); - m_in_render_pass = true; - m_comp_pipeline_bound = false; - m_render_pass_name = name; - } - void VKCtx::bind_target(const Ref& window) { - WG_AUTO_PROFILE_VULKAN("VKCtx::bind_target"); - - assert(check_thread_valid()); - assert(m_in_render_pass); - assert(window); - - m_render_pass_binder->bind_target(m_driver.window_manager()->get_or_create(window)); - m_target_bound = true; - } - void VKCtx::bind_color_target(const Ref& texture, int target, int mip, int slice) { - WG_AUTO_PROFILE_VULKAN("VKCtx::bind_color_target"); - - assert(check_thread_valid()); - assert(m_in_render_pass); - assert(texture); - - m_render_pass_binder->bind_color_target(texture.cast(), target, mip, slice); - m_target_bound = true; - } - void VKCtx::bind_depth_target(const Ref& texture, int mip, int slice) { - WG_AUTO_PROFILE_VULKAN("VKCtx::bind_depth_target"); - - assert(check_thread_valid()); - assert(m_in_render_pass); - assert(texture); - - m_render_pass_binder->bind_depth_target(texture.cast(), mip, slice); - m_target_bound = true; - } - void VKCtx::viewport(const Rect2i& viewport) { - WG_AUTO_PROFILE_VULKAN("VKCtx::viewport"); - - assert(check_thread_valid()); - assert(m_in_render_pass); - assert(m_target_bound); - - m_viewport = viewport; - } - void VKCtx::clear(int target, const Vec4f& color) { - WG_AUTO_PROFILE_VULKAN("VKCtx::clear"); - - assert(check_thread_valid()); - assert(m_in_render_pass); - assert(m_target_bound); - - m_clear_color[target] = color; - m_render_pass_binder->clear_color(target); - } - void VKCtx::clear(float depth, int stencil) { - WG_AUTO_PROFILE_VULKAN("VKCtx::clear"); - - assert(check_thread_valid()); - assert(m_in_render_pass); - assert(m_target_bound); - - m_clear_depth = depth; - m_clear_stencil = stencil; - m_render_pass_binder->clear_depth(); - m_render_pass_binder->clear_stencil(); - } - void VKCtx::extract_render_pass(GfxRenderPassRef& rp) { - WG_AUTO_PROFILE_VULKAN("VKCtx::extract_render_pass"); - - assert(check_thread_valid()); - assert(m_in_render_pass); - assert(m_target_bound); - - rp = m_render_pass_binder->get_or_create_render_pass().as(); - } - void VKCtx::bind_pso(const Ref& pipeline) { - WG_AUTO_PROFILE_VULKAN("VKCtx::bind_pso"); - - assert(check_thread_valid()); - assert(m_in_render_pass); - assert(m_target_bound); - assert(pipeline); - - prepare_render_pass(); - - Ref new_pipeline = pipeline.cast(); - - vkCmdBindPipeline(cmd_current(), VK_PIPELINE_BIND_POINT_GRAPHICS, new_pipeline->pipeline()); - m_current_pso_graphics = std::move(new_pipeline); - m_current_pso_layout = m_current_pso_graphics->layout(); - m_pipeline_bound = true; - } - void VKCtx::bind_pso(const Ref& pipeline) { - WG_AUTO_PROFILE_VULKAN("VKCtx::bind_pso"); - - assert(check_thread_valid()); - assert(!m_in_render_pass); - assert(pipeline); - - Ref new_pipeline = pipeline.cast(); - - vkCmdBindPipeline(cmd_current(), VK_PIPELINE_BIND_POINT_COMPUTE, new_pipeline->pipeline()); - m_current_pso_compute = std::move(new_pipeline); - m_current_pso_layout = m_current_pso_compute->layout(); - m_comp_pipeline_bound = true; - } - void VKCtx::bind_vert_buffer(const Ref& buffer, int index, int offset) { - WG_AUTO_PROFILE_VULKAN("VKCtx::bind_vert_buffer"); - - assert(check_thread_valid()); - assert(m_pipeline_bound); - assert(m_target_bound); - assert(buffer); - - m_current_vert_buffers[index] = buffer.cast(); - m_current_vert_buffers_offsets[index] = offset; - - VkBuffer vk_vert_buffer = m_current_vert_buffers[index]->buffer(); - VkDeviceSize vk_vert_buffer_offset = offset; - - vkCmdBindVertexBuffers(cmd_current(), index, 1, &vk_vert_buffer, &vk_vert_buffer_offset); - } - void VKCtx::bind_index_buffer(const Ref& buffer, GfxIndexType index_type, int offset) { - WG_AUTO_PROFILE_VULKAN("VKCtx::bind_index_buffer"); - - assert(check_thread_valid()); - assert(m_pipeline_bound); - assert(m_target_bound); - assert(buffer); - - m_current_index_buffer = buffer.cast(); - vkCmdBindIndexBuffer(cmd_current(), m_current_index_buffer->buffer(), offset, VKDefs::get_index_type(index_type)); - } - void VKCtx::bind_desc_set(const Ref& set, int index) { - WG_AUTO_PROFILE_VULKAN("VKCtx::bind_desc_set"); - - assert(check_thread_valid()); - assert(m_pipeline_bound || m_comp_pipeline_bound); - assert(set); - - VkPipelineBindPoint bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM; - - if (m_pipeline_bound) { - bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS; - } - if (m_comp_pipeline_bound) { - bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; - } - - m_desc_sets[index] = set.cast()->set(); - vkCmdBindDescriptorSets(cmd_current(), bind_point, m_current_pso_layout->layout(), index, 1, &m_desc_sets[index], 0, nullptr); - } - void VKCtx::bind_desc_sets(const array_view& sets, int offset) { - WG_AUTO_PROFILE_VULKAN("VKCtx::bind_desc_sets"); - - assert(check_thread_valid()); - assert(m_pipeline_bound || m_comp_pipeline_bound); - assert(!sets.empty()); - - const int count = int(sets.size()); - - for (int i = 0; i < count; i++) { - assert(i + offset < GfxLimits::MAX_DESC_SETS); - m_desc_sets[i + offset] = dynamic_cast(sets[i])->set(); - } - - VkPipelineBindPoint bind_point = VK_PIPELINE_BIND_POINT_MAX_ENUM; - - if (m_pipeline_bound) { - bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS; - } - if (m_comp_pipeline_bound) { - bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; - } - - vkCmdBindDescriptorSets(cmd_current(), bind_point, m_current_pso_layout->layout(), offset, count, &m_desc_sets[offset], 0, nullptr); - } - void VKCtx::draw(int vertex_count, int base_vertex, int instance_count) { - WG_AUTO_PROFILE_VULKAN("VKCtx::draw"); - - assert(check_thread_valid()); - assert(m_pipeline_bound); - assert(m_target_bound); - - vkCmdDraw(cmd_current(), vertex_count, instance_count, base_vertex, 0); - } - void VKCtx::draw_indexed(int index_count, int base_vertex, int instance_count) { - WG_AUTO_PROFILE_VULKAN("VKCtx::draw_indexed"); - - assert(check_thread_valid()); - assert(m_pipeline_bound); - assert(m_target_bound); - - vkCmdDrawIndexed(cmd_current(), index_count, instance_count, 0, base_vertex, 0); - } - void VKCtx::dispatch(Vec3i group_count) { - WG_AUTO_PROFILE_VULKAN("VKCtx::dispatch"); - - assert(check_thread_valid()); - assert(m_comp_pipeline_bound); - - vkCmdDispatch(cmd_current(), std::uint32_t(group_count.x()), std::uint32_t(group_count.y()), std::uint32_t(group_count.z())); - } - void VKCtx::end_render_pass() { - WG_AUTO_PROFILE_VULKAN("VKCtx::end_render_pass"); - - assert(check_thread_valid()); - assert(m_in_render_pass); - - if (!m_render_pass_started) { - prepare_render_pass(); - } - - assert(m_render_pass_started); - - vkCmdEndRenderPass(cmd_current()); - WG_VK_END_LABEL(cmd_current()); - - m_render_pass_binder->finish(cmd_current()); - m_current_pass.reset(); - m_current_pso_graphics.reset(); - m_current_pso_layout.reset(); - m_current_index_buffer.reset(); - m_current_vert_buffers.fill(nullptr); - m_current_vert_buffers_offsets.fill(0); - m_clear_color.fill(Vec4f()); - m_clear_depth = 1.0f; - m_clear_stencil = 0; - m_viewport = Rect2i(0, 0, 0, 0); - - m_in_render_pass = false; - m_render_pass_started = false; - m_pipeline_bound = false; - m_target_bound = false; - } - - void VKCtx::execute(const std::function& functor) { - WG_AUTO_PROFILE_VULKAN("VKCtx::execute"); - - functor(); - } - void VKCtx::shutdown() { - WG_AUTO_PROFILE_VULKAN("VKCtx::shutdown"); - - m_render_pass_binder.reset(); - m_cmd_manager.reset(); - } - - void VKCtx::begin_frame() { - WG_AUTO_PROFILE_VULKAN("VKCtx::begin_frame"); - } - void VKCtx::end_frame() { - WG_AUTO_PROFILE_VULKAN("VKCtx::end_frame"); - - assert(!m_render_pass_started); - - m_cmd_manager->update(); - - m_current_pso_graphics.reset(); - m_current_pso_compute.reset(); - m_current_pso_layout.reset(); - - m_target_bound = false; - m_pipeline_bound = false; - m_comp_pipeline_bound = false; - m_render_pass_started = false; - } - - void VKCtx::begin_label(const Strid& label) { - assert(!m_in_render_pass); - - WG_VK_BEGIN_LABEL(cmd_current(), label); - } - void VKCtx::end_label() { - assert(!m_in_render_pass); - - WG_VK_END_LABEL(cmd_current()); - } - - const Mat4x4f& VKCtx::clip_matrix() const { - return m_clip_matrix; - } - GfxCtxType VKCtx::ctx_type() const { - return m_ctx_type; - } - CallbackStream* VKCtx::cmd_stream() { - return m_driver.cmd_stream(); - } - bool VKCtx::check_thread_valid() { - return m_ctx_type != GfxCtxType::Immediate || m_driver.on_gfx_thread(); - } - - void VKCtx::prepare_render_pass() { - WG_AUTO_PROFILE_VULKAN("VKCtx::prepare_render_pass"); - - if (!m_render_pass_started) { - // Potentially recreate make pass and framebuffer - m_render_pass_binder->validate(cmd_current()); - m_current_pass = m_render_pass_binder->render_pass(); - - std::array clear_values{}; - int clear_value_count = 0; - - for (int i = 0; i < m_current_pass->color_targets_count(); i++) { - VkClearColorValue value; - value.float32[0] = m_clear_color[i].x(); - value.float32[1] = m_clear_color[i].y(); - value.float32[2] = m_clear_color[i].z(); - value.float32[3] = m_clear_color[i].w(); - clear_values[clear_value_count++].color = value; - } - if (m_current_pass->has_depth_stencil()) { - VkClearDepthStencilValue value; - value.depth = m_clear_depth; - value.stencil = m_clear_stencil; - clear_values[clear_value_count++].depthStencil = value; - } - - VkRect2D render_area{}; - render_area.offset.x = 0; - render_area.offset.y = 0; - render_area.extent.width = m_render_pass_binder->width(); - render_area.extent.height = m_render_pass_binder->height(); - - VkRenderPassBeginInfo render_pass_info{}; - render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - render_pass_info.renderPass = m_render_pass_binder->render_pass()->render_pass(); - render_pass_info.framebuffer = m_render_pass_binder->framebuffer()->framebuffer(); - render_pass_info.renderArea = render_area; - render_pass_info.clearValueCount = clear_value_count; - render_pass_info.pClearValues = clear_values.data(); - - WG_VK_BEGIN_LABEL(cmd_current(), m_render_pass_name); - vkCmdBeginRenderPass(cmd_current(), &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport; - viewport.x = static_cast(m_viewport.x()); - viewport.y = static_cast(m_viewport.y()); - viewport.width = static_cast(m_viewport.z()); - viewport.height = static_cast(m_viewport.w()); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - vkCmdSetViewport(cmd_current(), 0, 1, &viewport); - - VkRect2D scissor; - scissor.offset.x = m_viewport.x(); - scissor.offset.y = m_viewport.y(); - scissor.extent.width = m_viewport.z(); - scissor.extent.height = m_viewport.w(); - vkCmdSetScissor(cmd_current(), 0, 1, &scissor); - - m_render_pass_started = true; - } - } - -}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/vulkan/vk_driver.cpp b/engine/runtime/gfx/vulkan/vk_driver.cpp index 400649ec6..057780aeb 100644 --- a/engine/runtime/gfx/vulkan/vk_driver.cpp +++ b/engine/runtime/gfx/vulkan/vk_driver.cpp @@ -31,6 +31,7 @@ #include "core/task.hpp" #include "core/task_parallel_for.hpp" #include "gfx/vulkan/vk_buffers.hpp" +#include "gfx/vulkan/vk_cmd_list.hpp" #include "gfx/vulkan/vk_desc_set.hpp" #include "gfx/vulkan/vk_pipeline.hpp" #include "gfx/vulkan/vk_sampler.hpp" @@ -123,6 +124,12 @@ namespace wmoge { // init mem manager for allocations m_mem_manager = std::make_unique(*this); + // init semaphores pool for cmd buffers sync + m_semaphore_pool = std::make_unique(*this); + + // init cmd manager + m_cmd_manager = std::make_unique(*this); + // init manager for desc sets allocation VKDescPoolConfig pool_config{}; config->get_int(SID("gfx.vulkan.desc_pool_max_images"), pool_config.max_images); @@ -137,24 +144,6 @@ namespace wmoge { // sync primitives init_sync_fences(); - // init context required for rendering and commands submission - m_ctx_immediate = std::make_unique(*this); - - // cmd stream of driver thread - m_driver_cmd_stream = std::make_unique(); - - // and kick off worker in a separate thread - m_driver_worker = std::make_unique(m_driver_cmd_stream.get()); - - // thread, owning gfx processing - m_thread_id = m_driver_worker->get_worker_id(); - - // finally init wrapper for driver - m_driver_wrapper = std::make_unique(this); - - // finally init wrapper for ctx immediate - m_ctx_immediate_wrapper = std::make_unique(m_ctx_immediate.get()); - WG_LOG_INFO("init vulkan gfx driver"); } VKDriver::~VKDriver() { @@ -165,17 +154,65 @@ namespace wmoge { WG_LOG_INFO("shutdown vulkan gfx driver"); } + void VKDriver::shutdown() { + WG_AUTO_PROFILE_VULKAN("VKDriver::shutdown"); + + auto flush_release = [&]() { + for (int i = 0; i < GfxLimits::FRAMES_IN_FLIGHT; i++) { + release_resources(i); + } + }; + + if (m_instance) { + WG_VK_CHECK(vkDeviceWaitIdle(m_device)); + + m_cmd_manager.reset(); + flush_release(); + + m_render_passes.clear(); + flush_release(); + + m_desc_manager.reset(); + flush_release(); + + m_samplers.clear(); + flush_release(); + + m_window_manager.reset(); + flush_release(); + + flush_release(); + release_sync_fences(); + release_pipeline_cache(); + + m_semaphore_pool.reset(); + m_mem_manager.reset(); + m_queues.reset(); + + if (m_device) { + vkDestroyDevice(m_device, nullptr); + } + + if (m_debug_messenger) { + VKDebug::vkDestroyDebugUtilsMessengerEXT(m_instance, m_debug_messenger, nullptr); + } + + vkDestroyInstance(m_instance, nullptr); + + m_device = VK_NULL_HANDLE; + m_phys_device = VK_NULL_HANDLE; + m_instance = VK_NULL_HANDLE; + } + } + Ref VKDriver::make_vert_format(const GfxVertElements& elements, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_vert_format"); - assert(on_gfx_thread()); return make_ref(elements, name); } Ref VKDriver::make_vert_buffer(int size, GfxMemUsage usage, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_vert_buffer"); - assert(on_gfx_thread()); - auto buffer = make_ref(*this); buffer->create(size, usage, name); return buffer; @@ -183,8 +220,6 @@ namespace wmoge { Ref VKDriver::make_index_buffer(int size, GfxMemUsage usage, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_index_buffer"); - assert(on_gfx_thread()); - auto buffer = make_ref(*this); buffer->create(size, usage, name); return buffer; @@ -192,8 +227,6 @@ namespace wmoge { Ref VKDriver::make_uniform_buffer(int size, GfxMemUsage usage, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_uniform_buffer"); - assert(on_gfx_thread()); - auto buffer = make_ref(*this); buffer->create(size, usage, name); return buffer; @@ -201,8 +234,6 @@ namespace wmoge { Ref VKDriver::make_storage_buffer(int size, GfxMemUsage usage, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_storage_buffer"); - assert(on_gfx_thread()); - auto buffer = make_ref(*this); buffer->create(size, usage, name); return buffer; @@ -210,8 +241,6 @@ namespace wmoge { Ref VKDriver::make_shader(GfxShaderDesc desc, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_shader"); - assert(on_gfx_thread()); - auto shader = make_ref(name, *this); shader->create(std::move(desc)); return shader; @@ -219,8 +248,6 @@ namespace wmoge { Ref VKDriver::make_program(GfxShaderProgramDesc desc, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_program"); - assert(on_gfx_thread()); - auto program = make_ref(name, *this); program->create(std::move(desc)); return program; @@ -230,42 +257,34 @@ namespace wmoge { WG_AUTO_PROFILE_VULKAN("VKDriver::make_texture"); auto texture = make_ref(*this); - texture->create(m_ctx_immediate->cmd_current(), desc, name); + texture->create(desc, name); return texture; } Ref VKDriver::make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_texture_2d"); - assert(on_gfx_thread()); - auto texture = make_ref(*this); - texture->create_2d(m_ctx_immediate->cmd_current(), width, height, mips, format, usages, mem_usage, swizz, name); + texture->create_2d(width, height, mips, format, usages, mem_usage, swizz, name); return texture; } Ref VKDriver::make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_texture_2d_array"); - assert(on_gfx_thread()); - auto texture = make_ref(*this); - texture->create_2d_array(m_ctx_immediate->cmd_current(), width, height, mips, slices, format, usages, mem_usage, name); + texture->create_2d_array(width, height, mips, slices, format, usages, mem_usage, name); return texture; } Ref VKDriver::make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_texture_cube"); - assert(on_gfx_thread()); - auto texture = make_ref(*this); - texture->create_cube(m_ctx_immediate->cmd_current(), width, height, mips, format, usages, mem_usage, name); + texture->create_cube(width, height, mips, format, usages, mem_usage, name); return texture; } Ref VKDriver::make_sampler(const GfxSamplerDesc& desc, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_sampler"); - assert(on_gfx_thread()); - auto& sampler = m_samplers[desc]; if (!sampler) { sampler = make_ref(desc, name, *this); @@ -279,23 +298,17 @@ namespace wmoge { Ref VKDriver::make_pso_layout(const GfxDescSetLayouts& layouts, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_pso_layout"); - assert(on_gfx_thread()); - return make_ref(layouts, name, *this); } Ref VKDriver::make_pso_graphics(const GfxPsoStateGraphics& state, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_pso_graphics"); - assert(on_gfx_thread()); - Ref pipeline = make_ref(name, *this); return pipeline->compile(state) ? pipeline : Ref(); } Ref VKDriver::make_pso_compute(const GfxPsoStateCompute& state, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_pso_compute"); - assert(on_gfx_thread()); - Ref pipeline = make_ref(name, *this); return pipeline->compile(state) ? pipeline : Ref(); } @@ -310,31 +323,15 @@ namespace wmoge { return render_pass; } - Ref VKDriver::make_frame_buffer(const VKFrameBufferDesc& desc, const Strid& name) { - WG_AUTO_PROFILE_VULKAN("VKDriver::make_frame_buffer"); - - auto& frame_buffer = m_frame_buffers[desc]; - if (!frame_buffer) { - frame_buffer = make_ref(desc, name, *this); - WG_LOG_INFO("cache new frame buffer " << name); - } - - return frame_buffer; - } - Ref VKDriver::make_dyn_vert_buffer(int chunk_size, const Strid& name) { - WG_AUTO_PROFILE_VULKAN("VKDriver::make_dyn_vert_buffer"); - - return make_ref(chunk_size, 64, name); - } - Ref VKDriver::make_dyn_index_buffer(int chunk_size, const Strid& name) { - WG_AUTO_PROFILE_VULKAN("VKDriver::make_dyn_index_buffer"); + Ref VKDriver::make_render_pass(const Ref& window, const Strid& name) { + WG_AUTO_PROFILE_VULKAN("VKDriver::make_render_pass"); - return make_ref(chunk_size, 64, name); + return Ref(); } - Ref VKDriver::make_dyn_uniform_buffer(int chunk_size, const Strid& name) { - WG_AUTO_PROFILE_VULKAN("VKDriver::make_dyn_uniform_buffer"); + Ref VKDriver::make_frame_buffer(const GfxFrameBufferDesc& desc, const Strid& name) { + WG_AUTO_PROFILE_VULKAN("VKDriver::make_frame_buffer"); - return make_ref(chunk_size, m_device_caps.uniform_block_offset_alignment, name); + return make_ref(desc, name, *this); } Ref VKDriver::make_desc_layout(const GfxDescSetLayoutDesc& desc, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_desc_layout"); @@ -395,155 +392,87 @@ namespace wmoge { return task.schedule(int(request->states.size()), 1).as_async(); } - void VKDriver::shutdown() { - WG_AUTO_PROFILE_VULKAN("VKDriver::shutdown"); - - auto flush_release = [&]() { - auto to_flush = m_index; - m_index = (m_index + 1) % GfxLimits::FRAMES_IN_FLIGHT; - release_resources(to_flush); - }; - - if (m_instance) { - m_driver_worker->terminate(); - - WG_VK_CHECK(vkDeviceWaitIdle(m_device)); - - m_ctx_immediate.reset(); - flush_release(); - - m_ctx_async.reset(); - flush_release(); - - m_frame_buffers.clear(); - flush_release(); - - m_render_passes.clear(); - flush_release(); + void VKDriver::begin_frame(std::size_t frame_id, const array_view>& windows) { + WG_AUTO_PROFILE_VULKAN("VKDriver::begin_frame"); - m_desc_manager.reset(); - flush_release(); + m_frame_id = frame_id; + m_index = m_frame_id % GfxLimits::FRAMES_IN_FLIGHT; - m_samplers.clear(); - flush_release(); + release_resources(m_index); - m_window_manager.reset(); - flush_release(); + m_cmd_manager->update(m_frame_id); + m_mem_manager->update(m_frame_id); + m_semaphore_pool->update(m_frame_id); - flush_release(); - release_sync_fences(); - release_pipeline_cache(); + VkCommandBuffer cmd_buffer = m_cmd_manager->allocate(GfxQueueType::Graphics); - m_mem_manager.reset(); - m_queues.reset(); - m_driver_worker.reset(); - m_driver_wrapper.reset(); - - if (m_device) { - vkDestroyDevice(m_device, nullptr); - } + for (auto& window : windows) { + auto vk_window = m_window_manager->get_or_create(window); + vk_window->acquire_next(); + vk_window->color()[vk_window->current()]->transition_layout(cmd_buffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + m_to_present.push_back(vk_window); + } - if (m_debug_messenger) { - VKDebug::vkDestroyDebugUtilsMessengerEXT(m_instance, m_debug_messenger, nullptr); - } + m_cmd_manager->submit(GfxQueueType::Graphics, cmd_buffer); + } - vkDestroyInstance(m_instance, nullptr); + GfxCmdListRef VKDriver::acquire_cmd_list(GfxQueueType queue_type) { + WG_AUTO_PROFILE_VULKAN("VKDriver::acquire_cmd_list"); - m_device = VK_NULL_HANDLE; - m_phys_device = VK_NULL_HANDLE; - m_instance = VK_NULL_HANDLE; - } + return make_ref(m_cmd_manager->allocate(queue_type), queue_type, *this); } - void VKDriver::begin_frame() { - WG_AUTO_PROFILE_VULKAN("VKDriver::begin_frame"); - - assert(m_queue_wait.empty()); - assert(m_queue_signal.empty()); + void VKDriver::submit_cmd_list(const GfxCmdListRef& cmd_list) { + WG_AUTO_PROFILE_VULKAN("VKDriver::submit_cmd_list"); - m_ctx_immediate->begin_frame(); + assert(cmd_list); - if (m_ctx_async) { - m_ctx_async->begin_frame(); - } + VKCmdList* vk_cmd_list = dynamic_cast(cmd_list.get()); + m_cmd_manager->submit(vk_cmd_list->get_queue_type(), vk_cmd_list->get_handle()); } - void VKDriver::end_frame() { + + void VKDriver::end_frame(bool swap_buffers) { WG_AUTO_PROFILE_VULKAN("VKDriver::end_frame"); - VkCommandBuffer cmd_buffer = m_ctx_immediate->cmd_current(); + VkCommandBuffer cmd_buffer = m_cmd_manager->allocate(GfxQueueType::Graphics); + + buffered_vector queue_wait; + buffered_vector queue_signal; for (auto& window : m_to_present) { window->color()[window->current()]->transition_layout(cmd_buffer, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + queue_wait.push_back(window->acquire_semaphore()); + queue_signal.push_back(window->present_semaphore()); } - m_to_present.clear(); - m_ctx_immediate->cmd_end(); - m_ctx_immediate->cmd_begin(); - - std::vector wait_stages(m_queue_wait.size(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); - - VkSubmitInfo submit_info{}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.waitSemaphoreCount = int(m_queue_wait.size()); - submit_info.pWaitSemaphores = m_queue_wait.data(); - submit_info.pWaitDstStageMask = wait_stages.data(); - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &cmd_buffer; - submit_info.signalSemaphoreCount = int(m_queue_signal.size()); - submit_info.pSignalSemaphores = m_queue_signal.data(); - WG_VK_CHECK(vkWaitForFences(m_device, 1, &m_sync_fence, VK_TRUE, std::numeric_limits::max())); WG_VK_CHECK(vkResetFences(m_device, 1, &m_sync_fence)); - WG_VK_CHECK(vkQueueSubmit(m_queues->gfx_queue(), 1, &submit_info, m_sync_fence)); - m_queue_wait.clear(); - m_queue_signal.clear(); + m_cmd_manager->submit(GfxQueueType::Graphics, cmd_buffer, {}, {}, m_sync_fence); + m_cmd_manager->flush(queue_wait, queue_signal); - m_frame_number.fetch_add(1); - m_index = m_frame_number.load() % GfxLimits::FRAMES_IN_FLIGHT; + if (swap_buffers) { + buffered_vector swapchains; + buffered_vector image_indices; - release_resources(m_index); - - m_mem_manager->update(); + for (auto window : m_to_present) { + swapchains.push_back(window->swapchain()); + image_indices.push_back(window->current()); + } - m_ctx_immediate->end_frame(); + VkPresentInfoKHR present_info{}; + present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + present_info.waitSemaphoreCount = static_cast(queue_signal.size()); + present_info.pWaitSemaphores = queue_signal.data(); + present_info.swapchainCount = static_cast(m_to_present.size()); + present_info.pSwapchains = swapchains.data(); + present_info.pImageIndices = image_indices.data(); + present_info.pResults = nullptr; - if (m_ctx_async) { - m_ctx_async->end_frame(); + vkQueuePresentKHR(m_queues->prs_queue(), &present_info); } - } - void VKDriver::prepare_window(const Ref& window) { - WG_AUTO_PROFILE_VULKAN("VKDriver::prepare_window"); - auto vk_window = m_window_manager->get_or_create(window); - - assert(std::find(m_to_present.begin(), m_to_present.end(), vk_window) == m_to_present.end()); - - vk_window->acquire_next(); - vk_window->color()[vk_window->current()]->transition_layout(m_ctx_immediate->cmd_current(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - m_to_present.push_back(vk_window); - m_queue_wait.push_back(vk_window->acquire_semaphore()); - m_queue_signal.push_back(vk_window->present_semaphore()); - } - void VKDriver::swap_buffers(const Ref& window) { - WG_AUTO_PROFILE_VULKAN("VKDriver::swap_buffers"); - - auto vk_window = m_window_manager->get_or_create(window); - auto swapchain = vk_window->swapchain(); - auto image_index = vk_window->current(); - auto wait_semaphore = vk_window->present_semaphore(); - - VkPresentInfoKHR present_info{}; - present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - present_info.waitSemaphoreCount = 1; - present_info.pWaitSemaphores = &wait_semaphore; - present_info.pSwapchains = &swapchain; - present_info.swapchainCount = 1; - present_info.pImageIndices = &image_index; - present_info.pResults = nullptr; - - vkQueuePresentKHR(m_queues->prs_queue(), &present_info); + m_to_present.clear(); } void VKDriver::init_functions() { diff --git a/engine/runtime/gfx/vulkan/vk_driver.hpp b/engine/runtime/gfx/vulkan/vk_driver.hpp index 19e99f053..c5600f600 100644 --- a/engine/runtime/gfx/vulkan/vk_driver.hpp +++ b/engine/runtime/gfx/vulkan/vk_driver.hpp @@ -29,13 +29,11 @@ #include "core/buffered_vector.hpp" #include "core/flat_map.hpp" +#include "core/synchronization.hpp" #include "core/task_manager.hpp" #include "gfx/gfx_driver.hpp" -#include "gfx/threaded/gfx_driver_threaded.hpp" -#include "gfx/threaded/gfx_driver_wrapper.hpp" -#include "gfx/threaded/gfx_worker.hpp" #include "gfx/vulkan/vk_buffers.hpp" -#include "gfx/vulkan/vk_ctx.hpp" +#include "gfx/vulkan/vk_cmd_manager.hpp" #include "gfx/vulkan/vk_defs.hpp" #include "gfx/vulkan/vk_desc_manager.hpp" #include "gfx/vulkan/vk_desc_set.hpp" @@ -44,6 +42,7 @@ #include "gfx/vulkan/vk_queues.hpp" #include "gfx/vulkan/vk_render_pass.hpp" #include "gfx/vulkan/vk_sampler.hpp" +#include "gfx/vulkan/vk_semaphore.hpp" #include "gfx/vulkan/vk_vert_format.hpp" #include "gfx/vulkan/vk_window.hpp" #include "platform/file_system.hpp" @@ -59,61 +58,51 @@ namespace wmoge { * @class VKDriver * @brief Vulkan gfx driver implementation */ - class VKDriver final : public GfxDriverThreaded { + class VKDriver final : public GfxDriver { public: explicit VKDriver(const VKInitInfo& info); ~VKDriver() override; - Ref make_vert_format(const GfxVertElements& elements, const Strid& name) override; - Ref make_vert_buffer(int size, GfxMemUsage usage, const Strid& name) override; - Ref make_index_buffer(int size, GfxMemUsage usage, const Strid& name) override; - Ref make_uniform_buffer(int size, GfxMemUsage usage, const Strid& name) override; - Ref make_storage_buffer(int size, GfxMemUsage usage, const Strid& name) override; - Ref make_shader(GfxShaderDesc desc, const Strid& name) override; - Ref make_program(GfxShaderProgramDesc desc, const Strid& name) override; - Ref make_texture(const GfxTextureDesc& desc, const Strid& name) override; - Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name) override; - Ref make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) override; - Ref make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) override; - Ref make_sampler(const GfxSamplerDesc& desc, const Strid& name) override; - Ref make_pso_layout(const GfxDescSetLayouts& layouts, const Strid& name) override; - Ref make_pso_graphics(const GfxPsoStateGraphics& state, const Strid& name) override; - Ref make_pso_compute(const GfxPsoStateCompute& state, const Strid& name) override; - Ref make_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name) override; - Ref make_frame_buffer(const VKFrameBufferDesc& desc, const Strid& name); - Ref make_dyn_vert_buffer(int chunk_size, const Strid& name) override; - Ref make_dyn_index_buffer(int chunk_size, const Strid& name) override; - Ref make_dyn_uniform_buffer(int chunk_size, const Strid& name) override; - Ref make_desc_layout(const GfxDescSetLayoutDesc& desc, const Strid& name) override; - Ref make_desc_set(const GfxDescSetResources& resources, const Ref& layout, const Strid& name) override; - Async make_shaders(const Ref& request) override; - Async make_psos_graphics(const Ref& request) override; - Async make_psos_compute(const Ref& request) override; - void shutdown() override; - void begin_frame() override; - void end_frame() override; - void prepare_window(const Ref& window) override; - void swap_buffers(const Ref& window) override; - - class GfxCtx* ctx_immediate() override { return m_ctx_immediate.get(); } - class GfxCtx* ctx_async() override { return m_ctx_async.get(); } - - const GfxDeviceCaps& device_caps() const override { return m_device_caps; } - const Strid& driver_name() const override { return m_driver_name; } - const std::string& pipeline_cache_path() const override { return m_pipeline_cache_path; } - const std::thread::id& thread_id() const override { return m_thread_id; } - const Mat4x4f& clip_matrix() const override { return m_clip_matrix; } - std::size_t frame_number() const override { return m_frame_number.load(); } - bool on_gfx_thread() const override { return m_thread_id == std::this_thread::get_id(); } - GfxShaderLang shader_lang() const override { return GfxShaderLang::GlslVk450; } - CallbackStream* cmd_stream() override { return m_driver_cmd_stream.get(); } - GfxType get_gfx_type() const override { return GfxType::Vulkan; } - GfxShaderPlatform get_shader_platform() const override { return m_shader_patform; } - GfxDriverWrapper* driver_wrapper() { return m_driver_wrapper.get(); } - GfxCtxWrapper* ctx_immediate_wrapper() { return m_ctx_immediate_wrapper.get(); } - CallbackQueue* release_queue() { return &m_deferred_release[m_index]; } + Ref make_vert_format(const GfxVertElements& elements, const Strid& name) override; + Ref make_vert_buffer(int size, GfxMemUsage usage, const Strid& name) override; + Ref make_index_buffer(int size, GfxMemUsage usage, const Strid& name) override; + Ref make_uniform_buffer(int size, GfxMemUsage usage, const Strid& name) override; + Ref make_storage_buffer(int size, GfxMemUsage usage, const Strid& name) override; + Ref make_shader(GfxShaderDesc desc, const Strid& name) override; + Ref make_program(GfxShaderProgramDesc desc, const Strid& name) override; + Ref make_texture(const GfxTextureDesc& desc, const Strid& name) override; + Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name) override; + Ref make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) override; + Ref make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) override; + Ref make_sampler(const GfxSamplerDesc& desc, const Strid& name) override; + Ref make_pso_layout(const GfxDescSetLayouts& layouts, const Strid& name) override; + Ref make_pso_graphics(const GfxPsoStateGraphics& state, const Strid& name) override; + Ref make_pso_compute(const GfxPsoStateCompute& state, const Strid& name) override; + Ref make_render_pass(const GfxRenderPassDesc& pass_desc, const Strid& name) override; + Ref make_render_pass(const Ref& window, const Strid& name) override; + Ref make_frame_buffer(const GfxFrameBufferDesc& desc, const Strid& name); + Ref make_desc_layout(const GfxDescSetLayoutDesc& desc, const Strid& name) override; + Ref make_desc_set(const GfxDescSetResources& resources, const Ref& layout, const Strid& name) override; + Async make_shaders(const Ref& request) override; + Async make_psos_graphics(const Ref& request) override; + Async make_psos_compute(const Ref& request) override; + + virtual void begin_frame(std::size_t frame_id, const array_view>& windows) override; + virtual GfxCmdListRef acquire_cmd_list(GfxQueueType queue_type) override; + virtual void submit_cmd_list(const GfxCmdListRef& cmd_list) override; + virtual void end_frame(bool swap_buffers) override; + + const GfxDeviceCaps& device_caps() const override { return m_device_caps; } + const Strid& driver_name() const override { return m_driver_name; } + const std::string& pipeline_cache_path() const override { return m_pipeline_cache_path; } + const Mat4x4f& clip_matrix() const override { return m_clip_matrix; } + std::size_t frame_number() const override { return m_frame_id; } + GfxShaderLang shader_lang() const override { return GfxShaderLang::GlslVk450; } + GfxType get_gfx_type() const override { return GfxType::Vulkan; } + GfxShaderPlatform get_shader_platform() const override { return m_shader_patform; } + const GfxCmdListRef& get_default_list() const override { return m_default_list; } public: VkInstance instance() { return m_instance; } @@ -123,8 +112,10 @@ namespace wmoge { VKWindowManager* window_manager() { return m_window_manager.get(); } VKQueues* queues() { return m_queues.get(); } VKMemManager* mem_manager() { return m_mem_manager.get(); } + VKSemaphorePool* semaphore_pool() { return m_semaphore_pool.get(); } VKDescManager* desc_manager() { return m_desc_manager.get(); } - VKCtx* vk_ctx() { return m_ctx_immediate.get(); } + VKCmdManager* cmd_manager() { return m_cmd_manager.get(); } + CallbackQueue* release_queue() { return &m_deferred_release[m_index]; } private: void init_functions(); @@ -150,25 +141,30 @@ namespace wmoge { VkDebugUtilsMessengerEXT m_debug_messenger = VK_NULL_HANDLE; VkPipelineCache m_pipeline_cache = VK_NULL_HANDLE; - std::size_t m_index = 0 % GfxLimits::FRAMES_IN_FLIGHT; + std::size_t m_index = 0 % GfxLimits::FRAMES_IN_FLIGHT; + std::size_t m_frame_id = 0; std::array m_deferred_release; std::vector> m_to_present; - std::vector m_queue_wait; - std::vector m_queue_signal; VkFence m_sync_fence = VK_NULL_HANDLE; - flat_map> m_samplers; - flat_map> m_render_passes; - flat_map> m_frame_buffers; + std::unique_ptr m_window_manager; + std::unique_ptr m_queues; + std::unique_ptr m_semaphore_pool; + std::unique_ptr m_mem_manager; + std::unique_ptr m_desc_manager; + std::unique_ptr m_cmd_manager; + std::vector m_device_extensions; + + flat_map> m_samplers; + flat_map> m_render_passes; - GfxDeviceCaps m_device_caps; - Strid m_driver_name = SID("unknown"); - std::thread::id m_thread_id = std::this_thread::get_id(); - Mat4x4f m_clip_matrix; - std::atomic_size_t m_frame_number{0}; - std::string m_pipeline_cache_path; - GfxShaderPlatform m_shader_patform = GfxShaderPlatform::None; + GfxCmdListRef m_default_list; + GfxDeviceCaps m_device_caps; + Strid m_driver_name = SID("unknown"); + Mat4x4f m_clip_matrix; + std::string m_pipeline_cache_path; + GfxShaderPlatform m_shader_patform = GfxShaderPlatform::None; std::string m_app_name; std::string m_engine_name; @@ -177,18 +173,6 @@ namespace wmoge { std::vector m_required_device_extensions; bool m_use_validation = false; - std::unique_ptr m_driver_wrapper; - std::unique_ptr m_ctx_immediate_wrapper; - std::unique_ptr m_driver_worker; - std::unique_ptr m_driver_cmd_stream; - std::unique_ptr m_window_manager; - std::unique_ptr m_queues; - std::unique_ptr m_mem_manager; - std::unique_ptr m_desc_manager; - std::unique_ptr m_ctx_immediate; - std::unique_ptr m_ctx_async; - std::vector m_device_extensions; - FileSystem* m_file_system = nullptr; TaskManager* m_task_manager = nullptr; }; diff --git a/engine/runtime/gfx/vulkan/vk_mem_manager.cpp b/engine/runtime/gfx/vulkan/vk_mem_manager.cpp index 607ba49e6..742019b26 100644 --- a/engine/runtime/gfx/vulkan/vk_mem_manager.cpp +++ b/engine/runtime/gfx/vulkan/vk_mem_manager.cpp @@ -73,31 +73,35 @@ namespace wmoge { WG_VK_CHECK(vmaCreatePool(m_vma, &pool_info, &m_staging[i])); } } + VKMemManager::~VKMemManager() { for (int i = 0; i < GfxLimits::FRAMES_IN_FLIGHT; i++) { - update();// release next + update(i);// release next } for (int i = 0; i < GfxLimits::FRAMES_IN_FLIGHT; i++) { vmaDestroyPool(m_vma, m_staging[i]); } vmaDestroyAllocator(m_vma); } - void VKMemManager::update() { + + void VKMemManager::update(std::size_t frame_id) { std::lock_guard guard(m_mutex); - m_current = (m_current + 1) % GfxLimits::FRAMES_IN_FLIGHT; + m_frame_id = frame_id; + m_index = m_frame_id % GfxLimits::FRAMES_IN_FLIGHT; - for (auto& to_release : m_release_buffs[m_current]) + for (auto& to_release : m_release_buffs[m_index]) vmaDestroyBuffer(m_vma, to_release.first, to_release.second); - for (auto& to_release : m_release_images[m_current]) + for (auto& to_release : m_release_images[m_index]) vmaDestroyImage(m_vma, to_release.first, to_release.second); - for (auto& to_release : m_release_staging[m_current]) + for (auto& to_release : m_release_staging[m_index]) vmaDestroyBuffer(m_vma, to_release.first, to_release.second); - m_release_buffs[m_current].clear(); - m_release_images[m_current].clear(); - m_release_staging[m_current].clear(); + m_release_buffs[m_index].clear(); + m_release_images[m_index].clear(); + m_release_staging[m_index].clear(); } + void VKMemManager::allocate(VkBufferCreateInfo& buff_info, GfxMemUsage usage, VkBuffer& buffer, VmaAllocation& allocation) { VmaAllocationCreateInfo alloc_info{}; alloc_info.requiredFlags = VKDefs::get_memory_properties(usage); @@ -105,6 +109,7 @@ namespace wmoge { alloc_info.flags = VKDefs::get_allocation_flags(usage); WG_VK_CHECK(vmaCreateBuffer(m_vma, &buff_info, &alloc_info, &buffer, &allocation, nullptr)); } + void VKMemManager::allocate(VkImageCreateInfo& image_info, GfxMemUsage usage, VkImage& image, VmaAllocation& allocation) { VmaAllocationCreateInfo alloc_info{}; alloc_info.requiredFlags = VKDefs::get_memory_properties(usage); @@ -112,12 +117,15 @@ namespace wmoge { alloc_info.flags = VKDefs::get_allocation_flags(usage); WG_VK_CHECK(vmaCreateImage(m_vma, &image_info, &alloc_info, &image, &allocation, nullptr)); } + void VKMemManager::deallocate(VkBuffer buffer, VmaAllocation allocation) { - m_release_buffs[m_current].emplace_back(buffer, allocation); + m_release_buffs[m_index].emplace_back(buffer, allocation); } + void VKMemManager::deallocate(VkImage image, VmaAllocation allocation) { - m_release_images[m_current].emplace_back(image, allocation); + m_release_images[m_index].emplace_back(image, allocation); } + void VKMemManager::staging_allocate(VkDeviceSize size, VkBuffer& buffer, VmaAllocation& allocation) { std::lock_guard guard(m_mutex); @@ -127,24 +135,28 @@ namespace wmoge { buff_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; VmaAllocationCreateInfo alloc_info{}; - alloc_info.pool = m_staging[m_current]; + alloc_info.pool = m_staging[m_index]; WG_VK_CHECK(vmaCreateBuffer(m_vma, &buff_info, &alloc_info, &buffer, &allocation, nullptr)); - m_release_staging[m_current].emplace_back(buffer, allocation); + m_release_staging[m_index].emplace_back(buffer, allocation); } + void* VKMemManager::staging_map(VmaAllocation allocation) { void* ptr; WG_VK_CHECK(vmaMapMemory(m_vma, allocation, &ptr)); return ptr; } + void VKMemManager::staging_unmap(VmaAllocation allocation) { vmaUnmapMemory(m_vma, allocation); } + void* VKMemManager::map(VmaAllocation allocation) { void* ptr; WG_VK_CHECK(vmaMapMemory(m_vma, allocation, &ptr)); return ptr; } + void VKMemManager::unmap(VmaAllocation allocation) { vmaUnmapMemory(m_vma, allocation); } diff --git a/engine/runtime/gfx/vulkan/vk_mem_manager.hpp b/engine/runtime/gfx/vulkan/vk_mem_manager.hpp index cf29eb175..d276bac7a 100644 --- a/engine/runtime/gfx/vulkan/vk_mem_manager.hpp +++ b/engine/runtime/gfx/vulkan/vk_mem_manager.hpp @@ -44,7 +44,7 @@ namespace wmoge { VKMemManager(class VKDriver& driver); ~VKMemManager(); - void update(); + void update(std::size_t frame_id); void allocate(VkBufferCreateInfo& buff_info, GfxMemUsage usage, VkBuffer& bufffer, VmaAllocation& allocation); void allocate(VkImageCreateInfo& image_info, GfxMemUsage usage, VkImage& image, VmaAllocation& allocation); @@ -66,7 +66,9 @@ namespace wmoge { VmaPool m_staging[GfxLimits::FRAMES_IN_FLIGHT]; VmaAllocator m_vma = VK_NULL_HANDLE; - int m_current = 0; + std::size_t m_index = 0 % GfxLimits::FRAMES_IN_FLIGHT; + std::size_t m_frame_id = 0; + class VKDriver& m_driver; std::mutex m_mutex; diff --git a/engine/runtime/gfx/vulkan/vk_queues.cpp b/engine/runtime/gfx/vulkan/vk_queues.cpp index 3da199e75..35162bd4e 100644 --- a/engine/runtime/gfx/vulkan/vk_queues.cpp +++ b/engine/runtime/gfx/vulkan/vk_queues.cpp @@ -69,8 +69,12 @@ namespace wmoge { // Compute set of unique families m_families.push_back(m_gfx_queue_family); - if (m_tsf_queue_family != m_gfx_queue_family) m_families.push_back(m_tsf_queue_family); - if (m_prs_queue_family != m_gfx_queue_family && m_prs_queue_family != m_tsf_queue_family) m_families.push_back(m_prs_queue_family); + if (m_tsf_queue_family != m_gfx_queue_family) { + m_families.push_back(m_tsf_queue_family); + } + if (m_prs_queue_family != m_gfx_queue_family && m_prs_queue_family != m_tsf_queue_family) { + m_families.push_back(m_prs_queue_family); + } // Sharing mode m_mode = m_families.size() > 1 ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE; @@ -84,4 +88,34 @@ namespace wmoge { vkGetDeviceQueue(device, m_prs_queue_family, 0, &m_prs_queue); } + VkQueue VKQueues::get_queue(GfxQueueType queue_type) { + switch (queue_type) { + case GfxQueueType::Graphics: + return gfx_queue(); + case GfxQueueType::Compute: + return cmp_queue(); + case GfxQueueType::Copy: + return tsf_queue(); + default: + break; + } + + return VK_NULL_HANDLE; + } + + uint32_t VKQueues::get_family_index(GfxQueueType queue_type) { + switch (queue_type) { + case GfxQueueType::Graphics: + return gfx_queue_family(); + case GfxQueueType::Compute: + return cmp_queue_family(); + case GfxQueueType::Copy: + return tsf_queue_family(); + default: + break; + } + + return 0; + } + }// namespace wmoge diff --git a/engine/runtime/gfx/vulkan/vk_queues.hpp b/engine/runtime/gfx/vulkan/vk_queues.hpp index c873878b1..341ab781a 100644 --- a/engine/runtime/gfx/vulkan/vk_queues.hpp +++ b/engine/runtime/gfx/vulkan/vk_queues.hpp @@ -28,6 +28,7 @@ #pragma once #include "core/buffered_vector.hpp" +#include "core/flat_map.hpp" #include "gfx/gfx_driver.hpp" #include "gfx/vulkan/vk_defs.hpp" @@ -42,27 +43,33 @@ namespace wmoge { static const uint32_t INVALID_QUEUE_INDEX = 0xffffffff; VKQueues(VkPhysicalDevice device, VkSurfaceKHR surface); - bool is_complete() const; - void init_queues(VkDevice device); + bool is_complete() const; + void init_queues(VkDevice device); + VkQueue get_queue(GfxQueueType queue_type); + uint32_t get_family_index(GfxQueueType queue_type); - const buffered_vector& unique_families() const { return m_families; } - uint32_t gfx_queue_family() const { return m_gfx_queue_family; } - uint32_t tsf_queue_family() const { return m_tsf_queue_family; } - uint32_t prs_queue_family() const { return m_prs_queue_family; } - VkQueue gfx_queue() const { return m_gfx_queue; } - VkQueue tsf_queue() const { return m_tsf_queue; } - VkQueue prs_queue() const { return m_prs_queue; } - VkSharingMode mode() const { return m_mode; } + [[nodiscard]] const buffered_vector& unique_families() const { return m_families; } + [[nodiscard]] uint32_t gfx_queue_family() const { return m_gfx_queue_family; } + [[nodiscard]] uint32_t cmp_queue_family() const { return m_cmp_queue_family; } + [[nodiscard]] uint32_t tsf_queue_family() const { return m_tsf_queue_family; } + [[nodiscard]] uint32_t prs_queue_family() const { return m_prs_queue_family; } + [[nodiscard]] VkQueue gfx_queue() const { return m_gfx_queue; } + [[nodiscard]] VkQueue cmp_queue() const { return m_cmp_queue; } + [[nodiscard]] VkQueue tsf_queue() const { return m_tsf_queue; } + [[nodiscard]] VkQueue prs_queue() const { return m_prs_queue; } + [[nodiscard]] VkSharingMode mode() const { return m_mode; } private: buffered_vector m_families; buffered_vector m_props; VkQueue m_gfx_queue = VK_NULL_HANDLE; + VkQueue m_cmp_queue = VK_NULL_HANDLE; VkQueue m_tsf_queue = VK_NULL_HANDLE; VkQueue m_prs_queue = VK_NULL_HANDLE; uint32_t m_gfx_queue_family = INVALID_QUEUE_INDEX; + uint32_t m_cmp_queue_family = INVALID_QUEUE_INDEX; uint32_t m_tsf_queue_family = INVALID_QUEUE_INDEX; uint32_t m_prs_queue_family = INVALID_QUEUE_INDEX; diff --git a/engine/runtime/gfx/vulkan/vk_render_pass.cpp b/engine/runtime/gfx/vulkan/vk_render_pass.cpp index eea080c99..0a895b85b 100644 --- a/engine/runtime/gfx/vulkan/vk_render_pass.cpp +++ b/engine/runtime/gfx/vulkan/vk_render_pass.cpp @@ -29,11 +29,14 @@ #include "core/crc32.hpp" #include "gfx/vulkan/vk_driver.hpp" +#include "gfx/vulkan/vk_texture.hpp" #include "profiler/profiler.hpp" namespace wmoge { - VKRenderPass::VKRenderPass(const GfxRenderPassDesc& pass_desc, const Strid& name, class VKDriver& driver) : VKResource(driver), m_pass_desc(pass_desc) { + VKRenderPass::VKRenderPass(const GfxRenderPassDesc& desc, const Strid& name, class VKDriver& driver) + : VKResource(driver) { + m_desc = desc; m_name = name; int attachments_count = 0; @@ -45,13 +48,13 @@ namespace wmoge { VkAttachmentReference depth_stencil_reference{}; for (int i = 0; i < GfxLimits::MAX_COLOR_TARGETS; i++) { - if (m_pass_desc.color_target_fmts[i] == GfxFormat::Unknown) + if (m_desc.color_target_fmts[i] == GfxFormat::Unknown) break; - attachments[attachments_count].format = VKDefs::get_format(m_pass_desc.color_target_fmts[i]); + attachments[attachments_count].format = VKDefs::get_format(m_desc.color_target_fmts[i]); attachments[attachments_count].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[attachments_count].loadOp = VKDefs::load_op(m_pass_desc.color_target_ops[i]); - attachments[attachments_count].storeOp = VKDefs::store_op(m_pass_desc.color_target_ops[i]); + attachments[attachments_count].loadOp = VKDefs::load_op(m_desc.color_target_ops[i]); + attachments[attachments_count].storeOp = VKDefs::store_op(m_desc.color_target_ops[i]); attachments[attachments_count].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; attachments[attachments_count].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; @@ -61,15 +64,15 @@ namespace wmoge { attachments_count += 1; color_references_count += 1; } - if (m_pass_desc.depth_stencil_fmt != GfxFormat::Unknown) { - auto layout = VKDefs::rt_layout_from_fmt(m_pass_desc.depth_stencil_fmt); + if (m_desc.depth_stencil_fmt != GfxFormat::Unknown) { + auto layout = VKDefs::rt_layout_from_fmt(m_desc.depth_stencil_fmt); - attachments[attachments_count].format = VKDefs::get_format(m_pass_desc.depth_stencil_fmt); + attachments[attachments_count].format = VKDefs::get_format(m_desc.depth_stencil_fmt); attachments[attachments_count].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[attachments_count].loadOp = VKDefs::load_op(m_pass_desc.depth_op); - attachments[attachments_count].storeOp = VKDefs::store_op(m_pass_desc.depth_op); - attachments[attachments_count].stencilLoadOp = VKDefs::load_op(m_pass_desc.stencil_op); - attachments[attachments_count].stencilStoreOp = VKDefs::store_op(m_pass_desc.stencil_op); + attachments[attachments_count].loadOp = VKDefs::load_op(m_desc.depth_op); + attachments[attachments_count].storeOp = VKDefs::store_op(m_desc.depth_op); + attachments[attachments_count].stencilLoadOp = VKDefs::load_op(m_desc.stencil_op); + attachments[attachments_count].stencilStoreOp = VKDefs::store_op(m_desc.stencil_op); attachments[attachments_count].initialLayout = layout; attachments[attachments_count].finalLayout = layout; @@ -114,21 +117,14 @@ namespace wmoge { } } - bool VKFrameBufferDesc::operator==(const VKFrameBufferDesc& other) const { - return std::memcmp(this, &other, sizeof(VKFrameBufferDesc)) == 0; - } - std::size_t VKFrameBufferDesc::hash() const { - return static_cast(Crc32Util::hash(this, sizeof(VKFrameBufferDesc))); - } - - VKFramebufferObject::VKFramebufferObject(const VKFrameBufferDesc& desc, const Strid& name, class VKDriver& driver) - : VKResource(driver) { + VKFrameBuffer::VKFrameBuffer(const GfxFrameBufferDesc& desc, const Strid& name, class VKDriver& driver) + : VKResource(driver) { m_desc = desc; m_name = name; VkFramebufferCreateInfo create_info{}; create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - create_info.renderPass = desc.render_pass->render_pass(); + create_info.renderPass = desc.render_pass.cast()->render_pass(); std::array views; int views_count = 0; @@ -138,15 +134,15 @@ namespace wmoge { break; } - auto& texture = desc.color_targets[i].texture; + auto texture = desc.color_targets[i].texture.cast(); views[views_count++] = texture->has_rt_views() ? texture->rt_view(desc.color_targets[i].slice, desc.color_targets[i].mip) : texture->view(); } if (desc.depth_stencil_target.texture) { - auto& texture = desc.depth_stencil_target.texture; + auto& texture = desc.depth_stencil_target.texture.cast(); views[views_count++] = texture->rt_view(desc.depth_stencil_target.slice, desc.depth_stencil_target.mip); } - Ref ref = desc.depth_stencil_target.texture ? desc.depth_stencil_target.texture : desc.color_targets[0].texture; + Ref ref = (desc.depth_stencil_target.texture ? desc.depth_stencil_target.texture : desc.color_targets[0].texture).cast(); m_size[0] = ref->width(); m_size[1] = ref->height(); @@ -159,107 +155,12 @@ namespace wmoge { WG_VK_CHECK(vkCreateFramebuffer(m_driver.device(), &create_info, nullptr, &m_framebuffer)); WG_VK_NAME(m_driver.device(), m_framebuffer, VK_OBJECT_TYPE_FRAMEBUFFER, m_name.str()); } - VKFramebufferObject::~VKFramebufferObject() { - WG_AUTO_PROFILE_VULKAN("VKFramebufferObject::~VKFramebufferObject"); + VKFrameBuffer::~VKFrameBuffer() { + WG_AUTO_PROFILE_VULKAN("VKFrameBuffer::~VKFrameBuffer"); if (m_framebuffer) { vkDestroyFramebuffer(m_driver.device(), m_framebuffer, nullptr); } } - VKRenderPassBinder::VKRenderPassBinder(VKDriver& driver) : m_driver(driver) { - } - void VKRenderPassBinder::bind_target(const Ref& window) { - m_window = window; - bind_color_target(m_window->color()[m_window->current()], 0, 0, 0); - bind_depth_target(m_window->depth_stencil(), 0, 0); - } - void VKRenderPassBinder::bind_color_target(const Ref& texture, int target, int mip, int slice) { - m_current_pass_desc.color_target_fmts[target] = texture->format(); - VKTargetInfo& info = m_color_targets[target]; - info.texture = texture; - info.mip = mip; - info.slice = slice; - } - void VKRenderPassBinder::bind_depth_target(const Ref& texture, int mip, int slice) { - m_current_pass_desc.depth_stencil_fmt = texture->format(); - m_depth_stencil_target.texture = texture; - m_depth_stencil_target.mip = mip; - m_depth_stencil_target.slice = slice; - } - void VKRenderPassBinder::clear_color(int target) { - m_current_pass_desc.color_target_ops[target] = GfxRtOp::ClearStore; - } - void VKRenderPassBinder::clear_depth() { - m_current_pass_desc.depth_op = GfxRtOp::ClearStore; - } - void VKRenderPassBinder::clear_stencil() { - m_current_pass_desc.stencil_op = GfxRtOp::ClearStore; - } - - void VKRenderPassBinder::start(const Strid& name) { - WG_AUTO_PROFILE_VULKAN("VKRenderPassBinder::start"); - - m_current_name = name; - } - void VKRenderPassBinder::validate(VkCommandBuffer cmd) { - WG_AUTO_PROFILE_VULKAN("VKRenderPassBinder::validate"); - - prepare_render_pass(); - prepare_framebuffer(); - - for (auto& target : m_color_targets) { - if (target.texture) { - target.texture->transition_layout(cmd, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - } - } - - if (m_depth_stencil_target.texture) { - m_depth_stencil_target.texture->transition_layout(cmd, VKDefs::rt_layout_from_fmt(m_depth_stencil_target.texture->format())); - } - } - void VKRenderPassBinder::finish(VkCommandBuffer cmd) { - WG_AUTO_PROFILE_VULKAN("VKRenderPassBinder::finish"); - - for (auto& target : m_color_targets) { - if (target.texture) { - target.texture->transition_layout(cmd, target.texture->primary_layout()); - target = VKTargetInfo(); - } - } - - if (m_depth_stencil_target.texture) { - m_depth_stencil_target.texture->transition_layout(cmd, m_depth_stencil_target.texture->primary_layout()); - m_depth_stencil_target = VKTargetInfo(); - } - - m_current_render_pass.reset(); - m_current_framebuffer.reset(); - m_current_size = {0, 0}; - m_current_pass_desc = GfxRenderPassDesc{}; - m_current_name = Strid(); - } - - const Ref& VKRenderPassBinder::get_or_create_render_pass() { - prepare_render_pass(); - - return m_current_render_pass; - } - - void VKRenderPassBinder::prepare_render_pass() { - WG_AUTO_PROFILE_VULKAN("VKRenderPassBinder::prepare_render_pass"); - - m_current_render_pass = m_driver.make_render_pass(m_current_pass_desc, m_current_name).cast(); - } - void VKRenderPassBinder::prepare_framebuffer() { - WG_AUTO_PROFILE_VULKAN("VKRenderPassBinder::prepare_framebuffer"); - - m_current_fb_desc.color_targets = m_color_targets; - m_current_fb_desc.depth_stencil_target = m_depth_stencil_target; - m_current_fb_desc.render_pass = m_current_render_pass; - - m_current_framebuffer = m_driver.make_frame_buffer(m_current_fb_desc, m_current_name); - m_current_size = m_current_framebuffer->size(); - } - }// namespace wmoge diff --git a/engine/runtime/gfx/vulkan/vk_render_pass.hpp b/engine/runtime/gfx/vulkan/vk_render_pass.hpp index 24cd56c65..3a5b50536 100644 --- a/engine/runtime/gfx/vulkan/vk_render_pass.hpp +++ b/engine/runtime/gfx/vulkan/vk_render_pass.hpp @@ -27,139 +27,57 @@ #pragma once -#include "core/buffered_vector.hpp" #include "gfx/gfx_defs.hpp" #include "gfx/gfx_render_pass.hpp" #include "gfx/vulkan/vk_defs.hpp" #include "gfx/vulkan/vk_resource.hpp" #include "gfx/vulkan/vk_texture.hpp" -#include "gfx/vulkan/vk_window.hpp" - -#include +#include "math/vec.hpp" namespace wmoge { - /** - * @class VKTargetInfo - * @brief Info to bind texture as a render target - */ - struct VKTargetInfo { - Ref texture; - int slice = -1; - int mip = -1; - }; - - static_assert(sizeof(VKTargetInfo) == 16, "VKTargetInfo must fit 16 exactly"); - /** * @class VKRenderPass * @brief Vulkan single render pass implementation required for PSO and drawing */ class VKRenderPass : public VKResource { public: - VKRenderPass(const GfxRenderPassDesc& pass_desc, const Strid& name, class VKDriver& driver); + VKRenderPass(const GfxRenderPassDesc& desc, const Strid& name, class VKDriver& driver); ~VKRenderPass() override; - [[nodiscard]] const GfxRenderPassDesc& pass_desc() const override { return m_pass_desc; } - [[nodiscard]] VkRenderPass render_pass() const { return m_render_pass; } - [[nodiscard]] int color_targets_count() const { return m_color_targets_count; } - [[nodiscard]] bool has_depth_stencil() const { return m_has_depth_stencil; } + const GfxRenderPassDesc& desc() const override { return m_desc; } + + [[nodiscard]] VkRenderPass render_pass() const { return m_render_pass; } + [[nodiscard]] int color_targets_count() const { return m_color_targets_count; } + [[nodiscard]] bool has_depth_stencil() const { return m_has_depth_stencil; } + [[nodiscard]] Size2i get_size() const { return m_size; } private: - GfxRenderPassDesc m_pass_desc{}; - VkRenderPass m_render_pass = VK_NULL_HANDLE; + GfxRenderPassDesc m_desc{}; + VkRenderPass m_render_pass = VK_NULL_HANDLE; + Size2i m_size{0, 0}; bool m_has_depth_stencil = false; int m_color_targets_count = 0; }; /** - * @class VKFrameBufferDesc - * @brief Frame buffer desc for creation and caching - */ - struct VKFrameBufferDesc { - VKFrameBufferDesc() = default; - bool operator==(const VKFrameBufferDesc& other) const; - std::size_t hash() const; - - std::array color_targets{}; - VKTargetInfo depth_stencil_target{}; - Ref render_pass; - }; - - static_assert(sizeof(VKFrameBufferDesc) == (sizeof(VKTargetInfo) * 9 + sizeof(void*)), "VKFrameBufferDesc must fit exactly"); - - /** - * @class VKFramebufferObject - * @brief Raii wrapper for VkFramebuffer object - */ - class VKFramebufferObject : public VKResource { - public: - VKFramebufferObject(const VKFrameBufferDesc& desc, const Strid& name, class VKDriver& driver); - ~VKFramebufferObject() override; - - Size2i size() const { return m_size; } - VkFramebuffer framebuffer() const { return m_framebuffer; } - - private: - Size2i m_size; - VKFrameBufferDesc m_desc; - VkFramebuffer m_framebuffer = VK_NULL_HANDLE; - }; - - /** - * @class VKRenderPassBinder - * @brief Binds color targets to prepare render pass and frame buffer + * @class VKFrameBuffer + * @brief Vulkan frame buffer object implementation */ - class VKRenderPassBinder { + class VKFrameBuffer : public VKResource { public: - explicit VKRenderPassBinder(class VKDriver& driver); - ~VKRenderPassBinder() = default; + VKFrameBuffer(const GfxFrameBufferDesc& desc, const Strid& name, class VKDriver& driver); + ~VKFrameBuffer() override; - void bind_target(const Ref& window); - void bind_color_target(const Ref& texture, int target, int mip, int slice); - void bind_depth_target(const Ref& texture, int mip, int slice); - void clear_color(int target); - void clear_depth(); - void clear_stencil(); + const GfxFrameBufferDesc& desc() const override { return m_desc; } - void start(const Strid& name); - void validate(VkCommandBuffer cmd); - void finish(VkCommandBuffer cmd); - - [[nodiscard]] const Ref& get_or_create_render_pass(); - [[nodiscard]] const Ref& render_pass() const { return m_current_render_pass; } - [[nodiscard]] const Ref& framebuffer() const { return m_current_framebuffer; } - [[nodiscard]] int width() const { return m_current_size[0]; } - [[nodiscard]] int height() const { return m_current_size[1]; } + [[nodiscard]] Size2i size() const { return m_size; } + [[nodiscard]] VkFramebuffer framebuffer() const { return m_framebuffer; } private: - void prepare_render_pass(); - void prepare_framebuffer(); - - private: - std::array m_color_targets{}; - VKTargetInfo m_depth_stencil_target{}; - Ref m_window; - - GfxRenderPassDesc m_current_pass_desc{}; - VKFrameBufferDesc m_current_fb_desc{}; - Ref m_current_render_pass{}; - Ref m_current_framebuffer{}; - Size2i m_current_size{}; - Strid m_current_name{}; - - class VKDriver& m_driver; - }; - -}// namespace wmoge - -namespace std { - - template<> - struct hash { - std::size_t operator()(const wmoge::VKFrameBufferDesc& desc) const { - return desc.hash(); - } + Size2i m_size; + GfxFrameBufferDesc m_desc; + VkFramebuffer m_framebuffer = VK_NULL_HANDLE; }; -}// namespace std \ No newline at end of file +}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/threaded/gfx_worker.cpp b/engine/runtime/gfx/vulkan/vk_semaphore.cpp similarity index 59% rename from engine/runtime/gfx/threaded/gfx_worker.cpp rename to engine/runtime/gfx/vulkan/vk_semaphore.cpp index 992cc40ef..35dc1fb52 100644 --- a/engine/runtime/gfx/threaded/gfx_worker.cpp +++ b/engine/runtime/gfx/vulkan/vk_semaphore.cpp @@ -25,37 +25,64 @@ /* SOFTWARE. */ /**********************************************************************************/ -#include "gfx_worker.hpp" +#include "vk_semaphore.hpp" -#include "profiler/profiler.hpp" -#include "system/engine.hpp" - -#include +#include "gfx/vulkan/vk_driver.hpp" namespace wmoge { - GfxWorker::GfxWorker(CallbackStream* cmd_stream) { - assert(cmd_stream); + VKSemaphorePool::VKSemaphorePool(VKDriver& driver) : m_driver(driver) { + } - m_stream = cmd_stream; + VKSemaphorePool::~VKSemaphorePool() { + clear(); + } - m_worker_thread = std::thread([&]() { - m_stream->set_consumer_id(std::this_thread::get_id()); - while (!m_finished.load()) { - m_stream->consume(); + void VKSemaphorePool::clear() { + for (auto& list : m_used) { + for (auto semaphore : list) { + vkDestroySemaphore(m_driver.device(), semaphore, nullptr); } - }); + list.clear(); + } - Profiler* profiler = Engine::instance()->profiler(); - profiler->add_tid(m_worker_thread.get_id(), m_name); + for (auto semaphore : m_free) { + vkDestroySemaphore(m_driver.device(), semaphore, nullptr); + } + m_free.clear(); } - void GfxWorker::terminate() { - m_finished.store(true); - m_stream->push_close(); - m_worker_thread.join(); + + void VKSemaphorePool::update(std::size_t frame_id) { + m_frame_id = frame_id; + m_index = m_frame_id % GfxLimits::FRAMES_IN_FLIGHT; + + for (auto semaphore : m_used[m_index]) { + m_free.push_back(semaphore); + } + + m_used[m_index].clear(); } - std::thread::id GfxWorker::get_worker_id() { - return m_worker_thread.get_id(); + + VkSemaphore VKSemaphorePool::allocate() { + if (m_free.empty()) { + VkSemaphore semaphore; + + VkSemaphoreCreateInfo semaphore_info{}; + semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + WG_VK_CHECK(vkCreateSemaphore(m_driver.device(), &semaphore_info, nullptr, &semaphore)); + WG_VK_NAME(m_driver.device(), semaphore, VK_OBJECT_TYPE_SEMAPHORE, "id=" + std::to_string(m_next_id)); + + m_free.push_back(semaphore); + m_next_id++; + } + + VkSemaphore semaphore = m_free.back(); + m_free.pop_back(); + + m_used[m_index].push_back(semaphore); + + return semaphore; } -}// namespace wmoge +}// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/threaded/gfx_worker.hpp b/engine/runtime/gfx/vulkan/vk_semaphore.hpp similarity index 76% rename from engine/runtime/gfx/threaded/gfx_worker.hpp rename to engine/runtime/gfx/vulkan/vk_semaphore.hpp index 8e4579d2d..8784a0196 100644 --- a/engine/runtime/gfx/threaded/gfx_worker.hpp +++ b/engine/runtime/gfx/vulkan/vk_semaphore.hpp @@ -27,30 +27,39 @@ #pragma once -#include "core/callback_stream.hpp" -#include "core/string_id.hpp" +#include "core/buffered_vector.hpp" +#include "core/simple_id.hpp" +#include "gfx/vulkan/vk_defs.hpp" -#include -#include +#include +#include namespace wmoge { /** - * @class GfxWorker - * @brief Manages gfx thread processing gfx API calls - */ - class GfxWorker { + * @class VKSemaphorePool + * @brief Vulkan semaphores pool with reuse + */ + class VKSemaphorePool { public: - explicit GfxWorker(CallbackStream* cmd_stream); + VKSemaphorePool(class VKDriver& driver); + ~VKSemaphorePool(); - void terminate(); - std::thread::id get_worker_id(); + void clear(); + void update(std::size_t frame_id); + + VkSemaphore allocate(); private: - CallbackStream* m_stream = nullptr; - std::thread m_worker_thread; - std::atomic_bool m_finished{false}; - Strid m_name = SID("gfx-thread"); + std::vector m_used[GfxLimits::FRAMES_IN_FLIGHT]; + std::vector m_free; + + std::size_t m_index = 0 % GfxLimits::FRAMES_IN_FLIGHT; + std::size_t m_frame_id = 0; + + int m_next_id = 0; + + class VKDriver& m_driver; }; }// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/gfx/vulkan/vk_texture.cpp b/engine/runtime/gfx/vulkan/vk_texture.cpp index 7a13f640d..eaefaa633 100644 --- a/engine/runtime/gfx/vulkan/vk_texture.cpp +++ b/engine/runtime/gfx/vulkan/vk_texture.cpp @@ -37,23 +37,25 @@ namespace wmoge { VKTexture::~VKTexture() { WG_AUTO_PROFILE_VULKAN("VKTexture::~VKTexture"); - for (auto view : m_rt_views) + for (auto view : m_rt_views) { vkDestroyImageView(m_driver.device(), view, nullptr); - if (m_view) + } + if (m_view) { vkDestroyImageView(m_driver.device(), m_view, nullptr); - if (m_image && m_allocation) + } + if (m_image && m_allocation) { m_driver.mem_manager()->deallocate(m_image, m_allocation); + } } - void VKTexture::create(VkCommandBuffer cmd, const GfxTextureDesc& desc, const Strid& name) { + void VKTexture::create(const GfxTextureDesc& desc, const Strid& name) { m_desc = desc; m_name = name; init_image(); init_view(); init_rt_views(); - init_layout(cmd); } - void VKTexture::create_2d(VkCommandBuffer cmd, int width, int height, VkImage image, VkFormat format, const Strid& name) { + void VKTexture::create_2d(int width, int height, VkImage image, VkFormat format, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKTexture::create_2d"); m_desc.tex_type = GfxTex::Tex2d; @@ -84,9 +86,8 @@ namespace wmoge { } init_view(); - init_layout(cmd); } - void VKTexture::create_2d(VkCommandBuffer cmd, int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name) { + void VKTexture::create_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKTexture::create_2d"); GfxTextureDesc desc; @@ -101,9 +102,9 @@ namespace wmoge { desc.usages = usages; desc.mem_usage = mem_usage; - create(cmd, desc, name); + create(desc, name); } - void VKTexture::create_2d_array(VkCommandBuffer cmd, int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) { + void VKTexture::create_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKTexture::create_2d_array"); GfxTextureDesc desc; @@ -117,9 +118,9 @@ namespace wmoge { desc.usages = usages; desc.mem_usage = mem_usage; - create(cmd, desc, name); + create(desc, name); } - void VKTexture::create_cube(VkCommandBuffer cmd, int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) { + void VKTexture::create_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name) { WG_AUTO_PROFILE_VULKAN("VKTexture::create_cube"); GfxTextureDesc desc; @@ -133,7 +134,7 @@ namespace wmoge { desc.usages = usages; desc.mem_usage = mem_usage; - create(cmd, desc, name); + create(desc, name); } void VKTexture::update_2d(VkCommandBuffer cmd, int mip, const Rect2i& region, const Ref& data) { WG_AUTO_PROFILE_VULKAN("VKTexture::update_2d"); @@ -405,7 +406,6 @@ namespace wmoge { void VKTexture::init_layout(VkCommandBuffer cmd) { WG_AUTO_PROFILE_VULKAN("VKTexture::init_layout"); - assert(m_driver.on_gfx_thread()); assert(cmd != VK_NULL_HANDLE); transition_layout(cmd, m_primary_layout); diff --git a/engine/runtime/gfx/vulkan/vk_texture.hpp b/engine/runtime/gfx/vulkan/vk_texture.hpp index 2f405fcad..3d180a005 100644 --- a/engine/runtime/gfx/vulkan/vk_texture.hpp +++ b/engine/runtime/gfx/vulkan/vk_texture.hpp @@ -43,11 +43,11 @@ namespace wmoge { explicit VKTexture(class VKDriver& driver); ~VKTexture() override; - void create(VkCommandBuffer cmd, const GfxTextureDesc& desc, const Strid& name); - void create_2d(VkCommandBuffer cmd, int width, int height, VkImage image, VkFormat format, const Strid& name); - void create_2d(VkCommandBuffer cmd, int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name); - void create_2d_array(VkCommandBuffer cmd, int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name); - void create_cube(VkCommandBuffer cmd, int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name); + void create(const GfxTextureDesc& desc, const Strid& name); + void create_2d(int width, int height, VkImage image, VkFormat format, const Strid& name); + void create_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const Strid& name); + void create_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name); + void create_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const Strid& name); void update_2d(VkCommandBuffer cmd, int mip, const Rect2i& region, const Ref& data); void update_2d_array(VkCommandBuffer cmd, int mip, int slice, const Rect2i& region, const Ref& data); diff --git a/engine/runtime/gfx/vulkan/vk_window.cpp b/engine/runtime/gfx/vulkan/vk_window.cpp index 6c2349f35..8ea406f64 100644 --- a/engine/runtime/gfx/vulkan/vk_window.cpp +++ b/engine/runtime/gfx/vulkan/vk_window.cpp @@ -201,13 +201,13 @@ namespace wmoge { for (uint32_t i = 0; i < color_image_count; i++) { m_color_targets[i] = make_ref(m_driver); - m_color_targets[i]->create_2d(m_driver.vk_ctx()->cmd_current(), width(), height(), color_images[i], m_surface_format.format, m_window->id()); + m_color_targets[i]->create_2d(width(), height(), color_images[i], m_surface_format.format, m_window->id()); } GfxTexUsages depth_stencil_usages; depth_stencil_usages.set(GfxTexUsageFlag::DepthStencilTarget); m_depth_stencil_target = make_ref(m_driver); - m_depth_stencil_target->create_2d(m_driver.vk_ctx()->cmd_current(), width(), height(), 1, GfxFormat::DEPTH24_STENCIL8, depth_stencil_usages, GfxMemUsage::GpuLocal, GfxTexSwizz::None, m_window->id()); + m_depth_stencil_target->create_2d(width(), height(), 1, GfxFormat::DEPTH24_STENCIL8, depth_stencil_usages, GfxMemUsage::GpuLocal, GfxTexSwizz::None, m_window->id()); m_requested_extent = m_extent; m_version += 1; diff --git a/engine/runtime/grc/shader_param_block.cpp b/engine/runtime/grc/shader_param_block.cpp index cd401dbee..9a6fa4b10 100644 --- a/engine/runtime/grc/shader_param_block.cpp +++ b/engine/runtime/grc/shader_param_block.cpp @@ -28,7 +28,7 @@ #include "shader_param_block.hpp" #include "core/log.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_driver.hpp" #include "grc/shader_param.hpp" @@ -311,7 +311,7 @@ namespace wmoge { return WG_OK; } - Status ShaderParamBlock::validate(GfxDriver* driver, GfxCtx* ctx) { + Status ShaderParamBlock::validate(GfxDriver* driver, GfxCmdList* cmd_list) { if (!m_shader) { WG_LOG_ERROR("param block not configured"); return StatusCode::InvalidState; @@ -337,7 +337,7 @@ namespace wmoge { assert(buffer); assert(buffer->size() == src->size()); - ctx->update_uniform_buffer(buffer, v.offset, v.range, src); + cmd_list->update_uniform_buffer(buffer, v.offset, v.range, src); } } } diff --git a/engine/runtime/grc/shader_param_block.hpp b/engine/runtime/grc/shader_param_block.hpp index b585a2708..d315bb270 100644 --- a/engine/runtime/grc/shader_param_block.hpp +++ b/engine/runtime/grc/shader_param_block.hpp @@ -79,7 +79,7 @@ namespace wmoge { Status init(Shader& shader, std::int16_t space_idx, const Strid& name); Status restore_defaults(); - Status validate(class GfxDriver* driver, class GfxCtx* ctx); + Status validate(class GfxDriver* driver, class GfxCmdList* cmd_list); Status set_var(ShaderParamId param_id, int v); Status set_var(ShaderParamId param_id, float v); diff --git a/engine/runtime/grc/shader_pass.cpp b/engine/runtime/grc/shader_pass.cpp index 181ade9a1..549a0d5ed 100644 --- a/engine/runtime/grc/shader_pass.cpp +++ b/engine/runtime/grc/shader_pass.cpp @@ -28,7 +28,7 @@ #include "shader_pass.hpp" #include "core/log.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_driver.hpp" #include "grc/pso_cache.hpp" #include "grc/shader.hpp" @@ -130,15 +130,14 @@ namespace wmoge { m_pipeline_state.bs = bs; } - Status ShaderPass::configure(GfxCtx* context) { - assert(context); + Status ShaderPass::configure(GfxCmdList& cmd_list) { assert(m_technique); assert(m_pass); if (m_shader->is_graphics()) { - WG_CHECKED(configure_graphics(context)); + WG_CHECKED(configure_graphics(cmd_list)); } else if (m_shader->is_compute()) { - WG_CHECKED(configure_compute(context)); + WG_CHECKED(configure_compute(cmd_list)); } else { WG_LOG_ERROR("unsupported domain of shader " << m_shader->get_name()); return StatusCode::InvalidState; @@ -151,13 +150,13 @@ namespace wmoge { if (!m_params[i]) { return StatusCode::InvalidState; } - WG_CHECKED(m_params[i]->validate(driver, context)); + WG_CHECKED(m_params[i]->validate(driver, &cmd_list)); } return WG_OK; } - Status ShaderPass::configure_graphics(GfxCtx* context) { + Status ShaderPass::configure_graphics(GfxCmdList& cmd_list) { auto platform = m_shader->get_active_platform(); auto program = m_shader->get_or_create_program(platform, m_permutation); @@ -175,7 +174,7 @@ namespace wmoge { } GfxRenderPassRef rp; - context->extract_render_pass(rp); + cmd_list.peek_render_pass(rp); GfxPsoStateGraphics state; state.pass = rp; @@ -191,11 +190,11 @@ namespace wmoge { return StatusCode::NoValue; } - context->bind_pso(pso_ref.cast()); + cmd_list.bind_pso(pso_ref.cast()); return WG_OK; } - Status ShaderPass::configure_compute(GfxCtx* context) { + Status ShaderPass::configure_compute(GfxCmdList& cmd_list) { auto platform = m_shader->get_active_platform(); auto program = m_shader->get_or_create_program(platform, m_permutation); @@ -214,7 +213,7 @@ namespace wmoge { return StatusCode::NoValue; } - context->bind_pso(pso_ref.cast()); + cmd_list.bind_pso(pso_ref.cast()); return WG_OK; } diff --git a/engine/runtime/grc/shader_pass.hpp b/engine/runtime/grc/shader_pass.hpp index 32a1baf28..911de4275 100644 --- a/engine/runtime/grc/shader_pass.hpp +++ b/engine/runtime/grc/shader_pass.hpp @@ -54,11 +54,11 @@ namespace wmoge { void set_ds(const DepthStencilState& ds); void set_bs(const BlendState& bs); - Status configure(class GfxCtx* context); + Status configure(class GfxCmdList& cmd_list); private: - Status configure_graphics(class GfxCtx* context); - Status configure_compute(class GfxCtx* context); + Status configure_graphics(class GfxCmdList& cmd_list); + Status configure_compute(class GfxCmdList& cmd_list); private: buffered_vector> m_params; diff --git a/engine/runtime/grc/texture.cpp b/engine/runtime/grc/texture.cpp index 7db532a99..3a7e185d1 100644 --- a/engine/runtime/grc/texture.cpp +++ b/engine/runtime/grc/texture.cpp @@ -163,7 +163,6 @@ namespace wmoge { Engine* engine = Engine::instance(); GfxDriver* gfx_driver = engine->gfx_driver(); - GfxCtx* gfx_ctx = engine->gfx_ctx(); switch (m_tex_type) { case GfxTex::Tex2d: @@ -198,13 +197,13 @@ namespace wmoge { switch (m_tex_type) { case GfxTex::Tex2d: - gfx_ctx->update_texture_2d(m_texture, mip, rect, data); + // gfx_ctx->update_texture_2d(m_texture, mip, rect, data); continue; case GfxTex::Tex2dArray: - gfx_ctx->update_texture_2d_array(m_texture, mip, array_slice, rect, data); + // gfx_ctx->update_texture_2d_array(m_texture, mip, array_slice, rect, data); continue; case GfxTex::TexCube: - gfx_ctx->update_texture_cube(m_texture, mip, array_slice, rect, data); + // gfx_ctx->update_texture_cube(m_texture, mip, array_slice, rect, data); continue; default: assert(false); diff --git a/engine/runtime/grc/texture_manager.cpp b/engine/runtime/grc/texture_manager.cpp index 66df7ce49..3c21f40c2 100644 --- a/engine/runtime/grc/texture_manager.cpp +++ b/engine/runtime/grc/texture_manager.cpp @@ -38,7 +38,6 @@ namespace wmoge { WG_AUTO_PROFILE_GRC("TextureManager::TextureManager"); m_gfx_driver = IocContainer::iresolve_v(); - m_gfx_ctx = IocContainer::iresolve_v(); init_default_textures(); init_default_samplers(); @@ -80,7 +79,7 @@ namespace wmoge { } for (int i = 0; i < int(DefaultTexture::Total); i++) { - m_gfx_ctx->update_texture_2d(m_default_textures[i], 0, Rect2i(0, 0, 1, 1), make_ref(tex_colors[i].data(), sizeof(std::uint8_t[4]))); + // m_gfx_ctx->update_texture_2d(m_default_textures[i], 0, Rect2i(0, 0, 1, 1), make_ref(tex_colors[i].data(), sizeof(std::uint8_t[4]))); } } diff --git a/engine/runtime/grc/texture_manager.hpp b/engine/runtime/grc/texture_manager.hpp index 4b46b1894..90a373908 100644 --- a/engine/runtime/grc/texture_manager.hpp +++ b/engine/runtime/grc/texture_manager.hpp @@ -27,7 +27,7 @@ #pragma once -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_driver.hpp" #include "gfx/gfx_texture.hpp" @@ -73,7 +73,6 @@ namespace wmoge { private: GfxDriver* m_gfx_driver; - GfxCtx* m_gfx_ctx; Ref m_default_textures[int(DefaultTexture::Total)]; Ref m_default_samplers[int(DefaultSampler::Total)]; diff --git a/engine/runtime/mesh/mesh.cpp b/engine/runtime/mesh/mesh.cpp index 15eddef87..f66e62851 100644 --- a/engine/runtime/mesh/mesh.cpp +++ b/engine/runtime/mesh/mesh.cpp @@ -92,7 +92,7 @@ namespace wmoge { void Mesh::update_gfx_buffers() { auto* engine = Engine::instance(); auto* gfx_driver = engine->gfx_driver(); - auto* gfx_ctx = engine->gfx_ctx(); + // auto* gfx_ctx = engine->gfx_ctx(); GfxMemUsage mem_usage = GfxMemUsage::GpuLocal; @@ -102,7 +102,7 @@ namespace wmoge { const int size = static_cast(m_vertex_buffers[i]->size()); const Strid name = SID(get_name().str() + "_" + StringUtils::from_int(i)); m_gfx_vertex_buffers[i] = gfx_driver->make_vert_buffer(size, mem_usage, name); - gfx_ctx->update_vert_buffer(m_gfx_vertex_buffers[i], 0, size, m_vertex_buffers[i]); + // gfx_ctx->update_vert_buffer(m_gfx_vertex_buffers[i], 0, size, m_vertex_buffers[i]); } m_gfx_index_buffers.resize(m_index_buffers.size()); @@ -111,7 +111,7 @@ namespace wmoge { const int size = static_cast(m_index_buffers[i]->size()); const Strid name = SID(get_name().str() + "_" + StringUtils::from_int(i)); m_gfx_index_buffers[i] = gfx_driver->make_index_buffer(size, mem_usage, name); - gfx_ctx->update_index_buffer(m_gfx_index_buffers[i], 0, size, m_index_buffers[i]); + // gfx_ctx->update_index_buffer(m_gfx_index_buffers[i], 0, size, m_index_buffers[i]); } } diff --git a/engine/runtime/mesh/mesh_batch.cpp b/engine/runtime/mesh/mesh_batch.cpp index 4794e7a5f..4173f9d02 100644 --- a/engine/runtime/mesh/mesh_batch.cpp +++ b/engine/runtime/mesh/mesh_batch.cpp @@ -55,7 +55,6 @@ namespace wmoge { Engine* engine = Engine::instance(); m_driver = engine->gfx_driver(); - m_ctx = engine->gfx_ctx(); // Register pass processors here m_processors[int(MeshPassType::GBuffer)] = std::make_unique(); diff --git a/engine/runtime/mesh/mesh_batch.hpp b/engine/runtime/mesh/mesh_batch.hpp index a8ff212dd..98bfe241c 100644 --- a/engine/runtime/mesh/mesh_batch.hpp +++ b/engine/runtime/mesh/mesh_batch.hpp @@ -33,7 +33,6 @@ #include "core/synchronization.hpp" #include "gfx/gfx_buffers.hpp" #include "gfx/gfx_desc_set.hpp" -#include "gfx/gfx_dynamic_buffers.hpp" #include "gfx/gfx_pipeline.hpp" #include "gfx/gfx_vert_format.hpp" #include "math/aabb.hpp" @@ -86,19 +85,13 @@ namespace wmoge { void clear(); [[nodiscard]] array_view get_batches() const { return m_batches; } - [[nodiscard]] GfxDynVertBuffer* get_dyn_vbuff() const { return m_dyn_vbuff; } - [[nodiscard]] GfxDynIndexBuffer* get_dyn_ibuff() const { return m_dyn_ibuff; } - [[nodiscard]] GfxDynUniformBuffer* get_dyn_ubuff() const { return m_dyn_ubuff; } [[nodiscard]] int get_size() const { return int(m_batches.size()); } [[nodiscard]] bool is_empty() const { return m_batches.empty(); } private: std::vector m_batches; - GfxDynVertBuffer* m_dyn_vbuff; - GfxDynIndexBuffer* m_dyn_ibuff; - GfxDynUniformBuffer* m_dyn_ubuff; - class GfxDriver* m_gfx_driver; + class GfxDriver* m_gfx_driver; SpinMutex m_mutex; }; @@ -134,7 +127,6 @@ namespace wmoge { class ShaderManager* m_shader_manager = nullptr; class CameraList* m_cameras = nullptr; class GfxDriver* m_driver = nullptr; - class GfxCtx* m_ctx = nullptr; }; }// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/platform/application.cpp b/engine/runtime/platform/application.cpp index 565f0aaac..76f0b1125 100644 --- a/engine/runtime/platform/application.cpp +++ b/engine/runtime/platform/application.cpp @@ -163,11 +163,7 @@ namespace wmoge { }); ioc->bind_f([ioc]() { - return std::shared_ptr(ioc->resolve_v()->driver_wrapper(), [](auto p) {}); - }); - - ioc->bind_f([ioc]() { - return std::shared_ptr(ioc->resolve_v()->ctx_immediate_wrapper(), [](auto p) {}); + return std::shared_ptr(ioc->resolve_v(), [](auto p) {}); }); ioc->bind_f([]() { diff --git a/engine/runtime/render/aux_draw_manager.cpp b/engine/runtime/render/aux_draw_manager.cpp index 17a89a43c..38113baf1 100644 --- a/engine/runtime/render/aux_draw_manager.cpp +++ b/engine/runtime/render/aux_draw_manager.cpp @@ -593,7 +593,7 @@ namespace wmoge { auto engine = Engine::instance(); auto gfx_driver = engine->gfx_driver(); - auto gfx_ctx = engine->gfx_ctx(); + // auto gfx_ctx = engine->gfx_ctx(); // HgfxPassBase pass_lines; // pass_lines.name = SID("aux_draw_lines"); @@ -681,28 +681,28 @@ namespace wmoge { } // flush data - m_lines.flush(gfx_ctx); - m_tria_solid.flush(gfx_ctx); - m_tria_wired.flush(gfx_ctx); - m_text.flush(gfx_ctx); + // m_lines.flush(gfx_ctx); + // m_tria_solid.flush(gfx_ctx); + // m_tria_wired.flush(gfx_ctx); + // m_text.flush(gfx_ctx); // HgfxPass* passes[num_types] = {&pass_lines, &pass_triangles_solid, &pass_triangles_wire, &pass_text}; - gfx_ctx->execute([&]() { - gfx_ctx->begin_render_pass({}, SID("AuxDrawManager::render")); - gfx_ctx->bind_target(window); - gfx_ctx->viewport(viewport); - - // for (int i = 0; i < num_types; i++) { - // // if it has primitives and configured pass - do draw - // if (num_elements[i] > 0 && passes[i] && passes[i]->configure(thread_ctx)) { - // thread_ctx->bind_vert_buffer(*vert_buffers[i], 0, 0); - // thread_ctx->draw(num_vertices[i], 0, 1); - // } - // } - - gfx_ctx->end_render_pass(); - }); + //gfx_ctx->execute([&]() { + // gfx_ctx->begin_render_pass({}, SID("AuxDrawManager::render")); + // gfx_ctx->bind_target(window); + // gfx_ctx->viewport(viewport); + + // for (int i = 0; i < num_types; i++) { + // // if it has primitives and configured pass - do draw + // if (num_elements[i] > 0 && passes[i] && passes[i]->configure(thread_ctx)) { + // thread_ctx->bind_vert_buffer(*vert_buffers[i], 0, 0); + // thread_ctx->draw(num_vertices[i], 0, 1); + // } + // } + + // gfx_ctx->end_render_pass(); + //}); } void AuxDrawManager::flush(float delta_time) { WG_AUTO_PROFILE_RENDER("AuxDrawManager::flush"); diff --git a/engine/runtime/render/canvas.cpp b/engine/runtime/render/canvas.cpp index b81c7a1a7..53d05dc40 100644 --- a/engine/runtime/render/canvas.cpp +++ b/engine/runtime/render/canvas.cpp @@ -28,7 +28,7 @@ #include "canvas.hpp" #include "core/string_utils.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_driver.hpp" #include "grc/texture_manager.hpp" #include "profiler/profiler.hpp" @@ -402,7 +402,6 @@ namespace wmoge { WG_AUTO_PROFILE_RENDER("Canvas::compile"); Engine* engine = Engine::instance(); - GfxCtx* gfx_ctx = engine->gfx_ctx(); GfxDriver* gfx_drvier = engine->gfx_driver(); m_gpu_cmd_buffer.resize(m_cmd_buffer.size()); @@ -420,10 +419,10 @@ namespace wmoge { dst_cmd.Transform2 = Vec4f(t.col(2), 0.0f); } - m_gpu_cmd_buffer.flush(gfx_ctx); - m_vtx_buffer.flush(gfx_ctx); - m_idx_buffer.flush(gfx_ctx); - m_prx_buffer.flush(gfx_ctx); + // m_gpu_cmd_buffer.flush(gfx_ctx); + // m_vtx_buffer.flush(gfx_ctx); + // m_idx_buffer.flush(gfx_ctx); + // m_prx_buffer.flush(gfx_ctx); GfxDescSetResources resources; { @@ -463,43 +462,42 @@ namespace wmoge { } Engine* engine = Engine::instance(); - GfxCtx* gfx_ctx = engine->gfx_ctx(); GfxDriver* gfx_drvier = engine->gfx_driver(); - ShaderCanvas::Params& params = *((ShaderCanvas::Params*) gfx_ctx->map_uniform_buffer(m_params)); - { - params.ClipProjView = (gfx_drvier->clip_matrix() * Math3d::orthographic(area.x(), area.z(), area.y(), area.w(), -1.0f, 1.0f)).transpose(); - params.InverseGamma = 1.0f / gamma; - } - gfx_ctx->unmap_uniform_buffer(m_params); - - gfx_ctx->execute([&]() { - gfx_ctx->begin_render_pass({}, SID("Canvas::render")); - gfx_ctx->bind_target(window); - gfx_ctx->clear(0, Color::BLACK4f);// todo: remove - gfx_ctx->viewport(viewport); - - if (false /* thread_ctx->bind_pso(m_shared->pipeline_srgb) */) { - gfx_ctx->bind_desc_set(m_params_set, ShaderCanvas::PARAMS_SET); - - const int num_cmds = int(m_gpu_cmd_buffer.get_size()); - for (int cmd_id = 0; cmd_id < num_cmds; cmd_id++) { - const CanvasDrawCmd& cmd = m_cmd_buffer[cmd_id]; - - if (cmd.elements > 0) { - const int tex_set_idx = cmd.texture_idx >= 0 ? cmd.texture_idx / MAX_CANVAS_IMAGES : 0; - - gfx_ctx->bind_desc_set(m_shared->tex_sets[tex_set_idx], ShaderCanvas::CANVASIMAGE0_SET); - gfx_ctx->bind_vert_buffer(m_vtx_buffer.get_buffer(), 0); - gfx_ctx->bind_vert_buffer(m_prx_buffer.get_buffer(), 1, int(cmd_id * sizeof(int))); - gfx_ctx->bind_index_buffer(m_idx_buffer.get_buffer(), GfxIndexType::Uint32, int(cmd.idx_offset * sizeof(std::uint32_t))); - gfx_ctx->draw_indexed(cmd.elements * 3, 0, 1); - } - } - } - - gfx_ctx->end_render_pass(); - }); + // ShaderCanvas::Params& params = *((ShaderCanvas::Params*) gfx_ctx->map_uniform_buffer(m_params)); + // { + // params.ClipProjView = (gfx_drvier->clip_matrix() * Math3d::orthographic(area.x(), area.z(), area.y(), area.w(), -1.0f, 1.0f)).transpose(); + // params.InverseGamma = 1.0f / gamma; + // } + // gfx_ctx->unmap_uniform_buffer(m_params); + + // gfx_ctx->execute([&]() { + // gfx_ctx->begin_render_pass({}, SID("Canvas::render")); + // gfx_ctx->bind_target(window); + // gfx_ctx->clear(0, Color::BLACK4f);// todo: remove + // gfx_ctx->viewport(viewport); + + // if (false /* thread_ctx->bind_pso(m_shared->pipeline_srgb) */) { + // gfx_ctx->bind_desc_set(m_params_set, ShaderCanvas::PARAMS_SET); + + // const int num_cmds = int(m_gpu_cmd_buffer.get_size()); + // for (int cmd_id = 0; cmd_id < num_cmds; cmd_id++) { + // const CanvasDrawCmd& cmd = m_cmd_buffer[cmd_id]; + + // if (cmd.elements > 0) { + // const int tex_set_idx = cmd.texture_idx >= 0 ? cmd.texture_idx / MAX_CANVAS_IMAGES : 0; + + // gfx_ctx->bind_desc_set(m_shared->tex_sets[tex_set_idx], ShaderCanvas::CANVASIMAGE0_SET); + // gfx_ctx->bind_vert_buffer(m_vtx_buffer.get_buffer(), 0); + // gfx_ctx->bind_vert_buffer(m_prx_buffer.get_buffer(), 1, int(cmd_id * sizeof(int))); + // gfx_ctx->bind_index_buffer(m_idx_buffer.get_buffer(), GfxIndexType::Uint32, int(cmd.idx_offset * sizeof(std::uint32_t))); + // gfx_ctx->draw_indexed(cmd.elements * 3, 0, 1); + // } + // } + // } + + // gfx_ctx->end_render_pass(); + // }); } void Canvas::set_texture() { diff --git a/engine/runtime/render/deferred_pipeline.cpp b/engine/runtime/render/deferred_pipeline.cpp index 8aea00ddf..35b73c365 100644 --- a/engine/runtime/render/deferred_pipeline.cpp +++ b/engine/runtime/render/deferred_pipeline.cpp @@ -50,17 +50,12 @@ namespace wmoge { const int view_count = int(m_views.size()); Engine* engine = Engine::instance(); - GfxCtx* gfx_ctx = engine->gfx_ctx(); - - WG_GFX_LABEL(gfx_ctx, SID("DeferredPipeline::exectute")); for (int i = view_count - 1; i >= 0; i--) { WG_AUTO_PROFILE_RENDER("Render view=" + StringUtils::from_int(i)); const int view_idx = i; const CameraData& camera = m_cameras->data_at(view_idx); - - WG_GFX_LABEL(gfx_ctx, SID("Render view=" + StringUtils::from_int(view_idx))); } } diff --git a/engine/runtime/render/graphics_pipeline.hpp b/engine/runtime/render/graphics_pipeline.hpp index 7fa2b7afa..b8313a7fd 100644 --- a/engine/runtime/render/graphics_pipeline.hpp +++ b/engine/runtime/render/graphics_pipeline.hpp @@ -30,7 +30,7 @@ #include "asset/asset_ref.hpp" #include "core/array_view.hpp" #include "gfx/gfx_buffers.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_driver.hpp" #include "gfx/gfx_texture.hpp" #include "grc/texture.hpp" diff --git a/engine/runtime/render/render_engine.cpp b/engine/runtime/render/render_engine.cpp index 6e0729012..c3c3c96f9 100644 --- a/engine/runtime/render/render_engine.cpp +++ b/engine/runtime/render/render_engine.cpp @@ -48,7 +48,7 @@ namespace wmoge { m_fullscreen_tria[1].uv = Vec2f(0, 2); m_fullscreen_tria[2].pos = Vec2f(3, -1); m_fullscreen_tria[2].uv = Vec2f(2, 0); - m_fullscreen_tria.flush(Engine::instance()->gfx_ctx()); + // m_fullscreen_tria.flush(); } void RenderEngine::set_time(float time) { @@ -81,101 +81,101 @@ namespace wmoge { WG_AUTO_PROFILE_RENDER("RenderEngine::prepare_frame_data"); GfxDriver* gfx_driver = Engine::instance()->gfx_driver(); - GfxCtx* gfx_ctx = Engine::instance()->gfx_ctx(); - - if (!m_frame_data) { - m_frame_data = gfx_driver->make_uniform_buffer(int(sizeof(GPUFrameData)), GfxMemUsage::GpuLocal, SID("frame_data")); - } - - GPUFrameData& frame_data = *((GPUFrameData*) gfx_ctx->map_uniform_buffer(m_frame_data)); - { - frame_data.time = m_time; - frame_data.timeDelta = m_delta_time; - frame_data._fd_pad0 = 0.0f; - frame_data._fd_pad1 = 0.0f; - } - gfx_ctx->unmap_uniform_buffer(m_frame_data); + // GfxCtx* gfx_ctx = Engine::instance()->gfx_ctx(); + + // if (!m_frame_data) { + // m_frame_data = gfx_driver->make_uniform_buffer(int(sizeof(GPUFrameData)), GfxMemUsage::GpuLocal, SID("frame_data")); + // } + + // GPUFrameData& frame_data = *((GPUFrameData*) gfx_ctx->map_uniform_buffer(m_frame_data)); + // { + // frame_data.time = m_time; + // frame_data.timeDelta = m_delta_time; + // frame_data._fd_pad0 = 0.0f; + // frame_data._fd_pad1 = 0.0f; + // } + // gfx_ctx->unmap_uniform_buffer(m_frame_data); } void RenderEngine::allocate_veiws() { WG_AUTO_PROFILE_RENDER("RenderEngine::allocate_veiws"); GfxDriver* gfx_driver = Engine::instance()->gfx_driver(); - GfxCtx* gfx_ctx = Engine::instance()->gfx_ctx(); - Mat4x4f gfx_clip = gfx_driver->clip_matrix(); - - for (int view_idx = 0; view_idx < int(m_cameras.get_size()); view_idx++) { - RenderView& view = m_views[view_idx]; - view.index = view_idx; - - const CameraData& camera = m_cameras.data_at(view_idx); - - if (!view.view_data) { - view.view_data = gfx_driver->make_uniform_buffer(int(sizeof(GPUViewData)), GfxMemUsage::GpuLocal, SID("view_data_" + StringUtils::from_int(view_idx))); - } - - GPUViewData& view_data = *((GPUViewData*) gfx_ctx->map_uniform_buffer(view.view_data)); - { - view_data.Clip = gfx_clip.transpose(); - view_data.Proj = camera.proj.transpose(); - view_data.View = camera.view.transpose(); - view_data.ProjView = camera.proj_view.transpose(); - view_data.ClipProjView = (gfx_clip * camera.proj_view).transpose(); - view_data.ProjPrev = camera.proj_prev.transpose(); - view_data.ViewPrev = camera.view_prev.transpose(); - view_data.ProjViewPrev = camera.proj_view_prev.transpose(); - view_data.ClipProjViewPrev = (gfx_clip * camera.proj_view_prev).transpose(); - view_data.Movement = Vec4f(camera.movement, 0.0f); - view_data.Position = Vec4f(camera.position, 0.0f); - view_data.Direction = Vec4f(camera.direction, 0.0f); - view_data.Up = Vec4f(camera.up, 0.0f); - view_data.PositionPrev = Vec4f(camera.position_prev, 0.0f); - view_data.DirectionPrev = Vec4f(camera.direction_prev, 0.0f); - view_data.UpPrev = Vec4f(camera.up_prev, 0.0f); - view_data.Viewport = camera.viewport; - view_data.CamIdx = view_idx; - view_data._vd_pad0 = 0; - view_data._vd_pad1 = 0; - view_data._vd_pad2 = 0; - } - gfx_ctx->unmap_uniform_buffer(view.view_data); - - GfxDescSetResources view_resources; - { - { - auto& r = view_resources.emplace_back(); - r.first.type = GfxBindingType::UniformBuffer; - r.first.binding = ShaderMaterial::FRAMEDATA_SLOT; - r.first.array_element = 0; - r.second.resource = m_frame_data.as(); - r.second.offset = 0; - r.second.range = m_frame_data->size(); - } - { - auto& r = view_resources.emplace_back(); - r.first.type = GfxBindingType::UniformBuffer; - r.first.binding = ShaderMaterial::VIEWDATA_SLOT; - r.first.array_element = 0; - r.second.resource = view.view_data.as(); - r.second.offset = 0; - r.second.range = view.view_data->size(); - } - { - auto& r = view_resources.emplace_back(); - r.first.type = GfxBindingType::StorageBuffer; - r.first.binding = ShaderMaterial::RENDEROBJECTSDATA_SLOT; - r.first.array_element = 0; - r.second.resource = m_scene->get_objects_gpu_data().get_buffer().as(); - r.second.offset = 0; - r.second.range = m_scene->get_objects_gpu_data().get_buffer()->size(); - } - } - // view.view_set = gfx_driver->make_desc_set(view_resources, SID("view_set_" + StringUtils::from_int(view_idx))); - - for (RenderQueue& queue : view.queues) { - queue.clear(); - } - } + // GfxCtx* gfx_ctx = Engine::instance()->gfx_ctx(); + // Mat4x4f gfx_clip = gfx_driver->clip_matrix(); + + // for (int view_idx = 0; view_idx < int(m_cameras.get_size()); view_idx++) { + // RenderView& view = m_views[view_idx]; + // view.index = view_idx; + + // const CameraData& camera = m_cameras.data_at(view_idx); + + // if (!view.view_data) { + // view.view_data = gfx_driver->make_uniform_buffer(int(sizeof(GPUViewData)), GfxMemUsage::GpuLocal, SID("view_data_" + StringUtils::from_int(view_idx))); + // } + + // GPUViewData& view_data = *((GPUViewData*) gfx_ctx->map_uniform_buffer(view.view_data)); + // { + // view_data.Clip = gfx_clip.transpose(); + // view_data.Proj = camera.proj.transpose(); + // view_data.View = camera.view.transpose(); + // view_data.ProjView = camera.proj_view.transpose(); + // view_data.ClipProjView = (gfx_clip * camera.proj_view).transpose(); + // view_data.ProjPrev = camera.proj_prev.transpose(); + // view_data.ViewPrev = camera.view_prev.transpose(); + // view_data.ProjViewPrev = camera.proj_view_prev.transpose(); + // view_data.ClipProjViewPrev = (gfx_clip * camera.proj_view_prev).transpose(); + // view_data.Movement = Vec4f(camera.movement, 0.0f); + // view_data.Position = Vec4f(camera.position, 0.0f); + // view_data.Direction = Vec4f(camera.direction, 0.0f); + // view_data.Up = Vec4f(camera.up, 0.0f); + // view_data.PositionPrev = Vec4f(camera.position_prev, 0.0f); + // view_data.DirectionPrev = Vec4f(camera.direction_prev, 0.0f); + // view_data.UpPrev = Vec4f(camera.up_prev, 0.0f); + // view_data.Viewport = camera.viewport; + // view_data.CamIdx = view_idx; + // view_data._vd_pad0 = 0; + // view_data._vd_pad1 = 0; + // view_data._vd_pad2 = 0; + // } + // gfx_ctx->unmap_uniform_buffer(view.view_data); + + // GfxDescSetResources view_resources; + // { + // { + // auto& r = view_resources.emplace_back(); + // r.first.type = GfxBindingType::UniformBuffer; + // r.first.binding = ShaderMaterial::FRAMEDATA_SLOT; + // r.first.array_element = 0; + // r.second.resource = m_frame_data.as(); + // r.second.offset = 0; + // r.second.range = m_frame_data->size(); + // } + // { + // auto& r = view_resources.emplace_back(); + // r.first.type = GfxBindingType::UniformBuffer; + // r.first.binding = ShaderMaterial::VIEWDATA_SLOT; + // r.first.array_element = 0; + // r.second.resource = view.view_data.as(); + // r.second.offset = 0; + // r.second.range = view.view_data->size(); + // } + // { + // auto& r = view_resources.emplace_back(); + // r.first.type = GfxBindingType::StorageBuffer; + // r.first.binding = ShaderMaterial::RENDEROBJECTSDATA_SLOT; + // r.first.array_element = 0; + // r.second.resource = m_scene->get_objects_gpu_data().get_buffer().as(); + // r.second.offset = 0; + // r.second.range = m_scene->get_objects_gpu_data().get_buffer()->size(); + // } + // } + // // view.view_set = gfx_driver->make_desc_set(view_resources, SID("view_set_" + StringUtils::from_int(view_idx))); + + // for (RenderQueue& queue : view.queues) { + // queue.clear(); + // } + // } } void RenderEngine::compile_batches() { @@ -242,7 +242,7 @@ namespace wmoge { void RenderEngine::flush_buffers() { WG_AUTO_PROFILE_RENDER("RenderEngine::flush_buffers"); - m_scene->flush_buffers(Engine::instance()->gfx_ctx()); + // m_scene->flush_buffers(Engine::instance()->gfx_ctx()); } void RenderEngine::render_canvas(Canvas& canvas, const Vec4f& area) { diff --git a/engine/runtime/render/render_queue.cpp b/engine/runtime/render/render_queue.cpp index 8c4053da7..6b67794b6 100644 --- a/engine/runtime/render/render_queue.cpp +++ b/engine/runtime/render/render_queue.cpp @@ -59,7 +59,7 @@ namespace wmoge { std::sort(m_queue.begin(), m_queue.end()); } - int RenderQueue::execute(GfxCtx* gfx_ctx) const { + int RenderQueue::execute(GfxCmdList& cmd_list) const { WG_AUTO_PROFILE_RENDER("RenderQueue::execute"); int num_executed = 0; @@ -67,41 +67,41 @@ namespace wmoge { GfxPsoGraphics* bound_pipeline = nullptr; - for (int i = 0; i < num_total; i++) { - const SortableRenderCmd& sortable_cmd = m_queue[i]; - const RenderCmd& cmd = *sortable_cmd.cmd; - - const GfxVertBuffersSetup& vert_buffers = cmd.vert_buffers; - const GfxIndexBufferSetup& index_setup = cmd.index_setup; - const GfxDrawCall& call_params = cmd.call_params; - - if (bound_pipeline != cmd.pipeline) { - if (false /* !gfx_ctx->bind_pso(Ref(cmd.pipeline)) */) { - continue; - } - bound_pipeline = cmd.pipeline; - } - - for (int i = 0; i < RenderCmd::NUM_DESC_SETS; i++) { - if (cmd.desc_sets[i] && cmd.desc_sets_slots[i] >= 0) { - gfx_ctx->bind_desc_set(Ref(cmd.desc_sets[i]), cmd.desc_sets_slots[i]); - } - } - - for (int i = 0; i < GfxLimits::MAX_VERT_BUFFERS; i++) { - if (!vert_buffers.buffers[i]) { break; } - gfx_ctx->bind_vert_buffer(Ref(vert_buffers.buffers[i]), i, vert_buffers.offsets[i]); - } - - if (cmd.index_setup.buffer) { - gfx_ctx->bind_index_buffer(Ref(index_setup.buffer), index_setup.index_type, index_setup.offset); - gfx_ctx->draw_indexed(call_params.count, call_params.base, call_params.instances); - } else { - gfx_ctx->draw(call_params.count, call_params.base, call_params.instances); - } - - num_executed += 1; - } + // for (int i = 0; i < num_total; i++) { + // const SortableRenderCmd& sortable_cmd = m_queue[i]; + // const RenderCmd& cmd = *sortable_cmd.cmd; + + // const GfxVertBuffersSetup& vert_buffers = cmd.vert_buffers; + // const GfxIndexBufferSetup& index_setup = cmd.index_setup; + // const GfxDrawCall& call_params = cmd.call_params; + + // if (bound_pipeline != cmd.pipeline) { + // if (false /* !gfx_ctx->bind_pso(Ref(cmd.pipeline)) */) { + // continue; + // } + // bound_pipeline = cmd.pipeline; + // } + + // for (int i = 0; i < RenderCmd::NUM_DESC_SETS; i++) { + // if (cmd.desc_sets[i] && cmd.desc_sets_slots[i] >= 0) { + // gfx_ctx->bind_desc_set(Ref(cmd.desc_sets[i]), cmd.desc_sets_slots[i]); + // } + // } + + // for (int i = 0; i < GfxLimits::MAX_VERT_BUFFERS; i++) { + // if (!vert_buffers.buffers[i]) { break; } + // gfx_ctx->bind_vert_buffer(Ref(vert_buffers.buffers[i]), i, vert_buffers.offsets[i]); + // } + + // if (cmd.index_setup.buffer) { + // gfx_ctx->bind_index_buffer(Ref(index_setup.buffer), index_setup.index_type, index_setup.offset); + // gfx_ctx->draw_indexed(call_params.count, call_params.base, call_params.instances); + // } else { + // gfx_ctx->draw(call_params.count, call_params.base, call_params.instances); + // } + + // num_executed += 1; + // } return num_executed; } diff --git a/engine/runtime/render/render_queue.hpp b/engine/runtime/render/render_queue.hpp index 40d84537b..82c3bc6a2 100644 --- a/engine/runtime/render/render_queue.hpp +++ b/engine/runtime/render/render_queue.hpp @@ -32,7 +32,7 @@ #include "core/pool_vector.hpp" #include "core/synchronization.hpp" #include "gfx/gfx_buffers.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_defs.hpp" #include "gfx/gfx_desc_set.hpp" #include "gfx/gfx_pipeline.hpp" @@ -141,7 +141,7 @@ namespace wmoge { void push(const SortableRenderCmd& cmd); void clear(); void sort(); - int execute(GfxCtx* gfx_ctx) const; + int execute(GfxCmdList& cmd_list) const; [[nodiscard]] std::vector& get_queue(); [[nodiscard]] const SortableRenderCmd& get_cmd(std::size_t index) const; diff --git a/engine/runtime/render/render_scene.cpp b/engine/runtime/render/render_scene.cpp index eaaf0ac93..48067e5c1 100644 --- a/engine/runtime/render/render_scene.cpp +++ b/engine/runtime/render/render_scene.cpp @@ -27,7 +27,7 @@ #include "render_scene.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "profiler/profiler.hpp" #include @@ -39,11 +39,11 @@ namespace wmoge { m_objects_ids.set_name(SID("objects_ids")); } - void RenderScene::flush_buffers(GfxCtx* gfx_ctx) { - WG_AUTO_PROFILE_RENDER("RenderScene::flush_buffers"); + // void RenderScene::flush_buffers(GfxCmdList* gfx_ctx) { + // WG_AUTO_PROFILE_RENDER("RenderScene::flush_buffers"); - m_objects_gpu_data.flush(gfx_ctx); - m_objects_ids.flush(gfx_ctx); - } + // m_objects_gpu_data.flush(gfx_ctx); + // m_objects_ids.flush(gfx_ctx); + // } }// namespace wmoge \ No newline at end of file diff --git a/engine/runtime/render/render_scene.hpp b/engine/runtime/render/render_scene.hpp index 5c085f10f..7d3f2c621 100644 --- a/engine/runtime/render/render_scene.hpp +++ b/engine/runtime/render/render_scene.hpp @@ -70,7 +70,7 @@ namespace wmoge { public: RenderScene(); - void flush_buffers(class GfxCtx* gfx_ctx); + // void flush_buffers(class GfxCmdList* gfx_ctx); [[nodiscard]] MeshBucketMap& get_bucket_map(MeshPassType pass_type) { return m_bucket_map[int(pass_type)]; } [[nodiscard]] GPURenderObjectDataVector& get_objects_gpu_data() { return m_objects_gpu_data; } diff --git a/engine/runtime/scene/scene_manager.cpp b/engine/runtime/scene/scene_manager.cpp index 720486aa9..987b3e25f 100644 --- a/engine/runtime/scene/scene_manager.cpp +++ b/engine/runtime/scene/scene_manager.cpp @@ -30,7 +30,7 @@ #include "core/async.hpp" #include "core/task_parallel_for.hpp" #include "ecs/ecs_registry.hpp" -#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_cmd_list.hpp" #include "gfx/gfx_driver.hpp" #include "platform/time.hpp" #include "platform/window.hpp" @@ -211,7 +211,7 @@ namespace wmoge { RenderEngine* render_engine;// = engine->render_engine(); - // GfxCtx* gfx_ctx; // = engine->gfx_ctx(); + // GfxCmdList* gfx_ctx; // = engine->gfx_ctx(); // WindowManager* window_manager;// = engine->window_manager(); // Ref window; // = window_manager->primary_window(); diff --git a/engine/runtime/scripting/script_instance.hpp b/engine/runtime/scripting/script_instance.hpp index 84c51f346..b036b7fdf 100644 --- a/engine/runtime/scripting/script_instance.hpp +++ b/engine/runtime/scripting/script_instance.hpp @@ -80,7 +80,7 @@ namespace wmoge { virtual void on_scene_enter() {} virtual void on_scene_exit() {} virtual void on_transform_updated() {} - virtual void on_update(float delta_time){}; + virtual void on_update(float delta_time) {}; virtual void on_signal(const Strid& signal) {} virtual void on_input_mouse(const Ref& event) {} virtual void on_input_keyboard(const Ref& event) {} diff --git a/engine/runtime/system/engine.cpp b/engine/runtime/system/engine.cpp index ab98d3c77..602f68447 100644 --- a/engine/runtime/system/engine.cpp +++ b/engine/runtime/system/engine.cpp @@ -131,7 +131,6 @@ namespace wmoge { WG_LOG_INFO("init window " << window_info.id); m_gfx_driver = ioc->resolve_v(); - m_gfx_ctx = ioc->resolve_v(); m_shader_manager = ioc->resolve_v(); m_shader_manager->load_compilers(); @@ -171,6 +170,7 @@ namespace wmoge { WG_AUTO_PROFILE_SYSTEM("Engine::iteration"); m_time->tick(); + m_frame_id = m_time->get_iteration(); auto windows = m_window_manager->windows(); @@ -178,11 +178,7 @@ namespace wmoge { layer->on_start_frame(); }); - m_gfx_driver->begin_frame(); - - for (auto& w : windows) { - m_gfx_driver->prepare_window(w); - } + m_gfx_driver->begin_frame(m_frame_id, windows); if (m_event_manager) { m_event_manager->flush(); @@ -200,17 +196,13 @@ namespace wmoge { layer->on_debug_draw(); }); - m_gfx_driver->end_frame(); - m_layer_stack->each_down([](LayerStack::LayerPtr& layer) { layer->on_end_frame(); }); m_window_manager->poll_events(); - for (auto& w : windows) { - m_gfx_driver->swap_buffers(w); - } + m_gfx_driver->end_frame(true); return WG_OK; } @@ -253,7 +245,6 @@ namespace wmoge { WindowManager* Engine::window_manager() { return m_window_manager; } Input* Engine::input() { return m_input; } GfxDriver* Engine::gfx_driver() { return m_gfx_driver; } - GfxCtx* Engine::gfx_ctx() { return m_gfx_ctx; } ShaderManager* Engine::shader_manager() { return m_shader_manager; } ShaderLibrary* Engine::shader_library() { return m_shader_library; } PsoCache* Engine::pso_cache() { return m_pso_cache; } diff --git a/engine/runtime/system/engine.hpp b/engine/runtime/system/engine.hpp index 4240a0ad3..7109a861c 100644 --- a/engine/runtime/system/engine.hpp +++ b/engine/runtime/system/engine.hpp @@ -75,7 +75,6 @@ namespace wmoge { class WindowManager* window_manager(); class Input* input(); class GfxDriver* gfx_driver(); - class GfxCtx* gfx_ctx(); class ShaderManager* shader_manager(); class ShaderLibrary* shader_library(); class PsoCache* pso_cache(); @@ -98,6 +97,7 @@ namespace wmoge { private: std::atomic_bool m_close_requested{false}; + std::size_t m_frame_id = 0; class Application* m_application = nullptr; class RttiTypeStorage* m_type_storage = nullptr; @@ -117,7 +117,6 @@ namespace wmoge { class WindowManager* m_window_manager = nullptr; class Input* m_input = nullptr; class GfxDriver* m_gfx_driver = nullptr; - class GfxCtx* m_gfx_ctx = nullptr; class ShaderManager* m_shader_manager = nullptr; class ShaderLibrary* m_shader_library = nullptr; class PsoCache* m_pso_cache = nullptr; diff --git a/scripts/loc.py b/scripts/loc.py index 4061e1e4a..8e904f8aa 100644 --- a/scripts/loc.py +++ b/scripts/loc.py @@ -25,7 +25,9 @@ def visit(directory): def main(): parser = argparse.ArgumentParser("Count `loc` in directory recursively") - parser.add_argument("--dir", help="directory to count loc", default="./engine") + parser.add_argument( + "--dir", help="directory to count loc", default="./engine/runtime" + ) args = parser.parse_args() loc = visit(ROOT / args.dir) diff --git a/template/main.cpp b/template/main.cpp index 4b009b0a5..33c82a577 100644 --- a/template/main.cpp +++ b/template/main.cpp @@ -145,7 +145,7 @@ class TemplateApplication : public GameApplication { ShaderParamBlock block(*shader, 0, SID("canvas")); block.set_var(p_clip_proj_view, Math3d::perspective(1.0f, 1.0f, 0.1f, 100000.f)); block.set_var(p_inverse_gamma, 1.0f / 4.0f); - block.validate(Engine::instance()->gfx_driver(), Engine::instance()->gfx_ctx()); + // block.validate(Engine::instance()->gfx_driver(), Engine::instance()->gfx_ctx()); Engine* engine = Engine::instance();