wip: convert from include style to module import style :D

This commit is contained in:
light7734 2025-11-09 12:05:50 +03:30
parent 6635d6396d
commit a7be2fa370
Signed by: light7734
GPG key ID: 8C30176798F1A6BA
17 changed files with 1486 additions and 984 deletions

View file

@ -1,248 +0,0 @@
---
Checks: "-*,
performance-unnecessary-value-param,
performance-unnecessary-copy-initialization,
performance-type-promotion-in-math-fn,
performance-trivially-destructible,
performance-noexcept-swap,
performance-noexcept-move-constructor,
performance-noexcept-destructor,
performance-no-int-to-ptr,
performance-no-automatic-move,
performance-move-constructor-init,
performance-move-const-arg,
performance-inefficient-vector-operation,
performance-inefficient-string-concatenation,
performance-inefficient-algorithm,
performance-implicit-conversion-in-loop,
performance-for-range-copy,
performance-faster-string-find,
performance-enum-size,
performance-avoid-endl,
readability-avoid-const-params-in-decls,
readability-avoid-nested-conditional-operator,
readability-avoid-return-with-void-value,
readability-avoid-unconditional-preprocessor-if,
readability-braces-around-statements,
readability-const-return-type,
readability-container-contains,
readability-container-data-pointdr,
readability-container-size-empty,
readability-delete-null-pointer,
readability-duplicate-include,
readability-else-after-return,
readability-inconsistent-declaration-parameter-name,
readability-isolate-declaration,
readability-make-member-function-const,
readability-misleading-indentation,
readability-misplaced-array-index,
readability-named-parameter,
readability-non-const-parameter,
readability-qualified-auto,
readability-redundant-access-specifiers,
readability-redundant-casting,
readability-redundant-control-flow,
readability-redundant-declaration,
readability-redundant-function-ptr-dereference,
readability-redundant-inline-specifier,
readability-redundant-member-init,
readability-redundant-preprocessor,
readability-redundant-smartptr-get,
readability-redundant-string-cstr,
readability-reference-to-constructed-temporary,
readability-simplify-boolean-expr,
readability-simplify-subscript-expr,
readability-static-accessed-through-instance,
readability-static-definition-in-anonymous-namespace,
readability-string-compare,
readability-suspicious-call-argument,
readability-uniqueptr-delete-release,
readability-use-anyofallof
readability-use-std-min-max,
readability-function-cognitive-complexity
readability-function-size
readability-identifier-naming
readability-identifier-length
readability-magic-numbers
modernize-avoid-bind,
modernize-avoid-c-arrays,
modernize-concat-nested-namespaces,
modernize-deprecated-headers,
modernize-deprecated-ios-base-aliases,
modernize-loop-convert,
modernize-macro-to-enum,
modernize-make-shared,
modernize-make-unique,
modernize-pass-by-value,
modernize-raw-string-literal,
modernize-redundant-void-arg,
modernize-replace-auto-ptr,
modernize-replace-disallow-copy-and-assign-macro,
modernize-replace-random-shuffle,
modernize-return-braced-init-list,
modernize-shrink-to-fit,
modernize-type-traits,
modernize-unary-static-assert,
modernize-use-auto,
modernize-use-bool-literals,
modernize-use-constraints,
modernize-use-default-member-init,
modernize-use-designated-initializers,
modernize-use-emplace,
modernize-use-equals-default,
modernize-use-equals-delete,
modernize-use-nodiscard,
modernize-use-noexcept,
modernize-use-nullptr,
modernize-use-override,
modernize-use-starts-ends-with,
modernize-use-std-numbers,
modernize-use-std-print,
modernize-use-transparent-functors,
modernize-use-uncaught-exceptions,
modernize-use-using
modernize-min-max-use-initializer-list,
cppcoreguidelines-avoid-capturing-lambda-coroutines,
cppcoreguidelines-avoid-const-or-ref-data-members,
cppcoreguidelines-avoid-do-while,
cppcoreguidelines-avoid-goto,
cppcoreguidelines-avoid-non-const-global-variables,
cppcoreguidelines-avoid-reference-coroutine-parameters,
cppcoreguidelines-init-variables,
cppcoreguidelines-interfaces-global-init,
cppcoreguidelines-macro-usage,
cppcoreguidelines-misleading-capture-default-by-value,
cppcoreguidelines-missing-std-forward,
cppcoreguidelines-narrowing-conversions,
cppcoreguidelines-no-malloc,
cppcoreguidelines-no-suspend-with-lock,
cppcoreguidelines-owning-memory,
cppcoreguidelines-prefer-member-initializer,
cppcoreguidelines-pro-bounds-array-to-pointer-decay,
cppcoreguidelines-pro-bounds-pointer-arithmetic,
cppcoreguidelines-pro-type-const-cast,
cppcoreguidelines-pro-type-cstyle-cast,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-pro-type-vararg,
cppcoreguidelines-rvalue-reference-param-not-moved,
cppcoreguidelines-slicing,
cppcoreguidelines-special-member-functions,
cppcoreguidelines-virtual-class-destructor,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-assignment-in-if-condition,
bugprone-bad-signal-to-kill-thread,
bugprone-bool-pointer-implicit-conversion,
bugprone-branch-clone,
bugprone-casting-through-void,
bugprone-chained-comparison,
bugprone-compare-pointer-to-member-virtual-function,
bugprone-copy-constructor-init,
bugprone-crtp-constructor-accessibility,
bugprone-dangling-handle,
bugprone-empty-catch,
bugprone-exception-escape,
bugprone-fold-init-type,
bugprone-forward-declaration-namespace,
bugprone-forwarding-reference-overload,
bugprone-implicit-widening-of-multiplication-result,
bugprone-inaccurate-erase,
bugprone-inc-dec-in-conditions,
bugprone-incorrect-enable-if,
bugprone-incorrect-roundings,
bugprone-infinite-loop,
bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multi-level-implicit-pointer-conversion,
bugprone-multiple-new-in-one-expression,
bugprone-multiple-statement-macro,
bugprone-no-escape,
bugprone-non-zero-enum-to-bool-conversion,
bugprone-not-null-terminated-result,
bugprone-optional-value-conversion,
bugprone-parent-virtual-call,
bugprone-posix-return,
bugprone-redundant-branch-condition,
bugprone-reserved-identifier,
bugprone-return-const-ref-from-parameter,
bugprone-shared-ptr-array-mismatch,
bugprone-signal-handler,
bugprone-signed-char-misuse,
bugprone-sizeof-container,
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-standalone-empty,
bugprone-string-constructor,
bugprone-string-integer-assignment,
bugprone-string-literal-with-embedded-nul,
bugprone-stringview-nullptr,
bugprone-suspicious-enum-usage,
bugprone-suspicious-include,
bugprone-suspicious-memory-comparison,
bugprone-suspicious-memset-usage,
bugprone-suspicious-missing-comma,
bugprone-suspicious-realloc-usage,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-suspicious-stringview-data-usage,
bugprone-swapped-arguments,
bugprone-switch-missing-default-case,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-unchecked-optional-access,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-exception-at-new,
bugprone-unhandled-self-assignment,
bugprone-unique-ptr-array-mismatch,
bugprone-unsafe-functions,
bugprone-unused-local-non-trivial-variable,
bugprone-unused-raii,
bugprone-unused-return-value,
bugprone-use-after-move,
bugprone-virtual-near-miss,
concurrency-mt-unsafe,
concurrency-thread-canceltype-asynchronous,
misc-use-anonymous-namespace,
misc-unused-using-decls,
misc-unused-parameters,
misc-unused-alias-decls,
misc-uniqueptr-reset-release,
misc-unconventional-assign-operator,
misc-throw-by-value-catch-by-reference,
misc-static-assert,
misc-redundant-expression,
misc-non-private-member-variables-in-classes,
misc-non-copyable-objects,
misc-no-recursion,
misc-new-delete-overloads,
misc-misplaced-const,
misc-misleading-identifier,
misc-misleading-bidirectional,
misc-header-include-cycle,
misc-definitions-in-headers,
misc-coroutine-hostile-raii,
misc-const-correctness,
-hicpp-signed-bitwise,
hicpp-no-assembler,
hicpp-multiway-paths-covered,
hicpp-ignored-remove-result,
hicpp-exception-baseclass,
"

View file

@ -3,7 +3,6 @@ add_library_module(
renderer
INTERFACES
# system.cppm Vulkan - backend
api.cppm
frontends.cppm
factory.cppm
# backends/vk/messenger.cppm backends/vk/library_loader.cppm
@ -12,13 +11,9 @@ add_library_module(
backends/vk/context/gpu.cppm
backends/vk/context/instance.cppm
backends/vk/context/surface.cppm
# backends/vk/context/swapchain.cppm backends/vk/data/buffer.cppm
backends/vk/context/swapchain.cppm
backends/vk/data/buffer.cppm
# backends/vk/renderer/pass.cppm backends/vk/renderer/renderer.cppm frontend
# frontend/messenger.cppm frontend/context/device.cppm
# frontend/context/gpu.cppm frontend/context/instance.cppm
# frontend/context/surface.cppm frontend/context/swapchain.cppm
# frontend/data/buffer.cppm frontend/renderer/renderer.cppm
# frontend/renderer/pass.cppm
)
target_link_libraries(

View file

@ -1,14 +0,0 @@
export module renderer.api;
import std;
namespace lt::renderer {
export enum class Api: std::uint8_t {
none = 0u,
vulkan,
direct_x,
metal,
};
}

View file

@ -22,7 +22,7 @@ public:
return m_device;
}
[[nodiscard]] auto get_family_indices() const -> std::array<std::uint32_t, 2>
[[nodiscard]] auto get_family_indices() const -> std::vector<std::uint32_t>
{
return { m_graphics_queue_family_index, m_present_queue_family_index };
}

View file

@ -1,103 +1,81 @@
#pragma once
export module renderer.backend.vk.swapchain;
import renderer.backend.vk.library_wrapper;
import renderer.backend.vk.surface;
import renderer.backend.vk.device;
import renderer.backend.vk.instance;
import renderer.backend.vk.gpu;
import renderer.frontend;
import math.vec2;
import memory.null_on_move;
import logger;
import std;
#include <memory/pointer_types/null_on_move.hpp>
#include <renderer/backend/vk/utils.hpp>
#include <renderer/backend/vk/vulkan.hpp>
#include <renderer/frontend/context/device.hpp>
#include <renderer/frontend/context/gpu.hpp>
#include <renderer/frontend/context/surface.hpp>
#include <renderer/frontend/context/swapchain.hpp>
namespace lt::renderer::vkb {
namespace lt::renderer::vk {
class Swapchain: public ISwapchain
export class Swapchain: public ISwapchain
{
public:
Swapchain(ISurface *surface, IGpu *gpu, IDevice *device);
~Swapchain() override;
Swapchain(Swapchain &&) = default;
Swapchain(const Swapchain &) = delete;
auto operator=(Swapchain &&) -> Swapchain & = default;
auto operator=(const Swapchain &) const -> Swapchain & = delete;
[[nodiscard]] auto vk() const -> VkSwapchainKHR
[[nodiscard]] auto vk() -> vk::Swapchain &
{
return m_swapchain;
}
[[nodiscard]] auto vk_ptr() -> VkSwapchainKHR *
{
return &m_swapchain;
}
[[nodiscard]] auto get_resolution() const -> VkExtent2D
[[nodiscard]] auto get_resolution() const -> math::uvec2
{
return m_resolution;
}
[[nodiscard]] auto get_format() const -> VkFormat
[[nodiscard]] auto get_format() const -> vk::Format
{
return m_format;
}
[[nodiscard]] auto get_image_count() const -> size_t
[[nodiscard]] auto get_image_count() const -> std::size_t
{
return m_images.size();
}
[[nodiscard]] auto get_image_view(uint32_t idx) -> VkImageView
[[nodiscard]] auto get_image_view(std::uint32_t idx) -> vk::ImageView &
{
return m_image_views[idx];
}
[[nodiscard]] auto get_image(uint32_t idx) -> VkImage
[[nodiscard]] auto get_image(std::uint32_t idx) -> vk::Image &
{
return m_images[idx];
}
[[nodiscard]] auto create_framebuffers_for_pass(VkRenderPass pass) const
-> std::vector<VkFramebuffer>;
private:
[[nodiscard]] auto get_optimal_image_count(
VkSurfaceCapabilitiesKHR capabilities,
uint32_t desired_image_count
) const -> uint32_t;
vk::Surface::Capabilities capabilities,
std::uint32_t desired_image_count
) const -> std::uint32_t;
memory::NullOnMove<class Surface *> m_surface {};
Gpu *m_gpu;
class Gpu *m_gpu {};
Surface *m_surface {};
class Device *m_device {};
Device *m_device;
VkSwapchainKHR m_swapchain = VK_NULL_HANDLE;
vk::Swapchain m_swapchain;
std::vector<VkImage> m_images;
std::vector<vk::Image> m_images;
std::vector<VkImageView> m_image_views;
std::vector<vk::ImageView> m_image_views;
VkExtent2D m_resolution {};
math::uvec2 m_resolution {};
VkFormat m_format {};
vk::Format m_format {};
};
} // namespace lt::renderer::vk
} // namespace lt::renderer::vkb
#include <logger/logger.hpp>
#include <ranges>
#include <renderer/backend/vk/context/device.hpp>
#include <renderer/backend/vk/context/gpu.hpp>
#include <renderer/backend/vk/context/instance.hpp>
#include <renderer/backend/vk/context/surface.hpp>
#include <renderer/backend/vk/context/swapchain.hpp>
#include <renderer/backend/vk/utils.hpp>
namespace lt::renderer::vk {
module :private;
using namespace lt::renderer;
using namespace lt::renderer::vkb;
Swapchain::Swapchain(ISurface *surface, IGpu *gpu, IDevice *device)
: m_surface(static_cast<Surface *>(surface))
@ -106,122 +84,71 @@ Swapchain::Swapchain(ISurface *surface, IGpu *gpu, IDevice *device)
{
static auto idx = 0u;
const auto capabilities = m_gpu->get_surface_capabilities(m_surface->vk());
const auto formats = m_gpu->get_surface_formats(m_surface->vk());
const auto capabilities = m_gpu->vk().get_surface_capabilities(m_surface->vk());
const auto formats = m_gpu->vk().get_surface_formats(m_surface->vk());
// TODO(Light): parameterize
constexpr auto desired_image_count = uint32_t { 3 };
constexpr auto desired_image_count = std::uint32_t { 3u };
const auto surface_format = formats.front();
const auto queue_indices = m_device->get_family_indices();
m_format = surface_format.format;
m_swapchain = m_device->create_swapchain(
VkSwapchainCreateInfoKHR {
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
.surface = m_surface->vk(),
.minImageCount = get_optimal_image_count(capabilities, desired_image_count),
.imageFormat = surface_format.format,
.imageColorSpace = surface_format.colorSpace,
.imageExtent = capabilities.currentExtent,
.imageArrayLayers = 1u,
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = queue_indices.size(),
.pQueueFamilyIndices = queue_indices.data(),
.preTransform = capabilities.currentTransform,
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
.presentMode = VK_PRESENT_MODE_FIFO_KHR, // TODO(Light): parameterize
.clipped = VK_TRUE,
.oldSwapchain = nullptr,
}
);
m_resolution = capabilities.currentExtent;
m_device->name(m_swapchain, "swapchain {}", idx++);
m_device->wait_idle();
m_swapchain = vk::Swapchain(
m_device->vk(),
m_surface->vk(),
vk::Swapchain::CreateInfo {
m_images = m_device->get_swapchain_images(m_swapchain);
m_image_views.resize(m_images.size());
for (auto idx = 0u; auto [image, view] : std::views::zip(m_images, m_image_views))
{
view = m_device->create_image_view(VkImageViewCreateInfo {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.image = image,
.viewType = VK_IMAGE_VIEW_TYPE_2D,
.format = surface_format.format,
.components = VkComponentMapping {
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
.color_space = surface_format.color_space,
.extent = capabilities.current_extent,
.min_image_count = get_optimal_image_count(capabilities, desired_image_count),
.queue_family_indices = m_device->get_family_indices(),
.present_mode = vk::Swapchain::PresentMode::immediate,
.pre_transform = capabilities.current_transform,
}
);
m_resolution = capabilities.current_extent;
m_device->vk().name(m_swapchain, "swapchain {}", idx++);
m_device->vk().wait_idle();
m_images = m_swapchain.get_images();
for (auto idx = 0u; auto &image : m_images)
{
m_image_views.emplace_back(
vk::ImageView {
m_device->vk(),
image,
vk::ImageView::CreateInfo {
.type = vk::ImageView::Type::_2d,
.format = surface_format.format,
.components = {
vk::ImageView::Swizzle::identity,
vk::ImageView::Swizzle::identity,
vk::ImageView::Swizzle::identity,
vk::ImageView::Swizzle::identity,
},
.range = {
.aspect_flags = vk::Image::AspectFlags::color_bit,
.base_mip_level = 0u,
.level_count = 1u,
.base_array_layer = 0u,
.layer_count = 1u,
},
.subresourceRange = VkImageSubresourceRange {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
.baseMipLevel = 0u,
.levelCount = 1u,
.baseArrayLayer = 0u,
.layerCount = 1u,
}
});
m_device->name(image, "swapchain image {}", idx++);
m_device->name(view, "swapchain image view {}", idx++);
}
m_device->wait_idle();
}
Swapchain::~Swapchain()
{
if (!m_surface)
{
return;
}
try
{
m_device->wait_idle();
m_device->destroy_image_views(m_image_views);
m_device->destroy_swapchain(m_swapchain);
m_device->wait_idle();
}
catch (const std::exception &exp)
{
log::error("Failed to destroy swapchain:");
log::error("\twhat: {}", exp.what());
}
}
[[nodiscard]] auto Swapchain::create_framebuffers_for_pass(VkRenderPass pass) const
-> std::vector<VkFramebuffer>
{
auto framebuffers = std::vector<VkFramebuffer>(m_image_views.size());
for (auto idx = 0u; auto &framebuffer : framebuffers)
{
framebuffer = m_device->create_framebuffer(
VkFramebufferCreateInfo {
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
.renderPass = pass,
.attachmentCount = 1u,
.pAttachments = &m_image_views[idx++],
.width = m_resolution.width,
.height = m_resolution.height,
.layers = 1u,
.debug_name = std::format("swapchain image {}", idx++),
},
}
);
}
return framebuffers;
m_device->vk().wait_idle();
}
[[nodiscard]] auto Swapchain::get_optimal_image_count(
VkSurfaceCapabilitiesKHR capabilities,
uint32_t desired_image_count
) const -> uint32_t
vk::Surface::Capabilities capabilities,
std::uint32_t desired_image_count
) const -> std::uint32_t
{
const auto min_image_count = capabilities.minImageCount;
const auto max_image_count = capabilities.maxImageCount;
const auto min_image_count = capabilities.min_image_count;
const auto max_image_count = capabilities.max_image_count;
const auto has_max_limit = max_image_count != 0;
@ -232,7 +159,7 @@ Swapchain::~Swapchain()
return desired_image_count;
}
// Fall-back to 2 if in ange
// Fall-back to 2 if in range
if (min_image_count <= 2 && max_image_count >= 2)
{
return 2;
@ -241,6 +168,3 @@ Swapchain::~Swapchain()
// Fall-back to min_image_count
return min_image_count;
}
} // namespace lt::renderer::vk

View file

@ -1,11 +1,13 @@
#pragma once
export module renderer.backend.vk.buffer;
import renderer.backend.vk.device;
import renderer.backend.vk.gpu;
import renderer.backend.vk.library_wrapper;
import renderer.frontend;
import std;
#include <renderer/backend/vk/raii/raii.hpp>
#include <renderer/frontend/data/buffer.hpp>
namespace lt::renderer::vkb {
namespace lt::renderer::vk {
class Buffer: public IBuffer
export class Buffer: public IBuffer
{
public:
Buffer(class IDevice *device, class IGpu *gpu, const CreateInfo &info);
@ -14,155 +16,146 @@ public:
void unmap() override;
// TODO(Light): this is to make copying possible.
// But it should be removed in the future,
// Right now it's not possible because: buffers can't understand CommandBuffers.
// And I'm not sure how to properly abstract over command buffers,
// before using other APIs...
[[nodiscard]] auto vk()
{
return *m_buffer;
}
[[nodiscard]] auto get_size() const -> size_t override
[[nodiscard]] auto get_size() const -> std::size_t override
{
return m_size;
}
private:
[[nodiscard]] auto determine_allocation_info(Usage usage) const -> VkMemoryAllocateInfo;
[[nodiscard]] auto determine_allocation_info(Usage usage) const -> vk::Memory::AllocateInfo;
[[nodiscard]] auto to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags;
[[nodiscard]] auto to_native_usage_flags(Usage usage) const -> vk::Buffer::UsageFlags;
[[nodiscard]] auto to_native_memory_properties(Usage usage) const -> VkMemoryPropertyFlags;
[[nodiscard]] auto to_native_memory_properties(Usage usage) const -> vk::Memory::PropertyFlags;
[[nodiscard]] auto has_correct_memory_type_bit(uint32_t type_bits, uint32_t type_idx) const
-> bool;
[[nodiscard]] auto has_correct_memory_type_bit(
std::uint32_t type_bits,
std::uint32_t type_idx
) const -> bool;
[[nodiscard]] auto has_required_memory_properties(
uint32_t required_properties,
uint32_t property_flags
std::uint32_t required_properties,
std::uint32_t property_flags
) const -> bool;
Device *m_device {};
Gpu *m_gpu {};
raii::Buffer m_buffer;
vk::Buffer m_buffer;
raii::Memory m_memory;
vk::Memory m_memory;
// TODO(Light): should this reflect the allocation size instead?
size_t m_size {};
std::size_t m_size {};
};
} // namespace lt::renderer::vk
} // namespace lt::renderer::vkb
#include <renderer/backend/vk/context/device.hpp>
#include <renderer/backend/vk/context/gpu.hpp>
#include <renderer/backend/vk/data/buffer.hpp>
namespace lt::renderer::vk {
module :private;
using namespace ::lt::renderer;
using namespace ::lt::renderer::vkb;
Buffer::Buffer(IDevice *device, IGpu *gpu, const CreateInfo &info)
: m_device(static_cast<Device *>(device))
, m_gpu(static_cast<Gpu *>(gpu))
, m_buffer(
m_device,
VkBufferCreateInfo {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
m_device->vk(),
vk::Buffer::CreateInfo {
.size = info.size,
.usage = to_native_usage_flags(info.usage),
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.sharing_mode = vk::SharingMode::exclusive,
}
)
, m_memory(m_device, m_buffer, determine_allocation_info(info.usage))
, m_memory(m_device->vk(), m_buffer, determine_allocation_info(info.usage))
, m_size(info.size)
{
}
[[nodiscard]] auto Buffer::map() -> std::span<std::byte> /* override */
{
return m_device->map_memory(m_memory, m_size, 0ul);
return m_memory.map(m_size, 0ul);
}
void Buffer::unmap() /* override */
{
m_device->unmap_memory(m_memory);
m_memory.unmap();
}
[[nodiscard]] auto Buffer::determine_allocation_info(Usage usage) const -> VkMemoryAllocateInfo
[[nodiscard]] auto Buffer::determine_allocation_info(Usage usage) const -> vk::Memory::AllocateInfo
{
const auto requirements = m_device->get_memory_requirements(m_buffer);
auto memory_properties = m_gpu->get_memory_properties();
const auto requirements = m_buffer.get_memory_requirements();
auto memory_properties = m_gpu->vk().get_memory_properties();
const auto required_properties = to_native_memory_properties(usage);
auto type = 0u;
for (auto idx = 0; idx < memory_properties.memoryTypeCount; ++idx)
for (auto idx = 0; const auto &memory_type : memory_properties.memory_types)
{
const auto property_flags = memory_properties.memoryTypes[idx].propertyFlags;
if (has_correct_memory_type_bit(requirements.memoryTypeBits, idx)
const auto property_flags = memory_type.property_flags;
if (has_correct_memory_type_bit(requirements.memory_type_bits, idx)
&& has_required_memory_properties(required_properties, property_flags))
{
type = idx;
break;
}
++idx;
}
return VkMemoryAllocateInfo {
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
.allocationSize = requirements.size,
.memoryTypeIndex = type,
return vk::Memory::AllocateInfo {
.size = requirements.size,
.memory_type_idx = type,
};
}
[[nodiscard]] auto Buffer::to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags
[[nodiscard]] auto Buffer::to_native_usage_flags(Usage usage) const -> vk::Buffer::UsageFlags
{
using Flags = vk::Buffer::UsageFlags;
using enum vk::Buffer::UsageFlags;
switch (usage)
{
case Usage::vertex: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
case Usage::vertex: return static_cast<Flags>(vertex_buffer_bit | transfer_dst_bit);
case Usage::index: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
case Usage::index: return static_cast<Flags>(index_buffer_bit | transfer_dst_bit);
case Usage::storage:
return VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
case Usage::storage: return static_cast<Flags>(transfer_dst_bit | storage_buffer_bit);
case Usage::staging: return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
case Usage::staging: return transfer_src_bit;
}
}
std::unreachable();
}
[[nodiscard]] auto Buffer::to_native_memory_properties(Usage usage) const -> VkMemoryPropertyFlags
[[nodiscard]] auto Buffer::to_native_memory_properties(Usage usage) const
-> vk::Memory::PropertyFlags
{
using Flags = vk::Memory::PropertyFlags;
using enum vk::Memory::PropertyFlags;
switch (usage)
{
case Usage::vertex:
case Usage::index:
case Usage::storage: return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
case Usage::storage: return device_local_bit;
case Usage::staging:
return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
case Usage::staging: return static_cast<Flags>(host_visible_bit | host_coherent_bit);
}
std::unreachable();
}
[[nodiscard]] auto Buffer::has_correct_memory_type_bit(uint32_t type_bits, uint32_t type_idx) const
-> bool
[[nodiscard]] auto Buffer::has_correct_memory_type_bit(
std::uint32_t type_bits,
std::uint32_t type_idx
) const -> bool
{
return type_bits & (1 << type_idx);
}
[[nodiscard]] auto Buffer::has_required_memory_properties(
uint32_t required_properties,
uint32_t property_flags
std::uint32_t required_properties,
std::uint32_t property_flags
) const -> bool
{
return (property_flags & required_properties) == required_properties;
}
} // namespace lt::renderer::vk

File diff suppressed because it is too large Load diff

View file

@ -37,46 +37,6 @@ private:
VkDebugUtilsMessengerEXT m_object;
};
class Buffer
{
public:
Buffer(Device *device, VkBufferCreateInfo info)
: m_device(device)
, m_object(m_device->create_buffer(info))
{
}
~Buffer()
{
if (m_device)
{
m_device->destroy_buffer(m_object);
}
}
Buffer(Buffer &&) = default;
Buffer(const Buffer &) = delete;
auto operator=(Buffer &&) -> Buffer & = default;
auto operator=(const Buffer &) -> Buffer & = delete;
[[nodiscard]] auto operator*() const -> VkBuffer
{
return m_object;
}
[[nodiscard]] operator VkBuffer() const
{
return m_object;
}
private:
memory::NullOnMove<Device *> m_device {};
VkBuffer m_object;
};
class Memory
{

View file

@ -2,9 +2,10 @@ export module renderer.factory;
import renderer.frontend;
import renderer.backend.vk.device;
import renderer.backend.vk.instance;
import renderer.backend.vk.swapchain;
import renderer.backend.vk.buffer;
import renderer.backend.vk.gpu;
import renderer.backend.vk.surface;
import renderer.api;
import memory.scope;
import debug.assertions;
import ecs.entity;
@ -22,6 +23,9 @@ export namespace lt::renderer {
[[nodiscard]] auto create_gpu(Api target_api, IInstance *instance) -> memory::Scope<IGpu>;
[[nodiscard]] auto create_swapchain(Api target_api, ISurface *surface, IGpu *gpu, IDevice *device)
-> memory::Scope<ISwapchain>;
} // namespace lt::renderer
module :private;
@ -81,3 +85,35 @@ using namespace lt::renderer;
case Api::direct_x: throw std::runtime_error { "Invalid API" };
}
}
[[nodiscard]] auto create_swapchain(Api target_api, ISurface *surface, IGpu *gpu, IDevice *device)
-> memory::Scope<ISwapchain>
{
switch (target_api)
{
case Api::vulkan: return memory::create_scope<vkb::Swapchain>(surface, gpu, device);
case Api::none:
case Api::metal:
case Api::direct_x: throw std::runtime_error { "Invalid API" };
}
}
[[nodiscard]] auto create_buffer(
Api target_api,
class IDevice *device,
class IGpu *gpu,
const IBuffer::CreateInfo &info
) -> memory::Scope<IBuffer>
{
debug::ensure(device, "Failed to create renderer::IBuffer: null device");
debug::ensure(gpu, "Failed to create renderer::IBuffer: null gpu");
debug::ensure(info.size > 0, "Failed to create renderer::IBuffer: null size");
switch (target_api)
{
case Api::vulkan: return memory::create_scope<vkb::Buffer>(device, gpu, info);
case Api::none:
case Api::metal:
case Api::direct_x: throw std::runtime_error { "Invalid API" };
}
}

View file

@ -1,56 +0,0 @@
#pragma once
#include <memory/scope.hpp>
#include <renderer/api.hpp>
namespace lt::renderer {
class ISwapchain
{
public:
[[nodiscard]] static auto create(
Api target_api,
class ISurface *surface,
class IGpu *gpu,
class IDevice *device
) -> memory::Scope<ISwapchain>;
ISwapchain() = default;
virtual ~ISwapchain() = default;
ISwapchain(ISwapchain &&) = default;
ISwapchain(const ISwapchain &) = delete;
auto operator=(ISwapchain &&) -> ISwapchain & = default;
auto operator=(const ISwapchain &) -> ISwapchain & = delete;
};
} // namespace lt::renderer
#include <renderer/backend/vk/context/swapchain.hpp>
#include <renderer/frontend/context/swapchain.hpp>
namespace lt::renderer {
[[nodiscard]] /* static */ auto ISwapchain::create(
Api target_api,
ISurface *surface,
IGpu *gpu,
IDevice *device
) -> memory::Scope<ISwapchain>
{
switch (target_api)
{
case Api::vulkan: return memory::create_scope<vk::Swapchain>(surface, gpu, device);
case Api::none:
case Api::metal:
case Api::direct_x: throw std::runtime_error { "Invalid API" };
}
}
} // namespace lt::renderer

View file

@ -1,27 +0,0 @@
#include <renderer/backend/vk/data/buffer.hpp>
#include <renderer/frontend/data/buffer.hpp>
namespace lt::renderer {
[[nodiscard]] /* static */ auto IBuffer::create(
Api target_api,
class IDevice *device,
class IGpu *gpu,
const CreateInfo &info
) -> memory::Scope<IBuffer>
{
ensure(device, "Failed to create renderer::IBuffer: null device");
ensure(gpu, "Failed to create renderer::IBuffer: null gpu");
ensure(info.size > 0, "Failed to create renderer::IBuffer: null size");
switch (target_api)
{
case Api::vulkan: return memory::create_scope<vk::Buffer>(device, gpu, info);
case Api::none:
case Api::metal:
case Api::direct_x: throw std::runtime_error { "Invalid API" };
}
}
} // namespace lt::renderer

View file

@ -1,66 +0,0 @@
#pragma once
#include <memory/scope.hpp>
#include <renderer/api.hpp>
namespace lt::renderer {
class IBuffer
{
public:
enum class Usage : uint8_t
{
vertex,
index,
storage,
staging,
};
struct CreateInfo
{
Usage usage;
size_t size;
std::string debug_name;
};
struct CopyInfo
{
size_t offset;
size_t size;
};
[[nodiscard]] static auto create(
Api target_api,
class IDevice *device,
class IGpu *gpu,
const CreateInfo &info
) -> memory::Scope<IBuffer>;
IBuffer() = default;
virtual ~IBuffer() = default;
IBuffer(IBuffer &&) = default;
IBuffer(const IBuffer &) = delete;
auto operator=(IBuffer &&) -> IBuffer & = default;
auto operator=(const IBuffer &) -> IBuffer & = delete;
[[nodiscard]] virtual auto map() -> std::span<std::byte> = 0;
virtual void unmap() = 0;
[[nodiscard]] virtual auto get_size() const -> size_t = 0;
private:
};
} // namespace lt::renderer

View file

@ -1,7 +1,6 @@
export module renderer.frontend;
import debug.assertions;
import memory.scope;
import renderer.api;
import bitwise;
import std;

View file

@ -2,25 +2,35 @@ export module renderer.frontend;
import ecs.entity;
import math.vec2;
import renderer.api;
import memory.scope;
import std;
export namespace lt::renderer {
class IDevice
enum class Api : std::uint8_t
{
none = 0u,
vulkan,
direct_x,
metal,
};
class IInstance
{
public:
IDevice() = default;
// [[nodiscard]] static auto get(Api target_api) -> IInstance *;
IInstance() = default;
virtual ~IDevice() = default;
virtual ~IInstance() = default;
IDevice(IDevice &&) = default;
IInstance(IInstance &&) = default;
IDevice(const IDevice &) = delete;
IInstance(const IInstance &) = delete;
auto operator=(IDevice &&) -> IDevice & = default;
auto operator=(IInstance &&) -> IInstance & = default;
auto operator=(const IDevice &) -> IDevice & = delete;
auto operator=(const IInstance &) -> IInstance & = delete;
};
class IGpu
@ -39,21 +49,20 @@ public:
auto operator=(const IGpu &) -> IGpu & = delete;
};
class IInstance
class IDevice
{
public:
// [[nodiscard]] static auto get(Api target_api) -> IInstance *;
IInstance() = default;
IDevice() = default;
virtual ~IInstance() = default;
virtual ~IDevice() = default;
IInstance(IInstance &&) = default;
IDevice(IDevice &&) = default;
IInstance(const IInstance &) = delete;
IDevice(const IDevice &) = delete;
auto operator=(IInstance &&) -> IInstance & = default;
auto operator=(IDevice &&) -> IDevice & = default;
auto operator=(const IInstance &) -> IInstance & = delete;
auto operator=(const IDevice &) -> IDevice & = delete;
};
class ISurface
@ -74,4 +83,78 @@ public:
[[nodiscard]] virtual auto get_framebuffer_size() const -> math::uvec2 = 0;
};
class ISwapchain
{
public:
ISwapchain() = default;
virtual ~ISwapchain() = default;
ISwapchain(ISwapchain &&) = default;
ISwapchain(const ISwapchain &) = delete;
auto operator=(ISwapchain &&) -> ISwapchain & = default;
auto operator=(const ISwapchain &) -> ISwapchain & = delete;
};
class IBuffer
{
public:
enum class Usage : std::uint8_t
{
vertex,
index,
storage,
staging,
};
struct CreateInfo
{
Usage usage;
std::size_t size;
std::string debug_name;
};
struct CopyInfo
{
std::size_t offset;
std::size_t size;
};
[[nodiscard]] static auto create(
Api target_api,
class IDevice *device,
class IGpu *gpu,
const CreateInfo &info
) -> memory::Scope<IBuffer>;
IBuffer() = default;
virtual ~IBuffer() = default;
IBuffer(IBuffer &&) = default;
IBuffer(const IBuffer &) = delete;
auto operator=(IBuffer &&) -> IBuffer & = default;
auto operator=(const IBuffer &) -> IBuffer & = delete;
[[nodiscard]] virtual auto map() -> std::span<std::byte> = 0;
virtual void unmap() = 0;
[[nodiscard]] virtual auto get_size() const -> std::size_t = 0;
private:
};
} // namespace lt::renderer