diff --git a/modules/renderer/components.cppm b/modules/renderer/components.cppm index a1fe2d9..175e9bb 100644 --- a/modules/renderer/components.cppm +++ b/modules/renderer/components.cppm @@ -4,21 +4,23 @@ import math.vec3; import memory.reference; import std; -namespace lt::renderer::components { +export namespace lt::renderer::components { -export enum class VertexFormat: std::uint8_t { +enum class VertexFormat : std::uint8_t +{ r32_g32_b32_sfloat, r32_g32_sfloat, }; -export enum class VertexInputRate: std::uint8_t { +enum class VertexInputRate : std::uint8_t +{ per_vertex, per_instance, }; -export struct VertexInputAttributeDescriptipn +struct VertexInputAttributeDescriptipn { std::uint32_t location; @@ -29,7 +31,7 @@ export struct VertexInputAttributeDescriptipn VertexFormat format; }; -export struct VertexInputBindingDescription +struct VertexInputBindingDescription { std::uint32_t binding; @@ -37,7 +39,7 @@ export struct VertexInputBindingDescription }; /** Requires a math::components::Transform component on the same entity to be functional. */ -export struct Sprite +struct Sprite { struct Vertex { @@ -52,7 +54,7 @@ export struct Sprite VertexInputAttributeDescriptipn { .location = 0u, .binding = 0u, - .offset = offsetof(Sprite::Vertex, position), + .offset = 0u, .format = VertexFormat::r32_g32_b32_sfloat, }, @@ -60,7 +62,7 @@ export struct Sprite VertexInputAttributeDescriptipn { .location = 1u, .binding = 0u, - .offset = offsetof(Sprite::Vertex, color), + .offset = sizeof(math::vec3), .format = VertexFormat::r32_g32_b32_sfloat, }, }; diff --git a/modules/renderer/factory.cppm b/modules/renderer/factory.cppm index 757c30a..e1ed19f 100644 --- a/modules/renderer/factory.cppm +++ b/modules/renderer/factory.cppm @@ -5,9 +5,11 @@ import renderer.backend.vk.device; import renderer.vk.pass; import renderer.backend.vk.instance; import renderer.backend.vk.swapchain; +import renderer.vk.renderer; import renderer.backend.vk.buffer; import renderer.backend.vk.gpu; import renderer.backend.vk.surface; +import renderer.vk.renderer; import memory.scope; import debug.assertions; import ecs.entity; @@ -35,6 +37,14 @@ export namespace lt::renderer { const lt::assets::ShaderAsset &fragment_shader ) -> memory::Scope; +[[nodiscard]] auto create_renderer( + Api target_api, + IGpu *gpu, + IDevice *device, + ISwapchain *swapchain, + std::uint32_t max_frames_in_flight +) -> memory::Scope + } // namespace lt::renderer module :private; @@ -147,59 +157,62 @@ using namespace lt::renderer; } } -// [[nodiscard]] /* static */ auto IRenderer::create( -// Api target_api, -// IGpu *gpu, -// IDevice *device, -// ISwapchain *swapchain, -// uint32_t max_frames_in_flight -// ) -> memory::Scope -// { -// ensure(gpu, "Failed to create renderer::IRenderer: null gpu"); -// ensure(device, "Failed to create renderer::IRenderer: null device"); -// ensure(swapchain, "Failed to create renderer::IRenderer: null swapchain"); -// ensure( -// std::clamp(max_frames_in_flight, frames_in_flight_lower_limit, frames_in_flight_upper_limit) -// == max_frames_in_flight, -// "Failed to initialize renderer::System: max_frames_in_flight ({}) not within bounds ({} -> " -// "{}) ", -// max_frames_in_flight, -// frames_in_flight_lower_limit, -// frames_in_flight_upper_limit -// ); -// -// -// switch (target_api) -// { -// case Api::vulkan: -// return memory::create_scope(gpu, device, swapchain, max_frames_in_flight); -// case Api::none: -// case Api::metal: -// case Api::direct_x: throw std::runtime_error { "Invalid API" }; -// } -// } +[[nodiscard]] auto create_renderer( + Api target_api, + IGpu *gpu, + IDevice *device, + ISwapchain *swapchain, + std::uint32_t max_frames_in_flight +) -> memory::Scope +{ + debug::ensure(gpu, "Failed to create renderer::IRenderer: null gpu"); + debug::ensure(device, "Failed to create renderer::IRenderer: null device"); + debug::ensure(swapchain, "Failed to create renderer::IRenderer: null swapchain"); + debug::ensure( + std::clamp( + max_frames_in_flight, + IRenderer::frames_in_flight_lower_limit, + IRenderer::frames_in_flight_upper_limit + ) == max_frames_in_flight, + "Failed to initialize renderer::System: max_frames_in_flight ({}) not within bounds ({} -> " + "{}) ", + max_frames_in_flight, + IRenderer::frames_in_flight_lower_limit, + IRenderer::frames_in_flight_upper_limit + ); -// [[nodiscard]] /* static */ auto IDebugger::create( -// Api target_api, -// IInstance *instance, -// CreateInfo info -// ) -> memory::Scope -// { -// debug::ensure( -// info.severities != MessageSeverity::none, -// "Failed to create vk::Messenger: severities == none" -// ); -// -// debug::ensure(info.types != MessageType::none, "Failed to create vk::Messenger: types == none"); -// -// debug::ensure(info.callback, "Failed to create vk::Messenger: null callback"); -// -// switch (target_api) -// { -// case Api::vulkan: return memory::create_scope(instance, std::move(info)); -// case Api::none: -// case Api::metal: -// case Api::direct_x: throw std::runtime_error { "Invalid API" }; -// } -// } + switch (target_api) + { + case Api::vulkan: + return memory::create_scope(gpu, device, swapchain, max_frames_in_flight); + case Api::none: + case Api::metal: + case Api::direct_x: throw std::runtime_error { "Invalid API" }; + } +} + + +[[nodiscard]] /* static */ auto IDebugger::create( + Api target_api, + IInstance *instance, + CreateInfo info +) -> memory::Scope +{ + debug::ensure( + info.severities != MessageSeverity::none, + "Failed to create vk::Messenger: severities == none" + ); + + debug::ensure(info.types != MessageType::none, "Failed to create vk::Messenger: types == none"); + + debug::ensure(info.callback, "Failed to create vk::Messenger: null callback"); + + switch (target_api) + { + case Api::vulkan: return memory::create_scope(instance, std::move(info)); + case Api::none: + case Api::metal: + case Api::direct_x: throw std::runtime_error { "Invalid API" }; + } +} diff --git a/modules/renderer/frontends.cppm b/modules/renderer/frontends.cppm index 3052730..01e366e 100644 --- a/modules/renderer/frontends.cppm +++ b/modules/renderer/frontends.cppm @@ -1,4 +1,7 @@ export module renderer.frontend; +import renderer.data; +import renderer.components; +import math.components; import assets.shader; import ecs.entity; import math.vec2; @@ -129,13 +132,6 @@ public: std::size_t size; }; - [[nodiscard]] static auto create( - Api target_api, - class IDevice *device, - class IGpu *gpu, - const CreateInfo &info - ) -> memory::Scope; - IBuffer() = default; virtual ~IBuffer() = default; @@ -160,13 +156,6 @@ private: class IPass { public: - [[nodiscard]] static auto create( - lt::renderer::Api target_api, - class IDevice *device, - const class lt::assets::ShaderAsset &vertex_shader, - const class lt::assets::ShaderAsset &fragment_shader - ) -> memory::Scope; - IPass() = default; virtual ~IPass() = default; @@ -180,52 +169,43 @@ public: auto operator=(const IPass &) -> IPass & = delete; }; -// class IRenderer -// { -// public: -// static constexpr auto frames_in_flight_upper_limit = 5u; -// -// static constexpr auto frames_in_flight_lower_limit = 1u; -// -// enum class Result : uint8_t -// { -// success = 0, -// invalid_swapchain, -// error, -// }; -// -// [[nodiscard]] static auto create( -// Api target_api, -// class IGpu *gpu, -// class IDevice *device, -// class ISwapchain *swapchain, -// uint32_t max_frames_in_flight -// ) -> memory::Scope; -// -// IRenderer() = default; -// -// virtual ~IRenderer() = default; -// -// IRenderer(IRenderer &&) = default; -// -// IRenderer(const IRenderer &) = delete; -// -// auto operator=(IRenderer &&) -> IRenderer & = default; -// -// auto operator=(const IRenderer &) -> IRenderer & = delete; -// -// virtual auto frame(uint32_t frame_idx, std::function submit_scene) -> Result = 0; -// -// virtual void replace_swapchain(class ISwapchain *swapchain) = 0; -// -// virtual void set_frame_constants(FrameConstants constants) = 0; -// -// virtual void submit_sprite( -// const components::Sprite &sprite, -// const math::components::Transform &transform -// ) = 0; -// }; +class IRenderer +{ +public: + static constexpr auto frames_in_flight_upper_limit = 5u; + static constexpr auto frames_in_flight_lower_limit = 1u; + + enum class Result : std::uint8_t + { + success = 0, + invalid_swapchain, + error, + }; + + IRenderer() = default; + + virtual ~IRenderer() = default; + + IRenderer(IRenderer &&) = default; + + IRenderer(const IRenderer &) = delete; + + auto operator=(IRenderer &&) -> IRenderer & = default; + + auto operator=(const IRenderer &) -> IRenderer & = delete; + + virtual auto frame(std::uint32_t frame_idx, std::function submit_scene) -> Result = 0; + + virtual void replace_swapchain(class ISwapchain *swapchain) = 0; + + virtual void set_frame_constants(FrameConstants constants) = 0; + + virtual void submit_sprite( + const components::Sprite &sprite, + const math::components::Transform &transform + ) = 0; +}; // class IDebugger // { diff --git a/modules/renderer/vk/api_wrapper.cppm b/modules/renderer/vk/api_wrapper.cppm index 7616e9d..b199653 100644 --- a/modules/renderer/vk/api_wrapper.cppm +++ b/modules/renderer/vk/api_wrapper.cppm @@ -1116,83 +1116,6 @@ private: VkInstance m_instance {}; }; -class Semaphore -{ -public: - friend class Device; - friend class Queue; - - Semaphore() = default; - - Semaphore(Semaphore &&) = default; - - Semaphore(const Semaphore &) = delete; - - auto operator=(Semaphore &&) -> Semaphore & = default; - - auto operator=(const Semaphore &) -> Semaphore & = delete; - - ~Semaphore(); - - auto operator&() -> VkSemaphore * - { - return &m_semaphore; - } - -private: - VkDevice m_device; - - VkSemaphore m_semaphore; -}; - -class Fence -{ -public: - friend class Device; - friend class Queue; - - Fence() = default; - - Fence(Fence &&) = default; - - Fence(const Fence &) = delete; - - auto operator=(Fence &&) -> Fence & = default; - - auto operator=(const Fence &) -> Fence & = delete; - - ~Fence(); - - auto operator&() -> VkFence * - { - return &m_fence; - } - - operator VkFence() - { - return m_fence; - } - -private: - VkDevice m_device; - - VkFence m_fence; -}; - -class CommandBuffer -{ -public: - friend class Device; - - auto operator&() -> VkCommandBuffer * - { - return &m_command_buffer; - } - -private: - VkCommandBuffer m_command_buffer; -}; - class Device { public: @@ -1201,6 +1124,8 @@ public: friend class Image; friend class ImageView; friend class Pipeline; + friend class Semaphore; + friend class Fence; struct CreateInfo { @@ -1367,296 +1292,94 @@ private: memory::NullOnMove m_device {}; }; -class Queue +class Semaphore { public: friend class Device; + friend class Swapchain; + friend class Queue; - constexpr static auto object_type = VK_OBJECT_TYPE_QUEUE; + static constexpr auto object_type = VK_OBJECT_TYPE_SEMAPHORE; - struct SubmitInfo - { - CommandBuffer command_buffer; + Semaphore() = default; - PipelineStageFlags::T wait_stages; + Semaphore(Device &device); - Semaphore wait_semaphore; + Semaphore(Semaphore &&) = default; - Semaphore signal_semaphore; + Semaphore(const Semaphore &) = delete; - Fence signal_fence; - }; + auto operator=(Semaphore &&) -> Semaphore & = default; - struct PresentInfo - { - Semaphore wait_semaphore; + auto operator=(const Semaphore &) -> Semaphore & = delete; - class Swapchain *swapchain; - - uint32_t image_idx; - }; - - Queue() = default; - - Queue(Device &device, uint32_t queue_family_idx, uint32_t queue_idx); - - Queue(Queue &&) = default; - - Queue(const Queue &) = delete; - - auto operator=(Queue &&) -> Queue & = default; - - auto operator=(const Queue &) -> Queue & = delete; - - ~Queue(); - - void submit(SubmitInfo info) const; - - void present(PresentInfo info) const; + ~Semaphore(); private: - [[nodiscard]] auto get_vk_handle() -> VkQueue + [[nodiscard]] auto get_vk_handle() -> VkSemaphore { - return m_queue; + return m_semaphore; + } + + [[nodiscard]] auto get_addressof_vk_handle() -> VkSemaphore * + { + return &m_semaphore; } memory::NullOnMove m_device; - VkQueue m_queue; + VkSemaphore m_semaphore; }; -class Image -{ -public: - friend class Device; - - friend class Swapchain; - - static constexpr auto object_type = VK_OBJECT_TYPE_IMAGE_VIEW; - - enum AspectFlags : VkFlags - { - color_bit = VK_IMAGE_ASPECT_COLOR_BIT, - depth_bit = VK_IMAGE_ASPECT_DEPTH_BIT, - stencil_bit = VK_IMAGE_ASPECT_STENCIL_BIT, - metadata_bit = VK_IMAGE_ASPECT_METADATA_BIT, - plane_0_bit = VK_IMAGE_ASPECT_PLANE_0_BIT, - plane_1_bit = VK_IMAGE_ASPECT_PLANE_1_BIT, - plane_2_bit = VK_IMAGE_ASPECT_PLANE_2_BIT, - none = VK_IMAGE_ASPECT_NONE, - memory_plane_0_bit = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT, - memory_plane_1_bit = VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT, - memory_plane_2_bit = VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT, - memory_plane_3_bit = VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT, - }; - - enum Usage : VkFlags - { - transfer_src_bit = VK_IMAGE_USAGE_TRANSFER_SRC_BIT, - transfer_dst_bit = VK_IMAGE_USAGE_TRANSFER_DST_BIT, - sampled_bit = VK_IMAGE_USAGE_SAMPLED_BIT, - storage_bit = VK_IMAGE_USAGE_STORAGE_BIT, - color_attachment_bit = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - depth_stencil_attachment_bit = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - transient_attachment_bit = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, - input_attachment_bit = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, - host_transfer_bit = VK_IMAGE_USAGE_HOST_TRANSFER_BIT, - video_decode_dst_bit = VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR, - video_decode_src_bit = VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR, - video_decode_dpb_bit = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR, - fragment_density_map_bit = VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT, - fragment_shading_rate_attachment_bit - = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, - video_encode_dst_bit = VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR, - video_encode_src_bit = VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, - video_encode_dpb_bit = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR, - attachment_feedback_loop_bit = VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT, - invocation_mask_bit_huawei = VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI, - sample_weight_bit_qcom = VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM, - sample_block_match_bit_qcom = VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM, - tensor_aliasing_bit_arm = VK_IMAGE_USAGE_TENSOR_ALIASING_BIT_ARM, - tile_memory_bit_qcom = VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM, - video_encode_quantization_delta_map_bit - = VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR, - video_encode_emphasis_map_bit = VK_IMAGE_USAGE_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR, - }; - - struct CreateInfo - { - }; - - Image() = default; - - Image(Device &device, CreateInfo info); - - Image(Image &&) noexcept = default; - - Image(const Image &) = delete; - - auto operator=(Image &&) noexcept -> Image & = default; - - auto operator=(const Image &) -> Image & = delete; - - ~Image(); - -private: - Image(VkImage image) noexcept; // for swapchain images - - [[nodiscard]] auto get_vk_handle() -> VkImage - { - return m_image; - } - - VkDevice m_device; - - VkImage m_image; -}; - -class ImageView -{ -public: - friend class Device; - - static constexpr auto object_type = VK_OBJECT_TYPE_IMAGE_VIEW; - - enum class Type - { - - _1d = VK_IMAGE_VIEW_TYPE_1D, - _2d = VK_IMAGE_VIEW_TYPE_2D, - _3d = VK_IMAGE_VIEW_TYPE_3D, - cube = VK_IMAGE_VIEW_TYPE_CUBE, - _1d_array = VK_IMAGE_VIEW_TYPE_1D_ARRAY, - _2d_array = VK_IMAGE_VIEW_TYPE_2D_ARRAY, - cube_array = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, - }; - - enum class Swizzle - { - identity = VK_COMPONENT_SWIZZLE_IDENTITY, - zero = VK_COMPONENT_SWIZZLE_ZERO, - one = VK_COMPONENT_SWIZZLE_ONE, - r = VK_COMPONENT_SWIZZLE_R, - g = VK_COMPONENT_SWIZZLE_G, - b = VK_COMPONENT_SWIZZLE_B, - a = VK_COMPONENT_SWIZZLE_A, - }; - - struct Range - { - Image::AspectFlags aspect_flags; - std::uint32_t base_mip_level; - std::uint32_t level_count; - std::uint32_t base_array_layer; - std::uint32_t layer_count; - }; - - struct CreateInfo - { - Type type; - - Format format; - - std::array components; - - Range range; - - std::string_view debug_name; - }; - - ImageView() = default; - - ImageView(Device &device, Image &image, CreateInfo info); - - ImageView(ImageView &&) = default; - - ImageView(const ImageView &) = delete; - - auto operator=(ImageView &&) -> ImageView & = default; - - auto operator=(const ImageView &) -> ImageView & = delete; - - ~ImageView(); - -private: - [[nodiscard]] auto get_vk_handle() -> VkImageView - { - return m_image_view; - } - - VkDevice m_device; - - VkImageView m_image_view; -}; - -class Swapchain +class Fence { public: friend class Queue; - friend class Device; - static constexpr auto object_type = VK_OBJECT_TYPE_SWAPCHAIN_KHR; - - enum class PresentMode - { - immediate = VK_PRESENT_MODE_IMMEDIATE_KHR, - mailbox = VK_PRESENT_MODE_MAILBOX_KHR, - fifo = VK_PRESENT_MODE_FIFO_KHR, - fifo_relaxed = VK_PRESENT_MODE_FIFO_RELAXED_KHR, - shared_demand_refresh = VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, - shared_continuous_refresh = VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR, - fifo_latest_ready = VK_PRESENT_MODE_FIFO_LATEST_READY_KHR, - }; + static constexpr auto object_type = VK_OBJECT_TYPE_FENCE; struct CreateInfo { - Format format; - - ColorSpace color_space; - - math::uvec2 extent; - - std::uint32_t min_image_count; - - std::vector queue_family_indices; - - VkCompositeAlphaFlagBitsKHR compositeAlpha; - - PresentMode present_mode; - - Surface::Transform pre_transform; + bool signaled; }; - Swapchain() = default; + Fence() = default; - Swapchain(Device &device, Surface &surface, CreateInfo info); + Fence(Device &device, CreateInfo info); - Swapchain(Swapchain &&) = default; + Fence(Fence &&) = default; - Swapchain(const Swapchain &) = delete; + Fence(const Fence &) = delete; - auto operator=(Swapchain &&) -> Swapchain & = default; + auto operator=(Fence &&) -> Fence & = default; - auto operator=(const Swapchain &) -> Swapchain & = delete; + auto operator=(const Fence &) -> Fence & = delete; - ~Swapchain(); + ~Fence(); - [[nodiscard]] auto get_images() -> std::vector; + operator VkFence() + { + return m_fence; + } + + void wait(); + + void reset(); private: - [[nodiscard]] auto get_vk_handle() -> VkSwapchainKHR + [[nodiscard]] auto get_vk_handle() -> VkFence { - return m_swapchain; + return m_fence; } - [[nodiscard]] auto get_addressof_vk_handle() -> VkSwapchainKHR * + [[nodiscard]] auto get_addressof_vk_handle() -> VkFence * { - return &m_swapchain; + return &m_fence; } - VkDevice m_device; + memory::NullOnMove m_device; - VkSwapchainKHR m_swapchain; + VkFence m_fence; }; class Buffer @@ -1738,58 +1461,215 @@ private: VkBuffer m_buffer {}; }; -class Memory +class Image { public: friend class Device; - static constexpr auto object_type = VK_OBJECT_TYPE_DEVICE_MEMORY; + friend class Swapchain; - enum PropertyFlags : VkFlags + static constexpr auto object_type = VK_OBJECT_TYPE_IMAGE_VIEW; + + enum AspectFlags : VkFlags { - device_local_bit = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - host_visible_bit = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, - host_coherent_bit = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - host_cached_bit = VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - lazily_allocated_bit = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, - protected_bit = VK_MEMORY_PROPERTY_PROTECTED_BIT, - device_coherent_bit_amd = VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD, - device_uncached_bit_amd = VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD, - rdma_capable_bit_nv = VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV, + color_bit = VK_IMAGE_ASPECT_COLOR_BIT, + depth_bit = VK_IMAGE_ASPECT_DEPTH_BIT, + stencil_bit = VK_IMAGE_ASPECT_STENCIL_BIT, + metadata_bit = VK_IMAGE_ASPECT_METADATA_BIT, + plane_0_bit = VK_IMAGE_ASPECT_PLANE_0_BIT, + plane_1_bit = VK_IMAGE_ASPECT_PLANE_1_BIT, + plane_2_bit = VK_IMAGE_ASPECT_PLANE_2_BIT, + none = VK_IMAGE_ASPECT_NONE, + memory_plane_0_bit = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT, + memory_plane_1_bit = VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT, + memory_plane_2_bit = VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT, + memory_plane_3_bit = VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT, }; - struct AllocateInfo + enum class Layout : std::underlying_type_t { - std::size_t size; - - std::uint32_t memory_type_idx; + undefined = VK_IMAGE_LAYOUT_UNDEFINED, + general = VK_IMAGE_LAYOUT_GENERAL, + color_attachment_optimal = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + depth_stencil_attachment_optimal = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + depth_stencil_read_only_optimal = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, + shader_read_only_optimal = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + transfer_src_optimal = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + transfer_dst_optimal = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + preinitialized = VK_IMAGE_LAYOUT_PREINITIALIZED, + depth_read_only_stencil_attachment_optimal + = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL, + depth_attachment_stencil_read_only_optimal + = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL, + depth_attachment_optimal = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + depth_read_only_optimal = VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL, + stencil_attachment_optimal = VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, + stencil_read_only_optimal = VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL, + read_only_optimal = VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL, + attachment_optimal = VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL, + rendering_local_read = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ, + present_src = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + video_decode_dst = VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR, + video_decode_src = VK_IMAGE_LAYOUT_VIDEO_DECODE_SRC_KHR, + video_decode_dpb = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR, + shared_present = VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR, + fragment_density_map_optimal = VK_IMAGE_LAYOUT_FRAGMENT_DENSITY_MAP_OPTIMAL_EXT, + fragment_shading_rate_attachment_optimal + = VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR, + video_encode_dst = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DST_KHR, + video_encode_src = VK_IMAGE_LAYOUT_VIDEO_ENCODE_SRC_KHR, + video_encode_dpb = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR, + attachment_feedback_loop_optimal = VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT, + tensor_aliasing_arm = VK_IMAGE_LAYOUT_TENSOR_ALIASING_ARM, + video_encode_quantization_map = VK_IMAGE_LAYOUT_VIDEO_ENCODE_QUANTIZATION_MAP_KHR, + zero_initialized = VK_IMAGE_LAYOUT_ZERO_INITIALIZED_EXT, }; - Memory(Device &device, Buffer &buffer, AllocateInfo info); + enum Usage : VkFlags + { + transfer_src_bit = VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + transfer_dst_bit = VK_IMAGE_USAGE_TRANSFER_DST_BIT, + sampled_bit = VK_IMAGE_USAGE_SAMPLED_BIT, + storage_bit = VK_IMAGE_USAGE_STORAGE_BIT, + color_attachment_bit = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + depth_stencil_attachment_bit = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + transient_attachment_bit = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, + input_attachment_bit = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, + host_transfer_bit = VK_IMAGE_USAGE_HOST_TRANSFER_BIT, + video_decode_dst_bit = VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR, + video_decode_src_bit = VK_IMAGE_USAGE_VIDEO_DECODE_SRC_BIT_KHR, + video_decode_dpb_bit = VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR, + fragment_density_map_bit = VK_IMAGE_USAGE_FRAGMENT_DENSITY_MAP_BIT_EXT, + fragment_shading_rate_attachment_bit + = VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR, + video_encode_dst_bit = VK_IMAGE_USAGE_VIDEO_ENCODE_DST_BIT_KHR, + video_encode_src_bit = VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, + video_encode_dpb_bit = VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR, + attachment_feedback_loop_bit = VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT, + invocation_mask_bit_huawei = VK_IMAGE_USAGE_INVOCATION_MASK_BIT_HUAWEI, + sample_weight_bit_qcom = VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOM, + sample_block_match_bit_qcom = VK_IMAGE_USAGE_SAMPLE_BLOCK_MATCH_BIT_QCOM, + tensor_aliasing_bit_arm = VK_IMAGE_USAGE_TENSOR_ALIASING_BIT_ARM, + tile_memory_bit_qcom = VK_IMAGE_USAGE_TILE_MEMORY_BIT_QCOM, + video_encode_quantization_delta_map_bit + = VK_IMAGE_USAGE_VIDEO_ENCODE_QUANTIZATION_DELTA_MAP_BIT_KHR, + video_encode_emphasis_map_bit = VK_IMAGE_USAGE_VIDEO_ENCODE_EMPHASIS_MAP_BIT_KHR, + }; - ~Memory(); + struct Range + { + Image::AspectFlags aspect_flags; + std::uint32_t base_mip_level; + std::uint32_t level_count; + std::uint32_t base_array_layer; + std::uint32_t layer_count; + }; - Memory(Memory &&) = default; + static constexpr auto full_color_range = Range { + .aspect_flags = AspectFlags::color_bit, + .base_mip_level = 0u, + .level_count = VK_REMAINING_MIP_LEVELS, + .base_array_layer = 0u, + .layer_count = VK_REMAINING_ARRAY_LAYERS, + }; - Memory(const Memory &) = delete; + struct CreateInfo + { + }; - auto operator=(Memory &&) -> Memory & = default; + Image() = default; - auto operator=(const Memory &) -> Memory & = delete; + Image(Device &device, CreateInfo info); - [[nodiscard]] auto map(std::size_t size, std::size_t offset) -> std::span; + Image(Image &&) noexcept = default; - void unmap(); + Image(const Image &) = delete; + + auto operator=(Image &&) noexcept -> Image & = default; + + auto operator=(const Image &) -> Image & = delete; + + ~Image(); private: - [[nodiscard]] auto get_vk_handle() -> VkDeviceMemory + Image(VkImage image) noexcept; // for swapchain images + + [[nodiscard]] auto get_vk_handle() -> VkImage { - return m_memory; + return m_image; } - memory::NullOnMove m_device {}; + VkDevice m_device; - VkDeviceMemory m_memory {}; + VkImage m_image; +}; + +class ImageView +{ +public: + friend class Device; + + static constexpr auto object_type = VK_OBJECT_TYPE_IMAGE_VIEW; + + enum class Type + { + + _1d = VK_IMAGE_VIEW_TYPE_1D, + _2d = VK_IMAGE_VIEW_TYPE_2D, + _3d = VK_IMAGE_VIEW_TYPE_3D, + cube = VK_IMAGE_VIEW_TYPE_CUBE, + _1d_array = VK_IMAGE_VIEW_TYPE_1D_ARRAY, + _2d_array = VK_IMAGE_VIEW_TYPE_2D_ARRAY, + cube_array = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, + }; + + enum class Swizzle + { + identity = VK_COMPONENT_SWIZZLE_IDENTITY, + zero = VK_COMPONENT_SWIZZLE_ZERO, + one = VK_COMPONENT_SWIZZLE_ONE, + r = VK_COMPONENT_SWIZZLE_R, + g = VK_COMPONENT_SWIZZLE_G, + b = VK_COMPONENT_SWIZZLE_B, + a = VK_COMPONENT_SWIZZLE_A, + }; + + struct CreateInfo + { + Type type; + + Format format; + + std::array components; + + Image::Range range; + + std::string_view debug_name; + }; + + ImageView() = default; + + ImageView(Device &device, Image &image, CreateInfo info); + + ImageView(ImageView &&) = default; + + ImageView(const ImageView &) = delete; + + auto operator=(ImageView &&) -> ImageView & = default; + + auto operator=(const ImageView &) -> ImageView & = delete; + + ~ImageView(); + +private: + [[nodiscard]] auto get_vk_handle() -> VkImageView + { + return m_image_view; + } + + VkDevice m_device; + + VkImageView m_image_view; }; class ShaderModule @@ -1814,7 +1694,7 @@ public: auto operator=(ShaderModule &&) -> ShaderModule & = default; - auto operator=(const Memory &) -> Memory & = delete; + auto operator=(const ShaderModule &) -> ShaderModule & = delete; private: [[nodiscard]] auto get_vk_handle() @@ -1831,7 +1711,6 @@ class DescriptorPool { }; - class DescriptorSet { public: @@ -1931,6 +1810,14 @@ class Pipeline public: static constexpr auto object_type = VK_OBJECT_TYPE_PIPELINE; + enum class BindPoint : std::underlying_type_t + { + graphics = VK_PIPELINE_BIND_POINT_GRAPHICS, + compute = VK_PIPELINE_BIND_POINT_COMPUTE, + ray_tracing = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, + data_graph = VK_PIPELINE_BIND_POINT_DATA_GRAPH_ARM, + }; + struct InputAssemblyState { PrimitiveTopology topology; @@ -2094,6 +1981,417 @@ private: VkPipelineLayout m_layout {}; }; +class CommandBuffer +{ +public: + friend class Device; + friend class Queue; + + struct BeginInfo + { + }; + + struct BufferCopyInfo + { + Buffer *src_buffer; + + Buffer *dst_buffer; + + std::size_t src_offset; + + std::size_t dst_offset; + + std::size_t size; + }; + + struct PushConstantsInfo + { + class PipelineLayout *layout; + + vk::ShaderStageFlags::T shader_stages; + + std::uint32_t offset; + + std::uint32_t size; + + void *data; + }; + + struct ImageBarrierInfo + { + enum AccessFlagBits : std::underlying_type_t + { + indirect_command_read = VK_ACCESS_INDIRECT_COMMAND_READ_BIT, + index_read = VK_ACCESS_INDEX_READ_BIT, + vertex_attribute_read = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, + uniform_read = VK_ACCESS_UNIFORM_READ_BIT, + input_attachment_read = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, + shader_read = VK_ACCESS_SHADER_READ_BIT, + shader_write = VK_ACCESS_SHADER_WRITE_BIT, + color_attachment_read = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + color_attachment_write = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + depth_stencil_attachment_read = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, + depth_stencil_attachment_write = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + transfer_read = VK_ACCESS_TRANSFER_READ_BIT, + transfer_write = VK_ACCESS_TRANSFER_WRITE_BIT, + host_read = VK_ACCESS_HOST_READ_BIT, + host_write = VK_ACCESS_HOST_WRITE_BIT, + memory_read = VK_ACCESS_MEMORY_READ_BIT, + memory_write = VK_ACCESS_MEMORY_WRITE_BIT, + none = VK_ACCESS_NONE, + transform_feedback_write = VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, + transform_feedback_counter_read = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, + transform_feedback_counter_write = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, + conditional_rendering_read = VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT, + color_attachment_read_noncoherent = VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT, + acceleration_structure_read_khr = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR, + acceleration_structure_write_khr = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR, + fragment_density_map_read = VK_ACCESS_FRAGMENT_DENSITY_MAP_READ_BIT_EXT, + fragment_shading_rate_attachment_read_khr + = VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR, + command_preprocess_read = VK_ACCESS_COMMAND_PREPROCESS_READ_BIT_EXT, + command_preprocess_write = VK_ACCESS_COMMAND_PREPROCESS_WRITE_BIT_EXT, + }; + + class Image *image; + + Image::Range range; + + vk::PipelineStageFlags::T src_stages; + + vk::PipelineStageFlags::T dst_stages; + + Flags src_accesses; + + Flags dst_accesses; + + Image::Layout src_layout; + + Image::Layout dst_layout; + }; + + struct RenderingInfo + { + struct AttachmentInfo + { + enum class ResolveModeBits : std::underlying_type_t + { + none = VK_RESOLVE_MODE_NONE, + sample_zero = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, + average = VK_RESOLVE_MODE_AVERAGE_BIT, + min = VK_RESOLVE_MODE_MIN_BIT, + max = VK_RESOLVE_MODE_MAX_BIT, + }; + + enum class LoadOperation : std::underlying_type_t + { + load = VK_ATTACHMENT_LOAD_OP_LOAD, + clear = VK_ATTACHMENT_LOAD_OP_CLEAR, + dont_care = VK_ATTACHMENT_LOAD_OP_DONT_CARE, + none = VK_ATTACHMENT_LOAD_OP_NONE, + }; + + enum class StoreOperation : std::underlying_type_t + { + store = VK_ATTACHMENT_STORE_OP_STORE, + dont_care = VK_ATTACHMENT_STORE_OP_DONT_CARE, + none = VK_ATTACHMENT_STORE_OP_NONE, + }; + + ImageView *view; + + Image::Layout layout; + + LoadOperation load_operation; + + StoreOperation store_operation; + + std::array color_clear_values; + + float depth_clear_value; + + std::uint32_t stencil_clear_value; + + Flags resolve_mode_flags; + }; + + math::uvec2 area_offset; + + math::uvec2 area_extent; + + std::vector color_attachments; + }; + + struct DrawInfo + { + std::uint32_t vertex_count; + + std::uint32_t instance_count; + + std::uint32_t first_vertex; + + std::uint32_t first_instance; + }; + + void begin(BeginInfo info = {}); + + void end(); + + void copy(BufferCopyInfo info); + + void push_constants(PushConstantsInfo info); + + void image_barrier(ImageBarrierInfo info); + + void begin_rendering(RenderingInfo info); + + void end_rendering(); + + void bind_pipeline(Pipeline &pipeline, Pipeline::BindPoint bind_point); + + void draw(DrawInfo info); + +private: + [[nodiscard]] auto get_vk_handle() -> VkCommandBuffer + { + return m_buffer; + } + + [[nodiscard]] auto get_addressof_vk_handle() -> VkCommandBuffer * + { + return &m_buffer; + } + + VkCommandBuffer m_buffer; +}; + +class CommandPool +{ +public: + struct CreateInfo + { + enum FlagBits : std::underlying_type_t + { + transient = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, + reset_command_buffer = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, + _protected = VK_COMMAND_POOL_CREATE_PROTECTED_BIT, + }; + + Flags flags; + }; + + enum class BufferLevel + { + secondary = VK_COMMAND_BUFFER_LEVEL_SECONDARY, + primary = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + }; + + CommandPool() = default; + + CommandPool(Device &device, CreateInfo info); + + ~CommandPool(); + + CommandPool(CommandPool &&) = default; + + CommandPool(const CommandPool &) = delete; + + auto operator=(CommandPool &&) -> CommandPool & = default; + + auto operator=(const CommandPool &) -> CommandPool & = delete; + + [[nodiscard]] auto allocate(uint32_t count, BufferLevel level) -> std::vector; + +private: + VkDevice m_device {}; + + VkCommandPool m_pool {}; +}; + +class Swapchain +{ +public: + friend class Queue; + friend class Device; + + static constexpr auto object_type = VK_OBJECT_TYPE_SWAPCHAIN_KHR; + + enum class PresentMode + { + immediate = VK_PRESENT_MODE_IMMEDIATE_KHR, + mailbox = VK_PRESENT_MODE_MAILBOX_KHR, + fifo = VK_PRESENT_MODE_FIFO_KHR, + fifo_relaxed = VK_PRESENT_MODE_FIFO_RELAXED_KHR, + shared_demand_refresh = VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR, + shared_continuous_refresh = VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR, + fifo_latest_ready = VK_PRESENT_MODE_FIFO_LATEST_READY_KHR, + }; + + struct CreateInfo + { + Format format; + + ColorSpace color_space; + + math::uvec2 extent; + + std::uint32_t min_image_count; + + std::vector queue_family_indices; + + VkCompositeAlphaFlagBitsKHR compositeAlpha; + + PresentMode present_mode; + + Surface::Transform pre_transform; + }; + + Swapchain() = default; + + Swapchain(Device &device, Surface &surface, CreateInfo info); + + Swapchain(Swapchain &&) = default; + + Swapchain(const Swapchain &) = delete; + + auto operator=(Swapchain &&) -> Swapchain & = default; + + auto operator=(const Swapchain &) -> Swapchain & = delete; + + ~Swapchain(); + + [[nodiscard]] auto get_images() -> std::vector; + + [[nodiscard]] auto acquire_image(Semaphore &semaphore, std::uint64_t timeout = 100'000'000) + -> std::uint32_t; + +private: + [[nodiscard]] auto get_vk_handle() -> VkSwapchainKHR + { + return m_swapchain; + } + + [[nodiscard]] auto get_addressof_vk_handle() -> VkSwapchainKHR * + { + return &m_swapchain; + } + + VkDevice m_device; + + VkSwapchainKHR m_swapchain; +}; + +class Queue +{ +public: + friend class Device; + + constexpr static auto object_type = VK_OBJECT_TYPE_QUEUE; + + struct SubmitInfo + { + CommandBuffer *command_buffer; + + PipelineStageFlags::T wait_stages; + + Semaphore *wait_semaphore; + + Semaphore *signal_semaphore; + + Fence *signal_fence; + }; + + struct PresentInfo + { + Semaphore *wait_semaphore; + + Swapchain *swapchain; + + uint32_t image_idx; + }; + + Queue() = default; + + Queue(Device &device, uint32_t queue_family_idx, uint32_t queue_idx); + + Queue(Queue &&) = default; + + Queue(const Queue &) = delete; + + auto operator=(Queue &&) -> Queue & = default; + + auto operator=(const Queue &) -> Queue & = delete; + + ~Queue(); + + void submit(SubmitInfo info) const; + + void present(PresentInfo info) const; + +private: + [[nodiscard]] auto get_vk_handle() -> VkQueue + { + return m_queue; + } + + memory::NullOnMove m_device; + + VkQueue m_queue; +}; + +class Memory +{ +public: + friend class Device; + + static constexpr auto object_type = VK_OBJECT_TYPE_DEVICE_MEMORY; + + enum PropertyFlags : VkFlags + { + device_local_bit = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + host_visible_bit = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, + host_coherent_bit = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + host_cached_bit = VK_MEMORY_PROPERTY_HOST_CACHED_BIT, + lazily_allocated_bit = VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, + protected_bit = VK_MEMORY_PROPERTY_PROTECTED_BIT, + device_coherent_bit_amd = VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD, + device_uncached_bit_amd = VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD, + rdma_capable_bit_nv = VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV, + }; + + struct AllocateInfo + { + std::size_t size; + + std::uint32_t memory_type_idx; + }; + + Memory(Device &device, Buffer &buffer, AllocateInfo info); + + ~Memory(); + + Memory(Memory &&) = default; + + Memory(const Memory &) = delete; + + auto operator=(Memory &&) -> Memory & = default; + + auto operator=(const Memory &) -> Memory & = delete; + + [[nodiscard]] auto map(std::size_t size, std::size_t offset) -> std::span; + + void unmap(); + +private: + [[nodiscard]] auto get_vk_handle() -> VkDeviceMemory + { + return m_memory; + } + + memory::NullOnMove m_device {}; + + VkDeviceMemory m_memory {}; +}; } // namespace lt::renderer::vk @@ -2927,14 +3225,49 @@ Surface::~Surface() return formats; } +Semaphore::Semaphore(Device &device): m_device(device.get_vk_handle()) +{ + auto vk_info = VkSemaphoreCreateInfo { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + }; + + vkc(api::create_semaphore(m_device, &vk_info, nullptr, &m_semaphore)); +} + Semaphore::~Semaphore() { - api::destroy_semaphore(m_device, m_semaphore, nullptr); + if (m_device) + { + api::destroy_semaphore(m_device, m_semaphore, nullptr); + } +} + +Fence::Fence(Device &device, CreateInfo info): m_device(device.get_vk_handle()) +{ + auto vk_info = VkFenceCreateInfo { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + .flags = info.signaled ? VK_FENCE_CREATE_SIGNALED_BIT : VkFlags {}, + }; + + vkc(api::create_fence(m_device, &vk_info, nullptr, &m_fence)); } Fence::~Fence() { - api::destroy_fence(m_device, m_fence, nullptr); + if (m_device) + { + api::destroy_fence(m_device, m_fence, nullptr); + } +} + +void Fence::wait() +{ + vkc(api::wait_for_fences(m_device, 1u, &m_fence, true, std::numeric_limits::max())); +} + +void Fence::reset() +{ + vkc(api::reset_fences(m_device, 1u, &m_fence)); } Device::Device(const Gpu &gpu, CreateInfo info) @@ -3472,16 +3805,16 @@ void Queue::submit(SubmitInfo info) const .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .waitSemaphoreCount = 1u, - .pWaitSemaphores = &info.wait_semaphore, + .pWaitSemaphores = info.wait_semaphore->get_addressof_vk_handle(), .pWaitDstStageMask = addressof_underlying(info.wait_stages), .commandBufferCount = 1u, - .pCommandBuffers = &info.command_buffer, + .pCommandBuffers = info.command_buffer->get_addressof_vk_handle(), .signalSemaphoreCount = 1u, - .pSignalSemaphores = &info.signal_semaphore, + .pSignalSemaphores = info.signal_semaphore->get_addressof_vk_handle(), }; - vkc(api::queue_submit(m_queue, 1u, &vk_info, info.signal_fence)); + vkc(api::queue_submit(m_queue, 1u, &vk_info, info.signal_fence->get_vk_handle())); } void Queue::present(PresentInfo info) const @@ -3491,7 +3824,7 @@ void Queue::present(PresentInfo info) const const auto vk_info = VkPresentInfoKHR { .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .waitSemaphoreCount = 1u, - .pWaitSemaphores = &info.wait_semaphore, + .pWaitSemaphores = info.wait_semaphore->get_addressof_vk_handle(), .swapchainCount = 1u, .pSwapchains = info.swapchain->get_addressof_vk_handle(), .pImageIndices = &info.image_idx, @@ -3582,6 +3915,23 @@ Swapchain::~Swapchain() return images; } +[[nodiscard]] auto Swapchain::acquire_image(Semaphore &semaphore, std::uint64_t timeout) + -> std::uint32_t +{ + auto idx = std::uint32_t {}; + vkc(api::acquire_next_image_khr( + m_device, + m_swapchain, + timeout, + semaphore.get_vk_handle(), + VK_NULL_HANDLE, + &idx + )); + + return idx; +} + + Buffer::Buffer(Device &device, CreateInfo info) {}; Buffer::~Buffer() diff --git a/modules/renderer/vk/buffer.cppm b/modules/renderer/vk/buffer.cppm index bea2eb1..446d545 100644 --- a/modules/renderer/vk/buffer.cppm +++ b/modules/renderer/vk/buffer.cppm @@ -21,6 +21,11 @@ public: return m_size; } + [[nodiscard]] auto vk() -> vk::Buffer & + { + return m_buffer; + } + private: [[nodiscard]] auto determine_allocation_info(Usage usage) const -> vk::Memory::AllocateInfo; diff --git a/modules/renderer/vk/device.cppm b/modules/renderer/vk/device.cppm index aeab517..71e9d59 100644 --- a/modules/renderer/vk/device.cppm +++ b/modules/renderer/vk/device.cppm @@ -27,6 +27,16 @@ public: return { m_graphics_queue_family_index, m_present_queue_family_index }; } + [[nodiscard]] auto graphics_queue() -> vk::Queue & + { + return m_graphics_queue; + } + + [[nodiscard]] auto present_queue() -> vk::Queue & + { + return m_present_queue; + } + private: void initialize_physical_device(); diff --git a/modules/renderer/vk/pass.cppm b/modules/renderer/vk/pass.cppm index b57756f..3a4a5fc 100644 --- a/modules/renderer/vk/pass.cppm +++ b/modules/renderer/vk/pass.cppm @@ -1,5 +1,4 @@ export module renderer.vk.pass; - import renderer.data; import renderer.backend.vk.library_wrapper; import renderer.backend.vk.device; diff --git a/modules/renderer/vk/raii.cppm b/modules/renderer/vk/raii.cppm deleted file mode 100644 index 8a59169..0000000 --- a/modules/renderer/vk/raii.cppm +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -#include - - -export namespace lt::renderer::vk::raii { - -class DebugMessenger -{ -public: - DebugMessenger(Instance *instance, VkDebugUtilsMessengerCreateInfoEXT info) - : m_instance(instance) - , m_object(m_instance->create_messenger(info)) - { - } - - ~DebugMessenger() - { - if (m_instance) - { - m_instance->destroy_messenger(m_object); - } - } - - DebugMessenger(DebugMessenger &&) = default; - - DebugMessenger(const DebugMessenger &) = delete; - - auto operator=(DebugMessenger &&) -> DebugMessenger & = default; - - auto operator=(const DebugMessenger &) -> DebugMessenger & = delete; - -private: - memory::NullOnMove m_instance {}; - - VkDebugUtilsMessengerEXT m_object; -}; - - -class Memory -{ -public: - Memory(Device *device, VkBuffer buffer, VkMemoryAllocateInfo info) - : m_device(device) - , m_object(m_device->allocate_memory(info)) - { - m_device->bind_memory(buffer, m_object); - } - - ~Memory() - { - if (m_device) - { - m_device->free_memory(m_object); - } - } - - Memory(Memory &&) = default; - - Memory(const Memory &) = delete; - - auto operator=(Memory &&) -> Memory & = default; - - auto operator=(const Memory &) -> Memory & = delete; - - [[nodiscard]] auto operator*() const -> VkDeviceMemory - { - return m_object; - } - - [[nodiscard]] operator VkDeviceMemory() const - { - return m_object; - } - -private: - memory::NullOnMove m_device {}; - - VkDeviceMemory m_object = VK_NULL_HANDLE; -}; - - -} // namespace lt::renderer::vk::raii diff --git a/modules/renderer/vk/renderer.cppm b/modules/renderer/vk/renderer.cppm index 04d8c7e..9d2547f 100644 --- a/modules/renderer/vk/renderer.cppm +++ b/modules/renderer/vk/renderer.cppm @@ -1,38 +1,33 @@ -#pragma once +export module renderer.vk.renderer; +import assets.shader; +import debug.assertions; +import renderer.backend.vk.library_wrapper; +import memory.reference; +import memory.null_on_move; +import renderer.backend.vk.device; +import math.vec2; +import math.components; +import renderer.backend.vk.swapchain; +import renderer.components; +import renderer.backend.vk.buffer; +import renderer.vk.pass; +import renderer.data; +import renderer.frontend; +import std; -#include -#include -#include -#include -#include -#include -#include -#include -#include +namespace lt::renderer::vkb { -namespace lt::renderer::vk { - -class Renderer: public IRenderer +export class Renderer: public IRenderer { public: Renderer( class IGpu *gpu, class IDevice *device, class ISwapchain *swapchain, - uint32_t max_frames_in_flight + std::uint32_t max_frames_in_flight ); - ~Renderer() override; - - Renderer(Renderer &&) = default; - - Renderer(const Renderer &) = delete; - - auto operator=(Renderer &&) -> Renderer & = default; - - auto operator=(const Renderer &) -> Renderer & = delete; - - [[nodiscard]] auto frame(uint32_t frame_idx, std::function submit_scene) + [[nodiscard]] auto frame(std::uint32_t frame_idx, std::function submit_scene) -> Result override; void replace_swapchain(ISwapchain *swapchain) override; @@ -48,33 +43,29 @@ public: ) override; private: - void record_cmd(VkCommandBuffer cmd, uint32_t image_idx); + void record_cmd(vk::CommandBuffer &cmd, std::uint32_t image_idx); - void map_buffers(uint32_t frame_idx); + void map_buffers(std::uint32_t frame_idx); - void flush_buffers(VkCommandBuffer cmd); + std::uint32_t m_max_frames_in_flight {}; - memory::NullOnMove m_device {}; + memory::NullOnMove m_device {}; - class Swapchain *m_swapchain {}; + Swapchain *m_swapchain {}; - memory::Ref m_pass; + memory::Ref m_pass; - VkCommandPool m_pool = VK_NULL_HANDLE; + vk::CommandPool m_pool; - VkCommandPool m_transient_pool = VK_NULL_HANDLE; + std::vector m_cmds; - std::vector m_cmds; + std::vector m_frame_fences; - std::vector m_frame_fences; + std::vector m_acquire_image_semaphores; - std::vector m_aquire_image_semaphores; + std::vector m_submit_semaphores; - std::vector m_submit_semaphores; - - VkExtent2D m_resolution; - - uint32_t m_max_frames_in_flight {}; + math::uvec2 m_resolution; FrameConstants m_frame_constants; @@ -82,26 +73,27 @@ private: Buffer m_staging_buffer; - size_t m_staging_offset; + std::size_t m_staging_offset; std::span m_staging_map; std::span m_sprite_vertex_map; - size_t m_current_sprite_idx; + std::size_t m_current_sprite_idx; }; -} // namespace lt::renderer::vk +} // namespace lt::renderer::vkb module :private; +using namespace lt::renderer; +using namespace lt::renderer::vkb; -#include -#include -#include - -namespace lt::renderer::vk { - -Renderer::Renderer(IGpu *gpu, IDevice *device, ISwapchain *swapchain, uint32_t max_frames_in_flight) +Renderer::Renderer( + IGpu *gpu, + IDevice *device, + ISwapchain *swapchain, + std::uint32_t max_frames_in_flight +) : m_device(static_cast(device)) , m_swapchain(static_cast(swapchain)) , m_resolution(m_swapchain->get_resolution()) @@ -110,7 +102,7 @@ Renderer::Renderer(IGpu *gpu, IDevice *device, ISwapchain *swapchain, uint32_t m , m_vertex_buffer( device, gpu, - IBuffer::CreateInfo { + { .usage = IBuffer::Usage::vertex, .size = 1'000'000, .debug_name = "vertex buffer", @@ -119,91 +111,46 @@ Renderer::Renderer(IGpu *gpu, IDevice *device, ISwapchain *swapchain, uint32_t m , m_staging_buffer( device, gpu, - IBuffer::CreateInfo { + { .usage = IBuffer::Usage::staging, .size = 1'000'000, .debug_name = "staging buffer", } ) + , m_pass( + memory::create_ref( + m_device, + assets::ShaderAsset { "./data/test_assets/sprite.vert.asset" }, + assets::ShaderAsset { "./data/test_assets/triangle.frag.asset" } + ) + ) + , m_pool( + m_device->vk(), + { + .flags = vk::CommandPool::CreateInfo::FlagBits::reset_command_buffer, + } + ) + , m_cmds(m_pool.allocate(m_max_frames_in_flight, vk::CommandPool::BufferLevel::primary)) + , m_acquire_image_semaphores(m_max_frames_in_flight) + , m_frame_fences(m_max_frames_in_flight) + , m_submit_semaphores(m_swapchain->get_image_count()) { - ensure(m_device, "Failed to initialize renderer: null device"); - ensure(m_swapchain, "Failed to initialize renderer: null swapchain"); - - // TODO(Light): HARDCODED PASS!!! - m_pass = memory::create_ref( - m_device, - m_swapchain, - assets::ShaderAsset { "./data/test_assets/sprite.vert.asset" }, - assets::ShaderAsset { "./data/test_assets/triangle.frag.asset" } - ); - - m_pool = m_device->create_command_pool( - VkCommandPoolCreateInfo { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - .queueFamilyIndex = m_device->get_family_indices()[0], - } - ); - - - m_transient_pool = m_device->create_command_pool( - VkCommandPoolCreateInfo { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, - .queueFamilyIndex = m_device->get_family_indices()[0], - } - ); - - m_cmds.resize(m_max_frames_in_flight); - m_cmds = m_device->allocate_command_buffers( - VkCommandBufferAllocateInfo { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .commandPool = m_pool, - .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = static_cast(m_cmds.size()), - } - ); - - m_aquire_image_semaphores = m_device->create_semaphores(m_max_frames_in_flight); - m_frame_fences = m_device->create_fences( - VkFenceCreateInfo { - .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - .flags = VK_FENCE_CREATE_SIGNALED_BIT, - }, - m_max_frames_in_flight - ); - for (auto idx = 0u; - auto [semaphore, fence] : std::views::zip(m_aquire_image_semaphores, m_frame_fences)) + for (auto [semaphore, fence] : std::views::zip(m_acquire_image_semaphores, m_frame_fences)) { - m_device->name(semaphore, "acquire image semaphore {}", idx); - m_device->name(fence, "frame fence {}", idx); + semaphore = vk::Semaphore(m_device->vk()); + fence = vk::Fence(m_device->vk(), { .signaled = true }); } - m_submit_semaphores = m_device->create_semaphores(m_swapchain->get_image_count()); - for (auto idx = 0u; auto &semaphore : m_submit_semaphores) + for (auto &semaphore : m_submit_semaphores) { - m_device->name(semaphore, "submit semaphore {}", idx); + semaphore = vk::Semaphore(m_device->vk()); } }; -Renderer::~Renderer() +[[nodiscard]] auto Renderer::frame(std::uint32_t frame_idx, std::function submit_scene) + -> Result { - if (!m_device) - { - return; - } - - m_device->wait_idle(); - m_device->destroy_semaphores(m_aquire_image_semaphores); - m_device->destroy_semaphores(m_submit_semaphores); - m_device->destroy_fences(m_frame_fences); - m_device->destroy_command_pool(m_pool); - m_device->destroy_command_pool(m_transient_pool); -} - -[[nodiscard]] auto Renderer::frame(uint32_t frame_idx, std::function submit_scene) -> Result -{ - ensure( + debug::ensure( frame_idx < m_max_frames_in_flight, "Failed to draw: frame_idx >= max_frames_in_flight ({} >= {})", frame_idx, @@ -211,50 +158,33 @@ Renderer::~Renderer() ); auto &frame_fence = m_frame_fences[frame_idx]; - auto &aquire_semaphore = m_aquire_image_semaphores[frame_idx]; + auto &acquire_semaphore = m_acquire_image_semaphores[frame_idx]; auto &cmd = m_cmds[frame_idx]; - m_device->wait_for_fence(frame_fence); - - auto image_idx = m_device->acquire_image(m_swapchain->vk(), aquire_semaphore); - if (!image_idx.has_value()) - { - return Result::invalid_swapchain; - } - - m_device->reset_fence(frame_fence); + frame_fence.wait(); + const auto image_idx = m_swapchain->vk().acquire_image(acquire_semaphore); + frame_fence.reset(); map_buffers(frame_idx); submit_scene(); - record_cmd(cmd, *image_idx); + record_cmd(cmd, image_idx); - auto wait_stage = VkPipelineStageFlags { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; - auto &submit_semaphore = m_submit_semaphores[*image_idx]; - m_device->submit( - VkSubmitInfo { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .waitSemaphoreCount = 1u, - .pWaitSemaphores = &aquire_semaphore, - .pWaitDstStageMask = &wait_stage, - .commandBufferCount = 1u, - .pCommandBuffers = &cmd, - .signalSemaphoreCount = 1u, - .pSignalSemaphores = &submit_semaphore, - }, - frame_fence + auto &submit_semaphore = m_submit_semaphores[image_idx]; + m_device->graphics_queue().submit( + vk::Queue::SubmitInfo { + .command_buffer = &cmd, + .wait_stages = vk::PipelineStageFlags::color_attachment_output_bit, + .wait_semaphore = &acquire_semaphore, + .signal_semaphore = &submit_semaphore, + .signal_fence = &frame_fence, + } ); - // TODO(Light): handle result - auto result = VkResult {}; - m_device->present( - VkPresentInfoKHR { - .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, - .waitSemaphoreCount = 1u, - .pWaitSemaphores = &submit_semaphore, - .swapchainCount = 1u, - .pSwapchains = m_swapchain->vk_ptr(), - .pImageIndices = &image_idx.value(), - .pResults = &result, + m_device->present_queue().present( + vk::Queue::PresentInfo { + .wait_semaphore = &submit_semaphore, + .swapchain = &m_swapchain->vk(), + .image_idx = image_idx, } ); @@ -263,13 +193,12 @@ Renderer::~Renderer() void Renderer::replace_swapchain(ISwapchain *swapchain) { - m_device->wait_idle(); + m_device->vk().wait_idle(); m_swapchain = static_cast(swapchain); m_resolution = m_swapchain->get_resolution(); - m_pass->replace_swapchain(*swapchain); } -void Renderer::map_buffers(uint32_t frame_idx) +void Renderer::map_buffers(std::uint32_t frame_idx) { using components::Sprite; @@ -286,140 +215,188 @@ void Renderer::map_buffers(uint32_t frame_idx) ); } -void Renderer::flush_buffers(VkCommandBuffer cmd) +void Renderer::record_cmd(vk::CommandBuffer &cmd, std::uint32_t image_idx) { + // const auto cmd_begin_info = VkCommandBufferBeginInfo { + // .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + // .flags = {}, + // .pInheritanceInfo = nullptr, + // }; + + // vk_reset_command_buffer(cmd, {}); + // vkc(vk_begin_command_buffer(cmd, &cmd_begin_info)); + // const auto begin_frame_barrier = VkImageMemoryBarrier { + // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + // .srcAccessMask = {}, + // .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + // .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, + // .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + // .image = m_swapchain->get_image(image_idx), + // .range = vk::Image::full_color_range, + // .subresourceRange = VkImageSubresourceRange{ + // .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + // .baseMipLevel = 0u, + // .levelCount = VK_REMAINING_MIP_LEVELS, + // .baseArrayLayer = 0u, + // .layerCount = VK_REMAINING_ARRAY_LAYERS, + // }, + // }; + // + // + // vk_cmd_pipeline_barrier( + // cmd, + // VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // 0, + // 0, + // nullptr, + // 0, + // nullptr, + // 1, + // &begin_frame_barrier + // ); + // + // const auto end_frame_barrier = VkImageMemoryBarrier { + // .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + // .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | + // VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, .dstAccessMask = {}, .oldLayout = + // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + // .image = m_swapchain->get_image(image_idx), + // + // .subresourceRange = VkImageSubresourceRange{ + // .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + // .baseMipLevel = 0u, + // .levelCount = VK_REMAINING_MIP_LEVELS, + // .baseArrayLayer = 0u, + // .layerCount = VK_REMAINING_ARRAY_LAYERS, + // }, + // }; + // vk_cmd_pipeline_barrier( + // cmd, + // VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + // VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, + // 0, + // 0, + // nullptr, + // 0, + // nullptr, + // 1, + // &end_frame_barrier + // ); + + // const auto scissor = VkRect2D { + // .offset = { .x = 0u, .y = 0u }, + // .extent = m_resolution, + // }; + // const auto viewport = VkViewport { + // .x = 0.0f, + // .y = 0.0f, + // .width = static_cast(m_resolution.width), + // .height = static_cast(m_resolution.height), + // .minDepth = 0.0f, + // .maxDepth = 1.0f, + // }; + + // const auto color_attachment_info = VkRenderingAttachmentInfoKHR { + // .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, + // .imageView = m_swapchain->get_image_view(image_idx), + // .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + // .resolveMode = VK_RESOLVE_MODE_NONE, + // .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, + // .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + // .clearValue = VkClearValue { .color = { 0.93, 0.93, 0.93, 1.0 } }, + // }; + + // const auto rendering_info = VkRenderingInfoKHR { + // .sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, + // .renderArea = scissor, + // .layerCount = 1, + // .colorAttachmentCount = 1, + // .pColorAttachments = &color_attachment_info, + // + // }; + m_staging_map = {}; m_sprite_vertex_map = {}; + cmd.begin({}); m_staging_buffer.unmap(); - const auto buffer_copy_info = VkBufferCopy { - - .srcOffset = m_staging_offset, - .dstOffset = m_staging_offset, - .size = m_current_sprite_idx * sizeof(components::Sprite::Vertex), - }; - - vk_cmd_copy_buffer(cmd, m_staging_buffer.vk(), m_vertex_buffer.vk(), 1u, &buffer_copy_info); -} - -void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx) -{ - const auto cmd_begin_info = VkCommandBufferBeginInfo { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .flags = {}, - .pInheritanceInfo = nullptr, - }; - - const auto begin_frame_barrier = VkImageMemoryBarrier { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .srcAccessMask = {}, - .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED, - .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .image = m_swapchain->get_image(image_idx), - .subresourceRange = VkImageSubresourceRange{ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0u, - .levelCount = VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = 0u, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, - - }; - - const auto end_frame_barrier = VkImageMemoryBarrier { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - .dstAccessMask = {}, - .oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - .image = m_swapchain->get_image(image_idx), - - .subresourceRange = VkImageSubresourceRange{ - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0u, - .levelCount = VK_REMAINING_MIP_LEVELS, - .baseArrayLayer = 0u, - .layerCount = VK_REMAINING_ARRAY_LAYERS, - }, - }; - - const auto scissor = VkRect2D { - .offset = { .x = 0u, .y = 0u }, - .extent = m_resolution, - }; - - const auto viewport = VkViewport { - .x = 0.0f, - .y = 0.0f, - .width = static_cast(m_resolution.width), - .height = static_cast(m_resolution.height), - .minDepth = 0.0f, - .maxDepth = 1.0f, - }; - - const auto color_attachment_info = VkRenderingAttachmentInfoKHR { - .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, - .imageView = m_swapchain->get_image_view(image_idx), - .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .resolveMode = VK_RESOLVE_MODE_NONE, - .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .clearValue = VkClearValue { .color = { 0.93, 0.93, 0.93, 1.0 } }, - }; - - const auto rendering_info = VkRenderingInfoKHR { - .sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, - .renderArea = scissor, - .layerCount = 1, - .colorAttachmentCount = 1, - .pColorAttachments = &color_attachment_info, - - }; - - vk_reset_command_buffer(cmd, {}); - vkc(vk_begin_command_buffer(cmd, &cmd_begin_info)); - flush_buffers(cmd); - - vk_cmd_push_constants( - cmd, - m_pass->get_layout(), - VK_SHADER_STAGE_VERTEX_BIT, - 0u, - sizeof(FrameConstants), - &m_frame_constants + cmd.copy( + { + .src_buffer = &m_staging_buffer.vk(), + .dst_buffer = &m_vertex_buffer.vk(), + .src_offset = m_staging_offset, + .dst_offset = m_staging_offset, + .size = m_current_sprite_idx * sizeof(components::Sprite::Vertex), + } ); - vk_cmd_pipeline_barrier( - cmd, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - 0, - 0, - nullptr, - 0, - nullptr, - 1, - &begin_frame_barrier + cmd.push_constants( + { + .layout = &m_pass->get_layout(), + .shader_stages = vk::ShaderStageFlags::vertex_bit, + .offset = 0u, + .size = sizeof(FrameConstants), + .data = &m_frame_constants, + } ); - vk_cmd_begin_rendering(cmd, &rendering_info); - vk_cmd_bind_pipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pass->get_pipeline()); - vk_cmd_set_viewport(cmd, 0, 1, &viewport); - vk_cmd_set_scissors(cmd, 0, 1, &scissor); - vk_cmd_draw(cmd, m_current_sprite_idx, 1, 0, 0); - vk_cmd_end_rendering(cmd); - vk_cmd_pipeline_barrier( - cmd, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - 0, - 0, - nullptr, - 0, - nullptr, - 1, - &end_frame_barrier + + using AccessFlagBits = vk::CommandBuffer::ImageBarrierInfo::AccessFlagBits; + cmd.image_barrier( + { + .image = &m_swapchain->get_image(image_idx), + .range = vk::Image::full_color_range, + .src_stages = vk::PipelineStageFlags::color_attachment_output_bit, + .dst_stages = vk::PipelineStageFlags::color_attachment_output_bit, + .src_accesses = AccessFlagBits::none, + .dst_accesses = AccessFlagBits::color_attachment_write, + .src_layout = vk::Image::Layout::undefined, + .dst_layout = vk::Image::Layout::color_attachment_optimal, + } ); - vkc(vk_end_command_buffer(cmd)); + + using Attachment = vk::CommandBuffer::RenderingInfo::AttachmentInfo; + cmd.begin_rendering( + { + .area_offset = {0u, 0u,}, + .area_extent = m_resolution, + .color_attachments = std::vector { + Attachment{ + .view= &m_swapchain->get_image_view(image_idx), + .layout = vk::Image::Layout::color_attachment_optimal, + .load_operation = Attachment::LoadOperation::load, + .store_operation = Attachment::StoreOperation::store, + .color_clear_values = {.5f, .5f, .5f, 1.f} + } + } + } + ); + cmd.bind_pipeline(m_pass->get_pipeline(), vk::Pipeline::BindPoint::graphics); + // cmd.set_viewport(); + // cmd.set_scissors(); + cmd.draw( + { + .vertex_count = static_cast(m_current_sprite_idx), + .instance_count = 1u, + .first_vertex = 0u, + .first_instance = 0u, + } + ); + + cmd.end_rendering(); + cmd.image_barrier( + { + .image = &m_swapchain->get_image(image_idx), + .src_stages = vk::PipelineStageFlags::color_attachment_output_bit, + .dst_stages = vk::PipelineStageFlags::bottom_of_pipe_bit, + .src_accesses = AccessFlagBits::color_attachment_read + | AccessFlagBits::color_attachment_write, + .dst_accesses = {}, + .src_layout = vk::Image::Layout::color_attachment_optimal, + .dst_layout = vk::Image::Layout::present_src, + + } + ); + cmd.end(); } void Renderer::submit_sprite( @@ -462,5 +439,3 @@ void Renderer::submit_sprite( .color = sprite.color, }; } - -} // namespace lt::renderer::vk