From 883f683ce489921488a1cfbc9263d09542b887ea Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 6 Dec 2025 13:04:57 -0500 Subject: [PATCH 1/2] Can now configure Vulkan with JSON. ENJOY! --- json_mods.hpp | 34 +++++++++++++++++++++++++ meson.build | 2 ++ trash_test.hpp | 8 ++++++ vk_engine.cpp | 2 +- vk_initializers.cpp | 54 +++++++++++++++++++++++++++++----------- wraps/nlohmann_json.wrap | 11 ++++++++ 6 files changed, 96 insertions(+), 15 deletions(-) create mode 100644 json_mods.hpp create mode 100644 trash_test.hpp create mode 100644 wraps/nlohmann_json.wrap diff --git a/json_mods.hpp b/json_mods.hpp new file mode 100644 index 0000000..85481af --- /dev/null +++ b/json_mods.hpp @@ -0,0 +1,34 @@ +#pragma once +#include +#include +#include + +#define ENROLL_COMPONENT(COMPONENT, ...) \ + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(COMPONENT, __VA_ARGS__); \ + template <> struct NameOf { \ + static constexpr const char *name = #COMPONENT; \ + }; + +// partial specialization (full specialization works too) +namespace nlohmann { + template + struct adl_serializer> { + static void to_json(json& j, const std::optional& opt) { + if (opt == std::nullopt) { + j = nullptr; + } else { + j = *opt; // this will call adl_serializer::to_json which will + // find the free function to_json in T's namespace! + } + } + + static void from_json(const json& j, std::optional& opt) { + if (j.is_null() || j == false) { + opt = std::nullopt; + } else { + opt = std::make_optional(j.template get()); + // same as above, but with adl_serializer::from_json + } + } + }; +} diff --git a/meson.build b/meson.build index deacd3f..9d89fea 100644 --- a/meson.build +++ b/meson.build @@ -104,6 +104,7 @@ else }) endif +json = subproject('nlohmann_json').get_variable('nlohmann_json_dep') vkbootstrap_proj = cmake.subproject('vk-bootstrap', options: vk_opts) vkbootstrap = vkbootstrap_proj.get_variable('vk_bootstrap_dep') @@ -113,6 +114,7 @@ dependencies += [ glm, imgui, sdl2, + json, ] sources = [ diff --git a/trash_test.hpp b/trash_test.hpp new file mode 100644 index 0000000..e750836 --- /dev/null +++ b/trash_test.hpp @@ -0,0 +1,8 @@ +#include "vk_types.h" +#include "json_mods.hpp" + +template struct NameOf; + +ENROLL_COMPONENT(VkSemaphoreCreateInfo, sType); +ENROLL_COMPONENT(VkFenceCreateInfo, sType); +ENROLL_COMPONENT(VkImageViewCreateInfo, sType, viewType, subresourceRange.baseMipLevel, subresourceRange.levelCount, subresourceRange.baseArrayLayer, subresourceRange.layerCount); diff --git a/vk_engine.cpp b/vk_engine.cpp index da914ab..7fcec8f 100644 --- a/vk_engine.cpp +++ b/vk_engine.cpp @@ -19,7 +19,7 @@ #define VMA_IMPLEMENTATION #include "vk_mem_alloc.h" -constexpr bool bUseValidationLayers = true; +constexpr bool bUseValidationLayers = false; VulkanEngine* loadedEngine = nullptr; diff --git a/vk_initializers.cpp b/vk_initializers.cpp index 3c30974..c31d17b 100644 --- a/vk_initializers.cpp +++ b/vk_initializers.cpp @@ -1,4 +1,40 @@ #include +#include +#include "trash_test.hpp" + +nlohmann::json DATA = nlohmann::json::parse(R"( + { + "VkSemaphoreCreateInfo": { + "draw": { + "sType": 9 + } + }, + "VkFenceCreateInfo": { + "draw": { + "sType": 8 + } + }, + "VkImageViewCreateInfo": { + "draw": { + "sType": 15, + "viewType": 1, + "subresourceRange.baseMipLevel": 0, + "subresourceRange.levelCount": 1, + "subresourceRange.baseArrayLayer": 0, + "subresourceRange.layerCount": 1 + } + } + } +)"); + +template COMPONENT load(nlohmann::json &data, const std::string& profile) { + COMPONENT result{}; + auto& type_stuff = data[NameOf::name]; + auto& profile_data = type_stuff[profile]; + nlohmann::from_json(profile_data, result); + return result; +} + VkCommandPoolCreateInfo vkinit::command_pool_create_info(uint32_t queueFamilyIndex, VkCommandPoolCreateFlags flags /*= 0*/) @@ -27,19 +63,16 @@ VkCommandBufferAllocateInfo vkinit::command_buffer_allocate_info( VkFenceCreateInfo vkinit::fence_create_info(VkFenceCreateFlags flags /*=0*/) { - VkFenceCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - info.pNext = nullptr; + auto info = load(DATA, "draw"); info.flags = flags; return info; } VkSemaphoreCreateInfo vkinit::semaphore_create_info(VkSemaphoreCreateFlags flags/*=0*/) { - VkSemaphoreCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - info.pNext = nullptr; + auto info = load(DATA, "draw"); info.flags = flags; + return info; } @@ -133,17 +166,10 @@ VkImageCreateInfo vkinit::image_create_info(VkFormat format, VkImageUsageFlags u VkImageViewCreateInfo vkinit::imageview_create_info(VkFormat format, VkImage image, VkImageAspectFlags aspectFlags) { - VkImageViewCreateInfo info{}; - info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - info.pNext = nullptr; + auto info = load(DATA, "draw"); - info.viewType = VK_IMAGE_VIEW_TYPE_2D; info.image = image; info.format = format; - info.subresourceRange.baseMipLevel = 0; - info.subresourceRange.levelCount = 1; - info.subresourceRange.baseArrayLayer = 0; - info.subresourceRange.layerCount = 1; info.subresourceRange.aspectMask = aspectFlags; return info; diff --git a/wraps/nlohmann_json.wrap b/wraps/nlohmann_json.wrap new file mode 100644 index 0000000..8c46676 --- /dev/null +++ b/wraps/nlohmann_json.wrap @@ -0,0 +1,11 @@ +[wrap-file] +directory = nlohmann_json-3.11.3 +lead_directory_missing = true +source_url = https://github.com/nlohmann/json/releases/download/v3.11.3/include.zip +source_filename = nlohmann_json-3.11.3.zip +source_hash = a22461d13119ac5c78f205d3df1db13403e58ce1bb1794edc9313677313f4a9d +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/nlohmann_json_3.11.3-1/nlohmann_json-3.11.3.zip +wrapdb_version = 3.11.3-1 + +[provide] +nlohmann_json = nlohmann_json_dep From 24ae3705c9feeec03c40991fa7cd52b9c91a54d2 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 7 Dec 2025 14:48:34 -0500 Subject: [PATCH 2/2] Attempted to use the vulkan.hpp but it's too much C++ for this. It took 5 hours to just get this one file converted. --- vk_initializers.cpp | 173 ++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 96 deletions(-) diff --git a/vk_initializers.cpp b/vk_initializers.cpp index 3c30974..1d5c28c 100644 --- a/vk_initializers.cpp +++ b/vk_initializers.cpp @@ -1,93 +1,76 @@ #include +// #if !defined( VULKAN_HPP_NO_CONSTRUCTORS ) && !defined( VULKAN_HPP_NO_STRUCT_CONSTRUCTORS ) +// +#define VULKAN_HPP_NO_STRUCT_CONSTRUCTORS 1 +#define VULKAN_HPP_NO_CONSTRUCTORS 1 +#include + VkCommandPoolCreateInfo vkinit::command_pool_create_info(uint32_t queueFamilyIndex, VkCommandPoolCreateFlags flags /*= 0*/) { - VkCommandPoolCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - info.pNext = nullptr; - info.queueFamilyIndex = queueFamilyIndex; - info.flags = flags; - return info; + return vk::CommandPoolCreateInfo{ + .flags=vk::CommandPoolCreateFlags(flags), + .queueFamilyIndex=queueFamilyIndex + }; } VkCommandBufferAllocateInfo vkinit::command_buffer_allocate_info( VkCommandPool pool, uint32_t count /*= 1*/) { - VkCommandBufferAllocateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - info.pNext = nullptr; - - info.commandPool = pool; - info.commandBufferCount = count; - info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - return info; + return vk::CommandBufferAllocateInfo{ + .commandPool=pool, + .level=vk::CommandBufferLevel::ePrimary, + .commandBufferCount=count + }; } VkFenceCreateInfo vkinit::fence_create_info(VkFenceCreateFlags flags /*=0*/) { - VkFenceCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - info.pNext = nullptr; - info.flags = flags; - return info; + return vk::FenceCreateInfo{ + .flags=vk::FenceCreateFlags(flags) + }; } VkSemaphoreCreateInfo vkinit::semaphore_create_info(VkSemaphoreCreateFlags flags/*=0*/) { - VkSemaphoreCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - info.pNext = nullptr; - info.flags = flags; - return info; + return vk::SemaphoreCreateInfo{ + .flags=vk::SemaphoreCreateFlags(flags) + }; } VkCommandBufferBeginInfo vkinit::command_buffer_begin_info(VkCommandBufferUsageFlags flags /*= 0*/) { - VkCommandBufferBeginInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - info.pNext = nullptr; - - info.pInheritanceInfo = nullptr; - info.flags = flags; - return info; + return vk::CommandBufferBeginInfo{ + .flags=vk::CommandBufferUsageFlags(flags) + }; } VkImageSubresourceRange vkinit::image_subresource_range(VkImageAspectFlags aspectMask) { - VkImageSubresourceRange subImage {}; - subImage.aspectMask = aspectMask; - subImage.baseMipLevel = 0; - subImage.levelCount = VK_REMAINING_MIP_LEVELS; - subImage.baseArrayLayer = 0; - subImage.layerCount = VK_REMAINING_ARRAY_LAYERS; - - return subImage; + return vk::ImageSubresourceRange{ + vk::ImageAspectFlags(aspectMask), + 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS + }; } VkSemaphoreSubmitInfo vkinit::semaphore_submit_info(VkPipelineStageFlags2 stageMask, VkSemaphore semaphore) { - VkSemaphoreSubmitInfo submitInfo{}; - submitInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO; - submitInfo.pNext = nullptr; - submitInfo.semaphore = semaphore; - submitInfo.stageMask = stageMask; - submitInfo.deviceIndex = 0; - submitInfo.value = 1; - - return submitInfo; + return vk::SemaphoreSubmitInfo{ + .semaphore=vk::Semaphore{semaphore}, + .value=1, + .stageMask=vk::PipelineStageFlags2{stageMask}, + .deviceIndex=0, + }; } VkCommandBufferSubmitInfo vkinit::command_buffer_submit_info(VkCommandBuffer cmd) { - VkCommandBufferSubmitInfo info{}; - info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO; - info.pNext = nullptr; - info.commandBuffer = cmd; - info.deviceMask = 0; - - return info; + return vk::CommandBufferSubmitInfo{ + .commandBuffer=cmd, // commandBuffer + .deviceMask=0, // deviceMask + }; } VkSubmitInfo2 vkinit::submit_info(VkCommandBufferSubmitInfo* cmd, VkSemaphoreSubmitInfo* signalSemaphoreInfo, @@ -111,58 +94,56 @@ VkSubmitInfo2 vkinit::submit_info(VkCommandBufferSubmitInfo* cmd, VkSemaphoreSub VkImageCreateInfo vkinit::image_create_info(VkFormat format, VkImageUsageFlags usageFlags, VkExtent3D extent) { - VkImageCreateInfo info{}; - info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - info.pNext = nullptr; - - info.imageType = VK_IMAGE_TYPE_2D; - - info.format = format; - info.extent = extent; - - info.mipLevels = 1; - info.arrayLayers = 1; - - info.samples = VK_SAMPLE_COUNT_1_BIT; - - info.tiling = VK_IMAGE_TILING_OPTIMAL; - info.usage = usageFlags; - - return info; + return vk::ImageCreateInfo{ + .flags=vk::ImageCreateFlags(0), + .imageType=vk::ImageType::e2D, + .format=vk::Format{format}, + .extent=vk::Extent3D{extent.width, extent.height, extent.depth}, + .mipLevels=1, + .arrayLayers=1, + .samples=vk::SampleCountFlagBits::e1, + .tiling=vk::ImageTiling::eOptimal, + .usage=vk::ImageUsageFlags{usageFlags}, + }; } VkImageViewCreateInfo vkinit::imageview_create_info(VkFormat format, VkImage image, VkImageAspectFlags aspectFlags) { - VkImageViewCreateInfo info{}; - info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - info.pNext = nullptr; - - info.viewType = VK_IMAGE_VIEW_TYPE_2D; - info.image = image; - info.format = format; - info.subresourceRange.baseMipLevel = 0; - info.subresourceRange.levelCount = 1; - info.subresourceRange.baseArrayLayer = 0; - info.subresourceRange.layerCount = 1; - info.subresourceRange.aspectMask = aspectFlags; - - return info; + return vk::ImageViewCreateInfo{ + .image=image, + .viewType=vk::ImageViewType::e2D, + .format=vk::Format{format}, + .subresourceRange{ + .aspectMask=vk::ImageAspectFlags{aspectFlags}, + .baseMipLevel=0, + .levelCount=1, + .baseArrayLayer=0, + .layerCount=1, + } + }; } VkRenderingAttachmentInfo vkinit::attachment_info( VkImageView view, VkClearValue* clear ,VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/) { - VkRenderingAttachmentInfo colorAttachment {}; - colorAttachment.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO; - colorAttachment.pNext = nullptr; - - colorAttachment.imageView = view; - colorAttachment.imageLayout = layout; - colorAttachment.loadOp = clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + vk::RenderingAttachmentInfo colorAttachment{ + .imageView=view, + .imageLayout=vk::ImageLayout(layout), + .loadOp=vk::AttachmentLoadOp(clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD), + .storeOp=vk::AttachmentStoreOp(VK_ATTACHMENT_STORE_OP_STORE), + }; if (clear) { - colorAttachment.clearValue = *clear; + vk::ArrayWrapper1D thefuckingcolor{{ + clear->color.float32[0], + clear->color.float32[1], + clear->color.float32[2], + clear->color.float32[3], + }}; + + colorAttachment.clearValue = vk::ClearValue{ + .color = thefuckingcolor + }; } return colorAttachment;