From 109e33261abe6d22e73d3012f2d70b55fe1e9c39 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 01:26:21 -0700 Subject: [PATCH 001/106] More maintenance and logic cleanup for better flow for refactoring --- CMakeLists.txt | 1 + atlas/core/application copy.cppm | 385 +++++++++++ .../drivers/vulkan/environment_map copy.cppm | 605 ++++++++++++++++++ atlas/drivers/vulkan/environment_map.cppm | 134 ++-- atlas/drivers/vulkan/imgui_context copy.cppm | 481 ++++++++++++++ atlas/drivers/vulkan/mesh copy.cppm | 307 +++++++++ atlas/drivers/vulkan/mesh.cppm | 98 +-- atlas/drivers/vulkan/physical_device.cppm | 23 + atlas/drivers/vulkan/render_system.cppm | 46 +- .../vulkan/shader_resource_group copy.cppm | 443 +++++++++++++ atlas/drivers/vulkan/stb_image.cppm | 89 +++ atlas/drivers/vulkan/swapchain copy.cppm | 352 ++++++++++ editor/CMakeLists.txt | 21 +- editor/application.cpp | 3 +- editor/content_browser_panel.cppm | 43 +- editor/editor.cppm | 10 + editor/editor_world.cppm | 4 +- editor/icon.cppm | 73 +++ editor/level_scene.cppm | 248 ++----- editor/utilities.cppm | 96 +++ 20 files changed, 3096 insertions(+), 366 deletions(-) create mode 100644 atlas/core/application copy.cppm create mode 100644 atlas/drivers/vulkan/environment_map copy.cppm create mode 100644 atlas/drivers/vulkan/imgui_context copy.cppm create mode 100644 atlas/drivers/vulkan/mesh copy.cppm create mode 100644 atlas/drivers/vulkan/shader_resource_group copy.cppm create mode 100644 atlas/drivers/vulkan/stb_image.cppm create mode 100644 atlas/drivers/vulkan/swapchain copy.cppm create mode 100644 editor/editor.cppm create mode 100644 editor/icon.cppm create mode 100644 editor/utilities.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index faa95f62..8f2ea08c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -217,6 +217,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/vulkan/device.cppm atlas/drivers/vulkan/swapchain.cppm atlas/drivers/vulkan/environment_map.cppm + # atlas/drivers/vulkan/stb_image.cppm ) target_sources(${PROJECT_NAME} PUBLIC diff --git a/atlas/core/application copy.cppm b/atlas/core/application copy.cppm new file mode 100644 index 00000000..94166a38 --- /dev/null +++ b/atlas/core/application copy.cppm @@ -0,0 +1,385 @@ +module; + +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include +#include +#include +#include +#include +#include + +export module atlas.application; + +import atlas.core.utilities; +import atlas.core.utilities.poll_state; +import atlas.window; +import atlas.drivers; +import atlas.renderer.context_loader; +import atlas.core.event; +import atlas.drivers.renderer_system; +import atlas.renderer; +import atlas.drivers.vulkan.instance_context; +import atlas.core.scene; +import atlas.core.scene.world; +import atlas.core.event; +import atlas.core.scene.components; + +import atlas.core.math; +import atlas.drivers.vulkan.imgui_context; +import vk; +import atlas.drivers.graphics_context; + +export namespace atlas { + + /** + * @brief application properties settings for the window + */ + struct application_settings { + std::string name = "Undefined"; + uint32_t width = 0; + uint32_t height = 0; + glm::vec4 background_color = { 1.f, 0.5f, 0.5f, 1.f }; + }; + + /** + * @brief represents a single application that gets created by the engine + * internally + * + * There is only ever going to be one application tied to the engine's + * runtime. As the application is given responsibilities of preloading, + * pre-initialization any sort of utilities required by the engine, and any + * form of post-cleanup when the user requests the application to close. + * + */ + class application { + public: + /** + * @brief constructs a new application + * @param p_settings is the specific application settings to configure + * how the application may be setup + */ + application(/*NOLINT*/ ref p_context, + const application_settings& p_params, + event::bus& p_bus) + : m_bus(&p_bus) { + console_log_info( + "application(const application_settings&) initialized!!!"); + + window_params params = { + .width = p_params.width, + .height = p_params.height, + .name = p_params.name, + }; + m_window = + initialize_window(p_context, params, graphics_api::vulkan); + m_initial_window_params = m_window->data(); + event::set_window_size(static_cast(*m_window)); + + m_renderer = + initialize_renderer(p_context, + graphics_api::vulkan, + params, + m_window->current_swapchain().image_size(), + "Renderer"); + m_renderer->set_background_color(p_params.background_color); + + // m_ui_context = vulkan::imgui_context( + // p_context->handle(), m_window->current_swapchain(), *m_window); + + // p_context->submit_resource_free( + // [this]() { m_ui_context.destruct(); }); + + s_instance = this; + + // Setting internal-level listeners for specific events + m_bus->create_listener(); + m_bus->create_listener(); + m_bus->create_listener(); + m_bus->create_immediate_listener(); + m_bus->create_immediate_listener(); + + m_bus->trigger(this, &application::reload_mesh); + m_bus->trigger( + this, &application::reload_material); + } + + ~application() { m_window->close(); } + + /** + * @return the delta time as a float for giving you the timestep every + * frame + */ + static float delta_time() { return s_instance->m_delta_time; } + + /** + * @brief Explicitly is used to execute the application's mainloop + */ + void execute() { + console_log_info("Executing game mainloop!!!"); + + auto start_time = std::chrono::high_resolution_clock::now(); + + ref current_scene = m_current_world->current(); + + invoke_start(current_scene.get()); + + m_renderer->current_scene_context(current_scene); + + // Bug-prone API. + // Due to requiring there to be a valid m_current_scene specified. + // TODO: SHOULD have this API be invoked whenever a + // `current_scene_context` sets a new scene (for invalidation) + m_renderer->preload( + m_window->current_swapchain().swapchain_renderpass()); + + /* + - flecs::system is how your able to schedule changes for given + portions of data in this case the projection/view matrices are + only being changed when flecs::world::progress(g_delta_time) is + being invoked within the mainloop + current_world_scope.system() + + - When users do object->add>(), this automatically gets invoked by the + .system<...> that gets invoked by the mainloop. + */ + current_scene + ->system, + transform, + perspective_camera>() + .each([&](flecs::pair p_pair, + transform& p_transform, + perspective_camera& p_camera) { + float aspect_ratio = m_window->aspect_ratio(); + if (!p_camera.is_active) { + return; + } + + p_pair->projection = glm::mat4(1.f); + + p_pair->projection = + glm::perspective(glm::radians(p_camera.field_of_view), + aspect_ratio, + p_camera.plane.x, + p_camera.plane.y); + p_pair->projection[1][1] *= -1; + p_pair->view = glm::mat4(1.f); + + // This is converting a glm::highp_vec4 to a glm::quat + glm::quat quaternion = to_quat(p_transform.quaternion); + + p_pair->view = + glm::translate(p_pair->view, p_transform.position) * + glm::mat4_cast(quaternion); + + p_pair->view = glm::inverse(p_pair->view); + }); + + /* + - Currently how this works is we query with anything that has a + flecs::pair + - This tells the ecs flecs what to do query for in regards to + specific objects that are a camera + - in the tag:: namespace, this is to imply components that are + empty and just represent tags, to specify their uses. + */ + auto query_camera_objects = + current_scene + ->query_builder, + perspective_camera>() + .build(); + + while (m_window->available()) { + auto current_time = std::chrono::high_resolution_clock::now(); + m_delta_time = + std::chrono::duration( + current_time - start_time) + .count(); + start_time = current_time; + + event::flush_events(); + + // Progresses the flecs::world by one tick (or replaced with + // using the delta time) This also invokes the following + // system call before the mainloop + current_scene->progress(m_delta_time); + + m_current_frame_index = m_window->acquired_next_frame(); + + // Current commands that are going to be iterated through + // Use the acquired swapchain image index for the command buffer + // and swapchain framebuffer so we record and present the same + // image. + ::vk::command_buffer currently_active = + m_window->active_command(m_current_frame_index); + + invoke_physics_update(current_scene.get()); + + invoke_on_update(current_scene.get(), m_delta_time); + + invoke_defer_update(current_scene.get()); + // We want this to be called after late update + // This queries all camera objects within the camera system + // Update -- going to be removing camera system in replacement + // of just simply using flecs::system to keep it simple for the + // time + query_camera_objects.each( + [&](flecs::entity, + flecs::pair p_pair, + perspective_camera& p_camera) { + if (!p_camera.is_active) { + return; + } + + // m_proj_view = p_pair->projection * p_pair->view; + m_projection = p_pair->projection; + m_view = p_pair->view; + }); + + // invalidate imgui context + /* + if (m_initial_window_params.width != m_window->data().width and + m_initial_window_params.height != m_window->data().height) { + m_ui_context.invalidate(m_window->current_swapchain()); + // once we have invalidated the current width/height, we set + // that to its new width/height value post-resizing + // TODO: Make this into a event::window_resize event that + // can be handled! + m_initial_window_params = m_window->data(); + + // Make sure to update the imgui window size + ImGui::SetNextWindowSize(ImVec2( + static_cast(m_initial_window_params.width), + static_cast(m_initial_window_params.height))); + } + */ + + // Prevents things like stalling so the CPU doesnt have to wait + // for the GPU to fully complete before starting on the next + // frame Command buffer uses this to track the frames to process + // its commands. current_frame = (acquired_next_frame + 1) % + // frames_in_flight; auto current_frame = (m_current_frame_index + // + 1) % 2; + + // viewport renderpass to render the 3D screen to the offscreen + // texture + // auto viewport_framebuffer = + // m_ui_context.active_framebuffer(m_current_frame_index % 2u); + m_renderer->begin_frame( + currently_active, + m_window->current_swapchain().settings(), + m_ui_context.viewport_renderpass(), + // viewport_framebuffer, + m_window->current_swapchain().active_framebuffer( + m_current_frame_index), + m_projection, + m_view, + m_current_frame_index); + + m_renderer->end_frame(); + + m_ui_context.begin(currently_active, m_current_frame_index); + + invoke_ui_update(current_scene.get()); + + // final renderpass for rendering the offscreen information to + // the final renderpass + window_params swapchain_extent = + m_window->current_swapchain().settings(); + std::array color = { 0.1f, 0.105f, 0.11f, 1.0f }; + vk::renderpass_begin_params begin_renderpass = { + .current_command = currently_active, + .extent = { swapchain_extent.width, + swapchain_extent.height }, + .current_framebuffer = + m_window->current_swapchain().active_framebuffer( + m_current_frame_index), + .color = color, + .subpass = vk::subpass_contents::inline_bit + }; + m_window->current_swapchain().swapchain_renderpass().begin( + begin_renderpass); + m_ui_context.end(); + m_window->current_swapchain().swapchain_renderpass().end( + currently_active); + currently_active.end(); + + std::array commands = { + currently_active, + }; + m_window->current_swapchain().submit(commands); + + m_window->present(m_current_frame_index); + } + } + + /** + * @brief Performs any post cleanup when user requests the application + * to close + */ + void post_destroy() { console_log_info("Executing post cleanup!!!"); } + + /** + * @brief we only ever have one window + * + * This static function was a means to getting access to the window to + * perform any operations or request any data the window may have to + * provide + */ + // static window& get_window() { return *s_instance->m_window; } + + /* Retrieves the current selected graphics API */ + /** + * @return the currently specified API. + */ + static graphics_api current_api() { return graphics_api::vulkan; } + + /* Returns the currently selected swapchain */ + /** + * @brief gives you the current swapchain handle + * + * TODO: This is not actually needed, and should be removed + */ + VkSwapchainKHR get_current_swapchain() { + return m_window->current_swapchain(); + } + + void current_world(ref p_world) { m_current_world = p_world; } + + void reload_mesh(event::mesh_reload&) { + console_log_info( + "application::trigger invoked from core/application!"); + } + + void reload_material(event::material_reload&) { + console_log_info( + "application::trigger invoked from core/application!"); + } + + protected: + [[nodiscard]] ref renderer_instance() const { + return m_renderer; + } + + private: + float m_delta_time = 0.f; + ref m_current_world; + ref m_window; + window_params m_initial_window_params; + ref m_renderer = nullptr; + glm::mat4 m_projection; + glm::mat4 m_view; + uint32_t m_current_frame_index = -1; + // vulkan::imgui_context m_ui_context; + event::bus* m_bus = nullptr; + static application* s_instance; + }; + + application* application::s_instance = nullptr; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/environment_map copy.cppm b/atlas/drivers/vulkan/environment_map copy.cppm new file mode 100644 index 00000000..9871e6be --- /dev/null +++ b/atlas/drivers/vulkan/environment_map copy.cppm @@ -0,0 +1,605 @@ +module; + +#include +#include +#include +#include +#include +#include +#include + +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif +#include + +#define GLM_FORCE_RADIANS +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +export module atlas.drivers.vulkan.environment_map; + +import atlas.drivers.vulkan.instance_context; + +import vk; + +namespace atlas { + + export struct skybox_uniform { + glm::mat4 proj_view; + }; + + export class environment_map { + public: + environment_map() = default; + + environment_map(const VkDevice& p_device, + const std::filesystem::path& p_filename, + const vk::physical_device& p_physical, + VkRenderPass p_renderpass) + : m_device(p_device) { + create_hdr_skybox(p_filename, + p_physical, + p_physical.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit)); + + create_skybox_pipeline(p_physical, + p_physical.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + p_renderpass); + } + + // ~environment_map() { + // destroy(); + // } + + void create_hdr_skybox(const std::filesystem::path& p_filename, + const vk::physical_device& p_physical, + uint32_t p_memory_properties) { + + stbi_set_flip_vertically_on_load(true); + int w, h, channels; + float* pixels = stbi_loadf( + p_filename.string().c_str(), &w, &h, &channels, STBI_rgb_alpha); + + if (!pixels) { + throw std::runtime_error("Failed to load HDR image at: " + + p_filename.string()); + } + + const uint32_t width = static_cast(w); + const uint32_t height = static_cast(h); + + VkFormat texture_format = VK_FORMAT_R32G32B32A32_SFLOAT; + const uint64_t bytes_per_pixel_channel = 16; // float are 4 bytes + const uint64_t total_size_bytes = + static_cast(width * height * bytes_per_pixel_channel); + const uint64_t image_size = total_size_bytes; + + // Creating staging buffer + // uint32_t property_flag = vk::memory_property::host_visible_bit | + // vk::memory_property::host_cached_bit; + vk::buffer_parameters staging_buffer_params = { + // .physical_memory_properties = p_memory_properties, + .memory_mask = p_memory_properties, + // .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + .usage = vk::buffer_usage::transfer_src_bit, + }; + + vk::buffer staging_buffer = + vk::buffer(m_device, image_size, staging_buffer_params); + + // Creating image handle to storing the HDR data + // VkFormat texture_format = VK_FORMAT_R32G32B32A32_SFLOAT; + vk::image_params skybox_image_params = { + .extent = { + .width = width, + .height = height, + }, + .format = texture_format, + .memory_mask = p_physical.memory_properties(vk::memory_property::device_local_bit), + .aspect = vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::color_attachment_bit, + .mip_levels = 1, + .layer_count = 1, + }; + m_skybox_image = vk::sample_image(m_device, skybox_image_params); + + // Transferring data from the CPU + // void* data = nullptr; + // vkMapMemory(m_device, staging_memory, 0, total_size_bytes, 0, + // &data); std::memcpy(data, pixels, + // static_cast(total_size_bytes)); vkUnmapMemory(m_device, + // staging_memory); + std::span pixels_data( + reinterpret_cast(pixels), image_size); + staging_buffer.transfer(pixels_data, 0); + + // Free CPU pixels immediately after staging copy + stbi_image_free(pixels); + + // 6. Record and Execute Upload + vk::command_params upload_params = { + .levels = vk::command_levels::primary, + .queue_index = 0, // Graphics Queue + .flags = vk::command_pool_flags::reset, + }; + vk::command_buffer upload_cmd(m_device, upload_params); + + upload_cmd.begin(vk::command_usage::one_time_submit); + + // Begin Memory Barrier: Undefined to TRANSFER_DST + m_skybox_image.memory_barrier(upload_cmd, + texture_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + // Performing buffer image copies + // vk::buffer_image_copy image_copy = { + // .extent = skybox_image_params.extent + // }; + vk::buffer_image_copy image_copy{ + .image_offset = { .width = 0, .height = 0, .depth = 0, }, + .image_extent = { .width = skybox_image_params.extent.width, .height = skybox_image_params.extent.height, .depth = 1, }, + }; + staging_buffer.copy_to_image( + upload_cmd, m_skybox_image, std::span(&image_copy, 1)); + + // Begin Memory Barrier: TRANSFER_DST to SHADER_READ_ONLY + m_skybox_image.memory_barrier( + upload_cmd, + texture_format, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + upload_cmd.end(); + + VkQueue graphics_queue; + vkGetDeviceQueue(m_device, 0, 0, &graphics_queue); + + VkCommandBuffer raw_cmd = upload_cmd; + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &raw_cmd, + }; + + vkQueueSubmit(graphics_queue, 1, &submit_info, nullptr); + vkQueueWaitIdle(graphics_queue); + + upload_cmd.destruct(); + staging_buffer.destruct(); + stbi_set_flip_vertically_on_load(false); + } + + void create_buffers(const vk::physical_device& p_physical) { + std::vector vertices = { + // Front Face + vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, -1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, 1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + + // Left Face + vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, -1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + + // Right Face + vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, -1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, 1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + + // Back Face + vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, -1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + + // Top Face + vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, 1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, 1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + + // Bottom Face + vk::vertex_input{ { -1.0f, -1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } }, + vk::vertex_input{ { 1.0f, -1.0f, 1.0f }, + { 1.0f, 1.0f, 1.0f }, + { 0.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f } } + }; + const auto property_flags = static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit); + vk::buffer_parameters vertex_params = { + .memory_mask = p_physical.memory_properties(property_flags), + .property_flags = vk::memory_property::device_local_bit, + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, + }; + + m_skybox_vbo = vk::vertex_buffer(m_device, vertices, vertex_params); + } + + void create_skybox_pipeline(const vk::physical_device& p_physical, + uint32_t p_memory_properties, + const VkRenderPass& p_renderpass) { + create_buffers(p_physical); + std::array attribute_entries = { + vk::vertex_attribute_entry{ + .location = 0, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, position), + }, + vk::vertex_attribute_entry{ + .location = 1, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, color), + }, + vk::vertex_attribute_entry{ + .location = 2, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, normals), + }, + vk::vertex_attribute_entry{ + .location = 3, + .format = vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, uv), + } + }; + std::array attribute = { + vk::vertex_attribute{ + // layout (set = 0, binding = 0) + .binding = 0, + .entries = attribute_entries, + .stride = sizeof(vk::vertex_input), + .input_rate = vk::input_rate::vertex, + }, + }; + + const std::array sources = { + vk::shader_source{ + .filename = "builtin.shaders/skybox/skybox.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "builtin.shaders/skybox/skybox.frag.spv", + .stage = vk::shader_stage::fragment, + }, + }; + + vk::shader_resource_info shader_info = { + .sources = sources, + }; + m_skybox_shaders = vk::shader_resource(m_device, shader_info); + m_skybox_shaders.vertex_attributes(attribute); + + // set=0 binding=0 UBO: mat4 VP + // vk::uniform_params ubo_params = { + // .memory_mask = p_memory_properties, + // .size_bytes = sizeof(skybox_uniform), + // .debug_name = "skybox_ubo", + // .vkSetDebugUtilsObjectNameEXT = nullptr, + // }; + // vk::buffer_parameters ubo_params = { + // .memory_mask = p_memory_properties, + // }; + vk::buffer_parameters uniform_params = { + .memory_mask = p_memory_properties, + .usage = vk::buffer_usage::uniform_buffer_bit, + }; + m_skybox_ubo = + vk::buffer(m_device, sizeof(skybox_uniform), ubo_params); + + skybox_uniform identity = { .proj_view = glm::mat4(1.0f) }; + identity.proj_view[1][1] *= -1; + // m_skybox_ubo.write(std::span(&identity, + // 1)); + m_skybox_ubo.transfer( + std::span(&identity, 1)); + + // set=0 bindings: + // - binding 0: UBO (vertex) + // - binding 1: samplerCube (fragment) + std::array entries = { + vk::descriptor_entry{ + .type = vk::descriptor_type::uniform, + .binding_point = + vk::descriptor_binding_point{ + .binding = 0, .stage = vk::shader_stage::vertex }, + .descriptor_count = 1, + }, + vk::descriptor_entry{ + .type = vk::descriptor_type::combined_image_sampler, + .binding_point = + vk::descriptor_binding_point{ + .binding = 1, .stage = vk::shader_stage::fragment }, + .descriptor_count = 1, + }, + }; + + vk::descriptor_layout desc_layout = { + .slot = 0, + .max_sets = 1, + .entries = entries, + }; + m_skybox_descriptors = + vk::descriptor_resource(m_device, desc_layout); + + const std::array ubo_writes = { + vk::write_buffer{ + .buffer = static_cast(m_skybox_ubo), + .offset = 0, + .range = static_cast(sizeof(skybox_uniform)) }, + }; + const vk::write_buffer_descriptor ubo_write_desc = { + .dst_binding = 0, + .uniforms = ubo_writes, + }; + + const std::array image_writes = { + vk::write_image{ + .sampler = m_skybox_image.sampler(), + .view = m_skybox_image.image_view(), + .layout = vk::image_layout::shader_read_only_optimal, + }, + }; + const vk::write_image_descriptor image_write_desc = { + .dst_binding = 1, + .sample_images = image_writes, + }; + + m_skybox_descriptors.update(std::span(&ubo_write_desc, 1), + std::span(&image_write_desc, 1)); + + const std::array layouts = { + m_skybox_descriptors.layout(), + }; + + const std::array + blend_attachments = { + vk::color_blend_attachment_state{ .blend_enabled = false }, + }; + vk::color_blend_state blend_state = { + .logic_op_enable = false, + .logical_op = vk::logical_op::copy, + .attachments = blend_attachments, + .blend_constants = {}, + }; + + std::array dyn = { + vk::dynamic_state::viewport, + vk::dynamic_state::scissor, + }; + + // pipeline expects a non-const span + std::array pipeline_layouts = layouts; + + vk::pipeline_params pipe_info = { + .renderpass = p_renderpass, + .shader_modules = m_skybox_shaders.handles(), + .vertex_attributes = + m_skybox_shaders.vertex_attributes(), // no vertex input + .vertex_bind_attributes = + m_skybox_shaders.vertex_bind_attributes(), // no vertex input + .descriptor_layouts = pipeline_layouts, + .input_assembly = + vk::input_assembly_state{ + .topology = vk::primitive_topology::triangle_list, + .primitive_restart_enable = false, + }, + .viewport = + vk::viewport_state{ .viewport_count = 1, .scissor_count = 1 }, + .rasterization = + vk::rasterization_state{ + .polygon_mode = vk::polygon_mode::fill, + .cull_mode = vk::cull_mode::front_bit, + // .cull_mode = vk::cull_mode::none, + // .front_face = vk::front_face::counter_clockwise, + .front_face = vk::front_face::clockwise, + .line_width = 1.f, + }, + .multisample = vk::multisample_state{}, + .color_blend = blend_state, + .depth_stencil_enabled = true, + .depth_stencil = + vk::depth_stencil_state{ + .depth_test_enable = true, + .depth_write_enable = false, + .depth_compare_op = vk::compare_op::less_or_equal, + .depth_bounds_test_enable = false, + .stencil_test_enable = false, + }, + .dynamic_states = dyn, + }; + + m_skybox_pipeline = vk::pipeline(m_device, pipe_info); + } + + void update_uniform(const skybox_uniform& p_ubo) { + // m_skybox_ubo.transfer(std::span(&p_ubo, + // 1)); + m_skybox_ubo.update(&p_ubo); + } + + void bind(vk::command_buffer& p_current) { + m_skybox_pipeline.bind(p_current); + m_skybox_descriptors.bind(p_current, m_skybox_pipeline.layout()); + // m_skybox_vbo.bind(p_current); + const VkBuffer vertex = m_skybox_vbo; + p_current.bind_vertex_buffers(std::span(&vertex, 1)); + } + + void draw(const VkCommandBuffer& p_current) { + // bind(p_current); + vkCmdDraw(p_current, m_skybox_vbo.size(), 1, 0, 0); + // vkCmdDrawIndexed(p_current, 36, 1, 0, 0, 0); + } + + //! @brief Retreving the sample image of the environment map. + [[nodiscard]] vk::sample_image image() const { return m_skybox_image; } + + void destroy() { + + m_skybox_image.destruct(); + if (m_skybox_pipeline.alive()) { + m_skybox_pipeline.destruct(); + } + m_skybox_descriptors.destruct(); + m_skybox_ubo.destruct(); + m_skybox_shaders.destruct(); + m_skybox_vbo.destruct(); + } + + //! TODO: Logic for converting the HDR image handles to a skybox + //! samplerCube + void process_to_cubemap() {} + + private: + VkDevice m_device = nullptr; + + vk::sample_image m_skybox_image; + + vk::shader_resource m_skybox_shaders{}; + vk::buffer m_skybox_ubo{}; + vk::descriptor_resource m_skybox_descriptors{}; + vk::pipeline m_skybox_pipeline{}; + vk::vertex_buffer m_skybox_vbo; + }; + +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/environment_map.cppm b/atlas/drivers/vulkan/environment_map.cppm index b06c4c05..3f66ea15 100644 --- a/atlas/drivers/vulkan/environment_map.cppm +++ b/atlas/drivers/vulkan/environment_map.cppm @@ -49,18 +49,13 @@ namespace atlas { VkPhysicalDeviceMemoryProperties p_memory_properties, VkRenderPass p_renderpass) : m_device(p_device) { - create_hdr_skybox(p_filename, p_memory_properties); + m_memory_properties = p_memory_properties; + create_hdr_skybox(p_filename); - create_skybox_pipeline(p_memory_properties, p_renderpass); + create_skybox_pipeline(p_renderpass); } - // ~environment_map() { - // destroy(); - // } - - void create_hdr_skybox( - const std::filesystem::path& p_filename, - VkPhysicalDeviceMemoryProperties p_memory_properties) { + void create_hdr_skybox(const std::filesystem::path& p_filename) { stbi_set_flip_vertically_on_load(true); int w, h, channels; @@ -86,33 +81,37 @@ namespace atlas { vk::memory_property::host_cached_bit; vk::buffer_parameters staging_buffer_params = { .device_size = static_cast(image_size), - .physical_memory_properties = p_memory_properties, + // Replace with .memory_mask + .physical_memory_properties = m_memory_properties, + // Replace with .memory_mask .property_flags = static_cast(property_flag), .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, }; + // Replace to be vk::buffer vk::buffer_stream staging_buffer = vk::buffer_stream(m_device, staging_buffer_params); // Creating image handle to storing the HDR vk::image_params skybox_image_params = { - .extent = { .width = width, .height = height, }, + .extent = { + .width = width, + .height = height, + }, .format = texture_format, + // Replace with .memory_mask .property = vk::memory_property::device_local_bit, .aspect = vk::image_aspect_flags::color_bit, .usage = vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, - .phsyical_memory_properties = p_memory_properties, + // Replace with .memory_mask + .phsyical_memory_properties = m_memory_properties, }; m_skybox_image = vk::sample_image(m_device, skybox_image_params); // Transferring data from the CPU - // void* data = nullptr; - // vkMapMemory(m_device, staging_memory, 0, total_size_bytes, 0, - // &data); std::memcpy(data, pixels, - // static_cast(total_size_bytes)); vkUnmapMemory(m_device, - // staging_memory); + // Replace to using staging_buffer.transfer API std::span pixels_data( reinterpret_cast(pixels), image_size); staging_buffer.write(pixels_data); @@ -120,7 +119,7 @@ namespace atlas { // Free CPU pixels immediately after staging copy stbi_image_free(pixels); - // 6. Record and Execute Upload + // Record and Execute Upload vk::command_params upload_params = { .levels = vk::command_levels::primary, .queue_index = 0, // Graphics Queue @@ -167,34 +166,6 @@ namespace atlas { } void create_buffers() { - std::vector skyboxVertices = { - // positions - -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, - - -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, - -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, - - 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, - - -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, - - -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, - - -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, - 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f - }; - // m_physical = instance_context::physical_driver(); - // m_device = instance_context::logical_device(); - - // std::vector vertices = { - // vk::vertex_input{ - // .position = {-1.0f, 1.0f, -1.0f,} - // }, - // }; std::vector vertices = { // Front Face vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, @@ -352,36 +323,16 @@ namespace atlas { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f } } }; - // for (size_t i = 0; i < skyboxVertices.size(); i += 3) { - // vk::vertex_input v{}; - - // // Assign position from the float array - // v.position = glm::vec3( - // vertices[i], - // vertices[i + 1], - // vertices[i + 2] - // ); - - // // Default values for the remaining fields - // v.color = glm::vec3(1.0f); // Default white - // v.normals = glm::vec3(0.0f); // Or calculate if needed - // v.uv = glm::vec2(0.0f); - - // vertices.push_back(v); - // } vk::vertex_params vbo_params = { - .phsyical_memory_properties = - vulkan::instance_context::physical_driver() - .memory_properties(), + // Replace with .memory_mask + .phsyical_memory_properties = m_memory_properties, .vertices = vertices }; m_skybox_vbo = vk::vertex_buffer(m_device, vbo_params); } - void create_skybox_pipeline( - VkPhysicalDeviceMemoryProperties p_memory_properties, - const VkRenderPass& p_renderpass) { + void create_skybox_pipeline(const VkRenderPass& p_renderpass) { create_buffers(); std::array attribute_entries = { vk::vertex_attribute_entry{ @@ -434,18 +385,19 @@ namespace atlas { // set=0 binding=0 UBO: mat4 VP vk::uniform_params ubo_params = { - .phsyical_memory_properties = p_memory_properties, + .phsyical_memory_properties = m_memory_properties, .size_bytes = sizeof(skybox_uniform), .debug_name = "skybox_ubo", .vkSetDebugUtilsObjectNameEXT = nullptr, }; + // Replace vk::uniform_params with vk::buffer_parameters(m_device, + // sizeof(skybox_uniform), ubo_params); m_skybox_ubo = vk::uniform_buffer(m_device, ubo_params); - // vk::uniform_buffer(m_device, sizeof(skybox_uniform), ubo_params); skybox_uniform identity = { .proj_view = glm::mat4(1.0f) }; identity.proj_view[1][1] *= -1; - // m_skybox_ubo.write(std::span(&identity, - // 1)); + + // Replace with m_skybox_ubo.transfer m_skybox_ubo.update(&identity); // set=0 bindings: @@ -544,8 +496,6 @@ namespace atlas { vk::rasterization_state{ .polygon_mode = vk::polygon_mode::fill, .cull_mode = vk::cull_mode::front_bit, - // .cull_mode = vk::cull_mode::none, - // .front_face = vk::front_face::counter_clockwise, .front_face = vk::front_face::clockwise, .line_width = 1.f, }, @@ -567,19 +517,32 @@ namespace atlas { } void update_uniform(const skybox_uniform& p_ubo) { - // m_skybox_ubo.transfer(std::span(&p_ubo, - // 1)); + // Replace with m_skybox_ubo.transfer(...) m_skybox_ubo.update(&p_ubo); } - void bind(const VkCommandBuffer& p_current) { - m_skybox_pipeline.bind(p_current); - m_skybox_descriptors.bind(p_current, m_skybox_pipeline.layout()); - m_skybox_vbo.bind(p_current); + [[nodiscard]] VkPipelineLayout pipeline_layout() const { + return m_skybox_pipeline.layout(); + } + + [[nodiscard]] VkPipeline pipeline() const { return m_skybox_pipeline; } + + [[nodiscard]] VkDescriptorSetLayout descriptor_layout() const { + return m_skybox_descriptors.layout(); + } + + void descriptor_bind(const VkCommandBuffer& p_command, + const VkPipelineLayout& p_pipeline_layout) { + m_skybox_descriptors.bind(p_command, p_pipeline_layout); + } + + [[nodiscard]] VkBuffer vertex_handle() const { return m_skybox_vbo; } + + [[nodiscard]] uint32_t vertices_size() const { + return m_skybox_vbo.size(); } void draw(const VkCommandBuffer& p_current) { - // bind(p_current); vkCmdDraw(p_current, m_skybox_vbo.size(), 1, 0, 0); // vkCmdDrawIndexed(p_current, 36, 1, 0, 0, 0); } @@ -599,15 +562,10 @@ namespace atlas { m_skybox_vbo.destroy(); } - //! TODO: Logic for converting the HDR image handles to a skybox - //! samplerCube - void process_to_cubemap() {} - private: VkDevice m_device = nullptr; - + VkPhysicalDeviceMemoryProperties m_memory_properties; vk::sample_image m_skybox_image; - vk::shader_resource m_skybox_shaders{}; vk::uniform_buffer m_skybox_ubo{}; vk::descriptor_resource m_skybox_descriptors{}; diff --git a/atlas/drivers/vulkan/imgui_context copy.cppm b/atlas/drivers/vulkan/imgui_context copy.cppm new file mode 100644 index 00000000..92f509d1 --- /dev/null +++ b/atlas/drivers/vulkan/imgui_context copy.cppm @@ -0,0 +1,481 @@ +module; + +#include +#include +#include +#include +#include +#include +#include +#include + +export module atlas.drivers.vulkan.imgui_context; + +import atlas.common; +import vk; + +import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.physical_device; +import atlas.drivers.vulkan.device; +import atlas.drivers.vulkan.swapchain; +import atlas.core.utilities; + +namespace atlas::vulkan { + static void im_gui_layout_color_modification() { + auto& colors = ImGui::GetStyle().Colors; // @note Colors is ImVec4 + + colors[ImGuiCol_WindowBg] = ImVec4{ 0.1f, 0.105f, 0.11f, 1.0f }; + + // Headers + colors[ImGuiCol_Header] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_HeaderHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_HeaderActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Buttons + colors[ImGuiCol_Button] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_ButtonHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_ButtonActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Frame BG + colors[ImGuiCol_FrameBg] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_FrameBgHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_FrameBgActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Tabs + colors[ImGuiCol_Tab] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + colors[ImGuiCol_TabHovered] = ImVec4{ 0.38f, 0.3805f, 0.381f, 1.0f }; + colors[ImGuiCol_TabActive] = ImVec4{ 0.28f, 0.2805f, 0.281f, 1.0f }; + colors[ImGuiCol_TabUnfocused] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; + colors[ImGuiCol_TabUnfocusedActive] = + ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + + // Titles + colors[ImGuiCol_TitleBg] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + colors[ImGuiCol_TitleBgActive] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; + colors[ImGuiCol_TitleBgCollapsed] = + ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; + } + + void transition_image_layout(VkDevice p_device, + vk::sample_image& p_image, + VkFormat p_format, + VkImageLayout p_old, + VkImageLayout p_new) { + vk::command_params copy_command_params = { + .levels = vk::command_levels::primary, + .queue_index = 0, + .flags = vk::command_pool_flags::reset, + }; + vk::command_buffer temp_command_buffer = + vk::command_buffer(p_device, copy_command_params); + + temp_command_buffer.begin(vk::command_usage::one_time_submit); + + p_image.memory_barrier(temp_command_buffer, p_format, p_old, p_new); + + temp_command_buffer.end(); + + VkCommandBuffer handle = temp_command_buffer; + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &handle, + }; + + uint32_t queue_family_index = 0; + uint32_t queue_index = 0; + VkQueue temp_graphics_queue; + vkGetDeviceQueue( + p_device, queue_family_index, queue_index, &temp_graphics_queue); + + vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); + vkQueueWaitIdle(temp_graphics_queue); + + temp_command_buffer.destruct(); + } + + export ImTextureID g_viewport_image_id = nullptr; + export class imgui_context { + public: + imgui_context() = default; + + imgui_context(const VkInstance& p_instance, + const swapchain& p_swapchain_ctx, + GLFWwindow* p_window_ctx) { + m_instance = p_instance; + m_physical = instance_context::physical_driver(); + const uint32_t memory_properties = + instance_context::physical_driver().memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit); + m_driver = instance_context::logical_device(); + // vk::device device_temp = instance_context::physical_driver(); + + m_current_swapchain_handler = p_swapchain_ctx; + m_extent = { .width = p_swapchain_ctx.settings().width, + .height = p_swapchain_ctx.settings().height }; + + // Setting up imgui + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + + io.ConfigFlags |= + ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // + // Enable Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking + io.ConfigFlags |= + ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / + // Platform Windows + + // io.ConfigViewportsNoAutoMerge = true; + // io.ConfigViewportsNoAutoMerge = true; + // io.ConfigViewportsNoTaskBarIcon = true; + + // Setup Dear ImGui style + // ImGui::StyleColorsDark(); + // ImGui::StyleColorsClassic(); + im_gui_layout_color_modification(); + + ImGuiStyle& style = ImGui::GetStyle(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } + + m_viewport_command_buffers.resize(p_swapchain_ctx.image_size()); + + for (size_t i = 0; i < m_viewport_command_buffers.size(); i++) { + ::vk::command_params settings = { + .levels = ::vk::command_levels::primary, + // .queue_index = + // enumerate_swapchain_settings.present_index, + .queue_index = 0, + .flags = ::vk::command_pool_flags::reset, + }; + m_viewport_command_buffers[i] = + ::vk::command_buffer(m_driver, settings); + } + + // ::vk::descriptor_res + // m_imgui_descriptor = ::vk::descriptor_resource(m_driver, {}); + // 1: create descriptor pool for IMGUI + // the size of the pool is very oversize, but it's copied from + // imgui demo itself. + std::array pool_sizes = { + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } + }; + + VkDescriptorPoolCreateInfo desc_pool_create_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .pNext = nullptr, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + .maxSets = static_cast(1000 * pool_sizes.size()), + // .poolSizeCount = (uint32_t)std::size(pool_sizes), + .poolSizeCount = static_cast(pool_sizes.size()), + .pPoolSizes = pool_sizes.data() + }; + + // VkDescriptorPool imgui_pool; + vk::vk_check( + vkCreateDescriptorPool( + m_driver, &desc_pool_create_info, nullptr, &m_desc_pool), + "vkCreateDescriptorPool"); + + create(p_window_ctx, + p_swapchain_ctx.image_size(), + p_swapchain_ctx.swapchain_renderpass()); + + vk::image_params config_image = { + .extent = { .width = p_swapchain_ctx.settings().width, + .height = p_swapchain_ctx.settings().height }, + .format = VK_FORMAT_B8G8R8A8_UNORM, + .property = vk::memory_property::device_local_bit, + .memory_mask = memory_properties, + .aspect = vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::color_attachment_bit | + vk::image_usage::transfer_dst_bit | + vk::image_usage::sampled_bit, + // .usage = vk::image_usage::color_attachment_bit | + // vk::image_usage::transfer_dst_bit, + .address_mode_u = vk::sampler_address_mode::clamp_to_edge, + .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, + .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, + }; + m_viewport_image = vk::sample_image(m_driver, config_image); + + // transition image layout uses image memory barrier + transition_image_layout(m_driver, + m_viewport_image, + VK_FORMAT_B8G8R8A8_UNORM, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + // Viewport-specific render pass: color attachment ends in + // SHADER_READ_ONLY_OPTIMAL so the offscreen texture can be sampled + // by ImGui. (Swapchain pass uses PRESENT_SRC.) + VkFormat depth_format = m_driver.depth_format(); + std::array<::vk::attachment, 2> viewport_attachments = { + ::vk::attachment{ + .format = VK_FORMAT_B8G8R8A8_UNORM, + .layout = ::vk::image_layout::color_optimal, + .samples = ::vk::sample_bit::count_1, + .load = ::vk::attachment_load::clear, + .store = ::vk::attachment_store::store, + .stencil_load = ::vk::attachment_load::clear, + .stencil_store = ::vk::attachment_store::dont_care, + .initial_layout = ::vk::image_layout::undefined, + .final_layout = ::vk::image_layout::shader_read_only_optimal, + }, + ::vk::attachment{ + .format = depth_format, + .layout = ::vk::image_layout::depth_stencil_optimal, + .samples = ::vk::sample_bit::count_1, + .load = ::vk::attachment_load::clear, + .store = ::vk::attachment_store::dont_care, + .stencil_load = ::vk::attachment_load::dont_care, + .stencil_store = ::vk::attachment_store::dont_care, + .initial_layout = ::vk::image_layout::undefined, + .final_layout = ::vk::image_layout::depth_stencil_optimal, + }, + }; + m_viewport_renderpass = + ::vk::renderpass(m_driver, viewport_attachments); + + vk::image_params config_depth_image = { + .extent = { .width = p_swapchain_ctx.settings().width, + .height = p_swapchain_ctx.settings().height }, + .format = m_driver.depth_format(), + .memory_mask = memory_properties, + .property = vk::memory_property::device_local_bit, + .aspect = vk::image_aspect_flags::depth_bit, + // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + .usage = vk::image_usage::depth_stencil_bit, + }; + + m_depth_viewport_image = + vk::sample_image(m_driver, config_depth_image); + + for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { + std::array image_view_attachments = { + m_viewport_image.image_view(), + m_depth_viewport_image.image_view() + }; + + vk::framebuffer_params framebuffer_info = { + .renderpass = m_viewport_renderpass, + .views = image_view_attachments, + .extent = { p_swapchain_ctx.settings().width, + p_swapchain_ctx.settings().height } + }; + m_viewport_framebuffers[i] = + vk::framebuffer(m_driver, framebuffer_info); + } + + g_viewport_image_id = + static_cast(ImGui_ImplVulkan_AddTexture( + m_viewport_image.sampler(), + m_viewport_image.image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + } + + void create(GLFWwindow* p_window_handler, + const uint32_t& p_image_size, + const VkRenderPass& p_current_renderpass) { + ImGui_ImplGlfw_InitForVulkan(p_window_handler, true); + ImGui_ImplVulkan_InitInfo init_info = {}; + init_info.Instance = m_instance; + init_info.PhysicalDevice = m_physical; + init_info.Device = m_driver; + init_info.Queue = m_driver.graphics_queue(); + init_info.RenderPass = p_current_renderpass; + init_info.PipelineCache = nullptr; + init_info.DescriptorPool = m_desc_pool; + init_info.MinImageCount = 2; + init_info.ImageCount = p_image_size; + init_info.UseDynamicRendering = false; + init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + ImGui_ImplVulkan_Init(&init_info); + } + + void begin(const VkCommandBuffer& p_current, + const uint32_t& p_frame_index) { + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + m_current_frame_index = p_frame_index; + m_current = p_current; + } + + void invalidate(const swapchain& p_swapchain) { + // Wait for device to finish all operations before recreating + // resources + vkDeviceWaitIdle(m_driver); + + for (auto& fb : m_viewport_framebuffers) { + fb.destruct(); + } + + // Remove old texture from ImGui if needed + // ImTextureID in ImGui Vulkan backend is VkDescriptorSet cast to + // void* + if (g_viewport_image_id != nullptr) { + VkDescriptorSet old_descriptor_set = + reinterpret_cast(g_viewport_image_id); + ImGui_ImplVulkan_RemoveTexture(old_descriptor_set); + g_viewport_image_id = nullptr; + } + + // Destroy old images + m_viewport_image.destruct(); + m_depth_viewport_image.destruct(); + + // Recreate viewport images with new swapchain size + const uint32_t memory_properties = + instance_context::physical_driver().memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit); + + vk::image_params config_image = { + .extent = { .width = p_swapchain.settings().width, + .height = p_swapchain.settings().height }, + .format = VK_FORMAT_B8G8R8A8_UNORM, + .memory_mask = memory_properties, + .property = vk::memory_property::device_local_bit, + .aspect = vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::color_attachment_bit | + vk::image_usage::transfer_dst_bit | + vk::image_usage::sampled_bit, + .address_mode_u = vk::sampler_address_mode::clamp_to_edge, + .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, + .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, + }; + m_viewport_image = vk::sample_image(m_driver, config_image); + + // Transition to shader read-only layout + transition_image_layout(m_driver, + m_viewport_image, + VK_FORMAT_B8G8R8A8_UNORM, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + // Recreate depth image + vk::image_params config_depth_image = { + .extent = { .width = p_swapchain.settings().width, + .height = p_swapchain.settings().height }, + .format = m_driver.depth_format(), + .memory_mask = memory_properties, + .property = vk::memory_property::device_local_bit, + .aspect = vk::image_aspect_flags::depth_bit, + // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + .usage = vk::image_usage::depth_stencil_bit, + }; + m_depth_viewport_image = + vk::sample_image(m_driver, config_depth_image); + + // Recreate framebuffers with new images + for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { + std::array image_view_attachments = { + m_viewport_image.image_view(), + m_depth_viewport_image.image_view() + }; + + vk::framebuffer_params framebuffer_info = { + .renderpass = m_viewport_renderpass, + .views = image_view_attachments, + .extent = { p_swapchain.settings().width, + p_swapchain.settings().height } + }; + m_viewport_framebuffers[i] = + vk::framebuffer(m_driver, framebuffer_info); + } + + // Update ImGui texture ID with new image + g_viewport_image_id = (ImTextureID)ImGui_ImplVulkan_AddTexture( + m_viewport_image.sampler(), + m_viewport_image.image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + // Update extent + m_extent = { .width = p_swapchain.settings().width, + .height = p_swapchain.settings().height }; + } + + void end() { + ImGui::Render(); + + ImDrawData* draw_data = ImGui::GetDrawData(); + ImGui_ImplVulkan_RenderDrawData(draw_data, m_current); + + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + } + + [[nodiscard]] ::vk::command_buffer imgui_active_command() const { + return m_viewport_command_buffers[m_current_frame_index]; + } + + vk::framebuffer active_framebuffer(uint32_t p_frame) const { + return m_viewport_framebuffers[p_frame]; + } + + [[nodiscard]] vk::renderpass viewport_renderpass() const { + return m_viewport_renderpass; + } + + void destroy() { + ImGui_ImplVulkan_Shutdown(); + vkDestroyDescriptorPool(m_driver, m_desc_pool, nullptr); + + for (auto& command_buffer : m_viewport_command_buffers) { + command_buffer.destruct(); + } + + for (auto& fb : m_viewport_framebuffers) { + fb.destruct(); + } + + m_viewport_renderpass.destruct(); + m_viewport_image.destruct(); + m_depth_viewport_image.destruct(); + + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + } + + private: + VkInstance m_instance = nullptr; + VkPhysicalDevice m_physical = nullptr; + device m_driver{}; + uint32_t m_current_frame_index = 0; + VkSwapchainKHR m_current_swapchain_handler = nullptr; + VkDescriptorPool m_desc_pool = nullptr; + VkCommandBuffer m_current = nullptr; + std::vector<::vk::command_buffer> m_viewport_command_buffers; + std::array m_viewport_framebuffers; + ::vk::renderpass m_viewport_renderpass; + vk::sample_image m_viewport_image; + vk::sample_image m_depth_viewport_image; + window_params m_extent; + }; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/mesh copy.cppm b/atlas/drivers/vulkan/mesh copy.cppm new file mode 100644 index 00000000..b23079d1 --- /dev/null +++ b/atlas/drivers/vulkan/mesh copy.cppm @@ -0,0 +1,307 @@ +module; + +#include +#include +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include +#include +#include +#include +#include + +export module atlas.drivers.vulkan.mesh; +import vk; + +import atlas.logger; +import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.physical_device; +import atlas.drivers.vulkan.device; +import atlas.drivers.vulkan.hash; +import atlas.drivers.vulkan.stb_image; + +export namespace atlas::vulkan { + /** + * @brief mesh class specifically defined with vulkan implementations for + * specific primitives + * + * @brief mesh class will contain metadata needed by vulkan specifications + * Ways to communicate through vulkan by only supplying information needed + * to update this mesh + * + * @brief Represents a renderable object -- supporting various material + * types, etc + * TODO - For now we have a map, this should + * be expanded to a proper material system for blending various materials + */ + class mesh { + public: + mesh() = default; + mesh(std::span p_vertices, + std::span p_indices) { + m_physical = instance_context::physical_driver(); + m_device = instance_context::logical_device(); + //! @brief Creating vertex/index buffers with host visibility flags + const auto property_flags = static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit); + + vk::buffer_parameters vertex_params = { + .memory_mask = m_physical.memory_properties(property_flags), + .property_flags = vk::memory_property::device_local_bit, + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, + }; + + vk::buffer_parameters index_params = { + .memory_mask = m_physical.memory_properties(property_flags), + .property_flags = static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::index_buffer_bit, + }; + + m_vbo = vk::vertex_buffer(m_device, p_vertices, vertex_params); + m_ibo = vk::index_buffer(m_device, p_indices, index_params); + } + + mesh(const std::filesystem::path& p_filename, bool p_flip = false) + : m_flip(p_flip) { + m_physical = instance_context::physical_driver(); + m_device = instance_context::logical_device(); + reload_mesh(m_physical, p_filename); + } + + //! @brief Reload mesh vertices and indices when requested + void reload_mesh(const vk::physical_device& p_physical, const std::filesystem::path& p_filename) { + load_obj(p_filename); + } + + // void draw(const VkCommandBuffer& p_command_buffer) { + // m_vbo.bind(p_command_buffer); + // if (m_ibo.size() > 0) { + // m_ibo.bind(p_command_buffer); + // vkCmdDrawIndexed(p_command_buffer, m_ibo.size(), 1, 0, 0, 0); + // } + // else { + // vkCmdDraw(p_command_buffer, m_vbo.size(), 1, 0, 0); + // } + // } + + [[nodiscard]] VkBuffer vertex_handle() const { + return m_vbo; + } + + [[nodiscard]] VkBuffer index_handle() const { + return m_ibo; + } + + void destroy() { + m_vbo.destruct(); + m_ibo.destruct(); + + m_diffuse.destruct(); + m_specular.destruct(); + m_geoemtry_ubo.destruct(); + m_material_ubo.destruct(); + } + + [[nodiscard]] bool has_indices() const { + return m_has_indices; + } + + //! @brief Loading single texture with specified std::filesystem::path + void add_diffuse(const std::filesystem::path& p_path) { + vk::texture_params config_texture = { + .memory_mask = m_physical.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + }; + + vk::stb_image image(p_path.string(), config_texture); + m_diffuse = ::vk::texture(m_device, &image, config_texture); + + if (!m_diffuse.loaded()) { + console_log_info("Diffuse Texture {} is NOT loaded!!!", + p_path.string()); + return; + } + } + + void add_specular(const std::filesystem::path& p_path) { + vk::texture_params config_texture = { + .memory_mask = m_physical_device.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + }; + + vk::stb_image image(p_path.string()); + m_specular = vk::texture(m_device, &image, config_texture); + + if (!m_specular.loaded()) { + console_log_error("Specular Texture {} is NOT loaded!!!", + p_path.string()); + return; + } + } + + [[nodiscard]] ::vk::sample_image diffuse() const { + return m_diffuse.image(); + } + [[nodiscard]] ::vk::sample_image specular() const { + return m_specular.image(); + } + + //! @return true if mesh geometry model loaded succesfully + [[nodiscard]] bool loaded() const { return m_model_loaded; } + + [[nodiscard]] bool diffuse_loaded() const { return m_diffuse.loaded(); } + + [[nodiscard]] bool specular_loaded() const { + return m_specular.loaded(); + } + + void set_flip(bool p_flip) { m_flip = p_flip; } + + private: + void load_obj(const std::filesystem::path& p_filename) { + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + std::string warn, err; + + //! @note If we return the constructor then we can check if the mesh + //! loaded successfully + //! @note We also receive hints if the loading is successful! + //! @note Return default constructor automatically returns false + //! means that mesh will return the boolean as false because it + //! wasnt successful + if (!tinyobj::LoadObj(&attrib, + &shapes, + &materials, + &warn, + &err, + p_filename.string().c_str())) { + console_log_warn("Could not load model from path {}", + p_filename.string()); + m_model_loaded = false; + return; + } + + std::vector vertices; + std::vector indices; + std::unordered_map unique_vertices{}; + + // for (const auto& shape : shapes) { + for (size_t i = 0; i < shapes.size(); i++) { + auto shape = shapes[i]; + // for (const auto& index : shape.mesh.indices) { + for (size_t j = 0; j < shape.mesh.indices.size(); j++) { + auto index = shape.mesh.indices[j]; + vk::vertex_input vertex{}; + + if (!unique_vertices.contains(vertex)) { + unique_vertices[vertex] = + static_cast(vertices.size()); + vertices.push_back(vertex); + } + + if (index.vertex_index >= 0) { + vertex.position = { + attrib.vertices[3 * index.vertex_index + 0], + attrib.vertices[3 * index.vertex_index + 1], + attrib.vertices[3 * index.vertex_index + 2] + }; + + vertex.color = { + attrib.colors[3 * index.vertex_index + 0], + attrib.colors[3 * index.vertex_index + 1], + attrib.colors[3 * index.vertex_index + 2] + }; + } + + if (!attrib.normals.empty()) { + vertex.normals = { + attrib.normals[3 * index.normal_index + 0], + attrib.normals[3 * index.normal_index + 1], + attrib.normals[3 * index.normal_index + 2] + }; + } + if (!attrib.texcoords.empty()) { + glm::vec2 flipped_uv = { + attrib.texcoords[static_cast( + index.texcoord_index) * + 2], + 1.0f - attrib.texcoords[static_cast( + index.texcoord_index) * + 2 + + 1], + }; + + glm::vec2 original_uv = { + attrib.texcoords[static_cast( + index.texcoord_index) * + 2], + attrib.texcoords[static_cast( + index.texcoord_index) * + 2 + + 1], + }; + + vertex.uv = m_flip ? flipped_uv : original_uv; + } + else { + vertex.uv = glm::vec2(0.f, 0.f); + } + + if (!unique_vertices.contains(vertex)) { + unique_vertices[vertex] = + static_cast(vertices.size()); + vertices.push_back(vertex); + } + + indices.push_back(unique_vertices[vertex]); + } + } + + //! @brief Creating vertex/index buffers with host visibility flags + const auto property_flags = static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit); + + vk::buffer_parameters vertex_params = { + .memory_mask = p_physical.memory_properties(property_flags), + .property_flags = vk::memory_property::device_local_bit, + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, + }; + + vk::buffer_parameters index_params = { + .memory_mask = p_physical.memory_properties(property_flags), + .property_flags = static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::index_buffer_bit, + }; + m_vbo = ::vk::vertex_buffer(m_device, vertices, vertex_params); + m_ibo = ::vk::index_buffer(m_device, indices, index_params); + m_model_loaded = true; + + m_has_indices = (indices.size() > 0); + } + + private: + physical_device m_physical; + VkDevice m_device = nullptr; + vk::texture m_diffuse; + vk::texture m_specular; + vk::vertex_buffer m_vbo{}; + vk::index_buffer m_ibo{}; + vk::uniform_buffer m_geoemtry_ubo; + vk::uniform_buffer m_material_ubo; + bool m_model_loaded = false; + bool m_flip = false; + + bool m_has_indices = 0; + }; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/mesh.cppm b/atlas/drivers/vulkan/mesh.cppm index 229ea284..143f54df 100644 --- a/atlas/drivers/vulkan/mesh.cppm +++ b/atlas/drivers/vulkan/mesh.cppm @@ -36,25 +36,39 @@ export namespace atlas::vulkan { class mesh { public: mesh() = default; - mesh(std::span p_vertices, - std::span p_indices) { - m_physical = instance_context::physical_driver(); - m_device = instance_context::logical_device(); - - vk::vertex_params vbo_settings = { .phsyical_memory_properties = - m_physical.memory_properties(), - .vertices = p_vertices }; - vk::index_params ibo_settings = { .phsyical_memory_properties = - m_physical.memory_properties(), - .indices = p_indices }; + mesh(const VkDevice& p_device, + std::span p_vertices, + std::span p_indices, + VkPhysicalDeviceMemoryProperties p_memory_properties) + : m_device(p_device) { + // m_physical = instance_context::physical_driver(); + // m_device = instance_context::logical_device(); + m_memory_properties = p_memory_properties; + + vk::vertex_params vbo_settings = { + .phsyical_memory_properties = m_memory_properties, + .vertices = p_vertices, + }; + vk::index_params ibo_settings = { + .phsyical_memory_properties = m_memory_properties, + .indices = p_indices, + }; m_vbo = vk::vertex_buffer(m_device, vbo_settings); m_ibo = vk::index_buffer(m_device, ibo_settings); + + // m_vertices_size = p_vertices.size(); + m_vertices_size = static_cast(p_vertices.size()); + // m_indices_size = p_indices.size(); + m_indices_size = static_cast(p_indices.size()); } - mesh(const std::filesystem::path& p_filename, bool p_flip = false) - : m_flip(p_flip) { - m_physical = instance_context::physical_driver(); - m_device = instance_context::logical_device(); + mesh(const VkDevice& p_device, + VkPhysicalDeviceMemoryProperties p_memory_properties, + const std::filesystem::path& p_filename, + bool p_flip = false) + : m_device(p_device) + , m_memory_properties(p_memory_properties) + , m_flip(p_flip) { reload_mesh(p_filename); } @@ -63,16 +77,13 @@ export namespace atlas::vulkan { load_obj(p_filename); } - void draw(const VkCommandBuffer& p_command_buffer) { - m_vbo.bind(p_command_buffer); - if (m_ibo.size() > 0) { - m_ibo.bind(p_command_buffer); - vkCmdDrawIndexed(p_command_buffer, m_ibo.size(), 1, 0, 0, 0); - } - else { - vkCmdDraw(p_command_buffer, m_vbo.size(), 1, 0, 0); - } - } + [[nodiscard]] VkBuffer vertex_handle() const { return m_vbo; } + + [[nodiscard]] VkBuffer index_handle() const { return m_ibo; } + + [[nodiscard]] uint32_t vertices_size() const { return m_vbo.size(); } + + [[nodiscard]] uint32_t indices_size() const { return m_ibo.size(); } void destroy() { m_vbo.destroy(); @@ -87,7 +98,7 @@ export namespace atlas::vulkan { //! @brief Loading single texture with specified std::filesystem::path void add_diffuse(const std::filesystem::path& p_path) { ::vk::texture_info config_texture = { - .phsyical_memory_properties = m_physical.memory_properties(), + .phsyical_memory_properties = m_memory_properties, .filepath = p_path, }; m_diffuse = ::vk::texture(m_device, config_texture); @@ -101,7 +112,7 @@ export namespace atlas::vulkan { void add_specular(const std::filesystem::path& p_path) { vk::texture_info config_texture = { - .phsyical_memory_properties = m_physical.memory_properties(), + .phsyical_memory_properties = m_memory_properties, .filepath = p_path, }; m_specular = vk::texture(m_device, config_texture); @@ -120,6 +131,17 @@ export namespace atlas::vulkan { return m_specular.image(); } + void draw(const VkCommandBuffer& p_command_buffer) { + m_vbo.bind(p_command_buffer); + if (m_ibo.size() > 0) { + m_ibo.bind(p_command_buffer); + vkCmdDrawIndexed(p_command_buffer, m_ibo.size(), 1, 0, 0, 0); + } + else { + vkCmdDraw(p_command_buffer, m_vbo.size(), 1, 0, 0); + } + } + //! @return true if mesh geometry model loaded succesfully [[nodiscard]] bool loaded() const { return m_model_loaded; } @@ -232,21 +254,22 @@ export namespace atlas::vulkan { } } - ::vk::vertex_params vbo_settings = { - .phsyical_memory_properties = m_physical.memory_properties(), - .vertices = vertices - }; - ::vk::index_params ibo_settings = { - .phsyical_memory_properties = m_physical.memory_properties(), - .indices = indices - }; + ::vk::vertex_params vbo_settings = { .phsyical_memory_properties = + m_memory_properties, + .vertices = vertices }; + ::vk::index_params ibo_settings = { .phsyical_memory_properties = + m_memory_properties, + .indices = indices }; m_vbo = ::vk::vertex_buffer(m_device, vbo_settings); m_ibo = ::vk::index_buffer(m_device, ibo_settings); + + m_vertices_size = vertices.size(); + m_indices_size = indices.size(); m_model_loaded = true; } private: - physical_device m_physical; + VkPhysicalDeviceMemoryProperties m_memory_properties{}; VkDevice m_device = nullptr; vk::texture m_diffuse; vk::texture m_specular; @@ -256,5 +279,8 @@ export namespace atlas::vulkan { vk::uniform_buffer m_material_ubo; bool m_model_loaded = false; bool m_flip = false; + + uint32_t m_vertices_size = 0; + uint32_t m_indices_size = 0; }; }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/physical_device.cppm b/atlas/drivers/vulkan/physical_device.cppm index 1238f3e3..6858337b 100644 --- a/atlas/drivers/vulkan/physical_device.cppm +++ b/atlas/drivers/vulkan/physical_device.cppm @@ -19,6 +19,7 @@ export module atlas.drivers.vulkan.physical_device; import atlas.logger; import atlas.drivers.vulkan.utilities; +import vk; export namespace atlas::vulkan { struct surface_properties { @@ -124,6 +125,28 @@ export namespace atlas::vulkan { return physical_memory_properties; } + /* + [[nodiscard]] uint32_t memory_properties( + vk::memory_property p_property_required) { + vk::allocation_params return_params = {}; + + VkPhysicalDeviceMemoryProperties memory_properties; + vkGetPhysicalDeviceMemoryProperties(m_physical_driver, + &memory_properties); + + uint32_t mask = 0; + for (uint32_t i = 0; i < memory_properties.memoryTypeCount; i++) { + auto type_flags = + memory_properties.memoryTypes[i].propertyFlags; + + if ((type_flags & p_property_required) == p_property_required) { + mask |= ((1 << i)); + } + } + return mask; + } + */ + /** * @return uint32_t is the index to the presentation index of the * specific presentation queue diff --git a/atlas/drivers/vulkan/render_system.cppm b/atlas/drivers/vulkan/render_system.cppm index b60866ec..b6b36495 100644 --- a/atlas/drivers/vulkan/render_system.cppm +++ b/atlas/drivers/vulkan/render_system.cppm @@ -292,7 +292,7 @@ export namespace atlas::vulkan { caching.each([this](flecs::entity p_entity) { const mesh_source* target = p_entity.get(); - mesh new_mesh(std::filesystem::path(target->model_path), + mesh new_mesh(m_device, m_physical.memory_properties(), std::filesystem::path(target->model_path), target->flip); // we do a check if the geometry uniform associated with this @@ -571,8 +571,6 @@ export namespace atlas::vulkan { // TODO: Make to_bytes be part of utilities. This can be useful in // sending the amount of bytes in batches for batch-rendering - // std::span bytes_data = to_bytes(global_frame_ubo); - // m_global_uniforms.update(bytes_data.data()); m_global_uniforms.update(&global_frame_ubo); skybox_uniform skybox_ubo = { @@ -651,15 +649,48 @@ export namespace atlas::vulkan { m_mesh_descriptors[p_entity.id()]["materials"].bind( m_current_command_buffer, m_main_pipeline.layout()); - m_cached_meshes[p_entity.id()].draw( - m_current_command_buffer); + // m_cached_meshes[p_entity.id()].draw( + // m_current_command_buffer); + + // binding/draw calls + const VkBuffer vertex = m_cached_meshes[p_entity.id()].vertex_handle(); + const VkBuffer index = m_cached_meshes[p_entity.id()].index_handle(); + + std::array handler = {vertex}; + std::array offsets = {0}; + vkCmdBindVertexBuffers(m_current_command_buffer, + 0, + 1, + handler.data(), + offsets.data()); + + if(m_cached_meshes[p_entity.id()].indices_size() != 0) { + vkCmdBindIndexBuffer(m_current_command_buffer, + index, + 0, + VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed(m_current_command_buffer, static_cast(m_cached_meshes[p_entity.id()].indices_size()), 1, 0, 0, 0); + } + else { + vkCmdDraw(m_current_command_buffer, m_cached_meshes[p_entity.id()].vertices_size(), 1, 0, 0); + } } }); - m_skybox.bind(m_current_command_buffer); - m_skybox.draw(m_current_command_buffer); + std::array offsets = {0}; + vkCmdBindPipeline(m_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_skybox.pipeline()); + m_skybox.descriptor_bind(m_current_command_buffer, m_skybox.pipeline_layout()); + + const VkBuffer skybox_vertex = m_skybox.vertex_handle(); + vkCmdBindVertexBuffers(m_current_command_buffer, + 0, + 1, + &skybox_vertex, + offsets.data()); + vkCmdDraw(m_current_command_buffer, m_skybox.vertices_size(), 1, 0, 0); vkCmdEndRenderPass(m_current_command_buffer); + // Do not end the command buffer here when using offscreen + // swapchain two-pass: the application will begin the swapchain // render pass for ImGui, then end the command buffer. @@ -670,6 +701,7 @@ export namespace atlas::vulkan { m_current_scene = p_scene_ctx; } + // Remove this API void render_invalidate_mesh(uint32_t p_entity_id, std::filesystem::path p_filename) override { m_cached_meshes[p_entity_id].reload_mesh(p_filename); diff --git a/atlas/drivers/vulkan/shader_resource_group copy.cppm b/atlas/drivers/vulkan/shader_resource_group copy.cppm new file mode 100644 index 00000000..1c78e7f7 --- /dev/null +++ b/atlas/drivers/vulkan/shader_resource_group copy.cppm @@ -0,0 +1,443 @@ +module; + +#include +#include +#include +#include +#include + +export module atlas.drivers.vulkan.shader_resource_group; + +import atlas.logger; +import vk; + +namespace atlas::vulkan { + // Reading the raw .spv binaries + static std::vector read_raw_spirv(const std::string& p_file) { + std::vector out_buffer; + std::ifstream ins(p_file, std::ios::ate | std::ios::binary); + + if (!ins) { + throw std::runtime_error("Cannot load in .spv files!!"); + } + + uint32_t file_size = (uint32_t)ins.tellg(); + out_buffer.resize(file_size); + ins.seekg(0); + ins.read(out_buffer.data(), file_size); + return out_buffer; + } + + //! @brief Ensure file reads are valid before reading raw .spv binaries + static std::vector compile_binary_shader_source( + const ::vk::shader_source& p_shader_source) { + + if (!std::filesystem::is_regular_file(p_shader_source.filename)) { + throw std::runtime_error("Cannot load .spv file"); + } + + return read_raw_spirv(p_shader_source.filename); + } + +#if ENABLE_SHADERC + static std::string read_shader_source_code(const std::string& p_filename) { + std::ifstream ins(p_filename, std::ios::ate | std::ios::binary); + + if (!ins.is_open()) { + console_log_warn("Could not open filename = {}", p_filename); + return { 'a' }; + } + + size_t file_size = (size_t)ins.tellg(); + std::string output; + output.resize(file_size); + ins.seekg(0); + ins.read(output.data(), static_cast(file_size)); + + return output; + } +#endif + + /** + * compiles source code from the shader directly without needing manual + * recompilation + * + * shaderc requires these parameters to compile + * text_source_code: the std::string version of the entire source code to + * compile type: shader stage this shader corresponds to filename: input + * filename text entry_point: the entry point to this shader options: + * compiler-specific options to enable when compiling the shader sources + */ +#if ENABLE_SHADERC + static std::vector compile_source_from_file( + const ::vk::shader_source& p_shader_source) { + shaderc::CompileOptions options; + options.SetTargetEnvironment(shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_3); + options.SetWarningsAsErrors(); + + shaderc_shader_kind type; + + switch (p_shader_source.stage) { + case ::vk::shader_stage::vertex: + type = shaderc_glsl_vertex_shader; + break; + case ::vk::shader_stage::fragment: + type = shaderc_glsl_fragment_shader; + break; + default: + throw std::runtime_error("shader_stage unspecified!~!!"); + } + + shaderc::Compiler compiler; + std::string text_source_code = + read_shader_source_code(p_shader_source.filename); + + // Prints out the text of the shader source code + // console_log_warn("Source Text Code!!!"); + // console_log_info("{}", text_source_code); + shaderc::CompilationResult result = + compiler.CompileGlslToSpv(text_source_code, + type, + p_shader_source.filename.c_str(), + "main", + options); + + std::vector blob; + + if (result.GetCompilationStatus() != + shaderc_compilation_status_success) { + throw std::runtime_error( + std::format("Shader Compilation Error! Failed with reason {}\n{}", + p_shader_source.filename, + result.GetErrorMessage()) + .c_str()); + } + + for (auto blob_chunk : result) { + blob.push_back(blob_chunk); + } + + return blob; + } +#endif + /** + * @brief resource group for loading shader sources that give you back + * VkShaderModule handles + * + * Responsibility is to load stages of shader sources whether that be + * through precompiler .spv files or through shaderc runtime shader + * compilation + * + * Responsibility is loading and streaming the amount of bytes from the + * compiled shader sources into the vulkan shader module handles + * + * resource groups up the creation and management of vulkan shader modules. + */ + export class shader_resource_group { + public: + shader_resource_group() = default; + /** + * @brief constructs a new shader_resource_group + * + * @param p_device is the logical device required to creating the vulkan + * shader module + * @param p_info has the properties such as specified shader sources to + * load/compile + */ + shader_resource_group(const VkDevice& p_device, + const ::vk::shader_resource_info& p_info) + : m_device(p_device) { + + // We go through all of the specified shader source and their + // specific stage Compile them through shader compiler or if + // provided a .spv, then we compile and read in the stream of bytes + // directly + for (size_t i = 0; i < p_info.sources.size(); i++) { + const vk::shader_source shader_src = p_info.sources[i]; + std::filesystem::path filepath = + std::filesystem::path(shader_src.filename); +#ifndef ENABLE_SHADERC + if (filepath.extension().string() == ".spv") { + std::vector blob = + compile_binary_shader_source(shader_src); + + if (blob.empty()) { + m_resource_valid = false; + throw std::runtime_error( + "Cannot load in vector " + "blob of compiled down data!!!"); + } + + create_module(blob, shader_src); + } +#endif + +#ifdef ENABLE_SHADERC + if (filepath.extension().string() != ".spv") { + std::string text_source_code = + read_shader_source_code(filepath.string()); + std::vector blob = + compile_source_from_file(shader_src); + create_module(blob, shader_src); + } +#endif + } + } + + ~shader_resource_group() = default; + + /** + * @return true if resources are valid, otherwise return false + */ + [[nodiscard]] bool valid() const { return m_resource_valid; } + + /** + * @brief sets the vertex attributes with the shader modules that gets + * used by ::vk::pipeline (graphics pipeline) + * + * @param p_attributes is the high-level specifications for setting up + * vertex attributes that correspond with these shaders + */ + void vertex_attributes( + std::span p_attributes) { + /* + -- These comments are a reminder to myself -- + - this function simplifies the need to separately define vertex + attributes and the vertex binding attributes as shown below: + + - vertex attributes specify the types of data within the vertex + + - vertex binding attribute specifies the rate of reading that + data layout specified by the vertex attributes + + - Interpret the following vertex attributes below with this + shader code with `layout(location = n)` specified where by default + these are set to binding zero by the shader + + layout(location = 0) in vec3 inPosition; + layout(location = 1) in vec3 inColor; + layout(location = 2) in vec3 inNormals; + layout(location = 3) in vec2 inTexCoords; + + m_shader_group.set_vertex_attributes(VkVertexInputAttributeDescription{ + { .location = 0, .binding = 0, .format = + VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, + position), + }, { .location = 1, .binding = 0, .format = + VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, color), + }, { .location = 2, .binding = 0, .format = + VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, normals), + }, { .location = 3, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, + .offset = offsetof(vk::vertex, uv), }, + }); + + m_shader_group.set_vertex_bind_attributes(VkVertexInputBindingDescription{ + {.binding = 0, .stride = sizeof(vk::vertex), .inputRate = + VK_VERTEX_INPUT_RATE_VERTEX,}, + }); + + Which gets handled in specifying the following below + */ + + m_vertex_binding_attributes.resize(p_attributes.size()); + + for (size_t i = 0; i < m_vertex_binding_attributes.size(); i++) { + // setting up vertex binding + const ::vk::vertex_attribute attribute = p_attributes[i]; + m_vertex_attributes.resize(attribute.entries.size()); + m_vertex_binding_attributes[i] = { + .binding = attribute.binding, + .stride = attribute.stride, + .inputRate = static_cast(attribute.input_rate), + }; + + // then setting up the vertex attributes for the vertex data + // layouts + for (size_t j = 0; j < attribute.entries.size(); j++) { + const ::vk::vertex_attribute_entry entry = + attribute.entries[j]; + m_vertex_attributes[j] = { .location = entry.location, + .binding = attribute.binding, + .format = static_cast( + entry.format), + .offset = entry.stride }; + } + } + } + + /** + * @brief this gives you back the shader module handles along with each + * of their stages they have been compiled with + * + * Returns the vector to retain the shader modules that are needed by + * the graphics pipeline. + * + * It is required by vulkan specs the graphics pipeline to contain valid + * shader modules of the compiled shaders + * + * @return vector<::vk::shader_handle> + */ + [[nodiscard]] std::vector<::vk::shader_handle> handles() const { + return map_to_vector(); + } + + /** + * @return span + */ + [[nodiscard]] std::span + vertex_attributes() const { + return m_vertex_attributes; + } + + /** + * @return span + */ + [[nodiscard]] std::span + vertex_bind_attributes() const { + return m_vertex_binding_attributes; + } + + /** + * @brief explicit cleanup to the VkShaderModule handles created with + * this particular resource group + */ + void destroy() { + for (auto& [filename, shader_handle] : m_modules) { + if (shader_handle.module != nullptr) { + vkDestroyShaderModule( + m_device, shader_handle.module, nullptr); + } + } + } + + /** + * @brief ideally used for requesting for reload + * + * Planning to use this for invalidation when for runtime shader + * hot-reloading + * + * @note this is not used at the moment as shader runtime hot reloading + * is currently not supported. + */ + [[nodiscard]] bool reload_requested() const { + return m_reload_requested; + } + + private: + /** + * converts unordered_map to + * vector + */ + [[nodiscard]] std::vector<::vk::shader_handle> map_to_vector() const { + // Using C++'s std::views to extract all of the values in + // unordered_map to a + // vector that gets passed to graphics pipeline TEMP: + // Removing this. Will add this back in later. return (m_modules | + // std::views::values | + // std::ranges::to()); + std::vector<::vk::shader_handle> result; + + result.reserve(m_modules.size()); + + for (auto const& [name, handle] : m_modules) { + result.push_back(handle); + } + + return result; + } + + void create_module(std::span p_blob, + const ::vk::shader_source& p_source) { + VkShaderModuleCreateInfo shader_module_ci = { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .codeSize = p_blob.size(), + .pCode = reinterpret_cast(p_blob.data()) + }; + + std::filesystem::path filepath(p_source.filename); + std::string filename = filepath.filename().string(); + + // Setting m_shader_module_handlers[i]'s stage and the + // VkShaderModule handle altogether construct this beforehand and + // then we are going set that shader module + m_modules.emplace(filename, ::vk::shader_handle{}); + ::vk::vk_check(vkCreateShaderModule(m_device, + &shader_module_ci, + nullptr, + &m_modules[filename].module), + "vkCreateShaderModule"); + m_modules[filename].stage = p_source.stage; + } + + void create_module(std::span p_blob, + const ::vk::shader_source& p_source) { + VkShaderModuleCreateInfo shader_module_ci = { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .codeSize = p_blob.size_bytes(), + .pCode = p_blob.data() + }; + + // console_log_info("map key = {}", p_source.filename); + std::filesystem::path filepath(p_source.filename); + + std::string filename = filepath.filename().string(); + + console_log_info("Key = {}", filename); + + // Setting m_shader_module_handlers[i]'s stage and the + // VkShaderModule handle altogether construct this beforehand and + // then we are going set that shader module + m_modules.emplace(filename, ::vk::shader_handle{}); + ::vk::vk_check(vkCreateShaderModule(m_device, + &shader_module_ci, + nullptr, + &m_modules[filename].module), + "vkCreateShaderModule"); + m_modules[filename].stage = p_source.stage; + } + + /* + // TODO: Re-add this when shaderc works again. + void reload_shader(const ::vk::shader_source& p_source) { + console_log_info("p_source.filename = {}", p_source.filename); + if (m_modules[p_source.filename].module != nullptr) { + vkDestroyShaderModule( + m_device, m_modules[p_source.filename].module, nullptr); + } + + auto& handle = m_modules[p_source.filename]; + + std::filesystem::path filepath(p_source.filename); + std::string text_source_code = + read_shader_source_code(filepath.string()); + std::vector blob = compile_source_from_file(p_source); + std::span view_blob(blob.data(), blob.size()); + // create_module(blob, p_source); + VkShaderModuleCreateInfo shader_module_ci = { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .codeSize = view_blob.size_bytes(), + .pCode = view_blob.data() + }; + + ::vk::vk_check(vkCreateShaderModule( + m_device, &shader_module_ci, nullptr, + &handle.module), "vkCreateShaderModule"); + } + */ + + private: + VkDevice m_device = nullptr; + std::vector m_vertex_attributes; + std::vector + m_vertex_binding_attributes; + bool m_resource_valid = false; + // shader module handles + std::unordered_map m_modules; + // ref m_watcher; + bool m_reload_requested = false; + }; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/stb_image.cppm b/atlas/drivers/vulkan/stb_image.cppm new file mode 100644 index 00000000..cdf41145 --- /dev/null +++ b/atlas/drivers/vulkan/stb_image.cppm @@ -0,0 +1,89 @@ +module; + +#include +#include +#include +#include +#include + +#ifndef STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#include +#endif + +export module atlas.drivers.vulkan.stb_image; + +import vk; + +export namespace vk { + class stb_image : public vk::image { + public: + stb_image() = default; + + stb_image(std::string_view p_path, vk::texture_params p_params) { + image_load(p_path, p_params); + } + + ~stb_image() = default; + + protected: + bool image_load(std::string_view p_path, + vk::texture_params p_params) override { + int w = 0; + int h = 0; + int channels = 0; + + stbi_uc* image_pixel_data = + stbi_load(p_path.data(), &w, &h, &channels, STBI_rgb_alpha); + + if (!image_pixel_data) { + return false; + } + + const VkFormat texture_format = + static_cast(vk::format::r8g8b8a8_unorm); + int bytes_per_pixel = vk::bytes_per_texture_format(texture_format); + + m_extent = { + .width = static_cast(w), + .height = static_cast(h), + }; + + // Retrieving total size of bytes of the dimensions of the image and + // accounting for pixels of the image + uint32_t size_bytes = + m_extent.width * m_extent.height * bytes_per_pixel; + + // Retrieving total image size to the count of the image layers + uint32_t size = size_bytes * p_params.layer_count; + + // vk::image_params image_options = { + // .extent = m_extent, + // .format = texture_format, + // .memory_mask = p_params.memory_mask, + // .usage = + // vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, + // .mip_levels = p_params.mip_levels, + // .layer_count = p_params.layer_count, + // }; + + m_bytes.reserve(size); + std::span bytes_view = + std::span(image_pixel_data, size); + + m_bytes.assign(bytes_view.begin(), bytes_view.end()); + + stbi_image_free(image_pixel_data); + + return true; + } + + std::span image_read() const override { return m_bytes; } + + vk::image_extent image_extent() const override { return m_extent; } + + private: + vk::image_extent m_extent{}; + std::vector m_bytes{}; + }; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/swapchain copy.cppm b/atlas/drivers/vulkan/swapchain copy.cppm new file mode 100644 index 00000000..16263821 --- /dev/null +++ b/atlas/drivers/vulkan/swapchain copy.cppm @@ -0,0 +1,352 @@ +module; + +#include +#include +#include + +export module atlas.drivers.vulkan.swapchain; + +import vk; + +// import atlas.logger; +// import atlas.core.utilities.types; +import atlas.core.utilities; +import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.physical_device; +import atlas.drivers.vulkan.device; +import atlas.drivers.vulkan.utilities; + +export namespace atlas::vulkan { + /** + * @name vk_swapchain + * @brief High-level abstraction of a vulkan swapchain + * @brief ref will return the vk_swapchain directly + * @brief ref returning vk_swapchain will need to be changed + */ + class swapchain { + public: + swapchain() = default; + + /** + * @brief Constructs a new vulkan swapchain with a window settings to + * apply to this swapchain + * @param p_surface passing in the surface handler for swapchain uses + */ + swapchain(const VkSurfaceKHR& p_surface, const window_params& p_params) + : m_current_surface_handler(p_surface) + , m_window_params(p_params) + , m_current_surface(p_surface) { + m_physical = instance_context::physical_driver(); + m_driver = instance_context::logical_device(); + + create(); + + console_log_info_tagged("vulkan", + "swapchain created successfully!!!"); + } + + //! @return uint32_t the next available image to present acquired + uint32_t read_acquired_image() { + m_present_to_queue.wait_idle(); + + // uint32_t frame_idx = m_present_to_queue.acquired_frame(); + uint32_t frame_idx = m_present_to_queue.acquire_next_image(); + if (m_present_to_queue.out_of_date()) { + invalidate(); + m_present_to_queue.out_of_date(false); + frame_idx = m_present_to_queue.acquire_next_image(); + } + + return frame_idx; + } + + //! @return current active command buffer being processed + [[nodiscard]] vk::command_buffer active_command( + uint32_t p_frame_index) { + return m_swapchain_command_buffers[p_frame_index]; + } + + [[nodiscard]] VkFramebuffer active_framebuffer(uint32_t p_frame) const { + return m_swapchain_framebuffers[p_frame]; + } + + [[nodiscard]] vk::renderpass swapchain_renderpass() const { + return m_final_renderpass; + } + + [[nodiscard]] window_params settings() const { return m_window_params; } + + [[nodiscard]] uint32_t image_size() const { return m_image_size; } + + [[nodiscard]] surface_properties data() const { + return m_surface_properties; + } + + void destroy() { + vkDeviceWaitIdle(m_driver); + + for (size_t i = 0; i < m_swapchain_framebuffers.size(); i++) { + m_swapchain_framebuffers[i].destruct(); + } + + m_final_renderpass.destruct(); + + m_present_to_queue.destruct(); + + for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { + m_swapchain_command_buffers[i].destruct(); + } + + for (uint32_t i = 0; i < m_swapchain_depth_images.size(); i++) { + m_swapchain_depth_images[i].destruct(); + } + + for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { + m_swapchain_images[i].destruct(); + } + + vkDestroySwapchainKHR(m_driver, m_swapchain_handler, nullptr); + } + + void submit(std::span p_commands) { + m_present_to_queue.submit_async(p_commands); + } + + [[nodiscard]] ::vk::sample_image active_image(uint32_t p_index) const { + return m_swapchain_images[p_index]; + } + + operator VkSwapchainKHR() const { return m_swapchain_handler; } + + operator VkSwapchainKHR() { return m_swapchain_handler; } + + void present(const uint32_t& p_current_frame) { + m_present_to_queue.present_frame(p_current_frame); + if (m_present_to_queue.out_of_date()) { + invalidate(); + m_present_to_queue.out_of_date(false); + } + } + + private: + void invalidate() { + destroy(); + create(); + } + + void create() { + // surface properties are always updated from the physical device + // so they are valid should the swapchain be recreated + m_surface_properties = + m_physical.get_surface_properties(m_current_surface); + m_window_params.width = + m_surface_properties.surface_capabilities.currentExtent.width; + m_window_params.height = + m_surface_properties.surface_capabilities.currentExtent.height; + + //! @note Setting up presentation stuff + // request what our minimum image count is + uint32_t request_min_image_count = + select_images_size(m_surface_properties.surface_capabilities); + + m_swapchain_extent = + m_surface_properties.surface_capabilities.currentExtent; + + // setting our presentation properties + uint32_t present_index = + m_physical.read_presentation_index(m_current_surface_handler); + + VkSwapchainCreateInfoKHR swapchain_ci = { + .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + .surface = m_current_surface_handler, + .minImageCount = request_min_image_count, + .imageFormat = m_surface_properties.surface_format.format, + .imageColorSpace = + m_surface_properties.surface_format.colorSpace, + // use physical device surface formats to getting the right + // formats in vulkan + .imageExtent = m_swapchain_extent, + .imageArrayLayers = 1, + .imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT), + .queueFamilyIndexCount = 1, + .pQueueFamilyIndices = &present_index, + .preTransform = + m_surface_properties.surface_capabilities.currentTransform, + .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + .presentMode = VK_PRESENT_MODE_FIFO_KHR, + .clipped = true + }; + + vk_check(vkCreateSwapchainKHR( + m_driver, &swapchain_ci, nullptr, &m_swapchain_handler), + "vkCreateSwapchainKHR"); + + //!@brief querying images available + uint32_t image_count = 0; + vkGetSwapchainImagesKHR( + m_driver, + m_swapchain_handler, + &image_count, + nullptr); // used to get the amount of images + std::vector images(image_count); + vkGetSwapchainImagesKHR( + m_driver, + m_swapchain_handler, + &image_count, + images.data()); // used to store in the images + + // Creating Images + m_swapchain_images.resize(image_count); + m_image_size = image_count; + m_swapchain_depth_images.resize(image_count); + + VkFormat depth_format = m_driver.depth_format(); + + for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { + ::vk::image_params color_image_config = { + .extent = { m_swapchain_extent.width, + m_swapchain_extent.height, }, + .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), + .format = m_surface_properties.surface_format.format, + .aspect = ::vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::color_attachment_bit, + .mip_levels = 1, + .layer_count = 1, + }; + + m_swapchain_images[i] = + ::vk::sample_image(m_driver, images[i], color_image_config); + + ::vk::image_params depth_image_config = { + .extent = { m_swapchain_extent.width, + m_swapchain_extent.height, }, + .format = depth_format, + .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), + .aspect = ::vk::image_aspect_flags::depth_bit, + // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + .usage = vk::image_usage::depth_stencil_bit, + .mip_levels = 1, + .layer_count = 1, + }; + + m_swapchain_depth_images[i] = + ::vk::sample_image(m_driver, depth_image_config); + } + + // command buffers + + m_swapchain_command_buffers.resize(image_count); + + for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { + ::vk::command_params settings = { + .levels = ::vk::command_levels::primary, + // .queue_index = + // enumerate_swapchain_settings.present_index, + .queue_index = 0, + .flags = ::vk::command_pool_flags::reset, + }; + + m_swapchain_command_buffers[i] = + ::vk::command_buffer(m_driver, settings); + } + + std::array<::vk::attachment, 2> renderpass_attachments = { + ::vk::attachment{ + .format = m_surface_properties.surface_format.format, + .layout = ::vk::image_layout::color_optimal, + .samples = ::vk::sample_bit::count_1, + .load = ::vk::attachment_load::clear, + .store = ::vk::attachment_store::store, + .stencil_load = ::vk::attachment_load::clear, + .stencil_store = ::vk::attachment_store::dont_care, + .initial_layout = ::vk::image_layout::undefined, + .final_layout = ::vk::image_layout::present_src_khr, + }, + ::vk::attachment{ + .format = depth_format, + .layout = ::vk::image_layout::depth_stencil_optimal, + .samples = ::vk::sample_bit::count_1, + .load = ::vk::attachment_load::clear, + .store = ::vk::attachment_store::dont_care, + .stencil_load = ::vk::attachment_load::dont_care, + .stencil_store = ::vk::attachment_store::dont_care, + .initial_layout = ::vk::image_layout::undefined, + .final_layout = ::vk::image_layout::depth_stencil_optimal, + }, + }; + m_final_renderpass = + ::vk::renderpass(m_driver, renderpass_attachments); + + // creating framebuffers + m_swapchain_framebuffers.resize(m_swapchain_images.size()); + + for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { + + std::array + image_attachments = { + m_swapchain_images[i].image_view(), + m_swapchain_depth_images[i].image_view() + }; + + vk::framebuffer_params framebuffer_info = { + .renderpass = m_final_renderpass, + .views = image_attachments, + .extent = m_swapchain_extent + }; + m_swapchain_framebuffers[i] = + vk::framebuffer(m_driver, framebuffer_info); + } + + vk::queue_params present_queue_params{ + .family = 0, + .index = 0, + }; + m_present_to_queue = ::vk::device_present_queue( + m_driver, m_swapchain_handler, present_queue_params); + console_log_info("m_present_to_queue initialized!!!"); + console_log_info("m_presesnt_to_queue.alive() = {}", + (m_present_to_queue != nullptr)); + } + + uint32_t select_images_size( + const VkSurfaceCapabilitiesKHR& p_surface_capabilities) { + uint32_t requested_images = + p_surface_capabilities.minImageCount + 1; + uint32_t final_image_count = 0; + + if ((p_surface_capabilities.maxImageCount > 0) and + (requested_images > p_surface_capabilities.maxImageCount)) { + final_image_count = p_surface_capabilities.maxImageCount; + } + else { + final_image_count = requested_images; + } + + return final_image_count; + } + + private: + physical_device m_physical{}; + device m_driver{}; + VkSurfaceKHR m_current_surface_handler = nullptr; + VkSwapchainKHR m_swapchain_handler = nullptr; + VkExtent2D m_swapchain_extent{}; + window_params m_window_params{}; + + uint32_t m_image_size = 0; + + VkSurfaceKHR m_current_surface = nullptr; + surface_properties m_surface_properties{}; + std::vector m_swapchain_command_buffers{}; + std::vector m_swapchain_framebuffers; + + //! @brief setting up images + std::vector m_swapchain_images; + std::vector m_swapchain_depth_images; + + vk::renderpass m_final_renderpass; + + vk::device_present_queue m_present_to_queue; + }; +}; diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 5d61fefd..132143ec 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -1,24 +1,6 @@ cmake_minimum_required(VERSION 4.0) project(editor CXX) -# build_application( -# SOURCES -# application.cpp - -# PACKAGES -# glfw3 -# Vulkan -# glm -# spdlog - - -# LINK_PACKAGES -# atlas -# glfw -# Vulkan::Vulkan -# glm::glm -# spdlog::spdlog -# ) add_executable(${PROJECT_NAME} application.cpp) @@ -26,9 +8,12 @@ target_sources(editor PUBLIC FILE_SET CXX_MODULES TYPE CXX_MODULES FILES + editor.cppm editor_world.cppm level_scene.cppm content_browser_panel.cppm + icon.cppm + utilities.cppm ) find_package(glfw3 REQUIRED) diff --git a/editor/application.cpp b/editor/application.cpp index b69e8e75..bee99f4c 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -6,7 +6,8 @@ import atlas.application; import atlas.common; import atlas.core.level_streamer; import atlas.core.event; -import editor_world; +// import editor_world; +import editor; import atlas.drivers.graphics_context; diff --git a/editor/content_browser_panel.cppm b/editor/content_browser_panel.cppm index c65a57fe..f52b87cc 100644 --- a/editor/content_browser_panel.cppm +++ b/editor/content_browser_panel.cppm @@ -6,7 +6,7 @@ module; #include #include -export module content_browser; +export module editor:content_browser; import atlas.logger; import atlas.drivers.vulkan.instance_context; @@ -15,35 +15,32 @@ import vk; export class content_browser_panel { public: - content_browser_panel() { + content_browser_panel() = default; + + content_browser_panel( + const VkDevice& p_device, + VkPhysicalDeviceMemoryProperties p_memory_properties) { vk::texture_info config_texture = { - .phsyical_memory_properties = - atlas::vulkan::instance_context::physical_driver() - .memory_properties(), - .filepath = std::filesystem::path("assets/icons/FileIcon.png") + .phsyical_memory_properties = p_memory_properties, + .filepath = std::filesystem::path("assets/icons/FileIcon.png"), }; - m_file_icon = vk::texture( - atlas::vulkan::instance_context::logical_device(), config_texture); + m_file_icon = vk::texture(p_device, config_texture); if (!m_file_icon.loaded()) { console_log_info("Play Button Could not be loaded!!"); } - config_texture = { .phsyical_memory_properties = - atlas::vulkan::instance_context::physical_driver() - .memory_properties(), - .filepath = std::filesystem::path( - "assets/icons/DirectoryIcon.png") }; - m_directory_icon = vk::texture( - atlas::vulkan::instance_context::logical_device(), config_texture); + config_texture = { + .phsyical_memory_properties = p_memory_properties, + .filepath = std::filesystem::path("assets/icons/DirectoryIcon.png"), + }; + m_directory_icon = vk::texture(p_device, config_texture); if (!m_directory_icon.loaded()) { console_log_info("Stop Button Could not be loaded!!"); } - config_texture = { .phsyical_memory_properties = - atlas::vulkan::instance_context::physical_driver() - .memory_properties(), - .filepath = - std::filesystem::path("assets/icons/Back.png") }; - m_back_icon = vk::texture( - atlas::vulkan::instance_context::logical_device(), config_texture); + config_texture = { + .phsyical_memory_properties = p_memory_properties, + .filepath = std::filesystem::path("assets/icons/Back.png"), + }; + m_back_icon = vk::texture(p_device, config_texture); if (!m_back_icon.loaded()) { console_log_info("Stop Button Could not be loaded!!"); } @@ -166,7 +163,7 @@ private: ImTextureID m_file_icon_id; ImTextureID m_directory_icon_id; ImTextureID m_back_icon_id; - const std::filesystem::path m_asset_path = + std::filesystem::path m_asset_path = std::filesystem::current_path() / "assets"; std::filesystem::path m_current_directory = m_asset_path; }; \ No newline at end of file diff --git a/editor/editor.cppm b/editor/editor.cppm new file mode 100644 index 00000000..7fb07c5c --- /dev/null +++ b/editor/editor.cppm @@ -0,0 +1,10 @@ +module; + + +export module editor; + +export import :world; +export import :level_scene; +export import :icon; +export import :content_browser; +export import :utilities; \ No newline at end of file diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index a8f6f9ef..8bcf84ba 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -2,7 +2,7 @@ module; #include -export module editor_world; +export module editor:world; import atlas.core.utilities; import atlas.core.scene.world; @@ -11,7 +11,7 @@ import atlas.drivers.renderer_system; import atlas.core.scene.uuid; import atlas.core.level_streamer; import atlas.core.scene; -import level_scene; +import :level_scene; /** * @brief editor_world is where a lot of the editor logic will be handled diff --git a/editor/icon.cppm b/editor/icon.cppm new file mode 100644 index 00000000..84e7ba61 --- /dev/null +++ b/editor/icon.cppm @@ -0,0 +1,73 @@ +module; + +#include +#include +#include +#include +#include + +export module editor:icon; + +import atlas.core.utilities; +import atlas.drivers.vulkan.instance_context; +import vk; + +export namespace ui::experimental { + /** + * @brief This is an experimental feature for setting up an image + * thumbnail-like abstraction + * TODO: This should be considered to being abstracted in another approach + * as this is a temporary solution for it. OR this could be the way we + * handle icons for the time being for simplicity. + */ + class icon { + public: + icon() = default; + icon(const VkDevice& p_device, VkPhysicalDeviceMemoryProperties p_memory_properties, const std::filesystem::path& p_filename) { + vk::texture_info config_texture = { + .phsyical_memory_properties = p_memory_properties, + .filepath = p_filename + }; + m_icon_image = + vk::texture(p_device, + config_texture); + if (!m_icon_image.loaded()) { + console_log_info("Play Button Could not be loaded!!"); + } + m_icon_image_id = + static_cast(ImGui_ImplVulkan_AddTexture( + m_icon_image.image().sampler(), + m_icon_image.image().image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + } + + icon(const VkDevice& p_device, VkPhysicalDeviceMemoryProperties p_memory_properties, const vk::image_extent& p_extent) { + m_icon_image = + vk::texture(p_device, + p_extent, + p_memory_properties); + m_icon_image_id = + static_cast(ImGui_ImplVulkan_AddTexture( + m_icon_image.image().sampler(), + m_icon_image.image().image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + } + + ~icon() { + // implicitly destroy + // destroy(); + } + + [[nodiscard]] uint32_t width() const { return m_icon_image.width(); } + + [[nodiscard]] uint32_t height() const { return m_icon_image.height(); } + + [[nodiscard]] ImTextureID texture_id() const { return m_icon_image_id; } + + void destroy() { m_icon_image.destroy(); } + + private: + vk::texture m_icon_image; + ImTextureID m_icon_image_id; + }; +}; \ No newline at end of file diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 7ebacf37..2d0a1b5d 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -13,7 +13,7 @@ module; #include #include -export module level_scene; +export module editor:level_scene; import atlas.core.utilities; import atlas.application; @@ -31,168 +31,16 @@ import atlas.core.serialize; import atlas.physics.engine; import atlas.drivers.vulkan.imgui_context; import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.physical_device; +import atlas.drivers.vulkan.device; import atlas.core.ui.widgets.imgui_stdlib; import vk; -import content_browser; - -static void -ui_component_list(flecs::entity& p_selected_entity) { - std::string entity_name = p_selected_entity.name().c_str(); - std::string new_entity_name = ""; - atlas::ui::draw_input_text(new_entity_name, entity_name); - - p_selected_entity.set_name(new_entity_name.c_str()); - - ImGui::SameLine(); - ImGui::PushItemWidth(-1); - if (ImGui::Button("Add Component")) { - ImGui::OpenPopup("Add Component"); - } - - if (ImGui::BeginPopup("Add Component")) { - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Perspective Camera")) { - p_selected_entity.add< - flecs::pair>(); - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Mesh Source")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Material")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Point Light")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Serialize")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Physics Body")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Box Collider")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Sphere Collider")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - - if (!p_selected_entity.has()) { - if (ImGui::MenuItem("Capsule Collider")) { - p_selected_entity.add(); - ImGui::CloseCurrentPopup(); - } - } - ImGui::EndPopup(); - } - - ImGui::PopItemWidth(); -} +import :content_browser; +import :icon; +import :utilities; enum scene_runtime { edit, play }; -namespace ui::experimental { - /** - * @brief This is an experimental feature for setting up an image - * thumbnail-like abstraction - * TODO: This should be considered to being abstracted in another approach - * as this is a temporary solution for it. OR this could be the way we - * handle icons for the time being for simplicity. - */ - class icon { - public: - icon() = default; - icon(const std::filesystem::path& p_filename) { - vk::texture_info config_texture = { - .phsyical_memory_properties = - atlas::vulkan::instance_context::physical_driver() - .memory_properties(), - .filepath = p_filename - }; - m_icon_image = - vk::texture(atlas::vulkan::instance_context::logical_device(), - config_texture); - if (!m_icon_image.loaded()) { - console_log_info("Play Button Could not be loaded!!"); - } - m_icon_image_id = - static_cast(ImGui_ImplVulkan_AddTexture( - m_icon_image.image().sampler(), - m_icon_image.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - } - - icon(const vk::image_extent& p_extent) { - // vk::texture_info config_texture = { - // .phsyical_memory_properties = - // atlas::vulkan::instance_context::physical_driver().memory_properties(), - // .filepath = p_filename - // }; - m_icon_image = - vk::texture(atlas::vulkan::instance_context::logical_device(), - p_extent, - atlas::vulkan::instance_context::physical_driver() - .memory_properties()); - // if (!m_icon_image.loaded()) { - // console_log_info("Play Button Could not be loaded!!"); - // } - m_icon_image_id = - static_cast(ImGui_ImplVulkan_AddTexture( - m_icon_image.image().sampler(), - m_icon_image.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - } - - ~icon() { - // implicitly destroy - // destroy(); - } - - [[nodiscard]] uint32_t width() const { return m_icon_image.width(); } - - [[nodiscard]] uint32_t height() const { return m_icon_image.height(); } - - [[nodiscard]] ImTextureID texture_id() const { return m_icon_image_id; } - - void destroy() { m_icon_image.destroy(); } - - private: - vk::texture m_icon_image; - ImTextureID m_icon_image_id; - }; -}; - // TODO: This is just a temporary solution for loading material texture icons to // ImGui::Image This should be replaced with something like // atlas::material_manager, eventually. @@ -205,6 +53,9 @@ export class level_scene final : public atlas::scene { public: level_scene(const std::string& p_name, atlas::event::bus& p_bus) : atlas::scene(p_name, p_bus) { + m_device = atlas::vulkan::instance_context::logical_device(); + m_physical = atlas::vulkan::instance_context::physical_driver(); + auto editor_camera = entity("Editor Camera"); editor_camera .add>(); @@ -304,30 +155,32 @@ public: }); point_light.add(); - // for(size_t i = 0; i < 26; i++) { - // auto obj = entity(std::format("Object #{}", i)); - // obj.set({ - // .restitution = 1.25f, - // .body_movement_type = atlas::dynamic, - // }); - - // obj.set( - // { - // .radius = 1.0f, - // }); - - // glm::vec3 pos = {float(0*1.4),float(0 * 1.4),float(0 * -3) }; - - // obj.set({ - // .position = pos, - // .rotation = {.3f, 0.0f, 0.0f}, - // }); - - // obj.set({ - // .model_path = "assets/models/Ball OBJ.obj", - // .diffuse = "assets/models/clear.png", - // }); - // } + /* + for(size_t i = 0; i < 26; i++) { + auto obj = entity(std::format("Object #{}", i)); + obj.set({ + .restitution = 1.25f, + .body_movement_type = atlas::dynamic, + }); + + obj.set( + { + .radius = 1.0f, + }); + + glm::vec3 pos = {float(0*1.4),float(0 * 1.4),float(0 * -3) }; + + obj.set({ + .position = pos, + .rotation = {.3f, 0.0f, 0.0f}, + }); + + obj.set({ + .model_path = "assets/models/Ball OBJ.obj", + .diffuse = "assets/models/clear.png", + }); + } + */ m_editor_dockspace.fullscreen(false); m_editor_dockspace.dockspace_open(true); @@ -352,17 +205,16 @@ public: .width = 1, .height = 1, }; - m_default_material_icon.specular = ui::experimental::icon(extent); - m_default_material_icon.diffuse = ui::experimental::icon(extent); + m_default_material_icon.specular = ui::experimental::icon( + m_device, m_physical.memory_properties(), extent); + m_default_material_icon.diffuse = ui::experimental::icon( + m_device, m_physical.memory_properties(), extent); // TEMP: This is for testing if the triggered event only occurs once // whenever a signal occurs. This should be moved to the internal // application... OR the renderer // trigger(this, &level_scene::reload_mesh); - // @note checking to see what state we are in. (If playing/stopping) - // Ref icon = _sceneState == SceneState::Edit ? _iconPlay : - // _iconStop; vk::texture_info config_texture = { .phsyical_memory_properties = atlas::vulkan::instance_context::physical_driver() @@ -394,6 +246,8 @@ public: m_stop_button.image().image_view(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + m_content_browser = content_browser_panel(m_device, m_physical.memory_properties()); + atlas::vulkan::instance_context::submit_resource_free([this]() { m_play_button.destroy(); m_stop_button.destroy(); @@ -692,28 +546,36 @@ public: src->specular); if (std::filesystem::exists(src->specular)) { new_mat.specular = ui::experimental::icon( + m_device, + m_physical.memory_properties(), std::filesystem::path(src->specular)); } else { console_log_info("Specular (white) Path"); vk::image_extent extent = { .width = 1, .height = 1 }; - new_mat.specular = - ui::experimental::icon(extent); + new_mat.specular = ui::experimental::icon( + m_device, + m_physical.memory_properties(), + extent); } if (std::filesystem::exists(src->diffuse)) { console_log_info("Diffuse Path: {}", src->diffuse); new_mat.diffuse = ui::experimental::icon( + m_device, + m_physical.memory_properties(), std::filesystem::path(src->diffuse)); } else { console_log_info("Diffuse (white) Path"); vk::image_extent extent = { .width = 1, .height = 1 }; - new_mat.diffuse = - ui::experimental::icon(extent); + new_mat.diffuse = ui::experimental::icon( + m_device, + m_physical.memory_properties(), + extent); } m_material_icons.emplace(m_selected_entity.id(), @@ -854,6 +716,7 @@ public: // Material Properties Panel // TODO: Make this an abstraction to map out the materials + if (ImGui::Begin("Material Editor")) { // Specular @@ -909,6 +772,7 @@ public: ImGui::End(); } + // Note --- just added this temporarily for testing // auto time = atlas::application::delta_time(); @@ -1065,6 +929,8 @@ private: } private: + VkDevice m_device; + atlas::vulkan::physical_device m_physical; atlas::serializer m_deserializer_test; flecs::entity m_selected_entity; diff --git a/editor/utilities.cppm b/editor/utilities.cppm new file mode 100644 index 00000000..90a585de --- /dev/null +++ b/editor/utilities.cppm @@ -0,0 +1,96 @@ +module; + +#include +#include +#include +#include + + +export module editor:utilities; +import atlas.core.ui.widgets; +import atlas.core.scene.components; + +export void +ui_component_list(flecs::entity& p_selected_entity) { + std::string entity_name = p_selected_entity.name().c_str(); + std::string new_entity_name = ""; + atlas::ui::draw_input_text(new_entity_name, entity_name); + + p_selected_entity.set_name(new_entity_name.c_str()); + + ImGui::SameLine(); + ImGui::PushItemWidth(-1); + if (ImGui::Button("Add Component")) { + ImGui::OpenPopup("Add Component"); + } + + if (ImGui::BeginPopup("Add Component")) { + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Perspective Camera")) { + p_selected_entity.add< + flecs::pair>(); + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Mesh Source")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Material")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Point Light")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Serialize")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Physics Body")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Box Collider")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Sphere Collider")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + + if (!p_selected_entity.has()) { + if (ImGui::MenuItem("Capsule Collider")) { + p_selected_entity.add(); + ImGui::CloseCurrentPopup(); + } + } + ImGui::EndPopup(); + } + + ImGui::PopItemWidth(); +} \ No newline at end of file From 4b09b0f3a880f3abb022a0e541172c3a2d6e4295 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 01:36:40 -0700 Subject: [PATCH 002/106] Did some more maintenance in the editor code --- editor/application.cpp | 1 - editor/editor_world.cppm | 2 - editor/level_scene.cppm | 109 +++++++-------------------------------- 3 files changed, 18 insertions(+), 94 deletions(-) diff --git a/editor/application.cpp b/editor/application.cpp index bee99f4c..edb1125e 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -6,7 +6,6 @@ import atlas.application; import atlas.common; import atlas.core.level_streamer; import atlas.core.event; -// import editor_world; import editor; import atlas.drivers.graphics_context; diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 8bcf84ba..72825030 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -30,8 +30,6 @@ public: // Set what our current scene is // TODO: Probably have `default_custom_scene() set this current("LevelScene"); - - console_log_error("editor_world initialized successfully!!!"); } ~editor_world() override = default; diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 2d0a1b5d..60d6e6f0 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -216,23 +216,19 @@ public: // trigger(this, &level_scene::reload_mesh); vk::texture_info config_texture = { - .phsyical_memory_properties = - atlas::vulkan::instance_context::physical_driver() - .memory_properties(), - .filepath = std::filesystem::path("assets/icons/PlayButton.png") + .phsyical_memory_properties = m_physical.memory_properties(), + .filepath = std::filesystem::path("assets/icons/PlayButton.png"), }; m_play_button = vk::texture( atlas::vulkan::instance_context::logical_device(), config_texture); if (!m_play_button.loaded()) { console_log_info("Play Button Could not be loaded!!"); } - config_texture = { .phsyical_memory_properties = - atlas::vulkan::instance_context::physical_driver() - .memory_properties(), - .filepath = std::filesystem::path( - "assets/icons/StopButton.png") }; - m_stop_button = vk::texture( - atlas::vulkan::instance_context::logical_device(), config_texture); + config_texture = { + .phsyical_memory_properties = m_physical.memory_properties(), + .filepath = std::filesystem::path("assets/icons/StopButton.png"), + }; + m_stop_button = vk::texture(m_device, config_texture); if (!m_stop_button.loaded()) { console_log_info("Stop Button Could not be loaded!!"); } @@ -246,7 +242,8 @@ public: m_stop_button.image().image_view(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - m_content_browser = content_browser_panel(m_device, m_physical.memory_properties()); + m_content_browser = + content_browser_panel(m_device, m_physical.memory_properties()); atlas::vulkan::instance_context::submit_resource_free([this]() { m_play_button.destroy(); @@ -353,14 +350,11 @@ public: if (ImGui::BeginMenu("File")) { if (ImGui::MenuItem("Save")) { - // m_deserializer_test.save("LevelScene"); } ImGui::Separator(); if (ImGui::MenuItem("Exit")) { - // glfwSetWindowShouldClose(atlas::application::close(), - // true); } ImGui::EndMenu(); @@ -372,27 +366,10 @@ public: ImGui::SetNextWindowDockID(dockspace_id, ImGuiCond_FirstUseEver); if (ImGui::Begin("Viewport")) { ImVec2 viewport_size = ImGui::GetContentRegionAvail(); - // ImGui::Image(m_viewport_image_id, - // {static_cast(m_extent.width), - // static_cast(m_extent.height)}); - if (atlas::vulkan::g_viewport_image_id == nullptr) { - console_log_error("atlas::vulkan::g_viewport_image_id is " - "nullptr!!!!!!!!!!!!!!!!!!!"); - } ImGui::Image(atlas::vulkan::g_viewport_image_id, viewport_size); ImGui::End(); } - // if (ImGui::Begin("Viewport")) { - // // TODO: Consider doing this a different way, but not with - // static. - // // glm::vec2 viewport_panel_size = - // // glm::vec2{ atlas::application::params().width, - // // atlas::application::params().height }; - - // ImGui::End(); - // } - defer_begin(); auto query_builder = this->query_builder().build(); @@ -542,8 +519,6 @@ public: material new_mat = {}; const auto* src = m_selected_entity.get(); - console_log_info("Specular Path: {}", - src->specular); if (std::filesystem::exists(src->specular)) { new_mat.specular = ui::experimental::icon( m_device, @@ -551,9 +526,10 @@ public: std::filesystem::path(src->specular)); } else { - console_log_info("Specular (white) Path"); - vk::image_extent extent = { .width = 1, - .height = 1 }; + vk::image_extent extent = { + .width = 1, + .height = 1, + }; new_mat.specular = ui::experimental::icon( m_device, m_physical.memory_properties(), @@ -561,8 +537,6 @@ public: } if (std::filesystem::exists(src->diffuse)) { - console_log_info("Diffuse Path: {}", - src->diffuse); new_mat.diffuse = ui::experimental::icon( m_device, m_physical.memory_properties(), @@ -570,8 +544,10 @@ public: } else { console_log_info("Diffuse (white) Path"); - vk::image_extent extent = { .width = 1, - .height = 1 }; + vk::image_extent extent = { + .width = 1, + .height = 1, + }; new_mat.diffuse = ui::experimental::icon( m_device, m_physical.memory_properties(), @@ -593,23 +569,6 @@ public: atlas::ui::draw_float("Shininess", p_source->shininess); }); - /* - atlas::ui::draw_component("Directional - Light", m_selected_entity, [](atlas::directional_light* - p_dir_light){ ImGui::DragFloat4("Direction", - glm::value_ptr(p_dir_light->direction)); ImGui::DragFloat4("View - Pos", glm::value_ptr(p_dir_light->view_position)); - ImGui::DragFloat4("Color", - glm::value_ptr(p_dir_light->color)); - ImGui::DragFloat4("Ambient", - glm::value_ptr(p_dir_light->ambient)); - ImGui::DragFloat4("Diffuse", - glm::value_ptr(p_dir_light->diffuse)); - ImGui::DragFloat4("Specular", - glm::value_ptr(p_dir_light->specular)); - }); - */ - atlas::ui::draw_component( "Point Light", m_selected_entity, @@ -716,7 +675,7 @@ public: // Material Properties Panel // TODO: Make this an abstraction to map out the materials - + if (ImGui::Begin("Material Editor")) { // Specular @@ -772,38 +731,6 @@ public: ImGui::End(); } - - - // Note --- just added this temporarily for testing - // auto time = atlas::application::delta_time(); - - // if((int)(time * 10.0f) % 8 > 4) { - // m_blink = !m_blink; - // } - - // auto width = atlas::application::get_window().width(); - // auto height = atlas::application::get_window().height(); - - // ImGui::SetNextWindowPos(ImVec2(static_cast(width) * 0.5f, - // static_cast(height) * 0.5f), ImGuiCond_Always, - // ImVec2(0.5f, 0.5f)); ImGui::SetNextWindowSize(ImVec2(200, 20), - // ImGuiCond_Always); ImGuiWindowFlags flags = - // ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground | - // ImGuiWindowFlags_NoInputs; ImGui::SetNextWindowBgAlpha(0.f); - - // if(ImGui::Begin("Testing", nullptr, flags)) { - // ImGui::ProgressBar(10.f); - - // auto pos = ImGui::GetWindowPos(); - // pos.x += (float)width * 0.5f - 300.0f; - // pos.y += 50.0f; - // if(m_blink){ - // ImGui::GetForegroundDrawList()->AddText(m_font, 120.0f, - // pos, 0xffffffff, "Click to Play!"); - // } - - // ImGui::End(); - // } } ui_toolbar(); From 8171cb91033f58fca9f630a23d41ddca15974ef9 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 14:37:55 -0700 Subject: [PATCH 003/106] WIP in migrating renderer to fully using vulkan-cpp --- atlas/core/application copy.cppm | 385 -------- atlas/core/application.cppm | 524 +++++----- atlas/core/entry_point/main.cpp | 147 ++- atlas/core/utilities/types.cppm | 3 + atlas/core/window.cppm | 166 +++- atlas/drivers/drivers.cppm | 20 +- atlas/drivers/graphics_context.cppm | 68 +- .../drivers/vulkan/environment_map copy.cppm | 605 ------------ atlas/drivers/vulkan/environment_map.cppm | 114 ++- atlas/drivers/vulkan/imgui_context copy.cppm | 481 ---------- atlas/drivers/vulkan/imgui_context.cppm | 908 +++++++++--------- atlas/drivers/vulkan/instance_context.cppm | 253 ----- atlas/drivers/vulkan/mesh copy.cppm | 307 ------ atlas/drivers/vulkan/mesh.cppm | 132 ++- atlas/drivers/vulkan/physical_device.cppm | 6 +- atlas/drivers/vulkan/render_system.cppm | 252 +++-- .../vulkan/shader_resource_group copy.cppm | 443 --------- .../drivers/vulkan/shader_resource_group.cppm | 10 +- atlas/drivers/vulkan/stb_image.cppm | 24 +- atlas/drivers/vulkan/swapchain copy.cppm | 352 ------- atlas/drivers/vulkan/swapchain.cppm | 666 ++++++------- atlas/drivers/vulkan/window_context.cppm | 203 ++-- atlas/renderer/context_loader.cppm | 20 +- atlas/renderer/renderer.cppm | 28 +- editor/CMakeLists.txt | 10 +- editor/application.cpp | 34 +- editor/content_browser_panel.cppm | 51 +- editor/editor.cppm | 10 +- editor/editor_world.cppm | 4 +- editor/icon.cppm | 45 +- editor/level_scene.cppm | 861 +---------------- 31 files changed, 1908 insertions(+), 5224 deletions(-) delete mode 100644 atlas/core/application copy.cppm delete mode 100644 atlas/drivers/vulkan/environment_map copy.cppm delete mode 100644 atlas/drivers/vulkan/imgui_context copy.cppm delete mode 100644 atlas/drivers/vulkan/instance_context.cppm delete mode 100644 atlas/drivers/vulkan/mesh copy.cppm delete mode 100644 atlas/drivers/vulkan/shader_resource_group copy.cppm delete mode 100644 atlas/drivers/vulkan/swapchain copy.cppm diff --git a/atlas/core/application copy.cppm b/atlas/core/application copy.cppm deleted file mode 100644 index 94166a38..00000000 --- a/atlas/core/application copy.cppm +++ /dev/null @@ -1,385 +0,0 @@ -module; - -#include -#include -#define GLM_ENABLE_EXPERIMENTAL -#include -#include -#include -#include -#include -#include -#include -#include -#include - -export module atlas.application; - -import atlas.core.utilities; -import atlas.core.utilities.poll_state; -import atlas.window; -import atlas.drivers; -import atlas.renderer.context_loader; -import atlas.core.event; -import atlas.drivers.renderer_system; -import atlas.renderer; -import atlas.drivers.vulkan.instance_context; -import atlas.core.scene; -import atlas.core.scene.world; -import atlas.core.event; -import atlas.core.scene.components; - -import atlas.core.math; -import atlas.drivers.vulkan.imgui_context; -import vk; -import atlas.drivers.graphics_context; - -export namespace atlas { - - /** - * @brief application properties settings for the window - */ - struct application_settings { - std::string name = "Undefined"; - uint32_t width = 0; - uint32_t height = 0; - glm::vec4 background_color = { 1.f, 0.5f, 0.5f, 1.f }; - }; - - /** - * @brief represents a single application that gets created by the engine - * internally - * - * There is only ever going to be one application tied to the engine's - * runtime. As the application is given responsibilities of preloading, - * pre-initialization any sort of utilities required by the engine, and any - * form of post-cleanup when the user requests the application to close. - * - */ - class application { - public: - /** - * @brief constructs a new application - * @param p_settings is the specific application settings to configure - * how the application may be setup - */ - application(/*NOLINT*/ ref p_context, - const application_settings& p_params, - event::bus& p_bus) - : m_bus(&p_bus) { - console_log_info( - "application(const application_settings&) initialized!!!"); - - window_params params = { - .width = p_params.width, - .height = p_params.height, - .name = p_params.name, - }; - m_window = - initialize_window(p_context, params, graphics_api::vulkan); - m_initial_window_params = m_window->data(); - event::set_window_size(static_cast(*m_window)); - - m_renderer = - initialize_renderer(p_context, - graphics_api::vulkan, - params, - m_window->current_swapchain().image_size(), - "Renderer"); - m_renderer->set_background_color(p_params.background_color); - - // m_ui_context = vulkan::imgui_context( - // p_context->handle(), m_window->current_swapchain(), *m_window); - - // p_context->submit_resource_free( - // [this]() { m_ui_context.destruct(); }); - - s_instance = this; - - // Setting internal-level listeners for specific events - m_bus->create_listener(); - m_bus->create_listener(); - m_bus->create_listener(); - m_bus->create_immediate_listener(); - m_bus->create_immediate_listener(); - - m_bus->trigger(this, &application::reload_mesh); - m_bus->trigger( - this, &application::reload_material); - } - - ~application() { m_window->close(); } - - /** - * @return the delta time as a float for giving you the timestep every - * frame - */ - static float delta_time() { return s_instance->m_delta_time; } - - /** - * @brief Explicitly is used to execute the application's mainloop - */ - void execute() { - console_log_info("Executing game mainloop!!!"); - - auto start_time = std::chrono::high_resolution_clock::now(); - - ref current_scene = m_current_world->current(); - - invoke_start(current_scene.get()); - - m_renderer->current_scene_context(current_scene); - - // Bug-prone API. - // Due to requiring there to be a valid m_current_scene specified. - // TODO: SHOULD have this API be invoked whenever a - // `current_scene_context` sets a new scene (for invalidation) - m_renderer->preload( - m_window->current_swapchain().swapchain_renderpass()); - - /* - - flecs::system is how your able to schedule changes for given - portions of data in this case the projection/view matrices are - only being changed when flecs::world::progress(g_delta_time) is - being invoked within the mainloop - current_world_scope.system() - - - When users do object->add>(), this automatically gets invoked by the - .system<...> that gets invoked by the mainloop. - */ - current_scene - ->system, - transform, - perspective_camera>() - .each([&](flecs::pair p_pair, - transform& p_transform, - perspective_camera& p_camera) { - float aspect_ratio = m_window->aspect_ratio(); - if (!p_camera.is_active) { - return; - } - - p_pair->projection = glm::mat4(1.f); - - p_pair->projection = - glm::perspective(glm::radians(p_camera.field_of_view), - aspect_ratio, - p_camera.plane.x, - p_camera.plane.y); - p_pair->projection[1][1] *= -1; - p_pair->view = glm::mat4(1.f); - - // This is converting a glm::highp_vec4 to a glm::quat - glm::quat quaternion = to_quat(p_transform.quaternion); - - p_pair->view = - glm::translate(p_pair->view, p_transform.position) * - glm::mat4_cast(quaternion); - - p_pair->view = glm::inverse(p_pair->view); - }); - - /* - - Currently how this works is we query with anything that has a - flecs::pair - - This tells the ecs flecs what to do query for in regards to - specific objects that are a camera - - in the tag:: namespace, this is to imply components that are - empty and just represent tags, to specify their uses. - */ - auto query_camera_objects = - current_scene - ->query_builder, - perspective_camera>() - .build(); - - while (m_window->available()) { - auto current_time = std::chrono::high_resolution_clock::now(); - m_delta_time = - std::chrono::duration( - current_time - start_time) - .count(); - start_time = current_time; - - event::flush_events(); - - // Progresses the flecs::world by one tick (or replaced with - // using the delta time) This also invokes the following - // system call before the mainloop - current_scene->progress(m_delta_time); - - m_current_frame_index = m_window->acquired_next_frame(); - - // Current commands that are going to be iterated through - // Use the acquired swapchain image index for the command buffer - // and swapchain framebuffer so we record and present the same - // image. - ::vk::command_buffer currently_active = - m_window->active_command(m_current_frame_index); - - invoke_physics_update(current_scene.get()); - - invoke_on_update(current_scene.get(), m_delta_time); - - invoke_defer_update(current_scene.get()); - // We want this to be called after late update - // This queries all camera objects within the camera system - // Update -- going to be removing camera system in replacement - // of just simply using flecs::system to keep it simple for the - // time - query_camera_objects.each( - [&](flecs::entity, - flecs::pair p_pair, - perspective_camera& p_camera) { - if (!p_camera.is_active) { - return; - } - - // m_proj_view = p_pair->projection * p_pair->view; - m_projection = p_pair->projection; - m_view = p_pair->view; - }); - - // invalidate imgui context - /* - if (m_initial_window_params.width != m_window->data().width and - m_initial_window_params.height != m_window->data().height) { - m_ui_context.invalidate(m_window->current_swapchain()); - // once we have invalidated the current width/height, we set - // that to its new width/height value post-resizing - // TODO: Make this into a event::window_resize event that - // can be handled! - m_initial_window_params = m_window->data(); - - // Make sure to update the imgui window size - ImGui::SetNextWindowSize(ImVec2( - static_cast(m_initial_window_params.width), - static_cast(m_initial_window_params.height))); - } - */ - - // Prevents things like stalling so the CPU doesnt have to wait - // for the GPU to fully complete before starting on the next - // frame Command buffer uses this to track the frames to process - // its commands. current_frame = (acquired_next_frame + 1) % - // frames_in_flight; auto current_frame = (m_current_frame_index - // + 1) % 2; - - // viewport renderpass to render the 3D screen to the offscreen - // texture - // auto viewport_framebuffer = - // m_ui_context.active_framebuffer(m_current_frame_index % 2u); - m_renderer->begin_frame( - currently_active, - m_window->current_swapchain().settings(), - m_ui_context.viewport_renderpass(), - // viewport_framebuffer, - m_window->current_swapchain().active_framebuffer( - m_current_frame_index), - m_projection, - m_view, - m_current_frame_index); - - m_renderer->end_frame(); - - m_ui_context.begin(currently_active, m_current_frame_index); - - invoke_ui_update(current_scene.get()); - - // final renderpass for rendering the offscreen information to - // the final renderpass - window_params swapchain_extent = - m_window->current_swapchain().settings(); - std::array color = { 0.1f, 0.105f, 0.11f, 1.0f }; - vk::renderpass_begin_params begin_renderpass = { - .current_command = currently_active, - .extent = { swapchain_extent.width, - swapchain_extent.height }, - .current_framebuffer = - m_window->current_swapchain().active_framebuffer( - m_current_frame_index), - .color = color, - .subpass = vk::subpass_contents::inline_bit - }; - m_window->current_swapchain().swapchain_renderpass().begin( - begin_renderpass); - m_ui_context.end(); - m_window->current_swapchain().swapchain_renderpass().end( - currently_active); - currently_active.end(); - - std::array commands = { - currently_active, - }; - m_window->current_swapchain().submit(commands); - - m_window->present(m_current_frame_index); - } - } - - /** - * @brief Performs any post cleanup when user requests the application - * to close - */ - void post_destroy() { console_log_info("Executing post cleanup!!!"); } - - /** - * @brief we only ever have one window - * - * This static function was a means to getting access to the window to - * perform any operations or request any data the window may have to - * provide - */ - // static window& get_window() { return *s_instance->m_window; } - - /* Retrieves the current selected graphics API */ - /** - * @return the currently specified API. - */ - static graphics_api current_api() { return graphics_api::vulkan; } - - /* Returns the currently selected swapchain */ - /** - * @brief gives you the current swapchain handle - * - * TODO: This is not actually needed, and should be removed - */ - VkSwapchainKHR get_current_swapchain() { - return m_window->current_swapchain(); - } - - void current_world(ref p_world) { m_current_world = p_world; } - - void reload_mesh(event::mesh_reload&) { - console_log_info( - "application::trigger invoked from core/application!"); - } - - void reload_material(event::material_reload&) { - console_log_info( - "application::trigger invoked from core/application!"); - } - - protected: - [[nodiscard]] ref renderer_instance() const { - return m_renderer; - } - - private: - float m_delta_time = 0.f; - ref m_current_world; - ref m_window; - window_params m_initial_window_params; - ref m_renderer = nullptr; - glm::mat4 m_projection; - glm::mat4 m_view; - uint32_t m_current_frame_index = -1; - // vulkan::imgui_context m_ui_context; - event::bus* m_bus = nullptr; - static application* s_instance; - }; - - application* application::s_instance = nullptr; -}; \ No newline at end of file diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index a7623e41..247c6900 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -13,26 +13,18 @@ module; #include #include +#include +#include +#include + export module atlas.application; import atlas.core.utilities; import atlas.core.utilities.poll_state; -import atlas.window; -import atlas.drivers; -import atlas.renderer.context_loader; -import atlas.core.event; -import atlas.drivers.renderer_system; -import atlas.renderer; -import atlas.drivers.vulkan.instance_context; -import atlas.core.scene; -import atlas.core.scene.world; import atlas.core.event; -import atlas.core.scene.components; - -import atlas.core.math; -import atlas.drivers.vulkan.imgui_context; import vk; import atlas.drivers.graphics_context; +import atlas.window; export namespace atlas { @@ -56,323 +48,237 @@ export namespace atlas { * form of post-cleanup when the user requests the application to close. * */ + // class application { + // public: + // /** + // * @brief constructs a new application + // * @param p_settings is the specific application settings to + // configure + // * how the application may be setup + // */ + // application(/*NOLINT*/ ref p_context, + // const application_settings& p_params, + // event::bus& p_bus) + // : m_bus(&p_bus) { + // console_log_info( + // "application(const application_settings&) initialized!!!"); + + // window_params params = { + // .width = p_params.width, + // .height = p_params.height, + // .name = p_params.name, + // }; + // m_window = + // initialize_window(p_context, params, graphics_api::vulkan); + // // m_initial_window_params = m_window->data(); + // event::set_window_size(static_cast(*m_window)); + + // // m_renderer = + // // initialize_renderer(p_context, + // // graphics_api::vulkan, + // // params, + // // m_window->current_swapchain().image_size(), + // // "Renderer"); + // // m_renderer->set_background_color(p_params.background_color); + + // // m_ui_context = vulkan::imgui_context( + // // p_context->handle(), m_window->current_swapchain(), + // *m_window); + + // // p_context->submit_resource_free( + // // [this]() { m_ui_context.destroy(); }); + + // s_instance = this; + + // // Setting internal-level listeners for specific events + // m_bus->create_listener(); + // m_bus->create_listener(); + // m_bus->create_listener(); + // m_bus->create_immediate_listener(); + // m_bus->create_immediate_listener(); + + // m_bus->trigger(this, + // &application::reload_mesh); + // m_bus->trigger( + // this, &application::reload_material); + // } + + // ~application() { m_window->close(); } + + // /** + // * @return the delta time as a float for giving you the timestep + // every + // * frame + // */ + // static float delta_time() { return s_instance->m_delta_time; } + + // /** + // * @brief Explicitly is used to execute the application's mainloop + // */ + // void execute() { + // console_log_info("Executing game mainloop!!!"); + + // auto start_time = std::chrono::high_resolution_clock::now(); + + // ref current_scene = m_current_world->current(); + + // invoke_start(current_scene.get()); + + // while (m_window->available()) { + // auto current_time = + // std::chrono::high_resolution_clock::now(); m_delta_time = + // std::chrono::duration( + // current_time - start_time) + // .count(); + // start_time = current_time; + + // event::flush_events(); + + // // Progresses the flecs::world by one tick (or replaced with + // // using the delta time) This also invokes the following + // // system call before the mainloop + // current_scene->progress(m_delta_time); + + // m_current_frame_index = m_window->acquired_next_frame(); + + // // Current commands that are going to be iterated through + // // Use the acquired swapchain image index for the command + // buffer + // // and swapchain framebuffer so we record and present the + // same + // // image. + // vk::command_buffer currently_active = + // m_window->active_command(m_current_frame_index); + + // // invoke_physics_update(current_scene.get()); + + // // invoke_on_update(current_scene.get(), m_delta_time); + + // // invoke_defer_update(current_scene.get()); + + // // m_ui_context.begin(currently_active, + // m_current_frame_index); + + // // invoke_ui_update(current_scene.get()); + + // std::array commands = { + // currently_active, + // }; + // m_window->current_swapchain().submit(commands); + + // m_window->present(m_current_frame_index); + // } + // } + + // /** + // * @brief Performs any post cleanup when user requests the + // application + // * to close + // */ + // void post_destroy() { console_log_info("Executing post cleanup!!!"); + // } + + // /** + // * @brief we only ever have one window + // * + // * This static function was a means to getting access to the window + // to + // * perform any operations or request any data the window may have to + // * provide + // */ + // // static window& get_window() { return *s_instance->m_window; } + + // /* Retrieves the current selected graphics API */ + // /** + // * @return the currently specified API. + // */ + // static graphics_api current_api() { return graphics_api::vulkan; } + + // /* Returns the currently selected swapchain */ + // /** + // * @brief gives you the current swapchain handle + // * + // * TODO: This is not actually needed, and should be removed + // */ + // VkSwapchainKHR get_current_swapchain() { + // return m_window->current_swapchain(); + // } + + // void current_world(ref p_world) { m_current_world = p_world; } + + // void reload_mesh(event::mesh_reload&) { + // console_log_info( + // "application::trigger invoked from core/application!"); + // } + + // void reload_material(event::material_reload&) { + // console_log_info( + // "application::trigger invoked from + // core/application!"); + // } + + // protected: + // [[nodiscard]] ref renderer_instance() const { + // // return m_renderer; + // return nullptr; + // } + + // private: + // float m_delta_time = 0.f; + // ref m_current_world; + // ref m_window; + // // window_params m_initial_window_params; + // // ref m_renderer = nullptr; + // glm::mat4 m_projection; + // glm::mat4 m_view; + // uint32_t m_current_frame_index = -1; + // // vulkan::imgui_context m_ui_context; + // event::bus* m_bus = nullptr; + // static application* s_instance; + // }; + class application { public: - /** - * @brief constructs a new application - * @param p_settings is the specific application settings to configure - * how the application may be setup - */ - application(/*NOLINT*/ ref p_context, + application() = default; + application(std::shared_ptr p_context, const application_settings& p_params, event::bus& p_bus) - : m_bus(&p_bus) { - console_log_info( - "application(const application_settings&) initialized!!!"); + : m_context(p_context), m_bus(&p_bus) { + m_instance = p_context->instance_handle(); + m_physical = p_context->physical_device(); + m_device = p_context->logical_device(); + // Constructing the application + std::println("Constructing application"); window_params params = { .width = p_params.width, .height = p_params.height, .name = p_params.name, }; - m_window = - initialize_window(p_context, params, graphics_api::vulkan); - m_initial_window_params = m_window->data(); - event::set_window_size(static_cast(*m_window)); - - m_renderer = - initialize_renderer(p_context, - graphics_api::vulkan, - params, - m_window->current_swapchain().image_size(), - "Renderer"); - m_renderer->set_background_color(p_params.background_color); - - m_ui_context = vulkan::imgui_context( - p_context->handle(), m_window->current_swapchain(), *m_window); - - p_context->submit_resource_free( - [this]() { m_ui_context.destroy(); }); - - s_instance = this; - - // Setting internal-level listeners for specific events - m_bus->create_listener(); - m_bus->create_listener(); - m_bus->create_listener(); - m_bus->create_immediate_listener(); - m_bus->create_immediate_listener(); - - m_bus->trigger(this, &application::reload_mesh); - m_bus->trigger( - this, &application::reload_material); - } + // m_window = std::allocate_shared(, m_context->instance_handle(), params); + m_window = std::make_shared(p_context, params); - ~application() { m_window->close(); } - - /** - * @return the delta time as a float for giving you the timestep every - * frame - */ - static float delta_time() { return s_instance->m_delta_time; } + std::println("After constructing atlas::window"); + } - /** - * @brief Explicitly is used to execute the application's mainloop - */ void execute() { - console_log_info("Executing game mainloop!!!"); - - auto start_time = std::chrono::high_resolution_clock::now(); - - ref current_scene = m_current_world->current(); - - invoke_start(current_scene.get()); - - m_renderer->current_scene_context(current_scene); - - // Bug-prone API. - // Due to requiring there to be a valid m_current_scene specified. - // TODO: SHOULD have this API be invoked whenever a - // `current_scene_context` sets a new scene (for invalidation) - m_renderer->preload( - m_window->current_swapchain().swapchain_renderpass()); - - /* - - flecs::system is how your able to schedule changes for given - portions of data in this case the projection/view matrices are - only being changed when flecs::world::progress(g_delta_time) is - being invoked within the mainloop - current_world_scope.system() - - - When users do object->add>(), this automatically gets invoked by the - .system<...> that gets invoked by the mainloop. - */ - current_scene - ->system, - transform, - perspective_camera>() - .each([&](flecs::pair p_pair, - transform& p_transform, - perspective_camera& p_camera) { - float aspect_ratio = m_window->aspect_ratio(); - if (!p_camera.is_active) { - return; - } - - p_pair->projection = glm::mat4(1.f); - - p_pair->projection = - glm::perspective(glm::radians(p_camera.field_of_view), - aspect_ratio, - p_camera.plane.x, - p_camera.plane.y); - p_pair->projection[1][1] *= -1; - p_pair->view = glm::mat4(1.f); - - // This is converting a glm::highp_vec4 to a glm::quat - glm::quat quaternion = to_quat(p_transform.quaternion); - - p_pair->view = - glm::translate(p_pair->view, p_transform.position) * - glm::mat4_cast(quaternion); - - p_pair->view = glm::inverse(p_pair->view); - }); - - /* - - Currently how this works is we query with anything that has a - flecs::pair - - This tells the ecs flecs what to do query for in regards to - specific objects that are a camera - - in the tag:: namespace, this is to imply components that are - empty and just represent tags, to specify their uses. - */ - auto query_camera_objects = - current_scene - ->query_builder, - perspective_camera>() - .build(); - - while (m_window->available()) { - auto current_time = std::chrono::high_resolution_clock::now(); - m_delta_time = - std::chrono::duration( - current_time - start_time) - .count(); - start_time = current_time; + std::println("Executing mainloop"); + while(m_window->available()) { event::flush_events(); - - // Progresses the flecs::world by one tick (or replaced with - // using the delta time) This also invokes the following - // system call before the mainloop - current_scene->progress(m_delta_time); - - m_current_frame_index = m_window->acquired_next_frame(); - - // Current commands that are going to be iterated through - // Use the acquired swapchain image index for the command buffer - // and swapchain framebuffer so we record and present the same - // image. - ::vk::command_buffer currently_active = - m_window->active_command(m_current_frame_index); - - invoke_physics_update(current_scene.get()); - - invoke_on_update(current_scene.get(), m_delta_time); - - invoke_defer_update(current_scene.get()); - // We want this to be called after late update - // This queries all camera objects within the camera system - // Update -- going to be removing camera system in replacement - // of just simply using flecs::system to keep it simple for the - // time - query_camera_objects.each( - [&](flecs::entity, - flecs::pair p_pair, - perspective_camera& p_camera) { - if (!p_camera.is_active) { - return; - } - - // m_proj_view = p_pair->projection * p_pair->view; - m_projection = p_pair->projection; - m_view = p_pair->view; - }); - - // invalidate imgui context - if (m_initial_window_params.width != m_window->data().width and - m_initial_window_params.height != m_window->data().height) { - m_ui_context.invalidate(m_window->current_swapchain()); - // once we have invalidated the current width/height, we set - // that to its new width/height value post-resizing - // TODO: Make this into a event::window_resize event that - // can be handled! - m_initial_window_params = m_window->data(); - - // Make sure to update the imgui window size - ImGui::SetNextWindowSize(ImVec2( - static_cast(m_initial_window_params.width), - static_cast(m_initial_window_params.height))); - } - - // Prevents things like stalling so the CPU doesnt have to wait - // for the GPU to fully complete before starting on the next - // frame Command buffer uses this to track the frames to process - // its commands. current_frame = (acquired_next_frame + 1) % - // frames_in_flight; auto current_frame = (m_current_frame_index - // + 1) % 2; - - // viewport renderpass to render the 3D screen to the offscreen - // texture - auto viewport_framebuffer = - m_ui_context.active_framebuffer(m_current_frame_index % 2u); - m_renderer->begin_frame( - currently_active, - m_window->current_swapchain().settings(), - m_ui_context.viewport_renderpass(), - viewport_framebuffer, - m_projection, - m_view, - m_current_frame_index); - - m_renderer->end_frame(); - - m_ui_context.begin(currently_active, m_current_frame_index); - - invoke_ui_update(current_scene.get()); - - // final renderpass for rendering the offscreen information to - // the final renderpass - window_params swapchain_extent = - m_window->current_swapchain().settings(); - std::array color = { 0.1f, 0.105f, 0.11f, 1.0f }; - vk::renderpass_begin_params begin_renderpass = { - .current_command = currently_active, - .extent = { swapchain_extent.width, - swapchain_extent.height }, - .current_framebuffer = - m_window->current_swapchain().active_framebuffer( - m_current_frame_index), - .color = color, - .subpass = vk::subpass_contents::inline_bit - }; - m_window->current_swapchain().swapchain_renderpass().begin( - begin_renderpass); - m_ui_context.end(); - m_window->current_swapchain().swapchain_renderpass().end( - currently_active); - currently_active.end(); - - std::array commands = { - currently_active, - }; - m_window->current_swapchain().submit(commands); - - m_window->present(m_current_frame_index); } } - /** - * @brief Performs any post cleanup when user requests the application - * to close - */ - void post_destroy() { console_log_info("Executing post cleanup!!!"); } - - /** - * @brief we only ever have one window - * - * This static function was a means to getting access to the window to - * perform any operations or request any data the window may have to - * provide - */ - // static window& get_window() { return *s_instance->m_window; } - - /* Retrieves the current selected graphics API */ - /** - * @return the currently specified API. - */ - static graphics_api current_api() { return graphics_api::vulkan; } - - /* Returns the currently selected swapchain */ - /** - * @brief gives you the current swapchain handle - * - * TODO: This is not actually needed, and should be removed - */ - VkSwapchainKHR get_current_swapchain() { - return m_window->current_swapchain(); - } - - void current_world(ref p_world) { m_current_world = p_world; } - - void reload_mesh(event::mesh_reload&) { - console_log_info( - "application::trigger invoked from core/application!"); - } - - void reload_material(event::material_reload&) { - console_log_info( - "application::trigger invoked from core/application!"); - } - - protected: - [[nodiscard]] ref renderer_instance() const { - return m_renderer; + void post_destroy() { + std::println("Post destroy!"); } private: - float m_delta_time = 0.f; - ref m_current_world; - ref m_window; - window_params m_initial_window_params; - ref m_renderer = nullptr; - glm::mat4 m_projection; - glm::mat4 m_view; - uint32_t m_current_frame_index = -1; - vulkan::imgui_context m_ui_context; + vk::instance m_instance; + std::optional m_physical; + std::shared_ptr m_device; + std::shared_ptr m_context; + std::shared_ptr m_window=nullptr; event::bus* m_bus = nullptr; static application* s_instance; }; diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 0725c701..891996d0 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -1,5 +1,22 @@ // For glfwInit call #include +#include +#include +#include +#include + +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + import atlas.application; import atlas.common; import atlas.logger; @@ -7,12 +24,46 @@ import atlas.graphics_api; import atlas.drivers.graphics_context; import atlas.renderer.context_loader; import atlas.core.event; +import vk; // Defined in the user-application side [[nodiscard]] atlas::ref initialize_application( - atlas::ref p_context, + std::shared_ptr p_context, atlas::event::bus& p_bus); +static VKAPI_ATTR VkBool32 VKAPI_CALL +debug_callback( + [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT p_message_severity, + [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT p_message_type, + const VkDebugUtilsMessengerCallbackDataEXT* p_callback_data, + [[maybe_unused]] void* p_user_data) { + std::print("validation layer:\t\t{}\n\n", p_callback_data->pMessage); + return false; +} + +std::vector +get_instance_extensions() { + std::vector extension_names; + uint32_t extension_count = 0; + const char** required_extensions = + glfwGetRequiredInstanceExtensions(&extension_count); + + for (uint32_t i = 0; i < extension_count; i++) { + std::println("Required Extension = {}", required_extensions[i]); + extension_names.emplace_back(required_extensions[i]); + } + + extension_names.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + +#if defined(__APPLE__) + extension_names.emplace_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); + extension_names.emplace_back( + VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); +#endif + + return extension_names; +} + int main() { // We should not have our core system start up during testing environment @@ -23,10 +74,96 @@ main() { return -1; } - atlas::event::bus event_bus; - atlas::ref context = - atlas::initialize_context("vulkan", atlas::graphics_api::vulkan); + if (!glfwVulkanSupported()) { + std::println("GLFW: Vulkan is not supported!"); + return -1; + } + std::array validation_layers = { + "VK_LAYER_KHRONOS_validation", + }; + + // Retrieving the Vulkan instance-level extensions + std::vector global_extensions = get_instance_extensions(); + + vk::debug_message_utility debug_callback_info = { + // .severity essentially takes in vk::message::verbose, + // vk::message::warning, vk::message::error + .severity = + vk::message::verbose | vk::message::warning | vk::message::error, + // .message_type essentially takes in vk::debug. Like: + // vk::debug::general, vk::debug::validation, vk::debug::performance + .message_type = + vk::debug::general | vk::debug::validation | vk::debug::performance, + .callback = debug_callback + }; + + vk::application_params config = { + .name = "vulkan instance", + .version = vk::api_version::vk_1_3, // specify to using vulkan 1.3 + .validations = + validation_layers, // .validation takes in a std::span + .extensions = + global_extensions // .extensions also takes in std::span + }; + + // 1. Setting up vk instance + vk::instance api_instance(config, debug_callback_info); + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::integrated); + vk::physical_device physical_device = physical_device_expected.value(); + + std::array priorities = { 0.f }; +#if defined(__APPLE__) + std::array extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + "VK_KHR_portability_subset", + }; +#else + std::array extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + }; +#endif + std::array format_support = { + vk::format::d32_sfloat, + vk::format::d32_sfloat_s8_uint, + vk::format::d24_unorm_s8_uint + }; + + // We provide a selection of format support that we want to check is + // supported on current hardware device. + VkFormat depth_format = + physical_device.request_depth_format(format_support); + + vk::device_features device_features{ + vk::dynamic_rendering_feature{ { + .dynamicRendering = true, + } }, + }; + + vk::device_params logical_device_params = { + .features = device_features.data(), + .queue_priorities = priorities, + .extensions = extensions, + .queue_family_index = 0, + }; + + // pmr::monotonic_memory_resource for allocation + + std::array bytes{}; + std::pmr::monotonic_buffer_resource memory_resource{ bytes.data(), + bytes.size() }; + std::pmr::polymorphic_allocator allocator{ &memory_resource }; + + std::shared_ptr logical_device = + std::allocate_shared( + allocator, physical_device, logical_device_params); + + std::shared_ptr context = + std::allocate_shared( + allocator, api_instance, physical_device, logical_device); + + atlas::event::bus event_bus; atlas::ref app = initialize_application(context, event_bus); @@ -34,6 +171,6 @@ main() { app->post_destroy(); - context->destroy(); + context->post_cleanup(); return 0; } \ No newline at end of file diff --git a/atlas/core/utilities/types.cppm b/atlas/core/utilities/types.cppm index eb2e8700..3c7b6f1d 100644 --- a/atlas/core/utilities/types.cppm +++ b/atlas/core/utilities/types.cppm @@ -6,11 +6,14 @@ module; export module atlas.core.utilities.types; +import vk; + export namespace atlas { struct window_params { uint32_t width; uint32_t height; std::string name = ""; + vk::surface_params surface_properties{}; }; // TODO: Move this into atlas.drivers.vulkan.utilities diff --git a/atlas/core/window.cppm b/atlas/core/window.cppm index 58edb5c5..4eaf741c 100644 --- a/atlas/core/window.cppm +++ b/atlas/core/window.cppm @@ -1,93 +1,112 @@ module; -#include #include #include +#include +#include + +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif + +#include export module atlas.window; -// import atlas.common; -// import atlas.graphics_api; -// import atlas.core.utilities.types; +import atlas.common; +import atlas.core.utilities.types; import atlas.core.utilities; -import atlas.drivers.vulkan.swapchain; import vk; +import atlas.drivers.graphics_context; export namespace atlas { + /* class window { public: virtual ~window() = default; [[nodiscard]] window_params data() const { return get_params(); } - /** - * @brief Checks if window is available to close - */ + // ** + // * @brief Checks if window is available to close + // * [[nodiscard]] bool available() const { return !glfwWindowShouldClose(native_window()); } - /** - * @brief Returns the aspect ratio of the current window - */ + // * + // * @brief Returns the aspect ratio of the current window + // * [[nodiscard]] float aspect_ratio() const { return static_cast(get_params().width) / static_cast(get_params().height); } - /** - * @brief gives you the next presentable image to use and the index to - * retrieving that image - * - * @return uint32_t - */ + // * + // * @brief gives you the next presentable image to use and the index + to + // * retrieving that image + // * + // * @return uint32_t + // * [[nodiscard]] uint32_t acquired_next_frame() { return read_acquired_next_frame(); } - /** - * @brief Returns the window's currently selected swapchain - */ + // ** + // * @brief Returns the window's currently selected swapchain + // * [[nodiscard]] vulkan::swapchain current_swapchain() const { return window_swapchain(); } - /** - * @brief retrieves the current command buffer using the current frame - * index to ensure we are processing commands to the right command - * buffer in our current frame - * - * @return command buffer to actively record commands to - */ + // * + // * @brief retrieves the current command buffer using the current + frame + // * index to ensure we are processing commands to the right command + // * buffer in our current frame + // * + // * @return command buffer to actively record commands to + // * vk::command_buffer active_command(uint32_t p_frame_index) { return current_active_command(p_frame_index); } - /** - * @brief operator overload for treating atlas::window as a GLFWwindow - * handle - */ + // * + // * @brief operator overload for treating atlas::window as a + GLFWwindow + // * handle + // * operator GLFWwindow*() const { return native_window(); } - /** - * @brief operator overload for treating atlas::window as a GLFWwindow - * handle - */ + // * + // * @brief operator overload for treating atlas::window as a + GLFWwindow + // * handle + // * operator GLFWwindow*() { return native_window(); } - /** - * @brief Closing the window operation - */ + // * + // * @brief Closing the window operation + // * void close() { glfwSetWindowShouldClose(native_window(), true); } - /** - * @brief does the presentation operation that is operated internally - * with the vulkan swapchain - * - * @param p_current_frame_idx is current frame index to currently - * process an image in the current frame - */ + // * + // * @brief does the presentation operation that is operated internally + // * with the vulkan swapchain + // * + // * @param p_current_frame_idx is current frame index to currently + // * process an image in the current frame + // * void present(const uint32_t& p_current_frame_idx) { return present_frame(p_current_frame_idx); } @@ -103,4 +122,61 @@ export namespace atlas { virtual void present_frame(const uint32_t& p_current_frame) = 0; }; + */ + + class window { + public: + window() = default; + window(std::shared_ptr p_context, const window_params& p_params) + : m_device(p_context->logical_device()) { + m_instance = p_context->instance_handle(); + + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + m_params = p_params; + + m_window = glfwCreateWindow(static_cast(p_params.width), + static_cast(p_params.height), + p_params.name.c_str(), + nullptr, + nullptr); + + glfwMakeContextCurrent(m_window); + std::println("Constructing atlas::window"); + + m_surface = std::make_shared(p_context->instance_handle(), m_window); + + center_window(); + + + + graphics_context::submit_resource_free([this](){ + std::println("atlas::window submit resource free"); + // m_surface->destruct(); + }); + } + + GLFWwindow* glfw_window() const { return m_window; } + + void center_window() { + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode* mode = glfwGetVideoMode(monitor); + uint32_t width = (mode->width / 2) - (m_params.width / 2); + uint32_t height = (mode->height / 2) - (m_params.height / 2); + glfwSetWindowPos(m_window, + static_cast(width), + static_cast(height)); + } + + [[nodiscard]] bool available() const { + return !glfwWindowShouldClose(m_window); + } + + private: + vk::instance m_instance; + std::shared_ptr m_device=nullptr; + std::shared_ptr m_surface; + GLFWwindow* m_window = nullptr; + window_params m_params{}; + }; }; \ No newline at end of file diff --git a/atlas/drivers/drivers.cppm b/atlas/drivers/drivers.cppm index 12820831..5e3608ca 100644 --- a/atlas/drivers/drivers.cppm +++ b/atlas/drivers/drivers.cppm @@ -28,14 +28,14 @@ export namespace atlas { * * @return shared_ptr */ - ref initialize_window(ref p_context, - const window_params& p_params, - graphics_api p_api) { - switch (p_api) { - case graphics_api::vulkan: - return create_ref(p_context, p_params); - default: - return nullptr; - } - } + // ref initialize_window(ref p_context, + // const window_params& p_params, + // graphics_api p_api) { + // switch (p_api) { + // case graphics_api::vulkan: + // return create_ref(p_context, p_params); + // default: + // return nullptr; + // } + // } }; \ No newline at end of file diff --git a/atlas/drivers/graphics_context.cppm b/atlas/drivers/graphics_context.cppm index 3f0c8108..61f3405b 100644 --- a/atlas/drivers/graphics_context.cppm +++ b/atlas/drivers/graphics_context.cppm @@ -1,30 +1,76 @@ module; -#include +#include +#include #include +#include + +#include + +#define GLFW_INCLUDE_VULKAN +#if _WIN32 +#define VK_USE_PLATFORM_WIN32_KHR +#include +#define GLFW_EXPOSE_NATIVE_WIN32 +#include +#include +#else +#include +#include +#endif export module atlas.drivers.graphics_context; +import vk; + export namespace atlas { class graphics_context { public: - virtual ~graphics_context() = default; + graphics_context() = default; + graphics_context(const vk::instance& p_api_instance, + vk::physical_device& p_physical, + std::shared_ptr p_device) + : m_api_instance(p_api_instance) + , m_physical(&p_physical) + , m_device(p_device) { + // Constructing the graphics context + + s_instance = this; + } + + ~graphics_context() = default; - void submit_resource_free(const std::function& p_resource) { - return context_submit_resource_free(p_resource); + void post_cleanup() { + std::println("post_cleanup!"); + for (const auto& callback : m_submit_resource_free) { + callback(); + } } - [[nodiscard]] VkInstance handle() const { return context_handle(); } + [[nodiscard]] vk::instance instance_handle() const { + return m_api_instance; + } - void destroy() { return destroy_context(); } + [[nodiscard]] vk::physical_device physical_device() const { + return *m_physical; + } - protected: - virtual void destroy_context() = 0; - virtual void context_submit_resource_free( - const std::function& p_resource) = 0; + std::shared_ptr logical_device() { return m_device; } - [[nodiscard]] virtual VkInstance context_handle() const = 0; + static void submit_resource_free( + const std::function& p_callback) { + s_instance->m_submit_resource_free.emplace_back(p_callback); + } + + private: + vk::instance m_api_instance; + vk::physical_device* m_physical = nullptr; + std::shared_ptr m_device = nullptr; + std::deque> m_submit_resource_free{}; + static graphics_context* s_instance; }; + graphics_context* graphics_context::s_instance = nullptr; + }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/environment_map copy.cppm b/atlas/drivers/vulkan/environment_map copy.cppm deleted file mode 100644 index 9871e6be..00000000 --- a/atlas/drivers/vulkan/environment_map copy.cppm +++ /dev/null @@ -1,605 +0,0 @@ -module; - -#include -#include -#include -#include -#include -#include -#include - -#define GLFW_INCLUDE_VULKAN -#if _WIN32 -#define VK_USE_PLATFORM_WIN32_KHR -#include -#define GLFW_EXPOSE_NATIVE_WIN32 -#include -#include -#else -#include -#include -#endif -#include - -#define GLM_FORCE_RADIANS -#include -#include -#define GLM_ENABLE_EXPERIMENTAL -#include -#include - -export module atlas.drivers.vulkan.environment_map; - -import atlas.drivers.vulkan.instance_context; - -import vk; - -namespace atlas { - - export struct skybox_uniform { - glm::mat4 proj_view; - }; - - export class environment_map { - public: - environment_map() = default; - - environment_map(const VkDevice& p_device, - const std::filesystem::path& p_filename, - const vk::physical_device& p_physical, - VkRenderPass p_renderpass) - : m_device(p_device) { - create_hdr_skybox(p_filename, - p_physical, - p_physical.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit)); - - create_skybox_pipeline(p_physical, - p_physical.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - p_renderpass); - } - - // ~environment_map() { - // destroy(); - // } - - void create_hdr_skybox(const std::filesystem::path& p_filename, - const vk::physical_device& p_physical, - uint32_t p_memory_properties) { - - stbi_set_flip_vertically_on_load(true); - int w, h, channels; - float* pixels = stbi_loadf( - p_filename.string().c_str(), &w, &h, &channels, STBI_rgb_alpha); - - if (!pixels) { - throw std::runtime_error("Failed to load HDR image at: " + - p_filename.string()); - } - - const uint32_t width = static_cast(w); - const uint32_t height = static_cast(h); - - VkFormat texture_format = VK_FORMAT_R32G32B32A32_SFLOAT; - const uint64_t bytes_per_pixel_channel = 16; // float are 4 bytes - const uint64_t total_size_bytes = - static_cast(width * height * bytes_per_pixel_channel); - const uint64_t image_size = total_size_bytes; - - // Creating staging buffer - // uint32_t property_flag = vk::memory_property::host_visible_bit | - // vk::memory_property::host_cached_bit; - vk::buffer_parameters staging_buffer_params = { - // .physical_memory_properties = p_memory_properties, - .memory_mask = p_memory_properties, - // .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - .usage = vk::buffer_usage::transfer_src_bit, - }; - - vk::buffer staging_buffer = - vk::buffer(m_device, image_size, staging_buffer_params); - - // Creating image handle to storing the HDR data - // VkFormat texture_format = VK_FORMAT_R32G32B32A32_SFLOAT; - vk::image_params skybox_image_params = { - .extent = { - .width = width, - .height = height, - }, - .format = texture_format, - .memory_mask = p_physical.memory_properties(vk::memory_property::device_local_bit), - .aspect = vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::color_attachment_bit, - .mip_levels = 1, - .layer_count = 1, - }; - m_skybox_image = vk::sample_image(m_device, skybox_image_params); - - // Transferring data from the CPU - // void* data = nullptr; - // vkMapMemory(m_device, staging_memory, 0, total_size_bytes, 0, - // &data); std::memcpy(data, pixels, - // static_cast(total_size_bytes)); vkUnmapMemory(m_device, - // staging_memory); - std::span pixels_data( - reinterpret_cast(pixels), image_size); - staging_buffer.transfer(pixels_data, 0); - - // Free CPU pixels immediately after staging copy - stbi_image_free(pixels); - - // 6. Record and Execute Upload - vk::command_params upload_params = { - .levels = vk::command_levels::primary, - .queue_index = 0, // Graphics Queue - .flags = vk::command_pool_flags::reset, - }; - vk::command_buffer upload_cmd(m_device, upload_params); - - upload_cmd.begin(vk::command_usage::one_time_submit); - - // Begin Memory Barrier: Undefined to TRANSFER_DST - m_skybox_image.memory_barrier(upload_cmd, - texture_format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - // Performing buffer image copies - // vk::buffer_image_copy image_copy = { - // .extent = skybox_image_params.extent - // }; - vk::buffer_image_copy image_copy{ - .image_offset = { .width = 0, .height = 0, .depth = 0, }, - .image_extent = { .width = skybox_image_params.extent.width, .height = skybox_image_params.extent.height, .depth = 1, }, - }; - staging_buffer.copy_to_image( - upload_cmd, m_skybox_image, std::span(&image_copy, 1)); - - // Begin Memory Barrier: TRANSFER_DST to SHADER_READ_ONLY - m_skybox_image.memory_barrier( - upload_cmd, - texture_format, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - upload_cmd.end(); - - VkQueue graphics_queue; - vkGetDeviceQueue(m_device, 0, 0, &graphics_queue); - - VkCommandBuffer raw_cmd = upload_cmd; - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = 1, - .pCommandBuffers = &raw_cmd, - }; - - vkQueueSubmit(graphics_queue, 1, &submit_info, nullptr); - vkQueueWaitIdle(graphics_queue); - - upload_cmd.destruct(); - staging_buffer.destruct(); - stbi_set_flip_vertically_on_load(false); - } - - void create_buffers(const vk::physical_device& p_physical) { - std::vector vertices = { - // Front Face - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - - // Left Face - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - - // Right Face - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - - // Back Face - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - - // Top Face - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - - // Bottom Face - vk::vertex_input{ { -1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } } - }; - const auto property_flags = static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit); - vk::buffer_parameters vertex_params = { - .memory_mask = p_physical.memory_properties(property_flags), - .property_flags = vk::memory_property::device_local_bit, - .usage = vk::buffer_usage::transfer_dst_bit | - vk::buffer_usage::vertex_buffer_bit, - }; - - m_skybox_vbo = vk::vertex_buffer(m_device, vertices, vertex_params); - } - - void create_skybox_pipeline(const vk::physical_device& p_physical, - uint32_t p_memory_properties, - const VkRenderPass& p_renderpass) { - create_buffers(p_physical); - std::array attribute_entries = { - vk::vertex_attribute_entry{ - .location = 0, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position), - }, - vk::vertex_attribute_entry{ - .location = 1, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color), - }, - vk::vertex_attribute_entry{ - .location = 2, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals), - }, - vk::vertex_attribute_entry{ - .location = 3, - .format = vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv), - } - }; - std::array attribute = { - vk::vertex_attribute{ - // layout (set = 0, binding = 0) - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = vk::input_rate::vertex, - }, - }; - - const std::array sources = { - vk::shader_source{ - .filename = "builtin.shaders/skybox/skybox.vert.spv", - .stage = vk::shader_stage::vertex, - }, - vk::shader_source{ - .filename = "builtin.shaders/skybox/skybox.frag.spv", - .stage = vk::shader_stage::fragment, - }, - }; - - vk::shader_resource_info shader_info = { - .sources = sources, - }; - m_skybox_shaders = vk::shader_resource(m_device, shader_info); - m_skybox_shaders.vertex_attributes(attribute); - - // set=0 binding=0 UBO: mat4 VP - // vk::uniform_params ubo_params = { - // .memory_mask = p_memory_properties, - // .size_bytes = sizeof(skybox_uniform), - // .debug_name = "skybox_ubo", - // .vkSetDebugUtilsObjectNameEXT = nullptr, - // }; - // vk::buffer_parameters ubo_params = { - // .memory_mask = p_memory_properties, - // }; - vk::buffer_parameters uniform_params = { - .memory_mask = p_memory_properties, - .usage = vk::buffer_usage::uniform_buffer_bit, - }; - m_skybox_ubo = - vk::buffer(m_device, sizeof(skybox_uniform), ubo_params); - - skybox_uniform identity = { .proj_view = glm::mat4(1.0f) }; - identity.proj_view[1][1] *= -1; - // m_skybox_ubo.write(std::span(&identity, - // 1)); - m_skybox_ubo.transfer( - std::span(&identity, 1)); - - // set=0 bindings: - // - binding 0: UBO (vertex) - // - binding 1: samplerCube (fragment) - std::array entries = { - vk::descriptor_entry{ - .type = vk::descriptor_type::uniform, - .binding_point = - vk::descriptor_binding_point{ - .binding = 0, .stage = vk::shader_stage::vertex }, - .descriptor_count = 1, - }, - vk::descriptor_entry{ - .type = vk::descriptor_type::combined_image_sampler, - .binding_point = - vk::descriptor_binding_point{ - .binding = 1, .stage = vk::shader_stage::fragment }, - .descriptor_count = 1, - }, - }; - - vk::descriptor_layout desc_layout = { - .slot = 0, - .max_sets = 1, - .entries = entries, - }; - m_skybox_descriptors = - vk::descriptor_resource(m_device, desc_layout); - - const std::array ubo_writes = { - vk::write_buffer{ - .buffer = static_cast(m_skybox_ubo), - .offset = 0, - .range = static_cast(sizeof(skybox_uniform)) }, - }; - const vk::write_buffer_descriptor ubo_write_desc = { - .dst_binding = 0, - .uniforms = ubo_writes, - }; - - const std::array image_writes = { - vk::write_image{ - .sampler = m_skybox_image.sampler(), - .view = m_skybox_image.image_view(), - .layout = vk::image_layout::shader_read_only_optimal, - }, - }; - const vk::write_image_descriptor image_write_desc = { - .dst_binding = 1, - .sample_images = image_writes, - }; - - m_skybox_descriptors.update(std::span(&ubo_write_desc, 1), - std::span(&image_write_desc, 1)); - - const std::array layouts = { - m_skybox_descriptors.layout(), - }; - - const std::array - blend_attachments = { - vk::color_blend_attachment_state{ .blend_enabled = false }, - }; - vk::color_blend_state blend_state = { - .logic_op_enable = false, - .logical_op = vk::logical_op::copy, - .attachments = blend_attachments, - .blend_constants = {}, - }; - - std::array dyn = { - vk::dynamic_state::viewport, - vk::dynamic_state::scissor, - }; - - // pipeline expects a non-const span - std::array pipeline_layouts = layouts; - - vk::pipeline_params pipe_info = { - .renderpass = p_renderpass, - .shader_modules = m_skybox_shaders.handles(), - .vertex_attributes = - m_skybox_shaders.vertex_attributes(), // no vertex input - .vertex_bind_attributes = - m_skybox_shaders.vertex_bind_attributes(), // no vertex input - .descriptor_layouts = pipeline_layouts, - .input_assembly = - vk::input_assembly_state{ - .topology = vk::primitive_topology::triangle_list, - .primitive_restart_enable = false, - }, - .viewport = - vk::viewport_state{ .viewport_count = 1, .scissor_count = 1 }, - .rasterization = - vk::rasterization_state{ - .polygon_mode = vk::polygon_mode::fill, - .cull_mode = vk::cull_mode::front_bit, - // .cull_mode = vk::cull_mode::none, - // .front_face = vk::front_face::counter_clockwise, - .front_face = vk::front_face::clockwise, - .line_width = 1.f, - }, - .multisample = vk::multisample_state{}, - .color_blend = blend_state, - .depth_stencil_enabled = true, - .depth_stencil = - vk::depth_stencil_state{ - .depth_test_enable = true, - .depth_write_enable = false, - .depth_compare_op = vk::compare_op::less_or_equal, - .depth_bounds_test_enable = false, - .stencil_test_enable = false, - }, - .dynamic_states = dyn, - }; - - m_skybox_pipeline = vk::pipeline(m_device, pipe_info); - } - - void update_uniform(const skybox_uniform& p_ubo) { - // m_skybox_ubo.transfer(std::span(&p_ubo, - // 1)); - m_skybox_ubo.update(&p_ubo); - } - - void bind(vk::command_buffer& p_current) { - m_skybox_pipeline.bind(p_current); - m_skybox_descriptors.bind(p_current, m_skybox_pipeline.layout()); - // m_skybox_vbo.bind(p_current); - const VkBuffer vertex = m_skybox_vbo; - p_current.bind_vertex_buffers(std::span(&vertex, 1)); - } - - void draw(const VkCommandBuffer& p_current) { - // bind(p_current); - vkCmdDraw(p_current, m_skybox_vbo.size(), 1, 0, 0); - // vkCmdDrawIndexed(p_current, 36, 1, 0, 0, 0); - } - - //! @brief Retreving the sample image of the environment map. - [[nodiscard]] vk::sample_image image() const { return m_skybox_image; } - - void destroy() { - - m_skybox_image.destruct(); - if (m_skybox_pipeline.alive()) { - m_skybox_pipeline.destruct(); - } - m_skybox_descriptors.destruct(); - m_skybox_ubo.destruct(); - m_skybox_shaders.destruct(); - m_skybox_vbo.destruct(); - } - - //! TODO: Logic for converting the HDR image handles to a skybox - //! samplerCube - void process_to_cubemap() {} - - private: - VkDevice m_device = nullptr; - - vk::sample_image m_skybox_image; - - vk::shader_resource m_skybox_shaders{}; - vk::buffer m_skybox_ubo{}; - vk::descriptor_resource m_skybox_descriptors{}; - vk::pipeline m_skybox_pipeline{}; - vk::vertex_buffer m_skybox_vbo; - }; - -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/environment_map.cppm b/atlas/drivers/vulkan/environment_map.cppm index 3f66ea15..ff9716a4 100644 --- a/atlas/drivers/vulkan/environment_map.cppm +++ b/atlas/drivers/vulkan/environment_map.cppm @@ -27,10 +27,11 @@ module; #define GLM_ENABLE_EXPERIMENTAL #include #include +#include export module atlas.drivers.vulkan.environment_map; -import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.physical_device; import vk; @@ -45,10 +46,12 @@ namespace atlas { environment_map() = default; environment_map(const VkDevice& p_device, + vulkan::physical_device& p_physical, const std::filesystem::path& p_filename, - VkPhysicalDeviceMemoryProperties p_memory_properties, + uint32_t p_memory_properties, VkRenderPass p_renderpass) - : m_device(p_device) { + : m_device(p_device) + , m_physical(&p_physical) { m_memory_properties = p_memory_properties; create_hdr_skybox(p_filename); @@ -77,21 +80,24 @@ namespace atlas { const uint64_t image_size = total_size_bytes; // Creating staging buffer - uint32_t property_flag = vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit; vk::buffer_parameters staging_buffer_params = { - .device_size = static_cast(image_size), + // .device_size = static_cast(image_size), // Replace with .memory_mask - .physical_memory_properties = m_memory_properties, + .memory_mask = m_physical->memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), // Replace with .memory_mask - .property_flags = - static_cast(property_flag), - .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + // .property_flags = + // static_cast(property_flag), + // .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + .usage = vk::buffer_usage::transfer_src_bit, }; // Replace to be vk::buffer - vk::buffer_stream staging_buffer = - vk::buffer_stream(m_device, staging_buffer_params); + vk::buffer staging_buffer = + vk::buffer(m_device, + static_cast(image_size), + staging_buffer_params); // Creating image handle to storing the HDR vk::image_params skybox_image_params = { @@ -101,12 +107,12 @@ namespace atlas { }, .format = texture_format, // Replace with .memory_mask - .property = vk::memory_property::device_local_bit, + .memory_mask = m_memory_properties, + // Replace with .memory_mask + // .property = vk::memory_property::device_local_bit, .aspect = vk::image_aspect_flags::color_bit, .usage = vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, - // Replace with .memory_mask - .phsyical_memory_properties = m_memory_properties, }; m_skybox_image = vk::sample_image(m_device, skybox_image_params); @@ -114,7 +120,7 @@ namespace atlas { // Replace to using staging_buffer.transfer API std::span pixels_data( reinterpret_cast(pixels), image_size); - staging_buffer.write(pixels_data); + staging_buffer.transfer(pixels_data); // Free CPU pixels immediately after staging copy stbi_image_free(pixels); @@ -134,9 +140,13 @@ namespace atlas { texture_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - + + vk::buffer_image_copy image_copy = { + .image_offset = { .width = 0, .height = 0, .depth = 0, }, + .image_extent = { .width = skybox_image_params.extent.width, .height = skybox_image_params.extent.height, .depth = 1, }, + }; staging_buffer.copy_to_image( - upload_cmd, m_skybox_image, skybox_image_params.extent); + upload_cmd, m_skybox_image, std::span(&image_copy, 1)); // Begin Memory Barrier: TRANSFER_DST to SHADER_READ_ONLY m_skybox_image.memory_barrier( @@ -160,12 +170,15 @@ namespace atlas { vkQueueSubmit(graphics_queue, 1, &submit_info, nullptr); vkQueueWaitIdle(graphics_queue); - upload_cmd.destroy(); - staging_buffer.destroy(); + upload_cmd.destruct(); + staging_buffer.destruct(); stbi_set_flip_vertically_on_load(false); } void create_buffers() { + const auto property_flags = static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit); std::vector vertices = { // Front Face vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, @@ -323,13 +336,17 @@ namespace atlas { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f } } }; - vk::vertex_params vbo_params = { - // Replace with .memory_mask - .phsyical_memory_properties = m_memory_properties, - .vertices = vertices + + vk::buffer_parameters vertex_params = { + .memory_mask = m_physical->memory_properties(property_flags), + .property_flags = vk::memory_property::device_local_bit, + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; - m_skybox_vbo = vk::vertex_buffer(m_device, vbo_params); + m_skybox_vbo = vk::vertex_buffer(m_device, vertices, vertex_params); + + m_vertices_size = static_cast(vertices.size()); } void create_skybox_pipeline(const VkRenderPass& p_renderpass) { @@ -384,35 +401,39 @@ namespace atlas { m_skybox_shaders.vertex_attributes(attribute); // set=0 binding=0 UBO: mat4 VP - vk::uniform_params ubo_params = { - .phsyical_memory_properties = m_memory_properties, - .size_bytes = sizeof(skybox_uniform), - .debug_name = "skybox_ubo", - .vkSetDebugUtilsObjectNameEXT = nullptr, + vk::buffer_parameters uniform_params = { + .memory_mask = m_physical->memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | + vk::buffer_usage::shader_device_address_bit, + .allocate_flags = + vk::memory_allocate_flags::device_address_bit_khr, }; // Replace vk::uniform_params with vk::buffer_parameters(m_device, // sizeof(skybox_uniform), ubo_params); - m_skybox_ubo = vk::uniform_buffer(m_device, ubo_params); + m_skybox_ubo = vk::uniform_buffer(m_device, sizeof(skybox_uniform), uniform_params); skybox_uniform identity = { .proj_view = glm::mat4(1.0f) }; identity.proj_view[1][1] *= -1; // Replace with m_skybox_ubo.transfer - m_skybox_ubo.update(&identity); + m_skybox_ubo.transfer( + std::span(&identity, 1)); // set=0 bindings: // - binding 0: UBO (vertex) // - binding 1: samplerCube (fragment) std::array entries = { vk::descriptor_entry{ - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = vk::descriptor_binding_point{ .binding = 0, .stage = vk::shader_stage::vertex }, .descriptor_count = 1, }, vk::descriptor_entry{ - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = vk::descriptor_binding_point{ .binding = 1, .stage = vk::shader_stage::fragment }, @@ -518,7 +539,8 @@ namespace atlas { void update_uniform(const skybox_uniform& p_ubo) { // Replace with m_skybox_ubo.transfer(...) - m_skybox_ubo.update(&p_ubo); + // m_skybox_ubo.update(&p_ubo); + m_skybox_ubo.transfer(std::span(&p_ubo, 1)); } [[nodiscard]] VkPipelineLayout pipeline_layout() const { @@ -533,17 +555,17 @@ namespace atlas { void descriptor_bind(const VkCommandBuffer& p_command, const VkPipelineLayout& p_pipeline_layout) { - m_skybox_descriptors.bind(p_command, p_pipeline_layout); + // m_skybox_descriptors.bind(p_command, p_pipeline_layout); } [[nodiscard]] VkBuffer vertex_handle() const { return m_skybox_vbo; } [[nodiscard]] uint32_t vertices_size() const { - return m_skybox_vbo.size(); + return m_vertices_size; } void draw(const VkCommandBuffer& p_current) { - vkCmdDraw(p_current, m_skybox_vbo.size(), 1, 0, 0); + vkCmdDraw(p_current, m_vertices_size, 1, 0, 0); // vkCmdDrawIndexed(p_current, 36, 1, 0, 0, 0); } @@ -552,25 +574,27 @@ namespace atlas { void destroy() { - m_skybox_image.destroy(); + m_skybox_image.destruct(); if (m_skybox_pipeline.alive()) { - m_skybox_pipeline.destroy(); + m_skybox_pipeline.destruct(); } - m_skybox_descriptors.destroy(); - m_skybox_ubo.destroy(); - m_skybox_shaders.destroy(); - m_skybox_vbo.destroy(); + m_skybox_descriptors.destruct(); + m_skybox_ubo.destruct(); + m_skybox_shaders.destruct(); + m_skybox_vbo.destruct(); } private: VkDevice m_device = nullptr; - VkPhysicalDeviceMemoryProperties m_memory_properties; + vulkan::physical_device* m_physical; + uint32_t m_memory_properties; vk::sample_image m_skybox_image; vk::shader_resource m_skybox_shaders{}; vk::uniform_buffer m_skybox_ubo{}; vk::descriptor_resource m_skybox_descriptors{}; vk::pipeline m_skybox_pipeline{}; vk::vertex_buffer m_skybox_vbo; + uint32_t m_vertices_size=0; }; }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/imgui_context copy.cppm b/atlas/drivers/vulkan/imgui_context copy.cppm deleted file mode 100644 index 92f509d1..00000000 --- a/atlas/drivers/vulkan/imgui_context copy.cppm +++ /dev/null @@ -1,481 +0,0 @@ -module; - -#include -#include -#include -#include -#include -#include -#include -#include - -export module atlas.drivers.vulkan.imgui_context; - -import atlas.common; -import vk; - -import atlas.drivers.vulkan.instance_context; -import atlas.drivers.vulkan.physical_device; -import atlas.drivers.vulkan.device; -import atlas.drivers.vulkan.swapchain; -import atlas.core.utilities; - -namespace atlas::vulkan { - static void im_gui_layout_color_modification() { - auto& colors = ImGui::GetStyle().Colors; // @note Colors is ImVec4 - - colors[ImGuiCol_WindowBg] = ImVec4{ 0.1f, 0.105f, 0.11f, 1.0f }; - - // Headers - colors[ImGuiCol_Header] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_HeaderHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_HeaderActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Buttons - colors[ImGuiCol_Button] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_ButtonHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_ButtonActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Frame BG - colors[ImGuiCol_FrameBg] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_FrameBgHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_FrameBgActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Tabs - colors[ImGuiCol_Tab] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - colors[ImGuiCol_TabHovered] = ImVec4{ 0.38f, 0.3805f, 0.381f, 1.0f }; - colors[ImGuiCol_TabActive] = ImVec4{ 0.28f, 0.2805f, 0.281f, 1.0f }; - colors[ImGuiCol_TabUnfocused] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; - colors[ImGuiCol_TabUnfocusedActive] = - ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - - // Titles - colors[ImGuiCol_TitleBg] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - colors[ImGuiCol_TitleBgActive] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; - colors[ImGuiCol_TitleBgCollapsed] = - ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; - } - - void transition_image_layout(VkDevice p_device, - vk::sample_image& p_image, - VkFormat p_format, - VkImageLayout p_old, - VkImageLayout p_new) { - vk::command_params copy_command_params = { - .levels = vk::command_levels::primary, - .queue_index = 0, - .flags = vk::command_pool_flags::reset, - }; - vk::command_buffer temp_command_buffer = - vk::command_buffer(p_device, copy_command_params); - - temp_command_buffer.begin(vk::command_usage::one_time_submit); - - p_image.memory_barrier(temp_command_buffer, p_format, p_old, p_new); - - temp_command_buffer.end(); - - VkCommandBuffer handle = temp_command_buffer; - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = 1, - .pCommandBuffers = &handle, - }; - - uint32_t queue_family_index = 0; - uint32_t queue_index = 0; - VkQueue temp_graphics_queue; - vkGetDeviceQueue( - p_device, queue_family_index, queue_index, &temp_graphics_queue); - - vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); - vkQueueWaitIdle(temp_graphics_queue); - - temp_command_buffer.destruct(); - } - - export ImTextureID g_viewport_image_id = nullptr; - export class imgui_context { - public: - imgui_context() = default; - - imgui_context(const VkInstance& p_instance, - const swapchain& p_swapchain_ctx, - GLFWwindow* p_window_ctx) { - m_instance = p_instance; - m_physical = instance_context::physical_driver(); - const uint32_t memory_properties = - instance_context::physical_driver().memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit); - m_driver = instance_context::logical_device(); - // vk::device device_temp = instance_context::physical_driver(); - - m_current_swapchain_handler = p_swapchain_ctx; - m_extent = { .width = p_swapchain_ctx.settings().width, - .height = p_swapchain_ctx.settings().height }; - - // Setting up imgui - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - - io.ConfigFlags |= - ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // - // Enable Gamepad Controls - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking - io.ConfigFlags |= - ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / - // Platform Windows - - // io.ConfigViewportsNoAutoMerge = true; - // io.ConfigViewportsNoAutoMerge = true; - // io.ConfigViewportsNoTaskBarIcon = true; - - // Setup Dear ImGui style - // ImGui::StyleColorsDark(); - // ImGui::StyleColorsClassic(); - im_gui_layout_color_modification(); - - ImGuiStyle& style = ImGui::GetStyle(); - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - style.WindowRounding = 0.0f; - style.Colors[ImGuiCol_WindowBg].w = 1.0f; - } - - m_viewport_command_buffers.resize(p_swapchain_ctx.image_size()); - - for (size_t i = 0; i < m_viewport_command_buffers.size(); i++) { - ::vk::command_params settings = { - .levels = ::vk::command_levels::primary, - // .queue_index = - // enumerate_swapchain_settings.present_index, - .queue_index = 0, - .flags = ::vk::command_pool_flags::reset, - }; - m_viewport_command_buffers[i] = - ::vk::command_buffer(m_driver, settings); - } - - // ::vk::descriptor_res - // m_imgui_descriptor = ::vk::descriptor_resource(m_driver, {}); - // 1: create descriptor pool for IMGUI - // the size of the pool is very oversize, but it's copied from - // imgui demo itself. - std::array pool_sizes = { - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } - }; - - VkDescriptorPoolCreateInfo desc_pool_create_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .pNext = nullptr, - .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, - .maxSets = static_cast(1000 * pool_sizes.size()), - // .poolSizeCount = (uint32_t)std::size(pool_sizes), - .poolSizeCount = static_cast(pool_sizes.size()), - .pPoolSizes = pool_sizes.data() - }; - - // VkDescriptorPool imgui_pool; - vk::vk_check( - vkCreateDescriptorPool( - m_driver, &desc_pool_create_info, nullptr, &m_desc_pool), - "vkCreateDescriptorPool"); - - create(p_window_ctx, - p_swapchain_ctx.image_size(), - p_swapchain_ctx.swapchain_renderpass()); - - vk::image_params config_image = { - .extent = { .width = p_swapchain_ctx.settings().width, - .height = p_swapchain_ctx.settings().height }, - .format = VK_FORMAT_B8G8R8A8_UNORM, - .property = vk::memory_property::device_local_bit, - .memory_mask = memory_properties, - .aspect = vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::color_attachment_bit | - vk::image_usage::transfer_dst_bit | - vk::image_usage::sampled_bit, - // .usage = vk::image_usage::color_attachment_bit | - // vk::image_usage::transfer_dst_bit, - .address_mode_u = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, - }; - m_viewport_image = vk::sample_image(m_driver, config_image); - - // transition image layout uses image memory barrier - transition_image_layout(m_driver, - m_viewport_image, - VK_FORMAT_B8G8R8A8_UNORM, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Viewport-specific render pass: color attachment ends in - // SHADER_READ_ONLY_OPTIMAL so the offscreen texture can be sampled - // by ImGui. (Swapchain pass uses PRESENT_SRC.) - VkFormat depth_format = m_driver.depth_format(); - std::array<::vk::attachment, 2> viewport_attachments = { - ::vk::attachment{ - .format = VK_FORMAT_B8G8R8A8_UNORM, - .layout = ::vk::image_layout::color_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::store, - .stencil_load = ::vk::attachment_load::clear, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::shader_read_only_optimal, - }, - ::vk::attachment{ - .format = depth_format, - .layout = ::vk::image_layout::depth_stencil_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::dont_care, - .stencil_load = ::vk::attachment_load::dont_care, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::depth_stencil_optimal, - }, - }; - m_viewport_renderpass = - ::vk::renderpass(m_driver, viewport_attachments); - - vk::image_params config_depth_image = { - .extent = { .width = p_swapchain_ctx.settings().width, - .height = p_swapchain_ctx.settings().height }, - .format = m_driver.depth_format(), - .memory_mask = memory_properties, - .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::depth_bit, - // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .usage = vk::image_usage::depth_stencil_bit, - }; - - m_depth_viewport_image = - vk::sample_image(m_driver, config_depth_image); - - for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { - std::array image_view_attachments = { - m_viewport_image.image_view(), - m_depth_viewport_image.image_view() - }; - - vk::framebuffer_params framebuffer_info = { - .renderpass = m_viewport_renderpass, - .views = image_view_attachments, - .extent = { p_swapchain_ctx.settings().width, - p_swapchain_ctx.settings().height } - }; - m_viewport_framebuffers[i] = - vk::framebuffer(m_driver, framebuffer_info); - } - - g_viewport_image_id = - static_cast(ImGui_ImplVulkan_AddTexture( - m_viewport_image.sampler(), - m_viewport_image.image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - } - - void create(GLFWwindow* p_window_handler, - const uint32_t& p_image_size, - const VkRenderPass& p_current_renderpass) { - ImGui_ImplGlfw_InitForVulkan(p_window_handler, true); - ImGui_ImplVulkan_InitInfo init_info = {}; - init_info.Instance = m_instance; - init_info.PhysicalDevice = m_physical; - init_info.Device = m_driver; - init_info.Queue = m_driver.graphics_queue(); - init_info.RenderPass = p_current_renderpass; - init_info.PipelineCache = nullptr; - init_info.DescriptorPool = m_desc_pool; - init_info.MinImageCount = 2; - init_info.ImageCount = p_image_size; - init_info.UseDynamicRendering = false; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; - ImGui_ImplVulkan_Init(&init_info); - } - - void begin(const VkCommandBuffer& p_current, - const uint32_t& p_frame_index) { - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - m_current_frame_index = p_frame_index; - m_current = p_current; - } - - void invalidate(const swapchain& p_swapchain) { - // Wait for device to finish all operations before recreating - // resources - vkDeviceWaitIdle(m_driver); - - for (auto& fb : m_viewport_framebuffers) { - fb.destruct(); - } - - // Remove old texture from ImGui if needed - // ImTextureID in ImGui Vulkan backend is VkDescriptorSet cast to - // void* - if (g_viewport_image_id != nullptr) { - VkDescriptorSet old_descriptor_set = - reinterpret_cast(g_viewport_image_id); - ImGui_ImplVulkan_RemoveTexture(old_descriptor_set); - g_viewport_image_id = nullptr; - } - - // Destroy old images - m_viewport_image.destruct(); - m_depth_viewport_image.destruct(); - - // Recreate viewport images with new swapchain size - const uint32_t memory_properties = - instance_context::physical_driver().memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit); - - vk::image_params config_image = { - .extent = { .width = p_swapchain.settings().width, - .height = p_swapchain.settings().height }, - .format = VK_FORMAT_B8G8R8A8_UNORM, - .memory_mask = memory_properties, - .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::color_attachment_bit | - vk::image_usage::transfer_dst_bit | - vk::image_usage::sampled_bit, - .address_mode_u = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, - }; - m_viewport_image = vk::sample_image(m_driver, config_image); - - // Transition to shader read-only layout - transition_image_layout(m_driver, - m_viewport_image, - VK_FORMAT_B8G8R8A8_UNORM, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Recreate depth image - vk::image_params config_depth_image = { - .extent = { .width = p_swapchain.settings().width, - .height = p_swapchain.settings().height }, - .format = m_driver.depth_format(), - .memory_mask = memory_properties, - .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::depth_bit, - // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .usage = vk::image_usage::depth_stencil_bit, - }; - m_depth_viewport_image = - vk::sample_image(m_driver, config_depth_image); - - // Recreate framebuffers with new images - for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { - std::array image_view_attachments = { - m_viewport_image.image_view(), - m_depth_viewport_image.image_view() - }; - - vk::framebuffer_params framebuffer_info = { - .renderpass = m_viewport_renderpass, - .views = image_view_attachments, - .extent = { p_swapchain.settings().width, - p_swapchain.settings().height } - }; - m_viewport_framebuffers[i] = - vk::framebuffer(m_driver, framebuffer_info); - } - - // Update ImGui texture ID with new image - g_viewport_image_id = (ImTextureID)ImGui_ImplVulkan_AddTexture( - m_viewport_image.sampler(), - m_viewport_image.image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Update extent - m_extent = { .width = p_swapchain.settings().width, - .height = p_swapchain.settings().height }; - } - - void end() { - ImGui::Render(); - - ImDrawData* draw_data = ImGui::GetDrawData(); - ImGui_ImplVulkan_RenderDrawData(draw_data, m_current); - - ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - ImGui::UpdatePlatformWindows(); - ImGui::RenderPlatformWindowsDefault(); - } - } - - [[nodiscard]] ::vk::command_buffer imgui_active_command() const { - return m_viewport_command_buffers[m_current_frame_index]; - } - - vk::framebuffer active_framebuffer(uint32_t p_frame) const { - return m_viewport_framebuffers[p_frame]; - } - - [[nodiscard]] vk::renderpass viewport_renderpass() const { - return m_viewport_renderpass; - } - - void destroy() { - ImGui_ImplVulkan_Shutdown(); - vkDestroyDescriptorPool(m_driver, m_desc_pool, nullptr); - - for (auto& command_buffer : m_viewport_command_buffers) { - command_buffer.destruct(); - } - - for (auto& fb : m_viewport_framebuffers) { - fb.destruct(); - } - - m_viewport_renderpass.destruct(); - m_viewport_image.destruct(); - m_depth_viewport_image.destruct(); - - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - } - - private: - VkInstance m_instance = nullptr; - VkPhysicalDevice m_physical = nullptr; - device m_driver{}; - uint32_t m_current_frame_index = 0; - VkSwapchainKHR m_current_swapchain_handler = nullptr; - VkDescriptorPool m_desc_pool = nullptr; - VkCommandBuffer m_current = nullptr; - std::vector<::vk::command_buffer> m_viewport_command_buffers; - std::array m_viewport_framebuffers; - ::vk::renderpass m_viewport_renderpass; - vk::sample_image m_viewport_image; - vk::sample_image m_depth_viewport_image; - window_params m_extent; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index d533fefa..82d8d528 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -14,462 +14,466 @@ export module atlas.drivers.vulkan.imgui_context; import atlas.common; import vk; -import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.physical_device; import atlas.drivers.vulkan.device; import atlas.drivers.vulkan.swapchain; import atlas.core.utilities; namespace atlas::vulkan { - static void im_gui_layout_color_modification() { - auto& colors = ImGui::GetStyle().Colors; // @note Colors is ImVec4 - - colors[ImGuiCol_WindowBg] = ImVec4{ 0.1f, 0.105f, 0.11f, 1.0f }; - - // Headers - colors[ImGuiCol_Header] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_HeaderHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_HeaderActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Buttons - colors[ImGuiCol_Button] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_ButtonHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_ButtonActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Frame BG - colors[ImGuiCol_FrameBg] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_FrameBgHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_FrameBgActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Tabs - colors[ImGuiCol_Tab] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - colors[ImGuiCol_TabHovered] = ImVec4{ 0.38f, 0.3805f, 0.381f, 1.0f }; - colors[ImGuiCol_TabActive] = ImVec4{ 0.28f, 0.2805f, 0.281f, 1.0f }; - colors[ImGuiCol_TabUnfocused] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; - colors[ImGuiCol_TabUnfocusedActive] = - ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - - // Titles - colors[ImGuiCol_TitleBg] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - colors[ImGuiCol_TitleBgActive] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; - colors[ImGuiCol_TitleBgCollapsed] = - ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; - } - - void transition_image_layout(VkDevice p_device, - vk::sample_image& p_image, - VkFormat p_format, - VkImageLayout p_old, - VkImageLayout p_new) { - vk::command_params copy_command_params = { - .levels = vk::command_levels::primary, - .queue_index = 0, - .flags = vk::command_pool_flags::reset, - }; - vk::command_buffer temp_command_buffer = - vk::command_buffer(p_device, copy_command_params); - - temp_command_buffer.begin(vk::command_usage::one_time_submit); - - p_image.memory_barrier(temp_command_buffer, p_format, p_old, p_new); - - temp_command_buffer.end(); - - VkCommandBuffer handle = temp_command_buffer; - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = 1, - .pCommandBuffers = &handle, - }; - - uint32_t queue_family_index = 0; - uint32_t queue_index = 0; - VkQueue temp_graphics_queue; - vkGetDeviceQueue( - p_device, queue_family_index, queue_index, &temp_graphics_queue); - - vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); - vkQueueWaitIdle(temp_graphics_queue); - - temp_command_buffer.destroy(); - } - - export ImTextureID g_viewport_image_id = nullptr; - export class imgui_context { - public: - imgui_context() = default; - - imgui_context(const VkInstance& p_instance, - const swapchain& p_swapchain_ctx, - GLFWwindow* p_window_ctx) { - m_instance = p_instance; - m_physical = instance_context::physical_driver(); - VkPhysicalDeviceMemoryProperties memory_properties = - instance_context::physical_driver().memory_properties(); - m_driver = instance_context::logical_device(); - // vk::device device_temp = instance_context::physical_driver(); - - m_current_swapchain_handler = p_swapchain_ctx; - m_extent = { .width = p_swapchain_ctx.settings().width, - .height = p_swapchain_ctx.settings().height }; - - // Setting up imgui - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - - io.ConfigFlags |= - ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // - // Enable Gamepad Controls - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking - io.ConfigFlags |= - ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / - // Platform Windows - - // io.ConfigViewportsNoAutoMerge = true; - // io.ConfigViewportsNoAutoMerge = true; - // io.ConfigViewportsNoTaskBarIcon = true; - - // Setup Dear ImGui style - // ImGui::StyleColorsDark(); - // ImGui::StyleColorsClassic(); - im_gui_layout_color_modification(); - - ImGuiStyle& style = ImGui::GetStyle(); - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - style.WindowRounding = 0.0f; - style.Colors[ImGuiCol_WindowBg].w = 1.0f; - } - - m_viewport_command_buffers.resize(p_swapchain_ctx.image_size()); - - for (size_t i = 0; i < m_viewport_command_buffers.size(); i++) { - ::vk::command_params settings = { - .levels = ::vk::command_levels::primary, - // .queue_index = - // enumerate_swapchain_settings.present_index, - .queue_index = 0, - .flags = ::vk::command_pool_flags::reset, - }; - m_viewport_command_buffers[i] = - ::vk::command_buffer(m_driver, settings); - } - - // ::vk::descriptor_res - // m_imgui_descriptor = ::vk::descriptor_resource(m_driver, {}); - // 1: create descriptor pool for IMGUI - // the size of the pool is very oversize, but it's copied from - // imgui demo itself. - std::array pool_sizes = { - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } - }; - - VkDescriptorPoolCreateInfo desc_pool_create_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .pNext = nullptr, - .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, - .maxSets = static_cast(1000 * pool_sizes.size()), - // .poolSizeCount = (uint32_t)std::size(pool_sizes), - .poolSizeCount = static_cast(pool_sizes.size()), - .pPoolSizes = pool_sizes.data() - }; - - // VkDescriptorPool imgui_pool; - vk::vk_check( - vkCreateDescriptorPool( - m_driver, &desc_pool_create_info, nullptr, &m_desc_pool), - "vkCreateDescriptorPool"); - - create(p_window_ctx, - p_swapchain_ctx.image_size(), - p_swapchain_ctx.swapchain_renderpass()); - - vk::image_params config_image = { - .extent = { .width = p_swapchain_ctx.settings().width, - .height = p_swapchain_ctx.settings().height }, - .format = VK_FORMAT_B8G8R8A8_UNORM, - .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::color_attachment_bit | - vk::image_usage::transfer_dst_bit | - vk::image_usage::sampled_bit, - // .usage = vk::image_usage::color_attachment_bit | - // vk::image_usage::transfer_dst_bit, - .phsyical_memory_properties = memory_properties, - .address_mode_u = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, - }; - m_viewport_image = vk::sample_image(m_driver, config_image); - - // transition image layout uses image memory barrier - transition_image_layout(m_driver, - m_viewport_image, - VK_FORMAT_B8G8R8A8_UNORM, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Viewport-specific render pass: color attachment ends in - // SHADER_READ_ONLY_OPTIMAL so the offscreen texture can be sampled - // by ImGui. (Swapchain pass uses PRESENT_SRC.) - VkFormat depth_format = m_driver.depth_format(); - std::array<::vk::attachment, 2> viewport_attachments = { - ::vk::attachment{ - .format = VK_FORMAT_B8G8R8A8_UNORM, - .layout = ::vk::image_layout::color_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::store, - .stencil_load = ::vk::attachment_load::clear, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::shader_read_only_optimal, - }, - ::vk::attachment{ - .format = depth_format, - .layout = ::vk::image_layout::depth_stencil_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::dont_care, - .stencil_load = ::vk::attachment_load::dont_care, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::depth_stencil_optimal, - }, - }; - m_viewport_renderpass = - ::vk::renderpass(m_driver, viewport_attachments); - - vk::image_params config_depth_image = { - .extent = { .width = p_swapchain_ctx.settings().width, - .height = p_swapchain_ctx.settings().height }, - .format = m_driver.depth_format(), - .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::depth_bit, - .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .phsyical_memory_properties = memory_properties, - }; - - m_depth_viewport_image = - vk::sample_image(m_driver, config_depth_image); - - for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { - std::array image_view_attachments = { - m_viewport_image.image_view(), - m_depth_viewport_image.image_view() - }; - - vk::framebuffer_params framebuffer_info = { - .renderpass = m_viewport_renderpass, - .views = image_view_attachments, - .extent = { p_swapchain_ctx.settings().width, - p_swapchain_ctx.settings().height } - }; - m_viewport_framebuffers[i] = - vk::framebuffer(m_driver, framebuffer_info); - } - - g_viewport_image_id = - static_cast(ImGui_ImplVulkan_AddTexture( - m_viewport_image.sampler(), - m_viewport_image.image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - } - - void create(GLFWwindow* p_window_handler, - const uint32_t& p_image_size, - const VkRenderPass& p_current_renderpass) { - ImGui_ImplGlfw_InitForVulkan(p_window_handler, true); - ImGui_ImplVulkan_InitInfo init_info = {}; - init_info.Instance = m_instance; - init_info.PhysicalDevice = m_physical; - init_info.Device = m_driver; - init_info.Queue = m_driver.graphics_queue(); - init_info.RenderPass = p_current_renderpass; - init_info.PipelineCache = nullptr; - init_info.DescriptorPool = m_desc_pool; - init_info.MinImageCount = 2; - init_info.ImageCount = p_image_size; - init_info.UseDynamicRendering = false; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; - ImGui_ImplVulkan_Init(&init_info); - } - - void begin(const VkCommandBuffer& p_current, - const uint32_t& p_frame_index) { - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - m_current_frame_index = p_frame_index; - m_current = p_current; - } - - void invalidate(const swapchain& p_swapchain) { - // Wait for device to finish all operations before recreating - // resources - vkDeviceWaitIdle(m_driver); - - for (auto& fb : m_viewport_framebuffers) { - fb.destroy(); - } - - // Remove old texture from ImGui if needed - // ImTextureID in ImGui Vulkan backend is VkDescriptorSet cast to - // void* - if (g_viewport_image_id != nullptr) { - VkDescriptorSet old_descriptor_set = - reinterpret_cast(g_viewport_image_id); - ImGui_ImplVulkan_RemoveTexture(old_descriptor_set); - g_viewport_image_id = nullptr; - } - - // Destroy old images - m_viewport_image.destroy(); - m_depth_viewport_image.destroy(); - - // Recreate viewport images with new swapchain size - VkPhysicalDeviceMemoryProperties memory_properties = - instance_context::physical_driver().memory_properties(); - - vk::image_params config_image = { - .extent = { .width = p_swapchain.settings().width, - .height = p_swapchain.settings().height }, - .format = VK_FORMAT_B8G8R8A8_UNORM, - .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::color_attachment_bit | - vk::image_usage::transfer_dst_bit | - vk::image_usage::sampled_bit, - .phsyical_memory_properties = memory_properties, - .address_mode_u = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, - }; - m_viewport_image = vk::sample_image(m_driver, config_image); - - // Transition to shader read-only layout - transition_image_layout(m_driver, - m_viewport_image, - VK_FORMAT_B8G8R8A8_UNORM, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Recreate depth image - vk::image_params config_depth_image = { - .extent = { .width = p_swapchain.settings().width, - .height = p_swapchain.settings().height }, - .format = m_driver.depth_format(), - .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::depth_bit, - .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .phsyical_memory_properties = memory_properties, - }; - m_depth_viewport_image = - vk::sample_image(m_driver, config_depth_image); - - // Recreate framebuffers with new images - for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { - std::array image_view_attachments = { - m_viewport_image.image_view(), - m_depth_viewport_image.image_view() - }; - - vk::framebuffer_params framebuffer_info = { - .renderpass = m_viewport_renderpass, - .views = image_view_attachments, - .extent = { p_swapchain.settings().width, - p_swapchain.settings().height } - }; - m_viewport_framebuffers[i] = - vk::framebuffer(m_driver, framebuffer_info); - } - - // Update ImGui texture ID with new image - g_viewport_image_id = (ImTextureID)ImGui_ImplVulkan_AddTexture( - m_viewport_image.sampler(), - m_viewport_image.image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Update extent - m_extent = { .width = p_swapchain.settings().width, - .height = p_swapchain.settings().height }; - } - - void end() { - ImGui::Render(); - - ImDrawData* draw_data = ImGui::GetDrawData(); - ImGui_ImplVulkan_RenderDrawData(draw_data, m_current); - - ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - ImGui::UpdatePlatformWindows(); - ImGui::RenderPlatformWindowsDefault(); - } - } - - [[nodiscard]] ::vk::command_buffer imgui_active_command() const { - return m_viewport_command_buffers[m_current_frame_index]; - } - - vk::framebuffer active_framebuffer(uint32_t p_frame) const { - return m_viewport_framebuffers[p_frame]; - } - - [[nodiscard]] vk::renderpass viewport_renderpass() const { - return m_viewport_renderpass; - } - - void destroy() { - ImGui_ImplVulkan_Shutdown(); - vkDestroyDescriptorPool(m_driver, m_desc_pool, nullptr); - - for (auto& command_buffer : m_viewport_command_buffers) { - command_buffer.destroy(); - } - - for (auto& fb : m_viewport_framebuffers) { - fb.destroy(); - } - - m_viewport_renderpass.destroy(); - m_viewport_image.destroy(); - m_depth_viewport_image.destroy(); - - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - } - - private: - VkInstance m_instance = nullptr; - VkPhysicalDevice m_physical = nullptr; - device m_driver{}; - uint32_t m_current_frame_index = 0; - VkSwapchainKHR m_current_swapchain_handler = nullptr; - VkDescriptorPool m_desc_pool = nullptr; - VkCommandBuffer m_current = nullptr; - std::vector<::vk::command_buffer> m_viewport_command_buffers; - std::array m_viewport_framebuffers; - ::vk::renderpass m_viewport_renderpass; - vk::sample_image m_viewport_image; - vk::sample_image m_depth_viewport_image; - window_params m_extent; - }; + // static void im_gui_layout_color_modification() { + // auto& colors = ImGui::GetStyle().Colors; // @note Colors is ImVec4 + + // colors[ImGuiCol_WindowBg] = ImVec4{ 0.1f, 0.105f, 0.11f, 1.0f }; + + // // Headers + // colors[ImGuiCol_Header] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + // colors[ImGuiCol_HeaderHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + // colors[ImGuiCol_HeaderActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // // Buttons + // colors[ImGuiCol_Button] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + // colors[ImGuiCol_ButtonHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + // colors[ImGuiCol_ButtonActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // // Frame BG + // colors[ImGuiCol_FrameBg] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + // colors[ImGuiCol_FrameBgHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + // colors[ImGuiCol_FrameBgActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // // Tabs + // colors[ImGuiCol_Tab] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + // colors[ImGuiCol_TabHovered] = ImVec4{ 0.38f, 0.3805f, 0.381f, 1.0f }; + // colors[ImGuiCol_TabActive] = ImVec4{ 0.28f, 0.2805f, 0.281f, 1.0f }; + // colors[ImGuiCol_TabUnfocused] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; + // colors[ImGuiCol_TabUnfocusedActive] = + // ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + + // // Titles + // colors[ImGuiCol_TitleBg] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + // colors[ImGuiCol_TitleBgActive] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; + // colors[ImGuiCol_TitleBgCollapsed] = + // ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; + // } + + // void transition_image_layout(VkDevice p_device, + // vk::sample_image& p_image, + // VkFormat p_format, + // VkImageLayout p_old, + // VkImageLayout p_new) { + // vk::command_params copy_command_params = { + // .levels = vk::command_levels::primary, + // .queue_index = 0, + // .flags = vk::command_pool_flags::reset, + // }; + // vk::command_buffer temp_command_buffer = + // vk::command_buffer(p_device, copy_command_params); + + // temp_command_buffer.begin(vk::command_usage::one_time_submit); + + // p_image.memory_barrier(temp_command_buffer, p_format, p_old, p_new); + + // temp_command_buffer.end(); + + // VkCommandBuffer handle = temp_command_buffer; + // VkSubmitInfo submit_info = { + // .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + // .commandBufferCount = 1, + // .pCommandBuffers = &handle, + // }; + + // uint32_t queue_family_index = 0; + // uint32_t queue_index = 0; + // VkQueue temp_graphics_queue; + // vkGetDeviceQueue( + // p_device, queue_family_index, queue_index, &temp_graphics_queue); + + // vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); + // vkQueueWaitIdle(temp_graphics_queue); + + // temp_command_buffer.destruct(); + // } + + // export ImTextureID g_viewport_image_id = nullptr; + // export class imgui_context { + // public: + // imgui_context() = default; + + // imgui_context(const VkInstance& p_instance, + // const swapchain& p_swapchain_ctx, + // GLFWwindow* p_window_ctx) { + // m_instance = p_instance; + // console_log_info("imgui_context"); + // m_physical = instance_context::physical_driver(); + // m_driver = instance_context::logical_device(); + // // vk::device device_temp = instance_context::physical_driver(); + + // m_current_swapchain_handler = p_swapchain_ctx; + // m_extent = { .width = p_swapchain_ctx.settings().width, + // .height = p_swapchain_ctx.settings().height }; + + // // Setting up imgui + // IMGUI_CHECKVERSION(); + // ImGui::CreateContext(); + // ImGuiIO& io = ImGui::GetIO(); + + // io.ConfigFlags |= + // ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + // // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // + // // Enable Gamepad Controls + // io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking + // io.ConfigFlags |= + // ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / + // // Platform Windows + + // // io.ConfigViewportsNoAutoMerge = true; + // // io.ConfigViewportsNoAutoMerge = true; + // // io.ConfigViewportsNoTaskBarIcon = true; + + // // Setup Dear ImGui style + // // ImGui::StyleColorsDark(); + // // ImGui::StyleColorsClassic(); + // im_gui_layout_color_modification(); + + // ImGuiStyle& style = ImGui::GetStyle(); + // if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + // style.WindowRounding = 0.0f; + // style.Colors[ImGuiCol_WindowBg].w = 1.0f; + // } + + // m_viewport_command_buffers.resize(p_swapchain_ctx.image_size()); + + // for (size_t i = 0; i < m_viewport_command_buffers.size(); i++) { + // ::vk::command_params settings = { + // .levels = ::vk::command_levels::primary, + // // .queue_index = + // // enumerate_swapchain_settings.present_index, + // .queue_index = 0, + // .flags = ::vk::command_pool_flags::reset, + // }; + // m_viewport_command_buffers[i] = + // ::vk::command_buffer(m_driver, settings); + // } + + // // ::vk::descriptor_res + // // m_imgui_descriptor = ::vk::descriptor_resource(m_driver, {}); + // // 1: create descriptor pool for IMGUI + // // the size of the pool is very oversize, but it's copied from + // // imgui demo itself. + // std::array pool_sizes = { + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLER, 100 }, + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + // 100 }, + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 100 }, + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 100 }, + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + // 100 }, + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + // 100 }, + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100 }, + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 100 }, + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + // 100 }, + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, + // 100 }, + // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } + // }; + + // VkDescriptorPoolCreateInfo desc_pool_create_info = { + // .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + // .pNext = nullptr, + // .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + // .maxSets = static_cast(1000 * pool_sizes.size()), + // // .poolSizeCount = (uint32_t)std::size(pool_sizes), + // .poolSizeCount = static_cast(pool_sizes.size()), + // .pPoolSizes = pool_sizes.data() + // }; + + // // VkDescriptorPool imgui_pool; + // vk::vk_check( + // vkCreateDescriptorPool( + // m_driver, &desc_pool_create_info, nullptr, &m_desc_pool), + // "vkCreateDescriptorPool"); + + // create(p_window_ctx, + // p_swapchain_ctx.image_size(), + // p_swapchain_ctx.swapchain_renderpass()); + + // vk::image_params config_image = { + // .extent = { .width = p_swapchain_ctx.settings().width, + // .height = p_swapchain_ctx.settings().height }, + // .format = VK_FORMAT_B8G8R8A8_UNORM, + // .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), + // // .property = vk::memory_property::device_local_bit, + // .aspect = vk::image_aspect_flags::color_bit, + // .usage = vk::image_usage::color_attachment_bit | + // vk::image_usage::transfer_dst_bit | + // vk::image_usage::sampled_bit, + // // .usage = vk::image_usage::color_attachment_bit | + // // vk::image_usage::transfer_dst_bit, + // // .phsyical_memory_properties = memory_properties, + // .address_mode_u = vk::sampler_address_mode::clamp_to_edge, + // .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, + // .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, + // }; + // m_viewport_image = vk::sample_image(m_driver, config_image); + + // // transition image layout uses image memory barrier + // transition_image_layout(m_driver, + // m_viewport_image, + // VK_FORMAT_B8G8R8A8_UNORM, + // VK_IMAGE_LAYOUT_UNDEFINED, + // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + // // Viewport-specific render pass: color attachment ends in + // // SHADER_READ_ONLY_OPTIMAL so the offscreen texture can be sampled + // // by ImGui. (Swapchain pass uses PRESENT_SRC.) + // VkFormat depth_format = m_driver.depth_format(); + // std::array<::vk::attachment, 2> viewport_attachments = { + // ::vk::attachment{ + // .format = VK_FORMAT_B8G8R8A8_UNORM, + // .layout = ::vk::image_layout::color_optimal, + // .samples = ::vk::sample_bit::count_1, + // .load = ::vk::attachment_load::clear, + // .store = ::vk::attachment_store::store, + // .stencil_load = ::vk::attachment_load::clear, + // .stencil_store = ::vk::attachment_store::dont_care, + // .initial_layout = ::vk::image_layout::undefined, + // .final_layout = ::vk::image_layout::shader_read_only_optimal, + // }, + // ::vk::attachment{ + // .format = depth_format, + // .layout = ::vk::image_layout::depth_stencil_optimal, + // .samples = ::vk::sample_bit::count_1, + // .load = ::vk::attachment_load::clear, + // .store = ::vk::attachment_store::dont_care, + // .stencil_load = ::vk::attachment_load::dont_care, + // .stencil_store = ::vk::attachment_store::dont_care, + // .initial_layout = ::vk::image_layout::undefined, + // .final_layout = ::vk::image_layout::depth_stencil_optimal, + // }, + // }; + // m_viewport_renderpass = + // ::vk::renderpass(m_driver, viewport_attachments); + + // vk::image_params config_depth_image = { + // .extent = { .width = p_swapchain_ctx.settings().width, + // .height = p_swapchain_ctx.settings().height }, + // .format = m_driver.depth_format(), + // .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), + // // .property = vk::memory_property::device_local_bit, + // .aspect = vk::image_aspect_flags::depth_bit, + // // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + // .usage = vk::image_usage::depth_stencil_bit, + // // .phsyical_memory_properties = memory_properties, + // }; + + // m_depth_viewport_image = + // vk::sample_image(m_driver, config_depth_image); + + // for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { + // std::array image_view_attachments = { + // m_viewport_image.image_view(), + // m_depth_viewport_image.image_view() + // }; + + // vk::framebuffer_params framebuffer_info = { + // .renderpass = m_viewport_renderpass, + // .views = image_view_attachments, + // .extent = { p_swapchain_ctx.settings().width, + // p_swapchain_ctx.settings().height } + // }; + // m_viewport_framebuffers[i] = + // vk::framebuffer(m_driver, framebuffer_info); + // } + + // g_viewport_image_id = + // static_cast(ImGui_ImplVulkan_AddTexture( + // m_viewport_image.sampler(), + // m_viewport_image.image_view(), + // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + // } + + // void create(GLFWwindow* p_window_handler, + // const uint32_t& p_image_size, + // const VkRenderPass& p_current_renderpass) { + // ImGui_ImplGlfw_InitForVulkan(p_window_handler, true); + // ImGui_ImplVulkan_InitInfo init_info = {}; + // init_info.Instance = m_instance; + // init_info.PhysicalDevice = m_physical; + // init_info.Device = m_driver; + // init_info.Queue = m_driver.graphics_queue(); + // init_info.RenderPass = p_current_renderpass; + // init_info.PipelineCache = nullptr; + // init_info.DescriptorPool = m_desc_pool; + // init_info.MinImageCount = 2; + // init_info.ImageCount = p_image_size; + // init_info.UseDynamicRendering = false; + // init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + // ImGui_ImplVulkan_Init(&init_info); + // } + + // void begin(const VkCommandBuffer& p_current, + // const uint32_t& p_frame_index) { + // ImGui_ImplVulkan_NewFrame(); + // ImGui_ImplGlfw_NewFrame(); + // ImGui::NewFrame(); + + // m_current_frame_index = p_frame_index; + // m_current = p_current; + // } + + // void invalidate(const swapchain& p_swapchain) { + // // Wait for device to finish all operations before recreating + // // resources + // vkDeviceWaitIdle(m_driver); + + // for (auto& fb : m_viewport_framebuffers) { + // fb.destruct(); + // } + + // // Remove old texture from ImGui if needed + // // ImTextureID in ImGui Vulkan backend is VkDescriptorSet cast to + // // void* + // if (g_viewport_image_id != nullptr) { + // VkDescriptorSet old_descriptor_set = + // reinterpret_cast(g_viewport_image_id); + // ImGui_ImplVulkan_RemoveTexture(old_descriptor_set); + // g_viewport_image_id = nullptr; + // } + + // // Destroy old images + // m_viewport_image.destruct(); + // m_depth_viewport_image.destruct(); + + // // Recreate viewport images with new swapchain size + // // VkPhysicalDeviceMemoryProperties memory_properties = + // // instance_context::physical_driver().memory_properties(); + + // vk::image_params config_image = { + // .extent = { .width = p_swapchain.settings().width, + // .height = p_swapchain.settings().height }, + // .format = VK_FORMAT_B8G8R8A8_UNORM, + // .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), + // // .property = m_physical.memory_properties(vk::memory_property::device_local_bit), + // .aspect = vk::image_aspect_flags::color_bit, + // .usage = vk::image_usage::color_attachment_bit | + // vk::image_usage::transfer_dst_bit | + // vk::image_usage::sampled_bit, + // // .phsyical_memory_properties = memory_properties, + // .address_mode_u = vk::sampler_address_mode::clamp_to_edge, + // .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, + // .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, + // }; + // m_viewport_image = vk::sample_image(m_driver, config_image); + + // // Transition to shader read-only layout + // transition_image_layout(m_driver, + // m_viewport_image, + // VK_FORMAT_B8G8R8A8_UNORM, + // VK_IMAGE_LAYOUT_UNDEFINED, + // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + // // Recreate depth image + // vk::image_params config_depth_image = { + // .extent = { .width = p_swapchain.settings().width, + // .height = p_swapchain.settings().height }, + // .format = m_driver.depth_format(), + // .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), + // .property = vk::memory_property::device_local_bit, + // .aspect = vk::image_aspect_flags::depth_bit, + // // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + // .usage = vk::image_usage::depth_stencil_bit, + // // .phsyical_memory_properties = memory_properties, + // }; + // m_depth_viewport_image = + // vk::sample_image(m_driver, config_depth_image); + + // // Recreate framebuffers with new images + // for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { + // std::array image_view_attachments = { + // m_viewport_image.image_view(), + // m_depth_viewport_image.image_view() + // }; + + // vk::framebuffer_params framebuffer_info = { + // .renderpass = m_viewport_renderpass, + // .views = image_view_attachments, + // .extent = { p_swapchain.settings().width, + // p_swapchain.settings().height } + // }; + // m_viewport_framebuffers[i] = + // vk::framebuffer(m_driver, framebuffer_info); + // } + + // // Update ImGui texture ID with new image + // g_viewport_image_id = (ImTextureID)ImGui_ImplVulkan_AddTexture( + // m_viewport_image.sampler(), + // m_viewport_image.image_view(), + // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + // // Update extent + // m_extent = { .width = p_swapchain.settings().width, + // .height = p_swapchain.settings().height }; + // } + + // void end() { + // ImGui::Render(); + + // ImDrawData* draw_data = ImGui::GetDrawData(); + // ImGui_ImplVulkan_RenderDrawData(draw_data, m_current); + + // ImGuiIO& io = ImGui::GetIO(); + // if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + // ImGui::UpdatePlatformWindows(); + // ImGui::RenderPlatformWindowsDefault(); + // } + // } + + // [[nodiscard]] ::vk::command_buffer imgui_active_command() const { + // return m_viewport_command_buffers[m_current_frame_index]; + // } + + // vk::framebuffer active_framebuffer(uint32_t p_frame) const { + // return m_viewport_framebuffers[p_frame]; + // } + + // [[nodiscard]] vk::renderpass viewport_renderpass() const { + // return m_viewport_renderpass; + // } + + // void destroy() { + // ImGui_ImplVulkan_Shutdown(); + // vkDestroyDescriptorPool(m_driver, m_desc_pool, nullptr); + + // for (auto& command_buffer : m_viewport_command_buffers) { + // command_buffer.destruct(); + // } + + // for (auto& fb : m_viewport_framebuffers) { + // fb.destruct(); + // } + + // m_viewport_renderpass.destruct(); + // m_viewport_image.destruct(); + // m_depth_viewport_image.destruct(); + + // ImGui_ImplGlfw_Shutdown(); + // ImGui::DestroyContext(); + // } + + // private: + // VkInstance m_instance = nullptr; + // physical_device m_physical = nullptr; + // device m_driver{}; + // uint32_t m_current_frame_index = 0; + // VkSwapchainKHR m_current_swapchain_handler = nullptr; + // VkDescriptorPool m_desc_pool = nullptr; + // VkCommandBuffer m_current = nullptr; + // std::vector<::vk::command_buffer> m_viewport_command_buffers; + // std::array m_viewport_framebuffers; + // ::vk::renderpass m_viewport_renderpass; + // vk::sample_image m_viewport_image; + // vk::sample_image m_depth_viewport_image; + // window_params m_extent; + // }; }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/instance_context.cppm b/atlas/drivers/vulkan/instance_context.cppm deleted file mode 100644 index b828f4ee..00000000 --- a/atlas/drivers/vulkan/instance_context.cppm +++ /dev/null @@ -1,253 +0,0 @@ -module; - -#include -#include -#include -#include - -#define GLFW_INCLUDE_VULKAN -#if _WIN32 -#define VK_USE_PLATFORM_WIN32_KHR -#include -#define GLFW_EXPOSE_NATIVE_WIN32 -#include -#include -#else -#include -#include -#endif - -export module atlas.drivers.vulkan.instance_context; - -import atlas.logger; - -import atlas.drivers.graphics_context; -import atlas.drivers.vulkan.utilities; -import atlas.drivers.vulkan.physical_device; -import atlas.drivers.vulkan.device; - -namespace atlas::vulkan { - - static std::vector initialize_instance_extensions() { - std::vector extension_names; - - uint32_t extension_count = 0; - const char** require_extensions = - glfwGetRequiredInstanceExtensions(&extension_count); - - for (uint32_t i = 0; i < extension_count; i++) { - // std::println("Required Extension = {}", require_extensions[i]); - extension_names.emplace_back(require_extensions[i]); - } - -#if !defined(NDEBUG) || defined(_DEBUG) || defined(DEBUG) - extension_names.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); -#endif - -#if defined(__APPLE__) - extension_names.emplace_back( - VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); - extension_names.emplace_back( - VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); -#endif - - return extension_names; - } - -#if !defined(NDEBUG) || defined(_DEBUG) || defined(DEBUG) - const std::vector validation_layers = { - "VK_LAYER_KHRONOS_validation", - "VK_LAYER_KHRONOS_synchronization2" - }; - - static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( - [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT - p_message_severity, - [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT p_message_type, - const VkDebugUtilsMessengerCallbackDataEXT* p_callback_data, - [[maybe_unused]] void* p_user_data) { - console_log_trace("validation layer:\t\t{}", p_callback_data->pMessage); - return false; - } -#endif - - export class instance_context : public graphics_context { - public: - instance_context(const std::string&) { - VkApplicationInfo app_info = { - .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, - .pNext = nullptr, - .applicationVersion = 1, - .pEngineName = "TheAtlasEngine", - .engineVersion = 1, - .apiVersion = VK_API_VERSION_1_3, - }; - - VkInstanceCreateInfo create_info = { - .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .pApplicationInfo = &app_info - }; - -#if defined(__APPLE__) - create_info.flags |= - VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; -#endif - - //! @note Setting up the required extensions for vulkan - std::vector extensions = - initialize_instance_extensions(); -#if !defined(NDEBUG) || defined(_DEBUG) || defined(DEBUG) - extensions.push_back("VK_EXT_debug_utils"); -#endif - create_info.enabledExtensionCount = - static_cast(extensions.size()); - create_info.ppEnabledExtensionNames = extensions.data(); -#if !defined(NDEBUG) || defined(_DEBUG) || defined(DEBUG) - // by default we enable validation layers used for debugging! - create_info.enabledLayerCount = - static_cast(validation_layers.size()); - create_info.ppEnabledLayerNames = validation_layers.data(); - - // printing out available validation layers - uint32_t layer_count; - std::vector available_validation_layers; - vkEnumerateInstanceLayerProperties(&layer_count, nullptr); - - available_validation_layers.resize(layer_count); - vkEnumerateInstanceLayerProperties( - &layer_count, available_validation_layers.data()); - - console_log_trace( - "================================================"); - console_log_trace("\tValidation Layers Available"); - console_log_trace( - "================================================"); - for (VkLayerProperties properties : available_validation_layers) { - console_log_trace("Validation Layer:\t\t{}", - properties.layerName); - console_log_trace("Description\t\t{}", properties.description); - console_log_trace("Version\t\t\t{}", - (int)properties.specVersion); - } - - console_log_trace("\n"); - console_log_trace( - "================================================\n"); - - VkDebugUtilsMessengerCreateInfoEXT debug_create_info = { - .sType = - VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, - .messageSeverity = - VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, - .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, - .pfnUserCallback = debug_callback, - }; - - // create_info.pNext = - // (VkDebugUtilsMessengerCreateInfoEXT*)&debug_create_info; - create_info.pNext = - static_cast( - &debug_create_info); -#else - create_info.enabledLayerCount = 0; - create_info.ppEnabledLayerNames = nullptr; - create_info.pNext = nullptr; -#endif - vk_check( - vkCreateInstance(&create_info, nullptr, &m_instance_handler), - "vkCreateInstance"); - -#if !defined(NDEBUG) || defined(_DEBUG) || defined(DEBUG) - // This needs to be created after the VkInstance is or else it wont - // be applied the debug information during validation layer error - // message execution - m_vk_set_debug_utils_object_name_ext = - reinterpret_cast( - vkGetInstanceProcAddr(m_instance_handler, - "vkSetDebugUtilsObjectNameEXT")); -#endif - - m_physical = physical_device(m_instance_handler); - m_device = device(m_physical); - - s_instance = this; - } - - ~instance_context() override { - vkDestroyInstance(m_instance_handler, nullptr); - } - - /** - * @brief returns function pointer to allow for setting debug object - * name - * - * - * This allows for utilizing vkSetDebugUtilsObjectNameEXT during debug - * builds - * - * This allows for setting up object names that is useful to the - * programmer when a validation layer error message occurs unexpectedly - * - */ - static PFN_vkSetDebugUtilsObjectNameEXT get_debug_object_name() { - return s_instance->m_vk_set_debug_utils_object_name_ext; - } - - /** - * @brief used for providing a way to submit all vulkan metaobjects - * before the destruction of the vulkan logical device - * - * Per vulkan specification, it is required to have all object handles - * created with the logical device to be destroyed before the logical - * device itself gets destroyed during post cleanup - * - * This function was a means to ensure that the destruction of those - * vulkan child objects are handled in that order correctly - */ - static void submit_resource_free(std::function&& p_resource) { - s_instance->m_resources_free.push_back(p_resource); - } - - static physical_device physical_driver() { - return s_instance->m_physical; - } - - static device logical_device() { return s_instance->m_device; } - - protected: - [[nodiscard]] VkInstance context_handle() const override { - return m_instance_handler; - } - - void context_submit_resource_free( - const std::function& p_resource) override { - m_resources_free.push_back(p_resource); - } - - void destroy_context() override { - console_log_info("destroy_context!"); - for (auto& callback : m_resources_free) { - callback(); - } - - m_device.destroy(); - } - - private: - private: - static instance_context* s_instance; - VkInstance m_instance_handler = nullptr; - std::deque> m_resources_free{}; - PFN_vkSetDebugUtilsObjectNameEXT m_vk_set_debug_utils_object_name_ext; - physical_device m_physical; - device m_device; - }; - - instance_context* instance_context::s_instance = nullptr; -}; diff --git a/atlas/drivers/vulkan/mesh copy.cppm b/atlas/drivers/vulkan/mesh copy.cppm deleted file mode 100644 index b23079d1..00000000 --- a/atlas/drivers/vulkan/mesh copy.cppm +++ /dev/null @@ -1,307 +0,0 @@ -module; - -#include -#include -#define STB_IMAGE_IMPLEMENTATION -#define STB_IMAGE_WRITE_IMPLEMENTATION -#include -#include -#include -#include -#include - -export module atlas.drivers.vulkan.mesh; -import vk; - -import atlas.logger; -import atlas.drivers.vulkan.instance_context; -import atlas.drivers.vulkan.physical_device; -import atlas.drivers.vulkan.device; -import atlas.drivers.vulkan.hash; -import atlas.drivers.vulkan.stb_image; - -export namespace atlas::vulkan { - /** - * @brief mesh class specifically defined with vulkan implementations for - * specific primitives - * - * @brief mesh class will contain metadata needed by vulkan specifications - * Ways to communicate through vulkan by only supplying information needed - * to update this mesh - * - * @brief Represents a renderable object -- supporting various material - * types, etc - * TODO - For now we have a map, this should - * be expanded to a proper material system for blending various materials - */ - class mesh { - public: - mesh() = default; - mesh(std::span p_vertices, - std::span p_indices) { - m_physical = instance_context::physical_driver(); - m_device = instance_context::logical_device(); - //! @brief Creating vertex/index buffers with host visibility flags - const auto property_flags = static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit); - - vk::buffer_parameters vertex_params = { - .memory_mask = m_physical.memory_properties(property_flags), - .property_flags = vk::memory_property::device_local_bit, - .usage = vk::buffer_usage::transfer_dst_bit | - vk::buffer_usage::vertex_buffer_bit, - }; - - vk::buffer_parameters index_params = { - .memory_mask = m_physical.memory_properties(property_flags), - .property_flags = static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::index_buffer_bit, - }; - - m_vbo = vk::vertex_buffer(m_device, p_vertices, vertex_params); - m_ibo = vk::index_buffer(m_device, p_indices, index_params); - } - - mesh(const std::filesystem::path& p_filename, bool p_flip = false) - : m_flip(p_flip) { - m_physical = instance_context::physical_driver(); - m_device = instance_context::logical_device(); - reload_mesh(m_physical, p_filename); - } - - //! @brief Reload mesh vertices and indices when requested - void reload_mesh(const vk::physical_device& p_physical, const std::filesystem::path& p_filename) { - load_obj(p_filename); - } - - // void draw(const VkCommandBuffer& p_command_buffer) { - // m_vbo.bind(p_command_buffer); - // if (m_ibo.size() > 0) { - // m_ibo.bind(p_command_buffer); - // vkCmdDrawIndexed(p_command_buffer, m_ibo.size(), 1, 0, 0, 0); - // } - // else { - // vkCmdDraw(p_command_buffer, m_vbo.size(), 1, 0, 0); - // } - // } - - [[nodiscard]] VkBuffer vertex_handle() const { - return m_vbo; - } - - [[nodiscard]] VkBuffer index_handle() const { - return m_ibo; - } - - void destroy() { - m_vbo.destruct(); - m_ibo.destruct(); - - m_diffuse.destruct(); - m_specular.destruct(); - m_geoemtry_ubo.destruct(); - m_material_ubo.destruct(); - } - - [[nodiscard]] bool has_indices() const { - return m_has_indices; - } - - //! @brief Loading single texture with specified std::filesystem::path - void add_diffuse(const std::filesystem::path& p_path) { - vk::texture_params config_texture = { - .memory_mask = m_physical.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - }; - - vk::stb_image image(p_path.string(), config_texture); - m_diffuse = ::vk::texture(m_device, &image, config_texture); - - if (!m_diffuse.loaded()) { - console_log_info("Diffuse Texture {} is NOT loaded!!!", - p_path.string()); - return; - } - } - - void add_specular(const std::filesystem::path& p_path) { - vk::texture_params config_texture = { - .memory_mask = m_physical_device.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - }; - - vk::stb_image image(p_path.string()); - m_specular = vk::texture(m_device, &image, config_texture); - - if (!m_specular.loaded()) { - console_log_error("Specular Texture {} is NOT loaded!!!", - p_path.string()); - return; - } - } - - [[nodiscard]] ::vk::sample_image diffuse() const { - return m_diffuse.image(); - } - [[nodiscard]] ::vk::sample_image specular() const { - return m_specular.image(); - } - - //! @return true if mesh geometry model loaded succesfully - [[nodiscard]] bool loaded() const { return m_model_loaded; } - - [[nodiscard]] bool diffuse_loaded() const { return m_diffuse.loaded(); } - - [[nodiscard]] bool specular_loaded() const { - return m_specular.loaded(); - } - - void set_flip(bool p_flip) { m_flip = p_flip; } - - private: - void load_obj(const std::filesystem::path& p_filename) { - tinyobj::attrib_t attrib; - std::vector shapes; - std::vector materials; - std::string warn, err; - - //! @note If we return the constructor then we can check if the mesh - //! loaded successfully - //! @note We also receive hints if the loading is successful! - //! @note Return default constructor automatically returns false - //! means that mesh will return the boolean as false because it - //! wasnt successful - if (!tinyobj::LoadObj(&attrib, - &shapes, - &materials, - &warn, - &err, - p_filename.string().c_str())) { - console_log_warn("Could not load model from path {}", - p_filename.string()); - m_model_loaded = false; - return; - } - - std::vector vertices; - std::vector indices; - std::unordered_map unique_vertices{}; - - // for (const auto& shape : shapes) { - for (size_t i = 0; i < shapes.size(); i++) { - auto shape = shapes[i]; - // for (const auto& index : shape.mesh.indices) { - for (size_t j = 0; j < shape.mesh.indices.size(); j++) { - auto index = shape.mesh.indices[j]; - vk::vertex_input vertex{}; - - if (!unique_vertices.contains(vertex)) { - unique_vertices[vertex] = - static_cast(vertices.size()); - vertices.push_back(vertex); - } - - if (index.vertex_index >= 0) { - vertex.position = { - attrib.vertices[3 * index.vertex_index + 0], - attrib.vertices[3 * index.vertex_index + 1], - attrib.vertices[3 * index.vertex_index + 2] - }; - - vertex.color = { - attrib.colors[3 * index.vertex_index + 0], - attrib.colors[3 * index.vertex_index + 1], - attrib.colors[3 * index.vertex_index + 2] - }; - } - - if (!attrib.normals.empty()) { - vertex.normals = { - attrib.normals[3 * index.normal_index + 0], - attrib.normals[3 * index.normal_index + 1], - attrib.normals[3 * index.normal_index + 2] - }; - } - if (!attrib.texcoords.empty()) { - glm::vec2 flipped_uv = { - attrib.texcoords[static_cast( - index.texcoord_index) * - 2], - 1.0f - attrib.texcoords[static_cast( - index.texcoord_index) * - 2 + - 1], - }; - - glm::vec2 original_uv = { - attrib.texcoords[static_cast( - index.texcoord_index) * - 2], - attrib.texcoords[static_cast( - index.texcoord_index) * - 2 + - 1], - }; - - vertex.uv = m_flip ? flipped_uv : original_uv; - } - else { - vertex.uv = glm::vec2(0.f, 0.f); - } - - if (!unique_vertices.contains(vertex)) { - unique_vertices[vertex] = - static_cast(vertices.size()); - vertices.push_back(vertex); - } - - indices.push_back(unique_vertices[vertex]); - } - } - - //! @brief Creating vertex/index buffers with host visibility flags - const auto property_flags = static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit); - - vk::buffer_parameters vertex_params = { - .memory_mask = p_physical.memory_properties(property_flags), - .property_flags = vk::memory_property::device_local_bit, - .usage = vk::buffer_usage::transfer_dst_bit | - vk::buffer_usage::vertex_buffer_bit, - }; - - vk::buffer_parameters index_params = { - .memory_mask = p_physical.memory_properties(property_flags), - .property_flags = static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::index_buffer_bit, - }; - m_vbo = ::vk::vertex_buffer(m_device, vertices, vertex_params); - m_ibo = ::vk::index_buffer(m_device, indices, index_params); - m_model_loaded = true; - - m_has_indices = (indices.size() > 0); - } - - private: - physical_device m_physical; - VkDevice m_device = nullptr; - vk::texture m_diffuse; - vk::texture m_specular; - vk::vertex_buffer m_vbo{}; - vk::index_buffer m_ibo{}; - vk::uniform_buffer m_geoemtry_ubo; - vk::uniform_buffer m_material_ubo; - bool m_model_loaded = false; - bool m_flip = false; - - bool m_has_indices = 0; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/mesh.cppm b/atlas/drivers/vulkan/mesh.cppm index 143f54df..82eb25a7 100644 --- a/atlas/drivers/vulkan/mesh.cppm +++ b/atlas/drivers/vulkan/mesh.cppm @@ -13,11 +13,11 @@ module; export module atlas.drivers.vulkan.mesh; import vk; -import atlas.logger; -import atlas.drivers.vulkan.instance_context; +import atlas.logger;\ import atlas.drivers.vulkan.physical_device; import atlas.drivers.vulkan.device; import atlas.drivers.vulkan.hash; +import atlas.drivers.vulkan.stb_image; export namespace atlas::vulkan { /** @@ -39,22 +39,40 @@ export namespace atlas::vulkan { mesh(const VkDevice& p_device, std::span p_vertices, std::span p_indices, - VkPhysicalDeviceMemoryProperties p_memory_properties) + uint32_t p_memory_properties) : m_device(p_device) { - // m_physical = instance_context::physical_driver(); - // m_device = instance_context::logical_device(); m_memory_properties = p_memory_properties; - vk::vertex_params vbo_settings = { - .phsyical_memory_properties = m_memory_properties, - .vertices = p_vertices, + // vk::vertex_params vbo_settings = { + // .phsyical_memory_properties = m_memory_properties, + // .vertices = p_vertices, + // }; + // vk::index_params ibo_settings = { + // .phsyical_memory_properties = m_memory_properties, + // .indices = p_indices, + // }; + // const auto property_flags = static_cast( + // vk::memory_property::host_visible_bit | + // vk::memory_property::host_cached_bit); + + vk::buffer_parameters vertex_params = { + // .memory_mask = p_physical.memory_properties(property_flags), + .memory_mask = p_memory_properties, + .property_flags = vk::memory_property::device_local_bit, + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; - vk::index_params ibo_settings = { - .phsyical_memory_properties = m_memory_properties, - .indices = p_indices, + + vk::buffer_parameters index_params = { + // .memory_mask = p_physical.memory_properties(property_flags), + .memory_mask = p_memory_properties, + .property_flags = static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::index_buffer_bit, }; - m_vbo = vk::vertex_buffer(m_device, vbo_settings); - m_ibo = vk::index_buffer(m_device, ibo_settings); + m_vbo = vk::vertex_buffer(m_device, p_vertices, vertex_params); + m_ibo = vk::index_buffer(m_device, p_indices, index_params); // m_vertices_size = p_vertices.size(); m_vertices_size = static_cast(p_vertices.size()); @@ -63,7 +81,7 @@ export namespace atlas::vulkan { } mesh(const VkDevice& p_device, - VkPhysicalDeviceMemoryProperties p_memory_properties, + uint32_t p_memory_properties, const std::filesystem::path& p_filename, bool p_flip = false) : m_device(p_device) @@ -81,27 +99,28 @@ export namespace atlas::vulkan { [[nodiscard]] VkBuffer index_handle() const { return m_ibo; } - [[nodiscard]] uint32_t vertices_size() const { return m_vbo.size(); } + [[nodiscard]] uint32_t vertices_size() const { return m_vertices_size; } - [[nodiscard]] uint32_t indices_size() const { return m_ibo.size(); } + [[nodiscard]] uint32_t indices_size() const { return m_indices_size; } void destroy() { - m_vbo.destroy(); - m_ibo.destroy(); + m_vbo.destruct(); + m_ibo.destruct(); - m_diffuse.destroy(); - m_specular.destroy(); - m_geoemtry_ubo.destroy(); - m_material_ubo.destroy(); + m_diffuse.destruct(); + m_specular.destruct(); + m_geoemtry_ubo.destruct(); + m_material_ubo.destruct(); } //! @brief Loading single texture with specified std::filesystem::path void add_diffuse(const std::filesystem::path& p_path) { - ::vk::texture_info config_texture = { - .phsyical_memory_properties = m_memory_properties, - .filepath = p_path, + vk::texture_params config_texture = { + .memory_mask = m_memory_properties, }; - m_diffuse = ::vk::texture(m_device, config_texture); + + atlas::vulkan::stb_image diffuse(p_path.string(), config_texture); + m_diffuse = ::vk::texture(m_device, &diffuse, config_texture); if (!m_diffuse.loaded()) { console_log_info("Diffuse Texture {} is NOT loaded!!!", @@ -111,11 +130,11 @@ export namespace atlas::vulkan { } void add_specular(const std::filesystem::path& p_path) { - vk::texture_info config_texture = { - .phsyical_memory_properties = m_memory_properties, - .filepath = p_path, + vk::texture_params config_texture = { + .memory_mask = m_memory_properties, }; - m_specular = vk::texture(m_device, config_texture); + atlas::vulkan::stb_image specular(p_path.string(), config_texture); + m_specular = vk::texture(m_device, &specular, config_texture); if (!m_specular.loaded()) { console_log_error("Specular Texture {} is NOT loaded!!!", @@ -131,16 +150,16 @@ export namespace atlas::vulkan { return m_specular.image(); } - void draw(const VkCommandBuffer& p_command_buffer) { - m_vbo.bind(p_command_buffer); - if (m_ibo.size() > 0) { - m_ibo.bind(p_command_buffer); - vkCmdDrawIndexed(p_command_buffer, m_ibo.size(), 1, 0, 0, 0); - } - else { - vkCmdDraw(p_command_buffer, m_vbo.size(), 1, 0, 0); - } - } + // void draw(const VkCommandBuffer& p_command_buffer) { + // m_vbo.bind(p_command_buffer); + // if (m_ibo.size() > 0) { + // m_ibo.bind(p_command_buffer); + // vkCmdDrawIndexed(p_command_buffer, m_ibo.size(), 1, 0, 0, 0); + // } + // else { + // vkCmdDraw(p_command_buffer, m_vbo.size(), 1, 0, 0); + // } + // } //! @return true if mesh geometry model loaded succesfully [[nodiscard]] bool loaded() const { return m_model_loaded; } @@ -254,14 +273,29 @@ export namespace atlas::vulkan { } } - ::vk::vertex_params vbo_settings = { .phsyical_memory_properties = - m_memory_properties, - .vertices = vertices }; - ::vk::index_params ibo_settings = { .phsyical_memory_properties = - m_memory_properties, - .indices = indices }; - m_vbo = ::vk::vertex_buffer(m_device, vbo_settings); - m_ibo = ::vk::index_buffer(m_device, ibo_settings); + vk::buffer_parameters vertex_params = { + .memory_mask = m_memory_properties, + .property_flags = vk::memory_property::device_local_bit, + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, + }; + + vk::buffer_parameters index_params = { + .memory_mask = m_memory_properties, + .property_flags = static_cast( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::index_buffer_bit, + }; + + // ::vk::vertex_params vbo_settings = { .phsyical_memory_properties = + // m_memory_properties, + // .vertices = vertices }; + // ::vk::index_params ibo_settings = { .phsyical_memory_properties = + // m_memory_properties, + // .indices = indices }; + m_vbo = ::vk::vertex_buffer(m_device, vertices, vertex_params); + m_ibo = ::vk::index_buffer(m_device, indices, index_params); m_vertices_size = vertices.size(); m_indices_size = indices.size(); @@ -269,7 +303,7 @@ export namespace atlas::vulkan { } private: - VkPhysicalDeviceMemoryProperties m_memory_properties{}; + uint32_t m_memory_properties=0; VkDevice m_device = nullptr; vk::texture m_diffuse; vk::texture m_specular; diff --git a/atlas/drivers/vulkan/physical_device.cppm b/atlas/drivers/vulkan/physical_device.cppm index 6858337b..995b521f 100644 --- a/atlas/drivers/vulkan/physical_device.cppm +++ b/atlas/drivers/vulkan/physical_device.cppm @@ -58,6 +58,8 @@ export namespace atlas::vulkan { uint32_t device_count = 0; vkEnumeratePhysicalDevices(p_instance, &device_count, nullptr); + console_log_info("physical_device after enumerations!"); + if (device_count == 0) { console_log_fatal("Device Count is {} and no devices found!!!", device_count); @@ -125,11 +127,8 @@ export namespace atlas::vulkan { return physical_memory_properties; } - /* [[nodiscard]] uint32_t memory_properties( vk::memory_property p_property_required) { - vk::allocation_params return_params = {}; - VkPhysicalDeviceMemoryProperties memory_properties; vkGetPhysicalDeviceMemoryProperties(m_physical_driver, &memory_properties); @@ -145,7 +144,6 @@ export namespace atlas::vulkan { } return mask; } - */ /** * @return uint32_t is the index to the presentation index of the diff --git a/atlas/drivers/vulkan/render_system.cppm b/atlas/drivers/vulkan/render_system.cppm index b6b36495..64264bff 100644 --- a/atlas/drivers/vulkan/render_system.cppm +++ b/atlas/drivers/vulkan/render_system.cppm @@ -8,6 +8,7 @@ module; #include #include #include +#include #include @@ -18,7 +19,6 @@ import atlas.core.utilities; import vk; import atlas.core.scene; import atlas.drivers.graphics_context; -import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.physical_device; import atlas.drivers.vulkan.device; import atlas.drivers.vulkan.mesh; @@ -57,6 +57,7 @@ export namespace atlas::vulkan { * * Idea is the std::string is the geometries within this scene, the * data format is: > */ + /* class render_system : public renderer_system { public: render_system(ref p_context, @@ -143,7 +144,7 @@ export namespace atlas::vulkan { std::vector set0_entries = { vk::descriptor_entry{ // specifies "layout (set = 0, binding = 0) uniform GlobalUbo" - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = { .binding = 0, .stage = vk::shader_stage::vertex, @@ -152,7 +153,7 @@ export namespace atlas::vulkan { }, vk::descriptor_entry{ // specifies "layout (set = 0, binding = 1) uniform light_ubo" - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = { .binding = 1, .stage = vk::shader_stage::fragment, @@ -170,29 +171,49 @@ export namespace atlas::vulkan { m_global_descriptors = vk::descriptor_resource(m_device, set0_layout); - vk::uniform_params global_info = { - .phsyical_memory_properties = m_physical.memory_properties(), - .size_bytes = sizeof(global_ubo), - .debug_name = "\nm_global_uniforms\n", - .vkSetDebugUtilsObjectNameEXT = - instance_context::get_debug_object_name() + // vk::uniform_params global_info = { + // .phsyical_memory_properties = m_physical.memory_properties(), + // .size_bytes = sizeof(global_ubo), + // .debug_name = "\nm_global_uniforms\n", + // .vkSetDebugUtilsObjectNameEXT = + // instance_context::get_debug_object_name() + // }; + vk::buffer_parameters global_uniforms = { + .memory_mask = m_physical.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | + vk::buffer_usage::shader_device_address_bit, + .allocate_flags = + vk::memory_allocate_flags::device_address_bit_khr, }; - m_global_uniforms = vk::uniform_buffer(m_device, global_info); + m_global_uniforms = + vk::uniform_buffer(m_device, sizeof(global_ubo), global_uniforms); // setting up our light uniforms as the global uniforms rather then // per-object basis - vk::uniform_params light_ubo_params = { - .phsyical_memory_properties = m_physical.memory_properties(), - .size_bytes = sizeof(light_scene_ubo), + // vk::uniform_params light_ubo_params = { + // .phsyical_memory_properties = m_physical.memory_properties(), + // .size_bytes = sizeof(light_scene_ubo), + // }; + vk::buffer_parameters light_ubo_params = { + .memory_mask = m_physical.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | + vk::buffer_usage::shader_device_address_bit, + .allocate_flags = + vk::memory_allocate_flags::device_address_bit_khr, }; - m_point_light_uniforms = - vk::uniform_buffer(m_device, light_ubo_params); + m_point_light_uniforms = vk::uniform_buffer( + m_device, sizeof(light_scene_ubo), light_ubo_params); std::array binding0_uniforms = { vk::write_buffer{ .buffer = m_global_uniforms, .offset = 0, - .range = m_global_uniforms.size_bytes(), + .range = + static_cast(m_global_uniforms.size_bytes()), }, }; @@ -200,7 +221,8 @@ export namespace atlas::vulkan { vk::write_buffer{ .buffer = m_point_light_uniforms, .offset = 0, - .range = m_point_light_uniforms.size_bytes(), + .range = + static_cast(m_point_light_uniforms.size_bytes()), }, }; @@ -224,16 +246,22 @@ export namespace atlas::vulkan { .width = 1, .height = 1, }; + std::array white_color = { 0xff, 0xff, 0xff, 0xff }; m_white_texture = - vk::texture(m_device, extent, m_physical.memory_properties()); + vk::texture(m_device, + extent, + white_color, + m_physical.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit)); p_context->submit_resource_free([this]() { console_log_info("vulkan::render_system destructin invoked!!"); - m_white_texture.destroy(); + m_white_texture.destruct(); m_shader_group.destroy(); - m_global_descriptors.destroy(); - m_global_uniforms.destroy(); - m_point_light_uniforms.destroy(); + m_global_descriptors.destruct(); + m_global_uniforms.destruct(); + m_point_light_uniforms.destruct(); for (auto& [id, mesh] : m_cached_meshes) { console_log_trace( "Entity \"{}\" Destroyed in vk_renderer!!!", id); @@ -241,21 +269,21 @@ export namespace atlas::vulkan { } for (auto& [id, uniform] : m_mesh_geometry_set) { - uniform.destroy(); + uniform.destruct(); } for (auto& [id, material_uniform] : m_mesh_material_set) { - material_uniform.destroy(); + material_uniform.destruct(); } for (auto& [key, descriptor_map] : m_mesh_descriptors) { for (auto& [descriptor_type, descriptor] : descriptor_map) { - descriptor.destroy(); + descriptor.destruct(); } } m_skybox.destroy(); - m_main_pipeline.destroy(); + m_main_pipeline.destruct(); }); console_log_info( @@ -283,8 +311,11 @@ export namespace atlas::vulkan { m_current_scene->get(); m_skybox = environment_map(m_device, + m_physical, std::filesystem::path(environment_data->filepath), - m_physical.memory_properties(), + m_physical.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), m_final_renderpass); flecs::query<> caching = @@ -292,31 +323,53 @@ export namespace atlas::vulkan { caching.each([this](flecs::entity p_entity) { const mesh_source* target = p_entity.get(); - mesh new_mesh(m_device, m_physical.memory_properties(), std::filesystem::path(target->model_path), + mesh new_mesh(m_device, + m_physical.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + std::filesystem::path(target->model_path), target->flip); // we do a check if the geometry uniform associated with this // game object is valid if (!m_mesh_geometry_set.contains(p_entity.id())) { - vk::uniform_params geo_info = { - .phsyical_memory_properties = - m_physical.memory_properties(), - .size_bytes = sizeof(material_uniform), + // vk::uniform_params geo_info = { + // .phsyical_memory_properties = + // m_physical.memory_properties(), + // .size_bytes = sizeof(material_uniform), + // }; + vk::buffer_parameters geo_params = { + .memory_mask = m_physical.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | + vk::buffer_usage::shader_device_address_bit, + // .allocate_flags = + // vk::memory_allocate_flags::device_address_bit_khr, }; - m_mesh_geometry_set[p_entity.id()] = - vk::uniform_buffer(m_device, geo_info); + m_mesh_geometry_set[p_entity.id()] = vk::uniform_buffer( + m_device, sizeof(material_uniform), geo_params); } // check if material is already associated with this particular // game object if (!m_mesh_material_set.contains(p_entity.id())) { - vk::uniform_params mat_info = { - .phsyical_memory_properties = - m_physical.memory_properties(), - .size_bytes = sizeof(material_metadata), + // vk::uniform_params mat_info = { + // .phsyical_memory_properties = + // m_physical.memory_properties(), + // .size_bytes = sizeof(material_metadata), + // }; + vk::buffer_parameters mat_params = { + .memory_mask = m_physical.memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | + vk::buffer_usage::shader_device_address_bit, + .allocate_flags = + vk::memory_allocate_flags::device_address_bit_khr, }; - m_mesh_material_set[p_entity.id()] = - vk::uniform_buffer(m_device, mat_info); + m_mesh_material_set[p_entity.id()] = vk::uniform_buffer( + m_device, sizeof(material_metadata), mat_params); } new_mesh.add_diffuse(std::filesystem::path(target->diffuse)); @@ -328,7 +381,7 @@ export namespace atlas::vulkan { std::vector set1_entries = { vk::descriptor_entry{ // specifies "layout (set = 1, binding = 0) uniform geometry_uniform" - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = { .binding = 0, .stage = vk::shader_stage::vertex, @@ -337,7 +390,7 @@ export namespace atlas::vulkan { }, vk::descriptor_entry{ // specifies "layout (set = 1, binding = 1) uniform sampler2D diffuse_texture" - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = { .binding = 1, .stage = vk::shader_stage::fragment, @@ -346,7 +399,7 @@ export namespace atlas::vulkan { }, vk::descriptor_entry{ // specifies "layout (set = 1, binding = 2) uniform sampler2D specular_texture" - .type = vk::buffer::combined_image_sampler, + .type = vk::descriptor_type::combined_image_sampler, .binding_point = { .binding = 2, .stage = vk::shader_stage::fragment, @@ -355,7 +408,7 @@ export namespace atlas::vulkan { }, vk::descriptor_entry{ // specifies "layout (set = 1, binding = 3) uniform sampler2D material_ubo" - .type = vk::buffer::uniform, + .type = vk::descriptor_type::uniform, .binding_point = { .binding = 3, .stage = vk::shader_stage::fragment, @@ -379,8 +432,8 @@ export namespace atlas::vulkan { vk::write_buffer{ .buffer = m_mesh_geometry_set[p_entity.id()], .offset = 0, - .range = - m_mesh_geometry_set[p_entity.id()].size_bytes(), + .range = static_cast( + m_mesh_geometry_set[p_entity.id()].size_bytes()), } }; @@ -388,8 +441,8 @@ export namespace atlas::vulkan { vk::write_buffer{ .buffer = m_mesh_material_set[p_entity.id()], .offset = 0, - .range = - m_mesh_material_set[p_entity.id()].size_bytes(), + .range = static_cast( + m_mesh_material_set[p_entity.id()].size_bytes()), } }; @@ -571,7 +624,9 @@ export namespace atlas::vulkan { // TODO: Make to_bytes be part of utilities. This can be useful in // sending the amount of bytes in batches for batch-rendering - m_global_uniforms.update(&global_frame_ubo); + // m_global_uniforms.update(&global_frame_ubo); + m_global_uniforms.transfer( + std::span(&global_frame_ubo, 1)); skybox_uniform skybox_ubo = { .proj_view = m_skybox_proj_view, @@ -606,7 +661,9 @@ export namespace atlas::vulkan { }); test_light.num_lights = index; - m_point_light_uniforms.update(&test_light); + // m_point_light_uniforms.update(&test_light); + m_point_light_uniforms.transfer( + std::span(&test_light, 1)); // query all objects with a specified 3d mesh source flecs::query<> query_targets = @@ -615,8 +672,17 @@ export namespace atlas::vulkan { m_main_pipeline.bind(m_current_command_buffer); // Bind global camera data here - m_global_descriptors.bind(m_current_command_buffer, - m_main_pipeline.layout()); + // m_global_descriptors.bind(m_current_command_buffer, + // m_main_pipeline.layout()); + std::array descriptors = { + m_global_descriptors, + }; + + m_current_command_buffer.bind_descriptors( + m_main_pipeline.layout(), + VK_PIPELINE_BIND_POINT_GRAPHICS, + descriptors); + query_targets.each([this](flecs::entity p_entity) { const transform* transform_component = p_entity.get(); @@ -637,57 +703,80 @@ export namespace atlas::vulkan { material_component->color }; if (m_cached_meshes[p_entity.id()].loaded()) { - m_mesh_geometry_set[p_entity.id()].update(&mesh_ubo); + // m_mesh_geometry_set[p_entity.id()].update(&mesh_ubo); + m_mesh_geometry_set[p_entity.id()].transfer(std::span(&mesh_ubo, 1)); material_metadata data = {}; if (p_entity.has()) { data = *p_entity.get(); } - m_mesh_material_set[p_entity.id()].update(&data); + // m_mesh_material_set[p_entity.id()].update(&data); + m_mesh_material_set[p_entity.id()].transfer(std::span(&data, 1)); + + + // m_mesh_descriptors[p_entity.id()]["materials"].bind( + // m_current_command_buffer, m_main_pipeline.layout()); + + // descriptors.push_back(m_mesh_descriptors[p_entity.id()]["materials"]); + const VkDescriptorSet descriptors = m_mesh_descriptors[p_entity.id()]["materials"]; + m_current_command_buffer.bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&descriptors, 1)); - m_mesh_descriptors[p_entity.id()]["materials"].bind( - m_current_command_buffer, m_main_pipeline.layout()); // m_cached_meshes[p_entity.id()].draw( // m_current_command_buffer); // binding/draw calls - const VkBuffer vertex = m_cached_meshes[p_entity.id()].vertex_handle(); - const VkBuffer index = m_cached_meshes[p_entity.id()].index_handle(); - - std::array handler = {vertex}; - std::array offsets = {0}; + const VkBuffer vertex = + m_cached_meshes[p_entity.id()].vertex_handle(); + const VkBuffer index = + m_cached_meshes[p_entity.id()].index_handle(); + + std::array handler = { vertex }; + std::array offsets = { 0 }; vkCmdBindVertexBuffers(m_current_command_buffer, - 0, - 1, - handler.data(), - offsets.data()); + 0, + 1, + handler.data(), + offsets.data()); - if(m_cached_meshes[p_entity.id()].indices_size() != 0) { + if (m_cached_meshes[p_entity.id()].indices_size() != 0) { vkCmdBindIndexBuffer(m_current_command_buffer, - index, - 0, - VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed(m_current_command_buffer, static_cast(m_cached_meshes[p_entity.id()].indices_size()), 1, 0, 0, 0); + index, + 0, + VK_INDEX_TYPE_UINT32); + vkCmdDrawIndexed( + m_current_command_buffer, + static_cast( + m_cached_meshes[p_entity.id()].indices_size()), + 1, + 0, + 0, + 0); } else { - vkCmdDraw(m_current_command_buffer, m_cached_meshes[p_entity.id()].vertices_size(), 1, 0, 0); + vkCmdDraw( + m_current_command_buffer, + m_cached_meshes[p_entity.id()].vertices_size(), + 1, + 0, + 0); } } }); - std::array offsets = {0}; - vkCmdBindPipeline(m_current_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_skybox.pipeline()); - m_skybox.descriptor_bind(m_current_command_buffer, m_skybox.pipeline_layout()); + std::array offsets = { 0 }; + vkCmdBindPipeline(m_current_command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + m_skybox.pipeline()); + m_skybox.descriptor_bind(m_current_command_buffer, + m_skybox.pipeline_layout()); const VkBuffer skybox_vertex = m_skybox.vertex_handle(); - vkCmdBindVertexBuffers(m_current_command_buffer, - 0, - 1, - &skybox_vertex, - offsets.data()); - vkCmdDraw(m_current_command_buffer, m_skybox.vertices_size(), 1, 0, 0); + vkCmdBindVertexBuffers( + m_current_command_buffer, 0, 1, &skybox_vertex, offsets.data()); + vkCmdDraw( + m_current_command_buffer, m_skybox.vertices_size(), 1, 0, 0); vkCmdEndRenderPass(m_current_command_buffer); @@ -742,4 +831,5 @@ export namespace atlas::vulkan { ref m_current_scene; }; -}; + */ +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/shader_resource_group copy.cppm b/atlas/drivers/vulkan/shader_resource_group copy.cppm deleted file mode 100644 index 1c78e7f7..00000000 --- a/atlas/drivers/vulkan/shader_resource_group copy.cppm +++ /dev/null @@ -1,443 +0,0 @@ -module; - -#include -#include -#include -#include -#include - -export module atlas.drivers.vulkan.shader_resource_group; - -import atlas.logger; -import vk; - -namespace atlas::vulkan { - // Reading the raw .spv binaries - static std::vector read_raw_spirv(const std::string& p_file) { - std::vector out_buffer; - std::ifstream ins(p_file, std::ios::ate | std::ios::binary); - - if (!ins) { - throw std::runtime_error("Cannot load in .spv files!!"); - } - - uint32_t file_size = (uint32_t)ins.tellg(); - out_buffer.resize(file_size); - ins.seekg(0); - ins.read(out_buffer.data(), file_size); - return out_buffer; - } - - //! @brief Ensure file reads are valid before reading raw .spv binaries - static std::vector compile_binary_shader_source( - const ::vk::shader_source& p_shader_source) { - - if (!std::filesystem::is_regular_file(p_shader_source.filename)) { - throw std::runtime_error("Cannot load .spv file"); - } - - return read_raw_spirv(p_shader_source.filename); - } - -#if ENABLE_SHADERC - static std::string read_shader_source_code(const std::string& p_filename) { - std::ifstream ins(p_filename, std::ios::ate | std::ios::binary); - - if (!ins.is_open()) { - console_log_warn("Could not open filename = {}", p_filename); - return { 'a' }; - } - - size_t file_size = (size_t)ins.tellg(); - std::string output; - output.resize(file_size); - ins.seekg(0); - ins.read(output.data(), static_cast(file_size)); - - return output; - } -#endif - - /** - * compiles source code from the shader directly without needing manual - * recompilation - * - * shaderc requires these parameters to compile - * text_source_code: the std::string version of the entire source code to - * compile type: shader stage this shader corresponds to filename: input - * filename text entry_point: the entry point to this shader options: - * compiler-specific options to enable when compiling the shader sources - */ -#if ENABLE_SHADERC - static std::vector compile_source_from_file( - const ::vk::shader_source& p_shader_source) { - shaderc::CompileOptions options; - options.SetTargetEnvironment(shaderc_target_env_vulkan, - shaderc_env_version_vulkan_1_3); - options.SetWarningsAsErrors(); - - shaderc_shader_kind type; - - switch (p_shader_source.stage) { - case ::vk::shader_stage::vertex: - type = shaderc_glsl_vertex_shader; - break; - case ::vk::shader_stage::fragment: - type = shaderc_glsl_fragment_shader; - break; - default: - throw std::runtime_error("shader_stage unspecified!~!!"); - } - - shaderc::Compiler compiler; - std::string text_source_code = - read_shader_source_code(p_shader_source.filename); - - // Prints out the text of the shader source code - // console_log_warn("Source Text Code!!!"); - // console_log_info("{}", text_source_code); - shaderc::CompilationResult result = - compiler.CompileGlslToSpv(text_source_code, - type, - p_shader_source.filename.c_str(), - "main", - options); - - std::vector blob; - - if (result.GetCompilationStatus() != - shaderc_compilation_status_success) { - throw std::runtime_error( - std::format("Shader Compilation Error! Failed with reason {}\n{}", - p_shader_source.filename, - result.GetErrorMessage()) - .c_str()); - } - - for (auto blob_chunk : result) { - blob.push_back(blob_chunk); - } - - return blob; - } -#endif - /** - * @brief resource group for loading shader sources that give you back - * VkShaderModule handles - * - * Responsibility is to load stages of shader sources whether that be - * through precompiler .spv files or through shaderc runtime shader - * compilation - * - * Responsibility is loading and streaming the amount of bytes from the - * compiled shader sources into the vulkan shader module handles - * - * resource groups up the creation and management of vulkan shader modules. - */ - export class shader_resource_group { - public: - shader_resource_group() = default; - /** - * @brief constructs a new shader_resource_group - * - * @param p_device is the logical device required to creating the vulkan - * shader module - * @param p_info has the properties such as specified shader sources to - * load/compile - */ - shader_resource_group(const VkDevice& p_device, - const ::vk::shader_resource_info& p_info) - : m_device(p_device) { - - // We go through all of the specified shader source and their - // specific stage Compile them through shader compiler or if - // provided a .spv, then we compile and read in the stream of bytes - // directly - for (size_t i = 0; i < p_info.sources.size(); i++) { - const vk::shader_source shader_src = p_info.sources[i]; - std::filesystem::path filepath = - std::filesystem::path(shader_src.filename); -#ifndef ENABLE_SHADERC - if (filepath.extension().string() == ".spv") { - std::vector blob = - compile_binary_shader_source(shader_src); - - if (blob.empty()) { - m_resource_valid = false; - throw std::runtime_error( - "Cannot load in vector " - "blob of compiled down data!!!"); - } - - create_module(blob, shader_src); - } -#endif - -#ifdef ENABLE_SHADERC - if (filepath.extension().string() != ".spv") { - std::string text_source_code = - read_shader_source_code(filepath.string()); - std::vector blob = - compile_source_from_file(shader_src); - create_module(blob, shader_src); - } -#endif - } - } - - ~shader_resource_group() = default; - - /** - * @return true if resources are valid, otherwise return false - */ - [[nodiscard]] bool valid() const { return m_resource_valid; } - - /** - * @brief sets the vertex attributes with the shader modules that gets - * used by ::vk::pipeline (graphics pipeline) - * - * @param p_attributes is the high-level specifications for setting up - * vertex attributes that correspond with these shaders - */ - void vertex_attributes( - std::span p_attributes) { - /* - -- These comments are a reminder to myself -- - - this function simplifies the need to separately define vertex - attributes and the vertex binding attributes as shown below: - - - vertex attributes specify the types of data within the vertex - - - vertex binding attribute specifies the rate of reading that - data layout specified by the vertex attributes - - - Interpret the following vertex attributes below with this - shader code with `layout(location = n)` specified where by default - these are set to binding zero by the shader - - layout(location = 0) in vec3 inPosition; - layout(location = 1) in vec3 inColor; - layout(location = 2) in vec3 inNormals; - layout(location = 3) in vec2 inTexCoords; - - m_shader_group.set_vertex_attributes(VkVertexInputAttributeDescription{ - { .location = 0, .binding = 0, .format = - VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, - position), - }, { .location = 1, .binding = 0, .format = - VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, color), - }, { .location = 2, .binding = 0, .format = - VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, normals), - }, { .location = 3, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, - .offset = offsetof(vk::vertex, uv), }, - }); - - m_shader_group.set_vertex_bind_attributes(VkVertexInputBindingDescription{ - {.binding = 0, .stride = sizeof(vk::vertex), .inputRate = - VK_VERTEX_INPUT_RATE_VERTEX,}, - }); - - Which gets handled in specifying the following below - */ - - m_vertex_binding_attributes.resize(p_attributes.size()); - - for (size_t i = 0; i < m_vertex_binding_attributes.size(); i++) { - // setting up vertex binding - const ::vk::vertex_attribute attribute = p_attributes[i]; - m_vertex_attributes.resize(attribute.entries.size()); - m_vertex_binding_attributes[i] = { - .binding = attribute.binding, - .stride = attribute.stride, - .inputRate = static_cast(attribute.input_rate), - }; - - // then setting up the vertex attributes for the vertex data - // layouts - for (size_t j = 0; j < attribute.entries.size(); j++) { - const ::vk::vertex_attribute_entry entry = - attribute.entries[j]; - m_vertex_attributes[j] = { .location = entry.location, - .binding = attribute.binding, - .format = static_cast( - entry.format), - .offset = entry.stride }; - } - } - } - - /** - * @brief this gives you back the shader module handles along with each - * of their stages they have been compiled with - * - * Returns the vector to retain the shader modules that are needed by - * the graphics pipeline. - * - * It is required by vulkan specs the graphics pipeline to contain valid - * shader modules of the compiled shaders - * - * @return vector<::vk::shader_handle> - */ - [[nodiscard]] std::vector<::vk::shader_handle> handles() const { - return map_to_vector(); - } - - /** - * @return span - */ - [[nodiscard]] std::span - vertex_attributes() const { - return m_vertex_attributes; - } - - /** - * @return span - */ - [[nodiscard]] std::span - vertex_bind_attributes() const { - return m_vertex_binding_attributes; - } - - /** - * @brief explicit cleanup to the VkShaderModule handles created with - * this particular resource group - */ - void destroy() { - for (auto& [filename, shader_handle] : m_modules) { - if (shader_handle.module != nullptr) { - vkDestroyShaderModule( - m_device, shader_handle.module, nullptr); - } - } - } - - /** - * @brief ideally used for requesting for reload - * - * Planning to use this for invalidation when for runtime shader - * hot-reloading - * - * @note this is not used at the moment as shader runtime hot reloading - * is currently not supported. - */ - [[nodiscard]] bool reload_requested() const { - return m_reload_requested; - } - - private: - /** - * converts unordered_map to - * vector - */ - [[nodiscard]] std::vector<::vk::shader_handle> map_to_vector() const { - // Using C++'s std::views to extract all of the values in - // unordered_map to a - // vector that gets passed to graphics pipeline TEMP: - // Removing this. Will add this back in later. return (m_modules | - // std::views::values | - // std::ranges::to()); - std::vector<::vk::shader_handle> result; - - result.reserve(m_modules.size()); - - for (auto const& [name, handle] : m_modules) { - result.push_back(handle); - } - - return result; - } - - void create_module(std::span p_blob, - const ::vk::shader_source& p_source) { - VkShaderModuleCreateInfo shader_module_ci = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .codeSize = p_blob.size(), - .pCode = reinterpret_cast(p_blob.data()) - }; - - std::filesystem::path filepath(p_source.filename); - std::string filename = filepath.filename().string(); - - // Setting m_shader_module_handlers[i]'s stage and the - // VkShaderModule handle altogether construct this beforehand and - // then we are going set that shader module - m_modules.emplace(filename, ::vk::shader_handle{}); - ::vk::vk_check(vkCreateShaderModule(m_device, - &shader_module_ci, - nullptr, - &m_modules[filename].module), - "vkCreateShaderModule"); - m_modules[filename].stage = p_source.stage; - } - - void create_module(std::span p_blob, - const ::vk::shader_source& p_source) { - VkShaderModuleCreateInfo shader_module_ci = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .codeSize = p_blob.size_bytes(), - .pCode = p_blob.data() - }; - - // console_log_info("map key = {}", p_source.filename); - std::filesystem::path filepath(p_source.filename); - - std::string filename = filepath.filename().string(); - - console_log_info("Key = {}", filename); - - // Setting m_shader_module_handlers[i]'s stage and the - // VkShaderModule handle altogether construct this beforehand and - // then we are going set that shader module - m_modules.emplace(filename, ::vk::shader_handle{}); - ::vk::vk_check(vkCreateShaderModule(m_device, - &shader_module_ci, - nullptr, - &m_modules[filename].module), - "vkCreateShaderModule"); - m_modules[filename].stage = p_source.stage; - } - - /* - // TODO: Re-add this when shaderc works again. - void reload_shader(const ::vk::shader_source& p_source) { - console_log_info("p_source.filename = {}", p_source.filename); - if (m_modules[p_source.filename].module != nullptr) { - vkDestroyShaderModule( - m_device, m_modules[p_source.filename].module, nullptr); - } - - auto& handle = m_modules[p_source.filename]; - - std::filesystem::path filepath(p_source.filename); - std::string text_source_code = - read_shader_source_code(filepath.string()); - std::vector blob = compile_source_from_file(p_source); - std::span view_blob(blob.data(), blob.size()); - // create_module(blob, p_source); - VkShaderModuleCreateInfo shader_module_ci = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .codeSize = view_blob.size_bytes(), - .pCode = view_blob.data() - }; - - ::vk::vk_check(vkCreateShaderModule( - m_device, &shader_module_ci, nullptr, - &handle.module), "vkCreateShaderModule"); - } - */ - - private: - VkDevice m_device = nullptr; - std::vector m_vertex_attributes; - std::vector - m_vertex_binding_attributes; - bool m_resource_valid = false; - // shader module handles - std::unordered_map m_modules; - // ref m_watcher; - bool m_reload_requested = false; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/shader_resource_group.cppm b/atlas/drivers/vulkan/shader_resource_group.cppm index 75b41916..f5c789f3 100644 --- a/atlas/drivers/vulkan/shader_resource_group.cppm +++ b/atlas/drivers/vulkan/shader_resource_group.cppm @@ -246,10 +246,12 @@ namespace atlas::vulkan { // setting up vertex binding const ::vk::vertex_attribute attribute = p_attributes[i]; m_vertex_attributes.resize(attribute.entries.size()); - m_vertex_binding_attributes[i] = { .binding = attribute.binding, - .stride = attribute.stride, - .inputRate = to_input_rate( - attribute.input_rate) }; + m_vertex_binding_attributes[i] = { + .binding = attribute.binding, + .stride = attribute.stride, + .inputRate = + static_cast(attribute.input_rate), + }; // then setting up the vertex attributes for the vertex data // layouts diff --git a/atlas/drivers/vulkan/stb_image.cppm b/atlas/drivers/vulkan/stb_image.cppm index cdf41145..f5f692fd 100644 --- a/atlas/drivers/vulkan/stb_image.cppm +++ b/atlas/drivers/vulkan/stb_image.cppm @@ -15,7 +15,7 @@ export module atlas.drivers.vulkan.stb_image; import vk; -export namespace vk { +export namespace atlas::vulkan { class stb_image : public vk::image { public: stb_image() = default; @@ -34,14 +34,14 @@ export namespace vk { int channels = 0; stbi_uc* image_pixel_data = - stbi_load(p_path.data(), &w, &h, &channels, STBI_rgb_alpha); + stbi_load(p_path.data(), &w, &h, &channels, STBI_rgb_alpha); if (!image_pixel_data) { return false; } const VkFormat texture_format = - static_cast(vk::format::r8g8b8a8_unorm); + static_cast(vk::format::r8g8b8a8_unorm); int bytes_per_pixel = vk::bytes_per_texture_format(texture_format); m_extent = { @@ -52,7 +52,7 @@ export namespace vk { // Retrieving total size of bytes of the dimensions of the image and // accounting for pixels of the image uint32_t size_bytes = - m_extent.width * m_extent.height * bytes_per_pixel; + m_extent.width * m_extent.height * bytes_per_pixel; // Retrieving total image size to the count of the image layers uint32_t size = size_bytes * p_params.layer_count; @@ -62,14 +62,14 @@ export namespace vk { // .format = texture_format, // .memory_mask = p_params.memory_mask, // .usage = - // vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, - // .mip_levels = p_params.mip_levels, - // .layer_count = p_params.layer_count, + // vk::image_usage::transfer_dst_bit | + // vk::image_usage::sampled_bit, .mip_levels = + // p_params.mip_levels, .layer_count = p_params.layer_count, // }; m_bytes.reserve(size); std::span bytes_view = - std::span(image_pixel_data, size); + std::span(image_pixel_data, size); m_bytes.assign(bytes_view.begin(), bytes_view.end()); @@ -78,9 +78,13 @@ export namespace vk { return true; } - std::span image_read() const override { return m_bytes; } + [[nodiscard]] std::span image_read() const override { + return m_bytes; + } - vk::image_extent image_extent() const override { return m_extent; } + [[nodiscard]] vk::image_extent image_extent() const override { + return m_extent; + } private: vk::image_extent m_extent{}; diff --git a/atlas/drivers/vulkan/swapchain copy.cppm b/atlas/drivers/vulkan/swapchain copy.cppm deleted file mode 100644 index 16263821..00000000 --- a/atlas/drivers/vulkan/swapchain copy.cppm +++ /dev/null @@ -1,352 +0,0 @@ -module; - -#include -#include -#include - -export module atlas.drivers.vulkan.swapchain; - -import vk; - -// import atlas.logger; -// import atlas.core.utilities.types; -import atlas.core.utilities; -import atlas.drivers.vulkan.instance_context; -import atlas.drivers.vulkan.physical_device; -import atlas.drivers.vulkan.device; -import atlas.drivers.vulkan.utilities; - -export namespace atlas::vulkan { - /** - * @name vk_swapchain - * @brief High-level abstraction of a vulkan swapchain - * @brief ref will return the vk_swapchain directly - * @brief ref returning vk_swapchain will need to be changed - */ - class swapchain { - public: - swapchain() = default; - - /** - * @brief Constructs a new vulkan swapchain with a window settings to - * apply to this swapchain - * @param p_surface passing in the surface handler for swapchain uses - */ - swapchain(const VkSurfaceKHR& p_surface, const window_params& p_params) - : m_current_surface_handler(p_surface) - , m_window_params(p_params) - , m_current_surface(p_surface) { - m_physical = instance_context::physical_driver(); - m_driver = instance_context::logical_device(); - - create(); - - console_log_info_tagged("vulkan", - "swapchain created successfully!!!"); - } - - //! @return uint32_t the next available image to present acquired - uint32_t read_acquired_image() { - m_present_to_queue.wait_idle(); - - // uint32_t frame_idx = m_present_to_queue.acquired_frame(); - uint32_t frame_idx = m_present_to_queue.acquire_next_image(); - if (m_present_to_queue.out_of_date()) { - invalidate(); - m_present_to_queue.out_of_date(false); - frame_idx = m_present_to_queue.acquire_next_image(); - } - - return frame_idx; - } - - //! @return current active command buffer being processed - [[nodiscard]] vk::command_buffer active_command( - uint32_t p_frame_index) { - return m_swapchain_command_buffers[p_frame_index]; - } - - [[nodiscard]] VkFramebuffer active_framebuffer(uint32_t p_frame) const { - return m_swapchain_framebuffers[p_frame]; - } - - [[nodiscard]] vk::renderpass swapchain_renderpass() const { - return m_final_renderpass; - } - - [[nodiscard]] window_params settings() const { return m_window_params; } - - [[nodiscard]] uint32_t image_size() const { return m_image_size; } - - [[nodiscard]] surface_properties data() const { - return m_surface_properties; - } - - void destroy() { - vkDeviceWaitIdle(m_driver); - - for (size_t i = 0; i < m_swapchain_framebuffers.size(); i++) { - m_swapchain_framebuffers[i].destruct(); - } - - m_final_renderpass.destruct(); - - m_present_to_queue.destruct(); - - for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { - m_swapchain_command_buffers[i].destruct(); - } - - for (uint32_t i = 0; i < m_swapchain_depth_images.size(); i++) { - m_swapchain_depth_images[i].destruct(); - } - - for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - m_swapchain_images[i].destruct(); - } - - vkDestroySwapchainKHR(m_driver, m_swapchain_handler, nullptr); - } - - void submit(std::span p_commands) { - m_present_to_queue.submit_async(p_commands); - } - - [[nodiscard]] ::vk::sample_image active_image(uint32_t p_index) const { - return m_swapchain_images[p_index]; - } - - operator VkSwapchainKHR() const { return m_swapchain_handler; } - - operator VkSwapchainKHR() { return m_swapchain_handler; } - - void present(const uint32_t& p_current_frame) { - m_present_to_queue.present_frame(p_current_frame); - if (m_present_to_queue.out_of_date()) { - invalidate(); - m_present_to_queue.out_of_date(false); - } - } - - private: - void invalidate() { - destroy(); - create(); - } - - void create() { - // surface properties are always updated from the physical device - // so they are valid should the swapchain be recreated - m_surface_properties = - m_physical.get_surface_properties(m_current_surface); - m_window_params.width = - m_surface_properties.surface_capabilities.currentExtent.width; - m_window_params.height = - m_surface_properties.surface_capabilities.currentExtent.height; - - //! @note Setting up presentation stuff - // request what our minimum image count is - uint32_t request_min_image_count = - select_images_size(m_surface_properties.surface_capabilities); - - m_swapchain_extent = - m_surface_properties.surface_capabilities.currentExtent; - - // setting our presentation properties - uint32_t present_index = - m_physical.read_presentation_index(m_current_surface_handler); - - VkSwapchainCreateInfoKHR swapchain_ci = { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .surface = m_current_surface_handler, - .minImageCount = request_min_image_count, - .imageFormat = m_surface_properties.surface_format.format, - .imageColorSpace = - m_surface_properties.surface_format.colorSpace, - // use physical device surface formats to getting the right - // formats in vulkan - .imageExtent = m_swapchain_extent, - .imageArrayLayers = 1, - .imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT), - .queueFamilyIndexCount = 1, - .pQueueFamilyIndices = &present_index, - .preTransform = - m_surface_properties.surface_capabilities.currentTransform, - .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - .presentMode = VK_PRESENT_MODE_FIFO_KHR, - .clipped = true - }; - - vk_check(vkCreateSwapchainKHR( - m_driver, &swapchain_ci, nullptr, &m_swapchain_handler), - "vkCreateSwapchainKHR"); - - //!@brief querying images available - uint32_t image_count = 0; - vkGetSwapchainImagesKHR( - m_driver, - m_swapchain_handler, - &image_count, - nullptr); // used to get the amount of images - std::vector images(image_count); - vkGetSwapchainImagesKHR( - m_driver, - m_swapchain_handler, - &image_count, - images.data()); // used to store in the images - - // Creating Images - m_swapchain_images.resize(image_count); - m_image_size = image_count; - m_swapchain_depth_images.resize(image_count); - - VkFormat depth_format = m_driver.depth_format(); - - for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - ::vk::image_params color_image_config = { - .extent = { m_swapchain_extent.width, - m_swapchain_extent.height, }, - .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), - .format = m_surface_properties.surface_format.format, - .aspect = ::vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::color_attachment_bit, - .mip_levels = 1, - .layer_count = 1, - }; - - m_swapchain_images[i] = - ::vk::sample_image(m_driver, images[i], color_image_config); - - ::vk::image_params depth_image_config = { - .extent = { m_swapchain_extent.width, - m_swapchain_extent.height, }, - .format = depth_format, - .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), - .aspect = ::vk::image_aspect_flags::depth_bit, - // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .usage = vk::image_usage::depth_stencil_bit, - .mip_levels = 1, - .layer_count = 1, - }; - - m_swapchain_depth_images[i] = - ::vk::sample_image(m_driver, depth_image_config); - } - - // command buffers - - m_swapchain_command_buffers.resize(image_count); - - for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { - ::vk::command_params settings = { - .levels = ::vk::command_levels::primary, - // .queue_index = - // enumerate_swapchain_settings.present_index, - .queue_index = 0, - .flags = ::vk::command_pool_flags::reset, - }; - - m_swapchain_command_buffers[i] = - ::vk::command_buffer(m_driver, settings); - } - - std::array<::vk::attachment, 2> renderpass_attachments = { - ::vk::attachment{ - .format = m_surface_properties.surface_format.format, - .layout = ::vk::image_layout::color_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::store, - .stencil_load = ::vk::attachment_load::clear, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::present_src_khr, - }, - ::vk::attachment{ - .format = depth_format, - .layout = ::vk::image_layout::depth_stencil_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::dont_care, - .stencil_load = ::vk::attachment_load::dont_care, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::depth_stencil_optimal, - }, - }; - m_final_renderpass = - ::vk::renderpass(m_driver, renderpass_attachments); - - // creating framebuffers - m_swapchain_framebuffers.resize(m_swapchain_images.size()); - - for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - - std::array - image_attachments = { - m_swapchain_images[i].image_view(), - m_swapchain_depth_images[i].image_view() - }; - - vk::framebuffer_params framebuffer_info = { - .renderpass = m_final_renderpass, - .views = image_attachments, - .extent = m_swapchain_extent - }; - m_swapchain_framebuffers[i] = - vk::framebuffer(m_driver, framebuffer_info); - } - - vk::queue_params present_queue_params{ - .family = 0, - .index = 0, - }; - m_present_to_queue = ::vk::device_present_queue( - m_driver, m_swapchain_handler, present_queue_params); - console_log_info("m_present_to_queue initialized!!!"); - console_log_info("m_presesnt_to_queue.alive() = {}", - (m_present_to_queue != nullptr)); - } - - uint32_t select_images_size( - const VkSurfaceCapabilitiesKHR& p_surface_capabilities) { - uint32_t requested_images = - p_surface_capabilities.minImageCount + 1; - uint32_t final_image_count = 0; - - if ((p_surface_capabilities.maxImageCount > 0) and - (requested_images > p_surface_capabilities.maxImageCount)) { - final_image_count = p_surface_capabilities.maxImageCount; - } - else { - final_image_count = requested_images; - } - - return final_image_count; - } - - private: - physical_device m_physical{}; - device m_driver{}; - VkSurfaceKHR m_current_surface_handler = nullptr; - VkSwapchainKHR m_swapchain_handler = nullptr; - VkExtent2D m_swapchain_extent{}; - window_params m_window_params{}; - - uint32_t m_image_size = 0; - - VkSurfaceKHR m_current_surface = nullptr; - surface_properties m_surface_properties{}; - std::vector m_swapchain_command_buffers{}; - std::vector m_swapchain_framebuffers; - - //! @brief setting up images - std::vector m_swapchain_images; - std::vector m_swapchain_depth_images; - - vk::renderpass m_final_renderpass; - - vk::device_present_queue m_present_to_queue; - }; -}; diff --git a/atlas/drivers/vulkan/swapchain.cppm b/atlas/drivers/vulkan/swapchain.cppm index 66fbc51a..482bc102 100644 --- a/atlas/drivers/vulkan/swapchain.cppm +++ b/atlas/drivers/vulkan/swapchain.cppm @@ -11,7 +11,6 @@ import vk; // import atlas.logger; // import atlas.core.utilities.types; import atlas.core.utilities; -import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.physical_device; import atlas.drivers.vulkan.device; import atlas.drivers.vulkan.utilities; @@ -23,330 +22,343 @@ export namespace atlas::vulkan { * @brief ref will return the vk_swapchain directly * @brief ref returning vk_swapchain will need to be changed */ - class swapchain { - public: - swapchain() = default; - - /** - * @brief Constructs a new vulkan swapchain with a window settings to - * apply to this swapchain - * @param p_surface passing in the surface handler for swapchain uses - */ - swapchain(const VkSurfaceKHR& p_surface, const window_params& p_params) - : m_current_surface_handler(p_surface) - , m_window_params(p_params) - , m_current_surface(p_surface) { - m_physical = instance_context::physical_driver(); - m_driver = instance_context::logical_device(); - - create(); - - console_log_info_tagged("vulkan", - "swapchain created successfully!!!"); - } - - //! @return uint32_t the next available image to present acquired - uint32_t read_acquired_image() { - m_present_to_queue.wait_idle(); - - // uint32_t frame_idx = m_present_to_queue.acquired_frame(); - uint32_t frame_idx = m_present_to_queue.acquire_next_image(); - if (m_present_to_queue.out_of_date()) { - invalidate(); - m_present_to_queue.out_of_date(false); - frame_idx = m_present_to_queue.acquire_next_image(); - } - - return frame_idx; - } - - //! @return current active command buffer being processed - [[nodiscard]] vk::command_buffer active_command( - uint32_t p_frame_index) { - return m_swapchain_command_buffers[p_frame_index]; - } - - [[nodiscard]] VkFramebuffer active_framebuffer(uint32_t p_frame) const { - return m_swapchain_framebuffers[p_frame]; - } - - [[nodiscard]] vk::renderpass swapchain_renderpass() const { - return m_final_renderpass; - } - - [[nodiscard]] window_params settings() const { return m_window_params; } - - [[nodiscard]] uint32_t image_size() const { return m_image_size; } - - [[nodiscard]] surface_properties data() const { - return m_surface_properties; - } - - void destroy() { - vkDeviceWaitIdle(m_driver); - - for (size_t i = 0; i < m_swapchain_framebuffers.size(); i++) { - m_swapchain_framebuffers[i].destroy(); - } - - m_final_renderpass.destroy(); - - m_present_to_queue.destroy(); - - for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { - m_swapchain_command_buffers[i].destroy(); - } - - for (uint32_t i = 0; i < m_swapchain_depth_images.size(); i++) { - m_swapchain_depth_images[i].destroy(); - } - - for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - m_swapchain_images[i].destroy(); - } - - vkDestroySwapchainKHR(m_driver, m_swapchain_handler, nullptr); - } - - void submit(std::span p_commands) { - m_present_to_queue.submit_async(p_commands); - } - - [[nodiscard]] ::vk::sample_image active_image(uint32_t p_index) const { - return m_swapchain_images[p_index]; - } - - operator VkSwapchainKHR() const { return m_swapchain_handler; } - - operator VkSwapchainKHR() { return m_swapchain_handler; } - - void present(const uint32_t& p_current_frame) { - m_present_to_queue.present_frame(p_current_frame); - if (m_present_to_queue.out_of_date()) { - invalidate(); - m_present_to_queue.out_of_date(false); - } - } - - private: - void invalidate() { - destroy(); - create(); - } - - void create() { - // surface properties are always updated from the physical device - // so they are valid should the swapchain be recreated - m_surface_properties = - m_physical.get_surface_properties(m_current_surface); - m_window_params.width = - m_surface_properties.surface_capabilities.currentExtent.width; - m_window_params.height = - m_surface_properties.surface_capabilities.currentExtent.height; - - //! @note Setting up presentation stuff - // request what our minimum image count is - uint32_t request_min_image_count = - select_images_size(m_surface_properties.surface_capabilities); - - m_swapchain_extent = - m_surface_properties.surface_capabilities.currentExtent; - - // setting our presentation properties - uint32_t present_index = - m_physical.read_presentation_index(m_current_surface_handler); - - VkSwapchainCreateInfoKHR swapchain_ci = { - .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - .surface = m_current_surface_handler, - .minImageCount = request_min_image_count, - .imageFormat = m_surface_properties.surface_format.format, - .imageColorSpace = - m_surface_properties.surface_format.colorSpace, - // use physical device surface formats to getting the right - // formats in vulkan - .imageExtent = m_swapchain_extent, - .imageArrayLayers = 1, - .imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT), - .queueFamilyIndexCount = 1, - .pQueueFamilyIndices = &present_index, - .preTransform = - m_surface_properties.surface_capabilities.currentTransform, - .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - .presentMode = VK_PRESENT_MODE_FIFO_KHR, - .clipped = true - }; - - vk_check(vkCreateSwapchainKHR( - m_driver, &swapchain_ci, nullptr, &m_swapchain_handler), - "vkCreateSwapchainKHR"); - - //!@brief querying images available - uint32_t image_count = 0; - vkGetSwapchainImagesKHR( - m_driver, - m_swapchain_handler, - &image_count, - nullptr); // used to get the amount of images - std::vector images(image_count); - vkGetSwapchainImagesKHR( - m_driver, - m_swapchain_handler, - &image_count, - images.data()); // used to store in the images - - // Creating Images - m_swapchain_images.resize(image_count); - m_image_size = image_count; - m_swapchain_depth_images.resize(image_count); - - VkFormat depth_format = m_driver.depth_format(); - - for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - ::vk::image_params color_image_config = { - .extent = { m_swapchain_extent.width, - m_swapchain_extent.height, }, - .format = m_surface_properties.surface_format.format, - .aspect = ::vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::color_attachment_bit, - .mip_levels = 1, - .layer_count = 1, - .phsyical_memory_properties = m_physical.memory_properties(), - - }; - - m_swapchain_images[i] = - ::vk::sample_image(m_driver, images[i], color_image_config); - - ::vk::image_params depth_image_config = { - .extent = { m_swapchain_extent.width, - m_swapchain_extent.height, }, - .format = depth_format, - .aspect = ::vk::image_aspect_flags::depth_bit, - .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .mip_levels = 1, - .layer_count = 1, - .phsyical_memory_properties = m_physical.memory_properties(), - }; - - m_swapchain_depth_images[i] = - ::vk::sample_image(m_driver, depth_image_config); - } - - // command buffers - - m_swapchain_command_buffers.resize(image_count); - - for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { - ::vk::command_params settings = { - .levels = ::vk::command_levels::primary, - // .queue_index = - // enumerate_swapchain_settings.present_index, - .queue_index = 0, - .flags = ::vk::command_pool_flags::reset, - }; - - m_swapchain_command_buffers[i] = - ::vk::command_buffer(m_driver, settings); - } - - std::array<::vk::attachment, 2> renderpass_attachments = { - ::vk::attachment{ - .format = m_surface_properties.surface_format.format, - .layout = ::vk::image_layout::color_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::store, - .stencil_load = ::vk::attachment_load::clear, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::present_src_khr, - }, - ::vk::attachment{ - .format = depth_format, - .layout = ::vk::image_layout::depth_stencil_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::dont_care, - .stencil_load = ::vk::attachment_load::dont_care, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::depth_stencil_optimal, - }, - }; - m_final_renderpass = - ::vk::renderpass(m_driver, renderpass_attachments); - - // creating framebuffers - m_swapchain_framebuffers.resize(m_swapchain_images.size()); - - for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - - std::array - image_attachments = { - m_swapchain_images[i].image_view(), - m_swapchain_depth_images[i].image_view() - }; - - vk::framebuffer_params framebuffer_info = { - .renderpass = m_final_renderpass, - .views = image_attachments, - .extent = m_swapchain_extent - }; - m_swapchain_framebuffers[i] = - vk::framebuffer(m_driver, framebuffer_info); - } - - vk::queue_params present_queue_params{ - .family = 0, - .index = 0, - }; - m_present_to_queue = ::vk::device_present_queue( - m_driver, m_swapchain_handler, present_queue_params); - console_log_info("m_present_to_queue initialized!!!"); - console_log_info("m_presesnt_to_queue.alive() = {}", - (m_present_to_queue != nullptr)); - } - - uint32_t select_images_size( - const VkSurfaceCapabilitiesKHR& p_surface_capabilities) { - uint32_t requested_images = - p_surface_capabilities.minImageCount + 1; - uint32_t final_image_count = 0; - - if ((p_surface_capabilities.maxImageCount > 0) and - (requested_images > p_surface_capabilities.maxImageCount)) { - final_image_count = p_surface_capabilities.maxImageCount; - } - else { - final_image_count = requested_images; - } - - return final_image_count; - } - - private: - physical_device m_physical{}; - device m_driver{}; - VkSurfaceKHR m_current_surface_handler = nullptr; - VkSwapchainKHR m_swapchain_handler = nullptr; - VkExtent2D m_swapchain_extent{}; - window_params m_window_params{}; - - uint32_t m_image_size = 0; - - VkSurfaceKHR m_current_surface = nullptr; - surface_properties m_surface_properties{}; - std::vector m_swapchain_command_buffers{}; - std::vector m_swapchain_framebuffers; - - //! @brief setting up images - std::vector m_swapchain_images; - std::vector m_swapchain_depth_images; - - vk::renderpass m_final_renderpass; - - vk::device_present_queue m_present_to_queue; - }; + // class swapchain { + // public: + // swapchain() = default; + + // /** + // * @brief Constructs a new vulkan swapchain with a window settings to + // * apply to this swapchain + // * @param p_surface passing in the surface handler for swapchain uses + // */ + // swapchain(const VkSurfaceKHR& p_surface, const window_params& p_params) + // : m_current_surface_handler(p_surface) + // , m_window_params(p_params) + // , m_current_surface(p_surface) { + // m_physical = instance_context::physical_driver(); + // m_driver = instance_context::logical_device(); + + // create(); + + // console_log_info_tagged("vulkan", + // "swapchain created successfully!!!"); + // } + + // //! @return uint32_t the next available image to present acquired + // uint32_t read_acquired_image() { + // m_present_to_queue.wait_idle(); + + // // uint32_t frame_idx = m_present_to_queue.acquired_frame(); + // uint32_t frame_idx = m_present_to_queue.acquire_next_image(); + // if (m_present_to_queue.out_of_date()) { + // invalidate(); + // m_present_to_queue.out_of_date(false); + // frame_idx = m_present_to_queue.acquire_next_image(); + // } + + // return frame_idx; + // } + + // //! @return current active command buffer being processed + // [[nodiscard]] vk::command_buffer active_command( + // uint32_t p_frame_index) { + // return m_swapchain_command_buffers[p_frame_index]; + // } + + // [[nodiscard]] VkFramebuffer active_framebuffer(uint32_t p_frame) const { + // return m_swapchain_framebuffers[p_frame]; + // } + + // [[nodiscard]] vk::renderpass swapchain_renderpass() const { + // return m_final_renderpass; + // } + + // [[nodiscard]] window_params settings() const { return m_window_params; } + + // [[nodiscard]] uint32_t image_size() const { return m_image_size; } + + // [[nodiscard]] surface_properties data() const { + // return m_surface_properties; + // } + + // void destroy() { + // vkDeviceWaitIdle(m_driver); + + // for (size_t i = 0; i < m_swapchain_framebuffers.size(); i++) { + // m_swapchain_framebuffers[i].destruct(); + // } + + // m_final_renderpass.destruct(); + + // m_present_to_queue.destruct(); + + // for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { + // m_swapchain_command_buffers[i].destruct(); + // } + + // for (uint32_t i = 0; i < m_swapchain_depth_images.size(); i++) { + // m_swapchain_depth_images[i].destruct(); + // } + + // for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { + // m_swapchain_images[i].destruct(); + // } + + // vkDestroySwapchainKHR(m_driver, m_swapchain_handler, nullptr); + // } + + // void submit(std::span p_commands) { + // m_present_to_queue.submit_async(p_commands); + // } + + // [[nodiscard]] ::vk::sample_image active_image(uint32_t p_index) const { + // return m_swapchain_images[p_index]; + // } + + // operator VkSwapchainKHR() const { return m_swapchain_handler; } + + // operator VkSwapchainKHR() { return m_swapchain_handler; } + + // void present(const uint32_t& p_current_frame) { + // m_present_to_queue.present_frame(p_current_frame); + // if (m_present_to_queue.out_of_date()) { + // invalidate(); + // m_present_to_queue.out_of_date(false); + // } + // } + + // private: + // void invalidate() { + // destroy(); + // create(); + // } + + // void create() { + // // surface properties are always updated from the physical device + // // so they are valid should the swapchain be recreated + // m_surface_properties = + // m_physical.get_surface_properties(m_current_surface); + // m_window_params.width = + // m_surface_properties.surface_capabilities.currentExtent.width; + // m_window_params.height = + // m_surface_properties.surface_capabilities.currentExtent.height; + + // //! @note Setting up presentation stuff + // // request what our minimum image count is + // uint32_t request_min_image_count = + // select_images_size(m_surface_properties.surface_capabilities); + + // m_swapchain_extent = + // m_surface_properties.surface_capabilities.currentExtent; + + // // setting our presentation properties + // uint32_t present_index = + // m_physical.read_presentation_index(m_current_surface_handler); + + // VkSwapchainCreateInfoKHR swapchain_ci = { + // .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + // .surface = m_current_surface_handler, + // .minImageCount = request_min_image_count, + // .imageFormat = m_surface_properties.surface_format.format, + // .imageColorSpace = + // m_surface_properties.surface_format.colorSpace, + // // use physical device surface formats to getting the right + // // formats in vulkan + // .imageExtent = m_swapchain_extent, + // .imageArrayLayers = 1, + // .imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + // VK_IMAGE_USAGE_TRANSFER_DST_BIT), + // .queueFamilyIndexCount = 1, + // .pQueueFamilyIndices = &present_index, + // .preTransform = + // m_surface_properties.surface_capabilities.currentTransform, + // .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + // .presentMode = VK_PRESENT_MODE_FIFO_KHR, + // .clipped = true + // }; + + // vk_check(vkCreateSwapchainKHR( + // m_driver, &swapchain_ci, nullptr, &m_swapchain_handler), + // "vkCreateSwapchainKHR"); + + // //!@brief querying images available + // uint32_t image_count = 0; + // vkGetSwapchainImagesKHR( + // m_driver, + // m_swapchain_handler, + // &image_count, + // nullptr); // used to get the amount of images + // std::vector images(image_count); + // vkGetSwapchainImagesKHR( + // m_driver, + // m_swapchain_handler, + // &image_count, + // images.data()); // used to store in the images + + // // Creating Images + // m_swapchain_images.resize(image_count); + // m_image_size = image_count; + // m_swapchain_depth_images.resize(image_count); + + // VkFormat depth_format = m_driver.depth_format(); + + // for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { + // // ::vk::image_params color_image_config = { + // // .extent = { m_swapchain_extent.width, + // // m_swapchain_extent.height, }, + // // .format = m_surface_properties.surface_format.format, + // // .aspect = ::vk::image_aspect_flags::color_bit, + // // .usage = vk::image_usage::color_attachment_bit, + // // .mip_levels = 1, + // // .layer_count = 1, + // // .phsyical_memory_properties = m_physical.memory_properties(), + + // // }; + // vk::image_params color_image_params = { + // .extent = { + // .width = m_swapchain_extent.width, + // .height = m_swapchain_extent.height, + // }, + // .format = m_surface_properties.surface_format.format, + // .memory_mask = m_physical.memory_properties( + // vk::memory_property::device_local_bit), + // .aspect = vk::image_aspect_flags::color_bit, + // .usage = vk::image_usage::color_attachment_bit, + // .mip_levels = 1, + // .layer_count = 1, + // }; + + // m_swapchain_images[i] = + // ::vk::sample_image(m_driver, images[i], color_image_params); + + // vk::image_params depth_image_params = { + // .extent = { + // .width = m_swapchain_extent.width, + // .height = m_swapchain_extent.height, + // }, + // .format = depth_format, + // .memory_mask = m_physical.memory_properties( + // vk::memory_property::device_local_bit), + // .aspect = vk::image_aspect_flags::depth_bit, + // .usage = vk::image_usage::depth_stencil_bit, + // .mip_levels = 1, + // .layer_count = 1, + // }; + + // m_swapchain_depth_images[i] = + // ::vk::sample_image(m_driver, depth_image_params); + // } + + // // command buffers + // m_swapchain_command_buffers.resize(image_count); + + // for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { + // vk::command_params command_params = { + // .levels = vk::command_levels::primary, + // .queue_index = 0, + // .flags = vk::command_pool_flags::reset, + // }; + + // m_swapchain_command_buffers[i] = + // ::vk::command_buffer(m_driver, command_params); + // } + + // std::array<::vk::attachment, 2> renderpass_attachments = { + // ::vk::attachment{ + // .format = m_surface_properties.surface_format.format, + // .layout = ::vk::image_layout::color_optimal, + // .samples = ::vk::sample_bit::count_1, + // .load = ::vk::attachment_load::clear, + // .store = ::vk::attachment_store::store, + // .stencil_load = ::vk::attachment_load::clear, + // .stencil_store = ::vk::attachment_store::dont_care, + // .initial_layout = ::vk::image_layout::undefined, + // .final_layout = ::vk::image_layout::present_src_khr, + // }, + // ::vk::attachment{ + // .format = depth_format, + // .layout = ::vk::image_layout::depth_stencil_optimal, + // .samples = ::vk::sample_bit::count_1, + // .load = ::vk::attachment_load::clear, + // .store = ::vk::attachment_store::dont_care, + // .stencil_load = ::vk::attachment_load::dont_care, + // .stencil_store = ::vk::attachment_store::dont_care, + // .initial_layout = ::vk::image_layout::undefined, + // .final_layout = ::vk::image_layout::depth_stencil_optimal, + // }, + // }; + // m_final_renderpass = + // ::vk::renderpass(m_driver, renderpass_attachments); + + // // creating framebuffers + // m_swapchain_framebuffers.resize(m_swapchain_images.size()); + + // for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { + + // std::array + // image_attachments = { + // m_swapchain_images[i].image_view(), + // m_swapchain_depth_images[i].image_view() + // }; + + // vk::framebuffer_params framebuffer_info = { + // .renderpass = m_final_renderpass, + // .views = image_attachments, + // .extent = m_swapchain_extent + // }; + // m_swapchain_framebuffers[i] = + // vk::framebuffer(m_driver, framebuffer_info); + // } + + // vk::queue_params present_queue_params{ + // .family = 0, + // .index = 0, + // }; + // m_present_to_queue = ::vk::device_present_queue( + // m_driver, m_swapchain_handler, present_queue_params); + // console_log_info("m_present_to_queue initialized!!!"); + // console_log_info("m_presesnt_to_queue.alive() = {}", + // (m_present_to_queue != nullptr)); + // } + + // uint32_t select_images_size( + // const VkSurfaceCapabilitiesKHR& p_surface_capabilities) { + // uint32_t requested_images = + // p_surface_capabilities.minImageCount + 1; + // uint32_t final_image_count = 0; + + // if ((p_surface_capabilities.maxImageCount > 0) and + // (requested_images > p_surface_capabilities.maxImageCount)) { + // final_image_count = p_surface_capabilities.maxImageCount; + // } + // else { + // final_image_count = requested_images; + // } + + // return final_image_count; + // } + + // private: + // physical_device m_physical{}; + // device m_driver{}; + // VkSurfaceKHR m_current_surface_handler = nullptr; + // VkSwapchainKHR m_swapchain_handler = nullptr; + // VkExtent2D m_swapchain_extent{}; + // window_params m_window_params{}; + + // uint32_t m_image_size = 0; + + // VkSurfaceKHR m_current_surface = nullptr; + // surface_properties m_surface_properties{}; + // std::vector m_swapchain_command_buffers{}; + // std::vector m_swapchain_framebuffers; + + // //! @brief setting up images + // std::vector m_swapchain_images; + // std::vector m_swapchain_depth_images; + + // vk::renderpass m_final_renderpass; + + // vk::device_present_queue m_present_to_queue; + // }; }; diff --git a/atlas/drivers/vulkan/window_context.cppm b/atlas/drivers/vulkan/window_context.cppm index 49aa2325..8e86ab6f 100644 --- a/atlas/drivers/vulkan/window_context.cppm +++ b/atlas/drivers/vulkan/window_context.cppm @@ -23,113 +23,112 @@ import vk; import atlas.window; import atlas.drivers.graphics_context; -// import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.utilities; import atlas.drivers.vulkan.swapchain; export namespace atlas { - namespace vulkan { + // namespace vulkan { /** * @brief vulkan-backend implementation of the application-window */ - class window_context : public window { - public: - window_context(ref p_context, - const window_params& p_params) - : m_params(p_params) { - - console_log_info("window_context constructed!!!"); - - if (!glfwVulkanSupported()) { - console_log_error("GLFW: Vulkan is not supported!!!"); - console_log_error("GLFW: Vulkan Supported = {}", - static_cast(glfwVulkanSupported())); - return; - } - - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - - // m_instance = instance_context::handle(); - m_instance = p_context->handle(); - - m_window_handle = - glfwCreateWindow(static_cast(m_params.width), - static_cast(m_params.height), - m_params.name.c_str(), - nullptr, - nullptr); - - glfwMakeContextCurrent(m_window_handle); - - console_log_info("m_instance = {}", (m_instance == nullptr)); - - vk_check( - glfwCreateWindowSurface( - m_instance, m_window_handle, nullptr, &m_window_surface), - "glfwCreateWindowSurface"); - - center_window(); - - m_window_swapchain = swapchain(m_window_surface, m_params); - - p_context->submit_resource_free([this]() { - console_log_info("vulkan::window_context " - "submit_resource_free invokation!"); - m_window_swapchain.destroy(); - }); - } - - virtual ~window_context() { - if (m_window_surface != nullptr) { - vkDestroySurfaceKHR(m_instance, m_window_surface, nullptr); - } - glfwDestroyWindow(m_window_handle); - } - - protected: - [[nodiscard]] window_params get_params() const override { - return m_window_swapchain.settings(); - } - - [[nodiscard]] GLFWwindow* native_window() const override { - return m_window_handle; - } - - [[nodiscard]] uint32_t read_acquired_next_frame() override { - return m_window_swapchain.read_acquired_image(); - } - - [[nodiscard]] vulkan::swapchain window_swapchain() const override { - return m_window_swapchain; - } - - [[nodiscard]] vk::command_buffer current_active_command( - uint32_t p_frame_idx) override { - return m_window_swapchain.active_command(p_frame_idx); - } - - void present_frame(const uint32_t& p_current_frame) override { - m_window_swapchain.present(p_current_frame); - } - - private: - void center_window() { - GLFWmonitor* monitor = glfwGetPrimaryMonitor(); - const GLFWvidmode* mode = glfwGetVideoMode(monitor); - uint32_t width = (mode->width / 2) - (m_params.width / 2); - uint32_t height = (mode->height / 2) - (m_params.height / 2); - glfwSetWindowPos(m_window_handle, - static_cast(width), - static_cast(height)); - } - - private: - GLFWwindow* m_window_handle = nullptr; - VkSurfaceKHR m_window_surface = nullptr; - window_params m_params; - VkInstance m_instance = nullptr; - swapchain m_window_swapchain; - }; - }; + // class window_context : public window { + // public: + // window_context(ref p_context, + // const window_params& p_params) + // : m_params(p_params) { + + // console_log_info("window_context constructed!!!"); + + // if (!glfwVulkanSupported()) { + // console_log_error("GLFW: Vulkan is not supported!!!"); + // console_log_error("GLFW: Vulkan Supported = {}", + // static_cast(glfwVulkanSupported())); + // return; + // } + + // glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + // glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + + // // m_instance = instance_context::handle(); + // m_instance = p_context->handle(); + + // m_window_handle = + // glfwCreateWindow(static_cast(m_params.width), + // static_cast(m_params.height), + // m_params.name.c_str(), + // nullptr, + // nullptr); + + // glfwMakeContextCurrent(m_window_handle); + + // console_log_info("m_instance = {}", (m_instance == nullptr)); + + // vk_check( + // glfwCreateWindowSurface( + // m_instance, m_window_handle, nullptr, &m_window_surface), + // "glfwCreateWindowSurface"); + + // center_window(); + + // m_window_swapchain = swapchain(m_window_surface, m_params); + + // p_context->submit_resource_free([this]() { + // console_log_info("vulkan::window_context " + // "submit_resource_free invokation!"); + // m_window_swapchain.destroy(); + // }); + // } + + // virtual ~window_context() { + // if (m_window_surface != nullptr) { + // vkDestroySurfaceKHR(m_instance, m_window_surface, nullptr); + // } + // glfwDestroyWindow(m_window_handle); + // } + + // protected: + // [[nodiscard]] window_params get_params() const override { + // return m_window_swapchain.settings(); + // } + + // [[nodiscard]] GLFWwindow* native_window() const override { + // return m_window_handle; + // } + + // [[nodiscard]] uint32_t read_acquired_next_frame() override { + // return m_window_swapchain.read_acquired_image(); + // } + + // [[nodiscard]] vulkan::swapchain window_swapchain() const override { + // return m_window_swapchain; + // } + + // [[nodiscard]] vk::command_buffer current_active_command( + // uint32_t p_frame_idx) override { + // return m_window_swapchain.active_command(p_frame_idx); + // } + + // void present_frame(const uint32_t& p_current_frame) override { + // m_window_swapchain.present(p_current_frame); + // } + + // private: + // void center_window() { + // GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + // const GLFWvidmode* mode = glfwGetVideoMode(monitor); + // uint32_t width = (mode->width / 2) - (m_params.width / 2); + // uint32_t height = (mode->height / 2) - (m_params.height / 2); + // glfwSetWindowPos(m_window_handle, + // static_cast(width), + // static_cast(height)); + // } + + // private: + // GLFWwindow* m_window_handle = nullptr; + // VkSurfaceKHR m_window_surface = nullptr; + // window_params m_params; + // VkInstance m_instance = nullptr; + // swapchain m_window_swapchain; + // }; + // }; }; \ No newline at end of file diff --git a/atlas/renderer/context_loader.cppm b/atlas/renderer/context_loader.cppm index cc2836a5..1ade493c 100644 --- a/atlas/renderer/context_loader.cppm +++ b/atlas/renderer/context_loader.cppm @@ -9,20 +9,18 @@ import atlas.core.utilities; import atlas.drivers.graphics_context; -import atlas.drivers.vulkan.instance_context; - export namespace atlas { /** * @brief construct a new graphics context and initializes that API * @return shared_ptr */ - ref initialize_context(const std::string& p_name, - graphics_api p_api) { - switch (p_api) { - case graphics_api::vulkan: - return create_ref(p_name); - default: - return nullptr; - } - } + // ref initialize_context(const std::string& p_name, + // graphics_api p_api) { + // switch (p_api) { + // case graphics_api::vulkan: + // return create_ref(p_name); + // default: + // return nullptr; + // } + // } }; \ No newline at end of file diff --git a/atlas/renderer/renderer.cppm b/atlas/renderer/renderer.cppm index ab1dfda5..b816f43d 100644 --- a/atlas/renderer/renderer.cppm +++ b/atlas/renderer/renderer.cppm @@ -14,18 +14,18 @@ import atlas.drivers.graphics_context; import atlas.core.utilities.types; export namespace atlas { - ref initialize_renderer( - ref p_context, - graphics_api p_api, - const window_params& p_window_extent, - uint32_t p_image_size, - const std::string& p_name) { - switch (p_api) { - case graphics_api::vulkan: - return create_ref( - p_context, p_window_extent, p_image_size, p_name); - default: - return nullptr; - } - } + // ref initialize_renderer( + // ref p_context, + // graphics_api p_api, + // const window_params& p_window_extent, + // uint32_t p_image_size, + // const std::string& p_name) { + // switch (p_api) { + // case graphics_api::vulkan: + // return create_ref( + // p_context, p_window_extent, p_image_size, p_name); + // default: + // return nullptr; + // } + // } }; \ No newline at end of file diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 132143ec..d4ca0137 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -9,11 +9,11 @@ target_sources(editor PUBLIC TYPE CXX_MODULES FILES editor.cppm - editor_world.cppm - level_scene.cppm - content_browser_panel.cppm - icon.cppm - utilities.cppm + # editor_world.ppm + # level_scene.cppm + # content_browser_panel.cppm + # icon.cppm + # utilities.cppm ) find_package(glfw3 REQUIRED) diff --git a/editor/application.cpp b/editor/application.cpp index edb1125e..080569be 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -6,37 +6,47 @@ import atlas.application; import atlas.common; import atlas.core.level_streamer; import atlas.core.event; -import editor; +// import editor; import atlas.drivers.graphics_context; class editor_application : public atlas::application { public: - editor_application(atlas::ref p_context, + editor_application(std::shared_ptr p_context, const atlas::application_settings& p_settings, atlas::event::bus& p_bus) - : atlas::application(std::move(p_context), p_settings, p_bus) { + : atlas::application(p_context, p_settings, p_bus) { - m_world = - atlas::create_ref("Editor World", p_bus, m_stream); + // m_world = + // atlas::create_ref("Editor World", p_bus, m_stream); - current_world(m_world); + // current_world(m_world); } private: - atlas::ref m_world; - atlas::level_streamer m_stream; + // atlas::ref m_world; + // atlas::level_streamer m_stream; }; +// atlas::ref +// initialize_application( +// /*NOLINT*/ atlas::ref p_contetxt, +// atlas::event::bus& p_bus) { +// atlas::application_settings settings = { +// .name = "Editor", +// .width = 1510, +// .height = 877, +// .background_color = { 0.f, 0.f, 0.f, 0.f }, +// }; +// return create_ref(p_contetxt, settings, p_bus); +// } atlas::ref -initialize_application( - /*NOLINT*/ atlas::ref p_contetxt, - atlas::event::bus& p_bus) { +initialize_application(std::shared_ptr p_context, atlas::event::bus& p_bus) { atlas::application_settings settings = { .name = "Editor", .width = 1510, .height = 877, .background_color = { 0.f, 0.f, 0.f, 0.f }, }; - return create_ref(p_contetxt, settings, p_bus); + return create_ref(p_context, settings, p_bus); } \ No newline at end of file diff --git a/editor/content_browser_panel.cppm b/editor/content_browser_panel.cppm index f52b87cc..b229e045 100644 --- a/editor/content_browser_panel.cppm +++ b/editor/content_browser_panel.cppm @@ -9,8 +9,8 @@ module; export module editor:content_browser; import atlas.logger; -import atlas.drivers.vulkan.instance_context; import atlas.drivers.vulkan.imgui_context; +import atlas.drivers.vulkan.stb_image; import vk; export class content_browser_panel { @@ -19,31 +19,34 @@ public: content_browser_panel( const VkDevice& p_device, - VkPhysicalDeviceMemoryProperties p_memory_properties) { - vk::texture_info config_texture = { - .phsyical_memory_properties = p_memory_properties, - .filepath = std::filesystem::path("assets/icons/FileIcon.png"), + uint32_t p_memory_properties) { + vk::texture_params config_texture = { + .memory_mask = p_memory_properties, }; - m_file_icon = vk::texture(p_device, config_texture); - if (!m_file_icon.loaded()) { - console_log_info("Play Button Could not be loaded!!"); - } + + atlas::vulkan::stb_image play_button("assets/icons/FileIcon.png", config_texture); + m_file_icon = vk::texture(p_device, &play_button, config_texture); + // if (!m_file_icon.loaded()) { + // console_log_info("Play Button Could not be loaded!!"); + // } config_texture = { - .phsyical_memory_properties = p_memory_properties, - .filepath = std::filesystem::path("assets/icons/DirectoryIcon.png"), + .memory_mask = p_memory_properties, }; - m_directory_icon = vk::texture(p_device, config_texture); - if (!m_directory_icon.loaded()) { - console_log_info("Stop Button Could not be loaded!!"); - } + + atlas::vulkan::stb_image file_icon("assets/icons/FileIcon.png", config_texture); + m_directory_icon = vk::texture(p_device, &file_icon, config_texture); + // if (!m_directory_icon.loaded()) { + // console_log_info("Stop Button Could not be loaded!!"); + // } config_texture = { - .phsyical_memory_properties = p_memory_properties, - .filepath = std::filesystem::path("assets/icons/Back.png"), + .memory_mask = p_memory_properties, }; - m_back_icon = vk::texture(p_device, config_texture); - if (!m_back_icon.loaded()) { - console_log_info("Stop Button Could not be loaded!!"); - } + + atlas::vulkan::stb_image back_icon("assets/icons/Back.png", config_texture); + m_back_icon = vk::texture(p_device, &back_icon, config_texture); + // if (!back_icon.loaded()) { + // console_log_info("Stop Button Could not be loaded!!"); + // } m_file_icon_id = static_cast(ImGui_ImplVulkan_AddTexture( m_file_icon.image().sampler(), @@ -151,9 +154,9 @@ public: } void destroy() { - m_file_icon.destroy(); - m_directory_icon.destroy(); - m_back_icon.destroy(); + m_file_icon.destruct(); + m_directory_icon.destruct(); + m_back_icon.destruct(); } private: diff --git a/editor/editor.cppm b/editor/editor.cppm index 7fb07c5c..0621e209 100644 --- a/editor/editor.cppm +++ b/editor/editor.cppm @@ -3,8 +3,8 @@ module; export module editor; -export import :world; -export import :level_scene; -export import :icon; -export import :content_browser; -export import :utilities; \ No newline at end of file +// export import :world; +// export import :level_scene; +// export import :icon; +// export import :content_browser; +// export import :utilities; \ No newline at end of file diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 72825030..c7e59121 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -25,11 +25,11 @@ public: // Create defualt scene to level streamer // Does polymorphic allocations for these customized scenes - default_custom_scene("LevelScene", p_bus); + // default_custom_scene("LevelScene", p_bus); // Set what our current scene is // TODO: Probably have `default_custom_scene() set this - current("LevelScene"); + // current("LevelScene"); } ~editor_world() override = default; diff --git a/editor/icon.cppm b/editor/icon.cppm index 84e7ba61..3c509697 100644 --- a/editor/icon.cppm +++ b/editor/icon.cppm @@ -5,11 +5,13 @@ module; #include #include #include +#include export module editor:icon; import atlas.core.utilities; -import atlas.drivers.vulkan.instance_context; +import atlas.drivers.vulkan.physical_device; +import atlas.drivers.vulkan.stb_image; import vk; export namespace ui::experimental { @@ -23,17 +25,27 @@ export namespace ui::experimental { class icon { public: icon() = default; - icon(const VkDevice& p_device, VkPhysicalDeviceMemoryProperties p_memory_properties, const std::filesystem::path& p_filename) { - vk::texture_info config_texture = { - .phsyical_memory_properties = p_memory_properties, - .filepath = p_filename + icon(const VkDevice& p_device, + uint32_t p_memory_properties, + const std::filesystem::path& p_filename) { + // vk::texture_info config_texture = { + // .phsyical_memory_properties = p_memory_properties, + // .filepath = p_filename + // }; + vk::texture_params config_texture = { + // .memory_mask = physical_device.memory_properties( + // vk::memory_property::host_visible_bit | + // vk::memory_property::host_cached_bit), + .memory_mask = p_memory_properties, }; - m_icon_image = - vk::texture(p_device, - config_texture); + + atlas::vulkan::stb_image image(p_filename.string(), config_texture); + m_icon_image = vk::texture(p_device, &image, config_texture); if (!m_icon_image.loaded()) { console_log_info("Play Button Could not be loaded!!"); } + + m_extent = image.extent(); m_icon_image_id = static_cast(ImGui_ImplVulkan_AddTexture( m_icon_image.image().sampler(), @@ -41,11 +53,11 @@ export namespace ui::experimental { VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); } - icon(const VkDevice& p_device, VkPhysicalDeviceMemoryProperties p_memory_properties, const vk::image_extent& p_extent) { - m_icon_image = - vk::texture(p_device, - p_extent, - p_memory_properties); + icon(const VkDevice& p_device, + uint32_t p_memory_properties, + const vk::image_extent& p_extent, std::span p_data) { + m_extent = p_extent; + m_icon_image = vk::texture(p_device, p_extent, p_data, p_memory_properties); m_icon_image_id = static_cast(ImGui_ImplVulkan_AddTexture( m_icon_image.image().sampler(), @@ -58,15 +70,16 @@ export namespace ui::experimental { // destroy(); } - [[nodiscard]] uint32_t width() const { return m_icon_image.width(); } + [[nodiscard]] uint32_t width() const { return m_extent.width; } - [[nodiscard]] uint32_t height() const { return m_icon_image.height(); } + [[nodiscard]] uint32_t height() const { return m_extent.height; } [[nodiscard]] ImTextureID texture_id() const { return m_icon_image_id; } - void destroy() { m_icon_image.destroy(); } + void destroy() { m_icon_image.destruct(); } private: + vk::image_extent m_extent{}; vk::texture m_icon_image; ImTextureID m_icon_image_id; }; diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 60d6e6f0..213c9499 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -1,886 +1,37 @@ module; -#include -#define GLM_ENABLE_EXPERIMENTAL -#include -#include - -#include -#include -#include -#include -#include -#include -#include +#include export module editor:level_scene; -import atlas.core.utilities; import atlas.application; import atlas.core.scene; import atlas.core.scene.game_object; import atlas.core.event; import atlas.core.scene.components; -import atlas.core.utilities.state; -import atlas.core.math; -import atlas.core.editor.dockspace; -import atlas.application; -import atlas.core.ui.widgets; -import atlas.core.editor.menu_item; -import atlas.core.serialize; -import atlas.physics.engine; -import atlas.drivers.vulkan.imgui_context; -import atlas.drivers.vulkan.instance_context; -import atlas.drivers.vulkan.physical_device; -import atlas.drivers.vulkan.device; -import atlas.core.ui.widgets.imgui_stdlib; -import vk; -import :content_browser; -import :icon; -import :utilities; - -enum scene_runtime { edit, play }; - -// TODO: This is just a temporary solution for loading material texture icons to -// ImGui::Image This should be replaced with something like -// atlas::material_manager, eventually. -struct material { - ui::experimental::icon specular; - ui::experimental::icon diffuse; -}; +import atlas.core.utilities; export class level_scene final : public atlas::scene { public: level_scene(const std::string& p_name, atlas::event::bus& p_bus) : atlas::scene(p_name, p_bus) { - m_device = atlas::vulkan::instance_context::logical_device(); - m_physical = atlas::vulkan::instance_context::physical_driver(); - - auto editor_camera = entity("Editor Camera"); - editor_camera - .add>(); - editor_camera.set({ - .position = { 3.50f, 4.90f, 36.40f }, - .scale{ 1.f }, - }); - editor_camera.set({ - .plane = { 0.1f, 5000.f }, - .is_active = true, - .field_of_view = 45.f, - }); - - atlas::game_object bob_object = entity("Bob"); - bob_object.add(); - - // @brief For now adding this in - // because we do not have a way to handle empty scenes - // so we are adding this in just to have a specific mesh associated with - // the renderer for the time being, just to make sure it works. - atlas::game_object viking_room = entity("Viking Room"); - viking_room.add(); - viking_room.set({ - .position = { -2.70f, 2.70, -8.30f }, - .rotation = { 2.30f, 95.90f, 91.80f }, - .scale{ 1.f }, - }); - - viking_room.set({ - .radius = 1.0f, - }); - - viking_room.set({ - .friction = 15.f, - .restitution = 0.3f, - .body_movement_type = atlas::dynamic, - }); - - atlas::game_object cube = entity("Aircraft"); - - cube.set({ - .position = { 0.f, 2.10f, -7.30f }, - .scale = { 0.9f, 0.9f, 0.9f }, - }); - - cube.set({ - .color = { 1.f, 1.f, 1.f, 1.f }, - // .model_path = "assets/models/E 45 Aircraft_obj.obj", - .model_path = "assets/backpack/backpack.obj", - .diffuse = "assets/backpack/diffuse.jpg", - .specular = "assets/backpack/specular.jpg" - // .diffuse = "assets/models/E-45-steel detail_2_col.jpg", - }); - - atlas::game_object robot_model = entity("Cube"); - robot_model.add(); - // robot_model.add(); - robot_model.set({ - .position = { -2.70, 3.50f, 4.10f }, - .scale = { 1.f, 1.f, 1.f }, - }); - - robot_model.set( - { .color = { 1.f, 1.f, 1.f, 1.f }, - .model_path = "assets/models/cube.obj", - .diffuse = "assets/models/container_diffuse.png", - .specular = "assets/models/container_specular.png" }); - - robot_model.set({ - .half_extent = { 1.f, 1.f, 1.f }, - }); - robot_model.set({ - // .restitution = 1.f, - .body_movement_type = atlas::dynamic, - }); - - atlas::game_object platform = entity("Platform"); - - platform.set({ - .scale = { 15.f, 0.30f, 10.0f }, - }); - platform.set({ - .model_path = "assets/models/cube.obj", - .diffuse = "assets/models/wood.png", - }); - platform.set({ - .body_movement_type = atlas::fixed, - }); - platform.set({ - .half_extent = { 15.f, 0.30f, 10.0f }, - }); - - atlas::game_object point_light = entity("Point Light 1"); - point_light.set({ - .position = { 0.f, 2.10f, -7.30f }, - .scale = { 0.9f, 0.9f, 0.9f }, - }); - point_light.add(); - - /* - for(size_t i = 0; i < 26; i++) { - auto obj = entity(std::format("Object #{}", i)); - obj.set({ - .restitution = 1.25f, - .body_movement_type = atlas::dynamic, - }); - - obj.set( - { - .radius = 1.0f, - }); - - glm::vec3 pos = {float(0*1.4),float(0 * 1.4),float(0 * -3) }; - - obj.set({ - .position = pos, - .rotation = {.3f, 0.0f, 0.0f}, - }); - - obj.set({ - .model_path = "assets/models/Ball OBJ.obj", - .diffuse = "assets/models/clear.png", - }); - } - */ - - m_editor_dockspace.fullscreen(false); - m_editor_dockspace.dockspace_open(true); - - atlas::game_object gerald = entity("Gerald"); - gerald.add(); - - // TODO: Move this outside of level_scene - m_deserializer_test = atlas::serializer(); - - subscribe(this, - &level_scene::collision_enter); atlas::register_start(this, &level_scene::start); atlas::register_physics(this, &level_scene::physics_update); atlas::register_update(this, &level_scene::on_update); - atlas::register_ui(this, &level_scene::on_ui_update); - - // Just loading a default icon that has a white texture - // TODO: This should be considered handled differently. - vk::image_extent extent = { - .width = 1, - .height = 1, - }; - m_default_material_icon.specular = ui::experimental::icon( - m_device, m_physical.memory_properties(), extent); - m_default_material_icon.diffuse = ui::experimental::icon( - m_device, m_physical.memory_properties(), extent); - - // TEMP: This is for testing if the triggered event only occurs once - // whenever a signal occurs. This should be moved to the internal - // application... OR the renderer - // trigger(this, &level_scene::reload_mesh); - - vk::texture_info config_texture = { - .phsyical_memory_properties = m_physical.memory_properties(), - .filepath = std::filesystem::path("assets/icons/PlayButton.png"), - }; - m_play_button = vk::texture( - atlas::vulkan::instance_context::logical_device(), config_texture); - if (!m_play_button.loaded()) { - console_log_info("Play Button Could not be loaded!!"); - } - config_texture = { - .phsyical_memory_properties = m_physical.memory_properties(), - .filepath = std::filesystem::path("assets/icons/StopButton.png"), - }; - m_stop_button = vk::texture(m_device, config_texture); - if (!m_stop_button.loaded()) { - console_log_info("Stop Button Could not be loaded!!"); - } - - m_play_button_id = static_cast(ImGui_ImplVulkan_AddTexture( - m_play_button.image().sampler(), - m_play_button.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - m_stop_button_id = static_cast(ImGui_ImplVulkan_AddTexture( - m_stop_button.image().sampler(), - m_stop_button.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - - m_content_browser = - content_browser_panel(m_device, m_physical.memory_properties()); - - atlas::vulkan::instance_context::submit_resource_free([this]() { - m_play_button.destroy(); - m_stop_button.destroy(); - for (auto& [key, value] : m_material_icons) { - value.specular.destroy(); - value.diffuse.destroy(); - } - - m_default_material_icon.specular.destroy(); - m_default_material_icon.diffuse.destroy(); - - m_content_browser.destroy(); - }); } ~level_scene() override = default; void start() { - m_deserializer_test = atlas::serializer(); - - if (!m_deserializer_test.load("LevelScene", *this)) { - console_log_error("Could not load yaml file LevelScene!!!"); - } - - flecs::world registry = *this; - - // TODO: Should consider having this be a custom UI property to the - // editor. - auto viking_room = entity("Viking Room"); - atlas::mesh_source* src = viking_room.get_mut(); - src->flip = true; - m_physics_engine = atlas::physics::engine(registry, *event_handle()); + console_log_info("preload_start invoked!"); } - void on_update(float p_delta_time) { - auto query_cameras = - query_builder().build(); - float dt = p_delta_time; - - query_cameras.each([this, dt](atlas::perspective_camera& p_camera, - atlas::transform& p_transform) { - if (!p_camera.is_active) { - return; - } - - float default_speed = 10.f; // current default movement speed that - // does not applied modified speed - float rotation_speed = 1.f; - float velocity = default_speed * dt; - if (atlas::event::is_mouse_pressed(mouse_button_middle)) { - velocity = m_movement_speed * dt; - } - float rotation_velocity = rotation_speed * dt; - - glm::quat to_quaternion = atlas::to_quat(p_transform.quaternion); - - glm::vec3 up = glm::rotate(to_quaternion, atlas::math::up()); - glm::vec3 forward = - glm::rotate(to_quaternion, atlas::math::backward()); - glm::vec3 right = glm::rotate(to_quaternion, atlas::math::right()); - - if (atlas::event::is_key_pressed(key_left_shift)) { - p_transform.position += up * velocity; - } - - if (atlas::event::is_key_pressed(key_space)) { - p_transform.position -= up * velocity; - } - - if (atlas::event::is_key_pressed(key_w)) { - p_transform.position += forward * velocity; - } - if (atlas::event::is_key_pressed(key_s)) { - p_transform.position -= forward * velocity; - } - - if (atlas::event::is_key_pressed(key_d)) { - p_transform.position += right * velocity; - } - if (atlas::event::is_key_pressed(key_a)) { - p_transform.position -= right * velocity; - } - - if (atlas::event::is_key_pressed(key_q)) { - p_transform.rotation.y += rotation_velocity; - } - if (atlas::event::is_key_pressed(key_e)) { - p_transform.rotation.y -= rotation_velocity; - } - - p_transform.set_rotation(p_transform.rotation); - }); - } - - void on_ui_update() { - // setting up the dockspace UI widgets at the window toolbar - if (m_editor_dockspace.begin()) { - try { - m_editor_menu.begin(); - } - catch (const atlas::ui::menu_bar_exception& e) { - } - - if (ImGui::BeginMenu("File")) { - if (ImGui::MenuItem("Save")) { - } - - ImGui::Separator(); - - if (ImGui::MenuItem("Exit")) { - } - - ImGui::EndMenu(); - } - - m_editor_menu.end(); - } - ImGuiID dockspace_id = ImGui::GetID("Dockspace Demo"); - ImGui::SetNextWindowDockID(dockspace_id, ImGuiCond_FirstUseEver); - if (ImGui::Begin("Viewport")) { - ImVec2 viewport_size = ImGui::GetContentRegionAvail(); - ImGui::Image(atlas::vulkan::g_viewport_image_id, viewport_size); - ImGui::End(); - } - - defer_begin(); - auto query_builder = this->query_builder().build(); - - if (ImGui::Begin("Scene Heirarchy")) { - // @note right click on blank space - // @param string_id - // @param popup_flags - will be the mouse flag (0=right, 1=left) - if (atlas::ui::begin_popup_context_window(nullptr, 1, false)) { - if (ImGui::MenuItem("Create Empty Entity")) { - m_current_entity = entity("Empty Entity"); - } - ImGui::EndPopup(); - } - - query_builder.each([&](flecs::entity p_entity, atlas::transform&) { - // We set the imgui flags for our scene heirarchy panel - // TODO -- Make the scene heirarchy panel a separate class that - // is used for specify the layout and other UI elements here - ImGuiTreeNodeFlags flags = - ((m_selected_entity == p_entity) ? ImGuiTreeNodeFlags_Selected - : 0) | - ImGuiTreeNodeFlags_OpenOnArrow; - flags |= ImGuiTreeNodeFlags_SpanAvailWidth; - flags |= ImGuiWindowFlags_Popup; - flags |= ImGuiTreeNodeFlags_AllowItemOverlap; - - bool opened = ImGui::TreeNodeEx(p_entity.name().c_str(), flags); - - if (ImGui::IsItemClicked()) { - m_selected_entity = p_entity; - } - - bool delete_entity = false; - if (ImGui::BeginPopupContextItem()) { - if (ImGui::MenuItem("Delete Entity")) { - delete_entity = true; - } - ImGui::EndPopup(); - } - - if (delete_entity) { - m_selected_entity.destruct(); - } - - ImGui::SameLine(); - ImGui::TextDisabled("(%llu)", p_entity.id()); - - if (opened) { - flags = ImGuiTreeNodeFlags_OpenOnArrow | - ImGuiTreeNodeFlags_SpanAvailWidth; - auto query_children_builder = - this->query_builder() - .with(flecs::ChildOf, p_entity) - .build(); - int32_t child_count = query_children_builder.count(); - - // // Only show children in scene heirarchy panel if there - // are children entities - if (child_count > 0) { - m_selected_entity.children([&](flecs::entity p_child) { - opened = - ImGui::TreeNodeEx(p_child.name().c_str(), flags); - if (opened) { - if (ImGui::IsItemClicked()) { - m_selected_entity = p_child; - } - ImGui::TreePop(); - } - }); - } - - ImGui::TreePop(); - } - }); - - defer_end(); - ImGui::End(); - } - - if (ImGui::Begin("Properties")) { - if (m_selected_entity.is_alive()) { - ui_component_list(m_selected_entity); - - atlas::ui::draw_component( - "transform", - m_selected_entity, - [](atlas::transform* p_transform) { - atlas::ui::draw_vec3("Position", p_transform->position); - atlas::ui::draw_vec3("Scale", p_transform->scale); - atlas::ui::draw_vec3("Rotation", p_transform->rotation); - }); - - atlas::ui::draw_component( - "camera", - m_selected_entity, - [this](atlas::perspective_camera* p_camera) { - atlas::ui::draw_float("field of view", - p_camera->field_of_view); - ImGui::Checkbox("is_active", &p_camera->is_active); - ImGui::DragFloat("Speed", &m_movement_speed); - }); - - atlas::ui::draw_component( - "atlas::mesh_source", - m_selected_entity, - [this](atlas::mesh_source* p_source) { - if (ImGui::InputText( - "Input Label", - &p_source->model_path, - ImGuiInputTextFlags_EnterReturnsTrue)) { - console_log_info("mesh_src = {}", - p_source->model_path); - atlas::event::mesh_reload reload_request = { - .entity_id = m_selected_entity.id(), - .filename = p_source->model_path, - }; - - if (std::filesystem::exists(p_source->model_path)) { - signal(reload_request); - } - } - atlas::ui::draw_vec4("Color", p_source->color); - - if (ImGui::Button("Reload Material")) { - atlas::event::material_reload - reload_material_request = { - .entity_id = m_selected_entity.id(), - .diffuse = "assets/models/viking_room.png", - .specular = "", - }; - - signal(reload_material_request); - } - }); - - atlas::ui::draw_component( - "material", - m_selected_entity, - [this](atlas::material_metadata* p_source) { - // We only want to load in our material textures If - // requested - // TODO: Move this log outside from the add component - // logic. This should be automatically done rather then - // explictly requested - if (!m_material_icons.contains(m_selected_entity.id())) { - if (m_selected_entity.has()) { - material new_mat = {}; - const auto* src = - m_selected_entity.get(); - if (std::filesystem::exists(src->specular)) { - new_mat.specular = ui::experimental::icon( - m_device, - m_physical.memory_properties(), - std::filesystem::path(src->specular)); - } - else { - vk::image_extent extent = { - .width = 1, - .height = 1, - }; - new_mat.specular = ui::experimental::icon( - m_device, - m_physical.memory_properties(), - extent); - } - - if (std::filesystem::exists(src->diffuse)) { - new_mat.diffuse = ui::experimental::icon( - m_device, - m_physical.memory_properties(), - std::filesystem::path(src->diffuse)); - } - else { - console_log_info("Diffuse (white) Path"); - vk::image_extent extent = { - .width = 1, - .height = 1, - }; - new_mat.diffuse = ui::experimental::icon( - m_device, - m_physical.memory_properties(), - extent); - } - - m_material_icons.emplace(m_selected_entity.id(), - new_mat); - } - } - - float speed = 0.01f; - ImGui::DragFloat4( - "Ambient", glm::value_ptr(p_source->ambient), speed); - ImGui::DragFloat4( - "Diffuse", glm::value_ptr(p_source->diffuse), speed); - ImGui::DragFloat4( - "Specular", glm::value_ptr(p_source->specular), speed); - atlas::ui::draw_float("Shininess", p_source->shininess); - }); - - atlas::ui::draw_component( - "Point Light", - m_selected_entity, - [](atlas::point_light* p_dir_light) { - ImGui::DragFloat4( - "Color", glm::value_ptr(p_dir_light->color), 0.01); - ImGui::DragFloat( - "Attenuation", &p_dir_light->attenuation, 0.001); - ImGui::DragFloat4( - "Ambient", glm::value_ptr(p_dir_light->ambient), 0.01); - ImGui::DragFloat4( - "Diffuse", glm::value_ptr(p_dir_light->diffuse), 0.01); - ImGui::DragFloat4("Specular", - glm::value_ptr(p_dir_light->specular), - 0.01); - ImGui::DragFloat( - "Constant", &p_dir_light->constant, 0.01); - ImGui::DragFloat("Linear", &p_dir_light->linear, 0.01); - ImGui::DragFloat( - "Quadratic", &p_dir_light->quadratic, 0.01); - }); - - atlas::ui::draw_component( - "Physics Body", - m_selected_entity, - [](atlas::physics_body* p_body) { - std::array items = { - "Static", - "Kinematic", - "Dynamic", - }; - std::string combo_preview = - items[p_body->body_movement_type]; - - // Begin the combo box - if (ImGui::BeginCombo("Body Type", - combo_preview.data())) { - for (int n = 0; n < 3; n++) { - // Check if the current item is selected - const bool is_selected = - (p_body->body_movement_type == n); - if (ImGui::Selectable(items[n].data(), - is_selected)) { - // Update the current type when a new item is - // selected - p_body->body_movement_type = - static_cast(n); - } - - // Set the initial focus when the combo box is - // first opened - if (is_selected) { - ImGui::SetItemDefaultFocus(); - } - } - ImGui::EndCombo(); - } - - // physics body parameters - atlas::ui::draw_vec3("Linear Velocity", - p_body->linear_velocity); - atlas::ui::draw_vec3("Angular Velocity", - p_body->angular_velocity); - atlas::ui::draw_vec3("Force", p_body->force); - atlas::ui::draw_vec3("Impulse", p_body->impulse); - atlas::ui::draw_vec3("Torque", p_body->torque); - atlas::ui::draw_vec3("Center Mass", - p_body->center_mass_position); - }); - - atlas::ui::draw_component( - "Box Collider", - m_selected_entity, - [](atlas::box_collider* p_collider) { - atlas::ui::draw_vec3("Half Extent", - p_collider->half_extent); - }); - - atlas::ui::draw_component( - "Box Collider", - m_selected_entity, - [](atlas::sphere_collider* p_collider) { - atlas::ui::draw_float("Radius", p_collider->radius); - }); - - atlas::ui::draw_component( - "Box Collider", - m_selected_entity, - [](atlas::capsule_collider* p_collider) { - atlas::ui::draw_float("Half Height", - p_collider->half_height); - atlas::ui::draw_float("Radius", p_collider->radius); - }); - - atlas::ui::draw_component( - "Serialize", - m_selected_entity, - [](atlas::tag::serialize* p_serialize) { - ImGui::Checkbox("Enable", &p_serialize->enable); - }); - } - - ImGui::End(); - - // Material Properties Panel - // TODO: Make this an abstraction to map out the materials - - if (ImGui::Begin("Material Editor")) { - - // Specular - if (ImGui::BeginChild("Specular", ImVec2(150, 200), true)) { - if (m_material_icons.contains(m_selected_entity.id())) { - ImGui::Text("Specular"); - ImGui::Separator(); - const auto specular_icon = - m_material_icons[m_selected_entity.id()].specular; - ImGui::Text("size = %d x %d", - specular_icon.width(), - specular_icon.height()); - ImGui::Image(specular_icon.texture_id(), - ImVec2(128, 128)); - } - else { - const auto specular_icon = - m_default_material_icon.specular; - ImGui::Text("size = %d x %d", - specular_icon.width(), - specular_icon.height()); - ImGui::Image(specular_icon.texture_id(), - ImVec2(128, 128)); - } - ImGui::EndChild(); - - // Diffuse - ImGui::Spacing(); - if (ImGui::BeginChild("Diffuse", ImVec2(150, 200), true)) { - ImGui::Text("Diffuse"); - ImGui::Separator(); - if (m_material_icons.contains(m_selected_entity.id())) { - const auto diffuse_icon = - m_material_icons[m_selected_entity.id()].diffuse; - ImGui::Text("size = %d x %d", - diffuse_icon.width(), - diffuse_icon.height()); - ImGui::Image(diffuse_icon.texture_id(), - ImVec2(128, 128)); - } - else { - const auto diffuse_icon = - m_default_material_icon.diffuse; - ImGui::Text("size = %d x %d", - diffuse_icon.width(), - diffuse_icon.height()); - ImGui::Image(diffuse_icon.texture_id(), - ImVec2(128, 128)); - } - ImGui::EndChild(); - } - } - - ImGui::End(); - } - } - - ui_toolbar(); - - m_content_browser.run(); - - m_editor_dockspace.end(); - } - - void ui_toolbar() { - ImGui::PushStyleVar( - ImGuiStyleVar_WindowPadding, - ImVec2(0, 2)); // @note ImVec making button not touch bottom - ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2(0, 2)); - ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - - auto& color = ImGui::GetStyle().Colors; - auto& buttonHovered = color[ImGuiCol_ButtonHovered]; - auto& buttonActive = color[ImGuiCol_ButtonActive]; - ImGui::PushStyleColor( - ImGuiCol_ButtonHovered, - ImVec4(buttonHovered.x, buttonHovered.y, buttonHovered.z, 0.5f)); - ImGui::PushStyleColor( - ImGuiCol_ButtonHovered, - ImVec4(buttonActive.x, buttonActive.y, buttonActive.z, 0.5f)); - - float button_size = 20.0f; - ImGui::Begin("##toolbox"); - - ImTextureID button_id = (m_scene_state == scene_runtime::edit) - ? m_play_button_id - : m_stop_button_id; - - // @note GetWindowContentRegionMax().x is how much space is there for - // content (widgets) - // @note 0.5f is the offset for padding. - // @note takes button size and halves it and makes the offset the center - // of that tab. (centering buttons) - ImGui::SameLine((ImGui::GetWindowContentRegionMax().x * 0.5f) - - (button_size * 0.5f)); - - if (ImGui::ImageButton("##Button", - button_id, - ImVec2{ button_size, button_size }, - ImVec2(0, 0), - ImVec2(1, 1))) { - if (m_scene_state == scene_runtime::edit) { - m_scene_state = scene_runtime::play; - m_physics_engine.start(); - } - else if (m_scene_state == scene_runtime::play) { - m_scene_state = scene_runtime::edit; - m_physics_engine.stop(); - reset_objects(); - } - } - - ImGui::PopStyleVar(2); - ImGui::PopStyleColor(3); - ImGui::End(); + void on_update(float) { + console_log_info("on_update invoked!"); } void physics_update() { - // TODO: Replace delta_time with physics fixed-timestep instead - float dt = atlas::application::delta_time(); - auto viking_room = entity("Viking Room"); - - atlas::physics_body* sphere_body = - viking_room.get_mut(); - // U = +up - // J = -up - // H = +left - // L = -Left - if (atlas::event::is_key_pressed(key_space)) { - glm::vec3 linear_velocity = { 0.f, 10.0f, 0.f }; - sphere_body->linear_velocity = linear_velocity; - sphere_body->impulse = linear_velocity; - } - - if (atlas::event::is_key_pressed(key_j)) { - glm::vec3 angular_vel = { -10.f, 0.f, 0.f }; - sphere_body->angular_velocity = angular_vel; - } - - if (atlas::event::is_key_pressed(key_h)) { - glm::vec3 angular_vel = { 10.f, 0.f, 0.f }; - sphere_body->angular_velocity = angular_vel; - } - - if (atlas::event::is_key_pressed(key_l)) { - glm::vec3 angular_vel = { -0.1f, 0.f, 0.f }; - sphere_body->angular_velocity = angular_vel; - } - - if (m_scene_state == scene_runtime::play) { - m_physics_engine.update(dt); - } + console_log_info("physics_update invoked!"); } - - void reset_objects() { - if (!m_deserializer_test.load("LevelScene", *this)) { - console_log_error("Could not load yaml file LevelScene!!!"); - } - } - -private: - void collision_enter(atlas::event::collision_enter& p_event) { - console_log_warn("collision_enter event!!!"); - atlas::game_object e1 = entity(p_event.entity1); - atlas::game_object e2 = entity(p_event.entity2); - - console_log_warn("Entity1 = {}", e1.name().c_str()); - console_log_warn("Entity2 = {}", e2.name().c_str()); - } - - void collision_persisted(atlas::event::collision_persisted& p_event) { - console_log_warn("collision_persisted(p_event) invoked!!"); - atlas::game_object e1 = entity(p_event.entity1); - atlas::game_object e2 = entity(p_event.entity2); - - console_log_warn("Entity1 = {}", e1.name().c_str()); - console_log_warn("Entity2 = {}", e2.name().c_str()); - } - -private: - VkDevice m_device; - atlas::vulkan::physical_device m_physical; - atlas::serializer m_deserializer_test; - flecs::entity m_selected_entity; - - atlas::game_object_optional m_current_entity; - float m_movement_speed = 10.f; - - atlas::physics::engine m_physics_engine; - - atlas::ui::dockspace m_editor_dockspace; - atlas::ui::menu_item m_editor_menu; - // ui::experimental::icon m_default_icon; - material m_default_material_icon; - - scene_runtime m_scene_state = scene_runtime::edit; - vk::texture m_play_button; - vk::texture m_stop_button; - ImTextureID m_play_button_id; - ImTextureID m_stop_button_id; - - content_browser_panel m_content_browser; - - std::unordered_map m_material_icons; - - // Note -- Added this temporarily - // ImFont* m_font; }; \ No newline at end of file From 81d8924eedb98b906d73e9c0278524881e3f1909 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 15:22:10 -0700 Subject: [PATCH 004/106] WIP: removed altas::vk::swapchain in replacing with vk::swapchain --- atlas/core/application.cppm | 4 ++++ atlas/core/window.cppm | 31 +++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 247c6900..e3dcf344 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -267,10 +267,14 @@ export namespace atlas { while(m_window->available()) { event::flush_events(); } + + m_device->wait(); } void post_destroy() { std::println("Post destroy!"); + m_window->destruct(); + m_device->destruct(); } private: diff --git a/atlas/core/window.cppm b/atlas/core/window.cppm index 4eaf741c..04d3489b 100644 --- a/atlas/core/window.cppm +++ b/atlas/core/window.cppm @@ -18,6 +18,7 @@ module; #endif #include +#include export module atlas.window; @@ -147,13 +148,31 @@ export namespace atlas { m_surface = std::make_shared(p_context->instance_handle(), m_window); center_window(); + vk::swapchain_params swapchain_params = { + .width = static_cast(m_params.width), + .height = static_cast(m_params.height), + .present_index = 0, + }; + const VkSurfaceKHR surface = *m_surface; + m_swapchain = std::make_shared(*p_context->logical_device(), surface, swapchain_params, p_context->physical_device().request_surface(surface)); - graphics_context::submit_resource_free([this](){ - std::println("atlas::window submit resource free"); - // m_surface->destruct(); - }); + + // graphics_context::submit_resource_free([this](){ + // std::println("atlas::window submit resource free"); + // // m_swapchain.destruct(); + // }); + } + + ~window() { + // glfwDestroyWindow(m_window); + m_surface->destruct(); + glfwDestroyWindow(m_window); + } + + void destruct() { + m_swapchain->destruct(); } GLFWwindow* glfw_window() const { return m_window; } @@ -168,6 +187,9 @@ export namespace atlas { static_cast(height)); } + void present(std::span p_commands) { + } + [[nodiscard]] bool available() const { return !glfwWindowShouldClose(m_window); } @@ -176,6 +198,7 @@ export namespace atlas { vk::instance m_instance; std::shared_ptr m_device=nullptr; std::shared_ptr m_surface; + std::shared_ptr m_swapchain; GLFWwindow* m_window = nullptr; window_params m_params{}; }; From 67b32860c7df68f20cb9df5cda2e94a46b79235d Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 16:21:02 -0700 Subject: [PATCH 005/106] Refactor: Dyanmic rendering to change background color. Continue making more progress --- atlas/core/application.cppm | 383 +++++++++++++++----------------- atlas/core/entry_point/main.cpp | 12 - atlas/core/window.cppm | 35 ++- 3 files changed, 216 insertions(+), 214 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index e3dcf344..4d3f0fed 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -13,9 +13,11 @@ module; #include #include +#include #include #include #include +#include export module atlas.application; @@ -38,205 +40,6 @@ export namespace atlas { glm::vec4 background_color = { 1.f, 0.5f, 0.5f, 1.f }; }; - /** - * @brief represents a single application that gets created by the engine - * internally - * - * There is only ever going to be one application tied to the engine's - * runtime. As the application is given responsibilities of preloading, - * pre-initialization any sort of utilities required by the engine, and any - * form of post-cleanup when the user requests the application to close. - * - */ - // class application { - // public: - // /** - // * @brief constructs a new application - // * @param p_settings is the specific application settings to - // configure - // * how the application may be setup - // */ - // application(/*NOLINT*/ ref p_context, - // const application_settings& p_params, - // event::bus& p_bus) - // : m_bus(&p_bus) { - // console_log_info( - // "application(const application_settings&) initialized!!!"); - - // window_params params = { - // .width = p_params.width, - // .height = p_params.height, - // .name = p_params.name, - // }; - // m_window = - // initialize_window(p_context, params, graphics_api::vulkan); - // // m_initial_window_params = m_window->data(); - // event::set_window_size(static_cast(*m_window)); - - // // m_renderer = - // // initialize_renderer(p_context, - // // graphics_api::vulkan, - // // params, - // // m_window->current_swapchain().image_size(), - // // "Renderer"); - // // m_renderer->set_background_color(p_params.background_color); - - // // m_ui_context = vulkan::imgui_context( - // // p_context->handle(), m_window->current_swapchain(), - // *m_window); - - // // p_context->submit_resource_free( - // // [this]() { m_ui_context.destroy(); }); - - // s_instance = this; - - // // Setting internal-level listeners for specific events - // m_bus->create_listener(); - // m_bus->create_listener(); - // m_bus->create_listener(); - // m_bus->create_immediate_listener(); - // m_bus->create_immediate_listener(); - - // m_bus->trigger(this, - // &application::reload_mesh); - // m_bus->trigger( - // this, &application::reload_material); - // } - - // ~application() { m_window->close(); } - - // /** - // * @return the delta time as a float for giving you the timestep - // every - // * frame - // */ - // static float delta_time() { return s_instance->m_delta_time; } - - // /** - // * @brief Explicitly is used to execute the application's mainloop - // */ - // void execute() { - // console_log_info("Executing game mainloop!!!"); - - // auto start_time = std::chrono::high_resolution_clock::now(); - - // ref current_scene = m_current_world->current(); - - // invoke_start(current_scene.get()); - - // while (m_window->available()) { - // auto current_time = - // std::chrono::high_resolution_clock::now(); m_delta_time = - // std::chrono::duration( - // current_time - start_time) - // .count(); - // start_time = current_time; - - // event::flush_events(); - - // // Progresses the flecs::world by one tick (or replaced with - // // using the delta time) This also invokes the following - // // system call before the mainloop - // current_scene->progress(m_delta_time); - - // m_current_frame_index = m_window->acquired_next_frame(); - - // // Current commands that are going to be iterated through - // // Use the acquired swapchain image index for the command - // buffer - // // and swapchain framebuffer so we record and present the - // same - // // image. - // vk::command_buffer currently_active = - // m_window->active_command(m_current_frame_index); - - // // invoke_physics_update(current_scene.get()); - - // // invoke_on_update(current_scene.get(), m_delta_time); - - // // invoke_defer_update(current_scene.get()); - - // // m_ui_context.begin(currently_active, - // m_current_frame_index); - - // // invoke_ui_update(current_scene.get()); - - // std::array commands = { - // currently_active, - // }; - // m_window->current_swapchain().submit(commands); - - // m_window->present(m_current_frame_index); - // } - // } - - // /** - // * @brief Performs any post cleanup when user requests the - // application - // * to close - // */ - // void post_destroy() { console_log_info("Executing post cleanup!!!"); - // } - - // /** - // * @brief we only ever have one window - // * - // * This static function was a means to getting access to the window - // to - // * perform any operations or request any data the window may have to - // * provide - // */ - // // static window& get_window() { return *s_instance->m_window; } - - // /* Retrieves the current selected graphics API */ - // /** - // * @return the currently specified API. - // */ - // static graphics_api current_api() { return graphics_api::vulkan; } - - // /* Returns the currently selected swapchain */ - // /** - // * @brief gives you the current swapchain handle - // * - // * TODO: This is not actually needed, and should be removed - // */ - // VkSwapchainKHR get_current_swapchain() { - // return m_window->current_swapchain(); - // } - - // void current_world(ref p_world) { m_current_world = p_world; } - - // void reload_mesh(event::mesh_reload&) { - // console_log_info( - // "application::trigger invoked from core/application!"); - // } - - // void reload_material(event::material_reload&) { - // console_log_info( - // "application::trigger invoked from - // core/application!"); - // } - - // protected: - // [[nodiscard]] ref renderer_instance() const { - // // return m_renderer; - // return nullptr; - // } - - // private: - // float m_delta_time = 0.f; - // ref m_current_world; - // ref m_window; - // // window_params m_initial_window_params; - // // ref m_renderer = nullptr; - // glm::mat4 m_projection; - // glm::mat4 m_view; - // uint32_t m_current_frame_index = -1; - // // vulkan::imgui_context m_ui_context; - // event::bus* m_bus = nullptr; - // static application* s_instance; - // }; - class application { public: application() = default; @@ -255,17 +58,181 @@ export namespace atlas { .height = p_params.height, .name = p_params.name, }; + m_extent = { + .width = p_params.width, + .height = p_params.height, + }; // m_window = std::allocate_shared(, m_context->instance_handle(), params); m_window = std::make_shared(p_context, params); + // Requesting depth format + std::array format_support = { + vk::format::d32_sfloat, + vk::format::d32_sfloat_s8_uint, + vk::format::d24_unorm_s8_uint + }; + + // We provide a selection of format support that we want to check is + // supported on current hardware device. + m_depth_format = m_physical->request_depth_format(format_support); + + // Initializing command buffers + std::span images = m_window->request_images(); + + m_images.resize(images.size()); + m_depth_images.resize(images.size()); + + for(uint32_t i = 0; i < m_images.size(); i++) { + vk::image_params color_img_params = { + .extent = { + .width = p_params.width, + .height = p_params.height, + }, + .format = m_window->surface_properties().format.format, + .memory_mask = m_physical->memory_properties( + vk::memory_property::device_local_bit), + .aspect = vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::color_attachment_bit, + .mip_levels = 1, + .layer_count = 1, + }; + m_images[i] = vk::sample_image(*m_device, images[i], color_img_params); + + vk::image_params depth_img_params = { + .extent = { + .width = p_params.width, + .height = p_params.height, + }, + .format = m_depth_format, + .memory_mask = m_physical->memory_properties( + vk::memory_property::device_local_bit), + .aspect = vk::image_aspect_flags::depth_bit, + .usage = vk::image_usage::depth_stencil_bit, + .mip_levels = 1, + .layer_count = 1, + }; + + m_depth_images[i] = vk::sample_image(*m_device, depth_img_params); + } + + m_command_buffers.resize(images.size()); + + for(uint32_t i = 0; i < m_command_buffers.size(); i++) { + vk::command_params command_params = { + .levels = vk::command_levels::primary, + .queue_index = 0, + .flags = vk::command_pool_flags::reset, + }; + m_command_buffers[i] = vk::command_buffer(*m_device, command_params); + } + + std::println("images.size() = {}", images.size()); + std::println("After constructing atlas::window"); } void execute() { std::println("Executing mainloop"); + VkClearValue clear_color = { + { 0.f, 0.5f, 0.5f, 1.f }, + }; + + VkClearValue depth_value = { + .depthStencil = { .depth = 1.f, .stencil = 0 }, + }; + while(m_window->available()) { event::flush_events(); + + m_next_image_frame_idx = m_window->acquire_next_frame(); + const auto current_extent = m_window->surface_properties().capabilities.currentExtent; + + vk::command_buffer current = m_command_buffers[m_next_image_frame_idx]; + + current.begin(vk::command_usage::simulatneous_use_bit); + + m_images[m_next_image_frame_idx].memory_barrier( + current, + m_window->surface_properties().format.format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + m_depth_images[m_next_image_frame_idx].memory_barrier( + current, + m_depth_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + + vk::rendering_attachment color_render_attachment = { + .image_view = m_images[m_next_image_frame_idx].image_view(), + .layout = vk::image_layout::color_optimal, + .resolve_mode = vk::resolved_mode_flags::none, + .resolve_image_view = nullptr, + .resolve_image_layout = vk::image_layout::undefined, + .load = vk::attachment_load::clear, + .store = vk::attachment_store::store, + .clear_values = clear_color + }; + + vk::rendering_attachment depth_stencil_attachment = { + .image_view = m_depth_images[m_next_image_frame_idx].image_view(), + .layout = vk::image_layout::depth_stencil_optimal, + .resolve_mode = vk::resolved_mode_flags::none, + .resolve_image_view = nullptr, + .resolve_image_layout = vk::image_layout::undefined, + .load = vk::attachment_load::clear, + .store = vk::attachment_store::store, + .depth_values = depth_value + }; + + vk::rendering_begin_parameters begin_params = { + .render_area = { { 0, 0 }, + { + current_extent.width, + current_extent.height, + }, }, + .layer_count = 1, + .color_attachments = std::span( + &color_render_attachment, 1), + .depth_attachment = depth_stencil_attachment, + .stencil_attachment = depth_stencil_attachment, + }; + + vk::viewport_params viewport = { + .x = 0.0f, + .y = 0.0f, + .width = static_cast(current_extent.width), + .height = static_cast(current_extent.height), + .min_depth = 0.0f, + .max_depth = 1.0f, + }; + current.set_viewport(0, 1, std::span(&viewport, 1)); + + vk::scissor_params scissor = { + .offset = { 0, 0 }, + .extent = current_extent, + }; + + current.set_scissor(0, 1, std::span(&scissor, 1)); + + current.begin_rendering(begin_params); + + // Do rendering stuff... + + current.end_rendering(); + + m_images[m_next_image_frame_idx].memory_barrier( + current, + m_window->surface_properties().format.format, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + current.end(); + + std::array commands = {current}; + m_window->submit(commands); + m_window->present(m_next_image_frame_idx); } m_device->wait(); @@ -273,16 +240,34 @@ export namespace atlas { void post_destroy() { std::println("Post destroy!"); + + for(auto& command : m_command_buffers) { + command.destruct(); + } + + for(auto& color_image : m_images) { + color_image.destruct(); + } + + for(auto& depth_image : m_depth_images) { + depth_image.destruct(); + } m_window->destruct(); m_device->destruct(); } private: + uint32_t m_next_image_frame_idx=0; + VkFormat m_depth_format; vk::instance m_instance; std::optional m_physical; std::shared_ptr m_device; std::shared_ptr m_context; std::shared_ptr m_window=nullptr; + vk::image_extent m_extent{}; + std::vector m_images; + std::vector m_depth_images; + std::vector m_command_buffers; event::bus* m_bus = nullptr; static application* s_instance; }; diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 891996d0..d35f86f0 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -124,16 +124,6 @@ main() { VK_KHR_SWAPCHAIN_EXTENSION_NAME, }; #endif - std::array format_support = { - vk::format::d32_sfloat, - vk::format::d32_sfloat_s8_uint, - vk::format::d24_unorm_s8_uint - }; - - // We provide a selection of format support that we want to check is - // supported on current hardware device. - VkFormat depth_format = - physical_device.request_depth_format(format_support); vk::device_features device_features{ vk::dynamic_rendering_feature{ { @@ -148,8 +138,6 @@ main() { .queue_family_index = 0, }; - // pmr::monotonic_memory_resource for allocation - std::array bytes{}; std::pmr::monotonic_buffer_resource memory_resource{ bytes.data(), bytes.size() }; diff --git a/atlas/core/window.cppm b/atlas/core/window.cppm index 04d3489b..ddd19a56 100644 --- a/atlas/core/window.cppm +++ b/atlas/core/window.cppm @@ -155,9 +155,14 @@ export namespace atlas { }; const VkSurfaceKHR surface = *m_surface; + m_surface_properties = p_context->physical_device().request_surface(surface); m_swapchain = std::make_shared(*p_context->logical_device(), surface, swapchain_params, p_context->physical_device().request_surface(surface)); - + vk::queue_params present_params = { + .family = 0, + .index = 0, + }; + m_present_queue = vk::device_present_queue(*p_context->logical_device(), *m_swapchain, present_params); // graphics_context::submit_resource_free([this](){ // std::println("atlas::window submit resource free"); @@ -166,13 +171,30 @@ export namespace atlas { } ~window() { - // glfwDestroyWindow(m_window); + // At the end of the lifetime of this window, we can destroy any + // resources that any of the concurrent resources this window + // owns is no longer using m_surface->destruct(); glfwDestroyWindow(m_window); } + [[nodiscard]] std::span request_images() const { + return m_swapchain->get_images(); + } + + [[nodiscard]] vk::surface_params surface_properties() const { return m_surface_properties; } + + + [[nodiscard]] uint32_t acquire_next_frame() { + return m_present_queue.acquire_next_image(); + } + void destruct() { + // Any dependent resources that must be invoked + // before the primary resources like VkSurfaceKHR + // are destructed m_swapchain->destruct(); + m_present_queue.destruct(); } GLFWwindow* glfw_window() const { return m_window; } @@ -187,7 +209,12 @@ export namespace atlas { static_cast(height)); } - void present(std::span p_commands) { + void submit(std::span p_commands) { + m_present_queue.submit_async(p_commands); + } + + void present(uint32_t p_frame_idx) { + m_present_queue.present_frame(p_frame_idx); } [[nodiscard]] bool available() const { @@ -199,6 +226,8 @@ export namespace atlas { std::shared_ptr m_device=nullptr; std::shared_ptr m_surface; std::shared_ptr m_swapchain; + vk::surface_params m_surface_properties; + vk::device_present_queue m_present_queue; GLFWwindow* m_window = nullptr; window_params m_params{}; }; From 8ac88b11d774f1e07f78b524f99252b1586ff4b8 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 16:30:55 -0700 Subject: [PATCH 006/106] Moved location for calling logical_device->wait() call --- atlas/core/application.cppm | 2 -- atlas/core/entry_point/main.cpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 4d3f0fed..f8c02c1f 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -234,8 +234,6 @@ export namespace atlas { m_window->submit(commands); m_window->present(m_next_image_frame_idx); } - - m_device->wait(); } void post_destroy() { diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index d35f86f0..3db6311d 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -157,6 +157,8 @@ main() { app->execute(); + logical_device->wait(); + app->post_destroy(); context->post_cleanup(); From 43fabb93a89da5208379856db78490b57caf7889 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 16:49:46 -0700 Subject: [PATCH 007/106] Removed old files that are not needed + removing redundant import dependencies from codebase --- CMakeLists.txt | 30 +- atlas/core/application.cppm | 6 +- atlas/core/entry_point/main.cpp | 16 +- atlas/core/utilities/types.cppm | 2 +- atlas/core/utilities/utilities.cppm | 3 +- atlas/drivers/drivers.cppm | 41 - atlas/drivers/renderer_system.cppm | 2 - atlas/drivers/vulkan/device.cppm | 215 ----- atlas/drivers/vulkan/environment_map.cppm | 7 +- .../{ => vulkan}/graphics_context.cppm | 2 +- atlas/drivers/vulkan/imgui_context.cppm | 3 - atlas/drivers/vulkan/mesh.cppm | 4 +- atlas/drivers/vulkan/physical_device.cppm | 253 ------ atlas/drivers/vulkan/render_system.cppm | 820 ------------------ atlas/drivers/vulkan/swapchain.cppm | 364 -------- atlas/drivers/vulkan/vulkan.cppm | 7 + atlas/{core => drivers/vulkan}/window.cppm | 6 +- atlas/drivers/vulkan/window_context.cppm | 134 --- atlas/renderer/context_loader.cppm | 26 - atlas/renderer/renderer.cppm | 22 - conanfile.py | 2 +- editor/application.cpp | 3 +- 22 files changed, 41 insertions(+), 1927 deletions(-) delete mode 100644 atlas/drivers/drivers.cppm delete mode 100644 atlas/drivers/vulkan/device.cppm rename atlas/drivers/{ => vulkan}/graphics_context.cppm (97%) delete mode 100644 atlas/drivers/vulkan/physical_device.cppm delete mode 100644 atlas/drivers/vulkan/swapchain.cppm create mode 100644 atlas/drivers/vulkan/vulkan.cppm rename atlas/{core => drivers/vulkan}/window.cppm (98%) delete mode 100644 atlas/drivers/vulkan/window_context.cppm delete mode 100644 atlas/renderer/context_loader.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f2ea08c..e57a95dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,7 +142,6 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/core/core.cppm atlas/core/logger.cppm atlas/core/application.cppm - atlas/core/window.cppm # math atlas/core/math/types.cppm @@ -179,21 +178,10 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/core/serialize/serializer.cppm # renderer - atlas/renderer/context_loader.cppm atlas/renderer/renderer.cppm - atlas/drivers/drivers.cppm - atlas/drivers/graphics_context.cppm - atlas/drivers/renderer_system.cppm - - atlas/drivers/vulkan/hash.cppm - atlas/drivers/vulkan/mesh.cppm - atlas/drivers/vulkan/shader_resource_group.cppm - atlas/drivers/vulkan/render_system.cppm - atlas/drivers/vulkan/uniforms.cppm - # imgui/UI atlas/drivers/vulkan/imgui_context.cppm atlas/core/ui/imgui_stdlib.cppm @@ -209,15 +197,19 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/jolt_cpp/contact_listener.cppm atlas/drivers/jolt_cpp/context.cppm - # drivers + # drivers/vulkan + atlas/drivers/vulkan/vulkan.cppm + atlas/drivers/vulkan/graphics_context.cppm + atlas/drivers/vulkan/window.cppm atlas/drivers/vulkan/utilities.cppm - atlas/drivers/vulkan/instance_context.cppm - atlas/drivers/vulkan/window_context.cppm - atlas/drivers/vulkan/physical_device.cppm - atlas/drivers/vulkan/device.cppm - atlas/drivers/vulkan/swapchain.cppm atlas/drivers/vulkan/environment_map.cppm - # atlas/drivers/vulkan/stb_image.cppm + atlas/drivers/vulkan/stb_image.cppm + + atlas/drivers/vulkan/hash.cppm + atlas/drivers/vulkan/mesh.cppm + atlas/drivers/vulkan/shader_resource_group.cppm + atlas/drivers/vulkan/render_system.cppm + atlas/drivers/vulkan/uniforms.cppm ) target_sources(${PROJECT_NAME} PUBLIC diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index f8c02c1f..0864992a 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -25,8 +25,7 @@ import atlas.core.utilities; import atlas.core.utilities.poll_state; import atlas.core.event; import vk; -import atlas.drivers.graphics_context; -import atlas.window; +import atlas.drivers.vulkan; export namespace atlas { @@ -219,8 +218,9 @@ export namespace atlas { current.begin_rendering(begin_params); - // Do rendering stuff... + + // Do rendering stuff... current.end_rendering(); m_images[m_next_image_frame_idx].memory_barrier( diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 3db6311d..bf03aaa1 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -21,8 +21,7 @@ import atlas.application; import atlas.common; import atlas.logger; import atlas.graphics_api; -import atlas.drivers.graphics_context; -import atlas.renderer.context_loader; +import atlas.drivers.vulkan; import atlas.core.event; import vk; @@ -87,12 +86,8 @@ main() { std::vector global_extensions = get_instance_extensions(); vk::debug_message_utility debug_callback_info = { - // .severity essentially takes in vk::message::verbose, - // vk::message::warning, vk::message::error .severity = vk::message::verbose | vk::message::warning | vk::message::error, - // .message_type essentially takes in vk::debug. Like: - // vk::debug::general, vk::debug::validation, vk::debug::performance .message_type = vk::debug::general | vk::debug::validation | vk::debug::performance, .callback = debug_callback @@ -100,11 +95,14 @@ main() { vk::application_params config = { .name = "vulkan instance", - .version = vk::api_version::vk_1_3, // specify to using vulkan 1.3 + // specify to using vulkan 1.4 + .version = vk::api_version::vk_1_4, + // .validation takes in a std::span .validations = - validation_layers, // .validation takes in a std::span + validation_layers, + // .extensions also takes in std::span .extensions = - global_extensions // .extensions also takes in std::span + global_extensions }; // 1. Setting up vk instance diff --git a/atlas/core/utilities/types.cppm b/atlas/core/utilities/types.cppm index 3c7b6f1d..d3a4e3e6 100644 --- a/atlas/core/utilities/types.cppm +++ b/atlas/core/utilities/types.cppm @@ -4,7 +4,7 @@ module; #include #include -export module atlas.core.utilities.types; +export module atlas.core.utilities:types; import vk; diff --git a/atlas/core/utilities/utilities.cppm b/atlas/core/utilities/utilities.cppm index 0261aff2..fbc783e5 100644 --- a/atlas/core/utilities/utilities.cppm +++ b/atlas/core/utilities/utilities.cppm @@ -2,6 +2,5 @@ export module atlas.core.utilities; export import atlas.logger; export import atlas.common; -export import atlas.graphics_api; -export import atlas.core.utilities.types; +export import :types; export import atlas.core.utilities.state; diff --git a/atlas/drivers/drivers.cppm b/atlas/drivers/drivers.cppm deleted file mode 100644 index 5e3608ca..00000000 --- a/atlas/drivers/drivers.cppm +++ /dev/null @@ -1,41 +0,0 @@ -module; - -#include - -export module atlas.drivers; - -import atlas.core.utilities; -import atlas.window; -import atlas.drivers.graphics_context; -import atlas.drivers.vulkan.window_context; - -/** - * @brief This drivers.cppm will contain API-agnostic implementation that may be - * widely implemented differently. - * - * Such as Window contexts, graphics API-agnostic implementation, renderers, - * etc. - */ - -export namespace atlas { - /** - * @brief constructs an atlas::window - * - * There should only ever be one window constructed throughout the entire - * application - * - * @param p_settings is the window settings to construct the window with - * - * @return shared_ptr - */ - // ref initialize_window(ref p_context, - // const window_params& p_params, - // graphics_api p_api) { - // switch (p_api) { - // case graphics_api::vulkan: - // return create_ref(p_context, p_params); - // default: - // return nullptr; - // } - // } -}; \ No newline at end of file diff --git a/atlas/drivers/renderer_system.cppm b/atlas/drivers/renderer_system.cppm index bf6dc842..fef82ec0 100644 --- a/atlas/drivers/renderer_system.cppm +++ b/atlas/drivers/renderer_system.cppm @@ -7,8 +7,6 @@ module; export module atlas.drivers.renderer_system; -// import atlas.core.utilities.types; -// import atlas.common; import atlas.core.utilities; import atlas.core.scene; import vk; diff --git a/atlas/drivers/vulkan/device.cppm b/atlas/drivers/vulkan/device.cppm deleted file mode 100644 index d333eae8..00000000 --- a/atlas/drivers/vulkan/device.cppm +++ /dev/null @@ -1,215 +0,0 @@ -module; - -#include - -#define GLFW_INCLUDE_VULKAN -#if _WIN32 -#define VK_USE_PLATFORM_WIN32_KHR -#include -#define GLFW_EXPOSE_NATIVE_WIN32 -#include -#include -#else -#include -#include -#endif - -#include -#include - -export module atlas.drivers.vulkan.device; - -import atlas.drivers.vulkan.utilities; -import atlas.drivers.vulkan.physical_device; - -namespace atlas::vulkan { - static VkFormat search_supported_depth_format( - const VkPhysicalDevice& p_physical, - std::span p_formats, - VkImageTiling p_tiling, - VkFormatFeatureFlags p_feature_flag) { - VkFormat format = VK_FORMAT_UNDEFINED; - - for (size_t i = 0; i < p_formats.size(); i++) { - VkFormat current_format = p_formats[i]; - VkFormatProperties format_properties; - vkGetPhysicalDeviceFormatProperties( - p_physical, current_format, &format_properties); - - if (p_tiling == VK_IMAGE_TILING_LINEAR) { - if (format_properties.linearTilingFeatures & p_feature_flag) { - format = current_format; - } - } - else if (p_tiling == VK_IMAGE_TILING_OPTIMAL and - format_properties.optimalTilingFeatures & p_feature_flag) { - format = current_format; - } - } - - return format; - } - - static VkFormat search_depth_format(const VkPhysicalDevice& p_physical) { - std::vector candidate_formats = { - VK_FORMAT_D32_SFLOAT, - VK_FORMAT_D32_SFLOAT_S8_UINT, - VK_FORMAT_D24_UNORM_S8_UINT - }; - - VkFormat format = search_supported_depth_format( - p_physical, - candidate_formats, - VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); - return format; - } - - /** - * @brief logical device implementation wrapper around the VkDevice - * - * This class was a wrapper around VKDevice, that provided you with other - * API's to do with that particular logical device. - * - * Logical devices are representation of virtual software ways to interact - * with the GPU through Vulkan specifications - * - * TODO: Out-of-date. Using vulkan-cpp ::vk::device class to provide API's - * that allow you to do more queries on specific attributes the logical - * device gives you. - */ - export class device { - struct device_queue_family { - VkQueue graphics_queue; - VkQueue transfer_queue; - VkQueue compute_queue; - }; - - public: - device() = default; - - /** - * @brief construct a new logical device - * @param p_physical is the physical device required for the creation of - * the logical device - */ - device(const physical_device& p_physical) - : m_physical(p_physical) { - m_depth_format_selected = search_depth_format(m_physical); - - float queue_priority[1] = { 0.0f }; - -#if defined(__APPLE__) - std::vector device_extension = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, "VK_KHR_portability_subset" - }; -#else - std::vector device_extension = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME - }; -#endif - - uint32_t graphics_index = - m_physical.read_queue_family_indices().graphics; - - VkDeviceQueueCreateInfo queue_create_info = { - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .queueFamilyIndex = graphics_index, - .queueCount = 1, - .pQueuePriorities = queue_priority, - }; - - VkDeviceCreateInfo create_info = { - .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, - .pNext = nullptr, - .flags = 0, - .queueCreateInfoCount = 1, - .pQueueCreateInfos = &queue_create_info, - .enabledLayerCount = 0, - .ppEnabledLayerNames = nullptr, - .enabledExtensionCount = - static_cast(device_extension.size()), - .ppEnabledExtensionNames = device_extension.data(), - }; - - VkPhysicalDeviceFeatures features; - vkGetPhysicalDeviceFeatures(m_physical, &features); - features.robustBufferAccess = false; - create_info.pEnabledFeatures = &features; - - vk_check( - vkCreateDevice(m_physical, &create_info, nullptr, &m_driver), - "vkCreateDevice"); - - vkGetDeviceQueue( - m_driver, graphics_index, 0, &m_device_queues.graphics_queue); - } - - // Use .destroy to explicitly invoke when to do proper vulkan cleanup - ~device() = default; - - /** - * @brief returns the specified graphics queue from this logical device - */ - [[nodiscard]] VkQueue graphics_queue() const { - return m_device_queues.graphics_queue; - } - - /** - * @return -1 if there are no flags available/compatible/valid - */ - uint32_t select_memory_type(uint32_t p_type_filter, - VkMemoryPropertyFlags p_property_flag) { - VkPhysicalDeviceMemoryProperties mem_props; - vkGetPhysicalDeviceMemoryProperties(m_physical, &mem_props); - - for (uint32_t i = 0; i < mem_props.memoryTypeCount; i++) { - if ((p_type_filter & (1 << i)) and - (mem_props.memoryTypes[i].propertyFlags & - p_property_flag) == p_property_flag) { - return i; - } - } - - return -1; - } - - void destroy() { - vkDeviceWaitIdle(m_driver); - vkDestroyDevice(m_driver, nullptr); - } - - /** - * @brief gives you the depth format from the logical device - * - * @return VkFormat - */ - [[nodiscard]] VkFormat depth_format() const { - return m_depth_format_selected; - } - - /** - * @brief allows to treat vk_driver as a VkDevice handle - * - * For vulkan API's that accept only taking in VKDevice, this simplifies - * the need to not have a getter API - */ - operator VkDevice() const { return m_driver; } - - /** - * @brief allows to treat vk_driver as a VkDevice handle - * - * For vulkan API's that accept only taking in VKDevice, this simplifies - * the need to not have a getter API - */ - operator VkDevice() { return m_driver; } - - private: - physical_device m_physical{}; - VkDevice m_driver = nullptr; - device_queue_family m_device_queues{}; - VkFormat m_depth_format_selected; - }; -}; diff --git a/atlas/drivers/vulkan/environment_map.cppm b/atlas/drivers/vulkan/environment_map.cppm index ff9716a4..46b97bf4 100644 --- a/atlas/drivers/vulkan/environment_map.cppm +++ b/atlas/drivers/vulkan/environment_map.cppm @@ -31,10 +31,10 @@ module; export module atlas.drivers.vulkan.environment_map; -import atlas.drivers.vulkan.physical_device; - import vk; + +/* namespace atlas { export struct skybox_uniform { @@ -597,4 +597,5 @@ namespace atlas { uint32_t m_vertices_size=0; }; -}; \ No newline at end of file +}; +*/ \ No newline at end of file diff --git a/atlas/drivers/graphics_context.cppm b/atlas/drivers/vulkan/graphics_context.cppm similarity index 97% rename from atlas/drivers/graphics_context.cppm rename to atlas/drivers/vulkan/graphics_context.cppm index 61f3405b..21fac22e 100644 --- a/atlas/drivers/graphics_context.cppm +++ b/atlas/drivers/vulkan/graphics_context.cppm @@ -19,7 +19,7 @@ module; #include #endif -export module atlas.drivers.graphics_context; +export module atlas.drivers.vulkan:graphics_context; import vk; diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 82d8d528..21bda947 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -14,9 +14,6 @@ export module atlas.drivers.vulkan.imgui_context; import atlas.common; import vk; -import atlas.drivers.vulkan.physical_device; -import atlas.drivers.vulkan.device; -import atlas.drivers.vulkan.swapchain; import atlas.core.utilities; namespace atlas::vulkan { diff --git a/atlas/drivers/vulkan/mesh.cppm b/atlas/drivers/vulkan/mesh.cppm index 82eb25a7..53fcbcaf 100644 --- a/atlas/drivers/vulkan/mesh.cppm +++ b/atlas/drivers/vulkan/mesh.cppm @@ -13,9 +13,7 @@ module; export module atlas.drivers.vulkan.mesh; import vk; -import atlas.logger;\ -import atlas.drivers.vulkan.physical_device; -import atlas.drivers.vulkan.device; +import atlas.logger; import atlas.drivers.vulkan.hash; import atlas.drivers.vulkan.stb_image; diff --git a/atlas/drivers/vulkan/physical_device.cppm b/atlas/drivers/vulkan/physical_device.cppm deleted file mode 100644 index 995b521f..00000000 --- a/atlas/drivers/vulkan/physical_device.cppm +++ /dev/null @@ -1,253 +0,0 @@ -module; - -#include -#include - -#define GLFW_INCLUDE_VULKAN -#if _WIN32 -#define VK_USE_PLATFORM_WIN32_KHR -#include -#define GLFW_EXPOSE_NATIVE_WIN32 -#include -#include -#else -#include -#include -#endif - -export module atlas.drivers.vulkan.physical_device; - -import atlas.logger; -import atlas.drivers.vulkan.utilities; -import vk; - -export namespace atlas::vulkan { - struct surface_properties { - VkSurfaceCapabilitiesKHR surface_capabilities; - VkSurfaceFormatKHR surface_format; - }; - - /** - * @brief vulkan-specific implementation wrapper around VkPhysicalDevice - * - * Wrapper that constructs a single physical device that provides API's that - * can be used to query specific information for your specific physical - * device - * - * A physical device represents your current hardware GPU and allows for the - * ability to enumerate information to check for compatibility on the - * current GPU - */ - class physical_device { - struct queue_family_indices { - uint32_t graphics = -1; - uint32_t compute = -1; - uint32_t transfer = -1; - }; - - public: - physical_device() = default; - - /** - * @brief constructs a new vulkan physical device - * - * @param p_instance requires a VkInstance to create a VkPhysicalDevice - * handle - */ - physical_device(const VkInstance& p_instance) { - uint32_t device_count = 0; - vkEnumeratePhysicalDevices(p_instance, &device_count, nullptr); - - console_log_info("physical_device after enumerations!"); - - if (device_count == 0) { - console_log_fatal("Device Count is {} and no devices found!!!", - device_count); - return; - } - - std::vector physical_drivers(device_count); - vkEnumeratePhysicalDevices( - p_instance, &device_count, physical_drivers.data()); - - for (const auto& device : physical_drivers) { - VkPhysicalDeviceProperties device_properties; - VkPhysicalDeviceFeatures device_features; - vkGetPhysicalDeviceProperties(device, &device_properties); - vkGetPhysicalDeviceFeatures(device, &device_features); -#if defined(__APPLE__) - // Apple silicon chips are integrated GPUs - // Prefer integrated GPU over discrete GPU on macOS - if (device_properties.deviceType == - VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) { - m_physical_driver = device; - break; - } -#else - // Prefer discrete GPU over integrated GPU on other platforms - // (Linux, Windows) - if (device_properties.deviceType == - VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { - m_physical_driver = device; - break; - } -#endif - } - - uint32_t queue_family_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties( - m_physical_driver, &queue_family_count, nullptr); - m_queue_family_properties.resize(queue_family_count); - - vkGetPhysicalDeviceQueueFamilyProperties( - m_physical_driver, - &queue_family_count, - m_queue_family_properties.data()); - - m_queue_indices = select_queue_family_indices(); - } - - ~physical_device() = default; - - /** - * @brief gives you the queue families that are supported - * - * @return queue_family_indices are the indices of the specific queue's - * that are compatible on current hardware specifications - */ - [[nodiscard]] queue_family_indices read_queue_family_indices() const { - return m_queue_indices; - } - - [[nodiscard]] VkPhysicalDeviceMemoryProperties memory_properties() - const { - VkPhysicalDeviceMemoryProperties physical_memory_properties; - vkGetPhysicalDeviceMemoryProperties(m_physical_driver, - &physical_memory_properties); - return physical_memory_properties; - } - - [[nodiscard]] uint32_t memory_properties( - vk::memory_property p_property_required) { - VkPhysicalDeviceMemoryProperties memory_properties; - vkGetPhysicalDeviceMemoryProperties(m_physical_driver, - &memory_properties); - - uint32_t mask = 0; - for (uint32_t i = 0; i < memory_properties.memoryTypeCount; i++) { - auto type_flags = - memory_properties.memoryTypes[i].propertyFlags; - - if ((type_flags & p_property_required) == p_property_required) { - mask |= ((1 << i)); - } - } - return mask; - } - - /** - * @return uint32_t is the index to the presentation index of the - * specific presentation queue - */ - [[nodiscard]] uint32_t read_presentation_index( - const VkSurfaceKHR& p_surface) { - uint32_t presentation_index = -1; - VkBool32 compatible = VK_FALSE; - uint32_t i = 0; - for (const auto& queue_family : m_queue_family_properties) { - if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - vk_check(vkGetPhysicalDeviceSurfaceSupportKHR( - m_physical_driver, i, p_surface, &compatible), - "vkGetPhysicalDeviceSurfaceSupportKHR"); - - if (compatible) { - presentation_index = i; - } - } - i++; - } - - return presentation_index; - } - - /** - * @brief querying surface properties based on the currently specified - * VkSurfaceKHR handle created - */ - [[nodiscard]] surface_properties get_surface_properties( - const VkSurfaceKHR& p_surface) { - vk_check(vkGetPhysicalDeviceSurfaceCapabilitiesKHR( - m_physical_driver, - p_surface, - &m_surface_properties.surface_capabilities), - "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"); - - uint32_t format_count = 0; - std::vector formats; - vk_check(vkGetPhysicalDeviceSurfaceFormatsKHR( - m_physical_driver, p_surface, &format_count, nullptr), - "vkGetPhysicalDeviceSurfaceFormatsKHR"); - - formats.resize(format_count); - - vk_check( - vkGetPhysicalDeviceSurfaceFormatsKHR( - m_physical_driver, p_surface, &format_count, formats.data()), - "vkGetPhysicalDeviceSurfaceFormatsKHR"); - - for (const auto& format : formats) { - if (format.format == VK_FORMAT_B8G8R8A8_SRGB && - format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - m_surface_properties.surface_format = format; - } - } - - m_surface_properties.surface_format = formats[0]; - - return m_surface_properties; - } - - /** - * @brief Allows for treating vk_physical_device as a VkPhysicalDevice - * handle - * - * Simplifies using this same class for creating other vulkan - * metaobjects - */ - operator VkPhysicalDevice() { return m_physical_driver; } - - /** - * @brief Allows for treating vk_physical_device as a VkPhysicalDevice - * handle - * - * Simplifies using this same class for creating other vulkan - * metaobjects - */ - operator VkPhysicalDevice() const { return m_physical_driver; } - - private: - queue_family_indices select_queue_family_indices() { - VkPhysicalDeviceMemoryProperties physical_device_memory_properties; - vkGetPhysicalDeviceMemoryProperties( - m_physical_driver, &physical_device_memory_properties); - physical_device::queue_family_indices indices; - int i = 0; - - for (const auto& queue_family : m_queue_family_properties) { - if (queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphics = i; - break; - } - i++; - } - - return indices; - } - - private: - VkPhysicalDevice m_physical_driver = nullptr; - queue_family_indices m_queue_indices{}; - std::vector m_queue_family_properties{}; - surface_properties m_surface_properties{}; - }; -}; diff --git a/atlas/drivers/vulkan/render_system.cppm b/atlas/drivers/vulkan/render_system.cppm index 64264bff..f1e8d2cb 100644 --- a/atlas/drivers/vulkan/render_system.cppm +++ b/atlas/drivers/vulkan/render_system.cppm @@ -1,10 +1,7 @@ module; #include -#include #include -#include -#include #include #include #include @@ -13,823 +10,6 @@ module; #include export module atlas.drivers.vulkan.render_system; -import atlas.drivers.renderer_system; - -import atlas.core.utilities; -import vk; -import atlas.core.scene; -import atlas.drivers.graphics_context; -import atlas.drivers.vulkan.physical_device; -import atlas.drivers.vulkan.device; -import atlas.drivers.vulkan.mesh; -import atlas.drivers.vulkan.shader_resource_group; -import atlas.core.scene.world; -import atlas.core.scene; -import atlas.drivers.vulkan.uniforms; -import atlas.drivers.vulkan.mesh; -import atlas.core.scene.components; -import atlas.drivers.vulkan.environment_map; export namespace atlas::vulkan { - /** - * @brief Something to consider for mesh loading. - * - * How will meshes get loaded? - * - * There are a few ways for considering for the base approach, which are: - * TODO: These are things to think about how this may happen because I want - * to make this lightweight in the sense the data isnt continuously being - * modified. Taking a looking at minimizing the loading state of vulkan - * implementation-specific meshes - * * While also making the way how mesh components are being added the - * same as before - * - Something to avoid is the entities containing the geometry data itself - * but being able to reference to their respective geometry data that are - * getting submitted to the GPU - * - * * Batching ID's into hash table that contains the actual geometry data - * * Using ID to search up the mesh loaded and cached into the map, then - * reuse that geometry whenever the uniforms are changed - * * This way we aren't reloading in the same mesh multiple times, treating - * the hash table as a slot of the mesh contained within that scene - * * Potentially std::map> m_geometries - * * Idea is the std::string is the geometries within this scene, the - * data format is: > - */ - /* - class render_system : public renderer_system { - public: - render_system(ref p_context, - const window_params& p_params, - uint32_t p_image_size, - const std::string&) { - m_physical = instance_context::physical_driver(); - m_device = instance_context::logical_device(); - - m_window_extent = p_params; - m_image_count = p_image_size; - -#ifdef USE_SHADERC - console_log_info("shaderc enabled!!"); - std::array shader_sources = { - vk::shader_source{ - "builtin.shaders/test.vert", - vk::shader_stage::vertex, - }, - vk::shader_source { - "builtin.shaders/test.frag", - vk::shader_stage::fragment, - } - }; -#else - console_log_info("shaderc disabled!!"); - std::array shader_sources = { - vk::shader_source{ - "builtin.shaders/test.vert.spv", - vk::shader_stage::vertex, - }, - vk::shader_source{ - "builtin.shaders/test.frag.spv", - vk::shader_stage::fragment, - } - }; -#endif - std::array attribute_entries = { - vk::vertex_attribute_entry{ - .location = 0, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position), - }, - vk::vertex_attribute_entry{ - .location = 1, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color), - }, - vk::vertex_attribute_entry{ - .location = 2, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals), - }, - vk::vertex_attribute_entry{ - .location = 3, - .format = vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv), - } - }; - - std::array attribute = { - vk::vertex_attribute{ - // layout (set = 0, binding = 0) - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = vk::input_rate::vertex, - }, - }; - - vk::shader_resource_info shader_info = { - .sources = shader_sources, - }; - - try { - m_shader_group = shader_resource_group(m_device, shader_info); - m_shader_group.vertex_attributes(attribute); - } - catch (std::runtime_error& e) { - console_log_error("Compilation Error!!"); - console_log_error("{}", e.what()); - } - // Setting global descriptor set 0 - std::vector set0_entries = { - vk::descriptor_entry{ - // specifies "layout (set = 0, binding = 0) uniform GlobalUbo" - .type = vk::descriptor_type::uniform, - .binding_point = { - .binding = 0, - .stage = vk::shader_stage::vertex, - }, - .descriptor_count = 1, - }, - vk::descriptor_entry{ - // specifies "layout (set = 0, binding = 1) uniform light_ubo" - .type = vk::descriptor_type::uniform, - .binding_point = { - .binding = 1, - .stage = vk::shader_stage::fragment, - }, - .descriptor_count = 1, - }, - }; - - // uint32_t image_count = image_count; - vk::descriptor_layout set0_layout = { - .slot = 0, - .max_sets = m_image_count, - .entries = set0_entries, - }; - m_global_descriptors = - vk::descriptor_resource(m_device, set0_layout); - - // vk::uniform_params global_info = { - // .phsyical_memory_properties = m_physical.memory_properties(), - // .size_bytes = sizeof(global_ubo), - // .debug_name = "\nm_global_uniforms\n", - // .vkSetDebugUtilsObjectNameEXT = - // instance_context::get_debug_object_name() - // }; - vk::buffer_parameters global_uniforms = { - .memory_mask = m_physical.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::uniform_buffer_bit | - vk::buffer_usage::shader_device_address_bit, - .allocate_flags = - vk::memory_allocate_flags::device_address_bit_khr, - }; - m_global_uniforms = - vk::uniform_buffer(m_device, sizeof(global_ubo), global_uniforms); - - // setting up our light uniforms as the global uniforms rather then - // per-object basis - // vk::uniform_params light_ubo_params = { - // .phsyical_memory_properties = m_physical.memory_properties(), - // .size_bytes = sizeof(light_scene_ubo), - // }; - vk::buffer_parameters light_ubo_params = { - .memory_mask = m_physical.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::uniform_buffer_bit | - vk::buffer_usage::shader_device_address_bit, - .allocate_flags = - vk::memory_allocate_flags::device_address_bit_khr, - }; - m_point_light_uniforms = vk::uniform_buffer( - m_device, sizeof(light_scene_ubo), light_ubo_params); - - std::array binding0_uniforms = { - vk::write_buffer{ - .buffer = m_global_uniforms, - .offset = 0, - .range = - static_cast(m_global_uniforms.size_bytes()), - }, - }; - - std::array binding1_uniforms = { - vk::write_buffer{ - .buffer = m_point_light_uniforms, - .offset = 0, - .range = - static_cast(m_point_light_uniforms.size_bytes()), - }, - }; - - std::array set0_write_buffers = { - vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = binding0_uniforms, - }, - vk::write_buffer_descriptor{ - .dst_binding = 1, - .uniforms = binding1_uniforms, - } - }; - m_global_descriptors.update(set0_write_buffers); - - m_sets_layouts = { - m_global_descriptors.layout(), - }; - - vk::image_extent extent = { - .width = 1, - .height = 1, - }; - std::array white_color = { 0xff, 0xff, 0xff, 0xff }; - m_white_texture = - vk::texture(m_device, - extent, - white_color, - m_physical.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit)); - - p_context->submit_resource_free([this]() { - console_log_info("vulkan::render_system destructin invoked!!"); - m_white_texture.destruct(); - m_shader_group.destroy(); - m_global_descriptors.destruct(); - m_global_uniforms.destruct(); - m_point_light_uniforms.destruct(); - for (auto& [id, mesh] : m_cached_meshes) { - console_log_trace( - "Entity \"{}\" Destroyed in vk_renderer!!!", id); - mesh.destroy(); - } - - for (auto& [id, uniform] : m_mesh_geometry_set) { - uniform.destruct(); - } - - for (auto& [id, material_uniform] : m_mesh_material_set) { - material_uniform.destruct(); - } - - for (auto& [key, descriptor_map] : m_mesh_descriptors) { - for (auto& [descriptor_type, descriptor] : descriptor_map) { - descriptor.destruct(); - } - } - - m_skybox.destroy(); - m_main_pipeline.destruct(); - }); - - console_log_info( - "Vulkan-specific implementation constructed successfully!!!"); - } - - ~render_system() override = default; - - private: - void preload_assets(const vk::renderpass& p_renderpass) override { - m_final_renderpass = p_renderpass; - - // std::vector faces = { - // "assets/skybox/light_sky/right.png", - // "assets/skybox/light_sky/left.png", - // "assets/skybox/light_sky/top.png", - // "assets/skybox/light_sky/bottom.png", - // "assets/skybox/light_sky/front.png", - // "assets/skybox/light_sky/back.png" - // }; - // m_skybox = environment_map(m_device, faces, - // m_physical.memory_properties(), m_final_renderpass); std::string - - const environment* environment_data = - m_current_scene->get(); - m_skybox = - environment_map(m_device, - m_physical, - std::filesystem::path(environment_data->filepath), - m_physical.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - m_final_renderpass); - - flecs::query<> caching = - m_current_scene->query_builder().build(); - - caching.each([this](flecs::entity p_entity) { - const mesh_source* target = p_entity.get(); - mesh new_mesh(m_device, - m_physical.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - std::filesystem::path(target->model_path), - target->flip); - - // we do a check if the geometry uniform associated with this - // game object is valid - if (!m_mesh_geometry_set.contains(p_entity.id())) { - // vk::uniform_params geo_info = { - // .phsyical_memory_properties = - // m_physical.memory_properties(), - // .size_bytes = sizeof(material_uniform), - // }; - vk::buffer_parameters geo_params = { - .memory_mask = m_physical.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::uniform_buffer_bit | - vk::buffer_usage::shader_device_address_bit, - // .allocate_flags = - // vk::memory_allocate_flags::device_address_bit_khr, - }; - m_mesh_geometry_set[p_entity.id()] = vk::uniform_buffer( - m_device, sizeof(material_uniform), geo_params); - } - - // check if material is already associated with this particular - // game object - if (!m_mesh_material_set.contains(p_entity.id())) { - // vk::uniform_params mat_info = { - // .phsyical_memory_properties = - // m_physical.memory_properties(), - // .size_bytes = sizeof(material_metadata), - // }; - vk::buffer_parameters mat_params = { - .memory_mask = m_physical.memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::uniform_buffer_bit | - vk::buffer_usage::shader_device_address_bit, - .allocate_flags = - vk::memory_allocate_flags::device_address_bit_khr, - }; - m_mesh_material_set[p_entity.id()] = vk::uniform_buffer( - m_device, sizeof(material_metadata), mat_params); - } - - new_mesh.add_diffuse(std::filesystem::path(target->diffuse)); - new_mesh.add_specular(std::filesystem::path(target->specular)); - - if (new_mesh.loaded()) { - m_cached_meshes.emplace(p_entity.id(), new_mesh); - - std::vector set1_entries = { - vk::descriptor_entry{ - // specifies "layout (set = 1, binding = 0) uniform geometry_uniform" - .type = vk::descriptor_type::uniform, - .binding_point = { - .binding = 0, - .stage = vk::shader_stage::vertex, - }, - .descriptor_count = 1, - }, - vk::descriptor_entry{ - // specifies "layout (set = 1, binding = 1) uniform sampler2D diffuse_texture" - .type = vk::descriptor_type::combined_image_sampler, - .binding_point = { - .binding = 1, - .stage = vk::shader_stage::fragment, - }, - .descriptor_count = 1, - }, - vk::descriptor_entry{ - // specifies "layout (set = 1, binding = 2) uniform sampler2D specular_texture" - .type = vk::descriptor_type::combined_image_sampler, - .binding_point = { - .binding = 2, - .stage = vk::shader_stage::fragment, - }, - .descriptor_count = 1, - }, - vk::descriptor_entry{ - // specifies "layout (set = 1, binding = 3) uniform sampler2D material_ubo" - .type = vk::descriptor_type::uniform, - .binding_point = { - .binding = 3, - .stage = vk::shader_stage::fragment, - }, - .descriptor_count = 1, - }, - }; - - vk::descriptor_layout set1_layout = { - .slot = 1, - .max_sets = m_image_count, - .entries = set1_entries, - }; - - m_mesh_descriptors[p_entity.id()].emplace( - "materials", - vk::descriptor_resource(m_device, set1_layout)); - - // specify to the vk::write_descriptor_buffer - std::array binding0_buffers = { - vk::write_buffer{ - .buffer = m_mesh_geometry_set[p_entity.id()], - .offset = 0, - .range = static_cast( - m_mesh_geometry_set[p_entity.id()].size_bytes()), - } - }; - - std::array binding3_buffers = { - vk::write_buffer{ - .buffer = m_mesh_material_set[p_entity.id()], - .offset = 0, - .range = static_cast( - m_mesh_material_set[p_entity.id()].size_bytes()), - } - }; - - std::vector - material_uniforms = { - // layout(set= 1, binding = 0) geometry_ubo - vk::write_buffer_descriptor{ - .dst_binding = 0, - .uniforms = binding0_buffers, - }, - // layout(set= 1, binding = 3) material_ubo - vk::write_buffer_descriptor{ - .dst_binding = 3, - .uniforms = binding3_buffers, - }, - }; - - // layout(set = 1, binding = 1) - // If the texture loaded successfully then we use that - // texture, otherwise utilize the default white texture - vk::sample_image diffuse = - m_cached_meshes[p_entity.id()].diffuse_loaded() - ? m_cached_meshes[p_entity.id()].diffuse() - : m_white_texture.image(); - - // layout(set = 1, binding = 2) - vk::sample_image specular = - m_cached_meshes[p_entity.id()].specular_loaded() - ? m_cached_meshes[p_entity.id()].specular() - : m_white_texture.image(); - - // writes to texture at layout(set = 1, binding = 1) - std::array binding1_images = { - vk::write_image{ - .sampler = diffuse.sampler(), - .view = diffuse.image_view(), - .layout = vk::image_layout::shader_read_only_optimal, - }, - }; - - // writes to texture at layout(set = 1, binding = 2) - std::array binding2_images = { - vk::write_image{ - .sampler = specular.sampler(), - .view = specular.image_view(), - .layout = vk::image_layout::shader_read_only_optimal, - }, - }; - - // vulkan image descriptors are for writing textures - std::vector - material_textures = { - // layout(set = 1, binding = 1) uniform sampler2D - vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = binding1_images, - }, - // layout(set = 1, binding = 2) uniform sampler2D - vk::write_image_descriptor{ - .dst_binding = 2, - .sample_images = binding2_images, - }, - }; - - m_mesh_descriptors[p_entity.id()]["materials"].update( - material_uniforms, material_textures); - - m_sets_layouts.push_back( - m_mesh_descriptors[p_entity.id()]["materials"].layout()); - } - }); - - std::vector modules = m_shader_group.handles(); - - std::array - color_blend_attachments = { - vk::color_blend_attachment_state{}, - }; - - std::array dynamic_states = { - vk::dynamic_state::viewport, vk::dynamic_state::scissor - }; - - vk::pipeline_params pipeline_configuration = { - .renderpass = m_final_renderpass, - .shader_modules = modules, - .vertex_attributes = m_shader_group.vertex_attributes(), - .vertex_bind_attributes = - m_shader_group.vertex_bind_attributes(), - .descriptor_layouts = m_sets_layouts, - .color_blend = { - .attachments = color_blend_attachments, - }, - .depth_stencil_enabled = true, - .dynamic_states = dynamic_states, - }; - m_main_pipeline = vk::pipeline(m_device, pipeline_configuration); - - console_log_warn("graphics pipeline = {}", m_main_pipeline.alive()); - } - - void start_frame(const vk::command_buffer& p_current, - const window_params& p_settings, - const vk::renderpass& p_renderpass, - const VkFramebuffer& p_framebuffer, - const glm::mat4& p_projection, - const glm::mat4& p_view, - uint32_t p_current_frame) override { - m_proj_view = p_projection * p_view; - m_skybox_proj_view = p_projection * glm::mat4(glm::mat3(p_view)); - - m_current_frame = p_current_frame; - m_final_renderpass = p_renderpass; - - std::array clear_values = {}; - - clear_values[0].color = m_color; - clear_values[1].depthStencil = { 1.f, 0 }; - m_window_extent = p_settings; - - VkRenderPassBeginInfo renderpass_begin_info = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, - .pNext = nullptr, - .renderPass = p_renderpass, - .renderArea = { - .offset = { - .x = 0, - .y = 0 - }, - .extent = { - .width = p_settings.width, - .height = p_settings.height - }, - }, - .clearValueCount = static_cast(clear_values.size()), - .pClearValues = clear_values.data() - }; - - m_current_command_buffer = p_current; - m_current_command_buffer.begin( - vk::command_usage::simulatneous_use_bit); - - VkViewport viewport = { - .x = 0.0f, - .y = 0.0f, - .width = static_cast(m_window_extent.width), - .height = static_cast(m_window_extent.height), - .minDepth = 0.0f, - .maxDepth = 1.0f, - }; - - vkCmdSetViewport(m_current_command_buffer, 0, 1, &viewport); - - VkRect2D scissor = { - .offset = { 0, 0 }, - .extent = { m_window_extent.width, m_window_extent.height }, - }; - - vkCmdSetScissor(m_current_command_buffer, 0, 1, &scissor); - - renderpass_begin_info.framebuffer = p_framebuffer; - - vkCmdBeginRenderPass(m_current_command_buffer, - &renderpass_begin_info, - VK_SUBPASS_CONTENTS_INLINE); - } - - void background_color(const glm::vec4& p_color) override { - m_color = { - { p_color.x, p_color.y, p_color.z, p_color.w }, - }; - } - - void post_frame() override { - // For now, using this. Will need to remove this before vulkan - // integration merging into dev This is for testing and to hopefully - // have a global_ubo for globalized uniforms - global_ubo global_frame_ubo = { .mvp = m_proj_view }; - - // TODO: Make to_bytes be part of utilities. This can be useful in - // sending the amount of bytes in batches for batch-rendering - // m_global_uniforms.update(&global_frame_ubo); - m_global_uniforms.transfer( - std::span(&global_frame_ubo, 1)); - - skybox_uniform skybox_ubo = { - .proj_view = m_skybox_proj_view, - }; - - m_skybox.update_uniform(skybox_ubo); - - // query all entities that have a point light - flecs::query query_point_lights = - m_current_scene->query_builder().build(); - - light_scene_ubo test_light = {}; - uint32_t index = 0; - query_point_lights.each( - [&index, &test_light](flecs::entity p_entity, - point_light& p_light) { - const transform* t = p_entity.get(); - p_light.position = t->position; - - test_light.light_sources[index] = { - .position = glm::vec4(p_light.position, 1.f), - .color = p_light.color, - .attenuation = p_light.attenuation, - .constant = p_light.constant, - .linear = p_light.linear, - .quadratic = p_light.quadratic, - .ambient = p_light.ambient, - .diffuse = p_light.diffuse, - .specular = p_light.specular, - }; - index += 1; - }); - test_light.num_lights = index; - - // m_point_light_uniforms.update(&test_light); - m_point_light_uniforms.transfer( - std::span(&test_light, 1)); - - // query all objects with a specified 3d mesh source - flecs::query<> query_targets = - m_current_scene->query_builder().build(); - - m_main_pipeline.bind(m_current_command_buffer); - - // Bind global camera data here - // m_global_descriptors.bind(m_current_command_buffer, - // m_main_pipeline.layout()); - std::array descriptors = { - m_global_descriptors, - }; - - m_current_command_buffer.bind_descriptors( - m_main_pipeline.layout(), - VK_PIPELINE_BIND_POINT_GRAPHICS, - descriptors); - - query_targets.each([this](flecs::entity p_entity) { - const transform* transform_component = - p_entity.get(); - const mesh_source* material_component = - p_entity.get(); - m_model = glm::mat4(1.f); - m_model = - glm::translate(m_model, transform_component->position); - m_model = glm::scale(m_model, transform_component->scale); - glm::mat4 rotation_mat4 = - glm::mat4(glm::quat(transform_component->rotation)); - - m_model *= rotation_mat4; - - // Mesh used for viking_room - replaced with std::map equivalent - geometry_uniform mesh_ubo = { .model = m_model, - .color = - material_component->color }; - - if (m_cached_meshes[p_entity.id()].loaded()) { - // m_mesh_geometry_set[p_entity.id()].update(&mesh_ubo); - m_mesh_geometry_set[p_entity.id()].transfer(std::span(&mesh_ubo, 1)); - - material_metadata data = {}; - - if (p_entity.has()) { - data = *p_entity.get(); - } - // m_mesh_material_set[p_entity.id()].update(&data); - m_mesh_material_set[p_entity.id()].transfer(std::span(&data, 1)); - - - // m_mesh_descriptors[p_entity.id()]["materials"].bind( - // m_current_command_buffer, m_main_pipeline.layout()); - - // descriptors.push_back(m_mesh_descriptors[p_entity.id()]["materials"]); - const VkDescriptorSet descriptors = m_mesh_descriptors[p_entity.id()]["materials"]; - m_current_command_buffer.bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&descriptors, 1)); - - - // m_cached_meshes[p_entity.id()].draw( - // m_current_command_buffer); - - // binding/draw calls - const VkBuffer vertex = - m_cached_meshes[p_entity.id()].vertex_handle(); - const VkBuffer index = - m_cached_meshes[p_entity.id()].index_handle(); - - std::array handler = { vertex }; - std::array offsets = { 0 }; - vkCmdBindVertexBuffers(m_current_command_buffer, - 0, - 1, - handler.data(), - offsets.data()); - - if (m_cached_meshes[p_entity.id()].indices_size() != 0) { - vkCmdBindIndexBuffer(m_current_command_buffer, - index, - 0, - VK_INDEX_TYPE_UINT32); - vkCmdDrawIndexed( - m_current_command_buffer, - static_cast( - m_cached_meshes[p_entity.id()].indices_size()), - 1, - 0, - 0, - 0); - } - else { - vkCmdDraw( - m_current_command_buffer, - m_cached_meshes[p_entity.id()].vertices_size(), - 1, - 0, - 0); - } - } - }); - - std::array offsets = { 0 }; - vkCmdBindPipeline(m_current_command_buffer, - VK_PIPELINE_BIND_POINT_GRAPHICS, - m_skybox.pipeline()); - m_skybox.descriptor_bind(m_current_command_buffer, - m_skybox.pipeline_layout()); - - const VkBuffer skybox_vertex = m_skybox.vertex_handle(); - vkCmdBindVertexBuffers( - m_current_command_buffer, 0, 1, &skybox_vertex, offsets.data()); - vkCmdDraw( - m_current_command_buffer, m_skybox.vertices_size(), 1, 0, 0); - - vkCmdEndRenderPass(m_current_command_buffer); - - // Do not end the command buffer here when using offscreen + - // swapchain two-pass: the application will begin the swapchain - // render pass for ImGui, then end the command buffer. - // m_current_command_buffer.end(); - } - - void current_scene(ref p_scene_ctx) override { - m_current_scene = p_scene_ctx; - } - - // Remove this API - void render_invalidate_mesh(uint32_t p_entity_id, - std::filesystem::path p_filename) override { - m_cached_meshes[p_entity_id].reload_mesh(p_filename); - } - - private: - VkDevice m_device = nullptr; - physical_device m_physical; - glm::mat4 m_proj_view; - glm::mat4 m_skybox_proj_view; - vk::renderpass m_final_renderpass; - window_params m_window_extent; - vk::command_buffer m_current_command_buffer{}; - VkClearColorValue m_color; - - uint32_t m_image_count = 0; - shader_resource_group m_shader_group; - vk::pipeline m_main_pipeline; - vk::descriptor_resource m_global_descriptors; - std::vector m_sets_layouts; - - std::map m_cached_meshes; - vk::uniform_buffer m_global_uniforms; - vk::uniform_buffer m_point_light_uniforms; - - // game object-specific meshes - std::map m_mesh_geometry_set; - // TODO: Make this into a material system, eventually - std::map m_mesh_material_set; - std::map> - m_mesh_descriptors; - uint32_t m_current_frame = 0; - glm::mat4 m_model = { 1.f }; - - vk::texture m_white_texture; - - environment_map m_skybox; - - ref m_current_scene; - }; - */ }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/swapchain.cppm b/atlas/drivers/vulkan/swapchain.cppm deleted file mode 100644 index 482bc102..00000000 --- a/atlas/drivers/vulkan/swapchain.cppm +++ /dev/null @@ -1,364 +0,0 @@ -module; - -#include -#include -#include - -export module atlas.drivers.vulkan.swapchain; - -import vk; - -// import atlas.logger; -// import atlas.core.utilities.types; -import atlas.core.utilities; -import atlas.drivers.vulkan.physical_device; -import atlas.drivers.vulkan.device; -import atlas.drivers.vulkan.utilities; - -export namespace atlas::vulkan { - /** - * @name vk_swapchain - * @brief High-level abstraction of a vulkan swapchain - * @brief ref will return the vk_swapchain directly - * @brief ref returning vk_swapchain will need to be changed - */ - // class swapchain { - // public: - // swapchain() = default; - - // /** - // * @brief Constructs a new vulkan swapchain with a window settings to - // * apply to this swapchain - // * @param p_surface passing in the surface handler for swapchain uses - // */ - // swapchain(const VkSurfaceKHR& p_surface, const window_params& p_params) - // : m_current_surface_handler(p_surface) - // , m_window_params(p_params) - // , m_current_surface(p_surface) { - // m_physical = instance_context::physical_driver(); - // m_driver = instance_context::logical_device(); - - // create(); - - // console_log_info_tagged("vulkan", - // "swapchain created successfully!!!"); - // } - - // //! @return uint32_t the next available image to present acquired - // uint32_t read_acquired_image() { - // m_present_to_queue.wait_idle(); - - // // uint32_t frame_idx = m_present_to_queue.acquired_frame(); - // uint32_t frame_idx = m_present_to_queue.acquire_next_image(); - // if (m_present_to_queue.out_of_date()) { - // invalidate(); - // m_present_to_queue.out_of_date(false); - // frame_idx = m_present_to_queue.acquire_next_image(); - // } - - // return frame_idx; - // } - - // //! @return current active command buffer being processed - // [[nodiscard]] vk::command_buffer active_command( - // uint32_t p_frame_index) { - // return m_swapchain_command_buffers[p_frame_index]; - // } - - // [[nodiscard]] VkFramebuffer active_framebuffer(uint32_t p_frame) const { - // return m_swapchain_framebuffers[p_frame]; - // } - - // [[nodiscard]] vk::renderpass swapchain_renderpass() const { - // return m_final_renderpass; - // } - - // [[nodiscard]] window_params settings() const { return m_window_params; } - - // [[nodiscard]] uint32_t image_size() const { return m_image_size; } - - // [[nodiscard]] surface_properties data() const { - // return m_surface_properties; - // } - - // void destroy() { - // vkDeviceWaitIdle(m_driver); - - // for (size_t i = 0; i < m_swapchain_framebuffers.size(); i++) { - // m_swapchain_framebuffers[i].destruct(); - // } - - // m_final_renderpass.destruct(); - - // m_present_to_queue.destruct(); - - // for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { - // m_swapchain_command_buffers[i].destruct(); - // } - - // for (uint32_t i = 0; i < m_swapchain_depth_images.size(); i++) { - // m_swapchain_depth_images[i].destruct(); - // } - - // for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - // m_swapchain_images[i].destruct(); - // } - - // vkDestroySwapchainKHR(m_driver, m_swapchain_handler, nullptr); - // } - - // void submit(std::span p_commands) { - // m_present_to_queue.submit_async(p_commands); - // } - - // [[nodiscard]] ::vk::sample_image active_image(uint32_t p_index) const { - // return m_swapchain_images[p_index]; - // } - - // operator VkSwapchainKHR() const { return m_swapchain_handler; } - - // operator VkSwapchainKHR() { return m_swapchain_handler; } - - // void present(const uint32_t& p_current_frame) { - // m_present_to_queue.present_frame(p_current_frame); - // if (m_present_to_queue.out_of_date()) { - // invalidate(); - // m_present_to_queue.out_of_date(false); - // } - // } - - // private: - // void invalidate() { - // destroy(); - // create(); - // } - - // void create() { - // // surface properties are always updated from the physical device - // // so they are valid should the swapchain be recreated - // m_surface_properties = - // m_physical.get_surface_properties(m_current_surface); - // m_window_params.width = - // m_surface_properties.surface_capabilities.currentExtent.width; - // m_window_params.height = - // m_surface_properties.surface_capabilities.currentExtent.height; - - // //! @note Setting up presentation stuff - // // request what our minimum image count is - // uint32_t request_min_image_count = - // select_images_size(m_surface_properties.surface_capabilities); - - // m_swapchain_extent = - // m_surface_properties.surface_capabilities.currentExtent; - - // // setting our presentation properties - // uint32_t present_index = - // m_physical.read_presentation_index(m_current_surface_handler); - - // VkSwapchainCreateInfoKHR swapchain_ci = { - // .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, - // .surface = m_current_surface_handler, - // .minImageCount = request_min_image_count, - // .imageFormat = m_surface_properties.surface_format.format, - // .imageColorSpace = - // m_surface_properties.surface_format.colorSpace, - // // use physical device surface formats to getting the right - // // formats in vulkan - // .imageExtent = m_swapchain_extent, - // .imageArrayLayers = 1, - // .imageUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - // VK_IMAGE_USAGE_TRANSFER_DST_BIT), - // .queueFamilyIndexCount = 1, - // .pQueueFamilyIndices = &present_index, - // .preTransform = - // m_surface_properties.surface_capabilities.currentTransform, - // .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, - // .presentMode = VK_PRESENT_MODE_FIFO_KHR, - // .clipped = true - // }; - - // vk_check(vkCreateSwapchainKHR( - // m_driver, &swapchain_ci, nullptr, &m_swapchain_handler), - // "vkCreateSwapchainKHR"); - - // //!@brief querying images available - // uint32_t image_count = 0; - // vkGetSwapchainImagesKHR( - // m_driver, - // m_swapchain_handler, - // &image_count, - // nullptr); // used to get the amount of images - // std::vector images(image_count); - // vkGetSwapchainImagesKHR( - // m_driver, - // m_swapchain_handler, - // &image_count, - // images.data()); // used to store in the images - - // // Creating Images - // m_swapchain_images.resize(image_count); - // m_image_size = image_count; - // m_swapchain_depth_images.resize(image_count); - - // VkFormat depth_format = m_driver.depth_format(); - - // for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - // // ::vk::image_params color_image_config = { - // // .extent = { m_swapchain_extent.width, - // // m_swapchain_extent.height, }, - // // .format = m_surface_properties.surface_format.format, - // // .aspect = ::vk::image_aspect_flags::color_bit, - // // .usage = vk::image_usage::color_attachment_bit, - // // .mip_levels = 1, - // // .layer_count = 1, - // // .phsyical_memory_properties = m_physical.memory_properties(), - - // // }; - // vk::image_params color_image_params = { - // .extent = { - // .width = m_swapchain_extent.width, - // .height = m_swapchain_extent.height, - // }, - // .format = m_surface_properties.surface_format.format, - // .memory_mask = m_physical.memory_properties( - // vk::memory_property::device_local_bit), - // .aspect = vk::image_aspect_flags::color_bit, - // .usage = vk::image_usage::color_attachment_bit, - // .mip_levels = 1, - // .layer_count = 1, - // }; - - // m_swapchain_images[i] = - // ::vk::sample_image(m_driver, images[i], color_image_params); - - // vk::image_params depth_image_params = { - // .extent = { - // .width = m_swapchain_extent.width, - // .height = m_swapchain_extent.height, - // }, - // .format = depth_format, - // .memory_mask = m_physical.memory_properties( - // vk::memory_property::device_local_bit), - // .aspect = vk::image_aspect_flags::depth_bit, - // .usage = vk::image_usage::depth_stencil_bit, - // .mip_levels = 1, - // .layer_count = 1, - // }; - - // m_swapchain_depth_images[i] = - // ::vk::sample_image(m_driver, depth_image_params); - // } - - // // command buffers - // m_swapchain_command_buffers.resize(image_count); - - // for (size_t i = 0; i < m_swapchain_command_buffers.size(); i++) { - // vk::command_params command_params = { - // .levels = vk::command_levels::primary, - // .queue_index = 0, - // .flags = vk::command_pool_flags::reset, - // }; - - // m_swapchain_command_buffers[i] = - // ::vk::command_buffer(m_driver, command_params); - // } - - // std::array<::vk::attachment, 2> renderpass_attachments = { - // ::vk::attachment{ - // .format = m_surface_properties.surface_format.format, - // .layout = ::vk::image_layout::color_optimal, - // .samples = ::vk::sample_bit::count_1, - // .load = ::vk::attachment_load::clear, - // .store = ::vk::attachment_store::store, - // .stencil_load = ::vk::attachment_load::clear, - // .stencil_store = ::vk::attachment_store::dont_care, - // .initial_layout = ::vk::image_layout::undefined, - // .final_layout = ::vk::image_layout::present_src_khr, - // }, - // ::vk::attachment{ - // .format = depth_format, - // .layout = ::vk::image_layout::depth_stencil_optimal, - // .samples = ::vk::sample_bit::count_1, - // .load = ::vk::attachment_load::clear, - // .store = ::vk::attachment_store::dont_care, - // .stencil_load = ::vk::attachment_load::dont_care, - // .stencil_store = ::vk::attachment_store::dont_care, - // .initial_layout = ::vk::image_layout::undefined, - // .final_layout = ::vk::image_layout::depth_stencil_optimal, - // }, - // }; - // m_final_renderpass = - // ::vk::renderpass(m_driver, renderpass_attachments); - - // // creating framebuffers - // m_swapchain_framebuffers.resize(m_swapchain_images.size()); - - // for (uint32_t i = 0; i < m_swapchain_images.size(); i++) { - - // std::array - // image_attachments = { - // m_swapchain_images[i].image_view(), - // m_swapchain_depth_images[i].image_view() - // }; - - // vk::framebuffer_params framebuffer_info = { - // .renderpass = m_final_renderpass, - // .views = image_attachments, - // .extent = m_swapchain_extent - // }; - // m_swapchain_framebuffers[i] = - // vk::framebuffer(m_driver, framebuffer_info); - // } - - // vk::queue_params present_queue_params{ - // .family = 0, - // .index = 0, - // }; - // m_present_to_queue = ::vk::device_present_queue( - // m_driver, m_swapchain_handler, present_queue_params); - // console_log_info("m_present_to_queue initialized!!!"); - // console_log_info("m_presesnt_to_queue.alive() = {}", - // (m_present_to_queue != nullptr)); - // } - - // uint32_t select_images_size( - // const VkSurfaceCapabilitiesKHR& p_surface_capabilities) { - // uint32_t requested_images = - // p_surface_capabilities.minImageCount + 1; - // uint32_t final_image_count = 0; - - // if ((p_surface_capabilities.maxImageCount > 0) and - // (requested_images > p_surface_capabilities.maxImageCount)) { - // final_image_count = p_surface_capabilities.maxImageCount; - // } - // else { - // final_image_count = requested_images; - // } - - // return final_image_count; - // } - - // private: - // physical_device m_physical{}; - // device m_driver{}; - // VkSurfaceKHR m_current_surface_handler = nullptr; - // VkSwapchainKHR m_swapchain_handler = nullptr; - // VkExtent2D m_swapchain_extent{}; - // window_params m_window_params{}; - - // uint32_t m_image_size = 0; - - // VkSurfaceKHR m_current_surface = nullptr; - // surface_properties m_surface_properties{}; - // std::vector m_swapchain_command_buffers{}; - // std::vector m_swapchain_framebuffers; - - // //! @brief setting up images - // std::vector m_swapchain_images; - // std::vector m_swapchain_depth_images; - - // vk::renderpass m_final_renderpass; - - // vk::device_present_queue m_present_to_queue; - // }; -}; diff --git a/atlas/drivers/vulkan/vulkan.cppm b/atlas/drivers/vulkan/vulkan.cppm new file mode 100644 index 00000000..29c76d37 --- /dev/null +++ b/atlas/drivers/vulkan/vulkan.cppm @@ -0,0 +1,7 @@ +module; + +export module atlas.drivers.vulkan; + + +export import :window; +export import :graphics_context; \ No newline at end of file diff --git a/atlas/core/window.cppm b/atlas/drivers/vulkan/window.cppm similarity index 98% rename from atlas/core/window.cppm rename to atlas/drivers/vulkan/window.cppm index ddd19a56..4dc6dead 100644 --- a/atlas/core/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -20,13 +20,13 @@ module; #include #include -export module atlas.window; +// export module atlas.window; +export module atlas.drivers.vulkan:window; import atlas.common; -import atlas.core.utilities.types; import atlas.core.utilities; import vk; -import atlas.drivers.graphics_context; +import :graphics_context; export namespace atlas { diff --git a/atlas/drivers/vulkan/window_context.cppm b/atlas/drivers/vulkan/window_context.cppm deleted file mode 100644 index 8e86ab6f..00000000 --- a/atlas/drivers/vulkan/window_context.cppm +++ /dev/null @@ -1,134 +0,0 @@ -module; - -#include - -#define GLFW_INCLUDE_VULKAN -#if _WIN32 -#define VK_USE_PLATFORM_WIN32_KHR -#include -#define GLFW_EXPOSE_NATIVE_WIN32 -#include -#include -#else -#include -#include -#endif - -export module atlas.drivers.vulkan.window_context; - -// import atlas.logger; -// import atlas.core.utilities.types; -import atlas.core.utilities; -import vk; - -import atlas.window; -import atlas.drivers.graphics_context; -import atlas.drivers.vulkan.utilities; -import atlas.drivers.vulkan.swapchain; - -export namespace atlas { - // namespace vulkan { - /** - * @brief vulkan-backend implementation of the application-window - */ - // class window_context : public window { - // public: - // window_context(ref p_context, - // const window_params& p_params) - // : m_params(p_params) { - - // console_log_info("window_context constructed!!!"); - - // if (!glfwVulkanSupported()) { - // console_log_error("GLFW: Vulkan is not supported!!!"); - // console_log_error("GLFW: Vulkan Supported = {}", - // static_cast(glfwVulkanSupported())); - // return; - // } - - // glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - // glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - - // // m_instance = instance_context::handle(); - // m_instance = p_context->handle(); - - // m_window_handle = - // glfwCreateWindow(static_cast(m_params.width), - // static_cast(m_params.height), - // m_params.name.c_str(), - // nullptr, - // nullptr); - - // glfwMakeContextCurrent(m_window_handle); - - // console_log_info("m_instance = {}", (m_instance == nullptr)); - - // vk_check( - // glfwCreateWindowSurface( - // m_instance, m_window_handle, nullptr, &m_window_surface), - // "glfwCreateWindowSurface"); - - // center_window(); - - // m_window_swapchain = swapchain(m_window_surface, m_params); - - // p_context->submit_resource_free([this]() { - // console_log_info("vulkan::window_context " - // "submit_resource_free invokation!"); - // m_window_swapchain.destroy(); - // }); - // } - - // virtual ~window_context() { - // if (m_window_surface != nullptr) { - // vkDestroySurfaceKHR(m_instance, m_window_surface, nullptr); - // } - // glfwDestroyWindow(m_window_handle); - // } - - // protected: - // [[nodiscard]] window_params get_params() const override { - // return m_window_swapchain.settings(); - // } - - // [[nodiscard]] GLFWwindow* native_window() const override { - // return m_window_handle; - // } - - // [[nodiscard]] uint32_t read_acquired_next_frame() override { - // return m_window_swapchain.read_acquired_image(); - // } - - // [[nodiscard]] vulkan::swapchain window_swapchain() const override { - // return m_window_swapchain; - // } - - // [[nodiscard]] vk::command_buffer current_active_command( - // uint32_t p_frame_idx) override { - // return m_window_swapchain.active_command(p_frame_idx); - // } - - // void present_frame(const uint32_t& p_current_frame) override { - // m_window_swapchain.present(p_current_frame); - // } - - // private: - // void center_window() { - // GLFWmonitor* monitor = glfwGetPrimaryMonitor(); - // const GLFWvidmode* mode = glfwGetVideoMode(monitor); - // uint32_t width = (mode->width / 2) - (m_params.width / 2); - // uint32_t height = (mode->height / 2) - (m_params.height / 2); - // glfwSetWindowPos(m_window_handle, - // static_cast(width), - // static_cast(height)); - // } - - // private: - // GLFWwindow* m_window_handle = nullptr; - // VkSurfaceKHR m_window_surface = nullptr; - // window_params m_params; - // VkInstance m_instance = nullptr; - // swapchain m_window_swapchain; - // }; - // }; -}; \ No newline at end of file diff --git a/atlas/renderer/context_loader.cppm b/atlas/renderer/context_loader.cppm deleted file mode 100644 index 1ade493c..00000000 --- a/atlas/renderer/context_loader.cppm +++ /dev/null @@ -1,26 +0,0 @@ -module; - -#include -#include - -export module atlas.renderer.context_loader; - -import atlas.core.utilities; - -import atlas.drivers.graphics_context; - -export namespace atlas { - /** - * @brief construct a new graphics context and initializes that API - * @return shared_ptr - */ - // ref initialize_context(const std::string& p_name, - // graphics_api p_api) { - // switch (p_api) { - // case graphics_api::vulkan: - // return create_ref(p_name); - // default: - // return nullptr; - // } - // } -}; \ No newline at end of file diff --git a/atlas/renderer/renderer.cppm b/atlas/renderer/renderer.cppm index b816f43d..9abe892d 100644 --- a/atlas/renderer/renderer.cppm +++ b/atlas/renderer/renderer.cppm @@ -5,27 +5,5 @@ module; export module atlas.renderer; -import atlas.common; -import atlas.drivers.renderer_system; -import atlas.drivers.vulkan.render_system; -import atlas.common; -import atlas.graphics_api; -import atlas.drivers.graphics_context; -import atlas.core.utilities.types; - export namespace atlas { - // ref initialize_renderer( - // ref p_context, - // graphics_api p_api, - // const window_params& p_window_extent, - // uint32_t p_image_size, - // const std::string& p_name) { - // switch (p_api) { - // case graphics_api::vulkan: - // return create_ref( - // p_context, p_window_extent, p_image_size, p_name); - // default: - // return nullptr; - // } - // } }; \ No newline at end of file diff --git a/conanfile.py b/conanfile.py index c4b66b59..7f69cd5e 100644 --- a/conanfile.py +++ b/conanfile.py @@ -40,7 +40,7 @@ def requirements(self): self.requires("yaml-cpp/0.8.0") # Vulkan-related headers and includes packages - self.requires("vulkan-cpp/5.0") + self.requires("vulkan-cpp/6.0") self.requires("tinyobjloader/2.0.0-rc10") self.requires("stb/cci.20230920") diff --git a/editor/application.cpp b/editor/application.cpp index 080569be..7cab1617 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -7,8 +7,7 @@ import atlas.common; import atlas.core.level_streamer; import atlas.core.event; // import editor; - -import atlas.drivers.graphics_context; +import atlas.drivers.vulkan; class editor_application : public atlas::application { public: From 95612601e2fee946bc426c2f930b53837b0bc252 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 16:54:36 -0700 Subject: [PATCH 008/106] Created listeners for event::bus in application to remove warnings --- atlas/core/application.cppm | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 0864992a..65b85175 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -50,6 +50,12 @@ export namespace atlas { m_physical = p_context->physical_device(); m_device = p_context->logical_device(); + m_bus->create_listener(); + m_bus->create_listener(); + m_bus->create_listener(); + // m_bus->create_immediate_listener(); + // m_bus->create_immediate_listener(); + // Constructing the application std::println("Constructing application"); window_params params = { @@ -126,15 +132,11 @@ export namespace atlas { } std::println("images.size() = {}", images.size()); - - std::println("After constructing atlas::window"); } void execute() { - std::println("Executing mainloop"); - VkClearValue clear_color = { - { 0.f, 0.5f, 0.5f, 1.f }, + {{ 0.f, 0.5f, 0.5f, 1.f }}, }; VkClearValue depth_value = { From 967f8c6a44c36c9ee6044ecc76f1be323c0232ad Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 16:55:43 -0700 Subject: [PATCH 009/106] Removed old outdated shader files --- shaders/colorful_triangle/compile_shaders.sh | 2 - shaders/colorful_triangle/simple_shader.frag | 10 --- .../colorful_triangle/simple_shader.frag.spv | Bin 572 -> 0 bytes shaders/colorful_triangle/simple_shader.vert | 17 ---- .../colorful_triangle/simple_shader.vert.spv | Bin 1080 -> 0 bytes shaders/cube_shader/cube_shader.frag | 8 -- shaders/cube_shader/cube_shader.vert | 14 ---- .../mouse_picking_shaders/compile_shaders.sh | 2 - .../mouse_picking_shaders/simple_shader.frag | 49 ----------- .../simple_shader.frag.spv | Bin 1504 -> 0 bytes .../mouse_picking_shaders/simple_shader.vert | 78 ------------------ .../simple_shader.vert.spv | Bin 3200 -> 0 bytes shaders/showcase_shaders/simple_shader.frag | 24 ------ .../showcase_shaders/simple_shader.frag.spv | Bin 972 -> 0 bytes shaders/showcase_shaders/simple_shader.vert | 41 --------- .../showcase_shaders/simple_shader.vert.spv | Bin 2904 -> 0 bytes .../sim_shader_transforms/simple_shader.frag | 19 ----- .../simple_shader.frag.spv | Bin 968 -> 0 bytes .../sim_shader_transforms/simple_shader.vert | 38 --------- .../simple_shader.vert.spv | Bin 2584 -> 0 bytes .../simple_shader.frag | 37 --------- .../simple_shader.frag.spv | Bin 2776 -> 0 bytes .../simple_shader.vert | 38 --------- .../simple_shader.vert.spv | Bin 2760 -> 0 bytes shaders/simple_shader/compile_shaders.sh | 2 - shaders/simple_shader/simple_shader.frag | 16 ---- shaders/simple_shader/simple_shader.frag.spv | Bin 756 -> 0 bytes shaders/simple_shader/simple_shader.vert | 17 ---- shaders/simple_shader/simple_shader.vert.spv | Bin 1224 -> 0 bytes 29 files changed, 412 deletions(-) delete mode 100644 shaders/colorful_triangle/compile_shaders.sh delete mode 100644 shaders/colorful_triangle/simple_shader.frag delete mode 100644 shaders/colorful_triangle/simple_shader.frag.spv delete mode 100644 shaders/colorful_triangle/simple_shader.vert delete mode 100644 shaders/colorful_triangle/simple_shader.vert.spv delete mode 100644 shaders/cube_shader/cube_shader.frag delete mode 100644 shaders/cube_shader/cube_shader.vert delete mode 100644 shaders/mouse_picking_shaders/compile_shaders.sh delete mode 100644 shaders/mouse_picking_shaders/simple_shader.frag delete mode 100644 shaders/mouse_picking_shaders/simple_shader.frag.spv delete mode 100644 shaders/mouse_picking_shaders/simple_shader.vert delete mode 100644 shaders/mouse_picking_shaders/simple_shader.vert.spv delete mode 100644 shaders/showcase_shaders/simple_shader.frag delete mode 100644 shaders/showcase_shaders/simple_shader.frag.spv delete mode 100644 shaders/showcase_shaders/simple_shader.vert delete mode 100644 shaders/showcase_shaders/simple_shader.vert.spv delete mode 100644 shaders/sim_shader_transforms/simple_shader.frag delete mode 100644 shaders/sim_shader_transforms/simple_shader.frag.spv delete mode 100644 shaders/sim_shader_transforms/simple_shader.vert delete mode 100644 shaders/sim_shader_transforms/simple_shader.vert.spv delete mode 100644 shaders/sim_shader_ubo_tutorial/simple_shader.frag delete mode 100644 shaders/sim_shader_ubo_tutorial/simple_shader.frag.spv delete mode 100644 shaders/sim_shader_ubo_tutorial/simple_shader.vert delete mode 100644 shaders/sim_shader_ubo_tutorial/simple_shader.vert.spv delete mode 100644 shaders/simple_shader/compile_shaders.sh delete mode 100644 shaders/simple_shader/simple_shader.frag delete mode 100644 shaders/simple_shader/simple_shader.frag.spv delete mode 100644 shaders/simple_shader/simple_shader.vert delete mode 100644 shaders/simple_shader/simple_shader.vert.spv diff --git a/shaders/colorful_triangle/compile_shaders.sh b/shaders/colorful_triangle/compile_shaders.sh deleted file mode 100644 index 5aa7404c..00000000 --- a/shaders/colorful_triangle/compile_shaders.sh +++ /dev/null @@ -1,2 +0,0 @@ -glslc.exe simple_shader.vert -o simple_shader.vert.spv -glslc.exe simple_shader.frag -o simple_shader.frag.spv diff --git a/shaders/colorful_triangle/simple_shader.frag b/shaders/colorful_triangle/simple_shader.frag deleted file mode 100644 index b9810551..00000000 --- a/shaders/colorful_triangle/simple_shader.frag +++ /dev/null @@ -1,10 +0,0 @@ -#version 450 - - -layout(location = 0) in vec3 fragColor; - -layout(location = 0) out vec4 outColor; - -void main(){ - outColor = vec4(fragColor, 0.0); -} \ No newline at end of file diff --git a/shaders/colorful_triangle/simple_shader.frag.spv b/shaders/colorful_triangle/simple_shader.frag.spv deleted file mode 100644 index 43d2f81d8ad249bad7466d20509050a625450689..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 572 zcmYk2%}T>i5QWF4X=`i$Ea*-uE`{PkMG)PHWD}_31B8-93BB;HfdaBA1S;}jh8Ls ze3#S-z8G~~-+ZUN+7%D0e6^9B5Z`%u-7MZJFwhhpPar7h@muv1ImPR#b8YT?q;pHy zRCz2uZ=y$ks&7Y?zXE<+_Go~?@2bM5hu>4xuW&egdOU!gtA{&K64!bIe$XP=@h!wx xy%WmrzLNQ8q0A0TOywUNl^7ZoZ(L&Rf0BFrA1axL&pkfwrOJD_`;p5VFFODL diff --git a/shaders/colorful_triangle/simple_shader.vert b/shaders/colorful_triangle/simple_shader.vert deleted file mode 100644 index 07daf1a2..00000000 --- a/shaders/colorful_triangle/simple_shader.vert +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -// vec2 positions[3] = vec2[]( -// vec2(0.0, -0.5), -// vec2(0.5, 0.5), -// vec2(-0.5, 0.5) -// ); - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec3 Color; - -layout(location = 0) out vec3 fragColor; - -void main(){ - gl_Position = vec4(Position, 0.0, 1.0); - fragColor = Color; -} \ No newline at end of file diff --git a/shaders/colorful_triangle/simple_shader.vert.spv b/shaders/colorful_triangle/simple_shader.vert.spv deleted file mode 100644 index 75fe19c4a1749812a3aef036e98214f0c3e8cc43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1080 zcmYk4-Afxm6vf9RYhpA>V~kqsN5sd1^r4nQX+>1F4*@NLuS-Z)8CW-AvzE3`{%!tM zeJS+(W_LnHu6NG4UuW*7S~;m3vtrgw%N(2HbWKH!5x44mIJ_I4&hyFX$FmP)v`y6| zlG8D3?q1XXr;$woE!n2*Kz1an>aQaIs)Cwnns69}H#gz%IvUSr(LDd1#8G0?IGWfj z9_RLFOkQIt&!*$#d9s`kC}VkMAg$|~@t8!nadsbPdHhRIY{7FUHl5qtPE)aUm(Lp< zZ`1tF{?TM=iWr&|yG-ot%FgpqI*u1HHbCq-Nfxm{@8s>AK!5CDF|g#=$wM}JyqqS} z%yBihBagqUj(2dp_gwK!_*%wz4vplY$8+4_*iWbkck)6pXgZW}!01`Vd@nFFda9!C zSUu>;eOtFx`GIUl_4@HR%&fj}Lw+FRye~1o5c=&4H|42^JJbzrz6UXEpu7!v|Bf#u zX18$6X}i3lFLS^h83$c&L=hVN|o!Mxm|2uhV z;E3;+cX;}P*{zTJo%%SKT{HiazBxMCA%~j3VgmWEV$s}_q4$Sa=5Cjq+=AOFIeOko qDOz`B`ZTV~m;m`A2u8)iX>5!P}(?7r(B7L&o@ z@slGMtES7Aw4T)X%1aDj^V~S~oC(t8J%~6Pwvw<%9&Tm&-i9@?fC3 z?rAT~>_wcN#KRl#*>Jzi-^}*})!RqzF{#T!V+2g$YIka>$ zV1ew+PK%^xi?kfs_4ZKsc-C8}OzyQKV-a)5K0Z~<8L`ki)zilZ4*eJ7n^Us25tw&s)lRU6_UfDx+PTv>b0J%S89zz@Kr;PLPdYe*3 zcTX5vyl?5PCBG}%)_G8q7~Nex7vq10WQVRC;l{t0-@?s*$C4E>%uqNlqu^5L`3 Q`MgwBdSUOk6rRcc0NSv1cK`qY diff --git a/shaders/mouse_picking_shaders/simple_shader.vert b/shaders/mouse_picking_shaders/simple_shader.vert deleted file mode 100644 index 54abaf84..00000000 --- a/shaders/mouse_picking_shaders/simple_shader.vert +++ /dev/null @@ -1,78 +0,0 @@ -#version 450 - -//! @note Position and Color used in the vertex class. -layout(location = 0) in vec3 Position; -layout(location = 1) in vec3 Color; -layout(location = 2) in vec3 Normals; -layout(location = 3) in vec2 Uv; - - -layout(location = 0) out vec3 fragColor; - -// we set our descriptor set to binding = 0 -// meaning that our descriptor set references to GlobalUbo -// layout(set = 0, binding = 0) uniform GlobalLightUbo { -// mat4 Model; // light model -// vec3 Direction; // light dir -// } light_ubo; - -layout(set = 0, binding = 0) uniform GlobalCameraUbo{ - mat4 Projection; - mat4 View; - mat4 Model; - vec3 LightTransform; -} camera_ubo; - -layout(push_constant) uniform Push { - mat4 Projection; - mat4 View; - mat4 Model; - vec3 LightTransform; - vec4 Color; - vec2 MousePosition; -} push; - - - -vec3 dir_to_light = normalize(push.LightTransform); -const float AMBIENT = 0.2; - -/* -void main(){ - gl_Position = (push.Projection * push.View * push.Model) * vec4(Position, 1.0); - - vec3 normalize_world_space = normalize(mat3(push.Model) * Normals); - float LightIntensity = AMBIENT + max(dot(normalize_world_space, dir_to_light), 0); - - vec3 baseColor = LightIntensity * Color * push.Color.xyz; - - // VERY BASIC "PICKING" (Highly Inaccurate) - vec4 screenPos = gl_Position; - // vec4 screenPos = vec4(Position, 1.0); - screenPos.xyz /= screenPos.w; // Perspective divide - - vec2 fragScreenPos = screenPos.xy * 0.5 + 0.5; // NDC to screen space (0-1) - - float dist = length(fragScreenPos - push.MousePosition); // dist in screen space - - float threshold = 0.5; // Adjust this (very sensitive) - - if (dist < threshold) { - fragColor = baseColor; - } else { - // fragColor = baseColor; - fragColor = vec3(1.0, 0.0, 0.0); // Red highlight (or any effect you want) - } -} -*/ - - -void main(){ - gl_Position = (push.Projection * push.View * push.Model) * vec4(Position, 1.0); - - vec3 normalize_world_space = normalize(mat3(push.Model) * Normals); - - float LightIntensity = AMBIENT + max(dot(normalize_world_space, dir_to_light), 0); - - fragColor = LightIntensity * Color * push.Color.xyz; -} diff --git a/shaders/mouse_picking_shaders/simple_shader.vert.spv b/shaders/mouse_picking_shaders/simple_shader.vert.spv deleted file mode 100644 index d2b6e737de65cbc0c2ea0d0a2168ee91080a0255..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3200 zcmZveZF3V<6vr=3lU6JsAP*{HN(IGgeF8+0Qfx6)QW7k!;=}BOWGU-xvzbi-;;Z_? zx6a7$ff!%oj32>|;TvcC|Mu=_cA__Pde8aa|9QCgp1V+*n45BLk9*$jbKg5Z4!Q{; zPFN+IYxVW|LVwU%ICuU%82eo*Bf>c#7GqMf-HN*CuSm{Hu1MA-4aprzNxuorzsqsb z?RB+!P-`@5^=m=9*9-cCM{yX$Q8x@aQ5v=f(Ss1)bb%Lj+wrhdB$UM{<}Rz|=afSs zf-XtW)UiGD&tdghDY7Odi0Y{4~ z_2WKw6K2@7JEys;9k*g73mztE+zI-wQJ2xE0yiS*>;lVOQIKH zPxk+v*4kONV5oHNdfrchwTkWg278V_8bwTx%)O9dz7MIV=!cEplEnPL#{HP=HMt;67_66^$#CY^4*q;TA*kFH2YB~+x0`c&nCmH_5k1*;4V>TW>VB|Fn9gMuh zCLX++5c=z+gn>=(VB0!9Qe3A$u*nJkPHy{rlUa`l+C3}omciZ_)MVJ`th^sF?Tq1I zYAyO<&3%Dkvp%C4F1b!B8vOysgt+kGk#E0d z;=>~!Hs3n1BeHoDRmmR7d~P3u{)-c)Stv!(Y}6*T?nougU)7S$)y+t;%M=uWKfj)rZX+ zE5_%I5#RRrrF8lL|8>orht>PFbhz9*^AhpJ|dw`&Wp80WnypO z#NqDw))0rDAP#$YO#*J5S?O@9662hb4*pni@R^g~2X20+rQ=8cnBN)c;O6&+bbP^W zA8$#gr*0`W_x`p7jA7V2(!toDVGB9N**0|o+~Kr!_BOU-{CX+tQ*ev( zxpaEh?3#3X?up`Zm)9k5z-N>R>8sf4)?)303$xWHzi<}uPMDD z`8D6iE$LwJxI^CeZ3%bCyT^|^+mL|UId0|{ID`5)=U?);Ur8r6JnG^b1NM)Y7bX7! DiW=_j diff --git a/shaders/showcase_shaders/simple_shader.frag b/shaders/showcase_shaders/simple_shader.frag deleted file mode 100644 index 61421f18..00000000 --- a/shaders/showcase_shaders/simple_shader.frag +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - - -layout(location = 0) in vec3 fragColor; -layout(location = 0) out vec4 outColor; - - -// layout(push_constant) uniform Push { -// mat4 Transform; // proj * view * model -// mat4 ModelMatrix; -// vec3 LightTransform; -// } push; -layout(push_constant) uniform Push { - // mat4 Transform; // proj * view * model - mat4 Projection; - mat4 View; - mat4 ModelMatrix; - vec3 LightTransform; -} push; - -void main(){ - // outColor = vec4(fragColor, 0.0); - outColor = vec4(fragColor, 1.0); -} \ No newline at end of file diff --git a/shaders/showcase_shaders/simple_shader.frag.spv b/shaders/showcase_shaders/simple_shader.frag.spv deleted file mode 100644 index 62b514e66dddd2d9cb1f93a70c3212342d44afb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 972 zcmZ9JNlU{}6os$0X`Sb3C5lTyT&M`*03vY_v7)#QrHvYiO-WOSoj*ZP^BA)`o?cuv(^F@7mkyrR}Yq-EA0CR>_EPrmb#OY2>LH zc5sYJCL}ZBfvbT2D#~j1si3Njnd|xP<)!PL`K@l(@1<{1;74I6@Y`V$w9@c7fHzX& zg`HN^Zbqc|BJ)J6e@+ zu-R8(pXdGIb0p_^AJ`jQI%SOg&ScnNF8VFUVH0;EDdNEX$1zhm4x6}lNf8J37dO}s zGsF9kxO!)H25(+BdOdsn0k)+7ny@v=vgRZgHt)EmdqkRi;0L+QuE5}rNyEp6KQ7HI z;PA28CD^8HxKk3d_v01W^ZFw<^;YGjSFl3JL*7Mc>f$FaHg5>Fr!6rTIXLw4C4}7_ y3MI#+gg&l>(!+F)N&RBH89aI|c(XZ1{)RfG*EtFC@bNRxk*d-QzHepNm;3-ZlS~5u diff --git a/shaders/showcase_shaders/simple_shader.vert b/shaders/showcase_shaders/simple_shader.vert deleted file mode 100644 index f74405bf..00000000 --- a/shaders/showcase_shaders/simple_shader.vert +++ /dev/null @@ -1,41 +0,0 @@ -#version 450 - -//! @note Position and Color used in the Vertex class. -layout(location = 0) in vec3 Position; -layout(location = 1) in vec3 Color; -layout(location = 2) in vec3 Normals; -layout(location = 3) in vec2 Uv; - - -layout(location = 0) out vec3 fragColor; - -layout(push_constant) uniform Push { - // mat4 Transform; // proj * view * model - mat4 Projection; - mat4 View; - mat4 ModelMatrix; - vec3 LightTransform; -} push; - -// const vec3 dir_to_light = normalize(vec3(1.0, -3.0, -1.0)); -// vec3 light_transform = vec3(1.0, -3.0, -1.0); -// const vec3 dir_to_light = normalize(vec3(1.0, -3.0, -1.0)); -// vec3 dir_to_light = normalize(push.LightTransform); -// const vec3 dir_to_light = normalize(); -vec3 dir_to_light = normalize(push.LightTransform); - -void main(){ - // -.5f is to temp fix the rolling issue with the sphere. - vec3 newPos = vec3(Position.x,Position.y-0.5f,Position.z); - // vec4 worldPositionSpace = push.ModelMatrix * vec4(newPos, 1.0); - mat4 transform = push.Projection * push.View * push.ModelMatrix; - // gl_Position = push.Transform * vec4(newPos,1.0); - gl_Position = transform * vec4(newPos, 1.0); - - // mat3 normal_mat = transpose(inverse(mat3(push.ModelMatrix))); - vec3 normalize_world_space = normalize(mat3(push.ModelMatrix) * Normals); - float LightIntensity = max(dot(normalize_world_space, dir_to_light), 0) / 1.5f; - - // fragColor = Color; - fragColor = LightIntensity * Color; -} \ No newline at end of file diff --git a/shaders/showcase_shaders/simple_shader.vert.spv b/shaders/showcase_shaders/simple_shader.vert.spv deleted file mode 100644 index 25d9d7b32569ef12696fcb31b3dfe93bef44b705..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2904 zcmZ9OYjaao6owDIaj}4i6ja32s;Fqa0ipq!j$bj9>iZ zjE+Bu@mKl98K39mtTxl#dD&~d>$2Bgdz}oUBQtxGWKZ&3axiHogLNbsfl1&d^1WPH zt<3iN&Dpc(KGfq-GMYQ;a~Lnz7 z<;vAsV`HP%>py9wwN}tU_Bb`~=L}NR`W@1( zKj@<-`c1M|H+v7%C-_r$RlA*EJg-Cb6L`vdx3w(Y(jLCnzSL=^t)+Uun>~i#oBP_0 ziU-~5*4w@No$kZId57RPit{{w3ca0fRXaWH<9VM@vcbs%?rnVfJ8AHmNY2Bpw`$e2 zyOwtQ>0{KqCV7{(NMlX%)}QlPyT6+KN+*pO*t`d}#a6a)CF}L;?MAw7^Df#pTdi%| zIPd0ry2g2rMfNtgthY#9+v;>%&024xPL{#FefQMbGa;gvBNqxqDSi>Acojjj&gLk(d!*S}y&4Y-O z+Z|`GhU3(YdkP{>ZYOR~*C?ER&p?^}IaB(Txrg7!Dc~|kyyM_Y+TpB6&OQ9hA!q*J zl;!*mJj;A>mT%!%q1*E~+gj|mx@V|23f-JXi85}Qoa)L`NE7TOa2$W{t**UZkCsPjUhCnD-#Nd9<5X-S12882VxM64(RI6uR#pbsa(0 zH}V}Tf7t#$x@U&}N66+oiT^ov&$I^n>P$rMwF&cn%5IOe+gEkJb-Aef zB65;Eozs5-Nt?NRziaH)EoZ!abLOl||8Ll}M_=5(1+K{deXc#r^Z$r!E@RB6?#vG7 zzl&~u=c&$a&gkRMg-zag^+v&+=UdayS#z25Ul_k{eVvIZ5NDr8_V+k+?TbUYck{PR z`vO^Fix1r?#U&ev(SnUj){F6==ImCBCh^d7Pz_!1;5=%;Ozj1@htZ8gl%W zgii@h{x|X%^ExPjX%KO5AR9LWBJNFO`D#()TgaYgyf$mJH}d9j9?t;p>YSR#*?bSk zhtDjsKF(_Re1I(f7kP~FKNZHwN8HEA#yQgw_X)Cm#GOSpR^Ix2E4lFh3|UUyzJCt9 z!_A^MUlbhMHg~Due4p^UTyV}#l}yh5957yg?S3PFl2_Y2@N9j&&jS0G!0*alS*!Xy zi2Gha-hE%^L*6>fTLyBj6@F>G({&&(T-H4TBIX9NG4c`f6|%f=?T+~x&KUDVOa)n9 zxFW`RxrV+3ti{~=M$cD}mw~;p-YU>nKE8*W$ma7*?e@p-Og{45LY52tHu8S(H+h}& zHK33DBqzyz2h8gXX!m#L_rm`NWbOX;c-|_zocWFY3CP8HHDrHx{wVHo4_Qt>_EPX02{jX{6H( zyEw)rQ<6FHz*Rth6=gO1R8Z9>%=LWt`r7p_{8q2$_tUp1@T0IB`0X$WT50$az#A*^ z!fq=Xw95oXjB;JaoUC>{NYCRaPE<~allAhDG#?9)xFz`-gZ>konm%k!BZ;4>A8V4D zV!@g7J`7&*7Z|f##qA)V+eb$RI(tPt{$cUhXc_{odS8-g8ZOUy+M4!wK{VRy$u$uTXV sj~k)%Fq>mizZh=@k6sJje2$U7p-$;_K|(xy{LFKrs`P^ITNw@|KRZ}SjQ{`u diff --git a/shaders/sim_shader_transforms/simple_shader.vert b/shaders/sim_shader_transforms/simple_shader.vert deleted file mode 100644 index a2df0b74..00000000 --- a/shaders/sim_shader_transforms/simple_shader.vert +++ /dev/null @@ -1,38 +0,0 @@ -#version 450 - -//! @note Position and Color used in the Vertex class. -layout(location = 0) in vec3 Position; -layout(location = 1) in vec3 Color; -layout(location = 2) in vec3 Normals; -layout(location = 3) in vec2 Uv; - - -layout(location = 0) out vec3 fragColor; - -layout(push_constant) uniform Push { - // mat4 Transform; // proj * view - mat4 Projection; - mat4 View; - mat4 Model; - vec3 LightTransform; -} push; - -// const vec3 dir_to_light = normalize(vec3(1.0, -3.0, -1.0)); -// vec3 light_transform = vec3(1.0, -3.0, -1.0); -// const vec3 dir_to_light = normalize(vec3(1.0, -3.0, -1.0)); -// vec3 dir_to_light = normalize(push.LightTransform); -// const vec3 dir_to_light = normalize(); -vec3 dir_to_light = normalize(push.LightTransform); - -void main(){ - // vec4 worldPositionSpace = push.ModelMatrix * vec3(Position, 1.0); - mat4 transform = push.Projection * push.View; - gl_Position = transform * vec4(Position, 1.0); - - // mat3 normal_mat = transpose(inverse(mat3(push.ModelMatrix))); - vec3 normalize_world_space = normalize(mat3(push.Model) * Normals); - float LightIntensity = max(dot(normalize_world_space, dir_to_light), 0) / 1.5f; - - // fragColor = Color; - fragColor = LightIntensity * Color; -} \ No newline at end of file diff --git a/shaders/sim_shader_transforms/simple_shader.vert.spv b/shaders/sim_shader_transforms/simple_shader.vert.spv deleted file mode 100644 index b5ab4b74a560c1e5bd0d0c780141b1843cf89a29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2584 zcmZ9NU2_yg6oxxlvWXbLh}@e2?|LNMThF3Dn$+o`SW5XKsIw{|BWUUBJ_ zRa*Wa%3tM;RX)$mbh1UKUizH(e0KMlr7^uc8^Tn0H5>`|L$wydG)#bNmV2wc-Ci9R zz154CKGWl9Xq1ln9K*|X2t4j)edY6D1+0NK*aX|4!QV9dKLj2MheNBKw6?Zd?OVyt zaF~pXXL*|BSwBsB*(lv9vL~s2a}$19e<$DTO*+irFX(gbTG<$ z$#~c$b9GMNc(b&R$WAA7(PTjb55aZ-tj`RK|Wt;=7nb-z7*^gmq7_I?`ObI7Tm#mjq= zi!hIQkFc9ZyLr|9p5#uTA7ftxQ{Y0a`~I=71!R3=z7w@MLg%1$iAibf4R09V}0|l0c#rn9lNpCiS=5@uBhKBwHIamACb*v zjQP}^xyk&_ocW!Hd+g@6AM5?Zu1(%}b!SrUGT)AV&Wg*N|HAlv>g${On;L6-c7Lm) z?pZc!{RUAB$gczE$XU5Y4tle>^5!v%PZ?XSN$ny4P-mie1 zYl~kG@B0dn7cTp@&lvMHvN7^8<{M;r;d(jdDx5Lqi80?I%L`YG>2Q;N7uSHjm|Nd? z=hu<_M!XyQT?hKg$Cw3#^KFt2PTe;G~8bYIimyZ=_OI z`IM*pMft1pk}AJnPamDoRcHI0?_B!p(`R;I&*X>Bec%qbVfWG%>yXKkZ`^6EZEdxB`R_^8O5!wXb>eQcmdC$F#0{3>;&d(Pcgg`3MU>CS-lsFtXuFy9 zoU7;_a9Z!SHv~M%x=BZ-$4_Y2QLQ}Fu^X@Q0H;dj+T=u>eJ`K`Z~R$vnQp` z7cI%smCT0v)ZWhXDDAg>Rj?^x|F2hd*M*h&$y8+3&1s*H*Vp^K$fv~VhR1nB zdbX5xH`__kHfr;(S^wSjgjD=H6Ki+o4W22k+3&s5rc57QPlwPqA6V^WB)uedq_L}6l_)-fSe@*tFb}$5c zzjizGX0Ulfu%ohve4Ku?&IfzAFn#_(>BMq|`40um>?5+_2A_|$6U+a^3H^Se9SnO+ z9^TF{IO2onXWFTOAD-B}Ef_p`qnZRRoQr)@f}i|a(Cyx5WTP8z_OlY_cBU==qAcqh zf4J0wkKOBX$$usItsdv!kif_K%B&eb;_gXU@LSZ*S=1*Un^^?2d}fjSu`pxw39&mp zm(Ks~GYL7^F9LQ|Iq;{?Eb9I%gn1;ExgeKXX7it1wkJ#W8R`7rmHkt@?CZPixnR%g zROV(x!mKe*x5R;-@cn~Z%tz9RVWuqRuyk;XIVznP=FDP_Ne6GLDjbhXs7)@u+v))K z1*c9;`?!ReVs5BI-h>34c=~~DzAvPMnSDw+HUCsSa!*T$0VkjSfm!@H>0oA`5BA^6 zrxzC_#DKpE*jLieO7KyWHvr=f%;?t=?!fF)mwEa|0=}$QhS#?N17|T)%*L!vWsa{( ztOheq9r%0~e1C=eU6V~MaJcaPV8-R9bn4uY7?Ga29evm#R0f#U12}V49nU`<}vwxJ%H*0oXI`1_UW@*Ar?OP`Sy)hLpo;@124W4FgtfyI+)o_>2Uueyu*Fz#DH7OL+KABuS3j= wbmGA83xm@m2{_BJ$I`*zYS@#2F(XaghnadRA)k2s%p}~GwB!3v6|PC%0^xku-2eap diff --git a/shaders/sim_shader_ubo_tutorial/simple_shader.vert b/shaders/sim_shader_ubo_tutorial/simple_shader.vert deleted file mode 100644 index 7df065f4..00000000 --- a/shaders/sim_shader_ubo_tutorial/simple_shader.vert +++ /dev/null @@ -1,38 +0,0 @@ -#version 450 - -//! @note Position and Color used in the Vertex class. -layout(location = 0) in vec3 Position; -layout(location = 1) in vec3 Color; -layout(location = 2) in vec3 Normals; -layout(location = 3) in vec2 Uv; - - -layout(location = 0) out vec3 fragColor; -layout(location = 1) out vec3 fragPosWorld; -layout(location = 2) out vec3 fragNormalWorld; - -layout(set = 0, binding = 0) uniform GlobalUbo { - mat4 ProjectionView; - vec4 AmbientLightColor; // w = intensity - vec3 LightPosition; - vec4 LightColor; // w - is light intensity -} ubo; - - -layout(push_constant) uniform Push { - mat4 Transform; // proj * view * model - mat4 ModelMatrix; - vec3 LightTransform; -} push; - - -void main(){ - vec3 newPos = vec3(Position.x, Position.y, Position.z); - gl_Position = push.Transform * vec4(newPos, 1.0); - - - fragNormalWorld = normalize(mat3(push.ModelMatrix) * vec3(Normals.x, Normals.y, Normals.z)); - fragPosWorld = Position.xyz; - fragColor = Color; - -} \ No newline at end of file diff --git a/shaders/sim_shader_ubo_tutorial/simple_shader.vert.spv b/shaders/sim_shader_ubo_tutorial/simple_shader.vert.spv deleted file mode 100644 index 30c27c46f4ec2730f7863c4180b0c623e6fee3cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2760 zcmZ9MX;TzQ5Qd9Wyzg7t2G(O`m-Sw6VNnLxL54utkK@3!*c(kZ(bK5ApZp8^m;6&n56LwYVhPNO!vRfDuL1IbiSA8Cm?XmG_(*(I32IBxRC& zo+G;7IboY=yA>B}aZ$#fWD2ctbbOXF>h}0}?(Oj;D_4{M#EzWG$Gzm6Pm}FuNw4f= z8*$%9*YNG6Y2P=ZUeGHRoFnb6o!)zFcwn<$7oDv4E-$vE8xD`9yc?%Wow7(i`Ew#+ zaA+o*@5@>ewI_vdhuYko_jy-zHeac1C;dAw(yr&gn^jm(_Nae9;?#&LNPhasn}W~h zX=i}&4()fm0}uczTQdStmo3{85pZoJ)(4t~T|{KO1av#^qtwECwF} z&-2>31Acg7^LqmZ&x_h430ycA+ur$%?4M*)mvhI%tbrlciwWuc)PwuIQ6iZcQAU-+*zOCVfR>;P7VCzVKbLtchyUF`pSaKS0Q{a z#4>O6jCylInU}*7W{f#{tQa^Rk$_vwG3mrG7Z!6|I=IE0luiuuWih9ugSS+bGfzvX zO)kDCVhA5_>P%_>Su!bMUZ_J4E=j<#sdHIE-imVIdo^I%`q(c4qn{RcEnxJhrAqX4 zT0%bY_^(L*S6zI+N;sPs_%Ty65@sEK@W&?3_}`Qce`d+}-;xdv59;2LfU%bKD%|O= z1RP<(8=jW)hjenlE$5zeaD??^&V6CzP{(o}NC!t)mctt{^A9C(p*FGhzK^9d|MfX} zA{*Rdo`#tEoXiRXx0tyQQ=gMRy?=L3=4DfRR)UZBphwRn@WX!~%+zz~+<_fGZ^Czt dZS&HQ&TQga(2i}szofqiKE7Yo4t@*QR<&xim3 diff --git a/shaders/simple_shader/compile_shaders.sh b/shaders/simple_shader/compile_shaders.sh deleted file mode 100644 index 5aa7404c..00000000 --- a/shaders/simple_shader/compile_shaders.sh +++ /dev/null @@ -1,2 +0,0 @@ -glslc.exe simple_shader.vert -o simple_shader.vert.spv -glslc.exe simple_shader.frag -o simple_shader.frag.spv diff --git a/shaders/simple_shader/simple_shader.frag b/shaders/simple_shader/simple_shader.frag deleted file mode 100644 index 156225cc..00000000 --- a/shaders/simple_shader/simple_shader.frag +++ /dev/null @@ -1,16 +0,0 @@ -#version 450 - - -// layout(location = 0) in vec3 fragColor; - -layout(location = 0) out vec4 outColor; - -layout(push_constant) uniform Push { - vec2 offset; - vec3 color; -} push; - -void main(){ - // outColor = vec4(fragColor, 0.0); - outColor = vec4(push.color, 0.0); -} \ No newline at end of file diff --git a/shaders/simple_shader/simple_shader.frag.spv b/shaders/simple_shader/simple_shader.frag.spv deleted file mode 100644 index f9f7271b79db2df632b0a5e8c396e185cd9cdc8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 756 zcmYk2T}#4X9K|1BW~TX;sdXcUmw|Lq5kx^mtc!t0A7I3sG+0jD4ElO~s&0bLZ!X&d zXaAk^od4TXDvtMzDVVxxm=m)-9aEHIq*c;rJ1@>8PUe$~%X1t}Q%a3^TJn??!TW2l zqI)L*EU9rSHyzweKathmWtC^94&U z+|2U^OOAX`%UEgOXp=ldVYF5|DP?n@INQW;@QM^TCt56GKl#_##mf@OYl^S3JX@Td zh63j)S7*GHb{cii+JddU>BsI}eTk>(YizZ?{wvZ(!azNED>!?N^sOrL(&#rCXAU&{ zHAVc?h1WCA{ZO3Vc+jcWP$VCndT{nc>xs7%M?yh3%Q$<$$?quQr5^Y6J`y-rdK2bg zb`CRqOR*I1^(FUEpdU4F<)ltmK!28pdc90j*lGPtV~#)HAk*kM(+lxN#{&8Ixo5UJ NO~TCF{b-YG;TOGkHy8i_ diff --git a/shaders/simple_shader/simple_shader.vert b/shaders/simple_shader/simple_shader.vert deleted file mode 100644 index 243562cb..00000000 --- a/shaders/simple_shader/simple_shader.vert +++ /dev/null @@ -1,17 +0,0 @@ -#version 450 - -layout(location = 0) in vec2 Position; -layout(location = 1) in vec3 Color; - -// layout(location = 0) out vec3 fragColor; - -layout(push_constant) uniform Push { - vec2 offset; - vec3 color; -} push; - -void main(){ - // gl_Position = vec4(Position, 0.0, 1.0); - gl_Position = vec4(Position + push.offset, 0.0, 1.0); - // fragColor = Color; -} \ No newline at end of file diff --git a/shaders/simple_shader/simple_shader.vert.spv b/shaders/simple_shader/simple_shader.vert.spv deleted file mode 100644 index 5b8a97571b2c3df05c565bc324a4359f94fb047c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1224 zcmYk4T~8B16o!Yk3kU)t@}*c?t5+t(3pFG}jRCS=Gyy~6?S^azon+l@x?3Y$>0k3# zd1K=H% z?TK(U%(C}8`u}$2a)LGKed#l4TfdgE-RXr2&>G2buJoU7{bB}*>sT>W+V`k+}GB-YTWp$OOc9vs%a?>oE;KPfB zut!&lz-I?!P@5S>53qYuYQPIMn3o!GwuFNB#i1|$j=V+Lo^)3|^+EcWdA1evh4rM! zizdD!pLz$1S7bR4)|JQnp$0j$C*EDzu~l`SfCU z;(_dflz!AF<}JY9=q=fUJ4QJ7M@S_5RwzBUr0nxSD6{NKnU6aOoQDnmOB~KTl5!6G ulQ3rH?ZJ_NJ&_N_EEk%%p1J0dV^4OYcVG6Yl((YyJ55X6lm1nOBk4aKH(fRW From 43b91a3a655e6854715fe2e81cd61e2143ea9444 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 17:09:20 -0700 Subject: [PATCH 010/106] Added the render_context class for preparing rendering operations automation --- CMakeLists.txt | 1 + atlas/core/application.cppm | 12 ++++++--- atlas/drivers/vulkan/render_context.cppm | 34 ++++++++++++++++++++++++ atlas/drivers/vulkan/vulkan.cppm | 3 ++- 4 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 atlas/drivers/vulkan/render_context.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index e57a95dc..0471e771 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -201,6 +201,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/vulkan/vulkan.cppm atlas/drivers/vulkan/graphics_context.cppm atlas/drivers/vulkan/window.cppm + atlas/drivers/vulkan/render_context.cppm atlas/drivers/vulkan/utilities.cppm atlas/drivers/vulkan/environment_map.cppm atlas/drivers/vulkan/stb_image.cppm diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 65b85175..4dfc7b0c 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -131,6 +131,8 @@ export namespace atlas { m_command_buffers[i] = vk::command_buffer(*m_device, command_params); } + m_render_context = render_context(m_context); + std::println("images.size() = {}", images.size()); } @@ -259,16 +261,20 @@ export namespace atlas { private: uint32_t m_next_image_frame_idx=0; VkFormat m_depth_format; + std::shared_ptr m_context; + std::shared_ptr m_window=nullptr; + event::bus* m_bus = nullptr; + + render_context m_render_context; + + // vulkan-cpp specific handles vk::instance m_instance; std::optional m_physical; std::shared_ptr m_device; - std::shared_ptr m_context; - std::shared_ptr m_window=nullptr; vk::image_extent m_extent{}; std::vector m_images; std::vector m_depth_images; std::vector m_command_buffers; - event::bus* m_bus = nullptr; static application* s_instance; }; diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm new file mode 100644 index 00000000..83f72969 --- /dev/null +++ b/atlas/drivers/vulkan/render_context.cppm @@ -0,0 +1,34 @@ +module; + +#include +#include + +export module atlas.drivers.vulkan:render_context; + +import :graphics_context; +import vk; + +export namespace atlas { + + /** + * @brief Core render context to schedule images and barriers for coordinating rendering operations + * + * Manages multiple render contexts + */ + class render_context { + public: + render_context() = default; + render_context(std::shared_ptr p_context) { + m_device = p_context->logical_device(); + + std::println("Constructing render_context(shared_ptr)"); + } + + + void destruct() { + } + + private: + std::shared_ptr m_device; + }; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/vulkan.cppm b/atlas/drivers/vulkan/vulkan.cppm index 29c76d37..6d67c97c 100644 --- a/atlas/drivers/vulkan/vulkan.cppm +++ b/atlas/drivers/vulkan/vulkan.cppm @@ -4,4 +4,5 @@ export module atlas.drivers.vulkan; export import :window; -export import :graphics_context; \ No newline at end of file +export import :graphics_context; +export import :render_context; \ No newline at end of file From 60c4b92addd51eb686fbc79a0d3f9bedb28e8966 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 17:26:18 -0700 Subject: [PATCH 011/106] refactor: reworking render to use dynamic rendering and get triangle working once again --- atlas/core/application.cppm | 9 ++- atlas/drivers/vulkan/render_context.cppm | 72 +++++++++++++++++++++++- builtin.shaders/compile.bat | 6 +- builtin.shaders/pbr.frag | 9 +++ builtin.shaders/pbr.vert | 27 +++++++++ 5 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 builtin.shaders/pbr.frag create mode 100644 builtin.shaders/pbr.vert diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 4dfc7b0c..55faf26d 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -77,6 +77,7 @@ export namespace atlas { vk::format::d24_unorm_s8_uint }; + m_color_format = m_window->surface_properties().format.format; // We provide a selection of format support that we want to check is // supported on current hardware device. m_depth_format = m_physical->request_depth_format(format_support); @@ -131,7 +132,7 @@ export namespace atlas { m_command_buffers[i] = vk::command_buffer(*m_device, command_params); } - m_render_context = render_context(m_context); + m_render_context = render_context(m_context, m_color_format, m_depth_format); std::println("images.size() = {}", images.size()); } @@ -221,10 +222,11 @@ export namespace atlas { current.set_scissor(0, 1, std::span(&scissor, 1)); current.begin_rendering(begin_params); + m_render_context.set_command(current); + // Do drawing stuff... + m_render_context.bind_pipeline(); - - // Do rendering stuff... current.end_rendering(); m_images[m_next_image_frame_idx].memory_barrier( @@ -260,6 +262,7 @@ export namespace atlas { private: uint32_t m_next_image_frame_idx=0; + VkFormat m_color_format; VkFormat m_depth_format; std::shared_ptr m_context; std::shared_ptr m_window=nullptr; diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 83f72969..b5491f1b 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -2,6 +2,10 @@ module; #include #include +#include +#include + +#include export module atlas.drivers.vulkan:render_context; @@ -18,17 +22,83 @@ export namespace atlas { class render_context { public: render_context() = default; - render_context(std::shared_ptr p_context) { + render_context(std::shared_ptr p_context, VkFormat p_color_format, VkFormat p_depth_format) { m_device = p_context->logical_device(); std::println("Constructing render_context(shared_ptr)"); + + // gets set with the renderpass + // std::array color = { 0.f, 0.5f, 0.5f, 1.f }; + + // Loading graphics pipeline + std::array shader_sources = { + vk::shader_source{ + .filename = "builtin.shaders/pbr.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "builtin.shaders/pbr.frag.spv", + .stage = vk::shader_stage::fragment, + }, + }; + + // To render triangle, we do not need to set any vertex attributes + vk::shader_resource_info shader_info = { + .sources = shader_sources, + }; + // vk::shader_resource geometry_resource(logical_device, shader_info); + m_shader_resource = vk::shader_resource(*m_device, shader_info); + std::array color_blend_attachments = { + vk::color_blend_attachment_state{}, + }; + + std::array dynamic_states = { + vk::dynamic_state::viewport, vk::dynamic_state::scissor + }; + + uint32_t format = static_cast(p_color_format); + vk::pipeline_params pipeline_configuration = { + .use_render_pipeline = true, + .color_attachment_formats = std::span(&format, 1), + .depth_format = static_cast(p_depth_format), + .stencil_format = static_cast(p_depth_format), + .renderpass = nullptr, + .shader_modules = m_shader_resource.handles(), + .vertex_attributes = m_shader_resource.vertex_attributes(), + .vertex_bind_attributes = m_shader_resource.vertex_bind_attributes(), + .color_blend = { + .attachments = color_blend_attachments, + }, + .depth_stencil_enabled = true, + .dynamic_states = dynamic_states, + }; + m_main_pipeline = vk::pipeline(*m_device, pipeline_configuration); + std::println("After constructing vk::pipeline"); + } + + + void set_command(vk::command_buffer& p_command) { + m_current_command = &p_command; + } + + + void bind_pipeline() { + // m_current_command + m_main_pipeline.bind(*m_current_command); + + vkCmdDraw(*m_current_command, 3, 1, 0, 0); } void destruct() { + m_shader_resource.destruct(); + m_main_pipeline.destruct(); } private: std::shared_ptr m_device; + vk::command_buffer* m_current_command=nullptr; + vk::shader_resource m_shader_resource; + vk::pipeline m_main_pipeline; }; }; \ No newline at end of file diff --git a/builtin.shaders/compile.bat b/builtin.shaders/compile.bat index d6fd90fe..7bd159b6 100644 --- a/builtin.shaders/compile.bat +++ b/builtin.shaders/compile.bat @@ -1,4 +1,6 @@ -glslc.exe builtin.shaders/test.vert -o builtin.shaders/test.vert.spv -glslc.exe builtin.shaders/test.frag -o builtin.shaders/test.frag.spv +@REM glslc.exe builtin.shaders/test.vert -o builtin.shaders/test.vert.spv +@REM glslc.exe builtin.shaders/test.frag -o builtin.shaders/test.frag.spv +glslc.exe builtin.shaders/pbr.vert -o builtin.shaders/pbr.vert.spv +glslc.exe builtin.shaders/pbr.frag -o builtin.shaders/pbr.frag.spv echo Finished Compiling GLSL Shaders \ No newline at end of file diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag new file mode 100644 index 00000000..60325b6b --- /dev/null +++ b/builtin.shaders/pbr.frag @@ -0,0 +1,9 @@ +#version 460 + +layout(location = 0) in vec3 fragColor; + +layout(location = 0) out vec4 outColor; + +void main() { + outColor = vec4(fragColor, 1.0); +} \ No newline at end of file diff --git a/builtin.shaders/pbr.vert b/builtin.shaders/pbr.vert new file mode 100644 index 00000000..60361b01 --- /dev/null +++ b/builtin.shaders/pbr.vert @@ -0,0 +1,27 @@ +#version 460 + +// #extension GL_EXT_nonuniform_qualifier : enable // Required for descriptor indexing + +// layout(location = 0) in vec3 inPosition; +// layout(location = 1) in vec3 inColor; +// layout(location = 2) in vec3 inNormals; +// layout(location = 3) in vec2 inTexCoords; + +layout(location = 0) out vec3 fragColor; + +vec2 positions[3] = vec2[]( + vec2(0.0, -0.5), + vec2(0.5, 0.5), + vec2(-0.5, 0.5) +); + +vec3 colors[3] = vec3[]( + vec3(1.0, 0.0, 0.0), + vec3(0.0, 1.0, 0.0), + vec3(0.0, 0.0, 1.0) +); + +void main() { + gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); + fragColor = colors[gl_VertexIndex]; +} \ No newline at end of file From 6d3ecac2976fac9ed52c1f0c58928c6a3377b867 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 28 May 2026 17:29:36 -0700 Subject: [PATCH 012/106] refactor: Called destruct call for render_context to ensure proper cleanup --- atlas/core/application.cppm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 55faf26d..6d0e0d06 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -245,6 +245,8 @@ export namespace atlas { void post_destroy() { std::println("Post destroy!"); + m_render_context.destruct(); + for(auto& command : m_command_buffers) { command.destruct(); } From 080ba6c49eb44c6026086d14e349ee178ce0c954 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 29 May 2026 13:26:48 -0700 Subject: [PATCH 013/106] refactor: Added backt the level scene code --- atlas/core/application.cppm | 25 +++++++++++++++++-- atlas/drivers/vulkan/graphics_context.cppm | 1 - atlas/drivers/vulkan/render_context.cppm | 29 ++++++++++++++++------ editor/CMakeLists.txt | 4 +-- editor/application.cpp | 24 +++++------------- editor/editor.cppm | 4 +-- editor/editor_world.cppm | 4 +-- editor/level_scene.cppm | 4 +-- 8 files changed, 58 insertions(+), 37 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 6d0e0d06..2a7358e4 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -27,6 +27,9 @@ import atlas.core.event; import vk; import atlas.drivers.vulkan; +import atlas.core.scene; +import atlas.core.scene.world; + export namespace atlas { /** @@ -146,7 +149,16 @@ export namespace atlas { .depthStencil = { .depth = 1.f, .stencil = 0 }, }; + std::shared_ptr current_scene = m_world->current(); + + auto start_time = std::chrono::high_resolution_clock::now(); + invoke_start(current_scene.get()); + while(m_window->available()) { + auto current_time = std::chrono::high_resolution_clock::now(); + m_delta_time = std::chrono::duration(current_time - start_time).count(); + + start_time = current_time; event::flush_events(); m_next_image_frame_idx = m_window->acquire_next_frame(); @@ -154,6 +166,10 @@ export namespace atlas { vk::command_buffer current = m_command_buffers[m_next_image_frame_idx]; + invoke_physics_update(current_scene.get()); + + invoke_on_update(current_scene.get(), m_delta_time); + current.begin(vk::command_usage::simulatneous_use_bit); m_images[m_next_image_frame_idx].memory_barrier( @@ -243,8 +259,6 @@ export namespace atlas { } void post_destroy() { - std::println("Post destroy!"); - m_render_context.destruct(); for(auto& command : m_command_buffers) { @@ -262,6 +276,10 @@ export namespace atlas { m_device->destruct(); } + void current_world(std::shared_ptr p_world) { + m_world = p_world; + } + private: uint32_t m_next_image_frame_idx=0; VkFormat m_color_format; @@ -272,6 +290,8 @@ export namespace atlas { render_context m_render_context; + std::shared_ptr m_world; + // vulkan-cpp specific handles vk::instance m_instance; std::optional m_physical; @@ -280,6 +300,7 @@ export namespace atlas { std::vector m_images; std::vector m_depth_images; std::vector m_command_buffers; + float m_delta_time=0.f; static application* s_instance; }; diff --git a/atlas/drivers/vulkan/graphics_context.cppm b/atlas/drivers/vulkan/graphics_context.cppm index 21fac22e..45598eb5 100644 --- a/atlas/drivers/vulkan/graphics_context.cppm +++ b/atlas/drivers/vulkan/graphics_context.cppm @@ -42,7 +42,6 @@ export namespace atlas { ~graphics_context() = default; void post_cleanup() { - std::println("post_cleanup!"); for (const auto& callback : m_submit_resource_free) { callback(); } diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index b5491f1b..8c0dc9fc 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -6,14 +6,29 @@ module; #include #include +#include export module atlas.drivers.vulkan:render_context; +import atlas.core.scene; import :graphics_context; import vk; export namespace atlas { + struct mesh { + uint32_t index_count=0; + uint32_t instance=0; + uint32_t first_index=0; + uint32_t vertex_offset=0; + uint32_t first_instance=0; + }; + + struct gpu_mesh_data { + vk::buffer vertex; + vk::buffer index; + }; + /** * @brief Core render context to schedule images and barriers for coordinating rendering operations * @@ -25,11 +40,6 @@ export namespace atlas { render_context(std::shared_ptr p_context, VkFormat p_color_format, VkFormat p_depth_format) { m_device = p_context->logical_device(); - std::println("Constructing render_context(shared_ptr)"); - - // gets set with the renderpass - // std::array color = { 0.f, 0.5f, 0.5f, 1.f }; - // Loading graphics pipeline std::array shader_sources = { vk::shader_source{ @@ -73,7 +83,6 @@ export namespace atlas { .dynamic_states = dynamic_states, }; m_main_pipeline = vk::pipeline(*m_device, pipeline_configuration); - std::println("After constructing vk::pipeline"); } @@ -82,8 +91,11 @@ export namespace atlas { } + void current_scene(flecs::world& p_world) { + m_world = &p_world; + } + void bind_pipeline() { - // m_current_command m_main_pipeline.bind(*m_current_command); vkCmdDraw(*m_current_command, 3, 1, 0, 0); @@ -100,5 +112,8 @@ export namespace atlas { vk::command_buffer* m_current_command=nullptr; vk::shader_resource m_shader_resource; vk::pipeline m_main_pipeline; + std::vector m_indirect_commands; + std::vector m_mesh_metadata; + flecs::world* m_world=nullptr; }; }; \ No newline at end of file diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index d4ca0137..c0dfbc88 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -9,8 +9,8 @@ target_sources(editor PUBLIC TYPE CXX_MODULES FILES editor.cppm - # editor_world.ppm - # level_scene.cppm + editor_world.cppm + level_scene.cppm # content_browser_panel.cppm # icon.cppm # utilities.cppm diff --git a/editor/application.cpp b/editor/application.cpp index 7cab1617..3ac8e1cb 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -6,7 +6,7 @@ import atlas.application; import atlas.common; import atlas.core.level_streamer; import atlas.core.event; -// import editor; +import editor; import atlas.drivers.vulkan; class editor_application : public atlas::application { @@ -16,29 +16,17 @@ class editor_application : public atlas::application { atlas::event::bus& p_bus) : atlas::application(p_context, p_settings, p_bus) { - // m_world = - // atlas::create_ref("Editor World", p_bus, m_stream); + m_world = + std::make_shared("Editor World", p_bus, m_stream); - // current_world(m_world); + current_world(m_world); } private: - // atlas::ref m_world; - // atlas::level_streamer m_stream; + std::shared_ptr m_world; + atlas::level_streamer m_stream; }; -// atlas::ref -// initialize_application( -// /*NOLINT*/ atlas::ref p_contetxt, -// atlas::event::bus& p_bus) { -// atlas::application_settings settings = { -// .name = "Editor", -// .width = 1510, -// .height = 877, -// .background_color = { 0.f, 0.f, 0.f, 0.f }, -// }; -// return create_ref(p_contetxt, settings, p_bus); -// } atlas::ref initialize_application(std::shared_ptr p_context, atlas::event::bus& p_bus) { atlas::application_settings settings = { diff --git a/editor/editor.cppm b/editor/editor.cppm index 0621e209..0dcff35a 100644 --- a/editor/editor.cppm +++ b/editor/editor.cppm @@ -3,8 +3,8 @@ module; export module editor; -// export import :world; -// export import :level_scene; +export import :world; +export import :level_scene; // export import :icon; // export import :content_browser; // export import :utilities; \ No newline at end of file diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index c7e59121..72825030 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -25,11 +25,11 @@ public: // Create defualt scene to level streamer // Does polymorphic allocations for these customized scenes - // default_custom_scene("LevelScene", p_bus); + default_custom_scene("LevelScene", p_bus); // Set what our current scene is // TODO: Probably have `default_custom_scene() set this - // current("LevelScene"); + current("LevelScene"); } ~editor_world() override = default; diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 213c9499..2abeb1dd 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -1,6 +1,7 @@ module; #include +#include export module editor:level_scene; @@ -24,14 +25,11 @@ public: ~level_scene() override = default; void start() { - console_log_info("preload_start invoked!"); } void on_update(float) { - console_log_info("on_update invoked!"); } void physics_update() { - console_log_info("physics_update invoked!"); } }; \ No newline at end of file From 6d5e3ac192601c622530229c7440556c65cd867c Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 29 May 2026 17:33:41 -0700 Subject: [PATCH 014/106] Reworked some of the API to start integrating into the renderer --- atlas/core/application.cppm | 31 +++----------- atlas/drivers/vulkan/render_context.cppm | 52 ++++++++++++++++-------- 2 files changed, 41 insertions(+), 42 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 2a7358e4..cf7b0957 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -172,6 +172,8 @@ export namespace atlas { current.begin(vk::command_usage::simulatneous_use_bit); + m_render_context.set_command(current); + m_images[m_next_image_frame_idx].memory_barrier( current, m_window->surface_properties().format.format, @@ -220,30 +222,9 @@ export namespace atlas { .stencil_attachment = depth_stencil_attachment, }; - vk::viewport_params viewport = { - .x = 0.0f, - .y = 0.0f, - .width = static_cast(current_extent.width), - .height = static_cast(current_extent.height), - .min_depth = 0.0f, - .max_depth = 1.0f, - }; - current.set_viewport(0, 1, std::span(&viewport, 1)); - - vk::scissor_params scissor = { - .offset = { 0, 0 }, - .extent = current_extent, - }; - - current.set_scissor(0, 1, std::span(&scissor, 1)); - - current.begin_rendering(begin_params); - m_render_context.set_command(current); - // Do drawing stuff... - - m_render_context.bind_pipeline(); + m_render_context.begin(begin_params, current_extent); - current.end_rendering(); + m_render_context.end(); m_images[m_next_image_frame_idx].memory_barrier( current, @@ -252,8 +233,8 @@ export namespace atlas { VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); current.end(); - std::array commands = {current}; - m_window->submit(commands); + const VkCommandBuffer command = current; + m_window->submit(std::span(&command, 1)); m_window->present(m_next_image_frame_idx); } } diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 8c0dc9fc..be8ddbb7 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -4,6 +4,7 @@ module; #include #include #include +#include #include #include @@ -15,20 +16,16 @@ import :graphics_context; import vk; export namespace atlas { - - struct mesh { + struct gpu_mesh_data { + vk::buffer vertex; + vk::buffer index; uint32_t index_count=0; - uint32_t instance=0; + uint32_t instance=1; uint32_t first_index=0; uint32_t vertex_offset=0; uint32_t first_instance=0; }; - struct gpu_mesh_data { - vk::buffer vertex; - vk::buffer index; - }; - /** * @brief Core render context to schedule images and barriers for coordinating rendering operations * @@ -39,7 +36,7 @@ export namespace atlas { render_context() = default; render_context(std::shared_ptr p_context, VkFormat p_color_format, VkFormat p_depth_format) { m_device = p_context->logical_device(); - + // Loading graphics pipeline std::array shader_sources = { vk::shader_source{ @@ -85,6 +82,33 @@ export namespace atlas { m_main_pipeline = vk::pipeline(*m_device, pipeline_configuration); } + void begin(vk::rendering_begin_parameters p_begin_params, const auto& p_extent) { + vk::viewport_params viewport = { + .x = 0.0f, + .y = 0.0f, + .width = static_cast(p_extent.width), + .height = static_cast(p_extent.height), + .min_depth = 0.0f, + .max_depth = 1.0f, + }; + m_current_command->set_viewport(0, 1, std::span(&viewport, 1)); + + vk::scissor_params scissor = { + .offset = { 0, 0 }, + .extent = p_extent, + }; + m_current_command->set_scissor(0, 1, std::span(&scissor, 1)); + + m_current_command->begin_rendering(p_begin_params); + + m_main_pipeline.bind(*m_current_command); + + vkCmdDraw(*m_current_command, 3, 1, 0, 0); + } + + void end() { + m_current_command->end_rendering(); + } void set_command(vk::command_buffer& p_command) { m_current_command = &p_command; @@ -95,13 +119,6 @@ export namespace atlas { m_world = &p_world; } - void bind_pipeline() { - m_main_pipeline.bind(*m_current_command); - - vkCmdDraw(*m_current_command, 3, 1, 0, 0); - } - - void destruct() { m_shader_resource.destruct(); m_main_pipeline.destruct(); @@ -113,7 +130,8 @@ export namespace atlas { vk::shader_resource m_shader_resource; vk::pipeline m_main_pipeline; std::vector m_indirect_commands; - std::vector m_mesh_metadata; + // std::vector m_mesh_metadata; + std::unordered_map m_mesh_metadata; flecs::world* m_world=nullptr; }; }; \ No newline at end of file From 73f9d1ba7aad6e77c2724c601b4d29b766d9400f Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 29 May 2026 23:45:00 -0700 Subject: [PATCH 015/106] refactor: Getting viking demo using variety of modern Vulkan features to work --- atlas/core/application.cppm | 7 + atlas/core/entry_point/main.cpp | 10 + atlas/drivers/importer/importer.cppm | 6 + atlas/drivers/importer/obj_loader.cppm | 125 +++++++++++ atlas/drivers/vulkan/render_context.cppm | 260 +++++++++++++++++++++-- atlas/drivers/vulkan/stb_image.cppm | 2 +- builtin.shaders/pbr.frag | 12 +- builtin.shaders/pbr.frag.spv | Bin 0 -> 1092 bytes builtin.shaders/pbr.vert | 45 ++-- builtin.shaders/pbr.vert.spv | Bin 0 -> 2596 bytes 10 files changed, 428 insertions(+), 39 deletions(-) create mode 100644 atlas/drivers/importer/importer.cppm create mode 100644 atlas/drivers/importer/obj_loader.cppm create mode 100644 builtin.shaders/pbr.frag.spv create mode 100644 builtin.shaders/pbr.vert.spv diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index cf7b0957..80e655b6 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -151,9 +151,16 @@ export namespace atlas { std::shared_ptr current_scene = m_world->current(); + // Setting the current scene for the renderer to start rendering the objects + m_render_context.current_scene(*current_scene); + auto start_time = std::chrono::high_resolution_clock::now(); invoke_start(current_scene.get()); + + + m_render_context.prebake(); + while(m_window->available()) { auto current_time = std::chrono::high_resolution_clock::now(); m_delta_time = std::chrono::duration(current_time - start_time).count(); diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index bf03aaa1..24b9d0ea 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -127,6 +127,16 @@ main() { vk::dynamic_rendering_feature{ { .dynamicRendering = true, } }, + vk::descriptor_indexing_feature{ { + .shaderSampledImageArrayNonUniformIndexing = true, + .descriptorBindingSampledImageUpdateAfterBind = true, + .descriptorBindingPartiallyBound = true, + .descriptorBindingVariableDescriptorCount = true, + .runtimeDescriptorArray = true, + } }, + vk::buffer_device_address{ { + .bufferDeviceAddress = true, + } }, }; vk::device_params logical_device_params = { diff --git a/atlas/drivers/importer/importer.cppm b/atlas/drivers/importer/importer.cppm new file mode 100644 index 00000000..e745b282 --- /dev/null +++ b/atlas/drivers/importer/importer.cppm @@ -0,0 +1,6 @@ +module; + +export module atlas.drivers.importer; + +// Importers to load .obj 3D models +export import :obj_loader; \ No newline at end of file diff --git a/atlas/drivers/importer/obj_loader.cppm b/atlas/drivers/importer/obj_loader.cppm new file mode 100644 index 00000000..0c582998 --- /dev/null +++ b/atlas/drivers/importer/obj_loader.cppm @@ -0,0 +1,125 @@ +module; + +#include +#include +#include +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +export module atlas.drivers.importer:obj_loader; + +import vk; + +template +void +hash_combine(size_t& seed, const T& v, const Rest&... rest) { + seed ^= std::hash()(v) + 0x9e3779b9 + (seed << 6) + (seed << 2); + (hash_combine(seed, rest), ...); +} + +namespace std { + + template<> + struct hash { + size_t operator()(const vk::vertex_input& vertex) const { + size_t seed = 0; + hash_combine( + seed, vertex.position, vertex.color, vertex.normals, vertex.uv); + return seed; + } + }; +} + +export namespace atlas { + class obj_importer { + public: + obj_importer(std::string_view p_path) { + m_load = load(p_path); + } + + bool load(std::string_view p_path) { + tinyobj::attrib_t attrib; + std::vector shapes; + std::vector materials; + std::string warn, err; + + if(!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, p_path.data())) { + return false; + } + + std::unordered_map unique_vertices{}; + + for(const auto& shape_face : shapes) { + for(const auto& index : shape_face.mesh.indices) { + vk::vertex_input vertex{}; + + if(!unique_vertices.contains(vertex)) { + unique_vertices[vertex] = static_cast(m_vertices.size()); + m_vertices.push_back(vertex); + } + + if(index.vertex_index >= 0) { + vertex.position = { + attrib.vertices[3 * index.vertex_index + 0], + attrib.vertices[3 * index.vertex_index + 1], + attrib.vertices[3 * index.vertex_index + 2] + }; + + vertex.color = { + attrib.colors[3 * index.vertex_index + 0], + attrib.colors[3 * index.vertex_index + 1], + attrib.colors[3 * index.vertex_index + 2] + }; + } + + if (index.normal_index >= 0) { + vertex.normals = { + attrib.normals[3 * index.normal_index + 0], + attrib.normals[3 * index.normal_index + 1], + attrib.normals[3 * index.normal_index + 2] + }; + } + + if (index.texcoord_index >= 0) { + vertex.uv = { + attrib.texcoords[2 * index.texcoord_index + 0], + 1.0f - attrib.texcoords[2 * index.texcoord_index + 1] + }; + } + + if (!unique_vertices.contains(vertex)) { + unique_vertices[vertex] = + static_cast(m_vertices.size()); + m_vertices.push_back(vertex); + } + + m_indices.push_back(unique_vertices[vertex]); + } + } + + return true; + } + + [[nodiscard]] bool is_load() const { + return m_load; + } + + //! @return the geometry vertices + std::span vertices() { + return m_vertices; + } + + //! @return the geometry indices + std::span indices() { + return m_indices; + } + + private: + std::vector m_vertices; + std::vector m_indices; + bool m_load=false; + }; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index be8ddbb7..a6f48129 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -5,25 +5,57 @@ module; #include #include #include +#include +#include #include #include - +#define GLM_FORCE_RADIANS +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include export module atlas.drivers.vulkan:render_context; import atlas.core.scene; +import atlas.drivers.importer; +import atlas.core.scene; +import atlas.core.scene.components; +import atlas.drivers.vulkan.stb_image; + import :graphics_context; import vk; export namespace atlas { + + struct gpu_push_constant { + glm::mat4 proj; + glm::mat4 view; + glm::mat4 model; + }; + struct gpu_mesh_data { - vk::buffer vertex; - vk::buffer index; + vk::vertex_buffer vertex; + vk::index_buffer index; uint32_t index_count=0; uint32_t instance=1; uint32_t first_index=0; uint32_t vertex_offset=0; uint32_t first_instance=0; + bool has_indices_buffer=false; + uint32_t vertices_size = 0; + uint32_t indices_size=0; + }; + + struct push_constant_data { + int32_t texture_index=0; + uint64_t buffer_address=0; + }; + + struct global_uniform { + glm::mat4 model=glm::mat4(1.f); + glm::mat4 view=glm::mat4(1.f); + glm::mat4 proj=glm::mat4(1.f); }; /** @@ -35,17 +67,48 @@ export namespace atlas { public: render_context() = default; render_context(std::shared_ptr p_context, VkFormat p_color_format, VkFormat p_depth_format) { + m_physical = p_context->physical_device(); m_device = p_context->logical_device(); - - // Loading graphics pipeline + + // Vertex Attributes Parameters + std::array attribute_entries = { + vk::vertex_attribute_entry{ + .location = 0, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, position), + }, + vk::vertex_attribute_entry{ + .location = 1, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, color), + }, + vk::vertex_attribute_entry{ + .location = 2, + .format = vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, uv), + }, + vk::vertex_attribute_entry{ + .location = 3, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, normals), + } + }; + std::array attributes = { + vk::vertex_attribute{ + .binding = 0, + .entries = attribute_entries, + .stride = sizeof(vk::vertex_input), + .input_rate = vk::input_rate::vertex, + }, + }; std::array shader_sources = { vk::shader_source{ - .filename = "builtin.shaders/pbr.vert.spv", - .stage = vk::shader_stage::vertex, + .filename = "builtin.shaders/pbr.vert.spv", + .stage = vk::shader_stage::vertex, }, vk::shader_source{ - .filename = "builtin.shaders/pbr.frag.spv", - .stage = vk::shader_stage::fragment, + .filename = "builtin.shaders/pbr.frag.spv", + .stage = vk::shader_stage::fragment, }, }; @@ -53,33 +116,136 @@ export namespace atlas { vk::shader_resource_info shader_info = { .sources = shader_sources, }; - // vk::shader_resource geometry_resource(logical_device, shader_info); m_shader_resource = vk::shader_resource(*m_device, shader_info); + m_shader_resource.vertex_attributes(attributes); + + + // Configuring Descriptor Set 0 -- specify to vk::pipeline + // Descriptor Set 0 + std::array entries_set1 = { + vk::descriptor_entry{ + // layout (set = 0, binding = 1) uniform sampler2D textures[]; + .type = vk::descriptor_type::combined_image_sampler, + .binding_point = { + .binding = 1, + .stage = vk::shader_stage::fragment, + }, + .descriptor_count = 1, + .flags = vk::descriptor_bind_flags::partially_bound_bit | + vk::descriptor_bind_flags::variable_descriptor_count_bit | + vk::descriptor_bind_flags::update_after_bind, + } + }; + + // layout(set = 0, ...) + uint32_t max_descriptor = 1; + vk::descriptor_layout set0_layout = { + .slot = 0, + .max_sets = 3, + .entries = entries_set1, // descriptor layout entries description + .descriptor_counts = std::span(&max_descriptor, 1), + }; + set0_resource = vk::descriptor_resource(*m_device, set0_layout, vk::descriptor_layout_flags::update_after_bind_pool); + std::array color_blend_attachments = { vk::color_blend_attachment_state{}, }; std::array dynamic_states = { - vk::dynamic_state::viewport, vk::dynamic_state::scissor + vk::dynamic_state::viewport, vk::dynamic_state::scissor, + }; + + m_format = static_cast(p_color_format); + uint32_t vertex_mask = static_cast(vk::shader_stage::vertex); + uint32_t fragment_mask = static_cast(vk::shader_stage::fragment); + uint32_t stage_mask = vertex_mask | fragment_mask; + m_stage = static_cast(stage_mask); + vk::push_constant_range range = { + .stage = m_stage, + .offset = 0, + .range = sizeof(push_constant_data), }; - uint32_t format = static_cast(p_color_format); + // const VkDescriptorSetLayout layout = set0_resource.layout(); + std::array layouts = {set0_resource.layout()}; vk::pipeline_params pipeline_configuration = { .use_render_pipeline = true, - .color_attachment_formats = std::span(&format, 1), + .color_attachment_formats = std::span(&m_format, 1), .depth_format = static_cast(p_depth_format), .stencil_format = static_cast(p_depth_format), .renderpass = nullptr, .shader_modules = m_shader_resource.handles(), .vertex_attributes = m_shader_resource.vertex_attributes(), .vertex_bind_attributes = m_shader_resource.vertex_bind_attributes(), + .descriptor_layouts = layouts, .color_blend = { .attachments = color_blend_attachments, }, .depth_stencil_enabled = true, .dynamic_states = dynamic_states, + .push_constants = std::span(&range, 1), }; m_main_pipeline = vk::pipeline(*m_device, pipeline_configuration); + + vk::buffer_parameters uniform_params = { + .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | vk::buffer_usage::shader_device_address_bit, + .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, + }; + m_test_ubo = vk::dyn::buffer(*m_device, sizeof(global_uniform), uniform_params); + + + // testing texture + vk::texture_params config_texture = { + .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + }; + + // Loading texture and setting up VkSampler and VkImageView + stb_image img = stb_image("assets/models/viking_room.png", config_texture); + m_viking_room_texture = vk::texture(*m_device, &img, config_texture); + + // Updating descriptor 0 with the texture data + std::array samplers = { + vk::write_image{ + .sampler = m_viking_room_texture.image().sampler(), + .view = m_viking_room_texture.image().image_view(), + .layout = vk::image_layout::shader_read_only_optimal, + }, + }; + + std::array set0_samples = { + vk::write_image_descriptor{ + .dst_binding = 1, + .sample_images = samplers, + } + }; + + set0_resource.update({}, set0_samples); + + obj_importer importer("assets/models/viking_room.obj"); + const auto property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit; + + vk::buffer_parameters vertex_params = { + .memory_mask = m_physical->memory_properties(property_flags), + .property_flags = vk::memory_property::device_local_bit, + .usage = vk::buffer_usage::transfer_dst_bit | vk::buffer_usage::vertex_buffer_bit, + }; + + vk::buffer_parameters index_params = { + .memory_mask = m_physical->memory_properties(property_flags), + .property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit, + .usage = vk::buffer_usage::index_buffer_bit, + }; + m_viking_room_data.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); + m_viking_room_data.index = vk::index_buffer(*m_device, importer.indices(), index_params); + m_viking_room_data.has_indices_buffer = (importer.indices().size() >= 0) ? true : false; + m_viking_room_data.vertices_size = importer.vertices().size(); + m_viking_room_data.indices_size = importer.indices().size(); + + std::println("has_indices = {}", m_viking_room_data.has_indices_buffer); + } + + void prebake() { } void begin(vk::rendering_begin_parameters p_begin_params, const auto& p_extent) { @@ -102,11 +268,55 @@ export namespace atlas { m_current_command->begin_rendering(p_begin_params); m_main_pipeline.bind(*m_current_command); + static auto start_time = std::chrono::high_resolution_clock::now(); - vkCmdDraw(*m_current_command, 3, 1, 0, 0); - } + auto current_time = std::chrono::high_resolution_clock::now(); + float time = std::chrono::duration( + current_time - start_time) + .count(); + global_uniform ubo = { + .model = glm::rotate(glm::mat4(1.0f), + time * glm::radians(90.0f), + glm::vec3(0.0f, 0.0f, 1.0f)), + .view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), + glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3(0.0f, 0.0f, 1.0f)), + .proj = glm::perspective(glm::radians(45.0f), + static_cast(p_extent.width) / + static_cast(p_extent.height), + 0.1f, + 10.0f) + }; + ubo.proj[1][1] *= -1; + + m_test_ubo.transfer(std::span(&ubo, 1)); + + const uint64_t ubo_address = m_test_ubo.get_device_address(); + push_constant_data push = { + .texture_index = 0, + .buffer_address = ubo_address, + }; + m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); + + const VkDescriptorSet set0 = set0_resource; + m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); + const VkBuffer vertex = m_viking_room_data.vertex; + uint64_t offset = 0; + m_current_command->bind_vertex_buffers(std::span(&vertex, 1), std::span(&offset, 1)); + if (m_viking_room_data.has_indices_buffer) { + m_current_command->bind_index_buffers32(m_viking_room_data.index); + } + } + void end() { + + if (m_viking_room_data.has_indices_buffer) { + vkCmdDrawIndexed(*m_current_command, m_viking_room_data.indices_size, 1, 0, 0, 0); + } + else { + vkCmdDraw(*m_current_command, m_viking_room_data.vertices_size, 1, 0, 0); + } m_current_command->end_rendering(); } @@ -114,24 +324,38 @@ export namespace atlas { m_current_command = &p_command; } - void current_scene(flecs::world& p_world) { m_world = &p_world; } void destruct() { + m_test_ubo.reset(); + m_viking_room_data.vertex.destruct(); + m_viking_room_data.index.destruct(); + m_viking_room_texture.destruct(); + set0_resource.destruct(); m_shader_resource.destruct(); m_main_pipeline.destruct(); } private: + uint32_t m_format; + // Should change this but for now this will act as our mesh index + uint32_t m_mesh_idx_count = 0; + std::optional m_physical; std::shared_ptr m_device; vk::command_buffer* m_current_command=nullptr; vk::shader_resource m_shader_resource; vk::pipeline m_main_pipeline; std::vector m_indirect_commands; - // std::vector m_mesh_metadata; - std::unordered_map m_mesh_metadata; + vk::descriptor_resource set0_resource; + + vk::dyn::buffer m_test_ubo; + vk::texture m_viking_room_texture; + vk::shader_stage m_stage; + flecs::world* m_world=nullptr; + + gpu_mesh_data m_viking_room_data; }; }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/stb_image.cppm b/atlas/drivers/vulkan/stb_image.cppm index f5f692fd..6d8e7478 100644 --- a/atlas/drivers/vulkan/stb_image.cppm +++ b/atlas/drivers/vulkan/stb_image.cppm @@ -15,7 +15,7 @@ export module atlas.drivers.vulkan.stb_image; import vk; -export namespace atlas::vulkan { +export namespace atlas { class stb_image : public vk::image { public: stb_image() = default; diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag index 60325b6b..0a98c202 100644 --- a/builtin.shaders/pbr.frag +++ b/builtin.shaders/pbr.frag @@ -1,9 +1,17 @@ -#version 460 +#version 450 + +#extension GL_EXT_nonuniform_qualifier : require layout(location = 0) in vec3 fragColor; +layout(location = 1) in vec2 fragTexCoords; +layout(location = 2) in vec3 fragNormals; +layout(location = 3) in flat int fragTexIndex; layout(location = 0) out vec4 outColor; +layout(set = 0, binding = 1) uniform sampler2D textures[]; + void main() { - outColor = vec4(fragColor, 1.0); + + outColor = texture(textures[nonuniformEXT(fragTexIndex)], fragTexCoords); } \ No newline at end of file diff --git a/builtin.shaders/pbr.frag.spv b/builtin.shaders/pbr.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..7cc26048ac6f92c159ea5b7e814883401c1fc658 GIT binary patch literal 1092 zcmYk4U2D`(5QfL@hjnXhYi(<-)vewaFH{6kkWzxMSYeBL7naT0av)9Ce8~F0)En>o zRo)1`Pc~U{U@|lBd1uaiq_g()rr8bKuuU7<^6c1}5Hs}8drSSR*1x3(wr=B(pThGm zmto}cY3AoenuR`z+`=bU%GIypgVA_&nitXO^B2#^e8)P~1LWRPmaa5%J@E+_wHxVrddP)Ip`U@Nespez&@zGNt|1tYM2vT4nA+6NSJHm zKatG|G&5!jhdXRy*#vjH(m%9Q?7fz~zp}fleKh%rZ@*8C`0Qp^U-XIc@doz3tiJS6 za-bU6B|dW<>bout7yNbY(<9iSx*bTv=l%9+{39_pbOG;J_HAi=a&Jm=z{riyEI51e zx1@&>a>3uOZE*Pb%&fWBsH#JLdO47$Hu@y~zBF8L;_=z{66@MS+3@KN{&9T=4j-Rc z!f$-$i~myp1Me_54mth`=}Es4O3imA)H|+y_6zn-ENW-R^bbx9eXwhAeCmE6q2|wu VVJAltIN)#fD!T#ur>b5_{sU2AWo`ff literal 0 HcmV?d00001 diff --git a/builtin.shaders/pbr.vert b/builtin.shaders/pbr.vert index 60361b01..c270eec8 100644 --- a/builtin.shaders/pbr.vert +++ b/builtin.shaders/pbr.vert @@ -1,27 +1,36 @@ -#version 460 +#version 450 -// #extension GL_EXT_nonuniform_qualifier : enable // Required for descriptor indexing +#extension GL_EXT_buffer_reference : require -// layout(location = 0) in vec3 inPosition; -// layout(location = 1) in vec3 inColor; -// layout(location = 2) in vec3 inNormals; -// layout(location = 3) in vec2 inTexCoords; +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inColor; +layout(location = 2) in vec2 inTexCoords; +layout(location = 3) in vec3 inNormals; layout(location = 0) out vec3 fragColor; +layout(location = 1) out vec2 fragTexCoords; +layout(location = 2) out vec3 fragNormals; +layout(location = 3) out flat int fragTexIndex; + +layout(buffer_reference, std140) buffer readonly UniformBufferObject { + mat4 model; + mat4 view; + mat4 proj; +}; + +layout(push_constant) uniform Constants { + int texture_index; + UniformBufferObject global_ubo_address; +} push_const; -vec2 positions[3] = vec2[]( - vec2(0.0, -0.5), - vec2(0.5, 0.5), - vec2(-0.5, 0.5) -); -vec3 colors[3] = vec3[]( - vec3(1.0, 0.0, 0.0), - vec3(0.0, 1.0, 0.0), - vec3(0.0, 0.0, 1.0) -); void main() { - gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); - fragColor = colors[gl_VertexIndex]; + UniformBufferObject ubo = push_const.global_ubo_address; + + gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); + fragColor = inColor; + fragTexCoords = inTexCoords; + fragNormals = inNormals; + fragTexIndex = push_const.texture_index; } \ No newline at end of file diff --git a/builtin.shaders/pbr.vert.spv b/builtin.shaders/pbr.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..fcb1ab4b15ed456555fd788575ba4a2a73abd882 GIT binary patch literal 2596 zcmZ9MZ*vqy5XOgGE`%T=B7am2fvBK?01Aje;NS=s%an-*DBo>e?j~WV&FUGRa2r-8J?~ja` zF^9~?`m^N6m0yz4^H-%C^wXrQ@}j?Olg;tgmMs)N@?DHC()Y<0@?Lo0j=U z9Pk~L#+sDu^j*gJ6Ul<)rsO-x9m$g9zN91RN?Q7x(EgW5Ce1<9TTPaKebQu33ak7! z8(7(9u=Uo~daKLHU^G&ZuTq<&F0;wd6?Ra$mllrc$j@bibUch5+VY5NY%AxC@;}Yo zR$lBp^fzAHd?7yFy6tT;o1J`UQ|$rc&M%$)4O_st$Ee6(fVFk6_q2~UbDi71JKa1h ztA19M!l#tC?wB!^-L1xjOcLXk0!|29SbH znbY1sS+~VATZmMu&>H8wohIvf=_;3JK0p3-4&g4VHr(&(U|kzF?xUD)>PC+ol@IJ* zT&uB-({#_qoq2N>HS+c@+e_&&W?@Ui)y>nq@P3niHe6OC+=Ds6=ZW3z=6NxsU+^(I zE_;W9F-!RVq{r*0rT6Q2zkt-eVb&VXADTAnn`rs><(?~k!gSDTOIGyDT(I;J`F_Vf z^e6V2$5AWz(ASs;eLoLa%!3Y3M-q6bE#^Vr&jS|opu_W8!X25zH~LOFGjrIfJu|k!9x!6S*n=N=z*-T;8H{hRr{4wbvl13M^AYR(-#~{KJF^k% z%mg~Qurm*_-f495a{sP&?u{>Je6bxD103h1p>w{V)0Fmq)w`2A)Au>aDaFzobnbCl zzlXGgq0g#M%nn$PIavZ1Hgx&`2lxr;M?7BNbyhlcf?>!1sCM|k?=(992f!AZ_+vWL zEBrrfY=QrT$MvIyKl(`t{%540(oQ{Kv&zc5hI?W|;Qd%TJ;F{M=zRBJp^i^=W(EB- zo#`p@^qihjH@*ByJ9&x6{&*>b;o|g_*=dNStrGtmqKa~g0&n0sb?1AqKonyW)rGqg~ zp_U6egYW0NC=5>Q@bUhaB+Smw%1MtF8%*0CcBR1%MA+2^BgeWTnXPLQ;_=7M4E`Zr zY~M)8j}LuhCa+8QE~uTpqvIE9yQMR8h>iI~$HrXU^XJ;e?A3aGrw7tI9&7nILnkM5 avn=6#>VDP#Qyw=sd6+Zw|22)bByRz?YudB` literal 0 HcmV?d00001 From fd795fd5299a0cb73a9a3f30b0b8a0424f454d96 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sat, 30 May 2026 16:02:19 -0700 Subject: [PATCH 016/106] refactor: Added back the working camera system --- atlas/core/application.cppm | 91 ++- .../drivers/vulkan/imgui_context-backup.cppm | 476 ++++++++++++++ atlas/drivers/vulkan/imgui_context.cppm | 620 +++++------------- atlas/drivers/vulkan/render_context.cppm | 44 +- atlas/drivers/vulkan/vulkan.cppm | 3 +- atlas/drivers/vulkan/window.cppm | 9 + editor/level_scene.cppm | 85 ++- 7 files changed, 844 insertions(+), 484 deletions(-) create mode 100644 atlas/drivers/vulkan/imgui_context-backup.cppm diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 80e655b6..e71c3ed8 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -1,17 +1,10 @@ module; #include -#include -#define GLM_ENABLE_EXPERIMENTAL -#include -#include #include #include #include #include -#include -#include -#include #include #include @@ -19,6 +12,15 @@ module; #include #include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include + +#include +#include +#include +#include + export module atlas.application; import atlas.core.utilities; @@ -29,6 +31,8 @@ import atlas.drivers.vulkan; import atlas.core.scene; import atlas.core.scene.world; +import atlas.core.scene.components; +import atlas.core.math; export namespace atlas { @@ -73,6 +77,14 @@ export namespace atlas { // m_window = std::allocate_shared(, m_context->instance_handle(), params); m_window = std::make_shared(p_context, params); + event::set_window_size(m_window->glfw_window()); + + // m_imgui_context = std::make_shared(p_context, + // m_window->glfw_window(), + // m_window->swapchain_handle(), + // m_window->request_images().size(), + // m_window->present_queue()); + // Requesting depth format std::array format_support = { vk::format::d32_sfloat, @@ -151,13 +163,49 @@ export namespace atlas { std::shared_ptr current_scene = m_world->current(); + // Handling camera system execution + current_scene + ->system, + transform, + perspective_camera>() + .each([&](flecs::pair p_pair, + transform& p_transform, + perspective_camera& p_camera) { + float aspect_ratio = m_window->aspect_ratio(); + if (!p_camera.is_active) { + return; + } + + p_pair->projection = glm::mat4(1.f); + + p_pair->projection = + glm::perspective(glm::radians(p_camera.field_of_view), + aspect_ratio, + p_camera.plane.x, + p_camera.plane.y); + p_pair->projection[1][1] *= -1; + p_pair->view = glm::mat4(1.f); + + // This is converting a glm::highp_vec4 to a glm::quat + glm::quat quaternion = to_quat(p_transform.quaternion); + + p_pair->view = + glm::translate(p_pair->view, p_transform.position) * + glm::mat4_cast(quaternion); + + p_pair->view = glm::inverse(p_pair->view); + }); + // Setting the current scene for the renderer to start rendering the objects m_render_context.current_scene(*current_scene); auto start_time = std::chrono::high_resolution_clock::now(); invoke_start(current_scene.get()); - + + // Querying editor cameras specific objects + // Then using this to execute specific main cameras. + auto query_camera_objects = current_scene->query_builder, perspective_camera>().build(); m_render_context.prebake(); @@ -168,6 +216,11 @@ export namespace atlas { start_time = current_time; event::flush_events(); + // Progresses the flecs::world by one tick (or replaced with + // using the delta time) This also invokes the following + // system call before the mainloop + current_scene->progress(m_delta_time); + m_next_image_frame_idx = m_window->acquire_next_frame(); const auto current_extent = m_window->surface_properties().capabilities.currentExtent; @@ -177,6 +230,22 @@ export namespace atlas { invoke_on_update(current_scene.get(), m_delta_time); + // We want this to be called after late update + // This queries all camera objects within the camera system + // TODO: Should consider changing this from + // using tags in flecs for specifying active cameras. + query_camera_objects.each( + [&](flecs::entity, + flecs::pair p_pair, + perspective_camera& p_camera) { + if (!p_camera.is_active) { + return; + } + + m_projection = p_pair->projection; + m_view = p_pair->view; + }); + current.begin(vk::command_usage::simulatneous_use_bit); m_render_context.set_command(current); @@ -229,7 +298,7 @@ export namespace atlas { .stencil_attachment = depth_stencil_attachment, }; - m_render_context.begin(begin_params, current_extent); + m_render_context.begin(begin_params, current_extent, m_projection, m_view); m_render_context.end(); @@ -275,11 +344,15 @@ export namespace atlas { std::shared_ptr m_context; std::shared_ptr m_window=nullptr; event::bus* m_bus = nullptr; + glm::mat4 m_view=glm::mat4(1.f); + glm::mat4 m_projection=glm::mat4(1.f); render_context m_render_context; std::shared_ptr m_world; + // std::shared_ptr m_imgui_context; + // vulkan-cpp specific handles vk::instance m_instance; std::optional m_physical; diff --git a/atlas/drivers/vulkan/imgui_context-backup.cppm b/atlas/drivers/vulkan/imgui_context-backup.cppm new file mode 100644 index 00000000..64ff051a --- /dev/null +++ b/atlas/drivers/vulkan/imgui_context-backup.cppm @@ -0,0 +1,476 @@ +module; + +#include +#include +#include +#include +#include +#include +#include +#include + +export module atlas.drivers.vulkan.imgui_context; + +import atlas.common; +import vk; + +import atlas.core.utilities; + +namespace atlas::vulkan { + static void im_gui_layout_color_modification() { + auto& colors = ImGui::GetStyle().Colors; // @note Colors is ImVec4 + + colors[ImGuiCol_WindowBg] = ImVec4{ 0.1f, 0.105f, 0.11f, 1.0f }; + + // Headers + colors[ImGuiCol_Header] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_HeaderHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_HeaderActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Buttons + colors[ImGuiCol_Button] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_ButtonHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_ButtonActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Frame BG + colors[ImGuiCol_FrameBg] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_FrameBgHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_FrameBgActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Tabs + colors[ImGuiCol_Tab] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + colors[ImGuiCol_TabHovered] = ImVec4{ 0.38f, 0.3805f, 0.381f, 1.0f }; + colors[ImGuiCol_TabActive] = ImVec4{ 0.28f, 0.2805f, 0.281f, 1.0f }; + colors[ImGuiCol_TabUnfocused] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; + colors[ImGuiCol_TabUnfocusedActive] = + ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + + // Titles + colors[ImGuiCol_TitleBg] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + colors[ImGuiCol_TitleBgActive] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; + colors[ImGuiCol_TitleBgCollapsed] = + ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; + } + + void transition_image_layout(VkDevice p_device, + vk::sample_image& p_image, + VkFormat p_format, + VkImageLayout p_old, + VkImageLayout p_new) { + vk::command_params copy_command_params = { + .levels = vk::command_levels::primary, + .queue_index = 0, + .flags = vk::command_pool_flags::reset, + }; + vk::command_buffer temp_command_buffer = + vk::command_buffer(p_device, copy_command_params); + + temp_command_buffer.begin(vk::command_usage::one_time_submit); + + p_image.memory_barrier(temp_command_buffer, p_format, p_old, p_new); + + temp_command_buffer.end(); + + VkCommandBuffer handle = temp_command_buffer; + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &handle, + }; + + uint32_t queue_family_index = 0; + uint32_t queue_index = 0; + VkQueue temp_graphics_queue; + vkGetDeviceQueue( + p_device, queue_family_index, queue_index, &temp_graphics_queue); + + vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); + vkQueueWaitIdle(temp_graphics_queue); + + temp_command_buffer.destruct(); + } + + export ImTextureID g_viewport_image_id = nullptr; + export class imgui_context { + public: + imgui_context() = default; + + imgui_context(const VkInstance& p_instance, + const swapchain& p_swapchain_ctx, + GLFWwindow* p_window_ctx) { + m_instance = p_instance; + console_log_info("imgui_context"); + m_physical = instance_context::physical_driver(); + m_driver = instance_context::logical_device(); + // vk::device device_temp = instance_context::physical_driver(); + + m_current_swapchain_handler = p_swapchain_ctx; + m_extent = { .width = p_swapchain_ctx.settings().width, + .height = p_swapchain_ctx.settings().height }; + + // Setting up imgui + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + + io.ConfigFlags |= + ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // + // Enable Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking + io.ConfigFlags |= + ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / + // Platform Windows + + // io.ConfigViewportsNoAutoMerge = true; + // io.ConfigViewportsNoAutoMerge = true; + // io.ConfigViewportsNoTaskBarIcon = true; + + // Setup Dear ImGui style + // ImGui::StyleColorsDark(); + // ImGui::StyleColorsClassic(); + im_gui_layout_color_modification(); + + ImGuiStyle& style = ImGui::GetStyle(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } + + m_viewport_command_buffers.resize(p_swapchain_ctx.image_size()); + + for (size_t i = 0; i < m_viewport_command_buffers.size(); i++) { + ::vk::command_params settings = { + .levels = ::vk::command_levels::primary, + // .queue_index = + // enumerate_swapchain_settings.present_index, + .queue_index = 0, + .flags = ::vk::command_pool_flags::reset, + }; + m_viewport_command_buffers[i] = + ::vk::command_buffer(m_driver, settings); + } + + // ::vk::descriptor_res + // m_imgui_descriptor = ::vk::descriptor_resource(m_driver, {}); + // 1: create descriptor pool for IMGUI + // the size of the pool is very oversize, but it's copied from + // imgui demo itself. + std::array pool_sizes = { + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } + }; + + VkDescriptorPoolCreateInfo desc_pool_create_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .pNext = nullptr, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + .maxSets = static_cast(1000 * pool_sizes.size()), + // .poolSizeCount = (uint32_t)std::size(pool_sizes), + .poolSizeCount = static_cast(pool_sizes.size()), + .pPoolSizes = pool_sizes.data() + }; + + // VkDescriptorPool imgui_pool; + vk::vk_check( + vkCreateDescriptorPool( + m_driver, &desc_pool_create_info, nullptr, &m_desc_pool), + "vkCreateDescriptorPool"); + + create(p_window_ctx, + p_swapchain_ctx.image_size(), + p_swapchain_ctx.swapchain_renderpass()); + + vk::image_params config_image = { + .extent = { .width = p_swapchain_ctx.settings().width, + .height = p_swapchain_ctx.settings().height }, + .format = VK_FORMAT_B8G8R8A8_UNORM, + .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), + // .property = vk::memory_property::device_local_bit, + .aspect = vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::color_attachment_bit | + vk::image_usage::transfer_dst_bit | + vk::image_usage::sampled_bit, + // .usage = vk::image_usage::color_attachment_bit | + // vk::image_usage::transfer_dst_bit, + // .phsyical_memory_properties = memory_properties, + .address_mode_u = vk::sampler_address_mode::clamp_to_edge, + .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, + .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, + }; + m_viewport_image = vk::sample_image(m_driver, config_image); + + // transition image layout uses image memory barrier + transition_image_layout(m_driver, + m_viewport_image, + VK_FORMAT_B8G8R8A8_UNORM, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + // Viewport-specific render pass: color attachment ends in + // SHADER_READ_ONLY_OPTIMAL so the offscreen texture can be sampled + // by ImGui. (Swapchain pass uses PRESENT_SRC.) + VkFormat depth_format = m_driver.depth_format(); + std::array<::vk::attachment, 2> viewport_attachments = { + ::vk::attachment{ + .format = VK_FORMAT_B8G8R8A8_UNORM, + .layout = ::vk::image_layout::color_optimal, + .samples = ::vk::sample_bit::count_1, + .load = ::vk::attachment_load::clear, + .store = ::vk::attachment_store::store, + .stencil_load = ::vk::attachment_load::clear, + .stencil_store = ::vk::attachment_store::dont_care, + .initial_layout = ::vk::image_layout::undefined, + .final_layout = ::vk::image_layout::shader_read_only_optimal, + }, + ::vk::attachment{ + .format = depth_format, + .layout = ::vk::image_layout::depth_stencil_optimal, + .samples = ::vk::sample_bit::count_1, + .load = ::vk::attachment_load::clear, + .store = ::vk::attachment_store::dont_care, + .stencil_load = ::vk::attachment_load::dont_care, + .stencil_store = ::vk::attachment_store::dont_care, + .initial_layout = ::vk::image_layout::undefined, + .final_layout = ::vk::image_layout::depth_stencil_optimal, + }, + }; + m_viewport_renderpass = + ::vk::renderpass(m_driver, viewport_attachments); + + vk::image_params config_depth_image = { + .extent = { .width = p_swapchain_ctx.settings().width, + .height = p_swapchain_ctx.settings().height }, + .format = m_driver.depth_format(), + .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), + // .property = vk::memory_property::device_local_bit, + .aspect = vk::image_aspect_flags::depth_bit, + // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + .usage = vk::image_usage::depth_stencil_bit, + // .phsyical_memory_properties = memory_properties, + }; + + m_depth_viewport_image = + vk::sample_image(m_driver, config_depth_image); + + for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { + std::array image_view_attachments = { + m_viewport_image.image_view(), + m_depth_viewport_image.image_view() + }; + + vk::framebuffer_params framebuffer_info = { + .renderpass = m_viewport_renderpass, + .views = image_view_attachments, + .extent = { p_swapchain_ctx.settings().width, + p_swapchain_ctx.settings().height } + }; + m_viewport_framebuffers[i] = + vk::framebuffer(m_driver, framebuffer_info); + } + + g_viewport_image_id = + static_cast(ImGui_ImplVulkan_AddTexture( + m_viewport_image.sampler(), + m_viewport_image.image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + } + + void create(GLFWwindow* p_window_handler, + const uint32_t& p_image_size, + const VkRenderPass& p_current_renderpass) { + ImGui_ImplGlfw_InitForVulkan(p_window_handler, true); + ImGui_ImplVulkan_InitInfo init_info = {}; + init_info.Instance = m_instance; + init_info.PhysicalDevice = m_physical; + init_info.Device = m_driver; + init_info.Queue = m_driver.graphics_queue(); + init_info.RenderPass = p_current_renderpass; + init_info.PipelineCache = nullptr; + init_info.DescriptorPool = m_desc_pool; + init_info.MinImageCount = 2; + init_info.ImageCount = p_image_size; + init_info.UseDynamicRendering = false; + init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + ImGui_ImplVulkan_Init(&init_info); + } + + void begin(const VkCommandBuffer& p_current, + const uint32_t& p_frame_index) { + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + m_current_frame_index = p_frame_index; + m_current = p_current; + } + + void invalidate(const swapchain& p_swapchain) { + // Wait for device to finish all operations before recreating + // resources + vkDeviceWaitIdle(m_driver); + + for (auto& fb : m_viewport_framebuffers) { + fb.destruct(); + } + + // Remove old texture from ImGui if needed + // ImTextureID in ImGui Vulkan backend is VkDescriptorSet cast to + // void* + if (g_viewport_image_id != nullptr) { + VkDescriptorSet old_descriptor_set = + reinterpret_cast(g_viewport_image_id); + ImGui_ImplVulkan_RemoveTexture(old_descriptor_set); + g_viewport_image_id = nullptr; + } + + // Destroy old images + m_viewport_image.destruct(); + m_depth_viewport_image.destruct(); + + // Recreate viewport images with new swapchain size + // VkPhysicalDeviceMemoryProperties memory_properties = + // instance_context::physical_driver().memory_properties(); + + vk::image_params config_image = { + .extent = { .width = p_swapchain.settings().width, + .height = p_swapchain.settings().height }, + .format = VK_FORMAT_B8G8R8A8_UNORM, + .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), + // .property = m_physical.memory_properties(vk::memory_property::device_local_bit), + .aspect = vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::color_attachment_bit | + vk::image_usage::transfer_dst_bit | + vk::image_usage::sampled_bit, + // .phsyical_memory_properties = memory_properties, + .address_mode_u = vk::sampler_address_mode::clamp_to_edge, + .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, + .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, + }; + m_viewport_image = vk::sample_image(m_driver, config_image); + + // Transition to shader read-only layout + transition_image_layout(m_driver, + m_viewport_image, + VK_FORMAT_B8G8R8A8_UNORM, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + // Recreate depth image + vk::image_params config_depth_image = { + .extent = { .width = p_swapchain.settings().width, + .height = p_swapchain.settings().height }, + .format = m_driver.depth_format(), + .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), + .property = vk::memory_property::device_local_bit, + .aspect = vk::image_aspect_flags::depth_bit, + // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, + .usage = vk::image_usage::depth_stencil_bit, + // .phsyical_memory_properties = memory_properties, + }; + m_depth_viewport_image = + vk::sample_image(m_driver, config_depth_image); + + // Recreate framebuffers with new images + for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { + std::array image_view_attachments = { + m_viewport_image.image_view(), + m_depth_viewport_image.image_view() + }; + + vk::framebuffer_params framebuffer_info = { + .renderpass = m_viewport_renderpass, + .views = image_view_attachments, + .extent = { p_swapchain.settings().width, + p_swapchain.settings().height } + }; + m_viewport_framebuffers[i] = + vk::framebuffer(m_driver, framebuffer_info); + } + + // Update ImGui texture ID with new image + g_viewport_image_id = (ImTextureID)ImGui_ImplVulkan_AddTexture( + m_viewport_image.sampler(), + m_viewport_image.image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + // Update extent + m_extent = { .width = p_swapchain.settings().width, + .height = p_swapchain.settings().height }; + } + + void end() { + ImGui::Render(); + + ImDrawData* draw_data = ImGui::GetDrawData(); + ImGui_ImplVulkan_RenderDrawData(draw_data, m_current); + + ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + } + + [[nodiscard]] ::vk::command_buffer imgui_active_command() const { + return m_viewport_command_buffers[m_current_frame_index]; + } + + vk::framebuffer active_framebuffer(uint32_t p_frame) const { + return m_viewport_framebuffers[p_frame]; + } + + [[nodiscard]] vk::renderpass viewport_renderpass() const { + return m_viewport_renderpass; + } + + void destroy() { + ImGui_ImplVulkan_Shutdown(); + vkDestroyDescriptorPool(m_driver, m_desc_pool, nullptr); + + for (auto& command_buffer : m_viewport_command_buffers) { + command_buffer.destruct(); + } + + for (auto& fb : m_viewport_framebuffers) { + fb.destruct(); + } + + m_viewport_renderpass.destruct(); + m_viewport_image.destruct(); + m_depth_viewport_image.destruct(); + + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + } + + private: + VkInstance m_instance = nullptr; + physical_device m_physical = nullptr; + device m_driver{}; + uint32_t m_current_frame_index = 0; + VkSwapchainKHR m_current_swapchain_handler = nullptr; + VkDescriptorPool m_desc_pool = nullptr; + VkCommandBuffer m_current = nullptr; + std::vector<::vk::command_buffer> m_viewport_command_buffers; + std::array m_viewport_framebuffers; + ::vk::renderpass m_viewport_renderpass; + vk::sample_image m_viewport_image; + vk::sample_image m_depth_viewport_image; + window_params m_extent; + }; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 21bda947..13c63ad9 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -8,469 +8,173 @@ module; #include #include #include +#include +#include +#include +#include + +export module atlas.drivers.vulkan:imgui_context; -export module atlas.drivers.vulkan.imgui_context; +import :graphics_context; import atlas.common; import vk; import atlas.core.utilities; -namespace atlas::vulkan { - // static void im_gui_layout_color_modification() { - // auto& colors = ImGui::GetStyle().Colors; // @note Colors is ImVec4 - - // colors[ImGuiCol_WindowBg] = ImVec4{ 0.1f, 0.105f, 0.11f, 1.0f }; - - // // Headers - // colors[ImGuiCol_Header] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - // colors[ImGuiCol_HeaderHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - // colors[ImGuiCol_HeaderActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // // Buttons - // colors[ImGuiCol_Button] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - // colors[ImGuiCol_ButtonHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - // colors[ImGuiCol_ButtonActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // // Frame BG - // colors[ImGuiCol_FrameBg] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - // colors[ImGuiCol_FrameBgHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - // colors[ImGuiCol_FrameBgActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // // Tabs - // colors[ImGuiCol_Tab] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - // colors[ImGuiCol_TabHovered] = ImVec4{ 0.38f, 0.3805f, 0.381f, 1.0f }; - // colors[ImGuiCol_TabActive] = ImVec4{ 0.28f, 0.2805f, 0.281f, 1.0f }; - // colors[ImGuiCol_TabUnfocused] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; - // colors[ImGuiCol_TabUnfocusedActive] = - // ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - - // // Titles - // colors[ImGuiCol_TitleBg] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - // colors[ImGuiCol_TitleBgActive] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; - // colors[ImGuiCol_TitleBgCollapsed] = - // ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; - // } - - // void transition_image_layout(VkDevice p_device, - // vk::sample_image& p_image, - // VkFormat p_format, - // VkImageLayout p_old, - // VkImageLayout p_new) { - // vk::command_params copy_command_params = { - // .levels = vk::command_levels::primary, - // .queue_index = 0, - // .flags = vk::command_pool_flags::reset, - // }; - // vk::command_buffer temp_command_buffer = - // vk::command_buffer(p_device, copy_command_params); - - // temp_command_buffer.begin(vk::command_usage::one_time_submit); - - // p_image.memory_barrier(temp_command_buffer, p_format, p_old, p_new); - - // temp_command_buffer.end(); - - // VkCommandBuffer handle = temp_command_buffer; - // VkSubmitInfo submit_info = { - // .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - // .commandBufferCount = 1, - // .pCommandBuffers = &handle, - // }; - - // uint32_t queue_family_index = 0; - // uint32_t queue_index = 0; - // VkQueue temp_graphics_queue; - // vkGetDeviceQueue( - // p_device, queue_family_index, queue_index, &temp_graphics_queue); - - // vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); - // vkQueueWaitIdle(temp_graphics_queue); - - // temp_command_buffer.destruct(); - // } - - // export ImTextureID g_viewport_image_id = nullptr; - // export class imgui_context { - // public: - // imgui_context() = default; - - // imgui_context(const VkInstance& p_instance, - // const swapchain& p_swapchain_ctx, - // GLFWwindow* p_window_ctx) { - // m_instance = p_instance; - // console_log_info("imgui_context"); - // m_physical = instance_context::physical_driver(); - // m_driver = instance_context::logical_device(); - // // vk::device device_temp = instance_context::physical_driver(); - - // m_current_swapchain_handler = p_swapchain_ctx; - // m_extent = { .width = p_swapchain_ctx.settings().width, - // .height = p_swapchain_ctx.settings().height }; - - // // Setting up imgui - // IMGUI_CHECKVERSION(); - // ImGui::CreateContext(); - // ImGuiIO& io = ImGui::GetIO(); - - // io.ConfigFlags |= - // ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - // // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // - // // Enable Gamepad Controls - // io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking - // io.ConfigFlags |= - // ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / - // // Platform Windows - - // // io.ConfigViewportsNoAutoMerge = true; - // // io.ConfigViewportsNoAutoMerge = true; - // // io.ConfigViewportsNoTaskBarIcon = true; - - // // Setup Dear ImGui style - // // ImGui::StyleColorsDark(); - // // ImGui::StyleColorsClassic(); - // im_gui_layout_color_modification(); - - // ImGuiStyle& style = ImGui::GetStyle(); - // if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - // style.WindowRounding = 0.0f; - // style.Colors[ImGuiCol_WindowBg].w = 1.0f; - // } - - // m_viewport_command_buffers.resize(p_swapchain_ctx.image_size()); - - // for (size_t i = 0; i < m_viewport_command_buffers.size(); i++) { - // ::vk::command_params settings = { - // .levels = ::vk::command_levels::primary, - // // .queue_index = - // // enumerate_swapchain_settings.present_index, - // .queue_index = 0, - // .flags = ::vk::command_pool_flags::reset, - // }; - // m_viewport_command_buffers[i] = - // ::vk::command_buffer(m_driver, settings); - // } - - // // ::vk::descriptor_res - // // m_imgui_descriptor = ::vk::descriptor_resource(m_driver, {}); - // // 1: create descriptor pool for IMGUI - // // the size of the pool is very oversize, but it's copied from - // // imgui demo itself. - // std::array pool_sizes = { - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLER, 100 }, - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - // 100 }, - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 100 }, - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 100 }, - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, - // 100 }, - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, - // 100 }, - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100 }, - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 100 }, - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, - // 100 }, - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, - // 100 }, - // VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } - // }; - - // VkDescriptorPoolCreateInfo desc_pool_create_info = { - // .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - // .pNext = nullptr, - // .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, - // .maxSets = static_cast(1000 * pool_sizes.size()), - // // .poolSizeCount = (uint32_t)std::size(pool_sizes), - // .poolSizeCount = static_cast(pool_sizes.size()), - // .pPoolSizes = pool_sizes.data() - // }; - - // // VkDescriptorPool imgui_pool; - // vk::vk_check( - // vkCreateDescriptorPool( - // m_driver, &desc_pool_create_info, nullptr, &m_desc_pool), - // "vkCreateDescriptorPool"); - - // create(p_window_ctx, - // p_swapchain_ctx.image_size(), - // p_swapchain_ctx.swapchain_renderpass()); - - // vk::image_params config_image = { - // .extent = { .width = p_swapchain_ctx.settings().width, - // .height = p_swapchain_ctx.settings().height }, - // .format = VK_FORMAT_B8G8R8A8_UNORM, - // .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), - // // .property = vk::memory_property::device_local_bit, - // .aspect = vk::image_aspect_flags::color_bit, - // .usage = vk::image_usage::color_attachment_bit | - // vk::image_usage::transfer_dst_bit | - // vk::image_usage::sampled_bit, - // // .usage = vk::image_usage::color_attachment_bit | - // // vk::image_usage::transfer_dst_bit, - // // .phsyical_memory_properties = memory_properties, - // .address_mode_u = vk::sampler_address_mode::clamp_to_edge, - // .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, - // .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, - // }; - // m_viewport_image = vk::sample_image(m_driver, config_image); - - // // transition image layout uses image memory barrier - // transition_image_layout(m_driver, - // m_viewport_image, - // VK_FORMAT_B8G8R8A8_UNORM, - // VK_IMAGE_LAYOUT_UNDEFINED, - // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // // Viewport-specific render pass: color attachment ends in - // // SHADER_READ_ONLY_OPTIMAL so the offscreen texture can be sampled - // // by ImGui. (Swapchain pass uses PRESENT_SRC.) - // VkFormat depth_format = m_driver.depth_format(); - // std::array<::vk::attachment, 2> viewport_attachments = { - // ::vk::attachment{ - // .format = VK_FORMAT_B8G8R8A8_UNORM, - // .layout = ::vk::image_layout::color_optimal, - // .samples = ::vk::sample_bit::count_1, - // .load = ::vk::attachment_load::clear, - // .store = ::vk::attachment_store::store, - // .stencil_load = ::vk::attachment_load::clear, - // .stencil_store = ::vk::attachment_store::dont_care, - // .initial_layout = ::vk::image_layout::undefined, - // .final_layout = ::vk::image_layout::shader_read_only_optimal, - // }, - // ::vk::attachment{ - // .format = depth_format, - // .layout = ::vk::image_layout::depth_stencil_optimal, - // .samples = ::vk::sample_bit::count_1, - // .load = ::vk::attachment_load::clear, - // .store = ::vk::attachment_store::dont_care, - // .stencil_load = ::vk::attachment_load::dont_care, - // .stencil_store = ::vk::attachment_store::dont_care, - // .initial_layout = ::vk::image_layout::undefined, - // .final_layout = ::vk::image_layout::depth_stencil_optimal, - // }, - // }; - // m_viewport_renderpass = - // ::vk::renderpass(m_driver, viewport_attachments); - - // vk::image_params config_depth_image = { - // .extent = { .width = p_swapchain_ctx.settings().width, - // .height = p_swapchain_ctx.settings().height }, - // .format = m_driver.depth_format(), - // .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), - // // .property = vk::memory_property::device_local_bit, - // .aspect = vk::image_aspect_flags::depth_bit, - // // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - // .usage = vk::image_usage::depth_stencil_bit, - // // .phsyical_memory_properties = memory_properties, - // }; - - // m_depth_viewport_image = - // vk::sample_image(m_driver, config_depth_image); - - // for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { - // std::array image_view_attachments = { - // m_viewport_image.image_view(), - // m_depth_viewport_image.image_view() - // }; - - // vk::framebuffer_params framebuffer_info = { - // .renderpass = m_viewport_renderpass, - // .views = image_view_attachments, - // .extent = { p_swapchain_ctx.settings().width, - // p_swapchain_ctx.settings().height } - // }; - // m_viewport_framebuffers[i] = - // vk::framebuffer(m_driver, framebuffer_info); - // } - - // g_viewport_image_id = - // static_cast(ImGui_ImplVulkan_AddTexture( - // m_viewport_image.sampler(), - // m_viewport_image.image_view(), - // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - // } - - // void create(GLFWwindow* p_window_handler, - // const uint32_t& p_image_size, - // const VkRenderPass& p_current_renderpass) { - // ImGui_ImplGlfw_InitForVulkan(p_window_handler, true); - // ImGui_ImplVulkan_InitInfo init_info = {}; - // init_info.Instance = m_instance; - // init_info.PhysicalDevice = m_physical; - // init_info.Device = m_driver; - // init_info.Queue = m_driver.graphics_queue(); - // init_info.RenderPass = p_current_renderpass; - // init_info.PipelineCache = nullptr; - // init_info.DescriptorPool = m_desc_pool; - // init_info.MinImageCount = 2; - // init_info.ImageCount = p_image_size; - // init_info.UseDynamicRendering = false; - // init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; - // ImGui_ImplVulkan_Init(&init_info); - // } - - // void begin(const VkCommandBuffer& p_current, - // const uint32_t& p_frame_index) { - // ImGui_ImplVulkan_NewFrame(); - // ImGui_ImplGlfw_NewFrame(); - // ImGui::NewFrame(); - - // m_current_frame_index = p_frame_index; - // m_current = p_current; - // } - - // void invalidate(const swapchain& p_swapchain) { - // // Wait for device to finish all operations before recreating - // // resources - // vkDeviceWaitIdle(m_driver); - - // for (auto& fb : m_viewport_framebuffers) { - // fb.destruct(); - // } - - // // Remove old texture from ImGui if needed - // // ImTextureID in ImGui Vulkan backend is VkDescriptorSet cast to - // // void* - // if (g_viewport_image_id != nullptr) { - // VkDescriptorSet old_descriptor_set = - // reinterpret_cast(g_viewport_image_id); - // ImGui_ImplVulkan_RemoveTexture(old_descriptor_set); - // g_viewport_image_id = nullptr; - // } - - // // Destroy old images - // m_viewport_image.destruct(); - // m_depth_viewport_image.destruct(); - - // // Recreate viewport images with new swapchain size - // // VkPhysicalDeviceMemoryProperties memory_properties = - // // instance_context::physical_driver().memory_properties(); - - // vk::image_params config_image = { - // .extent = { .width = p_swapchain.settings().width, - // .height = p_swapchain.settings().height }, - // .format = VK_FORMAT_B8G8R8A8_UNORM, - // .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), - // // .property = m_physical.memory_properties(vk::memory_property::device_local_bit), - // .aspect = vk::image_aspect_flags::color_bit, - // .usage = vk::image_usage::color_attachment_bit | - // vk::image_usage::transfer_dst_bit | - // vk::image_usage::sampled_bit, - // // .phsyical_memory_properties = memory_properties, - // .address_mode_u = vk::sampler_address_mode::clamp_to_edge, - // .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, - // .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, - // }; - // m_viewport_image = vk::sample_image(m_driver, config_image); - - // // Transition to shader read-only layout - // transition_image_layout(m_driver, - // m_viewport_image, - // VK_FORMAT_B8G8R8A8_UNORM, - // VK_IMAGE_LAYOUT_UNDEFINED, - // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // // Recreate depth image - // vk::image_params config_depth_image = { - // .extent = { .width = p_swapchain.settings().width, - // .height = p_swapchain.settings().height }, - // .format = m_driver.depth_format(), - // .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), - // .property = vk::memory_property::device_local_bit, - // .aspect = vk::image_aspect_flags::depth_bit, - // // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - // .usage = vk::image_usage::depth_stencil_bit, - // // .phsyical_memory_properties = memory_properties, - // }; - // m_depth_viewport_image = - // vk::sample_image(m_driver, config_depth_image); - - // // Recreate framebuffers with new images - // for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { - // std::array image_view_attachments = { - // m_viewport_image.image_view(), - // m_depth_viewport_image.image_view() - // }; - - // vk::framebuffer_params framebuffer_info = { - // .renderpass = m_viewport_renderpass, - // .views = image_view_attachments, - // .extent = { p_swapchain.settings().width, - // p_swapchain.settings().height } - // }; - // m_viewport_framebuffers[i] = - // vk::framebuffer(m_driver, framebuffer_info); - // } - - // // Update ImGui texture ID with new image - // g_viewport_image_id = (ImTextureID)ImGui_ImplVulkan_AddTexture( - // m_viewport_image.sampler(), - // m_viewport_image.image_view(), - // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // // Update extent - // m_extent = { .width = p_swapchain.settings().width, - // .height = p_swapchain.settings().height }; - // } - - // void end() { - // ImGui::Render(); - - // ImDrawData* draw_data = ImGui::GetDrawData(); - // ImGui_ImplVulkan_RenderDrawData(draw_data, m_current); - - // ImGuiIO& io = ImGui::GetIO(); - // if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - // ImGui::UpdatePlatformWindows(); - // ImGui::RenderPlatformWindowsDefault(); - // } - // } - - // [[nodiscard]] ::vk::command_buffer imgui_active_command() const { - // return m_viewport_command_buffers[m_current_frame_index]; - // } - - // vk::framebuffer active_framebuffer(uint32_t p_frame) const { - // return m_viewport_framebuffers[p_frame]; - // } - - // [[nodiscard]] vk::renderpass viewport_renderpass() const { - // return m_viewport_renderpass; - // } - - // void destroy() { - // ImGui_ImplVulkan_Shutdown(); - // vkDestroyDescriptorPool(m_driver, m_desc_pool, nullptr); - - // for (auto& command_buffer : m_viewport_command_buffers) { - // command_buffer.destruct(); - // } - - // for (auto& fb : m_viewport_framebuffers) { - // fb.destruct(); - // } - - // m_viewport_renderpass.destruct(); - // m_viewport_image.destruct(); - // m_depth_viewport_image.destruct(); - - // ImGui_ImplGlfw_Shutdown(); - // ImGui::DestroyContext(); - // } - - // private: - // VkInstance m_instance = nullptr; - // physical_device m_physical = nullptr; - // device m_driver{}; - // uint32_t m_current_frame_index = 0; - // VkSwapchainKHR m_current_swapchain_handler = nullptr; - // VkDescriptorPool m_desc_pool = nullptr; - // VkCommandBuffer m_current = nullptr; - // std::vector<::vk::command_buffer> m_viewport_command_buffers; - // std::array m_viewport_framebuffers; - // ::vk::renderpass m_viewport_renderpass; - // vk::sample_image m_viewport_image; - // vk::sample_image m_depth_viewport_image; - // window_params m_extent; - // }; +namespace atlas { + void imgui_layout_color_modification() { + auto& colors = ImGui::GetStyle().Colors; // @note Colors is ImVec4 + + colors[ImGuiCol_WindowBg] = ImVec4{ 0.1f, 0.105f, 0.11f, 1.0f }; + + // Headers + colors[ImGuiCol_Header] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_HeaderHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_HeaderActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Buttons + colors[ImGuiCol_Button] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_ButtonHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_ButtonActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Frame BG + colors[ImGuiCol_FrameBg] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + colors[ImGuiCol_FrameBgHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; + colors[ImGuiCol_FrameBgActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + + // Tabs + colors[ImGuiCol_Tab] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + colors[ImGuiCol_TabHovered] = ImVec4{ 0.38f, 0.3805f, 0.381f, 1.0f }; + colors[ImGuiCol_TabActive] = ImVec4{ 0.28f, 0.2805f, 0.281f, 1.0f }; + colors[ImGuiCol_TabUnfocused] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; + colors[ImGuiCol_TabUnfocusedActive] = + ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; + + // Titles + colors[ImGuiCol_TitleBg] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; + colors[ImGuiCol_TitleBgActive] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; + colors[ImGuiCol_TitleBgCollapsed] = + ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; + } + + export class imgui_context { + public: + imgui_context() = delete; + imgui_context(std::shared_ptr p_context, + GLFWwindow* p_window, + std::shared_ptr p_swapchain, + uint32_t p_image_count, + const vk::device_present_queue& p_queue) { + m_instance = p_context->instance_handle(); + m_device = p_context->logical_device(); + m_physical = p_context->physical_device(); + + std::println("Constructing imgui_context"); + + // Common setup for imgui + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + + io.ConfigFlags |= + ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // + // Enable Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking + io.ConfigFlags |= + ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / + // Platform Windows + + // Additional configurations + imgui_layout_color_modification(); + + ImGuiStyle& style = ImGui::GetStyle(); + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + style.WindowRounding = 0.0f; + style.Colors[ImGuiCol_WindowBg].w = 1.0f; + } + + // Configurnig descriptor pool + std::array pool_sizes = { + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, + 100 }, + VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } + }; + + VkDescriptorPoolCreateInfo desc_pool_create_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .pNext = nullptr, + .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, + .maxSets = static_cast(1000 * pool_sizes.size()), + // .poolSizeCount = (uint32_t)std::size(pool_sizes), + .poolSizeCount = static_cast(pool_sizes.size()), + .pPoolSizes = pool_sizes.data() + }; + + // VkDescriptorPool imgui_pool; + vk::vk_check( + vkCreateDescriptorPool( + *m_device, &desc_pool_create_info, nullptr, &m_descriptor_pool), "vkCreateDescriptorPool"); + + construct(p_window, p_swapchain, p_image_count, p_queue); + } + + void construct(GLFWwindow* p_window, + std::shared_ptr p_swapchain, + uint32_t p_image_count, + const vk::device_present_queue& p_queue) { + ImGui_ImplGlfw_InitForVulkan(p_window, true); + ImGui_ImplVulkan_InitInfo init_info = {}; + init_info.Instance = m_instance.value(); + init_info.PhysicalDevice = m_physical.value(); + init_info.Device = *m_device; + init_info.Queue = p_queue; + init_info.RenderPass = nullptr; + init_info.PipelineCache = nullptr; + init_info.DescriptorPool = m_descriptor_pool; + init_info.MinImageCount = 2; + init_info.ImageCount = p_image_count; + init_info.UseDynamicRendering = true; + init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + ImGui_ImplVulkan_Init(&init_info); + } + + void set_current_command(vk::command_buffer& p_command) { + m_current_command = &p_command; + } + + // uint32_t = p_frame_ifx + void begin(uint32_t) {} + + void end() {} + + void destruct() { + ImGui_ImplVulkan_Shutdown(); + vkDestroyDescriptorPool(*m_device, m_descriptor_pool, nullptr); + + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + } + + private: + VkDescriptorPool m_descriptor_pool=nullptr; + vk::command_buffer* m_current_command; + std::optional m_instance; + std::optional m_physical; + std::shared_ptr m_device = nullptr; + }; }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index a6f48129..9b5ed8d2 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -227,13 +227,13 @@ export namespace atlas { vk::buffer_parameters vertex_params = { .memory_mask = m_physical->memory_properties(property_flags), - .property_flags = vk::memory_property::device_local_bit, + // .property_flags = vk::memory_property::device_local_bit, .usage = vk::buffer_usage::transfer_dst_bit | vk::buffer_usage::vertex_buffer_bit, }; vk::buffer_parameters index_params = { .memory_mask = m_physical->memory_properties(property_flags), - .property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit, + // .property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit, .usage = vk::buffer_usage::index_buffer_bit, }; m_viking_room_data.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); @@ -248,7 +248,9 @@ export namespace atlas { void prebake() { } - void begin(vk::rendering_begin_parameters p_begin_params, const auto& p_extent) { + void begin(vk::rendering_begin_parameters p_begin_params, const auto& p_extent, const glm::mat4& p_proj, const glm::mat4& p_view) { + m_proj_view = p_proj * p_view; + flecs::entity viking_room = m_world->entity("Viking Room"); vk::viewport_params viewport = { .x = 0.0f, .y = 0.0f, @@ -268,24 +270,34 @@ export namespace atlas { m_current_command->begin_rendering(p_begin_params); m_main_pipeline.bind(*m_current_command); + const transform* t = viking_room.get(); + static auto start_time = std::chrono::high_resolution_clock::now(); auto current_time = std::chrono::high_resolution_clock::now(); float time = std::chrono::duration( current_time - start_time) .count(); + // Setting up viking room + glm::mat4 model = glm::mat4(1.f); + model = glm::translate(model, t->position); + model = glm::scale(model, t->scale); + global_uniform ubo = { - .model = glm::rotate(glm::mat4(1.0f), - time * glm::radians(90.0f), - glm::vec3(0.0f, 0.0f, 1.0f)), - .view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), - glm::vec3(0.0f, 0.0f, 0.0f), - glm::vec3(0.0f, 0.0f, 1.0f)), - .proj = glm::perspective(glm::radians(45.0f), - static_cast(p_extent.width) / - static_cast(p_extent.height), - 0.1f, - 10.0f) + // .model = glm::rotate(glm::mat4(1.0f), + // time * glm::radians(90.0f), + // glm::vec3(0.0f, 0.0f, 1.0f)), + // .view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), + // glm::vec3(0.0f, 0.0f, 0.0f), + // glm::vec3(0.0f, 0.0f, 1.0f)), + // .proj = glm::perspective(glm::radians(45.0f), + // static_cast(p_extent.width) / + // static_cast(p_extent.height), + // 0.1f, + // 10.0f) + .model = model, + .view = p_view, + .proj = p_proj, }; ubo.proj[1][1] *= -1; @@ -342,6 +354,7 @@ export namespace atlas { uint32_t m_format; // Should change this but for now this will act as our mesh index uint32_t m_mesh_idx_count = 0; + glm::mat4 m_proj_view=glm::mat4(1.f); // Combination of the projection * view matrix result std::optional m_physical; std::shared_ptr m_device; vk::command_buffer* m_current_command=nullptr; @@ -351,6 +364,9 @@ export namespace atlas { vk::descriptor_resource set0_resource; vk::dyn::buffer m_test_ubo; + + std::unordered_map m_entity_uniforms; + vk::texture m_viking_room_texture; vk::shader_stage m_stage; diff --git a/atlas/drivers/vulkan/vulkan.cppm b/atlas/drivers/vulkan/vulkan.cppm index 6d67c97c..e31c2a7d 100644 --- a/atlas/drivers/vulkan/vulkan.cppm +++ b/atlas/drivers/vulkan/vulkan.cppm @@ -5,4 +5,5 @@ export module atlas.drivers.vulkan; export import :window; export import :graphics_context; -export import :render_context; \ No newline at end of file +export import :render_context; +export import :imgui_context; \ No newline at end of file diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 4dc6dead..2e5a5a15 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -199,6 +199,15 @@ export namespace atlas { GLFWwindow* glfw_window() const { return m_window; } + std::shared_ptr swapchain_handle() { return m_swapchain; } + + [[nodiscard]] vk::device_present_queue present_queue() const { return m_present_queue; } + + + float aspect_ratio() { + return static_cast(m_params.width / m_params.height); + } + void center_window() { GLFWmonitor* monitor = glfwGetPrimaryMonitor(); const GLFWvidmode* mode = glfwGetVideoMode(monitor); diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 2abeb1dd..b4977b70 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -2,21 +2,49 @@ module; #include #include +#include +#include + +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +#include export module editor:level_scene; import atlas.application; +import atlas.core.event; import atlas.core.scene; import atlas.core.scene.game_object; -import atlas.core.event; import atlas.core.scene.components; import atlas.core.utilities; +import atlas.core.math; export class level_scene final : public atlas::scene { public: level_scene(const std::string& p_name, atlas::event::bus& p_bus) : atlas::scene(p_name, p_bus) { + + m_editor_camera = entity("Editor Camera"); + m_editor_camera->add>(); + m_editor_camera->set({ + .position = { 3.50f, 4.90f, 36.40f }, + .scale{ 1.f }, + }); + m_editor_camera->set({ + .plane = { 0.1f, 5000.f }, + .is_active = true, + .field_of_view = 45.f, + }); + + atlas::game_object viking_room = entity("Viking Room"); + viking_room.set({ + .position = { -2.70f, 2.70, -8.30f }, + .rotation = { 2.30f, 95.90f, 91.80f }, + .scale{ 1.f }, + }); + atlas::register_start(this, &level_scene::start); atlas::register_physics(this, &level_scene::physics_update); atlas::register_update(this, &level_scene::on_update); @@ -27,9 +55,62 @@ public: void start() { } - void on_update(float) { + void on_update(float p_delta_time) { + atlas::transform* t = m_editor_camera->get_mut(); + float dt = p_delta_time; + + // current default movement speed that does not applied modified speed + float default_speed = 10.f; + float rotation_speed = 1.f; + float velocity = default_speed * dt; + if (atlas::event::is_mouse_pressed(mouse_button_middle)) { + velocity = m_movement_speed * dt; + } + + float rotation_velocity = rotation_speed * dt; + + glm::quat to_quaternion = atlas::to_quat(t->quaternion); + + glm::vec3 up = glm::rotate(to_quaternion, atlas::math::up()); + glm::vec3 forward = glm::rotate(to_quaternion, atlas::math::backward()); + glm::vec3 right = glm::rotate(to_quaternion, atlas::math::right()); + + if (atlas::event::is_key_pressed(key_left_shift)) { + t->position += up * velocity; + } + + if (atlas::event::is_key_pressed(key_space)) { + t->position -= up * velocity; + } + + if (atlas::event::is_key_pressed(key_w)) { + t->position += forward * velocity; + } + if (atlas::event::is_key_pressed(key_s)) { + t->position -= forward * velocity; + } + + if (atlas::event::is_key_pressed(key_d)) { + t->position += right * velocity; + } + if (atlas::event::is_key_pressed(key_a)) { + t->position -= right * velocity; + } + + if (atlas::event::is_key_pressed(key_q)) { + t->rotation.y += rotation_velocity; + } + if (atlas::event::is_key_pressed(key_e)) { + t->rotation.y -= rotation_velocity; + } + + t->set_rotation(t->rotation); } void physics_update() { } + +private: + std::optional m_editor_camera; + float m_movement_speed = 10.f; }; \ No newline at end of file From 127ecbd4caae9c5c886a6c0603571e1b31abdf11 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 31 May 2026 15:36:37 -0700 Subject: [PATCH 017/106] refactor: Re-added the mesh loading to the render_context --- atlas/drivers/importer/obj_loader.cppm | 5 +- atlas/drivers/vulkan/render_context.cppm | 158 +++++++++++++++-------- 2 files changed, 111 insertions(+), 52 deletions(-) diff --git a/atlas/drivers/importer/obj_loader.cppm b/atlas/drivers/importer/obj_loader.cppm index 0c582998..c055356a 100644 --- a/atlas/drivers/importer/obj_loader.cppm +++ b/atlas/drivers/importer/obj_loader.cppm @@ -9,6 +9,8 @@ module; #include #include +#include + export module atlas.drivers.importer:obj_loader; import vk; @@ -44,7 +46,8 @@ export namespace atlas { tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; - std::string warn, err; + std::string warn; + std::string err; if(!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, p_path.data())) { return false; diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 9b5ed8d2..800f4d26 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -58,6 +58,11 @@ export namespace atlas { glm::mat4 proj=glm::mat4(1.f); }; + struct storage_geometry { + vk::dyn::buffer vertex; + vk::dyn::buffer index; + }; + /** * @brief Core render context to schedule images and barriers for coordinating rendering operations * @@ -166,8 +171,7 @@ export namespace atlas { .range = sizeof(push_constant_data), }; - // const VkDescriptorSetLayout layout = set0_resource.layout(); - std::array layouts = {set0_resource.layout()}; + VkDescriptorSetLayout descriptor0_layout = set0_resource.layout(); vk::pipeline_params pipeline_configuration = { .use_render_pipeline = true, .color_attachment_formats = std::span(&m_format, 1), @@ -177,7 +181,7 @@ export namespace atlas { .shader_modules = m_shader_resource.handles(), .vertex_attributes = m_shader_resource.vertex_attributes(), .vertex_bind_attributes = m_shader_resource.vertex_bind_attributes(), - .descriptor_layouts = layouts, + .descriptor_layouts = std::span(&descriptor0_layout, 1), .color_blend = { .attachments = color_blend_attachments, }, @@ -192,7 +196,7 @@ export namespace atlas { .usage = vk::buffer_usage::uniform_buffer_bit | vk::buffer_usage::shader_device_address_bit, .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, }; - m_test_ubo = vk::dyn::buffer(*m_device, sizeof(global_uniform), uniform_params); + m_scene_uniforms = vk::dyn::buffer(*m_device, sizeof(global_uniform), uniform_params); // testing texture @@ -221,31 +225,41 @@ export namespace atlas { }; set0_resource.update({}, set0_samples); - - obj_importer importer("assets/models/viking_room.obj"); - const auto property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit; - - vk::buffer_parameters vertex_params = { - .memory_mask = m_physical->memory_properties(property_flags), - // .property_flags = vk::memory_property::device_local_bit, - .usage = vk::buffer_usage::transfer_dst_bit | vk::buffer_usage::vertex_buffer_bit, - }; - - vk::buffer_parameters index_params = { - .memory_mask = m_physical->memory_properties(property_flags), - // .property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit, - .usage = vk::buffer_usage::index_buffer_bit, - }; - m_viking_room_data.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); - m_viking_room_data.index = vk::index_buffer(*m_device, importer.indices(), index_params); - m_viking_room_data.has_indices_buffer = (importer.indices().size() >= 0) ? true : false; - m_viking_room_data.vertices_size = importer.vertices().size(); - m_viking_room_data.indices_size = importer.indices().size(); - - std::println("has_indices = {}", m_viking_room_data.has_indices_buffer); } void prebake() { + flecs::query<> all_meshes = m_world->query_builder().build(); + + all_meshes.each([this](flecs::entity p_entity){ + const mesh_source* src = p_entity.get(); + const auto property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit; + + vk::buffer_parameters vertex_params = { + .memory_mask = m_physical->memory_properties(property_flags), + // .property_flags = vk::memory_property::device_local_bit, + .usage = vk::buffer_usage::transfer_dst_bit | vk::buffer_usage::vertex_buffer_bit, + }; + + vk::buffer_parameters index_params = { + .memory_mask = m_physical->memory_properties(property_flags), + // .property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit, + .usage = vk::buffer_usage::index_buffer_bit, + }; + + // obj_importer importer("assets/models/viking_room.obj"); + obj_importer importer(src->model_path); + gpu_mesh_data gpu_mesh{}; + gpu_mesh.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); + gpu_mesh.index = vk::index_buffer(*m_device, importer.indices(), index_params); + gpu_mesh.has_indices_buffer = (importer.indices().size() >= 0) ? true : false; + gpu_mesh.vertices_size = importer.vertices().size(); + gpu_mesh.indices_size = importer.indices().size(); + + m_meshes.emplace(p_entity.id(), gpu_mesh); + + std::println("Entity ID: {}", p_entity.id()); + }); + } void begin(vk::rendering_begin_parameters p_begin_params, const auto& p_extent, const glm::mat4& p_proj, const glm::mat4& p_view) { @@ -270,40 +284,49 @@ export namespace atlas { m_current_command->begin_rendering(p_begin_params); m_main_pipeline.bind(*m_current_command); + + /* + TODO (TEMP): Consider having transform to be changed as an unbounded array on the shader + struct shader_transform_struct { + // Where we will have an unbounded array of 3D object + // transforms that can already be accessible when being modified + mat4 models[]; + } object_transform; + + + void main() { + gl_Position = ubo.view * ubo.proj * object_transform.models[gl_VertexIndex] * vec4(inPosition, 1.0); + } + + */ + const transform* t = viking_room.get(); - static auto start_time = std::chrono::high_resolution_clock::now(); + // static auto start_time = std::chrono::high_resolution_clock::now(); - auto current_time = std::chrono::high_resolution_clock::now(); - float time = std::chrono::duration( - current_time - start_time) - .count(); + // auto current_time = std::chrono::high_resolution_clock::now(); + // float time = std::chrono::duration( + // current_time - start_time) + // .count(); // Setting up viking room glm::mat4 model = glm::mat4(1.f); model = glm::translate(model, t->position); model = glm::scale(model, t->scale); global_uniform ubo = { - // .model = glm::rotate(glm::mat4(1.0f), - // time * glm::radians(90.0f), - // glm::vec3(0.0f, 0.0f, 1.0f)), - // .view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f), - // glm::vec3(0.0f, 0.0f, 0.0f), - // glm::vec3(0.0f, 0.0f, 1.0f)), - // .proj = glm::perspective(glm::radians(45.0f), - // static_cast(p_extent.width) / - // static_cast(p_extent.height), - // 0.1f, - // 10.0f) .model = model, .view = p_view, .proj = p_proj, }; ubo.proj[1][1] *= -1; - m_test_ubo.transfer(std::span(&ubo, 1)); + m_scene_uniforms.transfer(std::span(&ubo, 1)); + + // Retrieving the buffer address that can be looked up from the glsl shader + const uint64_t ubo_address = m_scene_uniforms.get_device_address(); - const uint64_t ubo_address = m_test_ubo.get_device_address(); + // push constant retrieve the buffer that is transferring data to + // Then we set the texture index. push_constant_data push = { .texture_index = 0, .buffer_address = ubo_address, @@ -313,22 +336,46 @@ export namespace atlas { const VkDescriptorSet set0 = set0_resource; m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); + /* const VkBuffer vertex = m_viking_room_data.vertex; uint64_t offset = 0; m_current_command->bind_vertex_buffers(std::span(&vertex, 1), std::span(&offset, 1)); if (m_viking_room_data.has_indices_buffer) { m_current_command->bind_index_buffers32(m_viking_room_data.index); } + */ + + for(auto[id, mesh] : m_meshes) { + const VkBuffer vertex = mesh.vertex; + uint64_t offset = 0; + m_current_command->bind_vertex_buffers(std::span(&vertex, 1), std::span(&offset, 1)); + if (mesh.has_indices_buffer) { + m_current_command->bind_index_buffers32(mesh.index); + } + } + + } void end() { + /* if (m_viking_room_data.has_indices_buffer) { vkCmdDrawIndexed(*m_current_command, m_viking_room_data.indices_size, 1, 0, 0, 0); } else { vkCmdDraw(*m_current_command, m_viking_room_data.vertices_size, 1, 0, 0); } + */ + + for(auto[id, mesh] : m_meshes) { + if (mesh.has_indices_buffer) { + vkCmdDrawIndexed(*m_current_command, mesh.indices_size, 1, 0, 0, 0); + } + else { + vkCmdDraw(*m_current_command, mesh.vertices_size, 1, 0, 0); + } + } m_current_command->end_rendering(); } @@ -341,9 +388,15 @@ export namespace atlas { } void destruct() { - m_test_ubo.reset(); - m_viking_room_data.vertex.destruct(); - m_viking_room_data.index.destruct(); + m_scene_uniforms.reset(); + // m_viking_room_data.vertex.destruct(); + // m_viking_room_data.index.destruct(); + // m_viking_room_texture.destruct(); + for(auto&[id, mesh] : m_meshes) { + mesh.vertex.destruct(); + mesh.index.destruct(); + } + m_viking_room_texture.destruct(); set0_resource.destruct(); m_shader_resource.destruct(); @@ -363,15 +416,18 @@ export namespace atlas { std::vector m_indirect_commands; vk::descriptor_resource set0_resource; - vk::dyn::buffer m_test_ubo; + vk::dyn::buffer m_scene_uniforms; + + // std::unordered_map m_entity_uniforms; + std::unordered_map m_meshes; - std::unordered_map m_entity_uniforms; + // Index to lookup for speci + uint32_t m_texture_slot_index = 0; + std::unordered_map m_texture_storage; vk::texture m_viking_room_texture; vk::shader_stage m_stage; flecs::world* m_world=nullptr; - - gpu_mesh_data m_viking_room_data; }; }; \ No newline at end of file From 5d6d133eb0de1840d0b6f29be467470df51ec6c6 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 31 May 2026 16:20:54 -0700 Subject: [PATCH 018/106] refactor: Did some code cleanup in render_context removing old code not in use --- atlas/drivers/vulkan/render_context.cppm | 83 ++++++++++-------------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 800f4d26..f6c10748 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -63,6 +63,11 @@ export namespace atlas { vk::dyn::buffer index; }; + struct gpu_image { + uint64_t texture_slot_index=0; + vk::texture specular; + }; + /** * @brief Core render context to schedule images and barriers for coordinating rendering operations * @@ -206,21 +211,30 @@ export namespace atlas { // Loading texture and setting up VkSampler and VkImageView stb_image img = stb_image("assets/models/viking_room.png", config_texture); - m_viking_room_texture = vk::texture(*m_device, &img, config_texture); - // Updating descriptor 0 with the texture data - std::array samplers = { - vk::write_image{ - .sampler = m_viking_room_texture.image().sampler(), - .view = m_viking_room_texture.image().image_view(), - .layout = vk::image_layout::shader_read_only_optimal, - }, + // Reminder: Use texture_slot_index + gpu_image store_image = { + .texture_slot_index = 0, + .specular = vk::texture(*m_device, &img, config_texture), }; + m_gpu_storage_images.emplace(0, store_image); + + // Preparing the texture data before we update descriptor set 0 + // Storing all of our texture via one contiguous array of textures + for(const auto&[id, image] : m_gpu_storage_images) { + vk::write_image viking_room_texture = { + .sampler = image.specular.image().sampler(), + .view = image.specular.image().image_view(), + .layout = vk::image_layout::shader_read_only_optimal, + }; + m_gpu_images.emplace_back(viking_room_texture); + } + std::array set0_samples = { vk::write_image_descriptor{ .dst_binding = 1, - .sample_images = samplers, + .sample_images = m_gpu_images, } }; @@ -232,21 +246,18 @@ export namespace atlas { all_meshes.each([this](flecs::entity p_entity){ const mesh_source* src = p_entity.get(); - const auto property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit; vk::buffer_parameters vertex_params = { - .memory_mask = m_physical->memory_properties(property_flags), - // .property_flags = vk::memory_property::device_local_bit, + .memory_mask = m_physical->memory_properties(vk::memory_property::device_local_bit), .usage = vk::buffer_usage::transfer_dst_bit | vk::buffer_usage::vertex_buffer_bit, }; vk::buffer_parameters index_params = { - .memory_mask = m_physical->memory_properties(property_flags), - // .property_flags = vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit, + .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), .usage = vk::buffer_usage::index_buffer_bit, }; - // obj_importer importer("assets/models/viking_room.obj"); + // import .obj 3d model and setting up vertices/indices obj_importer importer(src->model_path); gpu_mesh_data gpu_mesh{}; gpu_mesh.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); @@ -264,7 +275,6 @@ export namespace atlas { void begin(vk::rendering_begin_parameters p_begin_params, const auto& p_extent, const glm::mat4& p_proj, const glm::mat4& p_view) { m_proj_view = p_proj * p_view; - flecs::entity viking_room = m_world->entity("Viking Room"); vk::viewport_params viewport = { .x = 0.0f, .y = 0.0f, @@ -299,15 +309,9 @@ export namespace atlas { } */ - + flecs::entity viking_room = m_world->entity("Viking Room"); const transform* t = viking_room.get(); - // static auto start_time = std::chrono::high_resolution_clock::now(); - - // auto current_time = std::chrono::high_resolution_clock::now(); - // float time = std::chrono::duration( - // current_time - start_time) - // .count(); // Setting up viking room glm::mat4 model = glm::mat4(1.f); model = glm::translate(model, t->position); @@ -336,14 +340,6 @@ export namespace atlas { const VkDescriptorSet set0 = set0_resource; m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); - /* - const VkBuffer vertex = m_viking_room_data.vertex; - uint64_t offset = 0; - m_current_command->bind_vertex_buffers(std::span(&vertex, 1), std::span(&offset, 1)); - if (m_viking_room_data.has_indices_buffer) { - m_current_command->bind_index_buffers32(m_viking_room_data.index); - } - */ for(auto[id, mesh] : m_meshes) { const VkBuffer vertex = mesh.vertex; @@ -359,15 +355,7 @@ export namespace atlas { void end() { - /* - if (m_viking_room_data.has_indices_buffer) { - vkCmdDrawIndexed(*m_current_command, m_viking_room_data.indices_size, 1, 0, 0, 0); - } - else { - vkCmdDraw(*m_current_command, m_viking_room_data.vertices_size, 1, 0, 0); - } - */ - + // TODO: Use Vulkan Indirect Command Draw call for this to reduce draw calls for(auto[id, mesh] : m_meshes) { if (mesh.has_indices_buffer) { vkCmdDrawIndexed(*m_current_command, mesh.indices_size, 1, 0, 0, 0); @@ -389,15 +377,15 @@ export namespace atlas { void destruct() { m_scene_uniforms.reset(); - // m_viking_room_data.vertex.destruct(); - // m_viking_room_data.index.destruct(); - // m_viking_room_texture.destruct(); + for(auto&[id, image] : m_gpu_storage_images) { + image.specular.destruct(); + } + for(auto&[id, mesh] : m_meshes) { mesh.vertex.destruct(); mesh.index.destruct(); } - m_viking_room_texture.destruct(); set0_resource.destruct(); m_shader_resource.destruct(); m_main_pipeline.destruct(); @@ -405,8 +393,6 @@ export namespace atlas { private: uint32_t m_format; - // Should change this but for now this will act as our mesh index - uint32_t m_mesh_idx_count = 0; glm::mat4 m_proj_view=glm::mat4(1.f); // Combination of the projection * view matrix result std::optional m_physical; std::shared_ptr m_device; @@ -425,7 +411,10 @@ export namespace atlas { uint32_t m_texture_slot_index = 0; std::unordered_map m_texture_storage; - vk::texture m_viking_room_texture; + // GPU sampled images + // + std::unordered_map m_gpu_storage_images; + std::vector m_gpu_images; vk::shader_stage m_stage; flecs::world* m_world=nullptr; From 18bfe1b509d1a6e34a5e4f1b1efdca6c3ecfd1fb Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 31 May 2026 16:22:49 -0700 Subject: [PATCH 019/106] refactor: Added mesh_source to viking room demo --- editor/level_scene.cppm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index b4977b70..d8802a06 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -45,6 +45,11 @@ public: .scale{ 1.f }, }); + viking_room.set({ + .model_path = "assets/models/viking_room.obj", + .diffuse = "assets/models/viking_room.png", + }); + atlas::register_start(this, &level_scene::start); atlas::register_physics(this, &level_scene::physics_update); atlas::register_update(this, &level_scene::on_update); @@ -107,6 +112,7 @@ public: t->set_rotation(t->rotation); } + // TODO: Have this physics_update be executed during the physics fixed-update framerate void physics_update() { } From d622d5577c8583371c02fc6c843f3d2b23d1329a Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 31 May 2026 17:49:07 -0700 Subject: [PATCH 020/106] Fixed some buffer parameters specifications --- atlas/drivers/vulkan/render_context.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index f6c10748..c1ec72cb 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -248,7 +248,7 @@ export namespace atlas { const mesh_source* src = p_entity.get(); vk::buffer_parameters vertex_params = { - .memory_mask = m_physical->memory_properties(vk::memory_property::device_local_bit), + .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), .usage = vk::buffer_usage::transfer_dst_bit | vk::buffer_usage::vertex_buffer_bit, }; From fe3a5e063de955841fa220e6fa087bcfdf2d4dfe Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 31 May 2026 17:50:00 -0700 Subject: [PATCH 021/106] refactor: Added testing objects for demonstration --- editor/level_scene.cppm | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index d8802a06..0758e72c 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -50,6 +50,31 @@ public: .diffuse = "assets/models/viking_room.png", }); + // for(size_t i = 0; i < 31; i++) { + // atlas::game_object obj = entity(std::format("Object #{}", i)); + // obj.set({ + // .restitution = 1.25f, + // .body_movement_type = atlas::dynamic, + // }); + + // obj.set( + // { + // .radius = 1.0f, + // }); + + // glm::vec3 pos = {float(0.5 * 1.4), float(0.5 * 1.4), float(0.5 * 1.4) }; + + // obj.set({ + // .position = pos, + // .rotation = {.3f, 0.0f, 0.0f}, + // }); + + // obj.set({ + // .model_path = "assets/models/Ball OBJ.obj", + // .diffuse = "assets/models/clear.png", + // }); + // } + atlas::register_start(this, &level_scene::start); atlas::register_physics(this, &level_scene::physics_update); atlas::register_update(this, &level_scene::on_update); From b2f6e236ad26c2f7bc6eaac40ef27877bc21eaf2 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 31 May 2026 20:04:25 -0700 Subject: [PATCH 022/106] refactor: Added testing example code for scene transitions, not part of this change. For render context, I did some minor code cleanup and fixed naming conventions --- atlas/core/application.cppm | 45 +++++--- atlas/core/event/types.cppm | 6 +- atlas/core/scene/level_streamer.cppm | 15 +++ atlas/core/scene/world.cppm | 5 + atlas/drivers/vulkan/render_context.cppm | 33 ++---- editor/CMakeLists.txt | 1 + editor/editor.cppm | 1 + editor/editor_world.cppm | 7 +- editor/level_scene.cppm | 10 ++ editor/level_scene2.cppm | 136 +++++++++++++++++++++++ 10 files changed, 219 insertions(+), 40 deletions(-) create mode 100644 editor/level_scene2.cppm diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index e71c3ed8..70b4ee4a 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -57,12 +57,6 @@ export namespace atlas { m_physical = p_context->physical_device(); m_device = p_context->logical_device(); - m_bus->create_listener(); - m_bus->create_listener(); - m_bus->create_listener(); - // m_bus->create_immediate_listener(); - // m_bus->create_immediate_listener(); - // Constructing the application std::println("Constructing application"); window_params params = { @@ -79,6 +73,13 @@ export namespace atlas { event::set_window_size(m_window->glfw_window()); + m_bus->create_listener(); + m_bus->create_listener(); + m_bus->create_listener(); + // m_bus->create_immediate_listener(); + // m_bus->create_immediate_listener(); + // m_bus->create_immediate_listener(); + // m_imgui_context = std::make_shared(p_context, // m_window->glfw_window(), // m_window->swapchain_handle(), @@ -150,6 +151,8 @@ export namespace atlas { m_render_context = render_context(m_context, m_color_format, m_depth_format); std::println("images.size() = {}", images.size()); + + // m_bus->trigger(this, &application::on_scene_transition); } void execute() { @@ -161,10 +164,10 @@ export namespace atlas { .depthStencil = { .depth = 1.f, .stencil = 0 }, }; - std::shared_ptr current_scene = m_world->current(); + m_current_scene = m_world->current(); // Handling camera system execution - current_scene + m_current_scene ->system, transform, perspective_camera>() @@ -197,15 +200,15 @@ export namespace atlas { }); // Setting the current scene for the renderer to start rendering the objects - m_render_context.current_scene(*current_scene); + m_render_context.current_scene(*m_current_scene); auto start_time = std::chrono::high_resolution_clock::now(); - invoke_start(current_scene.get()); + invoke_start(m_current_scene.get()); // Querying editor cameras specific objects // Then using this to execute specific main cameras. - auto query_camera_objects = current_scene->query_builder, perspective_camera>().build(); + auto query_camera_objects = m_current_scene->query_builder, perspective_camera>().build(); m_render_context.prebake(); @@ -219,16 +222,16 @@ export namespace atlas { // Progresses the flecs::world by one tick (or replaced with // using the delta time) This also invokes the following // system call before the mainloop - current_scene->progress(m_delta_time); + m_current_scene->progress(m_delta_time); m_next_image_frame_idx = m_window->acquire_next_frame(); const auto current_extent = m_window->surface_properties().capabilities.currentExtent; vk::command_buffer current = m_command_buffers[m_next_image_frame_idx]; - invoke_physics_update(current_scene.get()); + invoke_physics_update(m_current_scene.get()); - invoke_on_update(current_scene.get(), m_delta_time); + invoke_on_update(m_current_scene.get(), m_delta_time); // We want this to be called after late update // This queries all camera objects within the camera system @@ -315,6 +318,19 @@ export namespace atlas { } } + + // Experimental: Will look into later once we dive into scene transitioning + // void on_scene_transition(event::scene_transition& p_scene_transition) { + // m_world->current(p_scene_transition.next_scene); + // std::println("Attempting to switch to the scene: {}", p_scene_transition.next_scene); + + // // We only want to set the current scene if that specific scene is valid + // if(m_world->current() != nullptr) { + // m_current_scene = m_world->current(); + // m_render_context.current_scene(*m_current_scene); + // } + // } + void post_destroy() { m_render_context.destruct(); @@ -352,6 +368,7 @@ export namespace atlas { std::shared_ptr m_world; // std::shared_ptr m_imgui_context; + std::shared_ptr m_current_scene=nullptr; // vulkan-cpp specific handles vk::instance m_instance; diff --git a/atlas/core/event/types.cppm b/atlas/core/event/types.cppm index 0fb4f1bc..d988564f 100644 --- a/atlas/core/event/types.cppm +++ b/atlas/core/event/types.cppm @@ -1,7 +1,7 @@ module; #include -#include +#include export module atlas.core.event:types; @@ -29,8 +29,8 @@ export namespace atlas::event { * @param to_scene is the new scene that is going to be transitioned to */ struct scene_transition { - const void* from_scene; - const void* to_scene; + std::string from_scene; + std::string next_scene; }; /** diff --git a/atlas/core/scene/level_streamer.cppm b/atlas/core/scene/level_streamer.cppm index d3c8a566..046b6f63 100644 --- a/atlas/core/scene/level_streamer.cppm +++ b/atlas/core/scene/level_streamer.cppm @@ -34,6 +34,10 @@ export namespace atlas { * @return the currently active scene to retrieve */ ref current_scene(const std::string& p_name) { + if(!m_scenes.contains(p_name)) { + return nullptr; + } + return m_scenes[p_name]; } @@ -47,6 +51,17 @@ export namespace atlas { p_bus)); } + // Experimental: This was just for testing. Will come back to later. + // template + // void create_scene(const std::string& p_name, event::bus& p_bus) { + // m_scenes.emplace( + // p_name, + // std::allocate_shared( + // std::pmr::polymorphic_allocator(m_allocator.resource()), + // p_name, + // p_bus)); + // } + /** * @brief used to iterate through over the scenes created * diff --git a/atlas/core/scene/world.cppm b/atlas/core/scene/world.cppm index 0616e4de..a72102cf 100644 --- a/atlas/core/scene/world.cppm +++ b/atlas/core/scene/world.cppm @@ -64,6 +64,11 @@ export namespace atlas { m_current = m_level_streamer->current_scene(p_name); } + // template + // void create_scene(const std::string& p_name, event::bus& p_bus) { + // m_level_streamer->create_scene(p_name, p_bus); + // } + private: ref m_current; std::string m_name = "Undefined Tag"; diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index c1ec72cb..85821bf1 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -28,12 +28,6 @@ import vk; export namespace atlas { - struct gpu_push_constant { - glm::mat4 proj; - glm::mat4 view; - glm::mat4 model; - }; - struct gpu_mesh_data { vk::vertex_buffer vertex; vk::index_buffer index; @@ -58,13 +52,9 @@ export namespace atlas { glm::mat4 proj=glm::mat4(1.f); }; - struct storage_geometry { - vk::dyn::buffer vertex; - vk::dyn::buffer index; - }; struct gpu_image { - uint64_t texture_slot_index=0; + uint64_t diffuse_idx=0; vk::texture specular; }; @@ -76,7 +66,7 @@ export namespace atlas { class render_context { public: render_context() = default; - render_context(std::shared_ptr p_context, VkFormat p_color_format, VkFormat p_depth_format) { + render_context(/*NOLINT*/std::shared_ptr p_context, VkFormat p_color_format, VkFormat p_depth_format) { m_physical = p_context->physical_device(); m_device = p_context->logical_device(); @@ -155,7 +145,7 @@ export namespace atlas { .entries = entries_set1, // descriptor layout entries description .descriptor_counts = std::span(&max_descriptor, 1), }; - set0_resource = vk::descriptor_resource(*m_device, set0_layout, vk::descriptor_layout_flags::update_after_bind_pool); + m_set0_resource = vk::descriptor_resource(*m_device, set0_layout, vk::descriptor_layout_flags::update_after_bind_pool); std::array color_blend_attachments = { vk::color_blend_attachment_state{}, @@ -176,7 +166,7 @@ export namespace atlas { .range = sizeof(push_constant_data), }; - VkDescriptorSetLayout descriptor0_layout = set0_resource.layout(); + VkDescriptorSetLayout descriptor0_layout = m_set0_resource.layout(); vk::pipeline_params pipeline_configuration = { .use_render_pipeline = true, .color_attachment_formats = std::span(&m_format, 1), @@ -212,9 +202,9 @@ export namespace atlas { // Loading texture and setting up VkSampler and VkImageView stb_image img = stb_image("assets/models/viking_room.png", config_texture); - // Reminder: Use texture_slot_index + // Reminder: Use diffuse_idx gpu_image store_image = { - .texture_slot_index = 0, + .diffuse_idx = 0, .specular = vk::texture(*m_device, &img, config_texture), }; @@ -238,7 +228,7 @@ export namespace atlas { } }; - set0_resource.update({}, set0_samples); + m_set0_resource.update({}, set0_samples); } void prebake() { @@ -337,7 +327,7 @@ export namespace atlas { }; m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); - const VkDescriptorSet set0 = set0_resource; + const VkDescriptorSet set0 = m_set0_resource; m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); @@ -386,7 +376,7 @@ export namespace atlas { mesh.index.destruct(); } - set0_resource.destruct(); + m_set0_resource.destruct(); m_shader_resource.destruct(); m_main_pipeline.destruct(); } @@ -400,15 +390,14 @@ export namespace atlas { vk::shader_resource m_shader_resource; vk::pipeline m_main_pipeline; std::vector m_indirect_commands; - vk::descriptor_resource set0_resource; + vk::descriptor_resource m_set0_resource; vk::dyn::buffer m_scene_uniforms; - // std::unordered_map m_entity_uniforms; std::unordered_map m_meshes; // Index to lookup for speci - uint32_t m_texture_slot_index = 0; + // uint32_t m_texture_slot_index = 0; std::unordered_map m_texture_storage; // GPU sampled images diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index c0dfbc88..8e82a0a6 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -11,6 +11,7 @@ target_sources(editor PUBLIC editor.cppm editor_world.cppm level_scene.cppm + level_scene2.cppm # content_browser_panel.cppm # icon.cppm # utilities.cppm diff --git a/editor/editor.cppm b/editor/editor.cppm index 0dcff35a..3fd24b78 100644 --- a/editor/editor.cppm +++ b/editor/editor.cppm @@ -5,6 +5,7 @@ export module editor; export import :world; export import :level_scene; +// export import :level_scene2; // export import :icon; // export import :content_browser; // export import :utilities; \ No newline at end of file diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 72825030..6cf55311 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -1,6 +1,7 @@ module; #include +#include export module editor:world; @@ -12,6 +13,8 @@ import atlas.core.scene.uuid; import atlas.core.level_streamer; import atlas.core.scene; import :level_scene; +// import :level_scene2; +// import atlas.core.event; /** * @brief editor_world is where a lot of the editor logic will be handled @@ -27,6 +30,9 @@ public: // Does polymorphic allocations for these customized scenes default_custom_scene("LevelScene", p_bus); + // Experimental for loading a second scene. + // create_scene("Level Scene 2", p_bus); + // Set what our current scene is // TODO: Probably have `default_custom_scene() set this current("LevelScene"); @@ -34,5 +40,4 @@ public: ~editor_world() override = default; -private: }; \ No newline at end of file diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 0758e72c..b68af5f8 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -134,6 +134,16 @@ public: t->rotation.y -= rotation_velocity; } + // Signal to trigger this kind of scene transition + // Experimental: This was used for testing. + // if(atlas::event::is_key_pressed(key_n)) { + // std::println("Signaling to transition to next_scene"); + // atlas::event::scene_transition scene_transition = { + // .next_scene = "Level Scene 2", + // }; + // signal(scene_transition); + // } + t->set_rotation(t->rotation); } diff --git a/editor/level_scene2.cppm b/editor/level_scene2.cppm new file mode 100644 index 00000000..e7222739 --- /dev/null +++ b/editor/level_scene2.cppm @@ -0,0 +1,136 @@ +module; + +#include +#include +#include +#include + +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +export module editor:level_scene2; + +import atlas.application; +import atlas.core.event; +import atlas.core.scene; +import atlas.core.scene.game_object; +import atlas.core.scene.components; +import atlas.core.utilities; +import atlas.core.math; + +// Creating this class for experimentation +export class level_scene2 final : public atlas::scene { +public: + level_scene2(const std::string& p_name, atlas::event::bus& p_bus) + : atlas::scene(p_name, p_bus) { + + + m_editor_camera = entity("Editor Camera"); + m_editor_camera->add>(); + m_editor_camera->set({ + .position = { 3.50f, 4.90f, 36.40f }, + .scale{ 1.f }, + }); + m_editor_camera->set({ + .plane = { 0.1f, 5000.f }, + .is_active = true, + .field_of_view = 45.f, + }); + + atlas::game_object cube = entity("Cube"); + cube.set({ + .position = { -2.70f, 2.70, -8.30f }, + .rotation = { 2.30f, 95.90f, 91.80f }, + .scale{ 1.f }, + }); + + cube.set({ + .model_path = "assets/models/cube.obj", + .diffuse = "assets/models/container_diffuse.png", + }); + + atlas::register_start(this, &level_scene2::start); + atlas::register_physics(this, &level_scene2::physics_update); + atlas::register_update(this, &level_scene2::on_update); + } + + ~level_scene2() override = default; + + void start() { + } + + void on_update(float p_delta_time) { + atlas::transform* t = m_editor_camera->get_mut(); + float dt = p_delta_time; + + // current default movement speed that does not applied modified speed + float default_speed = 10.f; + float rotation_speed = 1.f; + float velocity = default_speed * dt; + if (atlas::event::is_mouse_pressed(mouse_button_middle)) { + velocity = m_movement_speed * dt; + } + + float rotation_velocity = rotation_speed * dt; + + glm::quat to_quaternion = atlas::to_quat(t->quaternion); + + glm::vec3 up = glm::rotate(to_quaternion, atlas::math::up()); + glm::vec3 forward = glm::rotate(to_quaternion, atlas::math::backward()); + glm::vec3 right = glm::rotate(to_quaternion, atlas::math::right()); + + if (atlas::event::is_key_pressed(key_left_shift)) { + t->position += up * velocity; + } + + if (atlas::event::is_key_pressed(key_space)) { + t->position -= up * velocity; + } + + if (atlas::event::is_key_pressed(key_w)) { + t->position += forward * velocity; + } + if (atlas::event::is_key_pressed(key_s)) { + t->position -= forward * velocity; + } + + if (atlas::event::is_key_pressed(key_d)) { + t->position += right * velocity; + } + if (atlas::event::is_key_pressed(key_a)) { + t->position -= right * velocity; + } + + if (atlas::event::is_key_pressed(key_q)) { + t->rotation.y += rotation_velocity; + } + if (atlas::event::is_key_pressed(key_e)) { + t->rotation.y -= rotation_velocity; + } + + // Signal to trigger this kind of scene transition + if(atlas::event::is_key_pressed(key_n)) { + std::println("Signaling to transition to level scene"); + atlas::event::scene_transition scene_transition = { + .next_scene = "Level Scene", + }; + signal(scene_transition); + } + + t->set_rotation(t->rotation); + } + + // TODO: Have this physics_update be executed during the physics fixed-update framerate + void physics_update() { + } + + // void on_signal(atlas::event::scene_transition& p_transition) { + // p_transition.next_scene = "Level Scene 2"; + // } + +private: + std::optional m_editor_camera; + float m_movement_speed = 10.f; +}; \ No newline at end of file From 8cf83051ba4eab18f5ac1e313cecc25174a3d10a Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 1 Jun 2026 01:25:47 -0700 Subject: [PATCH 023/106] refactor: Re-added texture loading and did some linter cleanup for specific API parameters --- atlas/core/application.cppm | 4 +- atlas/drivers/vulkan/render_context.cppm | 141 +++++++++++++++++------ editor/application.cpp | 6 +- 3 files changed, 109 insertions(+), 42 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 70b4ee4a..c33134c9 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -49,7 +49,7 @@ export namespace atlas { class application { public: application() = default; - application(std::shared_ptr p_context, + application(/*NOLINT*/std::shared_ptr p_context, const application_settings& p_params, event::bus& p_bus) : m_context(p_context), m_bus(&p_bus) { @@ -350,7 +350,7 @@ export namespace atlas { } void current_world(std::shared_ptr p_world) { - m_world = p_world; + m_world = std::move(p_world); } private: diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 85821bf1..2bfbbf87 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -6,7 +6,6 @@ module; #include #include #include -#include #include #include @@ -42,7 +41,7 @@ export namespace atlas { }; struct push_constant_data { - int32_t texture_index=0; + uint64_t texture_index=0; uint64_t buffer_address=0; }; @@ -53,9 +52,15 @@ export namespace atlas { }; + /** + * + * @brief slot is the index into the texture array to retrieve this specific texture data + * + * vk::texture is the texture data to configure the GPU-visible image resource + */ struct gpu_image { - uint64_t diffuse_idx=0; - vk::texture specular; + uint64_t slot=0; + vk::texture texture_data; }; /** @@ -195,40 +200,40 @@ export namespace atlas { // testing texture - vk::texture_params config_texture = { - .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - }; + // vk::texture_params config_texture = { + // .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + // }; // Loading texture and setting up VkSampler and VkImageView - stb_image img = stb_image("assets/models/viking_room.png", config_texture); + // stb_image img = stb_image("assets/models/viking_room.png", config_texture); // Reminder: Use diffuse_idx - gpu_image store_image = { - .diffuse_idx = 0, - .specular = vk::texture(*m_device, &img, config_texture), - }; + // gpu_image store_image = { + // .slot = 0, + // .texture_data = vk::texture(*m_device, &img, config_texture), + // }; - m_gpu_storage_images.emplace(0, store_image); + // m_gpu_storage_images.emplace(0, store_image); // Preparing the texture data before we update descriptor set 0 // Storing all of our texture via one contiguous array of textures - for(const auto&[id, image] : m_gpu_storage_images) { - vk::write_image viking_room_texture = { - .sampler = image.specular.image().sampler(), - .view = image.specular.image().image_view(), - .layout = vk::image_layout::shader_read_only_optimal, - }; - m_gpu_images.emplace_back(viking_room_texture); - } - - std::array set0_samples = { - vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = m_gpu_images, - } - }; - - m_set0_resource.update({}, set0_samples); + // for(const auto&[id, image] : m_gpu_storage_images) { + // vk::write_image viking_room_texture = { + // .sampler = image.specular.image().sampler(), + // .view = image.specular.image().image_view(), + // .layout = vk::image_layout::shader_read_only_optimal, + // }; + // m_gpu_images.emplace_back(viking_room_texture); + // } + + // std::array set0_samples = { + // vk::write_image_descriptor{ + // .dst_binding = 1, + // .sample_images = m_gpu_images, + // } + // }; + + // m_set0_resource.update({}, set0_samples); } void prebake() { @@ -259,8 +264,60 @@ export namespace atlas { m_meshes.emplace(p_entity.id(), gpu_mesh); std::println("Entity ID: {}", p_entity.id()); + + // const material_metadata* mat = p_entity.get(); + // loading textures + vk::texture_params config_texture = { + .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + }; + + // Loading texture and setting up VkSampler and VkImageView + // stb_image img = stb_image("assets/models/viking_room.png", config_texture); + stb_image diffuse_img = stb_image(src->diffuse, config_texture); + stb_image specular_img = stb_image(src->specular, config_texture); + + // Reminder: Use diffuse_idx + if(!src->diffuse.empty()) { + std::println("Loading diffuse: {}", src->diffuse); + gpu_image diffuse_store_image = { + .slot = m_texture_slot_index++, + .texture_data = vk::texture(*m_device, &diffuse_img, config_texture), + }; + + m_gpu_storage_images.emplace(m_texture_slot_index, diffuse_store_image); + } + + if(!src->specular.empty()) { + std::println("Loading specular: {}", src->specular); + gpu_image specular_store_image { + .slot = m_texture_slot_index++, + .texture_data = vk::texture(*m_device, &specular_img, config_texture), + }; + + m_gpu_storage_images.emplace(p_entity.id(), specular_store_image); + } }); + // Preparing the texture data before we update descriptor set 0 + // Storing all of our texture via one contiguous array of textures + for(const auto&[id, image] : m_gpu_storage_images) { + vk::write_image viking_room_texture = { + .sampler = image.texture_data.image().sampler(), + .view = image.texture_data.image().image_view(), + .layout = vk::image_layout::shader_read_only_optimal, + }; + m_gpu_images.emplace_back(viking_room_texture); + } + + std::array set0_samples = { + vk::write_image_descriptor{ + .dst_binding = 1, + .sample_images = m_gpu_images, + } + }; + + m_set0_resource.update({}, set0_samples); + } void begin(vk::rendering_begin_parameters p_begin_params, const auto& p_extent, const glm::mat4& p_proj, const glm::mat4& p_view) { @@ -321,11 +378,21 @@ export namespace atlas { // push constant retrieve the buffer that is transferring data to // Then we set the texture index. - push_constant_data push = { - .texture_index = 0, - .buffer_address = ubo_address, - }; - m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); + + flecs::query<> all_meshes = m_world->query_builder().build(); + + all_meshes.each([this, ubo_address](flecs::entity p_entity){ + push_constant_data push = { + .texture_index = m_gpu_storage_images[p_entity.id()].slot, // slot = index to access specific diffuse texture + .buffer_address = ubo_address, + }; + m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); + }); + // push_constant_data push = { + // .texture_index = 0, + // .buffer_address = ubo_address, + // }; + // m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); const VkDescriptorSet set0 = m_set0_resource; m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); @@ -368,7 +435,7 @@ export namespace atlas { void destruct() { m_scene_uniforms.reset(); for(auto&[id, image] : m_gpu_storage_images) { - image.specular.destruct(); + image.texture_data.destruct(); } for(auto&[id, mesh] : m_meshes) { @@ -397,7 +464,7 @@ export namespace atlas { std::unordered_map m_meshes; // Index to lookup for speci - // uint32_t m_texture_slot_index = 0; + uint32_t m_texture_slot_index = 0; std::unordered_map m_texture_storage; // GPU sampled images diff --git a/editor/application.cpp b/editor/application.cpp index 3ac8e1cb..3e7adf7e 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -11,10 +11,10 @@ import atlas.drivers.vulkan; class editor_application : public atlas::application { public: - editor_application(std::shared_ptr p_context, + editor_application(/*NOLINT*/std::shared_ptr p_context, const atlas::application_settings& p_settings, atlas::event::bus& p_bus) - : atlas::application(p_context, p_settings, p_bus) { + : atlas::application(std::move(p_context), p_settings, p_bus) { m_world = std::make_shared("Editor World", p_bus, m_stream); @@ -28,7 +28,7 @@ class editor_application : public atlas::application { }; atlas::ref -initialize_application(std::shared_ptr p_context, atlas::event::bus& p_bus) { +initialize_application(/*NOLINT*/std::shared_ptr p_context, atlas::event::bus& p_bus) { atlas::application_settings settings = { .name = "Editor", .width = 1510, From 71a5f90ae82b6271918b3bd79297e8a0392582ef Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 2 Jun 2026 11:01:41 -0700 Subject: [PATCH 024/106] refactor: wip in getting material table lookup logic to work furthermore --- .../drivers/vulkan/render_context-backup.cppm | 459 ++++++++++++++++++ atlas/drivers/vulkan/render_context.cppm | 89 ++-- 2 files changed, 506 insertions(+), 42 deletions(-) create mode 100644 atlas/drivers/vulkan/render_context-backup.cppm diff --git a/atlas/drivers/vulkan/render_context-backup.cppm b/atlas/drivers/vulkan/render_context-backup.cppm new file mode 100644 index 00000000..6a837a81 --- /dev/null +++ b/atlas/drivers/vulkan/render_context-backup.cppm @@ -0,0 +1,459 @@ +module; + +#include +#include +#include +#include +#include +#include + +#include +#include +#define GLM_FORCE_RADIANS +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +export module atlas.drivers.vulkan:render_context; +import atlas.core.scene; + +import atlas.drivers.importer; +import atlas.core.scene; +import atlas.core.scene.components; +import atlas.drivers.vulkan.stb_image; + +import :graphics_context; +import vk; + +export namespace atlas { + + struct gpu_mesh_data { + vk::vertex_buffer vertex; + vk::index_buffer index; + uint32_t index_count=0; + uint32_t instance=1; + uint32_t first_index=0; + uint32_t vertex_offset=0; + uint32_t first_instance=0; + bool has_indices_buffer=false; + uint32_t vertices_size = 0; + uint32_t indices_size=0; + }; + + struct push_constant_data { + uint64_t diffuse_idx=0; + uint64_t specular_idx=0; + uint64_t buffer_address=0; + }; + + struct global_uniform { + glm::mat4 model=glm::mat4(1.f); + glm::mat4 view=glm::mat4(1.f); + glm::mat4 proj=glm::mat4(1.f); + }; + + + struct gpu_material { + uint64_t diffuse_idx=0; + // uint64_t specular_idx=0; + }; + + /** + * + * @brief slot is the index into the texture array to retrieve this specific texture data + * + * vk::texture is the texture data to configure the GPU-visible image resource + */ + struct gpu_image { + vk::texture texture_data; + }; + + /** + * @brief Core render context to schedule images and barriers for coordinating rendering operations + * + * Manages multiple render contexts + */ + class render_context { + public: + render_context() = default; + render_context(/*NOLINT*/std::shared_ptr p_context, VkFormat p_color_format, VkFormat p_depth_format) { + m_physical = p_context->physical_device(); + m_device = p_context->logical_device(); + + // Vertex Attributes Parameters + std::array attribute_entries = { + vk::vertex_attribute_entry{ + .location = 0, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, position), + }, + vk::vertex_attribute_entry{ + .location = 1, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, color), + }, + vk::vertex_attribute_entry{ + .location = 2, + .format = vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, uv), + }, + vk::vertex_attribute_entry{ + .location = 3, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, normals), + } + }; + std::array attributes = { + vk::vertex_attribute{ + .binding = 0, + .entries = attribute_entries, + .stride = sizeof(vk::vertex_input), + .input_rate = vk::input_rate::vertex, + }, + }; + std::array shader_sources = { + vk::shader_source{ + .filename = "builtin.shaders/pbr.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "builtin.shaders/pbr.frag.spv", + .stage = vk::shader_stage::fragment, + }, + }; + + // To render triangle, we do not need to set any vertex attributes + vk::shader_resource_info shader_info = { + .sources = shader_sources, + }; + m_shader_resource = vk::shader_resource(*m_device, shader_info); + m_shader_resource.vertex_attributes(attributes); + + + // Configuring Descriptor Set 0 -- specify to vk::pipeline + // Descriptor Set 0 + uint32_t max_descriptor = 3; + std::array entries_set1 = { + vk::descriptor_entry{ + // layout (set = 0, binding = 1) uniform sampler2D textures[]; + .type = vk::descriptor_type::combined_image_sampler, + .binding_point = { + .binding = 1, + .stage = vk::shader_stage::fragment, + }, + .descriptor_count = max_descriptor, + .flags = vk::descriptor_bind_flags::partially_bound_bit | + vk::descriptor_bind_flags::variable_descriptor_count_bit | + vk::descriptor_bind_flags::update_after_bind, + } + }; + + // layout(set = 0, ...) + vk::descriptor_layout set0_layout = { + .slot = 0, + .max_sets = max_descriptor, + .entries = entries_set1, // descriptor layout entries description + .descriptor_counts = std::span(&max_descriptor, 1), + }; + m_set0_resource = vk::descriptor_resource(*m_device, set0_layout, vk::descriptor_layout_flags::update_after_bind_pool); + + std::array color_blend_attachments = { + vk::color_blend_attachment_state{}, + }; + + std::array dynamic_states = { + vk::dynamic_state::viewport, vk::dynamic_state::scissor, + }; + + m_format = static_cast(p_color_format); + uint32_t vertex_mask = static_cast(vk::shader_stage::vertex); + uint32_t fragment_mask = static_cast(vk::shader_stage::fragment); + uint32_t stage_mask = vertex_mask | fragment_mask; + m_stage = static_cast(stage_mask); + vk::push_constant_range range = { + .stage = m_stage, + .offset = 0, + .range = sizeof(push_constant_data), + }; + + VkDescriptorSetLayout descriptor0_layout = m_set0_resource.layout(); + vk::pipeline_params pipeline_configuration = { + .use_render_pipeline = true, + .color_attachment_formats = std::span(&m_format, 1), + .depth_format = static_cast(p_depth_format), + .stencil_format = static_cast(p_depth_format), + .renderpass = nullptr, + .shader_modules = m_shader_resource.handles(), + .vertex_attributes = m_shader_resource.vertex_attributes(), + .vertex_bind_attributes = m_shader_resource.vertex_bind_attributes(), + .descriptor_layouts = std::span(&descriptor0_layout, 1), + .color_blend = { + .attachments = color_blend_attachments, + }, + .depth_stencil_enabled = true, + .dynamic_states = dynamic_states, + .push_constants = std::span(&range, 1), + }; + m_main_pipeline = vk::pipeline(*m_device, pipeline_configuration); + + vk::buffer_parameters uniform_params = { + .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | vk::buffer_usage::shader_device_address_bit, + .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, + }; + m_scene_uniforms = vk::dyn::buffer(*m_device, sizeof(global_uniform), uniform_params); + + vk::image_extent extent = { + .width = 1, + .height = 1, + }; + std::array white_color = {0xff, 0xff, 0xff, 0xff}; + // At index = 0 will default to white texture + m_storage_images_arrays.emplace_back(*m_device, extent, white_color, m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)); + + } + + void prebake() { + flecs::query<> all_meshes = m_world->query_builder().build(); + + all_meshes.each([this](flecs::entity p_entity){ + const mesh_source* src = p_entity.get(); + + vk::buffer_parameters vertex_params = { + .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::transfer_dst_bit | vk::buffer_usage::vertex_buffer_bit, + }; + + vk::buffer_parameters index_params = { + .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::index_buffer_bit, + }; + + // import .obj 3d model and setting up vertices/indices + obj_importer importer(src->model_path); + gpu_mesh_data gpu_mesh{}; + gpu_mesh.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); + gpu_mesh.index = vk::index_buffer(*m_device, importer.indices(), index_params); + gpu_mesh.has_indices_buffer = (importer.indices().size() >= 0) ? true : false; + gpu_mesh.vertices_size = importer.vertices().size(); + gpu_mesh.indices_size = importer.indices().size(); + + m_meshes.emplace(p_entity.id(), gpu_mesh); + + std::println("Entity ID: {}", p_entity.id()); + + // const material_metadata* mat = p_entity.get(); + // loading textures + vk::texture_params config_texture = { + .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + }; + + // Loading texture and setting up VkSampler and VkImageView + // stb_image img = stb_image("assets/models/viking_room.png", config_texture); + stb_image diffuse_img = stb_image(src->diffuse, config_texture); + gpu_material material_index = {}; + if(!src->diffuse.empty()) { + std::println("Loading diffuse: {}", src->diffuse); + material_index.diffuse_idx = m_texture_slot_index++; + // vk::texture diffuse(*m_device, &diffuse_img, config_texture); + m_storage_images_arrays.emplace_back(*m_device, &diffuse_img, config_texture); + } + + // if(!src->specular.empty()) { + // std::println("Loading specular: {}", src->specular); + // material_index.specular_idx = m_texture_slot_index++; + // stb_image specular_img = stb_image(src->specular, config_texture); + // vk::texture specular(*m_device, &specular_img, config_texture); + // // m_storage_images_arrays.emplace_back(*m_device, &specular_img, config_texture); + // m_storage_images_arrays.emplace_back(specular); + // } + + + m_mesh_materials.emplace(p_entity.id(), material_index); + }); + + // Preparing the texture data before we update descriptor set 0 + // Storing all of our texture via one contiguous array of textures + // for(const auto&[id, image] : m_gpu_storage_images) { + for(auto image : m_storage_images_arrays) { + vk::write_image write_gpu_image = { + .sampler = image.image().sampler(), + .view = image.image().image_view(), + .layout = vk::image_layout::shader_read_only_optimal, + }; + m_gpu_images.push_back(write_gpu_image); + } + + std::array set0_samples = { + vk::write_image_descriptor{ + .dst_binding = 1, + .sample_images = m_gpu_images, + } + }; + + m_set0_resource.update({}, set0_samples); + + } + + void begin(vk::rendering_begin_parameters p_begin_params, const auto& p_extent, const glm::mat4& p_proj, const glm::mat4& p_view) { + m_proj_view = p_proj * p_view; + vk::viewport_params viewport = { + .x = 0.0f, + .y = 0.0f, + .width = static_cast(p_extent.width), + .height = static_cast(p_extent.height), + .min_depth = 0.0f, + .max_depth = 1.0f, + }; + m_current_command->set_viewport(0, 1, std::span(&viewport, 1)); + + vk::scissor_params scissor = { + .offset = { 0, 0 }, + .extent = p_extent, + }; + m_current_command->set_scissor(0, 1, std::span(&scissor, 1)); + + m_current_command->begin_rendering(p_begin_params); + + m_main_pipeline.bind(*m_current_command); + + /* + TODO (TEMP): Consider having transform to be changed as an unbounded array on the shader + struct shader_transform_struct { + // Where we will have an unbounded array of 3D object + // transforms that can already be accessible when being modified + mat4 models[]; + } object_transform; + + + void main() { + gl_Position = ubo.view * ubo.proj * object_transform.models[gl_VertexIndex] * vec4(inPosition, 1.0); + } + + */ + flecs::entity viking_room = m_world->entity("Viking Room"); + const transform* t = viking_room.get(); + + // Setting up viking room + glm::mat4 model = glm::mat4(1.f); + model = glm::translate(model, t->position); + model = glm::scale(model, t->scale); + + global_uniform ubo = { + .model = model, + .view = p_view, + .proj = p_proj, + }; + ubo.proj[1][1] *= -1; + + m_scene_uniforms.transfer(std::span(&ubo, 1)); + + // Retrieving the buffer address that can be looked up from the glsl shader + const uint64_t ubo_address = m_scene_uniforms.get_device_address(); + + // push constant retrieve the buffer that is transferring data to + // Then we set the texture index. + + // flecs::query<> all_meshes = m_world->query_builder().build(); + + // all_meshes.each([this, ubo_address](flecs::entity p_entity){ + // if(!p_entity.has()) { + // return; + // } + // push_constant_data push = { + // .diffuse_idx = m_mesh_materials[p_entity.id()].diffuse_idx, + // // .specular_idx = m_mesh_materials[p_entity.id()].specular_idx, + // .buffer_address = ubo_address, + // }; + // m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); + // }); + push_constant_data push = { + .diffuse_idx = 0, + .buffer_address = ubo_address, + }; + m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); + + const VkDescriptorSet set0 = m_set0_resource; + m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); + + + for(auto[id, mesh] : m_meshes) { + const VkBuffer vertex = mesh.vertex; + uint64_t offset = 0; + m_current_command->bind_vertex_buffers(std::span(&vertex, 1), std::span(&offset, 1)); + if (mesh.has_indices_buffer) { + m_current_command->bind_index_buffers32(mesh.index); + } + } + + + } + + void end() { + + // TODO: Use Vulkan Indirect Command Draw call for this to reduce draw calls + for(auto[id, mesh] : m_meshes) { + if (mesh.has_indices_buffer) { + vkCmdDrawIndexed(*m_current_command, mesh.indices_size, 1, 0, 0, 0); + } + else { + vkCmdDraw(*m_current_command, mesh.vertices_size, 1, 0, 0); + } + } + m_current_command->end_rendering(); + } + + void set_command(vk::command_buffer& p_command) { + m_current_command = &p_command; + } + + void current_scene(flecs::world& p_world) { + m_world = &p_world; + } + + void destruct() { + m_scene_uniforms.reset(); + // for(auto&[id, image] : m_gpu_storage_images) { + // image.texture_data.destruct(); + // } + + for(auto&[id, mesh] : m_meshes) { + mesh.vertex.destruct(); + mesh.index.destruct(); + } + + m_set0_resource.destruct(); + m_shader_resource.destruct(); + m_main_pipeline.destruct(); + } + + private: + uint32_t m_format; + glm::mat4 m_proj_view=glm::mat4(1.f); // Combination of the projection * view matrix result + std::optional m_physical; + std::shared_ptr m_device; + vk::command_buffer* m_current_command=nullptr; + vk::shader_resource m_shader_resource; + vk::pipeline m_main_pipeline; + std::vector m_indirect_commands; + vk::descriptor_resource m_set0_resource; + + vk::dyn::buffer m_scene_uniforms; + + std::unordered_map m_meshes; + + // Index to lookup for specific texture (image) resource + // Index 0 default to a white texture if no textures found + uint32_t m_texture_slot_index = 1; + + // GPU sampled images + // + // std::unordered_map m_gpu_storage_images; + std::unordered_map m_mesh_materials; + std::vector m_storage_images_arrays; + std::vector m_gpu_images; + vk::shader_stage m_stage; + + flecs::world* m_world=nullptr; + }; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 2bfbbf87..d8ca05de 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -51,6 +51,10 @@ export namespace atlas { glm::mat4 proj=glm::mat4(1.f); }; + struct gpu_material { + uint64_t diffuse_idx=0; + }; + /** * @@ -198,42 +202,14 @@ export namespace atlas { }; m_scene_uniforms = vk::dyn::buffer(*m_device, sizeof(global_uniform), uniform_params); - - // testing texture - // vk::texture_params config_texture = { - // .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - // }; - - // Loading texture and setting up VkSampler and VkImageView - // stb_image img = stb_image("assets/models/viking_room.png", config_texture); - - // Reminder: Use diffuse_idx - // gpu_image store_image = { - // .slot = 0, - // .texture_data = vk::texture(*m_device, &img, config_texture), - // }; - - // m_gpu_storage_images.emplace(0, store_image); - - // Preparing the texture data before we update descriptor set 0 - // Storing all of our texture via one contiguous array of textures - // for(const auto&[id, image] : m_gpu_storage_images) { - // vk::write_image viking_room_texture = { - // .sampler = image.specular.image().sampler(), - // .view = image.specular.image().image_view(), - // .layout = vk::image_layout::shader_read_only_optimal, - // }; - // m_gpu_images.emplace_back(viking_room_texture); - // } - - // std::array set0_samples = { - // vk::write_image_descriptor{ - // .dst_binding = 1, - // .sample_images = m_gpu_images, - // } + // Index 0 will default to a white texture + // vk::image_extent extent = { + // .width = 1, + // .height = 1, // }; + // std::array white_color = {0xff, 0xff, 0xff, 0xff}; + // m_gpu_textures.emplace_back(*m_device, extent, white_color, m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)); - // m_set0_resource.update({}, set0_samples); } void prebake() { @@ -277,6 +253,21 @@ export namespace atlas { stb_image specular_img = stb_image(src->specular, config_texture); // Reminder: Use diffuse_idx + gpu_material material = {}; + if(!src->diffuse.empty()) { + std::println("Loading diffuse: {}", src->diffuse); + material.diffuse_idx = m_texture_slot_index++; + // gpu_image diffuse_store_image = { + // .slot = m_texture_slot_index++, + // .texture_data = vk::texture(*m_device, &diffuse_img, config_texture), + // }; + + // m_gpu_storage_images.emplace(m_texture_slot_index, diffuse_store_image); + m_gpu_textures.emplace_back(*m_device, &diffuse_img, config_texture); + } + + m_material_table.emplace(p_entity.id(), material); + /* if(!src->diffuse.empty()) { std::println("Loading diffuse: {}", src->diffuse); gpu_image diffuse_store_image = { @@ -296,19 +287,29 @@ export namespace atlas { m_gpu_storage_images.emplace(p_entity.id(), specular_store_image); } + */ }); // Preparing the texture data before we update descriptor set 0 // Storing all of our texture via one contiguous array of textures - for(const auto&[id, image] : m_gpu_storage_images) { + // for(const auto&[id, image] : m_gpu_storage_images) { + // vk::write_image viking_room_texture = { + // .sampler = image.texture_data.image().sampler(), + // .view = image.texture_data.image().image_view(), + // .layout = vk::image_layout::shader_read_only_optimal, + // }; + // m_gpu_images.emplace_back(viking_room_texture); + // } + for(auto& image : m_gpu_textures) { vk::write_image viking_room_texture = { - .sampler = image.texture_data.image().sampler(), - .view = image.texture_data.image().image_view(), + .sampler = image.image().sampler(), + .view = image.image().image_view(), .layout = vk::image_layout::shader_read_only_optimal, }; m_gpu_images.emplace_back(viking_room_texture); } + std::array set0_samples = { vk::write_image_descriptor{ .dst_binding = 1, @@ -434,8 +435,10 @@ export namespace atlas { void destruct() { m_scene_uniforms.reset(); - for(auto&[id, image] : m_gpu_storage_images) { - image.texture_data.destruct(); + + // destroying vector + for(auto& image : m_gpu_textures) { + image.destruct(); } for(auto&[id, mesh] : m_meshes) { @@ -463,9 +466,11 @@ export namespace atlas { std::unordered_map m_meshes; - // Index to lookup for speci - uint32_t m_texture_slot_index = 0; - std::unordered_map m_texture_storage; + uint64_t m_texture_slot_index = 0; + // is to search for specific indices that correspond to various material surfaces + // indices to search inside of vector + std::unordered_map m_material_table; + std::vector m_gpu_textures; // GPU sampled images // From a5d79a5792d2691fb454dc3ed4cef006d2c5154a Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 2 Jun 2026 16:54:33 -0700 Subject: [PATCH 025/106] Fixed texture size for descriptor allocations --- atlas/drivers/vulkan/render_context.cppm | 50 ++++++------------------ 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index d8ca05de..d05a832d 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -131,6 +131,7 @@ export namespace atlas { // Configuring Descriptor Set 0 -- specify to vk::pipeline // Descriptor Set 0 + uint32_t max_descriptors = 10; std::array entries_set1 = { vk::descriptor_entry{ // layout (set = 0, binding = 1) uniform sampler2D textures[]; @@ -139,7 +140,7 @@ export namespace atlas { .binding = 1, .stage = vk::shader_stage::fragment, }, - .descriptor_count = 1, + .descriptor_count = max_descriptors, .flags = vk::descriptor_bind_flags::partially_bound_bit | vk::descriptor_bind_flags::variable_descriptor_count_bit | vk::descriptor_bind_flags::update_after_bind, @@ -147,12 +148,11 @@ export namespace atlas { }; // layout(set = 0, ...) - uint32_t max_descriptor = 1; vk::descriptor_layout set0_layout = { .slot = 0, - .max_sets = 3, + .max_sets = max_descriptors, .entries = entries_set1, // descriptor layout entries description - .descriptor_counts = std::span(&max_descriptor, 1), + .descriptor_counts = std::span(&max_descriptors, 1), }; m_set0_resource = vk::descriptor_resource(*m_device, set0_layout, vk::descriptor_layout_flags::update_after_bind_pool); @@ -203,12 +203,12 @@ export namespace atlas { m_scene_uniforms = vk::dyn::buffer(*m_device, sizeof(global_uniform), uniform_params); // Index 0 will default to a white texture - // vk::image_extent extent = { - // .width = 1, - // .height = 1, - // }; - // std::array white_color = {0xff, 0xff, 0xff, 0xff}; - // m_gpu_textures.emplace_back(*m_device, extent, white_color, m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)); + vk::image_extent extent = { + .width = 1, + .height = 1, + }; + std::array white_color = {0xff, 0xff, 0xff, 0xff}; + m_gpu_textures.emplace_back(*m_device, extent, white_color, m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)); } @@ -257,27 +257,11 @@ export namespace atlas { if(!src->diffuse.empty()) { std::println("Loading diffuse: {}", src->diffuse); material.diffuse_idx = m_texture_slot_index++; - // gpu_image diffuse_store_image = { - // .slot = m_texture_slot_index++, - // .texture_data = vk::texture(*m_device, &diffuse_img, config_texture), - // }; - - // m_gpu_storage_images.emplace(m_texture_slot_index, diffuse_store_image); m_gpu_textures.emplace_back(*m_device, &diffuse_img, config_texture); } m_material_table.emplace(p_entity.id(), material); /* - if(!src->diffuse.empty()) { - std::println("Loading diffuse: {}", src->diffuse); - gpu_image diffuse_store_image = { - .slot = m_texture_slot_index++, - .texture_data = vk::texture(*m_device, &diffuse_img, config_texture), - }; - - m_gpu_storage_images.emplace(m_texture_slot_index, diffuse_store_image); - } - if(!src->specular.empty()) { std::println("Loading specular: {}", src->specular); gpu_image specular_store_image { @@ -292,14 +276,6 @@ export namespace atlas { // Preparing the texture data before we update descriptor set 0 // Storing all of our texture via one contiguous array of textures - // for(const auto&[id, image] : m_gpu_storage_images) { - // vk::write_image viking_room_texture = { - // .sampler = image.texture_data.image().sampler(), - // .view = image.texture_data.image().image_view(), - // .layout = vk::image_layout::shader_read_only_optimal, - // }; - // m_gpu_images.emplace_back(viking_room_texture); - // } for(auto& image : m_gpu_textures) { vk::write_image viking_room_texture = { .sampler = image.image().sampler(), @@ -384,7 +360,7 @@ export namespace atlas { all_meshes.each([this, ubo_address](flecs::entity p_entity){ push_constant_data push = { - .texture_index = m_gpu_storage_images[p_entity.id()].slot, // slot = index to access specific diffuse texture + .texture_index = m_material_table[p_entity.id()].diffuse_idx, // slot = index to access specific diffuse texture .buffer_address = ubo_address, }; m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); @@ -394,7 +370,7 @@ export namespace atlas { // .buffer_address = ubo_address, // }; // m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); - + const VkDescriptorSet set0 = m_set0_resource; m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); @@ -466,7 +442,7 @@ export namespace atlas { std::unordered_map m_meshes; - uint64_t m_texture_slot_index = 0; + uint64_t m_texture_slot_index = 1; // is to search for specific indices that correspond to various material surfaces // indices to search inside of vector std::unordered_map m_material_table; From 8f784436ea56d690d19d0e32ca73ba3971ef19d7 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 00:07:07 -0700 Subject: [PATCH 026/106] refactor: Redid the core renderer to better handle model matrices and scene related uniforms using the power of indexing to large storage buffers on the GPU --- atlas/core/entry_point/main.cpp | 15 +++ atlas/drivers/vulkan/render_context.cppm | 130 ++++++++++++++++------- builtin.shaders/pbr.frag | 10 +- builtin.shaders/pbr.frag.spv | Bin 1092 -> 1092 bytes builtin.shaders/pbr.vert | 36 +++++-- builtin.shaders/pbr.vert.spv | Bin 2596 -> 2976 bytes 6 files changed, 141 insertions(+), 50 deletions(-) diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 24b9d0ea..2fd14dfd 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -63,6 +63,11 @@ get_instance_extensions() { return extension_names; } +// using device_features = vk::feature_trait; +// using robustness2_features_ext = vk::feature_trait; + + + int main() { // We should not have our core system start up during testing environment @@ -123,6 +128,11 @@ main() { }; #endif + // VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features{}; + // robustness2Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; + // robustness2Features.robustBufferAccess2 = VK_TRUE; // <--- This enables the feature + // robustness2Features.robustImageAccess2 = VK_FALSE; // (Optional: enable if you want it for images too) + // robustness2Features.nullDescriptor = VK_FALSE; // (Optional: allows binding null descriptors) vk::device_features device_features{ vk::dynamic_rendering_feature{ { .dynamicRendering = true, @@ -137,6 +147,11 @@ main() { vk::buffer_device_address{ { .bufferDeviceAddress = true, } }, + // robustness2_features_ext{ { + // .robustBufferAccess2 = true, + // .robustImageAccess2 = false, + // .nullDescriptor = false, + // } }, }; vk::device_params logical_device_params = { diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index d05a832d..3cdd9b5d 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -41,16 +41,21 @@ export namespace atlas { }; struct push_constant_data { - uint64_t texture_index=0; - uint64_t buffer_address=0; + uint64_t scene_address=0; + uint64_t model_mat_array_address=0; + uint32_t model_idx=0; + uint32_t material_address=0; }; - struct global_uniform { - glm::mat4 model=glm::mat4(1.f); + struct scene_uniforms { glm::mat4 view=glm::mat4(1.f); glm::mat4 proj=glm::mat4(1.f); }; + struct objects_uniform { + std::span model_matrices; + }; + struct gpu_material { uint64_t diffuse_idx=0; }; @@ -131,7 +136,7 @@ export namespace atlas { // Configuring Descriptor Set 0 -- specify to vk::pipeline // Descriptor Set 0 - uint32_t max_descriptors = 10; + uint32_t max_descriptors = 1000; std::array entries_set1 = { vk::descriptor_entry{ // layout (set = 0, binding = 1) uniform sampler2D textures[]; @@ -200,7 +205,11 @@ export namespace atlas { .usage = vk::buffer_usage::uniform_buffer_bit | vk::buffer_usage::shader_device_address_bit, .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, }; - m_scene_uniforms = vk::dyn::buffer(*m_device, sizeof(global_uniform), uniform_params); + + uint32_t max_objects = 10'000; + m_scene_uniforms = vk::dyn::buffer(*m_device, sizeof(scene_uniforms), uniform_params); + + m_object_model_uniforms = vk::dyn::buffer(*m_device, sizeof(objects_uniform) * max_objects, uniform_params); // Index 0 will default to a white texture vk::image_extent extent = { @@ -234,8 +243,8 @@ export namespace atlas { gpu_mesh.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); gpu_mesh.index = vk::index_buffer(*m_device, importer.indices(), index_params); gpu_mesh.has_indices_buffer = (importer.indices().size() >= 0) ? true : false; - gpu_mesh.vertices_size = importer.vertices().size(); - gpu_mesh.indices_size = importer.indices().size(); + gpu_mesh.vertices_size = importer.vertices().size_bytes(); + gpu_mesh.indices_size = importer.indices().size_bytes(); m_meshes.emplace(p_entity.id(), gpu_mesh); @@ -319,50 +328,69 @@ export namespace atlas { m_main_pipeline.bind(*m_current_command); - /* - TODO (TEMP): Consider having transform to be changed as an unbounded array on the shader - struct shader_transform_struct { - // Where we will have an unbounded array of 3D object - // transforms that can already be accessible when being modified - mat4 models[]; - } object_transform; - - - void main() { - gl_Position = ubo.view * ubo.proj * object_transform.models[gl_VertexIndex] * vec4(inPosition, 1.0); - } - - */ - flecs::entity viking_room = m_world->entity("Viking Room"); - const transform* t = viking_room.get(); + // Calculating model matrix based on object's transforms specifications (pos, scale, rotation) - // Setting up viking room - glm::mat4 model = glm::mat4(1.f); - model = glm::translate(model, t->position); - model = glm::scale(model, t->scale); + flecs::query<> all_meshes = m_world->query_builder().build(); - global_uniform ubo = { - .model = model, + // Camera projection/view matrices calculated for worldspace calculation + scene_uniforms scene_ubo = { .view = p_view, .proj = p_proj, }; - ubo.proj[1][1] *= -1; + scene_ubo.proj[1][1] *= -1; - m_scene_uniforms.transfer(std::span(&ubo, 1)); + m_scene_uniforms.transfer(std::span(&scene_ubo, 1)); - // Retrieving the buffer address that can be looked up from the glsl shader - const uint64_t ubo_address = m_scene_uniforms.get_device_address(); + all_meshes.each([this](flecs::entity p_entity){ + const transform* t = p_entity.get(); + glm::mat4 model = glm::mat4(1.f); + model = glm::translate(model, t->position); + model = glm::scale(model, t->scale); + // m_model_matrix_index_count + + if(m_model_matrices_lookup.contains(p_entity.id())) { + // hash table to lookup specific index, using the entitys main ID has a hash key + // This way we can use the hash value as the location in the index to modify that model matrix. + m_model_matrices[m_model_matrices_lookup[p_entity.id()]] = model; + } + else { + // Add model matrix if non existant in the array + m_model_matrices.push_back(model); + + // Keeping track of the location to that model matrix for book keeping. + m_model_matrices_lookup.emplace(p_entity.id(), m_model_matrix_index_count++); + } + }); - // push constant retrieve the buffer that is transferring data to - // Then we set the texture index. + // objects_uniform object_ubo = { + // .model_matrices = m_model_matrices, + // }; + // m_object_model_uniforms.transfer(std::span(&object_ubo, 1)); + m_object_model_uniforms.transfer(std::span(m_model_matrices.data(), m_model_matrices.size())); - flecs::query<> all_meshes = m_world->query_builder().build(); + // Retrieving the buffer address that can be looked up from the glsl shader + // struct push_constant_data { + // uint64_t scene_address=0; + // uint64_t model_mat_array_address=0; + // uint64_t model_idx=0; + // uint64_t material_address=0; + // }; - all_meshes.each([this, ubo_address](flecs::entity p_entity){ + all_meshes.each([this](flecs::entity p_entity) { + const uint64_t scene_ubo_address = m_scene_uniforms.get_device_address(); + const uint64_t objects_ubo_address = m_object_model_uniforms.get_device_address(); push_constant_data push = { - .texture_index = m_material_table[p_entity.id()].diffuse_idx, // slot = index to access specific diffuse texture - .buffer_address = ubo_address, + .scene_address = scene_ubo_address, + .model_mat_array_address = objects_ubo_address, + .model_idx = static_cast(m_model_matrices_lookup[p_entity.id()]), + .material_address = static_cast(m_material_table[p_entity.id()].diffuse_idx), }; + + // std::println("scene_address = {}", static_cast(push.scene_address)); + // std::println("Model Array Addr = {}", static_cast(push.model_mat_array_address)); + // std::println("Model Index = {}", push.model_idx); + // std::println("Material Diffuse Index = {}", push.material_address); + m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); }); // push_constant_data push = { @@ -411,6 +439,7 @@ export namespace atlas { void destruct() { m_scene_uniforms.reset(); + m_object_model_uniforms.reset(); // destroying vector for(auto& image : m_gpu_textures) { @@ -438,11 +467,32 @@ export namespace atlas { std::vector m_indirect_commands; vk::descriptor_resource m_set0_resource; + /** + * 3 Specific Buffers for accessing data + * 1.) Scene Uniform Buffer (proj/view) + * 2.) Object Uniforms (model matrix): Another use is for instancing having multiple mat4's referencing to instancing copies + * 3.) Material Uniforms (diffuse/specular/etc...) + */ vk::dyn::buffer m_scene_uniforms; + // uniform buffer to write all of our objects mat4 model matrices in + vk::dyn::buffer m_object_model_uniforms; + std::unordered_map m_meshes; uint64_t m_texture_slot_index = 1; + + // Represents the index to retrieve the location to access the model matrix + // inside of the vector array + uint64_t m_model_matrix_index_count = 0; + + // + std::unordered_map m_model_matrices_lookup; + std::vector m_model_matrices; + + + // material lookups + // is to search for specific indices that correspond to various material surfaces // indices to search inside of vector std::unordered_map m_material_table; diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag index 0a98c202..30b2f385 100644 --- a/builtin.shaders/pbr.frag +++ b/builtin.shaders/pbr.frag @@ -5,7 +5,8 @@ layout(location = 0) in vec3 fragColor; layout(location = 1) in vec2 fragTexCoords; layout(location = 2) in vec3 fragNormals; -layout(location = 3) in flat int fragTexIndex; +layout(location = 3) in flat int fragDiffuseIdx; +// layout(location = 4) in flat int fragSpecularIdx; layout(location = 0) out vec4 outColor; @@ -13,5 +14,10 @@ layout(set = 0, binding = 1) uniform sampler2D textures[]; void main() { - outColor = texture(textures[nonuniformEXT(fragTexIndex)], fragTexCoords); + // vec4 diffuse = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); + // vec4 specular = texture(textures[nonuniformEXT(fragSpecularIdx)], fragTexCoords); + + outColor = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); + // vec3 material_color = vec3(diffuse.rgb * specular.rgb); + // outColor = vec4(material_color, 1.0); } \ No newline at end of file diff --git a/builtin.shaders/pbr.frag.spv b/builtin.shaders/pbr.frag.spv index 7cc26048ac6f92c159ea5b7e814883401c1fc658..9f3f042a0bc1729991085b7765abf190d54a68a8 100644 GIT binary patch delta 23 ecmX@YafD+-3L}?GW?EWlajIuZ#pXQ5YfJ!VUI?84 delta 23 ecmX@YafD+-3L{rYYK3QBN@@iI!{$83YfJ!Qtq0ox diff --git a/builtin.shaders/pbr.vert b/builtin.shaders/pbr.vert index c270eec8..9cdcd2a4 100644 --- a/builtin.shaders/pbr.vert +++ b/builtin.shaders/pbr.vert @@ -1,6 +1,19 @@ #version 450 #extension GL_EXT_buffer_reference : require +#extension GL_EXT_scalar_block_layout : require + +/* + +layout(location = 3) out MaterialData { + int diffuse_idx; + int specular_idx; + int roughness_idx; + int normal_idx; + int parallax_idx; +} material_output; + +*/ layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inColor; @@ -10,27 +23,34 @@ layout(location = 3) in vec3 inNormals; layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTexCoords; layout(location = 2) out vec3 fragNormals; -layout(location = 3) out flat int fragTexIndex; +layout(location = 3) out flat int fragDiffuseIdx; -layout(buffer_reference, std140) buffer readonly UniformBufferObject { - mat4 model; +layout(buffer_reference, scalar) buffer readonly SceneUniforms { mat4 view; mat4 proj; }; +layout(buffer_reference, scalar) buffer ObjectsTable { + mat4 model[]; +}; + layout(push_constant) uniform Constants { - int texture_index; - UniformBufferObject global_ubo_address; + SceneUniforms global_ubo; + ObjectsTable objects; + int model_matrix_idx; + int diffuse_idx; } push_const; void main() { - UniformBufferObject ubo = push_const.global_ubo_address; + SceneUniforms ubo = push_const.global_ubo; + ObjectsTable object = push_const.objects; + - gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); + gl_Position = ubo.proj * ubo.view * object.model[push_const.model_matrix_idx] * vec4(inPosition, 1.0); fragColor = inColor; fragTexCoords = inTexCoords; fragNormals = inNormals; - fragTexIndex = push_const.texture_index; + fragDiffuseIdx = push_const.diffuse_idx; } \ No newline at end of file diff --git a/builtin.shaders/pbr.vert.spv b/builtin.shaders/pbr.vert.spv index fcb1ab4b15ed456555fd788575ba4a2a73abd882..81b64f1fc54250239057f8cb7f49dfccca2cfb3d 100644 GIT binary patch literal 2976 zcmZ9M+j1L45QfLr!Hz=$A>;rgM#eyZfC-RkMpS4iGzHUW}SmD=#B@2FjIcj<}}-T?Uj7gU%7qf7S+z1lKD$D zsQ0QYR#|e`i4yc>$z4fZvMzZfX-U45Y)Q5yCH>86|3gK}X3jL*!RC+q?&Kf~b$*!i zLiy&sFIS75Ea=8*@24Q{9H-+ExeNH4J3GzxX3!fBb&2CR4B{vWgMO5Sy;1ZsB+k}x zaZ%EX$NlMmiXx`(P|@8N)Zbn&Ou`?MXpm-yx$LT`SX`=k8HGQydyIJuv-Aa6MfZC} z`?#A*uV_xjG}0s=b&^q0r)n``58|||=@V*e5lgMK`$FyK!scx(^EyoXVH_NGMp<+e zMExT{@)xyA()-b1FwR5k;tm&t?G$zPJKb25D9!+9*?QXP@uK$OIDa1WXcVk$-V|2! zfn7CAvJc{5H_V=e*(jWx56;4u=Fuoh6GhM2ciZVzqlR>A9s?k5l6#~i0Smg zNgnsXH;&_pkGaAx7CpnWD485-vAVEMV|#{pI$LbEPcZHd z#!l~G&~Vwez=9-+i(h-v+%>GX?x4roXfr7(Rr(v ztxhbyi>g44C0W?$H>5GwzcuK~(wSLJaz*FxM%dirs{WtR4u-v`|8Nfssmb^p?Zi>%zO(r~0=wzX zgG(&pFKNfenb>fgUa9Nj-;zEf!T+{);_=fzGp$Kj#AClBA^w`|ns(}eala+)ex5by zg_O;^(s>K~^o_mjFwT8nIy0NT$EU)0JNzr!@i8yn?6!8!r6&G6+Gix-)W?R8VDwGw zJ&7^DJ|zBuG;-+`d(GKCAG_`_UvFJD^*Db+J2icOo6@NVPCWJ_hf%*Nom}t7ZaIwj zHRGRzThv5n*R#nH;`QT%I_KdW5Wr4Be3g= zf-{#T@Jdf&Ruuz(u1LTis3Q5;#KW0u65`d30``q7kPQfj{QDgA?K0lF8fAj*+K9g`4_(u#g zza;^$YZCPPxr98<#J4J(`d>)!oj&(VVK<$hn(*u^2^@W*bD90u4%0TlzHt~l@NxGY z#u>ZHgu~xT$R{2@T>njV@vTZYpBU~4_a91@CG^kxU=!ziYe-*rzPfg7eDL?Nq$ME_ mj$`}0wsd%l4?bi2x$a75uJDw2=K4eePCR_Z{!gsGC;1;`DFG$` literal 2596 zcmZ9MZ*vqy5XOgGE`%T=B7am2fvBK?01Aje;NS=s%an-*DBo>e?j~WV&FUGRa2r-8J?~ja` zF^9~?`m^N6m0yz4^H-%C^wXrQ@}j?Olg;tgmMs)N@?DHC()Y<0@?Lo0j=U z9Pk~L#+sDu^j*gJ6Ul<)rsO-x9m$g9zN91RN?Q7x(EgW5Ce1<9TTPaKebQu33ak7! z8(7(9u=Uo~daKLHU^G&ZuTq<&F0;wd6?Ra$mllrc$j@bibUch5+VY5NY%AxC@;}Yo zR$lBp^fzAHd?7yFy6tT;o1J`UQ|$rc&M%$)4O_st$Ee6(fVFk6_q2~UbDi71JKa1h ztA19M!l#tC?wB!^-L1xjOcLXk0!|29SbH znbY1sS+~VATZmMu&>H8wohIvf=_;3JK0p3-4&g4VHr(&(U|kzF?xUD)>PC+ol@IJ* zT&uB-({#_qoq2N>HS+c@+e_&&W?@Ui)y>nq@P3niHe6OC+=Ds6=ZW3z=6NxsU+^(I zE_;W9F-!RVq{r*0rT6Q2zkt-eVb&VXADTAnn`rs><(?~k!gSDTOIGyDT(I;J`F_Vf z^e6V2$5AWz(ASs;eLoLa%!3Y3M-q6bE#^Vr&jS|opu_W8!X25zH~LOFGjrIfJu|k!9x!6S*n=N=z*-T;8H{hRr{4wbvl13M^AYR(-#~{KJF^k% z%mg~Qurm*_-f495a{sP&?u{>Je6bxD103h1p>w{V)0Fmq)w`2A)Au>aDaFzobnbCl zzlXGgq0g#M%nn$PIavZ1Hgx&`2lxr;M?7BNbyhlcf?>!1sCM|k?=(992f!AZ_+vWL zEBrrfY=QrT$MvIyKl(`t{%540(oQ{Kv&zc5hI?W|;Qd%TJ;F{M=zRBJp^i^=W(EB- zo#`p@^qihjH@*ByJ9&x6{&*>b;o|g_*=dNStrGtmqKa~g0&n0sb?1AqKonyW)rGqg~ zp_U6egYW0NC=5>Q@bUhaB+Smw%1MtF8%*0CcBR1%MA+2^BgeWTnXPLQ;_=7M4E`Zr zY~M)8j}LuhCa+8QE~uTpqvIE9yQMR8h>iI~$HrXU^XJ;e?A3aGrw7tI9&7nILnkM5 avn=6#>VDP#Qyw=sd6+Zw|22)bByRz?YudB` From 4c8eceb6f474b39a705ee1c34849ff9637ac4d92 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 01:03:09 -0700 Subject: [PATCH 027/106] refactor: update to using vulkan-cpp/6.1 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 7f69cd5e..07500927 100644 --- a/conanfile.py +++ b/conanfile.py @@ -40,7 +40,7 @@ def requirements(self): self.requires("yaml-cpp/0.8.0") # Vulkan-related headers and includes packages - self.requires("vulkan-cpp/6.0") + self.requires("vulkan-cpp/6.1") self.requires("tinyobjloader/2.0.0-rc10") self.requires("stb/cci.20230920") From 3c5f1bdfa91b13ae073521c03bd4e55d65d7bea1 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 01:08:49 -0700 Subject: [PATCH 028/106] refactor: code cleanup and removing any dead code that were present and redid some of the logic better --- atlas/drivers/vulkan/render_context.cppm | 66 ++++++------------------ editor/level_scene.cppm | 31 ++++++----- 2 files changed, 35 insertions(+), 62 deletions(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 3cdd9b5d..adb0704b 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -206,9 +206,11 @@ export namespace atlas { .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, }; - uint32_t max_objects = 10'000; m_scene_uniforms = vk::dyn::buffer(*m_device, sizeof(scene_uniforms), uniform_params); + // We are setting to the maximum of objects that should be managed in this uniform buffer + // This uniform buffer is responsible for managing the model matrices of every object in a given scene. + uint32_t max_objects = 10'000; m_object_model_uniforms = vk::dyn::buffer(*m_device, sizeof(objects_uniform) * max_objects, uniform_params); // Index 0 will default to a white texture @@ -237,34 +239,27 @@ export namespace atlas { .usage = vk::buffer_usage::index_buffer_bit, }; - // import .obj 3d model and setting up vertices/indices + // importing .obj 3d models here obj_importer importer(src->model_path); gpu_mesh_data gpu_mesh{}; gpu_mesh.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); gpu_mesh.index = vk::index_buffer(*m_device, importer.indices(), index_params); gpu_mesh.has_indices_buffer = (importer.indices().size() >= 0) ? true : false; - gpu_mesh.vertices_size = importer.vertices().size_bytes(); - gpu_mesh.indices_size = importer.indices().size_bytes(); + gpu_mesh.vertices_size = importer.vertices().size(); + gpu_mesh.indices_size = importer.indices().size(); m_meshes.emplace(p_entity.id(), gpu_mesh); - - std::println("Entity ID: {}", p_entity.id()); - - // const material_metadata* mat = p_entity.get(); - // loading textures + vk::texture_params config_texture = { .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), }; - // Loading texture and setting up VkSampler and VkImageView - // stb_image img = stb_image("assets/models/viking_room.png", config_texture); stb_image diffuse_img = stb_image(src->diffuse, config_texture); stb_image specular_img = stb_image(src->specular, config_texture); // Reminder: Use diffuse_idx gpu_material material = {}; if(!src->diffuse.empty()) { - std::println("Loading diffuse: {}", src->diffuse); material.diffuse_idx = m_texture_slot_index++; m_gpu_textures.emplace_back(*m_device, &diffuse_img, config_texture); } @@ -328,8 +323,6 @@ export namespace atlas { m_main_pipeline.bind(*m_current_command); - // Calculating model matrix based on object's transforms specifications (pos, scale, rotation) - flecs::query<> all_meshes = m_world->query_builder().build(); // Camera projection/view matrices calculated for worldspace calculation @@ -341,12 +334,12 @@ export namespace atlas { m_scene_uniforms.transfer(std::span(&scene_ubo, 1)); + // Calculating model matrix based on object's transforms specifications (pos, scale, rotation) all_meshes.each([this](flecs::entity p_entity){ const transform* t = p_entity.get(); glm::mat4 model = glm::mat4(1.f); model = glm::translate(model, t->position); model = glm::scale(model, t->scale); - // m_model_matrix_index_count if(m_model_matrices_lookup.contains(p_entity.id())) { // hash table to lookup specific index, using the entitys main ID has a hash key @@ -362,20 +355,9 @@ export namespace atlas { } }); - // objects_uniform object_ubo = { - // .model_matrices = m_model_matrices, - // }; - // m_object_model_uniforms.transfer(std::span(&object_ubo, 1)); m_object_model_uniforms.transfer(std::span(m_model_matrices.data(), m_model_matrices.size())); // Retrieving the buffer address that can be looked up from the glsl shader - // struct push_constant_data { - // uint64_t scene_address=0; - // uint64_t model_mat_array_address=0; - // uint64_t model_idx=0; - // uint64_t material_address=0; - // }; - all_meshes.each([this](flecs::entity p_entity) { const uint64_t scene_ubo_address = m_scene_uniforms.get_device_address(); const uint64_t objects_ubo_address = m_object_model_uniforms.get_device_address(); @@ -386,46 +368,30 @@ export namespace atlas { .material_address = static_cast(m_material_table[p_entity.id()].diffuse_idx), }; - // std::println("scene_address = {}", static_cast(push.scene_address)); - // std::println("Model Array Addr = {}", static_cast(push.model_mat_array_address)); - // std::println("Model Index = {}", push.model_idx); - // std::println("Material Diffuse Index = {}", push.material_address); - m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); }); - // push_constant_data push = { - // .texture_index = 0, - // .buffer_address = ubo_address, - // }; - // m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); const VkDescriptorSet set0 = m_set0_resource; m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); - - - for(auto[id, mesh] : m_meshes) { - const VkBuffer vertex = mesh.vertex; - uint64_t offset = 0; - m_current_command->bind_vertex_buffers(std::span(&vertex, 1), std::span(&offset, 1)); - if (mesh.has_indices_buffer) { - m_current_command->bind_index_buffers32(mesh.index); - } - } - - } void end() { // TODO: Use Vulkan Indirect Command Draw call for this to reduce draw calls - for(auto[id, mesh] : m_meshes) { + flecs::query<> all_meshes = m_world->query_builder().build(); + all_meshes.each([this](flecs::entity p_entity) { + auto& mesh = m_meshes[p_entity.id()]; + const VkBuffer vertex = mesh.vertex; + uint64_t offset = 0; + m_current_command->bind_vertex_buffers(std::span(&vertex, 1), std::span(&offset, 1)); if (mesh.has_indices_buffer) { + m_current_command->bind_index_buffers32(mesh.index); vkCmdDrawIndexed(*m_current_command, mesh.indices_size, 1, 0, 0, 0); } else { vkCmdDraw(*m_current_command, mesh.vertices_size, 1, 0, 0); } - } + }); m_current_command->end_rendering(); } diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index b68af5f8..3a1db505 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -25,9 +25,9 @@ public: level_scene(const std::string& p_name, atlas::event::bus& p_bus) : atlas::scene(p_name, p_bus) { - m_editor_camera = entity("Editor Camera"); - m_editor_camera->add>(); + m_editor_camera + ->add>(); m_editor_camera->set({ .position = { 3.50f, 4.90f, 36.40f }, .scale{ 1.f }, @@ -41,13 +41,18 @@ public: atlas::game_object viking_room = entity("Viking Room"); viking_room.set({ .position = { -2.70f, 2.70, -8.30f }, + // .position = { 1.f, 1.f, 1.f }, .rotation = { 2.30f, 95.90f, 91.80f }, + // .rotation = { 1.f, 1.f, 1.f }, .scale{ 1.f }, }); viking_room.set({ - .model_path = "assets/models/viking_room.obj", - .diffuse = "assets/models/viking_room.png", + .model_path = "assets/models/viking_room.obj", + .diffuse = "assets/models/viking_room.png", + // .model_path = "assets/models/cube.obj", + // .diffuse = "assets/models/container_diffuse.png", + // .diffuse = "assets/models/container_specular.png", }); // for(size_t i = 0; i < 31; i++) { @@ -62,7 +67,8 @@ public: // .radius = 1.0f, // }); - // glm::vec3 pos = {float(0.5 * 1.4), float(0.5 * 1.4), float(0.5 * 1.4) }; + // glm::vec3 pos = {float(0.5 * 1.4), float(0.5 * 1.4), float(0.5 + // * 1.4) }; // obj.set({ // .position = pos, @@ -70,8 +76,10 @@ public: // }); // obj.set({ - // .model_path = "assets/models/Ball OBJ.obj", - // .diffuse = "assets/models/clear.png", + // // .model_path = "assets/models/Ball OBJ.obj", + // .model_path = "assets/models/cube.obj", + // // .diffuse = "assets/models/clear.png", + // .diffuse = "assets/models/container_diffuse.png", // }); // } @@ -82,8 +90,7 @@ public: ~level_scene() override = default; - void start() { - } + void start() {} void on_update(float p_delta_time) { atlas::transform* t = m_editor_camera->get_mut(); @@ -147,9 +154,9 @@ public: t->set_rotation(t->rotation); } - // TODO: Have this physics_update be executed during the physics fixed-update framerate - void physics_update() { - } + // TODO: Have this physics_update be executed during the physics + // fixed-update framerate + void physics_update() {} private: std::optional m_editor_camera; From a74b2dc6d0ad26bf4a48134ba6acc002f0f66fca Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 11:44:50 -0700 Subject: [PATCH 029/106] refactor: remove dead code commented in entry_point.cpp --- atlas/core/entry_point/main.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 2fd14dfd..24b9d0ea 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -63,11 +63,6 @@ get_instance_extensions() { return extension_names; } -// using device_features = vk::feature_trait; -// using robustness2_features_ext = vk::feature_trait; - - - int main() { // We should not have our core system start up during testing environment @@ -128,11 +123,6 @@ main() { }; #endif - // VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features{}; - // robustness2Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; - // robustness2Features.robustBufferAccess2 = VK_TRUE; // <--- This enables the feature - // robustness2Features.robustImageAccess2 = VK_FALSE; // (Optional: enable if you want it for images too) - // robustness2Features.nullDescriptor = VK_FALSE; // (Optional: allows binding null descriptors) vk::device_features device_features{ vk::dynamic_rendering_feature{ { .dynamicRendering = true, @@ -147,11 +137,6 @@ main() { vk::buffer_device_address{ { .bufferDeviceAddress = true, } }, - // robustness2_features_ext{ { - // .robustBufferAccess2 = true, - // .robustImageAccess2 = false, - // .nullDescriptor = false, - // } }, }; vk::device_params logical_device_params = { From 274840156a979a2f0b4f290819f8d48412c1aada Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 11:51:31 -0700 Subject: [PATCH 030/106] refactor: update project CMakeLists.txt --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0471e771..93562bfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -207,10 +207,15 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/vulkan/stb_image.cppm atlas/drivers/vulkan/hash.cppm - atlas/drivers/vulkan/mesh.cppm + # atlas/drivers/vulkan/mesh.cppm atlas/drivers/vulkan/shader_resource_group.cppm atlas/drivers/vulkan/render_system.cppm atlas/drivers/vulkan/uniforms.cppm + + + # 3D Model Importers + atlas/drivers/importer/importer.cppm + atlas/drivers/importer/obj_loader.cppm ) target_sources(${PROJECT_NAME} PUBLIC From af8cca3fc650ca111479a8ac016eebbe2d0bb25c Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 18:20:39 -0700 Subject: [PATCH 031/106] refactor: remove commented old implementation of the window abstraction --- atlas/drivers/vulkan/window.cppm | 105 +++---------------------------- 1 file changed, 7 insertions(+), 98 deletions(-) diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 2e5a5a15..7046080b 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -20,7 +20,6 @@ module; #include #include -// export module atlas.window; export module atlas.drivers.vulkan:window; import atlas.common; @@ -30,111 +29,17 @@ import :graphics_context; export namespace atlas { - /* - class window { - public: - virtual ~window() = default; - - [[nodiscard]] window_params data() const { return get_params(); } - - // ** - // * @brief Checks if window is available to close - // * - [[nodiscard]] bool available() const { - return !glfwWindowShouldClose(native_window()); - } - - // * - // * @brief Returns the aspect ratio of the current window - // * - [[nodiscard]] float aspect_ratio() const { - return static_cast(get_params().width) / - static_cast(get_params().height); - } - - // * - // * @brief gives you the next presentable image to use and the index - to - // * retrieving that image - // * - // * @return uint32_t - // * - [[nodiscard]] uint32_t acquired_next_frame() { - return read_acquired_next_frame(); - } - - // ** - // * @brief Returns the window's currently selected swapchain - // * - [[nodiscard]] vulkan::swapchain current_swapchain() const { - return window_swapchain(); - } - - // * - // * @brief retrieves the current command buffer using the current - frame - // * index to ensure we are processing commands to the right command - // * buffer in our current frame - // * - // * @return command buffer to actively record commands to - // * - vk::command_buffer active_command(uint32_t p_frame_index) { - return current_active_command(p_frame_index); - } - - // * - // * @brief operator overload for treating atlas::window as a - GLFWwindow - // * handle - // * - operator GLFWwindow*() const { return native_window(); } - - // * - // * @brief operator overload for treating atlas::window as a - GLFWwindow - // * handle - // * - operator GLFWwindow*() { return native_window(); } - - // * - // * @brief Closing the window operation - // * - void close() { glfwSetWindowShouldClose(native_window(), true); } - - // * - // * @brief does the presentation operation that is operated internally - // * with the vulkan swapchain - // * - // * @param p_current_frame_idx is current frame index to currently - // * process an image in the current frame - // * - void present(const uint32_t& p_current_frame_idx) { - return present_frame(p_current_frame_idx); - } - - protected: - [[nodiscard]] virtual window_params get_params() const = 0; - [[nodiscard]] virtual GLFWwindow* native_window() const = 0; - [[nodiscard]] virtual uint32_t read_acquired_next_frame() = 0; - [[nodiscard]] virtual vulkan::swapchain window_swapchain() const = 0; - - [[nodiscard]] virtual vk::command_buffer current_active_command( - uint32_t p_frame_idx) = 0; - - virtual void present_frame(const uint32_t& p_current_frame) = 0; - }; - */ - class window { public: window() = default; - window(std::shared_ptr p_context, const window_params& p_params) + window(/*NOLINT*/ std::shared_ptr p_context, const window_params& p_params) : m_device(p_context->logical_device()) { m_instance = p_context->instance_handle(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); m_params = p_params; + m_window = glfwCreateWindow(static_cast(p_params.width), static_cast(p_params.height), @@ -142,6 +47,10 @@ export namespace atlas { nullptr, nullptr); + int w = 0; + int h =0; + + glfwGetFramebufferSize(m_window, &w, &h); glfwMakeContextCurrent(m_window); std::println("Constructing atlas::window"); @@ -197,7 +106,7 @@ export namespace atlas { m_present_queue.destruct(); } - GLFWwindow* glfw_window() const { return m_window; } + [[nodiscard]] GLFWwindow* glfw_window() const { return m_window; } std::shared_ptr swapchain_handle() { return m_swapchain; } From ffdef312b320169fb11f3a402257e790f7fb92b8 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 18:42:21 -0700 Subject: [PATCH 032/106] refactor: fix more of the window sizing parameters to be more consistent from the application to render_context --- atlas/core/application.cppm | 127 +++++++++++++---------- atlas/drivers/vulkan/render_context.cppm | 5 +- atlas/drivers/vulkan/window.cppm | 10 +- 3 files changed, 81 insertions(+), 61 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index c33134c9..ef6a57c7 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -49,10 +49,11 @@ export namespace atlas { class application { public: application() = default; - application(/*NOLINT*/std::shared_ptr p_context, + application(/*NOLINT*/ std::shared_ptr p_context, const application_settings& p_params, event::bus& p_bus) - : m_context(p_context), m_bus(&p_bus) { + : m_context(p_context) + , m_bus(&p_bus) { m_instance = p_context->instance_handle(); m_physical = p_context->physical_device(); m_device = p_context->logical_device(); @@ -64,11 +65,9 @@ export namespace atlas { .height = p_params.height, .name = p_params.name, }; - m_extent = { - .width = p_params.width, - .height = p_params.height, - }; - // m_window = std::allocate_shared(, m_context->instance_handle(), params); + + // m_window = std::allocate_shared(, + // m_context->instance_handle(), params); m_window = std::make_shared(p_context, params); event::set_window_size(m_window->glfw_window()); @@ -104,7 +103,7 @@ export namespace atlas { m_images.resize(images.size()); m_depth_images.resize(images.size()); - for(uint32_t i = 0; i < m_images.size(); i++) { + for (uint32_t i = 0; i < m_images.size(); i++) { vk::image_params color_img_params = { .extent = { .width = p_params.width, @@ -118,7 +117,8 @@ export namespace atlas { .mip_levels = 1, .layer_count = 1, }; - m_images[i] = vk::sample_image(*m_device, images[i], color_img_params); + m_images[i] = + vk::sample_image(*m_device, images[i], color_img_params); vk::image_params depth_img_params = { .extent = { @@ -134,30 +134,34 @@ export namespace atlas { .layer_count = 1, }; - m_depth_images[i] = vk::sample_image(*m_device, depth_img_params); + m_depth_images[i] = + vk::sample_image(*m_device, depth_img_params); } m_command_buffers.resize(images.size()); - for(uint32_t i = 0; i < m_command_buffers.size(); i++) { + for (uint32_t i = 0; i < m_command_buffers.size(); i++) { vk::command_params command_params = { .levels = vk::command_levels::primary, .queue_index = 0, .flags = vk::command_pool_flags::reset, }; - m_command_buffers[i] = vk::command_buffer(*m_device, command_params); + m_command_buffers[i] = + vk::command_buffer(*m_device, command_params); } - m_render_context = render_context(m_context, m_color_format, m_depth_format); + m_render_context = + render_context(m_context, m_color_format, m_depth_format); std::println("images.size() = {}", images.size()); - // m_bus->trigger(this, &application::on_scene_transition); + // m_bus->trigger(this, + // &application::on_scene_transition); } void execute() { VkClearValue clear_color = { - {{ 0.f, 0.5f, 0.5f, 1.f }}, + { { 0.f, 0.5f, 0.5f, 1.f } }, }; VkClearValue depth_value = { @@ -199,22 +203,29 @@ export namespace atlas { p_pair->view = glm::inverse(p_pair->view); }); - // Setting the current scene for the renderer to start rendering the objects + // Setting the current scene for the renderer to start rendering the + // objects m_render_context.current_scene(*m_current_scene); auto start_time = std::chrono::high_resolution_clock::now(); invoke_start(m_current_scene.get()); - // Querying editor cameras specific objects // Then using this to execute specific main cameras. - auto query_camera_objects = m_current_scene->query_builder, perspective_camera>().build(); + auto query_camera_objects = + m_current_scene + ->query_builder, + perspective_camera>() + .build(); m_render_context.prebake(); - while(m_window->available()) { + while (m_window->available()) { auto current_time = std::chrono::high_resolution_clock::now(); - m_delta_time = std::chrono::duration(current_time - start_time).count(); + m_delta_time = + std::chrono::duration( + current_time - start_time) + .count(); start_time = current_time; event::flush_events(); @@ -225,9 +236,9 @@ export namespace atlas { m_current_scene->progress(m_delta_time); m_next_image_frame_idx = m_window->acquire_next_frame(); - const auto current_extent = m_window->surface_properties().capabilities.currentExtent; - vk::command_buffer current = m_command_buffers[m_next_image_frame_idx]; + vk::command_buffer current = + m_command_buffers[m_next_image_frame_idx]; invoke_physics_update(m_current_scene.get()); @@ -254,18 +265,18 @@ export namespace atlas { m_render_context.set_command(current); m_images[m_next_image_frame_idx].memory_barrier( - current, - m_window->surface_properties().format.format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - + current, + m_window->surface_properties().format.format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + m_depth_images[m_next_image_frame_idx].memory_barrier( - current, - m_depth_format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - + current, + m_depth_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + vk::rendering_attachment color_render_attachment = { .image_view = m_images[m_next_image_frame_idx].image_view(), .layout = vk::image_layout::color_optimal, @@ -278,7 +289,8 @@ export namespace atlas { }; vk::rendering_attachment depth_stencil_attachment = { - .image_view = m_depth_images[m_next_image_frame_idx].image_view(), + .image_view = + m_depth_images[m_next_image_frame_idx].image_view(), .layout = vk::image_layout::depth_stencil_optimal, .resolve_mode = vk::resolved_mode_flags::none, .resolve_image_view = nullptr, @@ -291,8 +303,8 @@ export namespace atlas { vk::rendering_begin_parameters begin_params = { .render_area = { { 0, 0 }, { - current_extent.width, - current_extent.height, + m_window->extent().width, + m_window->extent().height, }, }, .layer_count = 1, .color_attachments = std::span( @@ -301,15 +313,16 @@ export namespace atlas { .stencil_attachment = depth_stencil_attachment, }; - m_render_context.begin(begin_params, current_extent, m_projection, m_view); + m_render_context.begin( + begin_params, m_window->extent(), m_projection, m_view); m_render_context.end(); m_images[m_next_image_frame_idx].memory_barrier( - current, - m_window->surface_properties().format.format, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + current, + m_window->surface_properties().format.format, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); current.end(); const VkCommandBuffer command = current; @@ -318,14 +331,15 @@ export namespace atlas { } } - - // Experimental: Will look into later once we dive into scene transitioning - // void on_scene_transition(event::scene_transition& p_scene_transition) { + // Experimental: Will look into later once we dive into scene + // transitioning void on_scene_transition(event::scene_transition& + // p_scene_transition) { // m_world->current(p_scene_transition.next_scene); - // std::println("Attempting to switch to the scene: {}", p_scene_transition.next_scene); + // std::println("Attempting to switch to the scene: {}", + // p_scene_transition.next_scene); - // // We only want to set the current scene if that specific scene is valid - // if(m_world->current() != nullptr) { + // // We only want to set the current scene if that specific scene + // is valid if(m_world->current() != nullptr) { // m_current_scene = m_world->current(); // m_render_context.current_scene(*m_current_scene); // } @@ -334,15 +348,15 @@ export namespace atlas { void post_destroy() { m_render_context.destruct(); - for(auto& command : m_command_buffers) { + for (auto& command : m_command_buffers) { command.destruct(); } - for(auto& color_image : m_images) { + for (auto& color_image : m_images) { color_image.destruct(); } - for(auto& depth_image : m_depth_images) { + for (auto& depth_image : m_depth_images) { depth_image.destruct(); } m_window->destruct(); @@ -354,31 +368,30 @@ export namespace atlas { } private: - uint32_t m_next_image_frame_idx=0; + uint32_t m_next_image_frame_idx = 0; VkFormat m_color_format; VkFormat m_depth_format; std::shared_ptr m_context; - std::shared_ptr m_window=nullptr; + std::shared_ptr m_window = nullptr; event::bus* m_bus = nullptr; - glm::mat4 m_view=glm::mat4(1.f); - glm::mat4 m_projection=glm::mat4(1.f); + glm::mat4 m_view = glm::mat4(1.f); + glm::mat4 m_projection = glm::mat4(1.f); render_context m_render_context; std::shared_ptr m_world; // std::shared_ptr m_imgui_context; - std::shared_ptr m_current_scene=nullptr; + std::shared_ptr m_current_scene = nullptr; // vulkan-cpp specific handles vk::instance m_instance; std::optional m_physical; std::shared_ptr m_device; - vk::image_extent m_extent{}; std::vector m_images; std::vector m_depth_images; std::vector m_command_buffers; - float m_delta_time=0.f; + float m_delta_time = 0.f; static application* s_instance; }; diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index adb0704b..45ebe426 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -21,6 +21,7 @@ import atlas.drivers.importer; import atlas.core.scene; import atlas.core.scene.components; import atlas.drivers.vulkan.stb_image; +import atlas.core.utilities; import :graphics_context; import vk; @@ -301,7 +302,7 @@ export namespace atlas { } - void begin(vk::rendering_begin_parameters p_begin_params, const auto& p_extent, const glm::mat4& p_proj, const glm::mat4& p_view) { + void begin(vk::rendering_begin_parameters p_begin_params, const window_params& p_extent, const glm::mat4& p_proj, const glm::mat4& p_view) { m_proj_view = p_proj * p_view; vk::viewport_params viewport = { .x = 0.0f, @@ -315,7 +316,7 @@ export namespace atlas { vk::scissor_params scissor = { .offset = { 0, 0 }, - .extent = p_extent, + .extent = {p_extent.width, p_extent.height}, }; m_current_command->set_scissor(0, 1, std::span(&scissor, 1)); diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 7046080b..0a144e8b 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -38,8 +38,6 @@ export namespace atlas { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - m_params = p_params; - m_window = glfwCreateWindow(static_cast(p_params.width), static_cast(p_params.height), @@ -51,6 +49,12 @@ export namespace atlas { int h =0; glfwGetFramebufferSize(m_window, &w, &h); + + m_params = { + .width = static_cast(w), + .height = static_cast(h), + }; + glfwMakeContextCurrent(m_window); std::println("Constructing atlas::window"); @@ -139,6 +143,8 @@ export namespace atlas { return !glfwWindowShouldClose(m_window); } + [[nodiscard]] window_params extent() const { return m_params; } + private: vk::instance m_instance; std::shared_ptr m_device=nullptr; From c5e135d7ba234a82a8eae8264fa7ea02e3390f01 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 18:44:03 -0700 Subject: [PATCH 033/106] refactor: add missing include --- atlas/core/entry_point/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 24b9d0ea..7ee5e36a 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -1,6 +1,7 @@ // For glfwInit call #include #include +#include #include #include #include From 2bd0de39fa67fe36b59a4c029b70eb631ff46d6d Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 18:49:36 -0700 Subject: [PATCH 034/106] refactor: fix the extent in the window abstraction --- atlas/core/application.cppm | 8 ++++---- atlas/drivers/vulkan/render_context.cppm | 2 +- atlas/drivers/vulkan/window.cppm | 16 ++++++---------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index ef6a57c7..0729304b 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -106,8 +106,8 @@ export namespace atlas { for (uint32_t i = 0; i < m_images.size(); i++) { vk::image_params color_img_params = { .extent = { - .width = p_params.width, - .height = p_params.height, + .width = m_window->extent().width, + .height = m_window->extent().height, }, .format = m_window->surface_properties().format.format, .memory_mask = m_physical->memory_properties( @@ -122,8 +122,8 @@ export namespace atlas { vk::image_params depth_img_params = { .extent = { - .width = p_params.width, - .height = p_params.height, + .width = m_window->extent().width, + .height = m_window->extent().height, }, .format = m_depth_format, .memory_mask = m_physical->memory_properties( diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 45ebe426..0d46fe68 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -316,7 +316,7 @@ export namespace atlas { vk::scissor_params scissor = { .offset = { 0, 0 }, - .extent = {p_extent.width, p_extent.height}, + .extent = {static_cast(p_extent.width), static_cast(p_extent.height)}, }; m_current_command->set_scissor(0, 1, std::span(&scissor, 1)); diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 0a144e8b..5784d9eb 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -45,22 +45,18 @@ export namespace atlas { nullptr, nullptr); - int w = 0; - int h =0; - - glfwGetFramebufferSize(m_window, &w, &h); - - m_params = { - .width = static_cast(w), - .height = static_cast(h), - }; - glfwMakeContextCurrent(m_window); std::println("Constructing atlas::window"); m_surface = std::make_shared(p_context->instance_handle(), m_window); center_window(); + + m_params = { + .width = p_params.width, + .height = p_params.height, + }; + vk::swapchain_params swapchain_params = { .width = static_cast(m_params.width), .height = static_cast(m_params.height), From ea30dc04efd752d1db50d5b135669c06de023292 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 18:54:12 -0700 Subject: [PATCH 035/106] refactor: fix centering the window according screen dimensions --- atlas/drivers/vulkan/window.cppm | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 5784d9eb..23a9f31b 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -38,6 +38,10 @@ export namespace atlas { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + m_params = { + .width = p_params.width, + .height = p_params.height, + }; m_window = glfwCreateWindow(static_cast(p_params.width), static_cast(p_params.height), @@ -52,11 +56,6 @@ export namespace atlas { center_window(); - m_params = { - .width = p_params.width, - .height = p_params.height, - }; - vk::swapchain_params swapchain_params = { .width = static_cast(m_params.width), .height = static_cast(m_params.height), From 9de8abe4a5c435c4053bf5223ceecbbbed268c29 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 21:18:53 -0700 Subject: [PATCH 036/106] refactor: fix window.cppm and removed dead code --- atlas/core/application.cppm | 8 ++-- atlas/drivers/vulkan/render_context.cppm | 2 +- atlas/drivers/vulkan/window.cppm | 55 ++++++++++++------------ 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 0729304b..b1307fa2 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -59,7 +59,6 @@ export namespace atlas { m_device = p_context->logical_device(); // Constructing the application - std::println("Constructing application"); window_params params = { .width = p_params.width, .height = p_params.height, @@ -70,6 +69,7 @@ export namespace atlas { // m_context->instance_handle(), params); m_window = std::make_shared(p_context, params); + m_aspect_ratio = static_cast(params.width / params.height); event::set_window_size(m_window->glfw_window()); m_bus->create_listener(); @@ -175,10 +175,9 @@ export namespace atlas { ->system, transform, perspective_camera>() - .each([&](flecs::pair p_pair, + .each([this](flecs::pair p_pair, transform& p_transform, perspective_camera& p_camera) { - float aspect_ratio = m_window->aspect_ratio(); if (!p_camera.is_active) { return; } @@ -187,7 +186,7 @@ export namespace atlas { p_pair->projection = glm::perspective(glm::radians(p_camera.field_of_view), - aspect_ratio, + m_aspect_ratio, p_camera.plane.x, p_camera.plane.y); p_pair->projection[1][1] *= -1; @@ -368,6 +367,7 @@ export namespace atlas { } private: + float m_aspect_ratio=0.f; uint32_t m_next_image_frame_idx = 0; VkFormat m_color_format; VkFormat m_depth_format; diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 0d46fe68..05a6d84b 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -381,7 +381,7 @@ export namespace atlas { // TODO: Use Vulkan Indirect Command Draw call for this to reduce draw calls flecs::query<> all_meshes = m_world->query_builder().build(); all_meshes.each([this](flecs::entity p_entity) { - auto& mesh = m_meshes[p_entity.id()]; + const auto& mesh = m_meshes[p_entity.id()]; const VkBuffer vertex = mesh.vertex; uint64_t offset = 0; m_current_command->bind_vertex_buffers(std::span(&vertex, 1), std::span(&offset, 1)); diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 23a9f31b..7c7485d8 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -32,7 +32,8 @@ export namespace atlas { class window { public: window() = default; - window(/*NOLINT*/ std::shared_ptr p_context, const window_params& p_params) + window(/*NOLINT*/ std::shared_ptr p_context, + const window_params& p_params) : m_device(p_context->logical_device()) { m_instance = p_context->instance_handle(); @@ -42,7 +43,7 @@ export namespace atlas { .width = p_params.width, .height = p_params.height, }; - + m_window = glfwCreateWindow(static_cast(p_params.width), static_cast(p_params.height), p_params.name.c_str(), @@ -50,11 +51,9 @@ export namespace atlas { nullptr); glfwMakeContextCurrent(m_window); - std::println("Constructing atlas::window"); - m_surface = std::make_shared(p_context->instance_handle(), m_window); - - center_window(); + m_surface = std::make_shared( + p_context->instance_handle(), m_window); vk::swapchain_params swapchain_params = { .width = static_cast(m_params.width), @@ -62,20 +61,23 @@ export namespace atlas { .present_index = 0, }; - const VkSurfaceKHR surface = *m_surface; - m_surface_properties = p_context->physical_device().request_surface(surface); - m_swapchain = std::make_shared(*p_context->logical_device(), surface, swapchain_params, p_context->physical_device().request_surface(surface)); + m_surface_properties = + p_context->physical_device().request_surface(*m_surface); + m_swapchain = + std::make_shared(*p_context->logical_device(), + *m_surface, + swapchain_params, + m_surface_properties); + + center_window(); + vk::queue_params present_params = { .family = 0, .index = 0, }; - m_present_queue = vk::device_present_queue(*p_context->logical_device(), *m_swapchain, present_params); - - // graphics_context::submit_resource_free([this](){ - // std::println("atlas::window submit resource free"); - // // m_swapchain.destruct(); - // }); + m_present_queue = vk::device_present_queue( + *p_context->logical_device(), *m_swapchain, present_params); } ~window() { @@ -90,9 +92,6 @@ export namespace atlas { return m_swapchain->get_images(); } - [[nodiscard]] vk::surface_params surface_properties() const { return m_surface_properties; } - - [[nodiscard]] uint32_t acquire_next_frame() { return m_present_queue.acquire_next_image(); } @@ -107,13 +106,16 @@ export namespace atlas { [[nodiscard]] GLFWwindow* glfw_window() const { return m_window; } - std::shared_ptr swapchain_handle() { return m_swapchain; } - - [[nodiscard]] vk::device_present_queue present_queue() const { return m_present_queue; } + std::shared_ptr swapchain_handle() { + return m_swapchain; + } + [[nodiscard]] vk::device_present_queue present_queue() const { + return m_present_queue; + } - float aspect_ratio() { - return static_cast(m_params.width / m_params.height); + [[nodiscard]] vk::surface_params surface_properties() const { + return m_surface_properties; } void center_window() { @@ -121,9 +123,8 @@ export namespace atlas { const GLFWvidmode* mode = glfwGetVideoMode(monitor); uint32_t width = (mode->width / 2) - (m_params.width / 2); uint32_t height = (mode->height / 2) - (m_params.height / 2); - glfwSetWindowPos(m_window, - static_cast(width), - static_cast(height)); + glfwSetWindowPos( + m_window, static_cast(width), static_cast(height)); } void submit(std::span p_commands) { @@ -142,7 +143,7 @@ export namespace atlas { private: vk::instance m_instance; - std::shared_ptr m_device=nullptr; + std::shared_ptr m_device = nullptr; std::shared_ptr m_surface; std::shared_ptr m_swapchain; vk::surface_params m_surface_properties; From 9f6bfd6367b9fa6d10f0e1a48bc63c18424dc9ed Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 3 Jun 2026 21:42:15 -0700 Subject: [PATCH 037/106] refactor: fixing window center_window API using glfwGetWindowSize --- atlas/core/application.cppm | 8 +++----- atlas/drivers/vulkan/window.cppm | 31 ++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index b1307fa2..a9fa94c7 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -155,6 +155,8 @@ export namespace atlas { std::println("images.size() = {}", images.size()); + m_window->center_window(); + // m_bus->trigger(this, // &application::on_scene_transition); } @@ -300,11 +302,7 @@ export namespace atlas { }; vk::rendering_begin_parameters begin_params = { - .render_area = { { 0, 0 }, - { - m_window->extent().width, - m_window->extent().height, - }, }, + .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, .layer_count = 1, .color_attachments = std::span( &color_render_attachment, 1), diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 7c7485d8..3445f14a 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -39,10 +39,8 @@ export namespace atlas { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - m_params = { - .width = p_params.width, - .height = p_params.height, - }; + + std::println("Creating window with width: {} and height: {}", p_params.width, p_params.height); m_window = glfwCreateWindow(static_cast(p_params.width), static_cast(p_params.height), @@ -55,9 +53,18 @@ export namespace atlas { m_surface = std::make_shared( p_context->instance_handle(), m_window); + int framebuffer_width=0; + int framebuffer_height=0; + glfwGetFramebufferSize(m_window, &framebuffer_width, &framebuffer_height); + + // Weird issue where the frame buffer size is different then the window size. + // Causing majority of the portion of the window to render pink pixels, indicating an error. + m_params.width = static_cast(framebuffer_width); + m_params.height = static_cast(framebuffer_height); + vk::swapchain_params swapchain_params = { - .width = static_cast(m_params.width), - .height = static_cast(m_params.height), + .width = static_cast(p_params.width), + .height = static_cast(p_params.height), .present_index = 0, }; @@ -69,9 +76,8 @@ export namespace atlas { *m_surface, swapchain_params, m_surface_properties); - - center_window(); + center_window(); vk::queue_params present_params = { .family = 0, .index = 0, @@ -119,12 +125,15 @@ export namespace atlas { } void center_window() { + int window_width=0; + int window_height=0; + glfwGetWindowSize(m_window, &window_width, &window_height); GLFWmonitor* monitor = glfwGetPrimaryMonitor(); const GLFWvidmode* mode = glfwGetVideoMode(monitor); - uint32_t width = (mode->width / 2) - (m_params.width / 2); - uint32_t height = (mode->height / 2) - (m_params.height / 2); + int width = (mode->width / 2) - (window_width / 2); + int height = (mode->height / 2) - (window_height / 2); glfwSetWindowPos( - m_window, static_cast(width), static_cast(height)); + m_window, width, height); } void submit(std::span p_commands) { From 30843e19b70a3512f0ea3dee21ff20dee3d69310 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 21:48:13 -0700 Subject: [PATCH 038/106] refactor: cleaned up window.cppm removing unecessary debugging print statements --- atlas/drivers/vulkan/window.cppm | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 3445f14a..9090b05b 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -2,8 +2,8 @@ module; #include #include -#include #include +#include #define GLFW_INCLUDE_VULKAN #if _WIN32 @@ -17,9 +17,6 @@ module; #include #endif -#include -#include - export module atlas.drivers.vulkan:window; import atlas.common; @@ -40,8 +37,6 @@ export namespace atlas { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - std::println("Creating window with width: {} and height: {}", p_params.width, p_params.height); - m_window = glfwCreateWindow(static_cast(p_params.width), static_cast(p_params.height), p_params.name.c_str(), From 6ddf0831a04a2af12799dc5a22b1715f097a7180 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 22:05:36 -0700 Subject: [PATCH 039/106] refactor: removed two old files --- .../drivers/vulkan/imgui_context-backup.cppm | 476 ------------------ .../drivers/vulkan/render_context-backup.cppm | 459 ----------------- 2 files changed, 935 deletions(-) delete mode 100644 atlas/drivers/vulkan/imgui_context-backup.cppm delete mode 100644 atlas/drivers/vulkan/render_context-backup.cppm diff --git a/atlas/drivers/vulkan/imgui_context-backup.cppm b/atlas/drivers/vulkan/imgui_context-backup.cppm deleted file mode 100644 index 64ff051a..00000000 --- a/atlas/drivers/vulkan/imgui_context-backup.cppm +++ /dev/null @@ -1,476 +0,0 @@ -module; - -#include -#include -#include -#include -#include -#include -#include -#include - -export module atlas.drivers.vulkan.imgui_context; - -import atlas.common; -import vk; - -import atlas.core.utilities; - -namespace atlas::vulkan { - static void im_gui_layout_color_modification() { - auto& colors = ImGui::GetStyle().Colors; // @note Colors is ImVec4 - - colors[ImGuiCol_WindowBg] = ImVec4{ 0.1f, 0.105f, 0.11f, 1.0f }; - - // Headers - colors[ImGuiCol_Header] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_HeaderHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_HeaderActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Buttons - colors[ImGuiCol_Button] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_ButtonHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_ButtonActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Frame BG - colors[ImGuiCol_FrameBg] = ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - colors[ImGuiCol_FrameBgHovered] = ImVec4{ 0.3f, 0.305f, 0.31f, 1.0f }; - colors[ImGuiCol_FrameBgActive] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - - // Tabs - colors[ImGuiCol_Tab] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - colors[ImGuiCol_TabHovered] = ImVec4{ 0.38f, 0.3805f, 0.381f, 1.0f }; - colors[ImGuiCol_TabActive] = ImVec4{ 0.28f, 0.2805f, 0.281f, 1.0f }; - colors[ImGuiCol_TabUnfocused] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; - colors[ImGuiCol_TabUnfocusedActive] = - ImVec4{ 0.2f, 0.205f, 0.21f, 1.0f }; - - // Titles - colors[ImGuiCol_TitleBg] = ImVec4{ 0.15f, 0.1505f, 0.151f, 1.0f }; - colors[ImGuiCol_TitleBgActive] = ImVec4{ 0.15f, 0.1505f, 0.15f, 1.0f }; - colors[ImGuiCol_TitleBgCollapsed] = - ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; - } - - void transition_image_layout(VkDevice p_device, - vk::sample_image& p_image, - VkFormat p_format, - VkImageLayout p_old, - VkImageLayout p_new) { - vk::command_params copy_command_params = { - .levels = vk::command_levels::primary, - .queue_index = 0, - .flags = vk::command_pool_flags::reset, - }; - vk::command_buffer temp_command_buffer = - vk::command_buffer(p_device, copy_command_params); - - temp_command_buffer.begin(vk::command_usage::one_time_submit); - - p_image.memory_barrier(temp_command_buffer, p_format, p_old, p_new); - - temp_command_buffer.end(); - - VkCommandBuffer handle = temp_command_buffer; - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = 1, - .pCommandBuffers = &handle, - }; - - uint32_t queue_family_index = 0; - uint32_t queue_index = 0; - VkQueue temp_graphics_queue; - vkGetDeviceQueue( - p_device, queue_family_index, queue_index, &temp_graphics_queue); - - vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); - vkQueueWaitIdle(temp_graphics_queue); - - temp_command_buffer.destruct(); - } - - export ImTextureID g_viewport_image_id = nullptr; - export class imgui_context { - public: - imgui_context() = default; - - imgui_context(const VkInstance& p_instance, - const swapchain& p_swapchain_ctx, - GLFWwindow* p_window_ctx) { - m_instance = p_instance; - console_log_info("imgui_context"); - m_physical = instance_context::physical_driver(); - m_driver = instance_context::logical_device(); - // vk::device device_temp = instance_context::physical_driver(); - - m_current_swapchain_handler = p_swapchain_ctx; - m_extent = { .width = p_swapchain_ctx.settings().width, - .height = p_swapchain_ctx.settings().height }; - - // Setting up imgui - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - - io.ConfigFlags |= - ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - // io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // - // Enable Gamepad Controls - io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking - io.ConfigFlags |= - ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / - // Platform Windows - - // io.ConfigViewportsNoAutoMerge = true; - // io.ConfigViewportsNoAutoMerge = true; - // io.ConfigViewportsNoTaskBarIcon = true; - - // Setup Dear ImGui style - // ImGui::StyleColorsDark(); - // ImGui::StyleColorsClassic(); - im_gui_layout_color_modification(); - - ImGuiStyle& style = ImGui::GetStyle(); - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - style.WindowRounding = 0.0f; - style.Colors[ImGuiCol_WindowBg].w = 1.0f; - } - - m_viewport_command_buffers.resize(p_swapchain_ctx.image_size()); - - for (size_t i = 0; i < m_viewport_command_buffers.size(); i++) { - ::vk::command_params settings = { - .levels = ::vk::command_levels::primary, - // .queue_index = - // enumerate_swapchain_settings.present_index, - .queue_index = 0, - .flags = ::vk::command_pool_flags::reset, - }; - m_viewport_command_buffers[i] = - ::vk::command_buffer(m_driver, settings); - } - - // ::vk::descriptor_res - // m_imgui_descriptor = ::vk::descriptor_resource(m_driver, {}); - // 1: create descriptor pool for IMGUI - // the size of the pool is very oversize, but it's copied from - // imgui demo itself. - std::array pool_sizes = { - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, - 100 }, - VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } - }; - - VkDescriptorPoolCreateInfo desc_pool_create_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .pNext = nullptr, - .flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, - .maxSets = static_cast(1000 * pool_sizes.size()), - // .poolSizeCount = (uint32_t)std::size(pool_sizes), - .poolSizeCount = static_cast(pool_sizes.size()), - .pPoolSizes = pool_sizes.data() - }; - - // VkDescriptorPool imgui_pool; - vk::vk_check( - vkCreateDescriptorPool( - m_driver, &desc_pool_create_info, nullptr, &m_desc_pool), - "vkCreateDescriptorPool"); - - create(p_window_ctx, - p_swapchain_ctx.image_size(), - p_swapchain_ctx.swapchain_renderpass()); - - vk::image_params config_image = { - .extent = { .width = p_swapchain_ctx.settings().width, - .height = p_swapchain_ctx.settings().height }, - .format = VK_FORMAT_B8G8R8A8_UNORM, - .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), - // .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::color_attachment_bit | - vk::image_usage::transfer_dst_bit | - vk::image_usage::sampled_bit, - // .usage = vk::image_usage::color_attachment_bit | - // vk::image_usage::transfer_dst_bit, - // .phsyical_memory_properties = memory_properties, - .address_mode_u = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, - }; - m_viewport_image = vk::sample_image(m_driver, config_image); - - // transition image layout uses image memory barrier - transition_image_layout(m_driver, - m_viewport_image, - VK_FORMAT_B8G8R8A8_UNORM, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Viewport-specific render pass: color attachment ends in - // SHADER_READ_ONLY_OPTIMAL so the offscreen texture can be sampled - // by ImGui. (Swapchain pass uses PRESENT_SRC.) - VkFormat depth_format = m_driver.depth_format(); - std::array<::vk::attachment, 2> viewport_attachments = { - ::vk::attachment{ - .format = VK_FORMAT_B8G8R8A8_UNORM, - .layout = ::vk::image_layout::color_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::store, - .stencil_load = ::vk::attachment_load::clear, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::shader_read_only_optimal, - }, - ::vk::attachment{ - .format = depth_format, - .layout = ::vk::image_layout::depth_stencil_optimal, - .samples = ::vk::sample_bit::count_1, - .load = ::vk::attachment_load::clear, - .store = ::vk::attachment_store::dont_care, - .stencil_load = ::vk::attachment_load::dont_care, - .stencil_store = ::vk::attachment_store::dont_care, - .initial_layout = ::vk::image_layout::undefined, - .final_layout = ::vk::image_layout::depth_stencil_optimal, - }, - }; - m_viewport_renderpass = - ::vk::renderpass(m_driver, viewport_attachments); - - vk::image_params config_depth_image = { - .extent = { .width = p_swapchain_ctx.settings().width, - .height = p_swapchain_ctx.settings().height }, - .format = m_driver.depth_format(), - .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), - // .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::depth_bit, - // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .usage = vk::image_usage::depth_stencil_bit, - // .phsyical_memory_properties = memory_properties, - }; - - m_depth_viewport_image = - vk::sample_image(m_driver, config_depth_image); - - for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { - std::array image_view_attachments = { - m_viewport_image.image_view(), - m_depth_viewport_image.image_view() - }; - - vk::framebuffer_params framebuffer_info = { - .renderpass = m_viewport_renderpass, - .views = image_view_attachments, - .extent = { p_swapchain_ctx.settings().width, - p_swapchain_ctx.settings().height } - }; - m_viewport_framebuffers[i] = - vk::framebuffer(m_driver, framebuffer_info); - } - - g_viewport_image_id = - static_cast(ImGui_ImplVulkan_AddTexture( - m_viewport_image.sampler(), - m_viewport_image.image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - } - - void create(GLFWwindow* p_window_handler, - const uint32_t& p_image_size, - const VkRenderPass& p_current_renderpass) { - ImGui_ImplGlfw_InitForVulkan(p_window_handler, true); - ImGui_ImplVulkan_InitInfo init_info = {}; - init_info.Instance = m_instance; - init_info.PhysicalDevice = m_physical; - init_info.Device = m_driver; - init_info.Queue = m_driver.graphics_queue(); - init_info.RenderPass = p_current_renderpass; - init_info.PipelineCache = nullptr; - init_info.DescriptorPool = m_desc_pool; - init_info.MinImageCount = 2; - init_info.ImageCount = p_image_size; - init_info.UseDynamicRendering = false; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; - ImGui_ImplVulkan_Init(&init_info); - } - - void begin(const VkCommandBuffer& p_current, - const uint32_t& p_frame_index) { - ImGui_ImplVulkan_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - m_current_frame_index = p_frame_index; - m_current = p_current; - } - - void invalidate(const swapchain& p_swapchain) { - // Wait for device to finish all operations before recreating - // resources - vkDeviceWaitIdle(m_driver); - - for (auto& fb : m_viewport_framebuffers) { - fb.destruct(); - } - - // Remove old texture from ImGui if needed - // ImTextureID in ImGui Vulkan backend is VkDescriptorSet cast to - // void* - if (g_viewport_image_id != nullptr) { - VkDescriptorSet old_descriptor_set = - reinterpret_cast(g_viewport_image_id); - ImGui_ImplVulkan_RemoveTexture(old_descriptor_set); - g_viewport_image_id = nullptr; - } - - // Destroy old images - m_viewport_image.destruct(); - m_depth_viewport_image.destruct(); - - // Recreate viewport images with new swapchain size - // VkPhysicalDeviceMemoryProperties memory_properties = - // instance_context::physical_driver().memory_properties(); - - vk::image_params config_image = { - .extent = { .width = p_swapchain.settings().width, - .height = p_swapchain.settings().height }, - .format = VK_FORMAT_B8G8R8A8_UNORM, - .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), - // .property = m_physical.memory_properties(vk::memory_property::device_local_bit), - .aspect = vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::color_attachment_bit | - vk::image_usage::transfer_dst_bit | - vk::image_usage::sampled_bit, - // .phsyical_memory_properties = memory_properties, - .address_mode_u = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, - .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, - }; - m_viewport_image = vk::sample_image(m_driver, config_image); - - // Transition to shader read-only layout - transition_image_layout(m_driver, - m_viewport_image, - VK_FORMAT_B8G8R8A8_UNORM, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Recreate depth image - vk::image_params config_depth_image = { - .extent = { .width = p_swapchain.settings().width, - .height = p_swapchain.settings().height }, - .format = m_driver.depth_format(), - .memory_mask = m_physical.memory_properties(vk::memory_property::device_local_bit), - .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::depth_bit, - // .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - .usage = vk::image_usage::depth_stencil_bit, - // .phsyical_memory_properties = memory_properties, - }; - m_depth_viewport_image = - vk::sample_image(m_driver, config_depth_image); - - // Recreate framebuffers with new images - for (uint32_t i = 0; i < m_viewport_framebuffers.size(); i++) { - std::array image_view_attachments = { - m_viewport_image.image_view(), - m_depth_viewport_image.image_view() - }; - - vk::framebuffer_params framebuffer_info = { - .renderpass = m_viewport_renderpass, - .views = image_view_attachments, - .extent = { p_swapchain.settings().width, - p_swapchain.settings().height } - }; - m_viewport_framebuffers[i] = - vk::framebuffer(m_driver, framebuffer_info); - } - - // Update ImGui texture ID with new image - g_viewport_image_id = (ImTextureID)ImGui_ImplVulkan_AddTexture( - m_viewport_image.sampler(), - m_viewport_image.image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - // Update extent - m_extent = { .width = p_swapchain.settings().width, - .height = p_swapchain.settings().height }; - } - - void end() { - ImGui::Render(); - - ImDrawData* draw_data = ImGui::GetDrawData(); - ImGui_ImplVulkan_RenderDrawData(draw_data, m_current); - - ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - ImGui::UpdatePlatformWindows(); - ImGui::RenderPlatformWindowsDefault(); - } - } - - [[nodiscard]] ::vk::command_buffer imgui_active_command() const { - return m_viewport_command_buffers[m_current_frame_index]; - } - - vk::framebuffer active_framebuffer(uint32_t p_frame) const { - return m_viewport_framebuffers[p_frame]; - } - - [[nodiscard]] vk::renderpass viewport_renderpass() const { - return m_viewport_renderpass; - } - - void destroy() { - ImGui_ImplVulkan_Shutdown(); - vkDestroyDescriptorPool(m_driver, m_desc_pool, nullptr); - - for (auto& command_buffer : m_viewport_command_buffers) { - command_buffer.destruct(); - } - - for (auto& fb : m_viewport_framebuffers) { - fb.destruct(); - } - - m_viewport_renderpass.destruct(); - m_viewport_image.destruct(); - m_depth_viewport_image.destruct(); - - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - } - - private: - VkInstance m_instance = nullptr; - physical_device m_physical = nullptr; - device m_driver{}; - uint32_t m_current_frame_index = 0; - VkSwapchainKHR m_current_swapchain_handler = nullptr; - VkDescriptorPool m_desc_pool = nullptr; - VkCommandBuffer m_current = nullptr; - std::vector<::vk::command_buffer> m_viewport_command_buffers; - std::array m_viewport_framebuffers; - ::vk::renderpass m_viewport_renderpass; - vk::sample_image m_viewport_image; - vk::sample_image m_depth_viewport_image; - window_params m_extent; - }; -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/render_context-backup.cppm b/atlas/drivers/vulkan/render_context-backup.cppm deleted file mode 100644 index 6a837a81..00000000 --- a/atlas/drivers/vulkan/render_context-backup.cppm +++ /dev/null @@ -1,459 +0,0 @@ -module; - -#include -#include -#include -#include -#include -#include - -#include -#include -#define GLM_FORCE_RADIANS -#include -#include -#define GLM_ENABLE_EXPERIMENTAL -#include -export module atlas.drivers.vulkan:render_context; -import atlas.core.scene; - -import atlas.drivers.importer; -import atlas.core.scene; -import atlas.core.scene.components; -import atlas.drivers.vulkan.stb_image; - -import :graphics_context; -import vk; - -export namespace atlas { - - struct gpu_mesh_data { - vk::vertex_buffer vertex; - vk::index_buffer index; - uint32_t index_count=0; - uint32_t instance=1; - uint32_t first_index=0; - uint32_t vertex_offset=0; - uint32_t first_instance=0; - bool has_indices_buffer=false; - uint32_t vertices_size = 0; - uint32_t indices_size=0; - }; - - struct push_constant_data { - uint64_t diffuse_idx=0; - uint64_t specular_idx=0; - uint64_t buffer_address=0; - }; - - struct global_uniform { - glm::mat4 model=glm::mat4(1.f); - glm::mat4 view=glm::mat4(1.f); - glm::mat4 proj=glm::mat4(1.f); - }; - - - struct gpu_material { - uint64_t diffuse_idx=0; - // uint64_t specular_idx=0; - }; - - /** - * - * @brief slot is the index into the texture array to retrieve this specific texture data - * - * vk::texture is the texture data to configure the GPU-visible image resource - */ - struct gpu_image { - vk::texture texture_data; - }; - - /** - * @brief Core render context to schedule images and barriers for coordinating rendering operations - * - * Manages multiple render contexts - */ - class render_context { - public: - render_context() = default; - render_context(/*NOLINT*/std::shared_ptr p_context, VkFormat p_color_format, VkFormat p_depth_format) { - m_physical = p_context->physical_device(); - m_device = p_context->logical_device(); - - // Vertex Attributes Parameters - std::array attribute_entries = { - vk::vertex_attribute_entry{ - .location = 0, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position), - }, - vk::vertex_attribute_entry{ - .location = 1, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color), - }, - vk::vertex_attribute_entry{ - .location = 2, - .format = vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv), - }, - vk::vertex_attribute_entry{ - .location = 3, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals), - } - }; - std::array attributes = { - vk::vertex_attribute{ - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = vk::input_rate::vertex, - }, - }; - std::array shader_sources = { - vk::shader_source{ - .filename = "builtin.shaders/pbr.vert.spv", - .stage = vk::shader_stage::vertex, - }, - vk::shader_source{ - .filename = "builtin.shaders/pbr.frag.spv", - .stage = vk::shader_stage::fragment, - }, - }; - - // To render triangle, we do not need to set any vertex attributes - vk::shader_resource_info shader_info = { - .sources = shader_sources, - }; - m_shader_resource = vk::shader_resource(*m_device, shader_info); - m_shader_resource.vertex_attributes(attributes); - - - // Configuring Descriptor Set 0 -- specify to vk::pipeline - // Descriptor Set 0 - uint32_t max_descriptor = 3; - std::array entries_set1 = { - vk::descriptor_entry{ - // layout (set = 0, binding = 1) uniform sampler2D textures[]; - .type = vk::descriptor_type::combined_image_sampler, - .binding_point = { - .binding = 1, - .stage = vk::shader_stage::fragment, - }, - .descriptor_count = max_descriptor, - .flags = vk::descriptor_bind_flags::partially_bound_bit | - vk::descriptor_bind_flags::variable_descriptor_count_bit | - vk::descriptor_bind_flags::update_after_bind, - } - }; - - // layout(set = 0, ...) - vk::descriptor_layout set0_layout = { - .slot = 0, - .max_sets = max_descriptor, - .entries = entries_set1, // descriptor layout entries description - .descriptor_counts = std::span(&max_descriptor, 1), - }; - m_set0_resource = vk::descriptor_resource(*m_device, set0_layout, vk::descriptor_layout_flags::update_after_bind_pool); - - std::array color_blend_attachments = { - vk::color_blend_attachment_state{}, - }; - - std::array dynamic_states = { - vk::dynamic_state::viewport, vk::dynamic_state::scissor, - }; - - m_format = static_cast(p_color_format); - uint32_t vertex_mask = static_cast(vk::shader_stage::vertex); - uint32_t fragment_mask = static_cast(vk::shader_stage::fragment); - uint32_t stage_mask = vertex_mask | fragment_mask; - m_stage = static_cast(stage_mask); - vk::push_constant_range range = { - .stage = m_stage, - .offset = 0, - .range = sizeof(push_constant_data), - }; - - VkDescriptorSetLayout descriptor0_layout = m_set0_resource.layout(); - vk::pipeline_params pipeline_configuration = { - .use_render_pipeline = true, - .color_attachment_formats = std::span(&m_format, 1), - .depth_format = static_cast(p_depth_format), - .stencil_format = static_cast(p_depth_format), - .renderpass = nullptr, - .shader_modules = m_shader_resource.handles(), - .vertex_attributes = m_shader_resource.vertex_attributes(), - .vertex_bind_attributes = m_shader_resource.vertex_bind_attributes(), - .descriptor_layouts = std::span(&descriptor0_layout, 1), - .color_blend = { - .attachments = color_blend_attachments, - }, - .depth_stencil_enabled = true, - .dynamic_states = dynamic_states, - .push_constants = std::span(&range, 1), - }; - m_main_pipeline = vk::pipeline(*m_device, pipeline_configuration); - - vk::buffer_parameters uniform_params = { - .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::uniform_buffer_bit | vk::buffer_usage::shader_device_address_bit, - .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, - }; - m_scene_uniforms = vk::dyn::buffer(*m_device, sizeof(global_uniform), uniform_params); - - vk::image_extent extent = { - .width = 1, - .height = 1, - }; - std::array white_color = {0xff, 0xff, 0xff, 0xff}; - // At index = 0 will default to white texture - m_storage_images_arrays.emplace_back(*m_device, extent, white_color, m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)); - - } - - void prebake() { - flecs::query<> all_meshes = m_world->query_builder().build(); - - all_meshes.each([this](flecs::entity p_entity){ - const mesh_source* src = p_entity.get(); - - vk::buffer_parameters vertex_params = { - .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::transfer_dst_bit | vk::buffer_usage::vertex_buffer_bit, - }; - - vk::buffer_parameters index_params = { - .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::index_buffer_bit, - }; - - // import .obj 3d model and setting up vertices/indices - obj_importer importer(src->model_path); - gpu_mesh_data gpu_mesh{}; - gpu_mesh.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); - gpu_mesh.index = vk::index_buffer(*m_device, importer.indices(), index_params); - gpu_mesh.has_indices_buffer = (importer.indices().size() >= 0) ? true : false; - gpu_mesh.vertices_size = importer.vertices().size(); - gpu_mesh.indices_size = importer.indices().size(); - - m_meshes.emplace(p_entity.id(), gpu_mesh); - - std::println("Entity ID: {}", p_entity.id()); - - // const material_metadata* mat = p_entity.get(); - // loading textures - vk::texture_params config_texture = { - .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - }; - - // Loading texture and setting up VkSampler and VkImageView - // stb_image img = stb_image("assets/models/viking_room.png", config_texture); - stb_image diffuse_img = stb_image(src->diffuse, config_texture); - gpu_material material_index = {}; - if(!src->diffuse.empty()) { - std::println("Loading diffuse: {}", src->diffuse); - material_index.diffuse_idx = m_texture_slot_index++; - // vk::texture diffuse(*m_device, &diffuse_img, config_texture); - m_storage_images_arrays.emplace_back(*m_device, &diffuse_img, config_texture); - } - - // if(!src->specular.empty()) { - // std::println("Loading specular: {}", src->specular); - // material_index.specular_idx = m_texture_slot_index++; - // stb_image specular_img = stb_image(src->specular, config_texture); - // vk::texture specular(*m_device, &specular_img, config_texture); - // // m_storage_images_arrays.emplace_back(*m_device, &specular_img, config_texture); - // m_storage_images_arrays.emplace_back(specular); - // } - - - m_mesh_materials.emplace(p_entity.id(), material_index); - }); - - // Preparing the texture data before we update descriptor set 0 - // Storing all of our texture via one contiguous array of textures - // for(const auto&[id, image] : m_gpu_storage_images) { - for(auto image : m_storage_images_arrays) { - vk::write_image write_gpu_image = { - .sampler = image.image().sampler(), - .view = image.image().image_view(), - .layout = vk::image_layout::shader_read_only_optimal, - }; - m_gpu_images.push_back(write_gpu_image); - } - - std::array set0_samples = { - vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = m_gpu_images, - } - }; - - m_set0_resource.update({}, set0_samples); - - } - - void begin(vk::rendering_begin_parameters p_begin_params, const auto& p_extent, const glm::mat4& p_proj, const glm::mat4& p_view) { - m_proj_view = p_proj * p_view; - vk::viewport_params viewport = { - .x = 0.0f, - .y = 0.0f, - .width = static_cast(p_extent.width), - .height = static_cast(p_extent.height), - .min_depth = 0.0f, - .max_depth = 1.0f, - }; - m_current_command->set_viewport(0, 1, std::span(&viewport, 1)); - - vk::scissor_params scissor = { - .offset = { 0, 0 }, - .extent = p_extent, - }; - m_current_command->set_scissor(0, 1, std::span(&scissor, 1)); - - m_current_command->begin_rendering(p_begin_params); - - m_main_pipeline.bind(*m_current_command); - - /* - TODO (TEMP): Consider having transform to be changed as an unbounded array on the shader - struct shader_transform_struct { - // Where we will have an unbounded array of 3D object - // transforms that can already be accessible when being modified - mat4 models[]; - } object_transform; - - - void main() { - gl_Position = ubo.view * ubo.proj * object_transform.models[gl_VertexIndex] * vec4(inPosition, 1.0); - } - - */ - flecs::entity viking_room = m_world->entity("Viking Room"); - const transform* t = viking_room.get(); - - // Setting up viking room - glm::mat4 model = glm::mat4(1.f); - model = glm::translate(model, t->position); - model = glm::scale(model, t->scale); - - global_uniform ubo = { - .model = model, - .view = p_view, - .proj = p_proj, - }; - ubo.proj[1][1] *= -1; - - m_scene_uniforms.transfer(std::span(&ubo, 1)); - - // Retrieving the buffer address that can be looked up from the glsl shader - const uint64_t ubo_address = m_scene_uniforms.get_device_address(); - - // push constant retrieve the buffer that is transferring data to - // Then we set the texture index. - - // flecs::query<> all_meshes = m_world->query_builder().build(); - - // all_meshes.each([this, ubo_address](flecs::entity p_entity){ - // if(!p_entity.has()) { - // return; - // } - // push_constant_data push = { - // .diffuse_idx = m_mesh_materials[p_entity.id()].diffuse_idx, - // // .specular_idx = m_mesh_materials[p_entity.id()].specular_idx, - // .buffer_address = ubo_address, - // }; - // m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); - // }); - push_constant_data push = { - .diffuse_idx = 0, - .buffer_address = ubo_address, - }; - m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); - - const VkDescriptorSet set0 = m_set0_resource; - m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); - - - for(auto[id, mesh] : m_meshes) { - const VkBuffer vertex = mesh.vertex; - uint64_t offset = 0; - m_current_command->bind_vertex_buffers(std::span(&vertex, 1), std::span(&offset, 1)); - if (mesh.has_indices_buffer) { - m_current_command->bind_index_buffers32(mesh.index); - } - } - - - } - - void end() { - - // TODO: Use Vulkan Indirect Command Draw call for this to reduce draw calls - for(auto[id, mesh] : m_meshes) { - if (mesh.has_indices_buffer) { - vkCmdDrawIndexed(*m_current_command, mesh.indices_size, 1, 0, 0, 0); - } - else { - vkCmdDraw(*m_current_command, mesh.vertices_size, 1, 0, 0); - } - } - m_current_command->end_rendering(); - } - - void set_command(vk::command_buffer& p_command) { - m_current_command = &p_command; - } - - void current_scene(flecs::world& p_world) { - m_world = &p_world; - } - - void destruct() { - m_scene_uniforms.reset(); - // for(auto&[id, image] : m_gpu_storage_images) { - // image.texture_data.destruct(); - // } - - for(auto&[id, mesh] : m_meshes) { - mesh.vertex.destruct(); - mesh.index.destruct(); - } - - m_set0_resource.destruct(); - m_shader_resource.destruct(); - m_main_pipeline.destruct(); - } - - private: - uint32_t m_format; - glm::mat4 m_proj_view=glm::mat4(1.f); // Combination of the projection * view matrix result - std::optional m_physical; - std::shared_ptr m_device; - vk::command_buffer* m_current_command=nullptr; - vk::shader_resource m_shader_resource; - vk::pipeline m_main_pipeline; - std::vector m_indirect_commands; - vk::descriptor_resource m_set0_resource; - - vk::dyn::buffer m_scene_uniforms; - - std::unordered_map m_meshes; - - // Index to lookup for specific texture (image) resource - // Index 0 default to a white texture if no textures found - uint32_t m_texture_slot_index = 1; - - // GPU sampled images - // - // std::unordered_map m_gpu_storage_images; - std::unordered_map m_mesh_materials; - std::vector m_storage_images_arrays; - std::vector m_gpu_images; - vk::shader_stage m_stage; - - flecs::world* m_world=nullptr; - }; -}; \ No newline at end of file From 0d69b3c5cdb88f5d0fa536d6f3d1542a462b074c Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 22:21:07 -0700 Subject: [PATCH 040/106] refactor: imgui_context initializes with no errors --- atlas/core/application.cppm | 17 +++++---- atlas/drivers/vulkan/imgui_context.cppm | 49 +++++++++++++++++++++---- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index a9fa94c7..6f733071 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -79,12 +79,6 @@ export namespace atlas { // m_bus->create_immediate_listener(); // m_bus->create_immediate_listener(); - // m_imgui_context = std::make_shared(p_context, - // m_window->glfw_window(), - // m_window->swapchain_handle(), - // m_window->request_images().size(), - // m_window->present_queue()); - // Requesting depth format std::array format_support = { vk::format::d32_sfloat, @@ -97,6 +91,14 @@ export namespace atlas { // supported on current hardware device. m_depth_format = m_physical->request_depth_format(format_support); + m_imgui_context = std::make_shared(p_context, + m_window->glfw_window(), + m_window->swapchain_handle(), + m_window->request_images().size(), + m_window->present_queue(), + m_color_format, + m_depth_format); + // Initializing command buffers std::span images = m_window->request_images(); @@ -343,6 +345,7 @@ export namespace atlas { // } void post_destroy() { + m_imgui_context->destruct(); m_render_context.destruct(); for (auto& command : m_command_buffers) { @@ -379,7 +382,7 @@ export namespace atlas { std::shared_ptr m_world; - // std::shared_ptr m_imgui_context; + std::shared_ptr m_imgui_context; std::shared_ptr m_current_scene = nullptr; // vulkan-cpp specific handles diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 13c63ad9..7aefce7b 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -12,6 +12,7 @@ module; #include #include #include +#include export module atlas.drivers.vulkan:imgui_context; @@ -58,14 +59,34 @@ namespace atlas { ImVec4{ 0.1f, 0.150f, 0.951f, 1.0f }; } + VkPipelineRenderingCreateInfo pipeline_rendering_info( + std::span p_color_attachment_formats, + const uint32_t p_depth_format, + const uint32_t p_stencil_format) { + VkPipelineRenderingCreateInfo rendering_ci = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, + .pNext = nullptr, + .colorAttachmentCount = + static_cast(p_color_attachment_formats.size()), + .pColorAttachmentFormats = reinterpret_cast( + p_color_attachment_formats.data()), + .depthAttachmentFormat = static_cast(p_depth_format), + .stencilAttachmentFormat = static_cast(p_stencil_format), + }; + + return rendering_ci; + } + export class imgui_context { public: imgui_context() = delete; - imgui_context(std::shared_ptr p_context, + imgui_context(/*NOLINT*/ std::shared_ptr p_context, GLFWwindow* p_window, - std::shared_ptr p_swapchain, + /*NOLINT*/ std::shared_ptr p_swapchain, uint32_t p_image_count, - const vk::device_present_queue& p_queue) { + const vk::device_present_queue& p_queue, + /*NOLINT*/ const VkFormat& p_color_format, + /*NOLINT*/ const VkFormat& p_depth_format) { m_instance = p_context->instance_handle(); m_device = p_context->logical_device(); m_physical = p_context->physical_device(); @@ -128,15 +149,19 @@ namespace atlas { // VkDescriptorPool imgui_pool; vk::vk_check( vkCreateDescriptorPool( - *m_device, &desc_pool_create_info, nullptr, &m_descriptor_pool), "vkCreateDescriptorPool"); + *m_device, &desc_pool_create_info, nullptr, &m_descriptor_pool), + "vkCreateDescriptorPool"); - construct(p_window, p_swapchain, p_image_count, p_queue); + construct(p_window, /*NOLINT*/ p_swapchain, p_image_count, p_queue, p_color_format, p_depth_format); } void construct(GLFWwindow* p_window, - std::shared_ptr p_swapchain, + /*NOLINT*/ std::shared_ptr p_swapchain, uint32_t p_image_count, - const vk::device_present_queue& p_queue) { + const vk::device_present_queue& p_queue, + /*NOLINT*/ const VkFormat& p_color_format, + /*NOLINT*/ const VkFormat& p_depth_format) { + ImGui_ImplGlfw_InitForVulkan(p_window, true); ImGui_ImplVulkan_InitInfo init_info = {}; init_info.Instance = m_instance.value(); @@ -150,6 +175,13 @@ namespace atlas { init_info.ImageCount = p_image_count; init_info.UseDynamicRendering = true; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + + const uint32_t color_format = static_cast(p_color_format); + const uint32_t depth_format = static_cast(p_depth_format); + init_info.PipelineRenderingCreateInfo = pipeline_rendering_info( + std::span(&color_format, 1), + depth_format, + depth_format); ImGui_ImplVulkan_Init(&init_info); } @@ -171,10 +203,11 @@ namespace atlas { } private: - VkDescriptorPool m_descriptor_pool=nullptr; + VkDescriptorPool m_descriptor_pool = nullptr; vk::command_buffer* m_current_command; std::optional m_instance; std::optional m_physical; std::shared_ptr m_device = nullptr; + vk::surface_params m_surface_properties; }; }; \ No newline at end of file From d3a27d07233eab09354238730c3c13c90dfba6b4 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 3 Jun 2026 23:05:37 -0700 Subject: [PATCH 041/106] refactor: additional fixes and some code cleanup to imgui_context --- atlas/core/application.cppm | 12 ++++++++++-- atlas/drivers/vulkan/imgui_context.cppm | 20 +++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 6f733071..d5a0582b 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -69,7 +69,7 @@ export namespace atlas { // m_context->instance_handle(), params); m_window = std::make_shared(p_context, params); - m_aspect_ratio = static_cast(params.width / params.height); + m_aspect_ratio = static_cast(params.width) / static_cast(params.height); event::set_window_size(m_window->glfw_window()); m_bus->create_listener(); @@ -267,6 +267,8 @@ export namespace atlas { m_render_context.set_command(current); + m_imgui_context->set_current_command(current); + m_images[m_next_image_frame_idx].memory_barrier( current, m_window->surface_properties().format.format, @@ -314,9 +316,15 @@ export namespace atlas { m_render_context.begin( begin_params, m_window->extent(), m_projection, m_view); - + m_render_context.end(); + // Performing UI Context Rendering + + m_imgui_context->begin(); + invoke_ui_update(m_current_scene.get()); + m_imgui_context->end(); + m_images[m_next_image_frame_idx].memory_barrier( current, m_window->surface_properties().format.format, diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 7aefce7b..6b1e5705 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -189,10 +189,24 @@ namespace atlas { m_current_command = &p_command; } - // uint32_t = p_frame_ifx - void begin(uint32_t) {} + void begin() { + ImGui_ImplVulkan_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + } + + void end() { + ImGui::Render(); + + ImDrawData* draw_data = ImGui::GetDrawData(); + ImGui_ImplVulkan_RenderDrawData(draw_data, *m_current_command); - void end() {} + ImGuiIO& io = ImGui::GetIO(); + if(io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + } + } void destruct() { ImGui_ImplVulkan_Shutdown(); From 1b16b8ec7ed8b8a4c31a92fe5ec0fddf9eb23ef6 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 4 Jun 2026 00:28:50 -0700 Subject: [PATCH 042/106] refactor: fix the render_context to handle push constants per mesh rather then having this be done at beginning of the frame but during rendering frame --- atlas/drivers/vulkan/render_context.cppm | 21 ++++----- editor/level_scene.cppm | 56 ++++++++++++------------ 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 05a6d84b..99639c55 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -357,9 +357,15 @@ export namespace atlas { }); m_object_model_uniforms.transfer(std::span(m_model_matrices.data(), m_model_matrices.size())); - - // Retrieving the buffer address that can be looked up from the glsl shader + + const VkDescriptorSet set0 = m_set0_resource; + m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); + } + + void end() { + flecs::query<> all_meshes = m_world->query_builder().build(); all_meshes.each([this](flecs::entity p_entity) { + // Retrieving the buffer address that can be looked up from the glsl shader const uint64_t scene_ubo_address = m_scene_uniforms.get_device_address(); const uint64_t objects_ubo_address = m_object_model_uniforms.get_device_address(); push_constant_data push = { @@ -370,17 +376,8 @@ export namespace atlas { }; m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); - }); - - const VkDescriptorSet set0 = m_set0_resource; - m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); - } - - void end() { - // TODO: Use Vulkan Indirect Command Draw call for this to reduce draw calls - flecs::query<> all_meshes = m_world->query_builder().build(); - all_meshes.each([this](flecs::entity p_entity) { + // TODO: Use Vulkan Indirect Command Draw call for this to reduce draw calls const auto& mesh = m_meshes[p_entity.id()]; const VkBuffer vertex = mesh.vertex; uint64_t offset = 0; diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 3a1db505..e4699241 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -10,6 +10,10 @@ module; #include #include +#include +#include +#include + export module editor:level_scene; import atlas.application; @@ -40,7 +44,7 @@ public: atlas::game_object viking_room = entity("Viking Room"); viking_room.set({ - .position = { -2.70f, 2.70, -8.30f }, + .position = { 5, 5, 0.f }, // .position = { 1.f, 1.f, 1.f }, .rotation = { 2.30f, 95.90f, 91.80f }, // .rotation = { 1.f, 1.f, 1.f }, @@ -55,32 +59,30 @@ public: // .diffuse = "assets/models/container_specular.png", }); - // for(size_t i = 0; i < 31; i++) { - // atlas::game_object obj = entity(std::format("Object #{}", i)); - // obj.set({ - // .restitution = 1.25f, - // .body_movement_type = atlas::dynamic, - // }); - - // obj.set( - // { - // .radius = 1.0f, - // }); - - // glm::vec3 pos = {float(0.5 * 1.4), float(0.5 * 1.4), float(0.5 - // * 1.4) }; - - // obj.set({ - // .position = pos, - // .rotation = {.3f, 0.0f, 0.0f}, - // }); - - // obj.set({ - // // .model_path = "assets/models/Ball OBJ.obj", - // .model_path = "assets/models/cube.obj", - // // .diffuse = "assets/models/clear.png", - // .diffuse = "assets/models/container_diffuse.png", - // }); + + // const size_t grid_width = 5; + // const float spacing = 5; + + // for(size_t i = 0; i < 40; i++) { + // atlas::game_object obj = entity(std::format("Object #{}", i)); + + // size_t col = i % grid_width; // X axis + // size_t row = i / grid_width; // Z axis + + // glm::vec3 pos = { + // float(static_cast(col) * spacing), + // 0.0f, // Keep Y flat on the ground + // float(static_cast(row) * -spacing) // Use row for Z depth (negative moves it away from camera) + // }; + + // obj.set({ + // .position = pos, + // .rotation = {.3f, 0.0f, 0.0f}, + // }); + // obj.set({ + // .model_path = "assets/models/Ball OBJ.obj", + // .diffuse = "assets/models/clear.png", + // }); // } atlas::register_start(this, &level_scene::start); From 0088baecfee6bb9bdcde7f39f38cd27427777137 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 4 Jun 2026 11:35:34 -0700 Subject: [PATCH 043/106] refactor: add demo code for testing objects rendering --- editor/level_scene.cppm | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index e4699241..6d0cd6f1 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -63,16 +63,16 @@ public: // const size_t grid_width = 5; // const float spacing = 5; - // for(size_t i = 0; i < 40; i++) { + // for(size_t i = 0; i < 100; i++) { // atlas::game_object obj = entity(std::format("Object #{}", i)); - // size_t col = i % grid_width; // X axis - // size_t row = i / grid_width; // Z axis + // size_t col = i % grid_width; + // size_t row = i / grid_width; // glm::vec3 pos = { - // float(static_cast(col) * spacing), - // 0.0f, // Keep Y flat on the ground - // float(static_cast(row) * -spacing) // Use row for Z depth (negative moves it away from camera) + // float(static_cast(col) * spacing), + // 0.0f, + // float(static_cast(row) * -spacing) // }; // obj.set({ @@ -114,11 +114,13 @@ public: glm::vec3 forward = glm::rotate(to_quaternion, atlas::math::backward()); glm::vec3 right = glm::rotate(to_quaternion, atlas::math::right()); - if (atlas::event::is_key_pressed(key_left_shift)) { + // Q = UP + if (atlas::event::is_key_pressed(key_q)) { t->position += up * velocity; } - if (atlas::event::is_key_pressed(key_space)) { + // E = DOWN + if (atlas::event::is_key_pressed(key_e)) { t->position -= up * velocity; } @@ -143,6 +145,25 @@ public: t->rotation.y -= rotation_velocity; } + glm::vec2 current_cursor_pos = atlas::event::cursor_position(); + if(atlas::event::is_key_pressed(key_left_shift)) { + glm::vec2 cursor_dt = current_cursor_pos - m_last_cursor_pos; + float mouse_sensitivity = 0.1; + + // Update Euler angles + + if(atlas::event::is_mouse_pressed(mouse_button_left)) { + t->rotation.y -= (cursor_dt.x * mouse_sensitivity) * dt; + } + + if(atlas::event::is_mouse_pressed(mouse_button_right)) { + t->rotation.x -= (cursor_dt.y * mouse_sensitivity) * dt; + } + + // Clamp pitch to prevent the camera from flipping completely upside down (optional but recommended) + t->rotation.x = glm::clamp(t->rotation.x, -89.0f, 89.0f); + } + // Signal to trigger this kind of scene transition // Experimental: This was used for testing. // if(atlas::event::is_key_pressed(key_n)) { @@ -152,8 +173,9 @@ public: // }; // signal(scene_transition); // } - t->set_rotation(t->rotation); + + m_last_cursor_pos = current_cursor_pos; } // TODO: Have this physics_update be executed during the physics @@ -163,4 +185,5 @@ public: private: std::optional m_editor_camera; float m_movement_speed = 10.f; + glm::vec2 m_last_cursor_pos{}; }; \ No newline at end of file From 8006fe1f93470b937c32e6071c6b6743a8e2ab44 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 4 Jun 2026 13:17:47 -0700 Subject: [PATCH 044/106] refactor: minor code cleanup --- atlas/drivers/vulkan/render_context.cppm | 8 -------- 1 file changed, 8 deletions(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 99639c55..593838b1 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -303,7 +303,6 @@ export namespace atlas { } void begin(vk::rendering_begin_parameters p_begin_params, const window_params& p_extent, const glm::mat4& p_proj, const glm::mat4& p_view) { - m_proj_view = p_proj * p_view; vk::viewport_params viewport = { .x = 0.0f, .y = 0.0f, @@ -422,7 +421,6 @@ export namespace atlas { private: uint32_t m_format; - glm::mat4 m_proj_view=glm::mat4(1.f); // Combination of the projection * view matrix result std::optional m_physical; std::shared_ptr m_device; vk::command_buffer* m_current_command=nullptr; @@ -438,7 +436,6 @@ export namespace atlas { * 3.) Material Uniforms (diffuse/specular/etc...) */ vk::dyn::buffer m_scene_uniforms; - // uniform buffer to write all of our objects mat4 model matrices in vk::dyn::buffer m_object_model_uniforms; @@ -456,15 +453,10 @@ export namespace atlas { // material lookups - // is to search for specific indices that correspond to various material surfaces // indices to search inside of vector std::unordered_map m_material_table; std::vector m_gpu_textures; - - // GPU sampled images - // - std::unordered_map m_gpu_storage_images; std::vector m_gpu_images; vk::shader_stage m_stage; From 6c094c0e9e0530c9c412e5db27fdaf2b0680431e Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 4 Jun 2026 13:28:49 -0700 Subject: [PATCH 045/106] refactor: fix key inputs for the camera system --- editor/level_scene.cppm | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 6d0cd6f1..841fd486 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -138,13 +138,6 @@ public: t->position -= right * velocity; } - if (atlas::event::is_key_pressed(key_q)) { - t->rotation.y += rotation_velocity; - } - if (atlas::event::is_key_pressed(key_e)) { - t->rotation.y -= rotation_velocity; - } - glm::vec2 current_cursor_pos = atlas::event::cursor_position(); if(atlas::event::is_key_pressed(key_left_shift)) { glm::vec2 cursor_dt = current_cursor_pos - m_last_cursor_pos; @@ -153,11 +146,11 @@ public: // Update Euler angles if(atlas::event::is_mouse_pressed(mouse_button_left)) { - t->rotation.y -= (cursor_dt.x * mouse_sensitivity) * dt; + t->rotation.y -= (cursor_dt.x * mouse_sensitivity) * rotation_velocity; } if(atlas::event::is_mouse_pressed(mouse_button_right)) { - t->rotation.x -= (cursor_dt.y * mouse_sensitivity) * dt; + t->rotation.x -= (cursor_dt.y * mouse_sensitivity) * rotation_velocity; } // Clamp pitch to prevent the camera from flipping completely upside down (optional but recommended) From 3a469f543f8cad3a667bab811fd957388ca8d17f Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 4 Jun 2026 13:41:00 -0700 Subject: [PATCH 046/106] refactor: fix the x-axis relative to the cursors current position for camera rotation --- editor/level_scene.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 841fd486..52686da3 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -150,7 +150,7 @@ public: } if(atlas::event::is_mouse_pressed(mouse_button_right)) { - t->rotation.x -= (cursor_dt.y * mouse_sensitivity) * rotation_velocity; + t->rotation.x += (cursor_dt.y * mouse_sensitivity) * rotation_velocity; } // Clamp pitch to prevent the camera from flipping completely upside down (optional but recommended) From d585c5eb5e916221112911e4e5eb72892e6ecf45 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 5 Jun 2026 16:02:18 -0700 Subject: [PATCH 047/106] refactor: did some cleanup and fixing up the command buffer begin_rendering/end_rendernig invokatinos in the render_context --- atlas/core/application.cppm | 29 ++++- atlas/drivers/vulkan/imgui_context.cppm | 130 +++++++++++++++++++++-- atlas/drivers/vulkan/render_context.cppm | 38 +++---- 3 files changed, 167 insertions(+), 30 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index d5a0582b..d1e654e2 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -97,7 +97,8 @@ export namespace atlas { m_window->request_images().size(), m_window->present_queue(), m_color_format, - m_depth_format); + m_depth_format, + params); // Initializing command buffers std::span images = m_window->request_images(); @@ -269,6 +270,13 @@ export namespace atlas { m_imgui_context->set_current_command(current); + /** + * NOTE: For getting imgui_context + * + * Using viewport images instead of swapchain images. + * + * These swapchain images will be used as soon the 3D scene is rendered to the imgui viewport images. + */ m_images[m_next_image_frame_idx].memory_barrier( current, m_window->surface_properties().format.format, @@ -314,10 +322,29 @@ export namespace atlas { .stencil_attachment = depth_stencil_attachment, }; + vk::viewport_params viewport = { + .x = 0.0f, + .y = 0.0f, + .width = static_cast(m_window->extent().width), + .height = static_cast(m_window->extent().height), + .min_depth = 0.0f, + .max_depth = 1.0f, + }; + current.set_viewport(0, 1, std::span(&viewport, 1)); + + vk::scissor_params scissor = { + .offset = { 0, 0 }, + .extent = {static_cast(m_window->extent().width), static_cast(m_window->extent().height)}, + }; + current.set_scissor(0, 1, std::span(&scissor, 1)); + + current.begin_rendering(begin_params); + m_render_context.begin( begin_params, m_window->extent(), m_projection, m_view); m_render_context.end(); + current.end_rendering(); // Performing UI Context Rendering diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 6b1e5705..e1590eb4 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -77,16 +77,83 @@ namespace atlas { return rendering_ci; } + void transition_image_layout(VkDevice p_device, + vk::sample_image& p_image, + VkFormat p_format, + VkImageLayout p_old, + VkImageLayout p_new) { + vk::command_params copy_command_params = { + .levels = vk::command_levels::primary, + .queue_index = 0, + .flags = vk::command_pool_flags::reset, + }; + vk::command_buffer temp_command_buffer = + vk::command_buffer(p_device, copy_command_params); + + temp_command_buffer.begin(vk::command_usage::one_time_submit); + + p_image.memory_barrier(temp_command_buffer, p_format, p_old, p_new); + + temp_command_buffer.end(); + + VkCommandBuffer handle = temp_command_buffer; + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &handle, + }; + + uint32_t queue_family_index = 0; + uint32_t queue_index = 0; + VkQueue temp_graphics_queue; + vkGetDeviceQueue( + p_device, queue_family_index, queue_index, &temp_graphics_queue); + + vkQueueSubmit(temp_graphics_queue, 1, &submit_info, nullptr); + vkQueueWaitIdle(temp_graphics_queue); + + temp_command_buffer.destruct(); + } + + /** + * TODO List + * 0.) Initialize ImGui Context + Test ImGui Panel Undocking Beforehand + * 1.) Render offscreen texture + * 2.) Upload to imgui dockspace + * 3.) Retrieve viewport ID (which is a ImTextureID) + */ + + + /** + * + * NOTE: There are a few things to remember: + * + * Actual TODOs that need to be done to get imgui back and working again for getting the viewport + dockspace running again: + * 0.) When performing off-screen rendering of the 3D screen. We are going to need to do begin_rendering/end_rendering for the viewport images. + * - Rather then using the specified begin rendering in the render_context + * - To get this to work we may need to strip out render_context begin_rendering/end_rendering outside of the begin/end APIs of render_context. + * 1.) Using imgui_contexts begin_rendering/end_rendering images. + * 2.) As we render those specific viewport images need to perform memory_barriers as well. + * 3.) Then once that is rendered. We will render the final imgui offscreen texture with the current command buffers to the swapchain for drawn to the screen. + * + * + * + * + */ export class imgui_context { public: imgui_context() = delete; imgui_context(/*NOLINT*/ std::shared_ptr p_context, GLFWwindow* p_window, - /*NOLINT*/ std::shared_ptr p_swapchain, + /*NOLINT*/ std::shared_ptr, uint32_t p_image_count, const vk::device_present_queue& p_queue, /*NOLINT*/ const VkFormat& p_color_format, - /*NOLINT*/ const VkFormat& p_depth_format) { + /*NOLINT*/ const VkFormat& p_depth_format, + const window_params& p_params) + : m_color_format(p_color_format) + , m_depth_format(p_depth_format) + , m_params(p_params) { m_instance = p_context->instance_handle(); m_device = p_context->logical_device(); m_physical = p_context->physical_device(); @@ -152,15 +219,50 @@ namespace atlas { *m_device, &desc_pool_create_info, nullptr, &m_descriptor_pool), "vkCreateDescriptorPool"); - construct(p_window, /*NOLINT*/ p_swapchain, p_image_count, p_queue, p_color_format, p_depth_format); + // Creating viewport image + vk::image_params viewport_params = { + .extent = { .width = m_params.width, + .height = m_params.height }, + // .format = VK_FORMAT_B8G8R8A8_UNORM, + .format = m_color_format, + // .property = vk::memory_property::device_local_bit, + .memory_mask = m_physical->memory_properties( + vk::memory_property::device_local_bit | + vk::memory_property::host_visible_bit), + .aspect = vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::color_attachment_bit | + vk::image_usage::transfer_dst_bit | + vk::image_usage::sampled_bit, + .address_mode_u = vk::sampler_address_mode::clamp_to_edge, + .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, + .addrses_mode_w = vk::sampler_address_mode::clamp_to_edge, + }; + + m_viewport_image = vk::sample_image(*m_device, viewport_params); + + transition_image_layout(*m_device, + m_viewport_image, + m_color_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + // Perform additional configurations for specific handles + vk::image_params viewport_depth_params = { + .extent = { .width = m_params.width, + .height = m_params.height }, + .format = m_depth_format, + .memory_mask = m_physical->memory_properties(vk::memory_property::device_local_bit | vk::memory_property::host_visible_bit), + .aspect = vk::image_aspect_flags::depth_bit, + .usage = vk::image_usage::depth_stencil_bit, + }; + m_viewport_depth_image = vk::sample_image(*m_device, viewport_depth_params); + + construct(p_window, p_image_count, p_queue); } void construct(GLFWwindow* p_window, - /*NOLINT*/ std::shared_ptr p_swapchain, uint32_t p_image_count, - const vk::device_present_queue& p_queue, - /*NOLINT*/ const VkFormat& p_color_format, - /*NOLINT*/ const VkFormat& p_depth_format) { + const vk::device_present_queue& p_queue) { ImGui_ImplGlfw_InitForVulkan(p_window, true); ImGui_ImplVulkan_InitInfo init_info = {}; @@ -176,8 +278,8 @@ namespace atlas { init_info.UseDynamicRendering = true; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; - const uint32_t color_format = static_cast(p_color_format); - const uint32_t depth_format = static_cast(p_depth_format); + const uint32_t color_format = static_cast(m_color_format); + const uint32_t depth_format = static_cast(m_depth_format); init_info.PipelineRenderingCreateInfo = pipeline_rendering_info( std::span(&color_format, 1), depth_format, @@ -202,7 +304,7 @@ namespace atlas { ImGui_ImplVulkan_RenderDrawData(draw_data, *m_current_command); ImGuiIO& io = ImGui::GetIO(); - if(io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); } @@ -212,16 +314,24 @@ namespace atlas { ImGui_ImplVulkan_Shutdown(); vkDestroyDescriptorPool(*m_device, m_descriptor_pool, nullptr); + m_viewport_image.destruct(); + m_viewport_depth_image.destruct(); + ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); } private: + VkFormat m_color_format; + VkFormat m_depth_format; VkDescriptorPool m_descriptor_pool = nullptr; vk::command_buffer* m_current_command; std::optional m_instance; std::optional m_physical; std::shared_ptr m_device = nullptr; vk::surface_params m_surface_properties; + vk::sample_image m_viewport_image; + vk::sample_image m_viewport_depth_image; + window_params m_params; }; }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 593838b1..10d150a8 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -302,24 +302,24 @@ export namespace atlas { } - void begin(vk::rendering_begin_parameters p_begin_params, const window_params& p_extent, const glm::mat4& p_proj, const glm::mat4& p_view) { - vk::viewport_params viewport = { - .x = 0.0f, - .y = 0.0f, - .width = static_cast(p_extent.width), - .height = static_cast(p_extent.height), - .min_depth = 0.0f, - .max_depth = 1.0f, - }; - m_current_command->set_viewport(0, 1, std::span(&viewport, 1)); - - vk::scissor_params scissor = { - .offset = { 0, 0 }, - .extent = {static_cast(p_extent.width), static_cast(p_extent.height)}, - }; - m_current_command->set_scissor(0, 1, std::span(&scissor, 1)); - - m_current_command->begin_rendering(p_begin_params); + void begin(vk::rendering_begin_parameters, const window_params&, const glm::mat4& p_proj, const glm::mat4& p_view) { + // vk::viewport_params viewport = { + // .x = 0.0f, + // .y = 0.0f, + // .width = static_cast(p_extent.width), + // .height = static_cast(p_extent.height), + // .min_depth = 0.0f, + // .max_depth = 1.0f, + // }; + // m_current_command->set_viewport(0, 1, std::span(&viewport, 1)); + + // vk::scissor_params scissor = { + // .offset = { 0, 0 }, + // .extent = {static_cast(p_extent.width), static_cast(p_extent.height)}, + // }; + // m_current_command->set_scissor(0, 1, std::span(&scissor, 1)); + + // m_current_command->begin_rendering(p_begin_params); m_main_pipeline.bind(*m_current_command); @@ -389,7 +389,7 @@ export namespace atlas { vkCmdDraw(*m_current_command, mesh.vertices_size, 1, 0, 0); } }); - m_current_command->end_rendering(); + // m_current_command->end_rendering(); } void set_command(vk::command_buffer& p_command) { From d310c687bc46a23e82640379fefc12b6e6117d5e Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 5 Jun 2026 16:47:20 -0700 Subject: [PATCH 048/106] refactor: working imgui and render context images to render to an offscreen texture --- atlas/core/application.cppm | 90 ++++++++++++++++++++---- atlas/drivers/vulkan/imgui_context.cppm | 28 ++++++++ atlas/drivers/vulkan/render_context.cppm | 2 +- 3 files changed, 104 insertions(+), 16 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index d1e654e2..9a693884 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -277,20 +277,48 @@ export namespace atlas { * * These swapchain images will be used as soon the 3D scene is rendered to the imgui viewport images. */ - m_images[m_next_image_frame_idx].memory_barrier( + + // m_images[m_next_image_frame_idx].memory_barrier( + m_imgui_context->image_memory_barrier( current, m_window->surface_properties().format.format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_ASPECT_COLOR_BIT); - m_depth_images[m_next_image_frame_idx].memory_barrier( + // m_depth_images[m_next_image_frame_idx].memory_barrier( + m_imgui_context->depth_image_memory_barrier( current, m_depth_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + VK_IMAGE_ASPECT_DEPTH_BIT); + + vk::rendering_attachment ui_color_render_attachment = { + // .image_view = m_images[m_next_image_frame_idx].image_view(), + .image_view = m_imgui_context->color_image_view(), + .layout = vk::image_layout::color_optimal, + .resolve_mode = vk::resolved_mode_flags::none, + .resolve_image_view = nullptr, + .resolve_image_layout = vk::image_layout::undefined, + .load = vk::attachment_load::clear, + .store = vk::attachment_store::store, + .clear_values = clear_color + }; + + vk::rendering_attachment ui_depth_stencil_attachment = { + .image_view = m_imgui_context->depth_image_view(), + .layout = vk::image_layout::depth_stencil_optimal, + .resolve_mode = vk::resolved_mode_flags::none, + .resolve_image_view = nullptr, + .resolve_image_layout = vk::image_layout::undefined, + .load = vk::attachment_load::clear, + .store = vk::attachment_store::store, + .depth_values = depth_value + }; - vk::rendering_attachment color_render_attachment = { + // presenting rendering attachments + vk::rendering_attachment present_color_render_attachment = { .image_view = m_images[m_next_image_frame_idx].image_view(), .layout = vk::image_layout::color_optimal, .resolve_mode = vk::resolved_mode_flags::none, @@ -301,7 +329,7 @@ export namespace atlas { .clear_values = clear_color }; - vk::rendering_attachment depth_stencil_attachment = { + vk::rendering_attachment present_depth_stencil_attachment = { .image_view = m_depth_images[m_next_image_frame_idx].image_view(), .layout = vk::image_layout::depth_stencil_optimal, @@ -313,13 +341,13 @@ export namespace atlas { .depth_values = depth_value }; - vk::rendering_begin_parameters begin_params = { + vk::rendering_begin_parameters ui_begin_params = { .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, .layer_count = 1, .color_attachments = std::span( - &color_render_attachment, 1), - .depth_attachment = depth_stencil_attachment, - .stencil_attachment = depth_stencil_attachment, + &ui_color_render_attachment, 1), + .depth_attachment = ui_depth_stencil_attachment, + .stencil_attachment = ui_depth_stencil_attachment, }; vk::viewport_params viewport = { @@ -338,25 +366,57 @@ export namespace atlas { }; current.set_scissor(0, 1, std::span(&scissor, 1)); - current.begin_rendering(begin_params); + current.begin_rendering(ui_begin_params); - m_render_context.begin( - begin_params, m_window->extent(), m_projection, m_view); + m_render_context.begin(m_projection, m_view); m_render_context.end(); current.end_rendering(); - // Performing UI Context Rendering + m_imgui_context->image_memory_barrier( + current, + VK_FORMAT_B8G8R8A8_UNORM, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_ASPECT_COLOR_BIT + ); + + // Performing Present Context Rendering + + m_images[m_next_image_frame_idx].memory_barrier( + current, + m_window->surface_properties().format.format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + m_depth_images[m_next_image_frame_idx].memory_barrier( + current, + m_depth_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + vk::rendering_begin_parameters begin_params = { + .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, + .layer_count = 1, + .color_attachments = std::span( + &present_color_render_attachment, 1), + .depth_attachment = present_depth_stencil_attachment, + .stencil_attachment = present_depth_stencil_attachment, + }; + current.begin_rendering(begin_params); m_imgui_context->begin(); invoke_ui_update(m_current_scene.get()); m_imgui_context->end(); + current.end_rendering(); m_images[m_next_image_frame_idx].memory_barrier( current, m_window->surface_properties().format.format, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + + // m_images[m_next_image_frame_idx].memory_barrier( current.end(); const VkCommandBuffer command = current; diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index e1590eb4..2ec972ca 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -260,6 +260,25 @@ namespace atlas { construct(p_window, p_image_count, p_queue); } + + void image_memory_barrier(const VkCommandBuffer& p_command, + VkFormat p_format, + VkImageLayout p_old, + VkImageLayout p_new, + uint32_t p_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT) { + + m_viewport_image.memory_barrier(p_command, p_format, p_old, p_new, p_aspect_mask); + } + + void depth_image_memory_barrier(const VkCommandBuffer& p_command, + VkFormat p_format, + VkImageLayout p_old, + VkImageLayout p_new, + uint32_t p_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT) { + + m_viewport_depth_image.memory_barrier(p_command, p_format, p_old, p_new, p_aspect_mask); + } + void construct(GLFWwindow* p_window, uint32_t p_image_count, const vk::device_present_queue& p_queue) { @@ -291,6 +310,15 @@ namespace atlas { m_current_command = &p_command; } + + [[nodiscard]] VkImageView color_image_view() const { + return m_viewport_image.image_view(); + } + + [[nodiscard]] VkImageView depth_image_view() const { + return m_viewport_depth_image.image_view(); + } + void begin() { ImGui_ImplVulkan_NewFrame(); ImGui_ImplGlfw_NewFrame(); diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 10d150a8..2e11d027 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -302,7 +302,7 @@ export namespace atlas { } - void begin(vk::rendering_begin_parameters, const window_params&, const glm::mat4& p_proj, const glm::mat4& p_view) { + void begin(const glm::mat4& p_proj, const glm::mat4& p_view) { // vk::viewport_params viewport = { // .x = 0.0f, // .y = 0.0f, From af9d0418c94bd2650710bfa7404efe2b893ff28e Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 5 Jun 2026 17:33:55 -0700 Subject: [PATCH 049/106] refactor: added back working viewport, BUT still work in progres. As it is brittle due to it crashing --- atlas/drivers/vulkan/imgui_context.cppm | 35 +++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 2ec972ca..7634cca0 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -140,6 +140,7 @@ namespace atlas { * * */ + export ImTextureID g_viewport_image_id = nullptr; export class imgui_context { public: imgui_context() = delete; @@ -163,6 +164,7 @@ namespace atlas { // Common setup for imgui IMGUI_CHECKVERSION(); ImGui::CreateContext(); + std::println("After ImGui::CreateContext"); ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= @@ -177,6 +179,7 @@ namespace atlas { // Additional configurations imgui_layout_color_modification(); + std::println("After setting imgui_layout_color_modification"); ImGuiStyle& style = ImGui::GetStyle(); if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { style.WindowRounding = 0.0f; @@ -203,6 +206,7 @@ namespace atlas { VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } }; + std::println("Before creating VkDescriptorPool"); VkDescriptorPoolCreateInfo desc_pool_create_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .pNext = nullptr, @@ -219,6 +223,7 @@ namespace atlas { *m_device, &desc_pool_create_info, nullptr, &m_descriptor_pool), "vkCreateDescriptorPool"); + std::println("After vkCrateDescriptorPool"); // Creating viewport image vk::image_params viewport_params = { .extent = { .width = m_params.width, @@ -227,8 +232,7 @@ namespace atlas { .format = m_color_format, // .property = vk::memory_property::device_local_bit, .memory_mask = m_physical->memory_properties( - vk::memory_property::device_local_bit | - vk::memory_property::host_visible_bit), + vk::memory_property::device_local_bit), .aspect = vk::image_aspect_flags::color_bit, .usage = vk::image_usage::color_attachment_bit | vk::image_usage::transfer_dst_bit | @@ -240,11 +244,14 @@ namespace atlas { m_viewport_image = vk::sample_image(*m_device, viewport_params); + std::println("before transition image layout"); transition_image_layout(*m_device, m_viewport_image, m_color_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + std::println("after transition image layout"); // Perform additional configurations for specific handles vk::image_params viewport_depth_params = { @@ -256,7 +263,15 @@ namespace atlas { .usage = vk::image_usage::depth_stencil_bit, }; m_viewport_depth_image = vk::sample_image(*m_device, viewport_depth_params); + std::println("After initializing m_viewport_depth_image"); + + if(m_viewport_image.sampler() == nullptr) { + std::println("sampler() = nullprt"); + } + if(m_viewport_image.image_view() == nullptr) { + std::println("image_view() = nullprt"); + } construct(p_window, p_image_count, p_queue); } @@ -304,6 +319,16 @@ namespace atlas { depth_format, depth_format); ImGui_ImplVulkan_Init(&init_info); + + std::println("g_viewport_image_id constructed"); + // Offscreen texture to retrieve + g_viewport_image_id = + static_cast(ImGui_ImplVulkan_AddTexture( + m_viewport_image.sampler(), + m_viewport_image.image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + + std::println("After g_viewport_image_id constructed"); } void set_current_command(vk::command_buffer& p_command) { @@ -342,6 +367,12 @@ namespace atlas { ImGui_ImplVulkan_Shutdown(); vkDestroyDescriptorPool(*m_device, m_descriptor_pool, nullptr); + if(g_viewport_image_id != nullptr) { + VkDescriptorSet old_descriptor_set = reinterpret_cast(g_viewport_image_id); + ImGui_ImplVulkan_RemoveTexture(old_descriptor_set); + g_viewport_image_id = nullptr; + } + m_viewport_image.destruct(); m_viewport_depth_image.destruct(); From 24c749049fe91cb787af149384f5d18bd0de51fe Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 7 Jun 2026 14:31:39 -0700 Subject: [PATCH 050/106] refactor: explicitly added VK_KHR_dynamic_rendering to logical device extensions to mitigate the cause of imgui crashing when undocking UI panels --- atlas/core/entry_point/main.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 7ee5e36a..f0734d5a 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -114,13 +114,15 @@ main() { std::array priorities = { 0.f }; #if defined(__APPLE__) - std::array extensions = { + std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, "VK_KHR_portability_subset", + "VK_KHR_dynamic_rendering", }; #else - std::array extensions = { + std::array extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME, + "VK_KHR_dynamic_rendering", }; #endif From 499ab1b4b85b08d6e3287fa10ffc0d7554b76ed3 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 8 Jun 2026 03:00:26 -0700 Subject: [PATCH 051/106] refactor: imgui_context works with no validation layer error messages, only when undocking imgui panels + minor fix level_streamer to pass polymorphic allocator --- atlas/core/application copy.cppm | 495 ++++++++++++++++++++++++ atlas/core/application.cppm | 137 ++++--- atlas/core/scene/level_streamer.cppm | 4 +- atlas/drivers/vulkan/imgui_context.cppm | 138 +++---- 4 files changed, 636 insertions(+), 138 deletions(-) create mode 100644 atlas/core/application copy.cppm diff --git a/atlas/core/application copy.cppm b/atlas/core/application copy.cppm new file mode 100644 index 00000000..58516e2c --- /dev/null +++ b/atlas/core/application copy.cppm @@ -0,0 +1,495 @@ +module; + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#define GLM_ENABLE_EXPERIMENTAL +#include + +#include +#include +#include +#include + +export module atlas.application; + +import atlas.core.utilities; +import atlas.core.utilities.poll_state; +import atlas.core.event; +import vk; +import atlas.drivers.vulkan; + +import atlas.core.scene; +import atlas.core.scene.world; +import atlas.core.scene.components; +import atlas.core.math; + +export namespace atlas { + + /** + * @brief application properties settings for the window + */ + struct application_settings { + std::string name = "Undefined"; + uint32_t width = 0; + uint32_t height = 0; + glm::vec4 background_color = { 1.f, 0.5f, 0.5f, 1.f }; + }; + + class application { + public: + application() = default; + application(/*NOLINT*/ std::shared_ptr p_context, + const application_settings& p_params, + event::bus& p_bus) + : m_context(p_context) + , m_bus(&p_bus) { + m_instance = p_context->instance_handle(); + m_physical = p_context->physical_device(); + m_device = p_context->logical_device(); + + // Constructing the application + window_params params = { + .width = p_params.width, + .height = p_params.height, + .name = p_params.name, + }; + + // m_window = std::allocate_shared(, + // m_context->instance_handle(), params); + m_window = std::make_shared(p_context, params); + + m_aspect_ratio = static_cast(params.width) / static_cast(params.height); + event::set_window_size(m_window->glfw_window()); + + m_bus->create_listener(); + m_bus->create_listener(); + m_bus->create_listener(); + // m_bus->create_immediate_listener(); + // m_bus->create_immediate_listener(); + // m_bus->create_immediate_listener(); + + // Requesting depth format + std::array format_support = { + vk::format::d32_sfloat, + vk::format::d32_sfloat_s8_uint, + vk::format::d24_unorm_s8_uint + }; + + m_color_format = m_window->surface_properties().format.format; + // We provide a selection of format support that we want to check is + // supported on current hardware device. + m_depth_format = m_physical->request_depth_format(format_support); + + m_imgui_context = std::make_shared(p_context, + m_window->glfw_window(), + m_window->swapchain_handle(), + m_window->request_images().size(), + m_window->present_queue(), + m_color_format, + m_depth_format, + params); + + // Initializing command buffers + std::span images = m_window->request_images(); + + m_images.resize(images.size()); + m_depth_images.resize(images.size()); + + for (uint32_t i = 0; i < m_images.size(); i++) { + vk::image_params color_img_params = { + .extent = { + .width = m_window->extent().width, + .height = m_window->extent().height, + }, + .format = m_window->surface_properties().format.format, + .memory_mask = m_physical->memory_properties( + vk::memory_property::device_local_bit), + .aspect = vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::color_attachment_bit, + .mip_levels = 1, + .layer_count = 1, + }; + m_images[i] = + vk::sample_image(*m_device, images[i], color_img_params); + + vk::image_params depth_img_params = { + .extent = { + .width = m_window->extent().width, + .height = m_window->extent().height, + }, + .format = m_depth_format, + .memory_mask = m_physical->memory_properties( + vk::memory_property::device_local_bit), + .aspect = vk::image_aspect_flags::depth_bit, + .usage = vk::image_usage::depth_stencil_bit, + .mip_levels = 1, + .layer_count = 1, + }; + + m_depth_images[i] = + vk::sample_image(*m_device, depth_img_params); + } + + m_command_buffers.resize(images.size()); + + for (uint32_t i = 0; i < m_command_buffers.size(); i++) { + vk::command_params command_params = { + .levels = vk::command_levels::primary, + .queue_index = 0, + .flags = vk::command_pool_flags::reset, + }; + m_command_buffers[i] = + vk::command_buffer(*m_device, command_params); + } + + m_render_context = + render_context(m_context, m_color_format, m_depth_format); + + std::println("images.size() = {}", images.size()); + + m_window->center_window(); + + // m_bus->trigger(this, + // &application::on_scene_transition); + } + + void execute() { + VkClearValue clear_color = { + { { 0.f, 0.5f, 0.5f, 1.f } }, + }; + + VkClearValue depth_value = { + .depthStencil = { .depth = 1.f, .stencil = 0 }, + }; + + m_current_scene = m_world->current(); + + // Handling camera system execution + m_current_scene + ->system, + transform, + perspective_camera>() + .each([this](flecs::pair p_pair, + transform& p_transform, + perspective_camera& p_camera) { + if (!p_camera.is_active) { + return; + } + + p_pair->projection = glm::mat4(1.f); + + p_pair->projection = + glm::perspective(glm::radians(p_camera.field_of_view), + m_aspect_ratio, + p_camera.plane.x, + p_camera.plane.y); + p_pair->projection[1][1] *= -1; + p_pair->view = glm::mat4(1.f); + + // This is converting a glm::highp_vec4 to a glm::quat + glm::quat quaternion = to_quat(p_transform.quaternion); + + p_pair->view = + glm::translate(p_pair->view, p_transform.position) * + glm::mat4_cast(quaternion); + + p_pair->view = glm::inverse(p_pair->view); + }); + + // Setting the current scene for the renderer to start rendering the + // objects + m_render_context.current_scene(*m_current_scene); + + auto start_time = std::chrono::high_resolution_clock::now(); + invoke_start(m_current_scene.get()); + + // Querying editor cameras specific objects + // Then using this to execute specific main cameras. + auto query_camera_objects = + m_current_scene + ->query_builder, + perspective_camera>() + .build(); + + m_render_context.prebake(); + + while (m_window->available()) { + auto current_time = std::chrono::high_resolution_clock::now(); + m_delta_time = + std::chrono::duration( + current_time - start_time) + .count(); + + start_time = current_time; + event::flush_events(); + + // Progresses the flecs::world by one tick (or replaced with + // using the delta time) This also invokes the following + // system call before the mainloop + m_current_scene->progress(m_delta_time); + + m_next_image_frame_idx = m_window->acquire_next_frame(); + + vk::command_buffer current = + m_command_buffers[m_next_image_frame_idx]; + + invoke_physics_update(m_current_scene.get()); + + invoke_on_update(m_current_scene.get(), m_delta_time); + + // We want this to be called after late update + // This queries all camera objects within the camera system + // TODO: Should consider changing this from + // using tags in flecs for specifying active cameras. + query_camera_objects.each( + [&](flecs::entity, + flecs::pair p_pair, + perspective_camera& p_camera) { + if (!p_camera.is_active) { + return; + } + + m_projection = p_pair->projection; + m_view = p_pair->view; + }); + + current.begin(vk::command_usage::simulatneous_use_bit); + + m_render_context.set_command(current); + + m_imgui_context->set_current_command(current); + + /** + * NOTE: For getting imgui_context + * + * Using viewport images instead of swapchain images. + * + * These swapchain images will be used as soon the 3D scene is rendered to the imgui viewport images. + */ + + // m_images[m_next_image_frame_idx].memory_barrier( + m_imgui_context->image_memory_barrier( + current, + m_color_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_ASPECT_COLOR_BIT); + + // m_depth_images[m_next_image_frame_idx].memory_barrier( + m_imgui_context->depth_image_memory_barrier( + current, + m_depth_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_ASPECT_DEPTH_BIT); + + vk::rendering_attachment ui_color_render_attachment = { + .image_view = m_imgui_context->color_image_view(), + .layout = vk::image_layout::color_optimal, + .resolve_mode = vk::resolved_mode_flags::none, + .resolve_image_view = nullptr, + .resolve_image_layout = vk::image_layout::undefined, + .load = vk::attachment_load::clear, + .store = vk::attachment_store::store, + .clear_values = clear_color + }; + + vk::rendering_attachment ui_depth_stencil_attachment = { + .image_view = m_imgui_context->depth_image_view(), + .layout = vk::image_layout::depth_stencil_optimal, + .resolve_mode = vk::resolved_mode_flags::none, + .resolve_image_view = nullptr, + .resolve_image_layout = vk::image_layout::undefined, + .load = vk::attachment_load::clear, + .store = vk::attachment_store::store, + .depth_values = depth_value + }; + + // presenting rendering attachments + vk::rendering_attachment present_color_render_attachment = { + .image_view = m_images[m_next_image_frame_idx].image_view(), + .layout = vk::image_layout::color_optimal, + .resolve_mode = vk::resolved_mode_flags::none, + .resolve_image_view = nullptr, + .resolve_image_layout = vk::image_layout::undefined, + .load = vk::attachment_load::clear, + .store = vk::attachment_store::store, + .clear_values = clear_color + }; + + vk::rendering_attachment present_depth_stencil_attachment = { + .image_view = + m_depth_images[m_next_image_frame_idx].image_view(), + .layout = vk::image_layout::depth_stencil_optimal, + .resolve_mode = vk::resolved_mode_flags::none, + .resolve_image_view = nullptr, + .resolve_image_layout = vk::image_layout::undefined, + .load = vk::attachment_load::clear, + .store = vk::attachment_store::store, + .depth_values = depth_value + }; + + vk::rendering_begin_parameters ui_begin_params = { + .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, + .layer_count = 1, + .color_attachments = std::span( + &ui_color_render_attachment, 1), + .depth_attachment = ui_depth_stencil_attachment, + .stencil_attachment = ui_depth_stencil_attachment, + }; + + vk::viewport_params viewport = { + .x = 0.0f, + .y = 0.0f, + .width = static_cast(m_window->extent().width), + .height = static_cast(m_window->extent().height), + .min_depth = 0.0f, + .max_depth = 1.0f, + }; + current.set_viewport(0, 1, std::span(&viewport, 1)); + + vk::scissor_params scissor = { + .offset = { 0, 0 }, + .extent = {static_cast(m_window->extent().width), static_cast(m_window->extent().height)}, + }; + current.set_scissor(0, 1, std::span(&scissor, 1)); + + current.begin_rendering(ui_begin_params); + + m_render_context.begin(m_projection, m_view); + + m_render_context.end(); + current.end_rendering(); + + m_imgui_context->image_memory_barrier( + current, + m_color_format, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_ASPECT_COLOR_BIT + ); + + // Performing Present Context Rendering + + m_images[m_next_image_frame_idx].memory_barrier( + current, + // m_window->surface_properties().format.format, + m_color_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + m_depth_images[m_next_image_frame_idx].memory_barrier( + current, + m_depth_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + + vk::rendering_begin_parameters begin_params = { + .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, + .layer_count = 1, + .color_attachments = std::span( + &present_color_render_attachment, 1), + .depth_attachment = present_depth_stencil_attachment, + .stencil_attachment = present_depth_stencil_attachment, + }; + current.begin_rendering(begin_params); + m_imgui_context->begin(); + invoke_ui_update(m_current_scene.get()); + m_imgui_context->end(); + + current.end_rendering(); + m_images[m_next_image_frame_idx].memory_barrier( + current, + m_window->surface_properties().format.format, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + + // m_images[m_next_image_frame_idx].memory_barrier( + current.end(); + + const VkCommandBuffer command = current; + m_window->submit(std::span(&command, 1)); + m_window->present(m_next_image_frame_idx); + } + } + + // Experimental: Will look into later once we dive into scene + // transitioning void on_scene_transition(event::scene_transition& + // p_scene_transition) { + // m_world->current(p_scene_transition.next_scene); + // std::println("Attempting to switch to the scene: {}", + // p_scene_transition.next_scene); + + // // We only want to set the current scene if that specific scene + // is valid if(m_world->current() != nullptr) { + // m_current_scene = m_world->current(); + // m_render_context.current_scene(*m_current_scene); + // } + // } + + void post_destroy() { + m_imgui_context->destruct(); + m_render_context.destruct(); + + for (auto& command : m_command_buffers) { + command.destruct(); + } + + for (auto& color_image : m_images) { + color_image.destruct(); + } + + for (auto& depth_image : m_depth_images) { + depth_image.destruct(); + } + m_window->destruct(); + m_device->destruct(); + } + + void current_world(std::shared_ptr p_world) { + m_world = std::move(p_world); + } + + private: + float m_aspect_ratio=0.f; + uint32_t m_next_image_frame_idx = 0; + VkFormat m_color_format; + VkFormat m_depth_format; + std::shared_ptr m_context; + std::shared_ptr m_window = nullptr; + event::bus* m_bus = nullptr; + glm::mat4 m_view = glm::mat4(1.f); + glm::mat4 m_projection = glm::mat4(1.f); + + render_context m_render_context; + + std::shared_ptr m_world; + + std::shared_ptr m_imgui_context; + std::shared_ptr m_current_scene = nullptr; + + // vulkan-cpp specific handles + vk::instance m_instance; + std::optional m_physical; + std::shared_ptr m_device; + std::vector m_images; + std::vector m_depth_images; + std::vector m_command_buffers; + float m_delta_time = 0.f; + static application* s_instance; + }; + + application* application::s_instance = nullptr; +}; \ No newline at end of file diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 9a693884..996efc11 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -91,15 +91,6 @@ export namespace atlas { // supported on current hardware device. m_depth_format = m_physical->request_depth_format(format_support); - m_imgui_context = std::make_shared(p_context, - m_window->glfw_window(), - m_window->swapchain_handle(), - m_window->request_images().size(), - m_window->present_queue(), - m_color_format, - m_depth_format, - params); - // Initializing command buffers std::span images = m_window->request_images(); @@ -156,6 +147,15 @@ export namespace atlas { m_render_context = render_context(m_context, m_color_format, m_depth_format); + m_imgui_context = std::make_shared(p_context, + m_window->glfw_window(), + m_window->swapchain_handle(), + m_window->request_images().size(), + m_window->present_queue(), + // VK_FORMAT_B8G8R8A8_UNORM, + m_color_format, + m_depth_format, + params); std::println("images.size() = {}", images.size()); m_window->center_window(); @@ -249,7 +249,7 @@ export namespace atlas { invoke_on_update(m_current_scene.get(), m_delta_time); // We want this to be called after late update - // This queries all camera objects within the camera system + // This queries all camera objects within the camera sytsem // TODO: Should consider changing this from // using tags in flecs for specifying active cameras. query_camera_objects.each( @@ -270,32 +270,21 @@ export namespace atlas { m_imgui_context->set_current_command(current); - /** - * NOTE: For getting imgui_context - * - * Using viewport images instead of swapchain images. - * - * These swapchain images will be used as soon the 3D scene is rendered to the imgui viewport images. - */ - - // m_images[m_next_image_frame_idx].memory_barrier( m_imgui_context->image_memory_barrier( current, - m_window->surface_properties().format.format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_ASPECT_COLOR_BIT); + // VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - // m_depth_images[m_next_image_frame_idx].memory_barrier( m_imgui_context->depth_image_memory_barrier( current, - m_depth_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_ASPECT_DEPTH_BIT); + VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + // presenting rendering attachments vk::rendering_attachment ui_color_render_attachment = { - // .image_view = m_images[m_next_image_frame_idx].image_view(), .image_view = m_imgui_context->color_image_view(), .layout = vk::image_layout::color_optimal, .resolve_mode = vk::resolved_mode_flags::none, @@ -317,30 +306,6 @@ export namespace atlas { .depth_values = depth_value }; - // presenting rendering attachments - vk::rendering_attachment present_color_render_attachment = { - .image_view = m_images[m_next_image_frame_idx].image_view(), - .layout = vk::image_layout::color_optimal, - .resolve_mode = vk::resolved_mode_flags::none, - .resolve_image_view = nullptr, - .resolve_image_layout = vk::image_layout::undefined, - .load = vk::attachment_load::clear, - .store = vk::attachment_store::store, - .clear_values = clear_color - }; - - vk::rendering_attachment present_depth_stencil_attachment = { - .image_view = - m_depth_images[m_next_image_frame_idx].image_view(), - .layout = vk::image_layout::depth_stencil_optimal, - .resolve_mode = vk::resolved_mode_flags::none, - .resolve_image_view = nullptr, - .resolve_image_layout = vk::image_layout::undefined, - .load = vk::attachment_load::clear, - .store = vk::attachment_store::store, - .depth_values = depth_value - }; - vk::rendering_begin_parameters ui_begin_params = { .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, .layer_count = 1, @@ -369,23 +334,58 @@ export namespace atlas { current.begin_rendering(ui_begin_params); m_render_context.begin(m_projection, m_view); - m_render_context.end(); + current.end_rendering(); + // m_imgui_context->image_memory_barrier( + // current, + // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); m_imgui_context->image_memory_barrier( - current, - VK_FORMAT_B8G8R8A8_UNORM, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_IMAGE_ASPECT_COLOR_BIT - ); + current, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - // Performing Present Context Rendering + /** + * Presenting to Swapchain Memory Barriers + */ + + vk::rendering_attachment present_color_render_attachment = { + .image_view = m_images[m_next_image_frame_idx].image_view(), + .layout = vk::image_layout::color_optimal, + .resolve_mode = vk::resolved_mode_flags::none, + .resolve_image_view = nullptr, + .resolve_image_layout = vk::image_layout::undefined, + .load = vk::attachment_load::clear, + .store = vk::attachment_store::store, + .clear_values = clear_color + }; + + vk::rendering_attachment present_depth_stencil_attachment = { + .image_view = + m_depth_images[m_next_image_frame_idx].image_view(), + .layout = vk::image_layout::depth_stencil_optimal, + .resolve_mode = vk::resolved_mode_flags::none, + .resolve_image_view = nullptr, + .resolve_image_layout = vk::image_layout::undefined, + .load = vk::attachment_load::clear, + .store = vk::attachment_store::store, + .depth_values = depth_value + }; + + vk::rendering_begin_parameters present_begin_params = { + .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, + .layer_count = 1, + .color_attachments = std::span( + &present_color_render_attachment, 1), + .depth_attachment = present_depth_stencil_attachment, + .stencil_attachment = present_depth_stencil_attachment, + }; m_images[m_next_image_frame_idx].memory_barrier( current, - m_window->surface_properties().format.format, + m_color_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); @@ -396,27 +396,22 @@ export namespace atlas { VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - vk::rendering_begin_parameters begin_params = { - .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, - .layer_count = 1, - .color_attachments = std::span( - &present_color_render_attachment, 1), - .depth_attachment = present_depth_stencil_attachment, - .stencil_attachment = present_depth_stencil_attachment, - }; - current.begin_rendering(begin_params); + + current.begin_rendering(present_begin_params); m_imgui_context->begin(); + m_imgui_context->set_current_command(current); invoke_ui_update(m_current_scene.get()); m_imgui_context->end(); - current.end_rendering(); + + m_images[m_next_image_frame_idx].memory_barrier( current, m_window->surface_properties().format.format, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - // m_images[m_next_image_frame_idx].memory_barrier( + // Performing Present Context Rendering current.end(); const VkCommandBuffer command = current; diff --git a/atlas/core/scene/level_streamer.cppm b/atlas/core/scene/level_streamer.cppm index 046b6f63..d4be6a16 100644 --- a/atlas/core/scene/level_streamer.cppm +++ b/atlas/core/scene/level_streamer.cppm @@ -46,9 +46,9 @@ export namespace atlas { m_scenes.emplace( p_name, std::allocate_shared( - std::pmr::polymorphic_allocator(m_allocator.resource()), + m_allocator, p_name, - p_bus)); + p_bus)) ; } // Experimental: This was just for testing. Will come back to later. diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 7634cca0..85585eeb 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -123,22 +123,27 @@ namespace atlas { * 3.) Retrieve viewport ID (which is a ImTextureID) */ - - /** - * - * NOTE: There are a few things to remember: - * - * Actual TODOs that need to be done to get imgui back and working again for getting the viewport + dockspace running again: - * 0.) When performing off-screen rendering of the 3D screen. We are going to need to do begin_rendering/end_rendering for the viewport images. - * - Rather then using the specified begin rendering in the render_context - * - To get this to work we may need to strip out render_context begin_rendering/end_rendering outside of the begin/end APIs of render_context. - * 1.) Using imgui_contexts begin_rendering/end_rendering images. - * 2.) As we render those specific viewport images need to perform memory_barriers as well. - * 3.) Then once that is rendered. We will render the final imgui offscreen texture with the current command buffers to the swapchain for drawn to the screen. - * - * - * - * + /** + * + * NOTE: There are a few things to remember: + * + * Actual TODOs that need to be done to get imgui back and working again for + * getting the viewport + dockspace running again: 0.) When performing + * off-screen rendering of the 3D screen. We are going to need to do + * begin_rendering/end_rendering for the viewport images. + * - Rather then using the specified begin rendering in the + * render_context + * - To get this to work we may need to strip out render_context + * begin_rendering/end_rendering outside of the begin/end APIs of + * render_context. 1.) Using imgui_contexts begin_rendering/end_rendering + * images. 2.) As we render those specific viewport images need to perform + * memory_barriers as well. 3.) Then once that is rendered. We will render + * the final imgui offscreen texture with the current command buffers to the + * swapchain for drawn to the screen. + * + * + * + * */ export ImTextureID g_viewport_image_id = nullptr; export class imgui_context { @@ -152,19 +157,18 @@ namespace atlas { /*NOLINT*/ const VkFormat& p_color_format, /*NOLINT*/ const VkFormat& p_depth_format, const window_params& p_params) - : m_color_format(p_color_format) - , m_depth_format(p_depth_format) - , m_params(p_params) { + : m_params(p_params) { m_instance = p_context->instance_handle(); m_device = p_context->logical_device(); m_physical = p_context->physical_device(); - std::println("Constructing imgui_context"); + m_color_format = p_color_format; + m_depth_format = p_depth_format; + // Common setup for imgui IMGUI_CHECKVERSION(); ImGui::CreateContext(); - std::println("After ImGui::CreateContext"); ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= @@ -179,7 +183,6 @@ namespace atlas { // Additional configurations imgui_layout_color_modification(); - std::println("After setting imgui_layout_color_modification"); ImGuiStyle& style = ImGui::GetStyle(); if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { style.WindowRounding = 0.0f; @@ -206,7 +209,6 @@ namespace atlas { VkDescriptorPoolSize{ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 100 } }; - std::println("Before creating VkDescriptorPool"); VkDescriptorPoolCreateInfo desc_pool_create_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .pNext = nullptr, @@ -223,7 +225,6 @@ namespace atlas { *m_device, &desc_pool_create_info, nullptr, &m_descriptor_pool), "vkCreateDescriptorPool"); - std::println("After vkCrateDescriptorPool"); // Creating viewport image vk::image_params viewport_params = { .extent = { .width = m_params.width, @@ -250,7 +251,7 @@ namespace atlas { m_color_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - + std::println("after transition image layout"); // Perform additional configurations for specific handles @@ -258,40 +259,51 @@ namespace atlas { .extent = { .width = m_params.width, .height = m_params.height }, .format = m_depth_format, - .memory_mask = m_physical->memory_properties(vk::memory_property::device_local_bit | vk::memory_property::host_visible_bit), + .memory_mask = m_physical->memory_properties( + vk::memory_property::device_local_bit | + vk::memory_property::host_visible_bit), .aspect = vk::image_aspect_flags::depth_bit, .usage = vk::image_usage::depth_stencil_bit, }; - m_viewport_depth_image = vk::sample_image(*m_device, viewport_depth_params); - std::println("After initializing m_viewport_depth_image"); + m_viewport_depth_image = + vk::sample_image(*m_device, viewport_depth_params); - if(m_viewport_image.sampler() == nullptr) { - std::println("sampler() = nullprt"); - } + transition_image_layout( + *m_device, + m_viewport_depth_image, + m_depth_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - if(m_viewport_image.image_view() == nullptr) { - std::println("image_view() = nullprt"); - } construct(p_window, p_image_count, p_queue); + + + // Offscreen texture to retrieve + g_viewport_image_id = + static_cast(ImGui_ImplVulkan_AddTexture( + m_viewport_image.sampler(), + m_viewport_image.image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); } + void image_memory_barrier( + const VkCommandBuffer& p_command, + VkImageLayout p_old, + VkImageLayout p_new, + uint32_t p_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT) { - void image_memory_barrier(const VkCommandBuffer& p_command, - VkFormat p_format, - VkImageLayout p_old, - VkImageLayout p_new, - uint32_t p_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT) { - - m_viewport_image.memory_barrier(p_command, p_format, p_old, p_new, p_aspect_mask); + m_viewport_image.memory_barrier( + p_command, m_color_format, p_old, p_new, p_aspect_mask); } - void depth_image_memory_barrier(const VkCommandBuffer& p_command, - VkFormat p_format, - VkImageLayout p_old, - VkImageLayout p_new, - uint32_t p_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT) { - - m_viewport_depth_image.memory_barrier(p_command, p_format, p_old, p_new, p_aspect_mask); + void depth_image_memory_barrier( + const VkCommandBuffer& p_command, + VkImageLayout p_old, + VkImageLayout p_new, + uint32_t p_aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT) { + + m_viewport_depth_image.memory_barrier( + p_command, m_depth_format, p_old, p_new, p_aspect_mask); } void construct(GLFWwindow* p_window, @@ -312,30 +324,25 @@ namespace atlas { init_info.UseDynamicRendering = true; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; + // const uint32_t color_format = + // static_cast(VK_FORMAT_B8G8R8A8_UNORM); const uint32_t color_format = static_cast(m_color_format); const uint32_t depth_format = static_cast(m_depth_format); + + std::span formats = + std::span(&color_format, 1); + init_info.PipelineRenderingCreateInfo = pipeline_rendering_info( std::span(&color_format, 1), depth_format, depth_format); ImGui_ImplVulkan_Init(&init_info); - - std::println("g_viewport_image_id constructed"); - // Offscreen texture to retrieve - g_viewport_image_id = - static_cast(ImGui_ImplVulkan_AddTexture( - m_viewport_image.sampler(), - m_viewport_image.image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - - std::println("After g_viewport_image_id constructed"); } void set_current_command(vk::command_buffer& p_command) { m_current_command = &p_command; } - [[nodiscard]] VkImageView color_image_view() const { return m_viewport_image.image_view(); } @@ -364,15 +371,16 @@ namespace atlas { } void destruct() { - ImGui_ImplVulkan_Shutdown(); - vkDestroyDescriptorPool(*m_device, m_descriptor_pool, nullptr); - - if(g_viewport_image_id != nullptr) { - VkDescriptorSet old_descriptor_set = reinterpret_cast(g_viewport_image_id); + if (g_viewport_image_id != nullptr) { + VkDescriptorSet old_descriptor_set = + reinterpret_cast(g_viewport_image_id); ImGui_ImplVulkan_RemoveTexture(old_descriptor_set); g_viewport_image_id = nullptr; } - + + ImGui_ImplVulkan_Shutdown(); + vkDestroyDescriptorPool(*m_device, m_descriptor_pool, nullptr); + m_viewport_image.destruct(); m_viewport_depth_image.destruct(); From 699fe45b1a1685af7d2ae8647829326e0fd8ac29 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 8 Jun 2026 14:05:21 -0700 Subject: [PATCH 052/106] refactor: undocking imgui works and updated imguidocking to 4.0 to fix the vulkan format assignment issue that it was faulting to format as undefined --- atlas/core/application.cppm | 12 ++---- atlas/drivers/vulkan/imgui_context.cppm | 57 +++++++------------------ conanfile.py | 2 +- 3 files changed, 19 insertions(+), 52 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 996efc11..18f002e8 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -268,13 +268,9 @@ export namespace atlas { m_render_context.set_command(current); - m_imgui_context->set_current_command(current); - m_imgui_context->image_memory_barrier( current, - // VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - // VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); m_imgui_context->depth_image_memory_barrier( @@ -338,10 +334,6 @@ export namespace atlas { current.end_rendering(); - // m_imgui_context->image_memory_barrier( - // current, - // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); m_imgui_context->image_memory_barrier( current, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, @@ -411,12 +403,14 @@ export namespace atlas { VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - // Performing Present Context Rendering current.end(); const VkCommandBuffer command = current; m_window->submit(std::span(&command, 1)); m_window->present(m_next_image_frame_idx); + + // Update platform window afterwards + m_imgui_context->update_platforms(); } } diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 85585eeb..29b21ce1 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -116,36 +116,12 @@ namespace atlas { } /** - * TODO List - * 0.) Initialize ImGui Context + Test ImGui Panel Undocking Beforehand - * 1.) Render offscreen texture - * 2.) Upload to imgui dockspace - * 3.) Retrieve viewport ID (which is a ImTextureID) - */ - - /** - * - * NOTE: There are a few things to remember: - * - * Actual TODOs that need to be done to get imgui back and working again for - * getting the viewport + dockspace running again: 0.) When performing - * off-screen rendering of the 3D screen. We are going to need to do - * begin_rendering/end_rendering for the viewport images. - * - Rather then using the specified begin rendering in the - * render_context - * - To get this to work we may need to strip out render_context - * begin_rendering/end_rendering outside of the begin/end APIs of - * render_context. 1.) Using imgui_contexts begin_rendering/end_rendering - * images. 2.) As we render those specific viewport images need to perform - * memory_barriers as well. 3.) Then once that is rendered. We will render - * the final imgui offscreen texture with the current command buffers to the - * swapchain for drawn to the screen. - * - * - * + * @brief Represents the context for rendering the UI-specific properties * + * This context is responsible to perform any configurations and rerouting + * of the underlying UI logic. */ - export ImTextureID g_viewport_image_id = nullptr; + export VkDescriptorSet g_viewport_image_id = nullptr; export class imgui_context { public: imgui_context() = delete; @@ -277,13 +253,11 @@ namespace atlas { construct(p_window, p_image_count, p_queue); - // Offscreen texture to retrieve - g_viewport_image_id = - static_cast(ImGui_ImplVulkan_AddTexture( - m_viewport_image.sampler(), - m_viewport_image.image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + g_viewport_image_id = ImGui_ImplVulkan_AddTexture( + m_viewport_image.sampler(), + m_viewport_image.image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } void image_memory_barrier( @@ -324,14 +298,9 @@ namespace atlas { init_info.UseDynamicRendering = true; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; - // const uint32_t color_format = - // static_cast(VK_FORMAT_B8G8R8A8_UNORM); const uint32_t color_format = static_cast(m_color_format); const uint32_t depth_format = static_cast(m_depth_format); - std::span formats = - std::span(&color_format, 1); - init_info.PipelineRenderingCreateInfo = pipeline_rendering_info( std::span(&color_format, 1), depth_format, @@ -362,19 +331,23 @@ namespace atlas { ImDrawData* draw_data = ImGui::GetDrawData(); ImGui_ImplVulkan_RenderDrawData(draw_data, *m_current_command); + } + void update_platforms() { ImGuiIO& io = ImGui::GetIO(); if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { + ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); + + vkDeviceWaitIdle(*m_device); } } void destruct() { if (g_viewport_image_id != nullptr) { - VkDescriptorSet old_descriptor_set = - reinterpret_cast(g_viewport_image_id); - ImGui_ImplVulkan_RemoveTexture(old_descriptor_set); + VkDescriptorSet old_descriptor = g_viewport_image_id; + ImGui_ImplVulkan_RemoveTexture(old_descriptor); g_viewport_image_id = nullptr; } diff --git a/conanfile.py b/conanfile.py index 07500927..c50b794e 100644 --- a/conanfile.py +++ b/conanfile.py @@ -32,7 +32,7 @@ def requirements(self): self.requires("joltphysics/5.2.0") if self.options.enable_shaderc: self.requires("shaderc/2025.3") - self.requires("imguidocking/3.0") + self.requires("imguidocking/4.0") self.requires("flecs/4.0.4") self.requires("glfw/3.4") self.requires("spdlog/1.16.0") From 0928231438ff73b4fd562db5a8ccfcd39fb0a0fb Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 8 Jun 2026 22:35:53 -0700 Subject: [PATCH 053/106] refactor: reworking the editor, migrating editor-level code into editor_world.cppm and fixed referencing to the UI logic to use the editor_world-layer logic --- atlas/core/application copy.cppm | 495 ------------------------------- atlas/core/application.cppm | 2 + editor/CMakeLists.txt | 2 +- editor/application.cpp | 10 +- editor/editor.cppm | 2 +- editor/editor_world.cppm | 201 ++++++++++++- editor/icon.cppm | 43 ++- editor/level_scene.cppm | 5 + 8 files changed, 235 insertions(+), 525 deletions(-) delete mode 100644 atlas/core/application copy.cppm diff --git a/atlas/core/application copy.cppm b/atlas/core/application copy.cppm deleted file mode 100644 index 58516e2c..00000000 --- a/atlas/core/application copy.cppm +++ /dev/null @@ -1,495 +0,0 @@ -module; - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#define GLM_ENABLE_EXPERIMENTAL -#include - -#include -#include -#include -#include - -export module atlas.application; - -import atlas.core.utilities; -import atlas.core.utilities.poll_state; -import atlas.core.event; -import vk; -import atlas.drivers.vulkan; - -import atlas.core.scene; -import atlas.core.scene.world; -import atlas.core.scene.components; -import atlas.core.math; - -export namespace atlas { - - /** - * @brief application properties settings for the window - */ - struct application_settings { - std::string name = "Undefined"; - uint32_t width = 0; - uint32_t height = 0; - glm::vec4 background_color = { 1.f, 0.5f, 0.5f, 1.f }; - }; - - class application { - public: - application() = default; - application(/*NOLINT*/ std::shared_ptr p_context, - const application_settings& p_params, - event::bus& p_bus) - : m_context(p_context) - , m_bus(&p_bus) { - m_instance = p_context->instance_handle(); - m_physical = p_context->physical_device(); - m_device = p_context->logical_device(); - - // Constructing the application - window_params params = { - .width = p_params.width, - .height = p_params.height, - .name = p_params.name, - }; - - // m_window = std::allocate_shared(, - // m_context->instance_handle(), params); - m_window = std::make_shared(p_context, params); - - m_aspect_ratio = static_cast(params.width) / static_cast(params.height); - event::set_window_size(m_window->glfw_window()); - - m_bus->create_listener(); - m_bus->create_listener(); - m_bus->create_listener(); - // m_bus->create_immediate_listener(); - // m_bus->create_immediate_listener(); - // m_bus->create_immediate_listener(); - - // Requesting depth format - std::array format_support = { - vk::format::d32_sfloat, - vk::format::d32_sfloat_s8_uint, - vk::format::d24_unorm_s8_uint - }; - - m_color_format = m_window->surface_properties().format.format; - // We provide a selection of format support that we want to check is - // supported on current hardware device. - m_depth_format = m_physical->request_depth_format(format_support); - - m_imgui_context = std::make_shared(p_context, - m_window->glfw_window(), - m_window->swapchain_handle(), - m_window->request_images().size(), - m_window->present_queue(), - m_color_format, - m_depth_format, - params); - - // Initializing command buffers - std::span images = m_window->request_images(); - - m_images.resize(images.size()); - m_depth_images.resize(images.size()); - - for (uint32_t i = 0; i < m_images.size(); i++) { - vk::image_params color_img_params = { - .extent = { - .width = m_window->extent().width, - .height = m_window->extent().height, - }, - .format = m_window->surface_properties().format.format, - .memory_mask = m_physical->memory_properties( - vk::memory_property::device_local_bit), - .aspect = vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::color_attachment_bit, - .mip_levels = 1, - .layer_count = 1, - }; - m_images[i] = - vk::sample_image(*m_device, images[i], color_img_params); - - vk::image_params depth_img_params = { - .extent = { - .width = m_window->extent().width, - .height = m_window->extent().height, - }, - .format = m_depth_format, - .memory_mask = m_physical->memory_properties( - vk::memory_property::device_local_bit), - .aspect = vk::image_aspect_flags::depth_bit, - .usage = vk::image_usage::depth_stencil_bit, - .mip_levels = 1, - .layer_count = 1, - }; - - m_depth_images[i] = - vk::sample_image(*m_device, depth_img_params); - } - - m_command_buffers.resize(images.size()); - - for (uint32_t i = 0; i < m_command_buffers.size(); i++) { - vk::command_params command_params = { - .levels = vk::command_levels::primary, - .queue_index = 0, - .flags = vk::command_pool_flags::reset, - }; - m_command_buffers[i] = - vk::command_buffer(*m_device, command_params); - } - - m_render_context = - render_context(m_context, m_color_format, m_depth_format); - - std::println("images.size() = {}", images.size()); - - m_window->center_window(); - - // m_bus->trigger(this, - // &application::on_scene_transition); - } - - void execute() { - VkClearValue clear_color = { - { { 0.f, 0.5f, 0.5f, 1.f } }, - }; - - VkClearValue depth_value = { - .depthStencil = { .depth = 1.f, .stencil = 0 }, - }; - - m_current_scene = m_world->current(); - - // Handling camera system execution - m_current_scene - ->system, - transform, - perspective_camera>() - .each([this](flecs::pair p_pair, - transform& p_transform, - perspective_camera& p_camera) { - if (!p_camera.is_active) { - return; - } - - p_pair->projection = glm::mat4(1.f); - - p_pair->projection = - glm::perspective(glm::radians(p_camera.field_of_view), - m_aspect_ratio, - p_camera.plane.x, - p_camera.plane.y); - p_pair->projection[1][1] *= -1; - p_pair->view = glm::mat4(1.f); - - // This is converting a glm::highp_vec4 to a glm::quat - glm::quat quaternion = to_quat(p_transform.quaternion); - - p_pair->view = - glm::translate(p_pair->view, p_transform.position) * - glm::mat4_cast(quaternion); - - p_pair->view = glm::inverse(p_pair->view); - }); - - // Setting the current scene for the renderer to start rendering the - // objects - m_render_context.current_scene(*m_current_scene); - - auto start_time = std::chrono::high_resolution_clock::now(); - invoke_start(m_current_scene.get()); - - // Querying editor cameras specific objects - // Then using this to execute specific main cameras. - auto query_camera_objects = - m_current_scene - ->query_builder, - perspective_camera>() - .build(); - - m_render_context.prebake(); - - while (m_window->available()) { - auto current_time = std::chrono::high_resolution_clock::now(); - m_delta_time = - std::chrono::duration( - current_time - start_time) - .count(); - - start_time = current_time; - event::flush_events(); - - // Progresses the flecs::world by one tick (or replaced with - // using the delta time) This also invokes the following - // system call before the mainloop - m_current_scene->progress(m_delta_time); - - m_next_image_frame_idx = m_window->acquire_next_frame(); - - vk::command_buffer current = - m_command_buffers[m_next_image_frame_idx]; - - invoke_physics_update(m_current_scene.get()); - - invoke_on_update(m_current_scene.get(), m_delta_time); - - // We want this to be called after late update - // This queries all camera objects within the camera system - // TODO: Should consider changing this from - // using tags in flecs for specifying active cameras. - query_camera_objects.each( - [&](flecs::entity, - flecs::pair p_pair, - perspective_camera& p_camera) { - if (!p_camera.is_active) { - return; - } - - m_projection = p_pair->projection; - m_view = p_pair->view; - }); - - current.begin(vk::command_usage::simulatneous_use_bit); - - m_render_context.set_command(current); - - m_imgui_context->set_current_command(current); - - /** - * NOTE: For getting imgui_context - * - * Using viewport images instead of swapchain images. - * - * These swapchain images will be used as soon the 3D scene is rendered to the imgui viewport images. - */ - - // m_images[m_next_image_frame_idx].memory_barrier( - m_imgui_context->image_memory_barrier( - current, - m_color_format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_ASPECT_COLOR_BIT); - - // m_depth_images[m_next_image_frame_idx].memory_barrier( - m_imgui_context->depth_image_memory_barrier( - current, - m_depth_format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_ASPECT_DEPTH_BIT); - - vk::rendering_attachment ui_color_render_attachment = { - .image_view = m_imgui_context->color_image_view(), - .layout = vk::image_layout::color_optimal, - .resolve_mode = vk::resolved_mode_flags::none, - .resolve_image_view = nullptr, - .resolve_image_layout = vk::image_layout::undefined, - .load = vk::attachment_load::clear, - .store = vk::attachment_store::store, - .clear_values = clear_color - }; - - vk::rendering_attachment ui_depth_stencil_attachment = { - .image_view = m_imgui_context->depth_image_view(), - .layout = vk::image_layout::depth_stencil_optimal, - .resolve_mode = vk::resolved_mode_flags::none, - .resolve_image_view = nullptr, - .resolve_image_layout = vk::image_layout::undefined, - .load = vk::attachment_load::clear, - .store = vk::attachment_store::store, - .depth_values = depth_value - }; - - // presenting rendering attachments - vk::rendering_attachment present_color_render_attachment = { - .image_view = m_images[m_next_image_frame_idx].image_view(), - .layout = vk::image_layout::color_optimal, - .resolve_mode = vk::resolved_mode_flags::none, - .resolve_image_view = nullptr, - .resolve_image_layout = vk::image_layout::undefined, - .load = vk::attachment_load::clear, - .store = vk::attachment_store::store, - .clear_values = clear_color - }; - - vk::rendering_attachment present_depth_stencil_attachment = { - .image_view = - m_depth_images[m_next_image_frame_idx].image_view(), - .layout = vk::image_layout::depth_stencil_optimal, - .resolve_mode = vk::resolved_mode_flags::none, - .resolve_image_view = nullptr, - .resolve_image_layout = vk::image_layout::undefined, - .load = vk::attachment_load::clear, - .store = vk::attachment_store::store, - .depth_values = depth_value - }; - - vk::rendering_begin_parameters ui_begin_params = { - .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, - .layer_count = 1, - .color_attachments = std::span( - &ui_color_render_attachment, 1), - .depth_attachment = ui_depth_stencil_attachment, - .stencil_attachment = ui_depth_stencil_attachment, - }; - - vk::viewport_params viewport = { - .x = 0.0f, - .y = 0.0f, - .width = static_cast(m_window->extent().width), - .height = static_cast(m_window->extent().height), - .min_depth = 0.0f, - .max_depth = 1.0f, - }; - current.set_viewport(0, 1, std::span(&viewport, 1)); - - vk::scissor_params scissor = { - .offset = { 0, 0 }, - .extent = {static_cast(m_window->extent().width), static_cast(m_window->extent().height)}, - }; - current.set_scissor(0, 1, std::span(&scissor, 1)); - - current.begin_rendering(ui_begin_params); - - m_render_context.begin(m_projection, m_view); - - m_render_context.end(); - current.end_rendering(); - - m_imgui_context->image_memory_barrier( - current, - m_color_format, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_IMAGE_ASPECT_COLOR_BIT - ); - - // Performing Present Context Rendering - - m_images[m_next_image_frame_idx].memory_barrier( - current, - // m_window->surface_properties().format.format, - m_color_format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - m_depth_images[m_next_image_frame_idx].memory_barrier( - current, - m_depth_format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - - vk::rendering_begin_parameters begin_params = { - .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, - .layer_count = 1, - .color_attachments = std::span( - &present_color_render_attachment, 1), - .depth_attachment = present_depth_stencil_attachment, - .stencil_attachment = present_depth_stencil_attachment, - }; - current.begin_rendering(begin_params); - m_imgui_context->begin(); - invoke_ui_update(m_current_scene.get()); - m_imgui_context->end(); - - current.end_rendering(); - m_images[m_next_image_frame_idx].memory_barrier( - current, - m_window->surface_properties().format.format, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - - // m_images[m_next_image_frame_idx].memory_barrier( - current.end(); - - const VkCommandBuffer command = current; - m_window->submit(std::span(&command, 1)); - m_window->present(m_next_image_frame_idx); - } - } - - // Experimental: Will look into later once we dive into scene - // transitioning void on_scene_transition(event::scene_transition& - // p_scene_transition) { - // m_world->current(p_scene_transition.next_scene); - // std::println("Attempting to switch to the scene: {}", - // p_scene_transition.next_scene); - - // // We only want to set the current scene if that specific scene - // is valid if(m_world->current() != nullptr) { - // m_current_scene = m_world->current(); - // m_render_context.current_scene(*m_current_scene); - // } - // } - - void post_destroy() { - m_imgui_context->destruct(); - m_render_context.destruct(); - - for (auto& command : m_command_buffers) { - command.destruct(); - } - - for (auto& color_image : m_images) { - color_image.destruct(); - } - - for (auto& depth_image : m_depth_images) { - depth_image.destruct(); - } - m_window->destruct(); - m_device->destruct(); - } - - void current_world(std::shared_ptr p_world) { - m_world = std::move(p_world); - } - - private: - float m_aspect_ratio=0.f; - uint32_t m_next_image_frame_idx = 0; - VkFormat m_color_format; - VkFormat m_depth_format; - std::shared_ptr m_context; - std::shared_ptr m_window = nullptr; - event::bus* m_bus = nullptr; - glm::mat4 m_view = glm::mat4(1.f); - glm::mat4 m_projection = glm::mat4(1.f); - - render_context m_render_context; - - std::shared_ptr m_world; - - std::shared_ptr m_imgui_context; - std::shared_ptr m_current_scene = nullptr; - - // vulkan-cpp specific handles - vk::instance m_instance; - std::optional m_physical; - std::shared_ptr m_device; - std::vector m_images; - std::vector m_depth_images; - std::vector m_command_buffers; - float m_delta_time = 0.f; - static application* s_instance; - }; - - application* application::s_instance = nullptr; -}; \ No newline at end of file diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 18f002e8..58eed504 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -392,6 +392,8 @@ export namespace atlas { current.begin_rendering(present_begin_params); m_imgui_context->begin(); m_imgui_context->set_current_command(current); + + invoke_ui_update(m_world.get()); invoke_ui_update(m_current_scene.get()); m_imgui_context->end(); current.end_rendering(); diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 8e82a0a6..29d13099 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -13,7 +13,7 @@ target_sources(editor PUBLIC level_scene.cppm level_scene2.cppm # content_browser_panel.cppm - # icon.cppm + icon.cppm # utilities.cppm ) diff --git a/editor/application.cpp b/editor/application.cpp index 3e7adf7e..3de3d8f5 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -14,14 +14,20 @@ class editor_application : public atlas::application { editor_application(/*NOLINT*/std::shared_ptr p_context, const atlas::application_settings& p_settings, atlas::event::bus& p_bus) - : atlas::application(std::move(p_context), p_settings, p_bus) { + : atlas::application(p_context, p_settings, p_bus) { m_world = - std::make_shared("Editor World", p_bus, m_stream); + std::make_shared(p_context, "Editor World", p_bus, m_stream); current_world(m_world); } + + // ~editor_application() { + // m_world->destruct(); + // } + ~editor_application() = default; + private: std::shared_ptr m_world; atlas::level_streamer m_stream; diff --git a/editor/editor.cppm b/editor/editor.cppm index 3fd24b78..813455f2 100644 --- a/editor/editor.cppm +++ b/editor/editor.cppm @@ -6,6 +6,6 @@ export module editor; export import :world; export import :level_scene; // export import :level_scene2; -// export import :icon; +export import :icon; // export import :content_browser; // export import :utilities; \ No newline at end of file diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 6cf55311..1c9071ef 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -3,6 +3,15 @@ module; #include #include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +#include +#include +#include + export module editor:world; import atlas.core.utilities; @@ -13,19 +22,26 @@ import atlas.core.scene.uuid; import atlas.core.level_streamer; import atlas.core.scene; import :level_scene; +import :icon; // import :level_scene2; -// import atlas.core.event; + +import atlas.core.editor.dockspace; +import atlas.core.editor.menu_item; +import vk; + +enum scene_runtime : uint8_t { edit, play }; /** * @brief editor_world is where a lot of the editor logic will be handled */ export class editor_world final : public atlas::world { public: - editor_world(const std::string& p_tag, + editor_world(/*NOLINT*/ std::shared_ptr p_context, + const std::string& p_tag, atlas::event::bus& p_bus, atlas::level_streamer& p_level_streamer) : atlas::world(p_tag, p_level_streamer) { - + m_device = p_context->logical_device(); // Create defualt scene to level streamer // Does polymorphic allocations for these customized scenes default_custom_scene("LevelScene", p_bus); @@ -36,8 +52,187 @@ public: // Set what our current scene is // TODO: Probably have `default_custom_scene() set this current("LevelScene"); + + m_current_scene = this->current(); + + m_editor_dockspace.fullscreen(false); + m_editor_dockspace.dockspace_open(true); + + std::println("Before loading play and stop icons!"); + // Initializing icon. + m_play_icon = + ui::experimental::icon(m_device, + p_context->physical_device().memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + "assets/icons/PlayButton.png"); + + if(!m_play_icon.loaded()) { + std::println("m_play_icon not loaded!"); + } + + m_stop_icon = + ui::experimental::icon(m_device, + p_context->physical_device().memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + "assets/icons/StopButton.png"); + + + if(!m_stop_icon.loaded()) { + std::println("m_stop_icon not loaded!"); + } + + atlas::register_ui(this, &editor_world::ui_update); } ~editor_world() override = default; + void ui_update() { + // setting up the dockspace UI widgets at the window toolbar + if (m_editor_dockspace.begin()) { + m_editor_menu.begin(); + + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("Save")) { + // m_deserializer_test.save("LevelScene"); + } + + ImGui::Separator(); + + if (ImGui::MenuItem("Exit")) { + // glfwSetWindowShouldClose(atlas::application::close(), + // true); + } + + ImGui::EndMenu(); + } + m_editor_menu.end(); + + ImGuiID dockspace_id = ImGui::GetID("Dockspace Demo"); + ImGui::SetNextWindowDockID(dockspace_id, ImGuiCond_FirstUseEver); + if (ImGui::Begin("Viewport")) { + ImVec2 viewport_size = ImGui::GetContentRegionAvail(); + // ImGui::Image(m_viewport_image_id, + // {static_cast(m_extent.width), + // static_cast(m_extent.height)}); + if (atlas::g_viewport_image_id == nullptr) { + console_log_error("atlas::vulkan::g_viewport_image_id is " + "nullptr!!!!!!!!!!!!!!!!!!!"); + } + ImGui::Image(atlas::g_viewport_image_id, viewport_size); + ImGui::End(); + } + + scene_heirarchy_panel(); + + properties_panel(); + + materials_editor_panel(); + + content_browser_panel(); + + ui_toolbar(); + + m_editor_dockspace.end(); + } + } + + void scene_heirarchy_panel() { + if (ImGui::Begin("Scene Heirarchy")) { + ImGui::End(); + } + } + + void properties_panel() { + if (ImGui::Begin("Properties")) { + ImGui::End(); + } + } + + void materials_editor_panel() { + if (ImGui::Begin("Material Editor")) { + ImGui::End(); + } + } + + void content_browser_panel() { + if (ImGui::Begin("Content Browser")) { + ImGui::End(); + } + } + + void ui_toolbar() { + ImGui::PushStyleVar( + ImGuiStyleVar_WindowPadding, + ImVec2(0, 2)); // @note ImVec making button not touch bottom + ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2(0, 2)); + ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); + + auto& color = ImGui::GetStyle().Colors; + auto& button_hovered = color[ImGuiCol_ButtonHovered]; + auto& button_active = color[ImGuiCol_ButtonActive]; + ImGui::PushStyleColor( + ImGuiCol_ButtonHovered, + ImVec4(button_hovered.x, button_hovered.y, button_hovered.z, 0.5f)); + ImGui::PushStyleColor( + ImGuiCol_ButtonHovered, + ImVec4(button_active.x, button_active.y, button_active.z, 0.5f)); + + float button_size = 20.0f; + // if(ImGui::Begin("##toolbox")) { + // ImGui::End(); + // } + + if(ImGui::Begin("##toolbox")) { + VkDescriptorSet button_id = (m_scene_state == scene_runtime::edit) + ? m_play_icon.texture_id() + : m_stop_icon.texture_id(); + + /** + * @note GetWindowContentRegionMax().x is how much space is there for + * content (widgets) + * @note 0.5f is the offset for padding. + * @note takes button size and halves it and makes the offset the center + * of that tab. (centering buttons) + */ + ImGui::SameLine((ImGui::GetWindowContentRegionMax().x * 0.5f) - + (button_size * 0.5f)); + + if (ImGui::ImageButton("##Button", + button_id, + ImVec2{ button_size, button_size }, + ImVec2(0, 0), + ImVec2(1, 1))) { + if (m_scene_state == scene_runtime::edit) { + m_scene_state = scene_runtime::play; + // m_physics_engine.start(); + } + else if (m_scene_state == scene_runtime::play) { + m_scene_state = scene_runtime::edit; + // m_physics_engine.stop(); + // reset_objects(); + } + } + + ImGui::PopStyleVar(2); + ImGui::PopStyleColor(3); + ImGui::End(); + } + } + + + void destruct() { + m_play_icon.destroy(); + m_stop_icon.destroy(); + } + +private: + std::shared_ptr m_device; + scene_runtime m_scene_state = scene_runtime::edit; + std::shared_ptr m_current_scene; + atlas::ui::dockspace m_editor_dockspace; + atlas::ui::menu_item m_editor_menu; + ui::experimental::icon m_play_icon; + ui::experimental::icon m_stop_icon; }; \ No newline at end of file diff --git a/editor/icon.cppm b/editor/icon.cppm index 3c509697..4d381291 100644 --- a/editor/icon.cppm +++ b/editor/icon.cppm @@ -10,9 +10,8 @@ module; export module editor:icon; import atlas.core.utilities; -import atlas.drivers.vulkan.physical_device; -import atlas.drivers.vulkan.stb_image; import vk; +import atlas.drivers.vulkan.stb_image; export namespace ui::experimental { /** @@ -25,13 +24,10 @@ export namespace ui::experimental { class icon { public: icon() = default; - icon(const VkDevice& p_device, + icon(/*NOLINT*/std::shared_ptr p_device, uint32_t p_memory_properties, const std::filesystem::path& p_filename) { - // vk::texture_info config_texture = { - // .phsyical_memory_properties = p_memory_properties, - // .filepath = p_filename - // }; + /*NOLINT*/m_device = p_device; vk::texture_params config_texture = { // .memory_mask = physical_device.memory_properties( // vk::memory_property::host_visible_bit | @@ -39,48 +35,49 @@ export namespace ui::experimental { .memory_mask = p_memory_properties, }; - atlas::vulkan::stb_image image(p_filename.string(), config_texture); - m_icon_image = vk::texture(p_device, &image, config_texture); - if (!m_icon_image.loaded()) { - console_log_info("Play Button Could not be loaded!!"); - } + atlas::stb_image image(p_filename.string(), config_texture); + m_icon_image = vk::texture(*m_device, &image, config_texture); m_extent = image.extent(); m_icon_image_id = - static_cast(ImGui_ImplVulkan_AddTexture( + ImGui_ImplVulkan_AddTexture( m_icon_image.image().sampler(), m_icon_image.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } - icon(const VkDevice& p_device, + icon(/*NOLINT*/std::shared_ptr p_device, uint32_t p_memory_properties, const vk::image_extent& p_extent, std::span p_data) { + /*NOLINT*/ m_device = p_device; m_extent = p_extent; - m_icon_image = vk::texture(p_device, p_extent, p_data, p_memory_properties); + m_icon_image = vk::texture(*m_device, p_extent, p_data, p_memory_properties); m_icon_image_id = - static_cast(ImGui_ImplVulkan_AddTexture( + ImGui_ImplVulkan_AddTexture( m_icon_image.image().sampler(), m_icon_image.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } - ~icon() { - // implicitly destroy - // destroy(); + ~icon() = default; + + + [[nodiscard]] bool loaded() const { + return m_icon_image.loaded(); } [[nodiscard]] uint32_t width() const { return m_extent.width; } [[nodiscard]] uint32_t height() const { return m_extent.height; } - [[nodiscard]] ImTextureID texture_id() const { return m_icon_image_id; } + [[nodiscard]] VkDescriptorSet texture_id() const { return m_icon_image_id; } void destroy() { m_icon_image.destruct(); } private: + std::shared_ptr m_device; vk::image_extent m_extent{}; vk::texture m_icon_image; - ImTextureID m_icon_image_id; + VkDescriptorSet m_icon_image_id; }; }; \ No newline at end of file diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 52686da3..4beeda82 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -24,6 +24,8 @@ import atlas.core.scene.components; import atlas.core.utilities; import atlas.core.math; +import atlas.drivers.vulkan; + export class level_scene final : public atlas::scene { public: level_scene(const std::string& p_name, atlas::event::bus& p_bus) @@ -88,6 +90,7 @@ public: atlas::register_start(this, &level_scene::start); atlas::register_physics(this, &level_scene::physics_update); atlas::register_update(this, &level_scene::on_update); + atlas::register_ui(this, &level_scene::ui_update); } ~level_scene() override = default; @@ -175,6 +178,8 @@ public: // fixed-update framerate void physics_update() {} + void ui_update() { + } private: std::optional m_editor_camera; float m_movement_speed = 10.f; From 022d112bae395e76f574327e22af93c9b4a15da5 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Mon, 8 Jun 2026 23:08:54 -0700 Subject: [PATCH 054/106] refactor: re-added some of the editor-specific UI panels for the object properties, scene heirarchy, and material editor panels --- atlas/core/application.cppm | 3 + editor/CMakeLists.txt | 2 +- editor/editor_world.cppm | 240 +++++++++++++++++++++++++++++++++++- 3 files changed, 240 insertions(+), 5 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 58eed504..b877a5a2 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -212,6 +212,7 @@ export namespace atlas { m_render_context.current_scene(*m_current_scene); auto start_time = std::chrono::high_resolution_clock::now(); + invoke_start(m_world.get()); invoke_start(m_current_scene.get()); // Querying editor cameras specific objects @@ -244,8 +245,10 @@ export namespace atlas { vk::command_buffer current = m_command_buffers[m_next_image_frame_idx]; + invoke_physics_update(m_world.get()); invoke_physics_update(m_current_scene.get()); + invoke_on_update(m_world.get(), m_delta_time); invoke_on_update(m_current_scene.get(), m_delta_time); // We want this to be called after late update diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 29d13099..85ea1a12 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -14,7 +14,7 @@ target_sources(editor PUBLIC level_scene2.cppm # content_browser_panel.cppm icon.cppm - # utilities.cppm + utilities.cppm ) find_package(glfw3 REQUIRED) diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 1c9071ef..f32752be 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -11,6 +11,8 @@ module; #include #include #include +#include +#include export module editor:world; @@ -21,8 +23,13 @@ import atlas.drivers.renderer_system; import atlas.core.scene.uuid; import atlas.core.level_streamer; import atlas.core.scene; +import atlas.core.ui.widgets; + +import atlas.core.ui.widgets.imgui_stdlib; + import :level_scene; import :icon; +import :utilities; // import :level_scene2; import atlas.core.editor.dockspace; @@ -59,12 +66,13 @@ public: m_editor_dockspace.dockspace_open(true); std::println("Before loading play and stop icons!"); + + m_host_bit = p_context->physical_device().memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit); // Initializing icon. m_play_icon = - ui::experimental::icon(m_device, - p_context->physical_device().memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), + ui::experimental::icon(m_device, m_host_bit, "assets/icons/PlayButton.png"); if(!m_play_icon.loaded()) { @@ -140,12 +148,232 @@ public: void scene_heirarchy_panel() { if (ImGui::Begin("Scene Heirarchy")) { + + auto query_all_transforms = m_current_scene->query_builder().build(); + + query_all_transforms.each([&](flecs::entity p_entity, atlas::transform&){ + // We set the imgui flags for our scene heirarchy panel + // TODO -- Make the scene heirarchy panel a separate class that + // is used for specify the layout and other UI elements here + ImGuiTreeNodeFlags flags = + ((m_selected_entity == p_entity) ? ImGuiTreeNodeFlags_Selected + : 0) | + ImGuiTreeNodeFlags_OpenOnArrow; + flags |= ImGuiTreeNodeFlags_SpanAvailWidth; + flags |= ImGuiWindowFlags_Popup; + flags |= ImGuiTreeNodeFlags_AllowItemOverlap; + + bool opened = ImGui::TreeNodeEx(p_entity.name().c_str(), flags); + + if (ImGui::IsItemClicked()) { + m_selected_entity = p_entity; + } + + bool delete_entity = false; + if (ImGui::BeginPopupContextItem()) { + if (ImGui::MenuItem("Delete Entity")) { + delete_entity = true; + } + ImGui::EndPopup(); + } + + if (delete_entity) { + m_selected_entity.destruct(); + } + + ImGui::SameLine(); + ImGui::TextDisabled("(%llu)", p_entity.id()); + + if (opened) { + flags = ImGuiTreeNodeFlags_OpenOnArrow | + ImGuiTreeNodeFlags_SpanAvailWidth; + auto query_children_builder = + m_current_scene->query_builder() + .with(flecs::ChildOf, p_entity) + .build(); + int32_t child_count = query_children_builder.count(); + + // // Only show children in scene heirarchy panel if there + // are children entities + if (child_count > 0) { + m_selected_entity.children([&](flecs::entity p_child) { + opened = + ImGui::TreeNodeEx(p_child.name().c_str(), flags); + if (opened) { + if (ImGui::IsItemClicked()) { + m_selected_entity = p_child; + } + ImGui::TreePop(); + } + }); + } + + ImGui::TreePop(); + } + }); + ImGui::End(); } } void properties_panel() { if (ImGui::Begin("Properties")) { + if (m_selected_entity.is_alive()) { + ui_component_list(m_selected_entity); + + atlas::ui::draw_component( + "transform", + m_selected_entity, + [](atlas::transform* p_transform) { + atlas::ui::draw_vec3("Position", p_transform->position); + atlas::ui::draw_vec3("Scale", p_transform->scale); + atlas::ui::draw_vec3("Rotation", p_transform->rotation); + }); + + atlas::ui::draw_component( + "camera", + m_selected_entity, + [this](atlas::perspective_camera* p_camera) { + atlas::ui::draw_float("field of view", + p_camera->field_of_view); + ImGui::Checkbox("is_active", &p_camera->is_active); + ImGui::DragFloat("Speed", &m_movement_speed); + }); + + atlas::ui::draw_component( + "atlas::mesh_source", + m_selected_entity, + [](atlas::mesh_source* p_source) { + // if (ImGui::InputText( + // "Input Label", + // &p_source->model_path, + // ImGuiInputTextFlags_EnterReturnsTrue)) { + // console_log_info("mesh_src = {}", + // p_source->model_path); + // // atlas::event::mesh_reload reload_request = { + // // .entity_id = m_selected_entity.id(), + // // .filename = p_source->model_path, + // // }; + + // // if (std::filesystem::exists(p_source->model_path)) { + // // signal(reload_request); + // // } + // } + atlas::ui::draw_vec4("Color", p_source->color); + + // if (ImGui::Button("Reload Material")) { + // atlas::event::material_reload + // // reload_material_request = { + // // .entity_id = m_selected_entity.id(), + // // .diffuse = "assets/models/viking_room.png", + // // .specular = "", + // // }; + + // // signal(reload_material_request); + // } + }); + + atlas::ui::draw_component( + "Point Light", + m_selected_entity, + [](atlas::point_light* p_dir_light) { + ImGui::DragFloat4( + "Color", glm::value_ptr(p_dir_light->color), 0.01); + ImGui::DragFloat( + "Attenuation", &p_dir_light->attenuation, 0.001); + ImGui::DragFloat4( + "Ambient", glm::value_ptr(p_dir_light->ambient), 0.01); + ImGui::DragFloat4( + "Diffuse", glm::value_ptr(p_dir_light->diffuse), 0.01); + ImGui::DragFloat4("Specular", + glm::value_ptr(p_dir_light->specular), + 0.01); + ImGui::DragFloat( + "Constant", &p_dir_light->constant, 0.01); + ImGui::DragFloat("Linear", &p_dir_light->linear, 0.01); + ImGui::DragFloat( + "Quadratic", &p_dir_light->quadratic, 0.01); + }); + + atlas::ui::draw_component( + "Physics Body", + m_selected_entity, + [](atlas::physics_body* p_body) { + std::array items = { + "Static", + "Kinematic", + "Dynamic", + }; + std::string combo_preview = + items[p_body->body_movement_type]; + + // Begin the combo box + if (ImGui::BeginCombo("Body Type", + combo_preview.data())) { + for (int n = 0; n < 3; n++) { + // Check if the current item is selected + const bool is_selected = + (p_body->body_movement_type == n); + if (ImGui::Selectable(items[n].data(), + is_selected)) { + // Update the current type when a new item is + // selected + p_body->body_movement_type = + static_cast(n); + } + + // Set the initial focus when the combo box is + // first opened + if (is_selected) { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndCombo(); + } + + // physics body parameters + atlas::ui::draw_vec3("Linear Velocity", + p_body->linear_velocity); + atlas::ui::draw_vec3("Angular Velocity", + p_body->angular_velocity); + atlas::ui::draw_vec3("Force", p_body->force); + atlas::ui::draw_vec3("Impulse", p_body->impulse); + atlas::ui::draw_vec3("Torque", p_body->torque); + atlas::ui::draw_vec3("Center Mass", + p_body->center_mass_position); + }); + + atlas::ui::draw_component( + "Box Collider", + m_selected_entity, + [](atlas::box_collider* p_collider) { + atlas::ui::draw_vec3("Half Extent", + p_collider->half_extent); + }); + + atlas::ui::draw_component( + "Box Collider", + m_selected_entity, + [](atlas::sphere_collider* p_collider) { + atlas::ui::draw_float("Radius", p_collider->radius); + }); + + atlas::ui::draw_component( + "Box Collider", + m_selected_entity, + [](atlas::capsule_collider* p_collider) { + atlas::ui::draw_float("Half Height", + p_collider->half_height); + atlas::ui::draw_float("Radius", p_collider->radius); + }); + + atlas::ui::draw_component( + "Serialize", + m_selected_entity, + [](atlas::tag::serialize* p_serialize) { + ImGui::Checkbox("Enable", &p_serialize->enable); + }); + } ImGui::End(); } } @@ -228,6 +456,10 @@ public: } private: + // Bit for setting vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit + uint32_t m_host_bit = 0; + float m_movement_speed = 10.f; + flecs::entity m_selected_entity; std::shared_ptr m_device; scene_runtime m_scene_state = scene_runtime::edit; std::shared_ptr m_current_scene; From 1b4be3a337b3bf21bd5fff1ad15a2c24d4363008 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 9 Jun 2026 00:08:13 -0700 Subject: [PATCH 055/106] refactor: removed redundant calculations of the projection multiplies by -1, since already calculated --- atlas/drivers/vulkan/render_context.cppm | 1 - 1 file changed, 1 deletion(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 2e11d027..7d49e913 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -330,7 +330,6 @@ export namespace atlas { .view = p_view, .proj = p_proj, }; - scene_ubo.proj[1][1] *= -1; m_scene_uniforms.transfer(std::span(&scene_ubo, 1)); From ffbf6ddfb75eb690a189584706a903440ca0ef17 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 9 Jun 2026 00:44:44 -0700 Subject: [PATCH 056/106] refactor: fix the editor for running physics simulation --- editor/editor_world.cppm | 50 ++++++++++++++++++++++++++++++++-------- editor/level_scene.cppm | 35 +++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 16 deletions(-) diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index f32752be..fbe5b4ae 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -24,7 +24,7 @@ import atlas.core.scene.uuid; import atlas.core.level_streamer; import atlas.core.scene; import atlas.core.ui.widgets; - +import atlas.physics.engine; import atlas.core.ui.widgets.imgui_stdlib; import :level_scene; @@ -34,6 +34,8 @@ import :utilities; import atlas.core.editor.dockspace; import atlas.core.editor.menu_item; +import atlas.core.serialize; +import atlas.physics.engine; import vk; enum scene_runtime : uint8_t { edit, play }; @@ -47,7 +49,7 @@ public: const std::string& p_tag, atlas::event::bus& p_bus, atlas::level_streamer& p_level_streamer) - : atlas::world(p_tag, p_level_streamer) { + : atlas::world(p_tag, p_level_streamer), m_bus(&p_bus) { m_device = p_context->logical_device(); // Create defualt scene to level streamer // Does polymorphic allocations for these customized scenes @@ -65,8 +67,6 @@ public: m_editor_dockspace.fullscreen(false); m_editor_dockspace.dockspace_open(true); - std::println("Before loading play and stop icons!"); - m_host_bit = p_context->physical_device().memory_properties( vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit); @@ -91,11 +91,29 @@ public: std::println("m_stop_icon not loaded!"); } + atlas::register_start(this, &editor_world::preload_assets); + atlas::register_update(this, &editor_world::update); + atlas::register_physics(this, &editor_world::physics_update); atlas::register_ui(this, &editor_world::ui_update); } ~editor_world() override = default; + + void preload_assets() { + // m_deserializer_test = atlas::serializer(); + + // if (!m_deserializer_test.load("LevelScene-small", *m_current_scene)) { + // console_log_error("Could not load yaml file LevelScene!!!"); + // } + + m_physics_engine = atlas::physics::engine(*m_current_scene, *m_bus); + } + + void update(float p_delta_time) { + m_delta_time = p_delta_time; + } + void ui_update() { // setting up the dockspace UI widgets at the window toolbar if (m_editor_dockspace.begin()) { @@ -148,7 +166,8 @@ public: void scene_heirarchy_panel() { if (ImGui::Begin("Scene Heirarchy")) { - + m_current_scene->defer_begin(); + auto query_all_transforms = m_current_scene->query_builder().build(); query_all_transforms.each([&](flecs::entity p_entity, atlas::transform&){ @@ -212,6 +231,9 @@ public: } }); + + m_current_scene->defer_end(); + ImGui::End(); } } @@ -304,12 +326,10 @@ public: "Kinematic", "Dynamic", }; - std::string combo_preview = - items[p_body->body_movement_type]; // Begin the combo box if (ImGui::BeginCombo("Body Type", - combo_preview.data())) { + items[p_body->body_movement_type].data())) { for (int n = 0; n < 3; n++) { // Check if the current item is selected const bool is_selected = @@ -434,11 +454,11 @@ public: ImVec2(1, 1))) { if (m_scene_state == scene_runtime::edit) { m_scene_state = scene_runtime::play; - // m_physics_engine.start(); + m_physics_engine.start(); } else if (m_scene_state == scene_runtime::play) { m_scene_state = scene_runtime::edit; - // m_physics_engine.stop(); + m_physics_engine.stop(); // reset_objects(); } } @@ -449,6 +469,12 @@ public: } } + void physics_update() { + if (m_scene_state == scene_runtime::play) { + m_physics_engine.update(m_delta_time); + } + } + void destruct() { m_play_icon.destroy(); @@ -456,6 +482,10 @@ public: } private: + atlas::event::bus* m_bus=nullptr; + float m_delta_time; + atlas::physics::engine m_physics_engine; + atlas::serializer m_deserializer_test; // Bit for setting vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit uint32_t m_host_bit = 0; float m_movement_speed = 10.f; diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 4beeda82..e1a42eee 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -56,16 +56,29 @@ public: viking_room.set({ .model_path = "assets/models/viking_room.obj", .diffuse = "assets/models/viking_room.png", - // .model_path = "assets/models/cube.obj", - // .diffuse = "assets/models/container_diffuse.png", - // .diffuse = "assets/models/container_specular.png", + }); + + atlas::game_object platform = entity("Platform"); + + platform.set({ + .scale = { 15.f, 0.30f, 10.0f }, + }); + platform.set({ + .model_path = "assets/models/cube.obj", + .diffuse = "assets/models/wood.png", + }); + platform.set({ + .body_movement_type = atlas::fixed, + }); + platform.set({ + .half_extent = { 15.f, 0.30f, 10.0f }, }); // const size_t grid_width = 5; // const float spacing = 5; - // for(size_t i = 0; i < 100; i++) { + // for(size_t i = 0; i < 50; i++) { // atlas::game_object obj = entity(std::format("Object #{}", i)); // size_t col = i % grid_width; @@ -73,8 +86,9 @@ public: // glm::vec3 pos = { // float(static_cast(col) * spacing), - // 0.0f, - // float(static_cast(row) * -spacing) + // // 0.0f, + // float(static_cast(row) * -spacing), + // 0.f, // }; // obj.set({ @@ -85,6 +99,13 @@ public: // .model_path = "assets/models/Ball OBJ.obj", // .diffuse = "assets/models/clear.png", // }); + + // obj.set({ + // .body_movement_type = atlas::body_type::dynamic, + // }); + // obj.set({ + // .radius = 1.f, + // }); // } atlas::register_start(this, &level_scene::start); @@ -180,6 +201,8 @@ public: void ui_update() { } + + private: std::optional m_editor_camera; float m_movement_speed = 10.f; From a5f232224f9c133543d968cd150c2e8fb9f1b44e Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 9 Jun 2026 01:21:07 -0700 Subject: [PATCH 057/106] refactor: fix and re-added content browser panel --- editor/CMakeLists.txt | 2 +- editor/content_browser_panel.cppm | 108 ++++++++++-------------------- editor/editor_world.cppm | 16 +++-- 3 files changed, 44 insertions(+), 82 deletions(-) diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 85ea1a12..7c1e02fe 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -12,7 +12,7 @@ target_sources(editor PUBLIC editor_world.cppm level_scene.cppm level_scene2.cppm - # content_browser_panel.cppm + content_browser_panel.cppm icon.cppm utilities.cppm ) diff --git a/editor/content_browser_panel.cppm b/editor/content_browser_panel.cppm index b229e045..e59f663c 100644 --- a/editor/content_browser_panel.cppm +++ b/editor/content_browser_panel.cppm @@ -1,5 +1,6 @@ module; +#include #include #include #include @@ -9,58 +10,28 @@ module; export module editor:content_browser; import atlas.logger; -import atlas.drivers.vulkan.imgui_context; +import atlas.drivers.vulkan; import atlas.drivers.vulkan.stb_image; import vk; +import :icon; export class content_browser_panel { public: content_browser_panel() = default; content_browser_panel( - const VkDevice& p_device, + std::shared_ptr p_device, uint32_t p_memory_properties) { - vk::texture_params config_texture = { - .memory_mask = p_memory_properties, - }; - - atlas::vulkan::stb_image play_button("assets/icons/FileIcon.png", config_texture); - m_file_icon = vk::texture(p_device, &play_button, config_texture); - // if (!m_file_icon.loaded()) { - // console_log_info("Play Button Could not be loaded!!"); - // } - config_texture = { - .memory_mask = p_memory_properties, - }; - - atlas::vulkan::stb_image file_icon("assets/icons/FileIcon.png", config_texture); - m_directory_icon = vk::texture(p_device, &file_icon, config_texture); - // if (!m_directory_icon.loaded()) { - // console_log_info("Stop Button Could not be loaded!!"); - // } - config_texture = { - .memory_mask = p_memory_properties, - }; - - atlas::vulkan::stb_image back_icon("assets/icons/Back.png", config_texture); - m_back_icon = vk::texture(p_device, &back_icon, config_texture); - // if (!back_icon.loaded()) { - // console_log_info("Stop Button Could not be loaded!!"); - // } - - m_file_icon_id = static_cast(ImGui_ImplVulkan_AddTexture( - m_file_icon.image().sampler(), - m_file_icon.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - m_directory_icon_id = - static_cast(ImGui_ImplVulkan_AddTexture( - m_directory_icon.image().sampler(), - m_directory_icon.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); - m_back_icon_id = static_cast(ImGui_ImplVulkan_AddTexture( - m_back_icon.image().sampler(), - m_back_icon.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); + /*NOLINT*/m_device = p_device; + + m_directory_icon = ui::experimental::icon(m_device, p_memory_properties, + "assets/icons/DirectoryIcon.png"); + + m_file_icon = ui::experimental::icon(m_device, p_memory_properties, + "assets/icons/FileIcon.png"); + + m_back_icon = ui::experimental::icon(m_device, p_memory_properties, + "assets/icons/Back.png"); } void run() { @@ -70,7 +41,7 @@ public: // m_current_directory = m_current_directory.parent_path(); // } if (ImGui::ImageButton( - "##BackButton", m_back_icon_id, ImVec2(10, 10))) { + "##BackButton", m_back_icon.texture_id(), ImVec2(10, 10))) { m_current_directory = m_current_directory.parent_path(); } } @@ -80,13 +51,13 @@ public: float thumbnail_size = 86.96f; // originally 128.f float cell_size = thumbnail_size + padding; - float panelWidth = ImGui::GetContentRegionAvail().x; - int columnCount = (int)(panelWidth / cell_size); + float panel_width = ImGui::GetContentRegionAvail().x; + int column_count = static_cast(panel_width / cell_size); - if (columnCount < 1) - columnCount = 1; + if (column_count < 1) + column_count = 1; - ImGui::Columns(columnCount, 0, false); + ImGui::Columns(column_count, nullptr, false); // @note First, list all files in directory // @@ -105,16 +76,11 @@ public: std::string filename = relative_path.filename().string(); ImGui::PushID(filename.c_str()); - // Ref icon = dir_entry.is_directory() ? - // _directoryIcon : _fileIcon; - ImTextureID icon = dir_entry.is_directory() - ? m_directory_icon_id - : m_file_icon_id; + VkDescriptorSet icon = dir_entry.is_directory() + ? m_directory_icon.texture_id() + : m_file_icon.texture_id(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); - // ImGui::ImageButton(reinterpret_cast(icon->getRendererID()), {thumbnail_size, thumbnail_size}, - // { 0, 1 }, { 1, 0}); ImGui::ImageButton("##Button", icon, ImVec2(thumbnail_size, thumbnail_size), @@ -122,11 +88,11 @@ public: { 0, 1 }); if (ImGui::BeginDragDropSource()) { - std::string itemPath = relative_path.string(); - // @note keep in mind sizeof(itemPath) is in bytes + std::string item_path = relative_path.string(); + // @note keep in mind sizeof(item_path) is in bytes ImGui::SetDragDropPayload("CONTENT_BROWSER_ITEM", - itemPath.c_str(), - itemPath.size()); + item_path.c_str(), + item_path.size()); ImGui::EndDragDropSource(); } @@ -145,27 +111,21 @@ public: ImGui::PopID(); } - // ImGui::Columns(1); - // ImGui::SliderFloat("Thumnail Size", &thumbnail_size, 16, 512); - // ImGui::SliderFloat("Padding", &padding, 0, 32); - ImGui::End(); } } void destroy() { - m_file_icon.destruct(); - m_directory_icon.destruct(); - m_back_icon.destruct(); + m_file_icon.destroy(); + m_directory_icon.destroy(); + m_back_icon.destroy(); } private: - vk::texture m_file_icon; - vk::texture m_directory_icon; - vk::texture m_back_icon; - ImTextureID m_file_icon_id; - ImTextureID m_directory_icon_id; - ImTextureID m_back_icon_id; + std::shared_ptr m_device; + ui::experimental::icon m_back_icon; + ui::experimental::icon m_directory_icon; + ui::experimental::icon m_file_icon; std::filesystem::path m_asset_path = std::filesystem::current_path() / "assets"; std::filesystem::path m_current_directory = m_asset_path; diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index fbe5b4ae..fecfa71e 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -30,6 +30,7 @@ import atlas.core.ui.widgets.imgui_stdlib; import :level_scene; import :icon; import :utilities; +import :content_browser; // import :level_scene2; import atlas.core.editor.dockspace; @@ -91,6 +92,9 @@ public: std::println("m_stop_icon not loaded!"); } + + m_content_browser = content_browser_panel(m_device, m_host_bit); + atlas::register_start(this, &editor_world::preload_assets); atlas::register_update(this, &editor_world::update); atlas::register_physics(this, &editor_world::physics_update); @@ -156,7 +160,7 @@ public: materials_editor_panel(); - content_browser_panel(); + m_content_browser.run(); ui_toolbar(); @@ -404,12 +408,6 @@ public: } } - void content_browser_panel() { - if (ImGui::Begin("Content Browser")) { - ImGui::End(); - } - } - void ui_toolbar() { ImGui::PushStyleVar( ImGuiStyleVar_WindowPadding, @@ -497,4 +495,8 @@ private: atlas::ui::menu_item m_editor_menu; ui::experimental::icon m_play_icon; ui::experimental::icon m_stop_icon; + // content_browser_panel( + // std::shared_ptr p_device, + // uint32_t p_memory_properties) { + content_browser_panel m_content_browser; }; \ No newline at end of file From e94bbd8723a78b7d071ac5dc95c400b5a57ce523 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 9 Jun 2026 01:25:05 -0700 Subject: [PATCH 058/106] refactor: fix serializer parameter intake to copy-by value --- atlas/core/serialize/serializer.cppm | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/atlas/core/serialize/serializer.cppm b/atlas/core/serialize/serializer.cppm index cdeaeb06..45dcd8d9 100644 --- a/atlas/core/serialize/serializer.cppm +++ b/atlas/core/serialize/serializer.cppm @@ -1,7 +1,5 @@ module; -// #include -// #include #include #include #include @@ -9,6 +7,7 @@ module; #include #include #include +#include export module atlas.core.serialize; @@ -177,8 +176,8 @@ namespace atlas { * @param p_scene_ctx is the current scene to perform * serialization/deserialization to */ - serializer(const ref& p_scene_ctx) - : m_current_scene_ctx(p_scene_ctx) {} + serializer(ref p_scene) + : m_current_scene_ctx(/*NOLINT*/p_scene) {} /** * @param p_filepath is the specified path to save the file @@ -208,8 +207,9 @@ namespace atlas { .without() .build(); - q.each([&output](flecs::entity p_entity_id) { - serialize_entity(output, p_entity_id); + q.each([&output](flecs::entity p_entity) { + std::println("Serialize Entity: {}", p_entity.name().c_str()); + serialize_entity(output, p_entity); }); std::ofstream output_file(p_filepath.string()); @@ -235,16 +235,16 @@ namespace atlas { return false; } - console_log_info("Before loading environment mappings!"); - std::string environment_map_data = ""; - if (data["Environment"]) { - environment_map_data = data["Environment"].as(); + // console_log_info("Before loading environment mappings!"); + // std::string environment_map_data = ""; + // if (data["Environment"]) { + // environment_map_data = data["Environment"].as(); - console_log_info("Environment Map Loaded Path (from yaml): {}", - environment_map_data); - } + // console_log_info("Environment Map Loaded Path (from yaml): {}", + // environment_map_data); + // } - p_registry.set({ .filepath = environment_map_data }); + // p_registry.set({ .filepath = environment_map_data }); YAML::Node entity_objects = data["Entities"]; From e11854e6bd878d457c8513f670beb2f5138c6924 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 9 Jun 2026 14:16:09 -0700 Subject: [PATCH 059/106] refactor: add directives for toggling between different physical device selection based on specific platforms --- atlas/core/entry_point/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index f0734d5a..80737005 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -108,8 +108,13 @@ main() { // 1. Setting up vk instance vk::instance api_instance(config, debug_callback_info); +#if defined(__APPLE__) std::expected physical_device_expected = api_instance.enumerate_physical_device(vk::physical_gpu::integrated); +#else + std::expected physical_device_expected = + api_instance.enumerate_physical_device(vk::physical_gpu::discrete); +#endif vk::physical_device physical_device = physical_device_expected.value(); std::array priorities = { 0.f }; From 61556c8abd5ec46cf365e0ed67d4cb1d59a4e042 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 9 Jun 2026 14:17:25 -0700 Subject: [PATCH 060/106] refactor: minor code cleanup and fixed some of the formatting --- editor/editor_world.cppm | 126 +++++++++++++++++++-------------------- editor/icon.cppm | 41 +++++++------ 2 files changed, 82 insertions(+), 85 deletions(-) diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index fecfa71e..a80e7fa3 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -50,7 +50,8 @@ public: const std::string& p_tag, atlas::event::bus& p_bus, atlas::level_streamer& p_level_streamer) - : atlas::world(p_tag, p_level_streamer), m_bus(&p_bus) { + : atlas::world(p_tag, p_level_streamer) + , m_bus(&p_bus) { m_device = p_context->logical_device(); // Create defualt scene to level streamer // Does polymorphic allocations for these customized scenes @@ -69,14 +70,13 @@ public: m_editor_dockspace.dockspace_open(true); m_host_bit = p_context->physical_device().memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit); + vk::memory_property::host_visible_bit | + vk::memory_property::host_coherent_bit); // Initializing icon. - m_play_icon = - ui::experimental::icon(m_device, m_host_bit, - "assets/icons/PlayButton.png"); + m_play_icon = ui::experimental::icon( + m_device, m_host_bit, "assets/icons/PlayButton.png"); - if(!m_play_icon.loaded()) { + if (!m_play_icon.loaded()) { std::println("m_play_icon not loaded!"); } @@ -84,15 +84,13 @@ public: ui::experimental::icon(m_device, p_context->physical_device().memory_properties( vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), + vk::memory_property::host_coherent_bit), "assets/icons/StopButton.png"); - - if(!m_stop_icon.loaded()) { + if (!m_stop_icon.loaded()) { std::println("m_stop_icon not loaded!"); } - m_content_browser = content_browser_panel(m_device, m_host_bit); atlas::register_start(this, &editor_world::preload_assets); @@ -103,20 +101,18 @@ public: ~editor_world() override = default; - void preload_assets() { // m_deserializer_test = atlas::serializer(); - // if (!m_deserializer_test.load("LevelScene-small", *m_current_scene)) { + // if (!m_deserializer_test.load("LevelScene-small", *m_current_scene)) + // { // console_log_error("Could not load yaml file LevelScene!!!"); // } m_physics_engine = atlas::physics::engine(*m_current_scene, *m_bus); } - void update(float p_delta_time) { - m_delta_time = p_delta_time; - } + void update(float p_delta_time) { m_delta_time = p_delta_time; } void ui_update() { // setting up the dockspace UI widgets at the window toolbar @@ -171,10 +167,12 @@ public: void scene_heirarchy_panel() { if (ImGui::Begin("Scene Heirarchy")) { m_current_scene->defer_begin(); - - auto query_all_transforms = m_current_scene->query_builder().build(); - query_all_transforms.each([&](flecs::entity p_entity, atlas::transform&){ + auto query_all_transforms = + m_current_scene->query_builder().build(); + + query_all_transforms.each([&](flecs::entity p_entity, + atlas::transform&) { // We set the imgui flags for our scene heirarchy panel // TODO -- Make the scene heirarchy panel a separate class that // is used for specify the layout and other UI elements here @@ -186,7 +184,7 @@ public: flags |= ImGuiWindowFlags_Popup; flags |= ImGuiTreeNodeFlags_AllowItemOverlap; - bool opened = ImGui::TreeNodeEx(p_entity.name().c_str(), flags); + bool opened = ImGui::TreeNodeEx(p_entity.name().c_str(), flags); if (ImGui::IsItemClicked()) { m_selected_entity = p_entity; @@ -235,7 +233,6 @@ public: } }); - m_current_scene->defer_end(); ImGui::End(); @@ -270,33 +267,35 @@ public: "atlas::mesh_source", m_selected_entity, [](atlas::mesh_source* p_source) { - // if (ImGui::InputText( - // "Input Label", - // &p_source->model_path, - // ImGuiInputTextFlags_EnterReturnsTrue)) { - // console_log_info("mesh_src = {}", - // p_source->model_path); - // // atlas::event::mesh_reload reload_request = { - // // .entity_id = m_selected_entity.id(), - // // .filename = p_source->model_path, - // // }; - - // // if (std::filesystem::exists(p_source->model_path)) { - // // signal(reload_request); - // // } - // } + // if (ImGui::InputText( + // "Input Label", + // &p_source->model_path, + // ImGuiInputTextFlags_EnterReturnsTrue)) { + // console_log_info("mesh_src = {}", + // p_source->model_path); + // // atlas::event::mesh_reload reload_request = { + // // .entity_id = m_selected_entity.id(), + // // .filename = p_source->model_path, + // // }; + + // // if + // (std::filesystem::exists(p_source->model_path)) { + // // signal(reload_request); + // // } + // } atlas::ui::draw_vec4("Color", p_source->color); - // if (ImGui::Button("Reload Material")) { - // atlas::event::material_reload - // // reload_material_request = { - // // .entity_id = m_selected_entity.id(), - // // .diffuse = "assets/models/viking_room.png", - // // .specular = "", - // // }; - - // // signal(reload_material_request); - // } + // if (ImGui::Button("Reload Material")) { + // atlas::event::material_reload + // // reload_material_request = { + // // .entity_id = m_selected_entity.id(), + // // .diffuse = + // "assets/models/viking_room.png", + // // .specular = "", + // // }; + + // // signal(reload_material_request); + // } }); atlas::ui::draw_component( @@ -332,8 +331,9 @@ public: }; // Begin the combo box - if (ImGui::BeginCombo("Body Type", - items[p_body->body_movement_type].data())) { + if (ImGui::BeginCombo( + "Body Type", + items[p_body->body_movement_type].data())) { for (int n = 0; n < 3; n++) { // Check if the current item is selected const bool is_selected = @@ -430,26 +430,26 @@ public: // ImGui::End(); // } - if(ImGui::Begin("##toolbox")) { + if (ImGui::Begin("##toolbox")) { VkDescriptorSet button_id = (m_scene_state == scene_runtime::edit) - ? m_play_icon.texture_id() - : m_stop_icon.texture_id(); + ? m_play_icon.texture_id() + : m_stop_icon.texture_id(); /** - * @note GetWindowContentRegionMax().x is how much space is there for - * content (widgets) - * @note 0.5f is the offset for padding. - * @note takes button size and halves it and makes the offset the center - * of that tab. (centering buttons) - */ + * @note GetWindowContentRegionMax().x is how much space is there + * for content (widgets) + * @note 0.5f is the offset for padding. + * @note takes button size and halves it and makes the offset the + * center of that tab. (centering buttons) + */ ImGui::SameLine((ImGui::GetWindowContentRegionMax().x * 0.5f) - (button_size * 0.5f)); if (ImGui::ImageButton("##Button", - button_id, - ImVec2{ button_size, button_size }, - ImVec2(0, 0), - ImVec2(1, 1))) { + button_id, + ImVec2{ button_size, button_size }, + ImVec2(0, 0), + ImVec2(1, 1))) { if (m_scene_state == scene_runtime::edit) { m_scene_state = scene_runtime::play; m_physics_engine.start(); @@ -473,18 +473,16 @@ public: } } - void destruct() { m_play_icon.destroy(); m_stop_icon.destroy(); } private: - atlas::event::bus* m_bus=nullptr; + atlas::event::bus* m_bus = nullptr; float m_delta_time; atlas::physics::engine m_physics_engine; atlas::serializer m_deserializer_test; - // Bit for setting vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit uint32_t m_host_bit = 0; float m_movement_speed = 10.f; flecs::entity m_selected_entity; diff --git a/editor/icon.cppm b/editor/icon.cppm index 4d381291..749b07e8 100644 --- a/editor/icon.cppm +++ b/editor/icon.cppm @@ -24,14 +24,14 @@ export namespace ui::experimental { class icon { public: icon() = default; - icon(/*NOLINT*/std::shared_ptr p_device, + icon(/*NOLINT*/ std::shared_ptr p_device, uint32_t p_memory_properties, const std::filesystem::path& p_filename) { - /*NOLINT*/m_device = p_device; + /*NOLINT*/ m_device = p_device; vk::texture_params config_texture = { // .memory_mask = physical_device.memory_properties( // vk::memory_property::host_visible_bit | - // vk::memory_property::host_cached_bit), + // vk::memory_property::host_coherent_bit), .memory_mask = p_memory_properties, }; @@ -39,38 +39,37 @@ export namespace ui::experimental { m_icon_image = vk::texture(*m_device, &image, config_texture); m_extent = image.extent(); - m_icon_image_id = - ImGui_ImplVulkan_AddTexture( - m_icon_image.image().sampler(), - m_icon_image.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + m_icon_image_id = ImGui_ImplVulkan_AddTexture( + m_icon_image.image().sampler(), + m_icon_image.image().image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } - icon(/*NOLINT*/std::shared_ptr p_device, + icon(/*NOLINT*/ std::shared_ptr p_device, uint32_t p_memory_properties, - const vk::image_extent& p_extent, std::span p_data) { + const vk::image_extent& p_extent, + std::span p_data) { /*NOLINT*/ m_device = p_device; m_extent = p_extent; - m_icon_image = vk::texture(*m_device, p_extent, p_data, p_memory_properties); - m_icon_image_id = - ImGui_ImplVulkan_AddTexture( - m_icon_image.image().sampler(), - m_icon_image.image().image_view(), - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + m_icon_image = + vk::texture(*m_device, p_extent, p_data, p_memory_properties); + m_icon_image_id = ImGui_ImplVulkan_AddTexture( + m_icon_image.image().sampler(), + m_icon_image.image().image_view(), + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); } ~icon() = default; - - [[nodiscard]] bool loaded() const { - return m_icon_image.loaded(); - } + [[nodiscard]] bool loaded() const { return m_icon_image.loaded(); } [[nodiscard]] uint32_t width() const { return m_extent.width; } [[nodiscard]] uint32_t height() const { return m_extent.height; } - [[nodiscard]] VkDescriptorSet texture_id() const { return m_icon_image_id; } + [[nodiscard]] VkDescriptorSet texture_id() const { + return m_icon_image_id; + } void destroy() { m_icon_image.destruct(); } From d15e523012acb4542cf4dd7091c29c968cf6b192 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 9 Jun 2026 15:01:39 -0700 Subject: [PATCH 061/106] refactor: remove old mesh.cppm from codebase --- CMakeLists.txt | 1 - atlas/drivers/vulkan/mesh.cppm | 318 --------------------------------- 2 files changed, 319 deletions(-) delete mode 100644 atlas/drivers/vulkan/mesh.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index 93562bfa..c96af4fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -207,7 +207,6 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/vulkan/stb_image.cppm atlas/drivers/vulkan/hash.cppm - # atlas/drivers/vulkan/mesh.cppm atlas/drivers/vulkan/shader_resource_group.cppm atlas/drivers/vulkan/render_system.cppm atlas/drivers/vulkan/uniforms.cppm diff --git a/atlas/drivers/vulkan/mesh.cppm b/atlas/drivers/vulkan/mesh.cppm deleted file mode 100644 index 53fcbcaf..00000000 --- a/atlas/drivers/vulkan/mesh.cppm +++ /dev/null @@ -1,318 +0,0 @@ -module; - -#include -#include -#define STB_IMAGE_IMPLEMENTATION -#define STB_IMAGE_WRITE_IMPLEMENTATION -#include -#include -#include -#include -#include - -export module atlas.drivers.vulkan.mesh; -import vk; - -import atlas.logger; -import atlas.drivers.vulkan.hash; -import atlas.drivers.vulkan.stb_image; - -export namespace atlas::vulkan { - /** - * @brief mesh class specifically defined with vulkan implementations for - * specific primitives - * - * @brief mesh class will contain metadata needed by vulkan specifications - * Ways to communicate through vulkan by only supplying information needed - * to update this mesh - * - * @brief Represents a renderable object -- supporting various material - * types, etc - * TODO - For now we have a map, this should - * be expanded to a proper material system for blending various materials - */ - class mesh { - public: - mesh() = default; - mesh(const VkDevice& p_device, - std::span p_vertices, - std::span p_indices, - uint32_t p_memory_properties) - : m_device(p_device) { - m_memory_properties = p_memory_properties; - - // vk::vertex_params vbo_settings = { - // .phsyical_memory_properties = m_memory_properties, - // .vertices = p_vertices, - // }; - // vk::index_params ibo_settings = { - // .phsyical_memory_properties = m_memory_properties, - // .indices = p_indices, - // }; - // const auto property_flags = static_cast( - // vk::memory_property::host_visible_bit | - // vk::memory_property::host_cached_bit); - - vk::buffer_parameters vertex_params = { - // .memory_mask = p_physical.memory_properties(property_flags), - .memory_mask = p_memory_properties, - .property_flags = vk::memory_property::device_local_bit, - .usage = vk::buffer_usage::transfer_dst_bit | - vk::buffer_usage::vertex_buffer_bit, - }; - - vk::buffer_parameters index_params = { - // .memory_mask = p_physical.memory_properties(property_flags), - .memory_mask = p_memory_properties, - .property_flags = static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::index_buffer_bit, - }; - m_vbo = vk::vertex_buffer(m_device, p_vertices, vertex_params); - m_ibo = vk::index_buffer(m_device, p_indices, index_params); - - // m_vertices_size = p_vertices.size(); - m_vertices_size = static_cast(p_vertices.size()); - // m_indices_size = p_indices.size(); - m_indices_size = static_cast(p_indices.size()); - } - - mesh(const VkDevice& p_device, - uint32_t p_memory_properties, - const std::filesystem::path& p_filename, - bool p_flip = false) - : m_device(p_device) - , m_memory_properties(p_memory_properties) - , m_flip(p_flip) { - reload_mesh(p_filename); - } - - //! @brief Reload mesh vertices and indices when requested - void reload_mesh(const std::filesystem::path& p_filename) { - load_obj(p_filename); - } - - [[nodiscard]] VkBuffer vertex_handle() const { return m_vbo; } - - [[nodiscard]] VkBuffer index_handle() const { return m_ibo; } - - [[nodiscard]] uint32_t vertices_size() const { return m_vertices_size; } - - [[nodiscard]] uint32_t indices_size() const { return m_indices_size; } - - void destroy() { - m_vbo.destruct(); - m_ibo.destruct(); - - m_diffuse.destruct(); - m_specular.destruct(); - m_geoemtry_ubo.destruct(); - m_material_ubo.destruct(); - } - - //! @brief Loading single texture with specified std::filesystem::path - void add_diffuse(const std::filesystem::path& p_path) { - vk::texture_params config_texture = { - .memory_mask = m_memory_properties, - }; - - atlas::vulkan::stb_image diffuse(p_path.string(), config_texture); - m_diffuse = ::vk::texture(m_device, &diffuse, config_texture); - - if (!m_diffuse.loaded()) { - console_log_info("Diffuse Texture {} is NOT loaded!!!", - p_path.string()); - return; - } - } - - void add_specular(const std::filesystem::path& p_path) { - vk::texture_params config_texture = { - .memory_mask = m_memory_properties, - }; - atlas::vulkan::stb_image specular(p_path.string(), config_texture); - m_specular = vk::texture(m_device, &specular, config_texture); - - if (!m_specular.loaded()) { - console_log_error("Specular Texture {} is NOT loaded!!!", - p_path.string()); - return; - } - } - - [[nodiscard]] ::vk::sample_image diffuse() const { - return m_diffuse.image(); - } - [[nodiscard]] ::vk::sample_image specular() const { - return m_specular.image(); - } - - // void draw(const VkCommandBuffer& p_command_buffer) { - // m_vbo.bind(p_command_buffer); - // if (m_ibo.size() > 0) { - // m_ibo.bind(p_command_buffer); - // vkCmdDrawIndexed(p_command_buffer, m_ibo.size(), 1, 0, 0, 0); - // } - // else { - // vkCmdDraw(p_command_buffer, m_vbo.size(), 1, 0, 0); - // } - // } - - //! @return true if mesh geometry model loaded succesfully - [[nodiscard]] bool loaded() const { return m_model_loaded; } - - [[nodiscard]] bool diffuse_loaded() const { return m_diffuse.loaded(); } - - [[nodiscard]] bool specular_loaded() const { - return m_specular.loaded(); - } - - void set_flip(bool p_flip) { m_flip = p_flip; } - - private: - void load_obj(const std::filesystem::path& p_filename) { - tinyobj::attrib_t attrib; - std::vector shapes; - std::vector materials; - std::string warn, err; - - //! @note If we return the constructor then we can check if the mesh - //! loaded successfully - //! @note We also receive hints if the loading is successful! - //! @note Return default constructor automatically returns false - //! means that mesh will return the boolean as false because it - //! wasnt successful - if (!tinyobj::LoadObj(&attrib, - &shapes, - &materials, - &warn, - &err, - p_filename.string().c_str())) { - console_log_warn("Could not load model from path {}", - p_filename.string()); - m_model_loaded = false; - return; - } - - std::vector vertices; - std::vector indices; - std::unordered_map unique_vertices{}; - - // for (const auto& shape : shapes) { - for (size_t i = 0; i < shapes.size(); i++) { - auto shape = shapes[i]; - // for (const auto& index : shape.mesh.indices) { - for (size_t j = 0; j < shape.mesh.indices.size(); j++) { - auto index = shape.mesh.indices[j]; - vk::vertex_input vertex{}; - - if (!unique_vertices.contains(vertex)) { - unique_vertices[vertex] = - static_cast(vertices.size()); - vertices.push_back(vertex); - } - - if (index.vertex_index >= 0) { - vertex.position = { - attrib.vertices[3 * index.vertex_index + 0], - attrib.vertices[3 * index.vertex_index + 1], - attrib.vertices[3 * index.vertex_index + 2] - }; - - vertex.color = { - attrib.colors[3 * index.vertex_index + 0], - attrib.colors[3 * index.vertex_index + 1], - attrib.colors[3 * index.vertex_index + 2] - }; - } - - if (!attrib.normals.empty()) { - vertex.normals = { - attrib.normals[3 * index.normal_index + 0], - attrib.normals[3 * index.normal_index + 1], - attrib.normals[3 * index.normal_index + 2] - }; - } - if (!attrib.texcoords.empty()) { - glm::vec2 flipped_uv = { - attrib.texcoords[static_cast( - index.texcoord_index) * - 2], - 1.0f - attrib.texcoords[static_cast( - index.texcoord_index) * - 2 + - 1], - }; - - glm::vec2 original_uv = { - attrib.texcoords[static_cast( - index.texcoord_index) * - 2], - attrib.texcoords[static_cast( - index.texcoord_index) * - 2 + - 1], - }; - - vertex.uv = m_flip ? flipped_uv : original_uv; - } - else { - vertex.uv = glm::vec2(0.f, 0.f); - } - - if (!unique_vertices.contains(vertex)) { - unique_vertices[vertex] = - static_cast(vertices.size()); - vertices.push_back(vertex); - } - - indices.push_back(unique_vertices[vertex]); - } - } - - vk::buffer_parameters vertex_params = { - .memory_mask = m_memory_properties, - .property_flags = vk::memory_property::device_local_bit, - .usage = vk::buffer_usage::transfer_dst_bit | - vk::buffer_usage::vertex_buffer_bit, - }; - - vk::buffer_parameters index_params = { - .memory_mask = m_memory_properties, - .property_flags = static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::index_buffer_bit, - }; - - // ::vk::vertex_params vbo_settings = { .phsyical_memory_properties = - // m_memory_properties, - // .vertices = vertices }; - // ::vk::index_params ibo_settings = { .phsyical_memory_properties = - // m_memory_properties, - // .indices = indices }; - m_vbo = ::vk::vertex_buffer(m_device, vertices, vertex_params); - m_ibo = ::vk::index_buffer(m_device, indices, index_params); - - m_vertices_size = vertices.size(); - m_indices_size = indices.size(); - m_model_loaded = true; - } - - private: - uint32_t m_memory_properties=0; - VkDevice m_device = nullptr; - vk::texture m_diffuse; - vk::texture m_specular; - vk::vertex_buffer m_vbo{}; - vk::index_buffer m_ibo{}; - vk::uniform_buffer m_geoemtry_ubo; - vk::uniform_buffer m_material_ubo; - bool m_model_loaded = false; - bool m_flip = false; - - uint32_t m_vertices_size = 0; - uint32_t m_indices_size = 0; - }; -}; \ No newline at end of file From e7ac733da74d2a40fc0942ab88c153fb6cfec539 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 9 Jun 2026 15:02:35 -0700 Subject: [PATCH 062/106] refactor: update conanfile.py to use vulkan-cpp/2.0 --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index c50b794e..83fc4cd6 100644 --- a/conanfile.py +++ b/conanfile.py @@ -40,7 +40,7 @@ def requirements(self): self.requires("yaml-cpp/0.8.0") # Vulkan-related headers and includes packages - self.requires("vulkan-cpp/6.1") + self.requires("vulkan-cpp/6.2") self.requires("tinyobjloader/2.0.0-rc10") self.requires("stb/cci.20230920") From a4f6ced7d3c9d86e776d46fb77bdf6d0f03193b7 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 9 Jun 2026 15:04:02 -0700 Subject: [PATCH 063/106] refactor: update window.cppm to use correct format --- atlas/drivers/vulkan/window.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 9090b05b..5a2cabed 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -64,7 +64,7 @@ export namespace atlas { }; m_surface_properties = - p_context->physical_device().request_surface(*m_surface); + p_context->physical_device().request_surface(*m_surface, VK_FORMAT_B8G8R8A8_UNORM); m_swapchain = std::make_shared(*p_context->logical_device(), From b2ced619c35b15e14ff8b88ca39f95b8d0518ac4 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Tue, 9 Jun 2026 23:49:03 -0700 Subject: [PATCH 064/106] refactor: working HDRI loading for environment maps --- atlas/drivers/vulkan/environment_map.cppm | 1146 +++++++++++---------- atlas/drivers/vulkan/render_context.cppm | 73 +- builtin.shaders/pbr.frag | 19 +- builtin.shaders/pbr.frag.spv | Bin 1092 -> 2816 bytes builtin.shaders/pbr.vert | 3 + builtin.shaders/pbr.vert.spv | Bin 2976 -> 3064 bytes builtin.shaders/skybox/skybox.frag | 4 +- builtin.shaders/skybox/skybox.frag.spv | Bin 1908 -> 1916 bytes builtin.shaders/skybox/skybox.vert | 16 +- builtin.shaders/skybox/skybox.vert.spv | Bin 1608 -> 1980 bytes 10 files changed, 676 insertions(+), 585 deletions(-) diff --git a/atlas/drivers/vulkan/environment_map.cppm b/atlas/drivers/vulkan/environment_map.cppm index 46b97bf4..3bc59e6d 100644 --- a/atlas/drivers/vulkan/environment_map.cppm +++ b/atlas/drivers/vulkan/environment_map.cppm @@ -7,6 +7,14 @@ module; #include #include #include +#include + +#define GLM_FORCE_RADIANS +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +#include #define GLFW_INCLUDE_VULKAN #if _WIN32 @@ -21,581 +29,607 @@ module; #endif #include -#define GLM_FORCE_RADIANS -#include -#include -#define GLM_ENABLE_EXPERIMENTAL -#include -#include -#include - -export module atlas.drivers.vulkan.environment_map; +export module atlas.drivers.vulkan:environment_map; import vk; +struct environment_uniforms { + glm::mat4 proj_view; +}; -/* -namespace atlas { +struct environment_push_constant { + uint64_t scene_environment_address=0; +}; - export struct skybox_uniform { - glm::mat4 proj_view; - }; +export class environment_map { +public: + environment_map() = default; + environment_map(std::shared_ptr p_device, + vk::physical_device& p_physical, + const std::string& p_filename, /*NOLINT*/VkFormat p_color_format, VkFormat p_depth_format) : m_color_format(p_color_format), m_depth_format(p_depth_format) { + /*NOLINT*/ m_device = p_device; + m_physical = p_physical; + m_memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit); - export class environment_map { - public: - environment_map() = default; + construct(p_filename); + } - environment_map(const VkDevice& p_device, - vulkan::physical_device& p_physical, - const std::filesystem::path& p_filename, - uint32_t p_memory_properties, - VkRenderPass p_renderpass) - : m_device(p_device) - , m_physical(&p_physical) { - m_memory_properties = p_memory_properties; - create_hdr_skybox(p_filename); + void construct(const std::string& p_filename) { + bool res = create_hdr(p_filename); - create_skybox_pipeline(p_renderpass); + if (!res) { + std::println("Cannot load environment: {}", p_filename); } - void create_hdr_skybox(const std::filesystem::path& p_filename) { - - stbi_set_flip_vertically_on_load(true); - int w, h, channels; - float* pixels = stbi_loadf( - p_filename.string().c_str(), &w, &h, &channels, STBI_rgb_alpha); - - if (!pixels) { - throw std::runtime_error("Failed to load HDR image at: " + - p_filename.string()); - } - - const uint32_t width = static_cast(w); - const uint32_t height = static_cast(h); - - VkFormat texture_format = VK_FORMAT_R32G32B32A32_SFLOAT; - const uint64_t bytes_per_pixel_channel = 16; // float are 4 bytes - const uint64_t total_size_bytes = - static_cast(width * height * bytes_per_pixel_channel); - const uint64_t image_size = total_size_bytes; - - // Creating staging buffer - vk::buffer_parameters staging_buffer_params = { - // .device_size = static_cast(image_size), - // Replace with .memory_mask - .memory_mask = m_physical->memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - // Replace with .memory_mask - // .property_flags = - // static_cast(property_flag), - // .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - .usage = vk::buffer_usage::transfer_src_bit, - }; - - // Replace to be vk::buffer - vk::buffer staging_buffer = - vk::buffer(m_device, - static_cast(image_size), - staging_buffer_params); - - // Creating image handle to storing the HDR - vk::image_params skybox_image_params = { - .extent = { - .width = width, - .height = height, - }, - .format = texture_format, - // Replace with .memory_mask - .memory_mask = m_memory_properties, - // Replace with .memory_mask - // .property = vk::memory_property::device_local_bit, - .aspect = vk::image_aspect_flags::color_bit, - .usage = vk::image_usage::transfer_dst_bit | - vk::image_usage::sampled_bit, - }; - m_skybox_image = vk::sample_image(m_device, skybox_image_params); - - // Transferring data from the CPU - // Replace to using staging_buffer.transfer API - std::span pixels_data( - reinterpret_cast(pixels), image_size); - staging_buffer.transfer(pixels_data); - - // Free CPU pixels immediately after staging copy - stbi_image_free(pixels); - - // Record and Execute Upload - vk::command_params upload_params = { - .levels = vk::command_levels::primary, - .queue_index = 0, // Graphics Queue - .flags = vk::command_pool_flags::reset, - }; - vk::command_buffer upload_cmd(m_device, upload_params); - - upload_cmd.begin(vk::command_usage::one_time_submit); - - // Begin Memory Barrier: Undefined to TRANSFER_DST - m_skybox_image.memory_barrier(upload_cmd, - texture_format, - VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - vk::buffer_image_copy image_copy = { - .image_offset = { .width = 0, .height = 0, .depth = 0, }, - .image_extent = { .width = skybox_image_params.extent.width, .height = skybox_image_params.extent.height, .depth = 1, }, - }; - staging_buffer.copy_to_image( - upload_cmd, m_skybox_image, std::span(&image_copy, 1)); - - // Begin Memory Barrier: TRANSFER_DST to SHADER_READ_ONLY - m_skybox_image.memory_barrier( - upload_cmd, - texture_format, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - upload_cmd.end(); - - VkQueue graphics_queue; - vkGetDeviceQueue(m_device, 0, 0, &graphics_queue); - - VkCommandBuffer raw_cmd = upload_cmd; - VkSubmitInfo submit_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = 1, - .pCommandBuffers = &raw_cmd, - }; - - vkQueueSubmit(graphics_queue, 1, &submit_info, nullptr); - vkQueueWaitIdle(graphics_queue); - - upload_cmd.destruct(); - staging_buffer.destruct(); - stbi_set_flip_vertically_on_load(false); + if (res) { + std::println("Loaded succesfully: {}", p_filename); } + create_pipelines(); + } - void create_buffers() { - const auto property_flags = static_cast( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit); - std::vector vertices = { - // Front Face - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - - // Left Face - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - - // Right Face - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - - // Back Face - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - - // Top Face - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, 1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - - // Bottom Face - vk::vertex_input{ { -1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, -1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { -1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } }, - vk::vertex_input{ { 1.0f, -1.0f, 1.0f }, - { 1.0f, 1.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f } } - }; - - vk::buffer_parameters vertex_params = { - .memory_mask = m_physical->memory_properties(property_flags), - .property_flags = vk::memory_property::device_local_bit, - .usage = vk::buffer_usage::transfer_dst_bit | - vk::buffer_usage::vertex_buffer_bit, - }; - - m_skybox_vbo = vk::vertex_buffer(m_device, vertices, vertex_params); - - m_vertices_size = static_cast(vertices.size()); - } + bool create_hdr(const std::string& p_filename) { + stbi_set_flip_vertically_on_load(true); + int w, h, channels; + float* pixels = + stbi_loadf(p_filename.c_str(), &w, &h, &channels, STBI_rgb_alpha); - void create_skybox_pipeline(const VkRenderPass& p_renderpass) { - create_buffers(); - std::array attribute_entries = { - vk::vertex_attribute_entry{ - .location = 0, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position), - }, - vk::vertex_attribute_entry{ - .location = 1, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color), - }, - vk::vertex_attribute_entry{ - .location = 2, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals), - }, - vk::vertex_attribute_entry{ - .location = 3, - .format = vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv), - } - }; - std::array attribute = { - vk::vertex_attribute{ - // layout (set = 0, binding = 0) - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = vk::input_rate::vertex, - }, - }; + if (!pixels) { + return false; + } - const std::array sources = { - vk::shader_source{ - .filename = "builtin.shaders/skybox/skybox.vert.spv", - .stage = vk::shader_stage::vertex, - }, - vk::shader_source{ - .filename = "builtin.shaders/skybox/skybox.frag.spv", - .stage = vk::shader_stage::fragment, - }, - }; - - vk::shader_resource_info shader_info = { - .sources = sources, - }; - m_skybox_shaders = vk::shader_resource(m_device, shader_info); - m_skybox_shaders.vertex_attributes(attribute); - - // set=0 binding=0 UBO: mat4 VP - vk::buffer_parameters uniform_params = { - .memory_mask = m_physical->memory_properties( - vk::memory_property::host_visible_bit | - vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::uniform_buffer_bit | - vk::buffer_usage::shader_device_address_bit, - .allocate_flags = - vk::memory_allocate_flags::device_address_bit_khr, - }; - // Replace vk::uniform_params with vk::buffer_parameters(m_device, - // sizeof(skybox_uniform), ubo_params); - m_skybox_ubo = vk::uniform_buffer(m_device, sizeof(skybox_uniform), uniform_params); - - skybox_uniform identity = { .proj_view = glm::mat4(1.0f) }; - identity.proj_view[1][1] *= -1; - - // Replace with m_skybox_ubo.transfer - m_skybox_ubo.transfer( - std::span(&identity, 1)); - - // set=0 bindings: - // - binding 0: UBO (vertex) - // - binding 1: samplerCube (fragment) - std::array entries = { - vk::descriptor_entry{ - .type = vk::descriptor_type::uniform, - .binding_point = - vk::descriptor_binding_point{ - .binding = 0, .stage = vk::shader_stage::vertex }, - .descriptor_count = 1, - }, - vk::descriptor_entry{ - .type = vk::descriptor_type::combined_image_sampler, - .binding_point = - vk::descriptor_binding_point{ - .binding = 1, .stage = vk::shader_stage::fragment }, - .descriptor_count = 1, - }, - }; - - vk::descriptor_layout desc_layout = { - .slot = 0, - .max_sets = 1, - .entries = entries, - }; - m_skybox_descriptors = - vk::descriptor_resource(m_device, desc_layout); - - const std::array ubo_writes = { - vk::write_buffer{ - .buffer = static_cast(m_skybox_ubo), - .offset = 0, - .range = static_cast(sizeof(skybox_uniform)) }, - }; - const vk::write_buffer_descriptor ubo_write_desc = { - .dst_binding = 0, - .uniforms = ubo_writes, - }; - - const std::array image_writes = { - vk::write_image{ - .sampler = m_skybox_image.sampler(), - .view = m_skybox_image.image_view(), - .layout = vk::image_layout::shader_read_only_optimal, + const uint64_t width = static_cast(w); + const uint64_t height = static_cast(h); + + VkFormat texture_format = VK_FORMAT_R32G32B32A32_SFLOAT; + const uint64_t bytes_per_pixel_channel = 16; // float are 4 bytes + const uint64_t total_size_bytes = + static_cast(width * height * bytes_per_pixel_channel); + const uint64_t image_size = total_size_bytes; + + vk::buffer_parameters staging_params = { + .memory_mask = m_memory_mask, + .usage = vk::buffer_usage::transfer_src_bit, + }; + + vk::buffer staging_buffer = + vk::buffer(*m_device, image_size, staging_params); + + // Creating image handle to storing the HDR + vk::image_params skybox_params = { + .extent = { .width = static_cast(width), .height = static_cast(height), }, + .format = texture_format, + .memory_mask = m_memory_mask, + // .property = vk::memory_property::device_local_bit, + .aspect = vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::transfer_dst_bit | + vk::image_usage::sampled_bit, + // .view_type = VK_IMAGE_VIEW_TYPE_CUBE, + }; + m_skybox_image = vk::sample_image(*m_device, skybox_params); + + // Transferring data from the CPU + std::span pixels_data( + reinterpret_cast(pixels), image_size); + staging_buffer.transfer(pixels_data); + + // Free CPU pixels immediately after staging copy + stbi_image_free(pixels); + + // 6. Record and Execute Upload + vk::command_params upload_params = { + .levels = vk::command_levels::primary, + .queue_index = 0, // Graphics Queue + .flags = vk::command_pool_flags::reset, + }; + vk::command_buffer upload_cmd(*m_device, upload_params); + + upload_cmd.begin(vk::command_usage::one_time_submit); + + // Begin Memory Barrier: Undefined to TRANSFER_DST + m_skybox_image.memory_barrier(upload_cmd, + texture_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + vk::buffer_image_copy image_copy{ + .image_offset = { .width = 0, .height = 0, .depth = 0, }, + .image_extent = skybox_params.extent, + }; + staging_buffer.copy_to_image( + upload_cmd, + m_skybox_image, + std::span(&image_copy, 1)); + + // Begin Memory Barrier: TRANSFER_DST to SHADER_READ_ONLY + m_skybox_image.memory_barrier(upload_cmd, + texture_format, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + upload_cmd.end(); + + VkQueue graphics_queue; + vkGetDeviceQueue(*m_device, 0, 0, &graphics_queue); + + VkCommandBuffer raw_cmd = upload_cmd; + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &raw_cmd, + }; + + vkQueueSubmit(graphics_queue, 1, &submit_info, nullptr); + vkQueueWaitIdle(graphics_queue); + + upload_cmd.destruct(); + staging_buffer.destruct(); + stbi_set_flip_vertically_on_load(false); + + return true; + } + + void create_buffers() { + std::vector vertices = { + // Front Face + vk::vertex_input{ + .position = { -1.0f, 1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, -1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, -1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, -1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, 1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, 1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + + // Left Face + vk::vertex_input{ + .position = { -1.0f, -1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, -1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, 1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, 1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, 1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position{ -1.0f, -1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + + // Right Face + vk::vertex_input{ + .position = { 1.0f, -1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, -1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, 1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, 1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, 1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, -1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + + // Back Face + vk::vertex_input{ + .position = { -1.0f, -1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, 1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, 1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, 1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, -1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, -1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + + // Top Face + vk::vertex_input{ + .position = { -1.0f, 1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, 1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, 1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, 1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, 1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, 1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + + // Bottom Face + vk::vertex_input{ + .position = { -1.0f, -1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, -1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, -1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, -1.0f, -1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { -1.0f, -1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + }, + vk::vertex_input{ + .position = { 1.0f, -1.0f, 1.0f }, + .color = { 1.0f, 1.0f, 1.0f }, + .normals = { 0.0f, 0.0f, 0.0f }, + .uv = { 0.0f, 0.0f }, + } + }; + + m_vertices_size = vertices.size(); + + vk::buffer_parameters vertex_params = { + // .memory_mask = p_physical.memory_properties( + // vk::memory_property::device_local_bit | + // vk::memory_property::host_visible_bit), + .memory_mask = m_memory_mask, + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, + }; + + m_skybox_vbo = vk::vertex_buffer(*m_device, vertices, vertex_params); + } + + + void create_pipelines() { + create_buffers(); + std::array attribute_entries = { + vk::vertex_attribute_entry{ + .location = 0, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, position), + }, + vk::vertex_attribute_entry{ + .location = 1, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, color), + }, + vk::vertex_attribute_entry{ + .location = 2, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, normals), + }, + vk::vertex_attribute_entry{ + .location = 3, + .format = vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, uv), + } + }; + std::array attribute = { + vk::vertex_attribute{ + // layout (set = 0, binding = 0) + .binding = 0, + .entries = attribute_entries, + .stride = sizeof(vk::vertex_input), + .input_rate = vk::input_rate::vertex, + }, + }; + + const std::array sources = { + vk::shader_source{ + .filename = "builtin.shaders/skybox/skybox.vert.spv", + .stage = vk::shader_stage::vertex, + }, + vk::shader_source{ + .filename = "builtin.shaders/skybox/skybox.frag.spv", + .stage = vk::shader_stage::fragment, + }, + }; + + vk::shader_resource_info shader_info = { + .sources = sources, + }; + m_skybox_shaders = vk::shader_resource(*m_device, shader_info); + m_skybox_shaders.vertex_attributes(attribute); + + + // Specifying descriptors + + std::array entries = { + vk::descriptor_entry{ + // layout (set = 0, binding = 1) uniform sampler2D textures[]; + .type = vk::descriptor_type::combined_image_sampler, + .binding_point = { + .binding = 1, + .stage = vk::shader_stage::fragment, }, - }; - const vk::write_image_descriptor image_write_desc = { - .dst_binding = 1, - .sample_images = image_writes, - }; - - m_skybox_descriptors.update(std::span(&ubo_write_desc, 1), - std::span(&image_write_desc, 1)); - - const std::array layouts = { - m_skybox_descriptors.layout(), - }; - - const std::array - blend_attachments = { - vk::color_blend_attachment_state{ .blend_enabled = false }, - }; - vk::color_blend_state blend_state = { - .logic_op_enable = false, - .logical_op = vk::logical_op::copy, - .attachments = blend_attachments, - .blend_constants = {}, - }; - - std::array dyn = { - vk::dynamic_state::viewport, - vk::dynamic_state::scissor, - }; - - // pipeline expects a non-const span - std::array pipeline_layouts = layouts; - - vk::pipeline_params pipe_info = { - .renderpass = p_renderpass, + .descriptor_count = 1, + .flags = vk::descriptor_bind_flags::partially_bound_bit | + vk::descriptor_bind_flags::update_after_bind, + }, + }; + + + // layout(set = 0, ...) + uint32_t max_descriptors = 1; + vk::descriptor_layout set0_layout = { + .slot = 0, + .max_sets = 1, + .entries = entries, // descriptor layout entries description + .descriptor_counts = std::span(&max_descriptors, 1), + }; + m_skybox_descriptor = vk::descriptor_resource(*m_device, set0_layout, vk::descriptor_layout_flags::update_after_bind_pool); + + + // specifying push constant for pipelines + std::array color_blend_attachments = { + vk::color_blend_attachment_state{}, + }; + + std::array dynamic_states = { + vk::dynamic_state::viewport, vk::dynamic_state::scissor, + }; + + uint32_t vertex_mask = static_cast(vk::shader_stage::vertex); + uint32_t fragment_mask = static_cast(vk::shader_stage::fragment); + uint32_t stage_mask = vertex_mask | fragment_mask; + m_stage = static_cast(stage_mask); + vk::push_constant_range range = { + .stage = m_stage, + .offset = 0, + .range = sizeof(environment_push_constant), + }; + + VkDescriptorSetLayout descriptor0_layout = m_skybox_descriptor.layout(); + uint32_t color_format = static_cast(m_color_format); + vk::pipeline_params skybox_pipeline_params = { + .use_render_pipeline = true, + .color_attachment_formats = std::span(&color_format, 1), + .depth_format = static_cast(m_depth_format), + .stencil_format = static_cast(m_depth_format), + .renderpass = nullptr, .shader_modules = m_skybox_shaders.handles(), - .vertex_attributes = - m_skybox_shaders.vertex_attributes(), // no vertex input - .vertex_bind_attributes = - m_skybox_shaders.vertex_bind_attributes(), // no vertex input - .descriptor_layouts = pipeline_layouts, - .input_assembly = - vk::input_assembly_state{ - .topology = vk::primitive_topology::triangle_list, - .primitive_restart_enable = false, - }, - .viewport = - vk::viewport_state{ .viewport_count = 1, .scissor_count = 1 }, - .rasterization = - vk::rasterization_state{ - .polygon_mode = vk::polygon_mode::fill, - .cull_mode = vk::cull_mode::front_bit, - .front_face = vk::front_face::clockwise, - .line_width = 1.f, - }, - .multisample = vk::multisample_state{}, - .color_blend = blend_state, + .vertex_attributes = m_skybox_shaders.vertex_attributes(), + .vertex_bind_attributes = m_skybox_shaders.vertex_bind_attributes(), + .descriptor_layouts = std::span(&descriptor0_layout, 1), + .color_blend = { + .attachments = color_blend_attachments, + }, .depth_stencil_enabled = true, - .depth_stencil = - vk::depth_stencil_state{ + .depth_stencil = { .depth_test_enable = true, .depth_write_enable = false, .depth_compare_op = vk::compare_op::less_or_equal, .depth_bounds_test_enable = false, .stencil_test_enable = false, - }, - .dynamic_states = dyn, - }; - - m_skybox_pipeline = vk::pipeline(m_device, pipe_info); - } - - void update_uniform(const skybox_uniform& p_ubo) { - // Replace with m_skybox_ubo.transfer(...) - // m_skybox_ubo.update(&p_ubo); - m_skybox_ubo.transfer(std::span(&p_ubo, 1)); - } - - [[nodiscard]] VkPipelineLayout pipeline_layout() const { - return m_skybox_pipeline.layout(); - } - - [[nodiscard]] VkPipeline pipeline() const { return m_skybox_pipeline; } - - [[nodiscard]] VkDescriptorSetLayout descriptor_layout() const { - return m_skybox_descriptors.layout(); - } - - void descriptor_bind(const VkCommandBuffer& p_command, - const VkPipelineLayout& p_pipeline_layout) { - // m_skybox_descriptors.bind(p_command, p_pipeline_layout); - } - - [[nodiscard]] VkBuffer vertex_handle() const { return m_skybox_vbo; } - - [[nodiscard]] uint32_t vertices_size() const { - return m_vertices_size; - } - - void draw(const VkCommandBuffer& p_current) { - vkCmdDraw(p_current, m_vertices_size, 1, 0, 0); - // vkCmdDrawIndexed(p_current, 36, 1, 0, 0, 0); - } - - //! @brief Retreving the sample image of the environment map. - [[nodiscard]] vk::sample_image image() const { return m_skybox_image; } - - void destroy() { - - m_skybox_image.destruct(); - if (m_skybox_pipeline.alive()) { - m_skybox_pipeline.destruct(); - } - m_skybox_descriptors.destruct(); - m_skybox_ubo.destruct(); - m_skybox_shaders.destruct(); - m_skybox_vbo.destruct(); - } - - private: - VkDevice m_device = nullptr; - vulkan::physical_device* m_physical; - uint32_t m_memory_properties; - vk::sample_image m_skybox_image; - vk::shader_resource m_skybox_shaders{}; - vk::uniform_buffer m_skybox_ubo{}; - vk::descriptor_resource m_skybox_descriptors{}; - vk::pipeline m_skybox_pipeline{}; - vk::vertex_buffer m_skybox_vbo; - uint32_t m_vertices_size=0; - }; - -}; -*/ \ No newline at end of file + }, + .dynamic_states = dynamic_states, + .push_constants = std::span(&range, 1), + }; + m_skybox_pipeline = vk::pipeline(*m_device, skybox_pipeline_params); + + vk::buffer_parameters uniform_params = { + .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | vk::buffer_usage::shader_device_address_bit, + .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, + }; + + m_skybox_uniforms = vk::dyn::buffer(*m_device, sizeof(environment_uniforms), uniform_params); + + vk::write_image environment_image = { + .sampler = m_skybox_image.sampler(), + .view = m_skybox_image.image_view(), + .layout = vk::image_layout::shader_read_only_optimal, + }; + std::array write_descriptors = { + // layout(set = 0, binding = 1) sampler2D environment; + vk::write_image_descriptor{ + .dst_binding = 1, + .sample_images = std::span(&environment_image, 1), + }, + }; + + m_skybox_descriptor.update({}, write_descriptors); + } + + void set_current_command(vk::command_buffer& p_current) { + m_current_command = &p_current; + } + + + void begin(const glm::mat4& p_proj, const glm::mat4& p_view) { + m_proj_view = p_proj * glm::mat4(glm::mat3(p_view)); + + m_skybox_pipeline.bind(*m_current_command); + environment_uniforms scene_ubo = { + .proj_view = m_proj_view, + }; + + m_skybox_uniforms.transfer(std::span(&scene_ubo, 1)); + + const VkDescriptorSet skybox_descriptor = m_skybox_descriptor; + m_current_command->bind_descriptors(m_skybox_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&skybox_descriptor, 1)); + } + + void end() { + const uint64_t scene_environment = m_skybox_uniforms.get_device_address(); + + environment_push_constant environment_push_const = { + .scene_environment_address = scene_environment, + }; + + m_skybox_pipeline.push_constant(*m_current_command, environment_push_const, m_stage, 0); + + // Binding our vertex buffers here + const VkBuffer& skybox_vertex = m_skybox_vbo; + uint64_t offset = 0; + m_current_command->bind_vertex_buffers(std::span(&skybox_vertex, 1), std::span(&offset, 1)); + + vkCmdDraw(*m_current_command, m_vertices_size, 1, 0, 0); + } + + [[nodiscard]] VkImageView image_view() const { + return m_skybox_image.image_view(); + } + + [[nodiscard]] VkSampler sampler() const { return m_skybox_image.sampler(); } + + void destruct() { + m_skybox_vbo.destruct(); + m_skybox_image.destruct(); + m_skybox_descriptor.destruct(); + m_skybox_shaders.destruct(); + m_skybox_pipeline.destruct(); + } + +private: + glm::mat4 m_proj_view; + vk::command_buffer* m_current_command; + uint64_t m_vertices_size=0; + std::shared_ptr m_device; + std::optional m_physical; + vk::vertex_buffer m_skybox_vbo; + vk::sample_image m_skybox_image; + uint32_t m_memory_mask; + vk::shader_stage m_stage; + + VkFormat m_color_format; + VkFormat m_depth_format; + vk::dyn::buffer m_skybox_uniforms; + vk::descriptor_resource m_skybox_descriptor; + vk::shader_resource m_skybox_shaders; + vk::pipeline m_skybox_pipeline; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 7d49e913..0eb29be0 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -24,6 +24,7 @@ import atlas.drivers.vulkan.stb_image; import atlas.core.utilities; import :graphics_context; +import :environment_map; import vk; export namespace atlas { @@ -84,6 +85,8 @@ export namespace atlas { render_context(/*NOLINT*/std::shared_ptr p_context, VkFormat p_color_format, VkFormat p_depth_format) { m_physical = p_context->physical_device(); m_device = p_context->logical_device(); + m_color_format = p_color_format; + m_depth_format = p_depth_format; // Vertex Attributes Parameters std::array attribute_entries = { @@ -138,7 +141,7 @@ export namespace atlas { // Configuring Descriptor Set 0 -- specify to vk::pipeline // Descriptor Set 0 uint32_t max_descriptors = 1000; - std::array entries_set1 = { + std::array entries_set1 = { vk::descriptor_entry{ // layout (set = 0, binding = 1) uniform sampler2D textures[]; .type = vk::descriptor_type::combined_image_sampler, @@ -148,7 +151,17 @@ export namespace atlas { }, .descriptor_count = max_descriptors, .flags = vk::descriptor_bind_flags::partially_bound_bit | - vk::descriptor_bind_flags::variable_descriptor_count_bit | + vk::descriptor_bind_flags::update_after_bind, + }, + vk::descriptor_entry{ + // layout (set = 0, binding = 2) uniform sampler2D environment_maps[]; + .type = vk::descriptor_type::combined_image_sampler, + .binding_point = { + .binding = 2, + .stage = vk::shader_stage::fragment, + }, + .descriptor_count = 100, + .flags = vk::descriptor_bind_flags::partially_bound_bit | vk::descriptor_bind_flags::update_after_bind, } }; @@ -291,10 +304,25 @@ export namespace atlas { } - std::array set0_samples = { + // Loading environment maps + m_environment_map = environment_map(m_device, m_physical.value(), "assets/skybox/mirrored_hall_8k.hdr", m_color_format, m_depth_format); + + vk::write_image environment_image = { + .sampler = m_environment_map.sampler(), + .view = m_environment_map.image_view(), + .layout = vk::image_layout::shader_read_only_optimal, + }; + std::array set0_samples = { + // layout(set = 0, binding = 1) sampler2D[] vk::write_image_descriptor{ .dst_binding = 1, .sample_images = m_gpu_images, + }, + + // layout(set = 0, binding = 2) samplerCube[] + vk::write_image_descriptor{ + .dst_binding = 2, + .sample_images = std::span(&environment_image, 1), } }; @@ -303,23 +331,10 @@ export namespace atlas { } void begin(const glm::mat4& p_proj, const glm::mat4& p_view) { - // vk::viewport_params viewport = { - // .x = 0.0f, - // .y = 0.0f, - // .width = static_cast(p_extent.width), - // .height = static_cast(p_extent.height), - // .min_depth = 0.0f, - // .max_depth = 1.0f, - // }; - // m_current_command->set_viewport(0, 1, std::span(&viewport, 1)); - - // vk::scissor_params scissor = { - // .offset = { 0, 0 }, - // .extent = {static_cast(p_extent.width), static_cast(p_extent.height)}, - // }; - // m_current_command->set_scissor(0, 1, std::span(&scissor, 1)); - - // m_current_command->begin_rendering(p_begin_params); + // Calculating skybox projection and view + // m_skybox_proj_view = p_proj * glm::mat4(glm::mat3(p_view)); + m_projection = p_proj; + m_view = p_view; m_main_pipeline.bind(*m_current_command); @@ -388,11 +403,18 @@ export namespace atlas { vkCmdDraw(*m_current_command, mesh.vertices_size, 1, 0, 0); } }); - // m_current_command->end_rendering(); + + + + // Draw Environments + m_environment_map.begin(m_projection, m_view); + + m_environment_map.end(); } void set_command(vk::command_buffer& p_command) { m_current_command = &p_command; + m_environment_map.set_current_command(*m_current_command); } void current_scene(flecs::world& p_world) { @@ -403,6 +425,8 @@ export namespace atlas { m_scene_uniforms.reset(); m_object_model_uniforms.reset(); + m_environment_map.destruct(); + // destroying vector for(auto& image : m_gpu_textures) { image.destruct(); @@ -419,7 +443,11 @@ export namespace atlas { } private: + glm::mat4 m_projection; + glm::mat4 m_view; uint32_t m_format; + VkFormat m_color_format; + VkFormat m_depth_format; std::optional m_physical; std::shared_ptr m_device; vk::command_buffer* m_current_command=nullptr; @@ -460,5 +488,8 @@ export namespace atlas { vk::shader_stage m_stage; flecs::world* m_world=nullptr; + + glm::mat4 m_skybox_proj_view; + environment_map m_environment_map; }; }; \ No newline at end of file diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag index 30b2f385..ebf6f9c7 100644 --- a/builtin.shaders/pbr.frag +++ b/builtin.shaders/pbr.frag @@ -6,18 +6,33 @@ layout(location = 0) in vec3 fragColor; layout(location = 1) in vec2 fragTexCoords; layout(location = 2) in vec3 fragNormals; layout(location = 3) in flat int fragDiffuseIdx; +layout(location = 4) in flat int fragEnvironmentIdx; // layout(location = 4) in flat int fragSpecularIdx; layout(location = 0) out vec4 outColor; layout(set = 0, binding = 1) uniform sampler2D textures[]; +layout(set = 0, binding = 2) uniform sampler2D environments[]; + +const vec2 inverse_atan = vec2(0.1591, 0.3183); // 1/(2*PI), 1/PI + +// Convert 3D direction to 2D Equirectangular UV coordinates +vec2 sample_spherical_map(vec3 direction) { + vec2 uv = vec2(atan(direction.z, direction.x), asin(direction.y)); + uv *= inverse_atan; + uv += 0.5; + return uv; +} void main() { - // vec4 diffuse = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); + vec4 diffuse = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); // vec4 specular = texture(textures[nonuniformEXT(fragSpecularIdx)], fragTexCoords); - outColor = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); + vec3 final_color = diffuse.rgb; + final_color = final_color / (final_color + vec3(1.0)); + final_color = pow(final_color, vec3(1.0 / 2.2)); + outColor = vec4(final_color, 1.0); // vec3 material_color = vec3(diffuse.rgb * specular.rgb); // outColor = vec4(material_color, 1.0); } \ No newline at end of file diff --git a/builtin.shaders/pbr.frag.spv b/builtin.shaders/pbr.frag.spv index 9f3f042a0bc1729991085b7765abf190d54a68a8..8038f7642e5003f41ff96a4c272632508cd2e387 100644 GIT binary patch literal 2816 zcmZ9M-Evb^6vsC-iO?3>0tG9eX)EYREh=9{q@|P+(Ljr>fS)Ia0^I2M|DEhrqC2y)*7~onz1Lo6j~twT$+-h=%pGw%Zm_1@K_Sk; ze?2kazj^*leAFFsTbqx9^(WgwBkI<(xYJ9sAWj<5UYzVGS1FILRJW>&-Ckqy@|AbU zeAJEP1;{-iuYx$#4&wyFg6O8`o@hf<6E#JXio;JEl{BJVIroQ>6ts^@HQz>(CjBIC zrdd1qwjZ|QW*lX*k7BQEY*ec2LA}!ny1nmOQP7H$C}_l4RPV*R(S9E97bo>rzcK7k zRHos57TsYtu03?ac1P*Doo}Knu7|Cl9d_Q_ZC<(|TT#C;abG6ofJNl-xyOQL-CnY0{38USP2_v=e4wTfC^wToDi3Ph)(B{PP^| z|2IchY92$cski!*0v6`^7-&@N8@5h}JZ(v2eqBpOKxO;TYH2Xh&PCBci zK6AFCxm?I)V!1n*Qw2U&ipmEj2-8I7b zYck+>R`QZKI=QZkv%sj0&J42X7vFqYL@xY4@G?05=**%78tSU z%pc2gF>{vdftTqac68oP?AFJ}lAZg0WkDUFCr?CRM&|dWu#3O{sXH0?eI*^ti2Vi9 znKSxIJ@lFg44r#wil~28cgxIhCoFuP3n_}@%lz>UvL|%rkT=hC?7VfRbEmv@!#Z!3 z>G<=`px;zJ_}e1pWZa)=Q8IfY4%@PJ#U8*d=3U8P*r<<{VqQ~4lvD^uEV)6Y{ z1ZMgpum7O)V*gA8#+?4-vCkzFhs|<=S&lCxlXF}d$nmv^J-i~q#w=SLHj4`-6ZcSc zcpsjMz*vUWC4-UAu!hGt> zHj6(k8Jus4_%kBnCq>vc{khIcCO3A@&;G&4!?|ZgU_W~QIggda%^%GCUzd!(mL_kDjk$b|07!#w3LDHCP#AJzj*KD?@R?|Em=e6+K4bl;eJX2qtjJ|vg z&c9yz`Ue!yKjjuksC@ORNDV)LWRsDfq+Syr}W+4IOpl9$VF&Hxd`>giHac+E7!<^u9 z@Ok@C!dx5wrEHF`nK4s1++h>TCb-*_{-K>>Z?)|0h2353qsdQv`+aJ}XE&Srq7Rji zH?X&5^`r-q9o4`t@tNyD-(_jI;BRZ69>I3iZC@Hb@3&9m?}@ph3wZmoA4=nsdsUhP zMs9p&!P%0(COwdl3;ud-gTu#XX3f1uRUPuv%Z@a)(I@dwrQw1TkI(-+$GYaZZ20sB zf4{y1hmX%J;Ws|>#ec2;fp?f2ha7)}c+&5LQuAX8^^R(v{epcEi`v;S{eu%jAM6?& cpSqt(sQH^>*vXy*4)}Y$%5K2^sj4@U|9FySFaQ7m diff --git a/builtin.shaders/pbr.vert b/builtin.shaders/pbr.vert index 9cdcd2a4..c836e43a 100644 --- a/builtin.shaders/pbr.vert +++ b/builtin.shaders/pbr.vert @@ -24,10 +24,12 @@ layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTexCoords; layout(location = 2) out vec3 fragNormals; layout(location = 3) out flat int fragDiffuseIdx; +layout(location = 4) out flat int fragEnvironmentIdx; layout(buffer_reference, scalar) buffer readonly SceneUniforms { mat4 view; mat4 proj; + mat4 skybox_proj_view; }; layout(buffer_reference, scalar) buffer ObjectsTable { @@ -53,4 +55,5 @@ void main() { fragTexCoords = inTexCoords; fragNormals = inNormals; fragDiffuseIdx = push_const.diffuse_idx; + fragEnvironmentIdx = 0; } \ No newline at end of file diff --git a/builtin.shaders/pbr.vert.spv b/builtin.shaders/pbr.vert.spv index 81b64f1fc54250239057f8cb7f49dfccca2cfb3d..ba5d4ad1585d2f5c0b00b123a5f43874fb025c16 100644 GIT binary patch delta 128 zcmZ1={zIIXnMs+Qfq{{Mn}L@hcp`5iBmcyFQ^uf;3tuydvof$V1Tio$q!lHmyXKW; z7Uk#VrskDwZf6c;l5}Ta221h*6}U67fZ1|DHp}L#tjx@u)<7X&AUA09MULZ4B6d*K NB0!YWeZjfwv^I}OC%)OOWhhpzsscWXTpy~Z3chs>aPV7hC>^awGA{l_t5228(MU3nWm zUwjp|-|yruYQ-$+c=x(GEzGRWv`J*;>+`-`ZMCv+El#74 zVcgnDI|aD|_?yei&83AfYPZ$+PHe;2B{p1lnT-m!ZHX)ERBEzw`EHpsnM>1bJvV_q+{q;?Y3>S_>ZXCBj|f|hY+@IZZI`9VmQ9K`iQ7oCtz0fK zSTAGHx1IeIwzKqu^gvu3)!tc4%i5#T=h7rET1i1-UA=>`Hsf?n)3JLekRO=i^0hnp z`!FK0TXPI7rQf=lDs#gXo4vJJVL!_(`vGTd#^LT|>bg5PGc9qK6szuwSR|+GV|Mb* z#jZW?=rppszFOt$#PP0=JMsotaLrqAA~a4j*+Ka(T=GIxwPNlJ#yfGzYx}w4y{SBA zGA?0ZGlxC9R`N@4i}EoKRv=l_x3~3!DE0j@r~ZqXkj-jVv-zzzj?Nsq^@H7+?2m;v z@Aur&Ba0ru;1!JBW8{FroyX9@c$eH2&bTXi*!L=%Tx|HlPu{4y0KXs$8~uc|y7q?T zq~hTL8-GJ~U!{XTs%-f7{sHNn?fuyP9+Qe1l>JLQQF}-_wdwtozK6AgVUH`8S%7h_ z&jZ6A(ass*#KJi`K9w)u02n=D^Y-cUxa+1Is`12!&gO1tL*AHq2|w8JZY?ty)?!tmd& zbaL^-HS^~jZ!>>v_`a{5bD1;wGurWi6OYaN0Gri2B#v3I=;MzNeka7jKmSL5&Tzzk z3HD?8*$+#Y{S#%wC-yT{fZx*+W&-cT!}S>nIPuiR_P%q{!N`aI^AfObe!Y4pU7Wso zC%%sh(&^)+a=HJ61dQdeOVYu(yT>k981+_kBY3_dA)k2s7bV|R7vH3$At8o4zy}z8 l;GdR&EsG88TNMV*;%s|6zOVoQ literal 1608 zcmZ9M-EPxB5QVo%ot8pdO6d85!&i*pO&+I8)d&v9N`m;WX7dqMIk zNV4EqFt3GY5p#_zX2HOtUC!GmJFq`=Q);F$G*YY;+VLBkX8mXooWxL`*dz>3V$6fq zEc8Hg8@1vvPK3Q&e;d8i)%u~+gZHq}sY-3t@ou{^78uP=aXHtB+4dDfFP10U*MEog zF`4uKaZZPJq1(3NoR5Yz8O!0lDHJZ}I!*g|xlf3hSoCx{!l9?*sDVQ($Kk{AtwA`!h71Of!mc=*Y55^45QC=?dUU%WW^~-uf@9vECP5FrP3p-f z&ink*xx}u?=uHl@at}D>AbwK@*VQe+w+arPMQ`-LxF7FuN5 Date: Wed, 10 Jun 2026 00:13:18 -0700 Subject: [PATCH 065/106] refactor: added sample experimentation for getting IBL to work after getting environment maps to load --- atlas/drivers/vulkan/render_context.cppm | 10 ++++--- builtin.shaders/pbr.frag | 33 ++++++++++++++--------- builtin.shaders/pbr.frag.spv | Bin 2816 -> 2868 bytes builtin.shaders/pbr.vert | 3 --- builtin.shaders/pbr.vert.spv | Bin 3064 -> 2976 bytes 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 0eb29be0..cb9e7b7a 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -154,13 +154,13 @@ export namespace atlas { vk::descriptor_bind_flags::update_after_bind, }, vk::descriptor_entry{ - // layout (set = 0, binding = 2) uniform sampler2D environment_maps[]; + // layout (set = 0, binding = 2) uniform sampler2D environment_map; .type = vk::descriptor_type::combined_image_sampler, .binding_point = { .binding = 2, .stage = vk::shader_stage::fragment, }, - .descriptor_count = 100, + .descriptor_count = 1, .flags = vk::descriptor_bind_flags::partially_bound_bit | vk::descriptor_bind_flags::update_after_bind, } @@ -318,14 +318,16 @@ export namespace atlas { .dst_binding = 1, .sample_images = m_gpu_images, }, - - // layout(set = 0, binding = 2) samplerCube[] + // layout(set = 0, binding = 2) sampler2D environment; vk::write_image_descriptor{ .dst_binding = 2, .sample_images = std::span(&environment_image, 1), } }; + + + m_set0_resource.update({}, set0_samples); } diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag index ebf6f9c7..b0d9bbac 100644 --- a/builtin.shaders/pbr.frag +++ b/builtin.shaders/pbr.frag @@ -6,33 +6,40 @@ layout(location = 0) in vec3 fragColor; layout(location = 1) in vec2 fragTexCoords; layout(location = 2) in vec3 fragNormals; layout(location = 3) in flat int fragDiffuseIdx; -layout(location = 4) in flat int fragEnvironmentIdx; // layout(location = 4) in flat int fragSpecularIdx; layout(location = 0) out vec4 outColor; layout(set = 0, binding = 1) uniform sampler2D textures[]; -layout(set = 0, binding = 2) uniform sampler2D environments[]; +layout(set = 0, binding = 2) uniform sampler2D environment_map; // used for IBL -const vec2 inverse_atan = vec2(0.1591, 0.3183); // 1/(2*PI), 1/PI - -// Convert 3D direction to 2D Equirectangular UV coordinates -vec2 sample_spherical_map(vec3 direction) { +const vec2 invAtan = vec2(0.1591, 0.3183); +vec2 SampleEquirectangular(vec3 v) { + vec3 direction = normalize(v); vec2 uv = vec2(atan(direction.z, direction.x), asin(direction.y)); - uv *= inverse_atan; + uv *= invAtan; uv += 0.5; return uv; } void main() { - + vec3 color = fragColor; vec4 diffuse = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); // vec4 specular = texture(textures[nonuniformEXT(fragSpecularIdx)], fragTexCoords); - vec3 final_color = diffuse.rgb; - final_color = final_color / (final_color + vec3(1.0)); - final_color = pow(final_color, vec3(1.0 / 2.2)); + vec3 albedo = diffuse.rgb; + // Map the surface normal direction to the HDR map to get diffuse ambient light + vec3 N = normalize(fragNormals); + vec2 envUV = SampleEquirectangular(N); + // Low-frequency ambient lighting from the surrounding environment + // vec3 ambientIrradiance = texture(environment_map, envUV).rgb; + vec3 ambientIrradiance = textureLod(environment_map, envUV, 4.0).rgb; + + // In a full PBR equation, this would be multiplied by your diffuse term (1.0 - metallic) * albedo + vec3 ambient = ambientIrradiance * albedo * 0.05; // Dim down slightly for a basic placeholder balance + + // 4. Combine lighting components (Direct light + Ambient IBL) + vec3 final_color = albedo + ambient * color; + outColor = vec4(final_color, 1.0); - // vec3 material_color = vec3(diffuse.rgb * specular.rgb); - // outColor = vec4(material_color, 1.0); } \ No newline at end of file diff --git a/builtin.shaders/pbr.frag.spv b/builtin.shaders/pbr.frag.spv index 8038f7642e5003f41ff96a4c272632508cd2e387..0c33824d5226fbf7763408b98f76489bfe12dcf6 100644 GIT binary patch literal 2868 zcmYk8+jR*ShuCAVCX#ey9WA>Rt=CJwE4A!{WFT@!5 zvy%hWkD3uvUwarVZ*Bxp+->AZrb03}FPgb}?R_#I zF++9(avxQek~q{3lN7^yqFbUnq7_jjI;I$WRHURKRbEY_)tW6K&C-6FG_$-N zJn4t6q?yFI?4#JLtE<)8a?t2>f^P4pRvfgFG!CL9j~l&YC*I5B{F1cM>PJO~vN9EG zESrO7Of}TQcBd6DKk3_4VY=OKh56;3<`o^FtU3?LXGc`lza!#q%Z!6!KQ7*v1Nq;T z+{jv4Zf#}Thh`pbFYRF^b49i&X*T=a*yfy--ivp8{XFhU6gF&oN8H_k-%7MQ!09LW zM!dU}WqCvZ`!0)zt*to9(1*-D>G!RzZ2M2leYG`gb*+C*wm98+@X-2{%;(~rFb~^S zKVa6x!}eAZr@fUt52GYZ8)~s)ht0aUVv{^e+p-7kuw!#RdKn|VY`&G=OwzCw3_1eF z9Ay2TZ-=R>c4p;*h=oo+rbNt^*Dp$DRdqJzihIC@Of1ugZBG1m%{B5uL0;UGOLiuS z@%fogbmozqoR9sB`pf-G_6)w>6Y|1uO8Zd*@+nEf;uXc?`lRH2PG|2a(d54u=dq)6 z-r48B&A+2NW8Y~JKH%Qxl4Pv~_MDMGKK8xkbnX?5GkzdWUfv)6ABy7(epWkN6~~T$ zae4imx_3B<>S;)3Hs}TU(0M0d-oGi?n5PTZbsx+L zePrSDTu51*SZ0QAkiQ4|%=gCY*!flz^?L<nFBDN<2%XZ@OmH_AFn@_%slu#Ldp0%7X9q@ z*pf^hZ0x~of%zPT|RF1R<=sOX0LM#TBQ0`Kv#xPOoQR?$QBaq;6$_h&dNoj5;J$0SoLy~9Qg0tG9eX)EYREh=9{q@|P+(Ljr>fS)Ia0^I2M|DEhrqC2y)*7~onz1Lo6j~twT$+-h=%pGw%Zm_1@K_Sk; ze?2kazj^*leAFFsTbqx9^(WgwBkI<(xYJ9sAWj<5UYzVGS1FILRJW>&-Ckqy@|AbU zeAJEP1;{-iuYx$#4&wyFg6O8`o@hf<6E#JXio;JEl{BJVIroQ>6ts^@HQz>(CjBIC zrdd1qwjZ|QW*lX*k7BQEY*ec2LA}!ny1nmOQP7H$C}_l4RPV*R(S9E97bo>rzcK7k zRHos57TsYtu03?ac1P*Doo}Knu7|Cl9d_Q_ZC<(|TT#C;abG6ofJNl-xyOQL-CnY0{38USP2_v=e4wTfC^wToDi3Ph)(B{PP^| z|2IchY92$cski!*0v6`^7-&@N8@5h}JZ(v2eqBpOKxO;TYH2Xh&PCBci zK6AFCxm?I)V!1n*Qw2U&ipmEj2-8I7b zYck+>R`QZKI=QZkv%sj0&J42X7vFqYL@xY4@G?05=**%78tSU z%pc2gF>{vdftTqac68oP?AFJ}lAZg0WkDUFCr?CRM&|dWu#3O{sXH0?eI*^ti2Vi9 znKSxIJ@lFg44r#wil~28cgxIhCoFuP3n_}@%lz>UvL|%rkT=hC?7VfRbEmv@!#Z!3 z>G<=`px;zJ_}e1pWZa)=Q8IfY4%@PJ#U8*d=3U8P*r<<{VqQ~4lvD^uEV)6Y{ z1ZMgpum7O)V*gA8#+?4-vCkzFhs|<=S&lCxlXF}d$nmv^J-i~q#w=SLHj4`-6ZcSc zcpsjMz*vUWC4-UAu!hGt> zHj6(k8Jus4_%kBnCq>vc{khIcCO3A@&;G&4!?|ZgU_W~QIggda%^%GCUzd!( Date: Wed, 10 Jun 2026 00:13:43 -0700 Subject: [PATCH 066/106] refactor: modify viking room scale parameters --- editor/level_scene.cppm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index e1a42eee..1466357d 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -47,10 +47,8 @@ public: atlas::game_object viking_room = entity("Viking Room"); viking_room.set({ .position = { 5, 5, 0.f }, - // .position = { 1.f, 1.f, 1.f }, .rotation = { 2.30f, 95.90f, 91.80f }, - // .rotation = { 1.f, 1.f, 1.f }, - .scale{ 1.f }, + .scale{ 10.f }, }); viking_room.set({ From 894d63e80d664376111399083fbefa6f157fc778 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 10 Jun 2026 00:15:05 -0700 Subject: [PATCH 067/106] refactor: remove unused m_skybox_proj_view parameter variable --- atlas/drivers/vulkan/render_context.cppm | 1 - 1 file changed, 1 deletion(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index cb9e7b7a..d7b994d1 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -491,7 +491,6 @@ export namespace atlas { flecs::world* m_world=nullptr; - glm::mat4 m_skybox_proj_view; environment_map m_environment_map; }; }; \ No newline at end of file From 46978215ad41f75d82e20b1ad159ddd7bea19ec6 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 10 Jun 2026 01:04:17 -0700 Subject: [PATCH 068/106] refactor: fix the camera movement and rotation to work better --- editor/level_scene.cppm | 43 +++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 1466357d..eb586d67 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -120,16 +120,13 @@ public: atlas::transform* t = m_editor_camera->get_mut(); float dt = p_delta_time; - // current default movement speed that does not applied modified speed - float default_speed = 10.f; - float rotation_speed = 1.f; + // movement speed -- higher the faster camera moves + float default_speed = 50.f; float velocity = default_speed * dt; if (atlas::event::is_mouse_pressed(mouse_button_middle)) { velocity = m_movement_speed * dt; } - float rotation_velocity = rotation_speed * dt; - glm::quat to_quaternion = atlas::to_quat(t->quaternion); glm::vec3 up = glm::rotate(to_quaternion, atlas::math::up()); @@ -161,22 +158,28 @@ public: } glm::vec2 current_cursor_pos = atlas::event::cursor_position(); + if (m_is_first_frame) { + m_last_cursor_pos = current_cursor_pos; + m_is_first_frame = false; + } + if(atlas::event::is_key_pressed(key_left_shift)) { + + // sensitivity is how fast the cursor rotates + float mouse_sensitivity = 0.01; glm::vec2 cursor_dt = current_cursor_pos - m_last_cursor_pos; - float mouse_sensitivity = 0.1; + m_last_cursor_pos = current_cursor_pos; // Store for next frame - // Update Euler angles + m_yaw -= (cursor_dt.x * mouse_sensitivity); + m_pitch -= (cursor_dt.y * mouse_sensitivity); - if(atlas::event::is_mouse_pressed(mouse_button_left)) { - t->rotation.y -= (cursor_dt.x * mouse_sensitivity) * rotation_velocity; - } - - if(atlas::event::is_mouse_pressed(mouse_button_right)) { - t->rotation.x += (cursor_dt.y * mouse_sensitivity) * rotation_velocity; - } + t->set_rotation(glm::vec3(m_pitch, m_yaw, 0.0f)); + } - // Clamp pitch to prevent the camera from flipping completely upside down (optional but recommended) - t->rotation.x = glm::clamp(t->rotation.x, -89.0f, 89.0f); + // The first frame when presseing left shift is to + // continue rotating the camera from where the original position left off + if(atlas::event::is_key_released(key_left_shift)) { + m_is_first_frame = true; } // Signal to trigger this kind of scene transition @@ -188,13 +191,8 @@ public: // }; // signal(scene_transition); // } - t->set_rotation(t->rotation); - - m_last_cursor_pos = current_cursor_pos; } - // TODO: Have this physics_update be executed during the physics - // fixed-update framerate void physics_update() {} void ui_update() { @@ -205,4 +203,7 @@ private: std::optional m_editor_camera; float m_movement_speed = 10.f; glm::vec2 m_last_cursor_pos{}; + float m_yaw=0.f; + float m_pitch=0.f; + bool m_is_first_frame=true; }; \ No newline at end of file From 000afe6a72e98a7abacd96279b6c880f4ba59775 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 10 Jun 2026 01:09:07 -0700 Subject: [PATCH 069/106] refactor: fix mouse rotation to be enabled when clicking mouse middle button instead of key presses --- editor/level_scene.cppm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index eb586d67..79dc832c 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -163,7 +163,7 @@ public: m_is_first_frame = false; } - if(atlas::event::is_key_pressed(key_left_shift)) { + if(atlas::event::is_mouse_pressed(mouse_button_middle)) { // sensitivity is how fast the cursor rotates float mouse_sensitivity = 0.01; @@ -178,7 +178,7 @@ public: // The first frame when presseing left shift is to // continue rotating the camera from where the original position left off - if(atlas::event::is_key_released(key_left_shift)) { + if(atlas::event::is_mouse_released(mouse_button_middle)) { m_is_first_frame = true; } From f291529c310b63a1ea7a44ad583835209e7e4b44 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 10 Jun 2026 11:48:05 -0700 Subject: [PATCH 070/106] refactor: add set_cursor_mode when disabling when doing camera rotations --- atlas/core/event/event.cppm | 12 ++++++++++++ atlas/drivers/importer/obj_loader.cppm | 8 +++----- editor/editor_world.cppm | 3 --- editor/level_scene.cppm | 7 +++++-- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/atlas/core/event/event.cppm b/atlas/core/event/event.cppm index 6c6da69f..33e95707 100644 --- a/atlas/core/event/event.cppm +++ b/atlas/core/event/event.cppm @@ -26,6 +26,13 @@ namespace atlas { */ enum input_state { None, Idle, Pressed, Released }; + export enum cursor_mode : uint32_t { + normal=0x00034001, + hidden=0x00034002, + disabled=0x00034003, + captured=0x00034004, + }; + struct joystick_button { int ID = -1; std::string Name = ""; @@ -143,6 +150,11 @@ namespace atlas { s_window_address = p_window; } + + void set_cursor_mode(cursor_mode p_mode) { + glfwSetInputMode(s_window_address, GLFW_CURSOR, static_cast(p_mode)); + } + // specfying listening for events void flush_events() { glfwPollEvents(); diff --git a/atlas/drivers/importer/obj_loader.cppm b/atlas/drivers/importer/obj_loader.cppm index c055356a..a6871d63 100644 --- a/atlas/drivers/importer/obj_loader.cppm +++ b/atlas/drivers/importer/obj_loader.cppm @@ -9,8 +9,6 @@ module; #include #include -#include - export module atlas.drivers.importer:obj_loader; import vk; @@ -38,18 +36,18 @@ namespace std { export namespace atlas { class obj_importer { public: - obj_importer(std::string_view p_path) { + obj_importer(const std::string& p_path) { m_load = load(p_path); } - bool load(std::string_view p_path) { + bool load(const std::string& p_path) { tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string warn; std::string err; - if(!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, p_path.data())) { + if(!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, p_path.c_str())) { return false; } diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index a80e7fa3..9398e092 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -493,8 +493,5 @@ private: atlas::ui::menu_item m_editor_menu; ui::experimental::icon m_play_icon; ui::experimental::icon m_stop_icon; - // content_browser_panel( - // std::shared_ptr p_device, - // uint32_t p_memory_properties) { content_browser_panel m_content_browser; }; \ No newline at end of file diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 79dc832c..cf026b4c 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -164,11 +164,10 @@ public: } if(atlas::event::is_mouse_pressed(mouse_button_middle)) { - + atlas::event::set_cursor_mode(atlas::cursor_mode::disabled); // sensitivity is how fast the cursor rotates float mouse_sensitivity = 0.01; glm::vec2 cursor_dt = current_cursor_pos - m_last_cursor_pos; - m_last_cursor_pos = current_cursor_pos; // Store for next frame m_yaw -= (cursor_dt.x * mouse_sensitivity); m_pitch -= (cursor_dt.y * mouse_sensitivity); @@ -180,6 +179,7 @@ public: // continue rotating the camera from where the original position left off if(atlas::event::is_mouse_released(mouse_button_middle)) { m_is_first_frame = true; + atlas::event::set_cursor_mode(atlas::cursor_mode::normal); } // Signal to trigger this kind of scene transition @@ -191,6 +191,9 @@ public: // }; // signal(scene_transition); // } + + // Store for next frame + m_last_cursor_pos = current_cursor_pos; } void physics_update() {} From a11db3c694558b5baee63d2067ff1230ff282f6a Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 10 Jun 2026 12:27:49 -0700 Subject: [PATCH 071/106] refactor: fixed serialization system to also handle invalid inputs to ensure the render context is only supplied with valid components --- atlas/core/application.cppm | 8 +- atlas/core/serialize/serializer.cppm | 32 ++++--- atlas/drivers/vulkan/environment_map.cppm | 110 ++++++++++++++++++++++ atlas/drivers/vulkan/render_context.cppm | 14 ++- editor/editor_world.cppm | 15 +-- 5 files changed, 153 insertions(+), 26 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index b877a5a2..12b1665c 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -207,14 +207,14 @@ export namespace atlas { p_pair->view = glm::inverse(p_pair->view); }); - // Setting the current scene for the renderer to start rendering the - // objects - m_render_context.current_scene(*m_current_scene); - auto start_time = std::chrono::high_resolution_clock::now(); invoke_start(m_world.get()); invoke_start(m_current_scene.get()); + // Setting the current scene for the renderer to start rendering the + // objects + m_render_context.current_scene(*m_current_scene); + // Querying editor cameras specific objects // Then using this to execute specific main cameras. auto query_camera_objects = diff --git a/atlas/core/serialize/serializer.cppm b/atlas/core/serialize/serializer.cppm index 45dcd8d9..a82cf7a2 100644 --- a/atlas/core/serialize/serializer.cppm +++ b/atlas/core/serialize/serializer.cppm @@ -92,13 +92,15 @@ namespace atlas { // Deserialize atlas::material component if (p_entity_value["Mesh Source"]) { - auto perspective_camera_data = p_entity_value["Mesh Source"]; - p_deserialize_to_object.set({ - .model_path = - perspective_camera_data["Model Path"].as(), - .diffuse = perspective_camera_data["Diffuse"].as(), - .specular = perspective_camera_data["Specular"].as(), - }); + auto mesh = p_entity_value["Mesh Source"]; + if(!mesh["Model Path"].as().empty()) { + p_deserialize_to_object.set({ + .model_path = + mesh["Model Path"].as(), + .diffuse = mesh["Diffuse"].as(), + .specular = mesh["Specular"].as(), + }); + } } if (p_entity_value["Point Light"]) { @@ -236,15 +238,17 @@ namespace atlas { } // console_log_info("Before loading environment mappings!"); - // std::string environment_map_data = ""; - // if (data["Environment"]) { - // environment_map_data = data["Environment"].as(); + std::string environment_map_data = ""; + if (data["Environment"]) { + environment_map_data = data["Environment"].as(); - // console_log_info("Environment Map Loaded Path (from yaml): {}", - // environment_map_data); - // } + console_log_info("Environment Map Loaded Path (from yaml): {}", + environment_map_data); + } - // p_registry.set({ .filepath = environment_map_data }); + if(!environment_map_data.empty()) { + p_registry.set({ .filepath = environment_map_data }); + } YAML::Node entity_objects = data["Entities"]; diff --git a/atlas/drivers/vulkan/environment_map.cppm b/atlas/drivers/vulkan/environment_map.cppm index 3bc59e6d..0e364302 100644 --- a/atlas/drivers/vulkan/environment_map.cppm +++ b/atlas/drivers/vulkan/environment_map.cppm @@ -54,6 +54,16 @@ public: construct(p_filename); } + environment_map(std::shared_ptr p_device, + vk::physical_device& p_physical, + std::span p_color, const vk::image_extent& p_extent, /*NOLINT*/VkFormat p_color_format, VkFormat p_depth_format) : m_color_format(p_color_format), m_depth_format(p_depth_format) { + /*NOLINT*/ m_device = p_device; + m_physical = p_physical; + m_memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit); + + construct(p_color, p_extent); + } + void construct(const std::string& p_filename) { bool res = create_hdr(p_filename); @@ -67,6 +77,19 @@ public: create_pipelines(); } + void construct(std::span p_color, const vk::image_extent& p_extent) { + bool res = create_hdr(p_color, p_extent); + + if (!res) { + std::println("Cannot load environment"); + } + + if (res) { + std::println("Loaded succesfully raw pixels successfully"); + } + create_pipelines(); + } + bool create_hdr(const std::string& p_filename) { stbi_set_flip_vertically_on_load(true); int w, h, channels; @@ -168,6 +191,93 @@ public: return true; } + bool create_hdr(std::span p_colors, const vk::image_extent& p_extent) { + + VkFormat texture_format = VK_FORMAT_R32G32B32A32_SFLOAT; + const uint64_t bytes_per_pixel_channel = 16; // float are 4 bytes + const uint64_t total_size_bytes = + static_cast(static_cast(p_extent.width) * p_extent.height * bytes_per_pixel_channel); + const uint64_t image_size = total_size_bytes; + + vk::buffer_parameters staging_params = { + .memory_mask = m_memory_mask, + .usage = vk::buffer_usage::transfer_src_bit, + }; + + vk::buffer staging_buffer = + vk::buffer(*m_device, image_size, staging_params); + + // Creating image handle to storing the HDR + vk::image_params skybox_params = { + .extent = { .width = static_cast(p_extent.width), .height = static_cast(p_extent.height), }, + .format = texture_format, + .memory_mask = m_memory_mask, + // .property = vk::memory_property::device_local_bit, + .aspect = vk::image_aspect_flags::color_bit, + .usage = vk::image_usage::transfer_dst_bit | + vk::image_usage::sampled_bit, + // .view_type = VK_IMAGE_VIEW_TYPE_CUBE, + }; + m_skybox_image = vk::sample_image(*m_device, skybox_params); + + // Transferring data from the CPU + std::span pixels_data( + reinterpret_cast(p_colors.data()), image_size); + staging_buffer.transfer(pixels_data); + + + // 6. Record and Execute Upload + vk::command_params upload_params = { + .levels = vk::command_levels::primary, + .queue_index = 0, // Graphics Queue + .flags = vk::command_pool_flags::reset, + }; + vk::command_buffer upload_cmd(*m_device, upload_params); + + upload_cmd.begin(vk::command_usage::one_time_submit); + + // Begin Memory Barrier: Undefined to TRANSFER_DST + m_skybox_image.memory_barrier(upload_cmd, + texture_format, + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + vk::buffer_image_copy image_copy{ + .image_offset = { .width = 0, .height = 0, .depth = 0, }, + .image_extent = skybox_params.extent, + }; + staging_buffer.copy_to_image( + upload_cmd, + m_skybox_image, + std::span(&image_copy, 1)); + + // Begin Memory Barrier: TRANSFER_DST to SHADER_READ_ONLY + m_skybox_image.memory_barrier(upload_cmd, + texture_format, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + upload_cmd.end(); + + VkQueue graphics_queue; + vkGetDeviceQueue(*m_device, 0, 0, &graphics_queue); + + VkCommandBuffer raw_cmd = upload_cmd; + VkSubmitInfo submit_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &raw_cmd, + }; + + vkQueueSubmit(graphics_queue, 1, &submit_info, nullptr); + vkQueueWaitIdle(graphics_queue); + + upload_cmd.destruct(); + staging_buffer.destruct(); + + return true; + } + void create_buffers() { std::vector vertices = { // Front Face diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index d7b994d1..262c7d43 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -243,6 +243,8 @@ export namespace atlas { all_meshes.each([this](flecs::entity p_entity){ const mesh_source* src = p_entity.get(); + std::println("ID {}: prebake(): {}",p_entity.id(), src->model_path); + vk::buffer_parameters vertex_params = { .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), .usage = vk::buffer_usage::transfer_dst_bit | vk::buffer_usage::vertex_buffer_bit, @@ -304,8 +306,16 @@ export namespace atlas { } - // Loading environment maps - m_environment_map = environment_map(m_device, m_physical.value(), "assets/skybox/mirrored_hall_8k.hdr", m_color_format, m_depth_format); + // Ensure that we load the environment + // We should never load an invalid environment + if(m_world->has()) { + const environment* environment_data = m_world->get(); + m_environment_map = environment_map(m_device, m_physical.value(), environment_data->filepath, m_color_format, m_depth_format); + } + else { + std::array black_color = {0.f, 0.f, 0.f, 0.f}; + m_environment_map = environment_map(m_device, m_physical.value(), black_color, vk::image_extent{.width=1, .height=1}, m_color_format, m_depth_format); + } vk::write_image environment_image = { .sampler = m_environment_map.sampler(), diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 9398e092..f27ad8e2 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -102,12 +102,12 @@ public: ~editor_world() override = default; void preload_assets() { - // m_deserializer_test = atlas::serializer(); + m_deserializer_test = atlas::serializer(); - // if (!m_deserializer_test.load("LevelScene-small", *m_current_scene)) - // { - // console_log_error("Could not load yaml file LevelScene!!!"); - // } + if (!m_deserializer_test.load("LevelScene", *m_current_scene)) + { + console_log_error("Could not load yaml file LevelScene!!!"); + } m_physics_engine = atlas::physics::engine(*m_current_scene, *m_bus); } @@ -457,7 +457,10 @@ public: else if (m_scene_state == scene_runtime::play) { m_scene_state = scene_runtime::edit; m_physics_engine.stop(); - // reset_objects(); + + if (!m_deserializer_test.load("LevelScene", *m_current_scene)) { + console_log_error("Could not load yaml file LevelScene!!!"); + } } } From d9f3ef039c1b9c3fec767618fbdf39e1e2deaf5c Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 10 Jun 2026 12:30:18 -0700 Subject: [PATCH 072/106] refactor: updated imgui.ini --- imgui.ini | 86 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 27 deletions(-) diff --git a/imgui.ini b/imgui.ini index aceffcd7..d6b0e057 100644 --- a/imgui.ini +++ b/imgui.ini @@ -1,6 +1,6 @@ [Window][Debug##Default] ViewportPos=1901,-8 -ViewportId=0x9F5F46A1 +ViewportId=0x16723995 Size=1485,757 Collapsed=0 @@ -13,14 +13,14 @@ Collapsed=0 DockId=0x00000007,0 [Window][Viewport] -Pos=425,64 -Size=1085,615 +Pos=356,76 +Size=917,551 Collapsed=0 -DockId=0x0000000F,0 +DockId=0x00000010,0 [Window][Scene Heirarchy] Pos=0,19 -Size=423,429 +Size=354,429 Collapsed=0 DockId=0x0000000A,0 @@ -38,10 +38,10 @@ Size=1510,877 Collapsed=0 [Window][Content Browser] -Pos=425,681 -Size=1085,196 +Pos=356,629 +Size=917,248 Collapsed=0 -DockId=0x0000000D,0 +DockId=0x00000013,0 [Window][Dear ImGui Demo] ViewportPos=1937,14 @@ -54,32 +54,64 @@ ViewportPos=713,260 ViewportId=0x4AD707D2 Size=480,242 Collapsed=0 -DockId=0x0000000C,1 +DockId=0x6DCE998E,1 [Window][Properties] Pos=0,450 -Size=423,427 +Size=354,427 Collapsed=0 -DockId=0x0000000C,0 +DockId=0x0000000B,0 [Window][##toolbox] -Pos=425,19 -Size=1085,43 +Pos=356,19 +Size=917,55 +Collapsed=0 +DockId=0x0000000F,0 + +[Window][Materials Properties] +Pos=1088,143 +Size=399,201 +Collapsed=0 +DockId=0x00000002,0 + +[Window][Specular] +Pos=1035,305 +Size=399,202 +Collapsed=0 +DockId=0x00000012,0 + +[Window][Diffuse] +Pos=1035,106 +Size=399,197 Collapsed=0 -DockId=0x0000000E,0 +DockId=0x00000011,0 + +[Window][Material Editor] +Pos=1275,19 +Size=235,858 +Collapsed=0 +DockId=0x0000000D,0 [Docking][Data] -DockSpace ID=0x6DCE998E Window=0x091AB4BE Pos=965,301 Size=1510,858 Split=X - DockNode ID=0x00000003 Parent=0x6DCE998E SizeRef=423,858 Split=Y Selected=0x2182E8B1 - DockNode ID=0x0000000A Parent=0x00000003 SizeRef=751,429 HiddenTabBar=1 Selected=0x2182E8B1 - DockNode ID=0x0000000C Parent=0x00000003 SizeRef=751,427 HiddenTabBar=1 Selected=0x199AB496 - DockNode ID=0x00000008 Parent=0x6DCE998E SizeRef=1085,858 Split=X - DockNode ID=0x00000004 Parent=0x00000008 SizeRef=411,445 Split=Y Selected=0x2182E8B1 - DockNode ID=0x00000006 Parent=0x00000004 SizeRef=209,242 Split=Y Selected=0x199AB496 - DockNode ID=0x0000000B Parent=0x00000006 SizeRef=757,660 Split=Y Selected=0x13926F0B - DockNode ID=0x0000000E Parent=0x0000000B SizeRef=885,43 HiddenTabBar=1 Selected=0x804D7EB5 - DockNode ID=0x0000000F Parent=0x0000000B SizeRef=885,615 HiddenTabBar=1 Selected=0x13926F0B - DockNode ID=0x0000000D Parent=0x00000006 SizeRef=757,196 CentralNode=1 HiddenTabBar=1 Selected=0xBF096F38 - DockNode ID=0x00000007 Parent=0x00000004 SizeRef=209,511 Selected=0xB5796446 - DockNode ID=0x00000005 Parent=0x00000008 SizeRef=1096,445 Selected=0x13926F0B +DockNode ID=0x00000001 Pos=1240,208 Size=399,401 Split=Y + DockNode ID=0x00000002 Parent=0x00000001 SizeRef=399,201 Selected=0x920F10F9 + DockNode ID=0x00000009 Parent=0x00000001 SizeRef=399,198 Split=Y Selected=0xDCAC6044 + DockNode ID=0x00000011 Parent=0x00000009 SizeRef=399,197 Selected=0xD3AF05B3 + DockNode ID=0x00000012 Parent=0x00000009 SizeRef=399,202 Selected=0xDCAC6044 +DockSpace ID=0x6DCE998E Pos=965,301 Size=1510,858 Split=X HiddenTabBar=1 + DockNode ID=0x00000004 Parent=0x6DCE998E SizeRef=411,445 Split=Y Selected=0x2182E8B1 + DockNode ID=0x00000006 Parent=0x00000004 SizeRef=209,242 CentralNode=1 HiddenTabBar=1 Selected=0x199AB496 + DockNode ID=0x00000007 Parent=0x00000004 SizeRef=209,511 Selected=0xB5796446 + DockNode ID=0x00000005 Parent=0x6DCE998E SizeRef=1096,445 Selected=0x13926F0B +DockSpace ID=0x7FD4D3C2 Window=0xCEBF5101 Pos=965,301 Size=1510,858 Split=X + DockNode ID=0x0000000C Parent=0x7FD4D3C2 SizeRef=1273,858 Split=X + DockNode ID=0x00000003 Parent=0x0000000C SizeRef=354,858 Split=Y Selected=0x09F641C8 + DockNode ID=0x0000000A Parent=0x00000003 SizeRef=373,429 Selected=0x09F641C8 + DockNode ID=0x0000000B Parent=0x00000003 SizeRef=373,427 Selected=0x8C72BEA8 + DockNode ID=0x00000008 Parent=0x0000000C SizeRef=917,858 Split=Y + DockNode ID=0x0000000E Parent=0x00000008 SizeRef=898,608 Split=Y Selected=0xC450F867 + DockNode ID=0x0000000F Parent=0x0000000E SizeRef=898,55 HiddenTabBar=1 Selected=0x2B095A26 + DockNode ID=0x00000010 Parent=0x0000000E SizeRef=898,551 HiddenTabBar=1 Selected=0xC450F867 + DockNode ID=0x00000013 Parent=0x00000008 SizeRef=898,248 CentralNode=1 HiddenTabBar=1 Selected=0x3DF3100E + DockNode ID=0x0000000D Parent=0x7FD4D3C2 SizeRef=235,858 HiddenTabBar=1 Selected=0x3D0FF072 From dbabd6b1cf2f0ddb63a288de44a945f91e82456b Mon Sep 17 00:00:00 2001 From: = <=> Date: Wed, 10 Jun 2026 12:49:46 -0700 Subject: [PATCH 073/106] refactor: fix the window parameters specification to the rendering attachments --- atlas/core/application.cppm | 17 +++++++++-------- atlas/drivers/vulkan/window.cppm | 11 ++++++++--- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 12b1665c..84db514b 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -59,7 +59,7 @@ export namespace atlas { m_device = p_context->logical_device(); // Constructing the application - window_params params = { + m_window_params = { .width = p_params.width, .height = p_params.height, .name = p_params.name, @@ -67,9 +67,9 @@ export namespace atlas { // m_window = std::allocate_shared(, // m_context->instance_handle(), params); - m_window = std::make_shared(p_context, params); + m_window = std::make_shared(p_context, m_window_params); - m_aspect_ratio = static_cast(params.width) / static_cast(params.height); + m_aspect_ratio = static_cast(m_window_params.width) / static_cast(m_window_params.height); event::set_window_size(m_window->glfw_window()); m_bus->create_listener(); @@ -155,7 +155,7 @@ export namespace atlas { // VK_FORMAT_B8G8R8A8_UNORM, m_color_format, m_depth_format, - params); + m_window_params); std::println("images.size() = {}", images.size()); m_window->center_window(); @@ -306,7 +306,7 @@ export namespace atlas { }; vk::rendering_begin_parameters ui_begin_params = { - .render_area = { { 0, 0 }, { m_window->extent().width, m_window->extent().height }, }, + .render_area = { { 0, 0 }, { m_window_params.width, m_window_params.height }, }, .layer_count = 1, .color_attachments = std::span( &ui_color_render_attachment, 1), @@ -317,8 +317,8 @@ export namespace atlas { vk::viewport_params viewport = { .x = 0.0f, .y = 0.0f, - .width = static_cast(m_window->extent().width), - .height = static_cast(m_window->extent().height), + .width = static_cast(m_window_params.width), + .height = static_cast(m_window_params.height), .min_depth = 0.0f, .max_depth = 1.0f, }; @@ -326,7 +326,7 @@ export namespace atlas { vk::scissor_params scissor = { .offset = { 0, 0 }, - .extent = {static_cast(m_window->extent().width), static_cast(m_window->extent().height)}, + .extent = {static_cast(m_window_params.width), static_cast(m_window_params.height)}, }; current.set_scissor(0, 1, std::span(&scissor, 1)); @@ -482,6 +482,7 @@ export namespace atlas { std::vector m_depth_images; std::vector m_command_buffers; float m_delta_time = 0.f; + window_params m_window_params{}; static application* s_instance; }; diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 5a2cabed..d76ca3cd 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -4,6 +4,7 @@ module; #include #include #include +#include #define GLFW_INCLUDE_VULKAN #if _WIN32 @@ -57,9 +58,11 @@ export namespace atlas { m_params.width = static_cast(framebuffer_width); m_params.height = static_cast(framebuffer_height); + std::println("Window created with extent: {}x{}", m_params.width, m_params.height); + vk::swapchain_params swapchain_params = { - .width = static_cast(p_params.width), - .height = static_cast(p_params.height), + .width = static_cast(m_params.width), + .height = static_cast(m_params.height), .present_index = 0, }; @@ -143,7 +146,9 @@ export namespace atlas { return !glfwWindowShouldClose(m_window); } - [[nodiscard]] window_params extent() const { return m_params; } + [[nodiscard]] window_params extent() const { + return m_params; + } private: vk::instance m_instance; From e0bbfff898680ef7c28a281400a237d1a3994936 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 10 Jun 2026 13:14:29 -0700 Subject: [PATCH 074/106] refactor: re-added back specular access to shaders and re-fixed the texture coordinates to enable flipped --- atlas/drivers/importer/obj_loader.cppm | 31 +++++++++++++++++++---- atlas/drivers/vulkan/render_context.cppm | 27 +++++++++++--------- builtin.shaders/pbr.frag | 4 +-- builtin.shaders/pbr.frag.spv | Bin 2868 -> 3128 bytes builtin.shaders/pbr.vert | 12 +++++++++ builtin.shaders/pbr.vert.spv | Bin 2976 -> 3164 bytes 6 files changed, 55 insertions(+), 19 deletions(-) diff --git a/atlas/drivers/importer/obj_loader.cppm b/atlas/drivers/importer/obj_loader.cppm index a6871d63..732bcdc6 100644 --- a/atlas/drivers/importer/obj_loader.cppm +++ b/atlas/drivers/importer/obj_loader.cppm @@ -36,7 +36,7 @@ namespace std { export namespace atlas { class obj_importer { public: - obj_importer(const std::string& p_path) { + obj_importer(const std::string& p_path, bool p_flip) : m_flip(p_flip) { m_load = load(p_path); } @@ -84,11 +84,31 @@ export namespace atlas { }; } - if (index.texcoord_index >= 0) { - vertex.uv = { - attrib.texcoords[2 * index.texcoord_index + 0], - 1.0f - attrib.texcoords[2 * index.texcoord_index + 1] + if (!attrib.texcoords.empty()) { + glm::vec2 flipped_uv = { + attrib.texcoords[static_cast( + index.texcoord_index) * + 2], + 1.0f - attrib.texcoords[static_cast( + index.texcoord_index) * + 2 + + 1], }; + + glm::vec2 original_uv = { + attrib.texcoords[static_cast( + index.texcoord_index) * + 2], + attrib.texcoords[static_cast( + index.texcoord_index) * + 2 + + 1], + }; + + vertex.uv = m_flip ? flipped_uv : original_uv; + } + else { + vertex.uv = glm::vec2(0.f, 0.f); } if (!unique_vertices.contains(vertex)) { @@ -121,6 +141,7 @@ export namespace atlas { private: std::vector m_vertices; std::vector m_indices; + bool m_flip=false; bool m_load=false; }; }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 262c7d43..846df980 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -46,7 +46,8 @@ export namespace atlas { uint64_t scene_address=0; uint64_t model_mat_array_address=0; uint32_t model_idx=0; - uint32_t material_address=0; + uint32_t diffuse_idx=0; + uint32_t specular_idx=0; }; struct scene_uniforms { @@ -60,6 +61,7 @@ export namespace atlas { struct gpu_material { uint64_t diffuse_idx=0; + uint64_t specular_idx=0; }; @@ -256,7 +258,7 @@ export namespace atlas { }; // importing .obj 3d models here - obj_importer importer(src->model_path); + obj_importer importer(src->model_path, src->flip); gpu_mesh_data gpu_mesh{}; gpu_mesh.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); gpu_mesh.index = vk::index_buffer(*m_device, importer.indices(), index_params); @@ -280,18 +282,18 @@ export namespace atlas { m_gpu_textures.emplace_back(*m_device, &diffuse_img, config_texture); } - m_material_table.emplace(p_entity.id(), material); - /* + if(!src->specular.empty()) { std::println("Loading specular: {}", src->specular); - gpu_image specular_store_image { - .slot = m_texture_slot_index++, - .texture_data = vk::texture(*m_device, &specular_img, config_texture), - }; - - m_gpu_storage_images.emplace(p_entity.id(), specular_store_image); + // gpu_image specular_store_image { + // .slot = m_texture_slot_index++, + // .texture_data = vk::texture(*m_device, &specular_img, config_texture), + // }; + material.specular_idx = m_texture_slot_index++; + m_gpu_textures.emplace_back(*m_device, &specular_img, config_texture); } - */ + + m_material_table.emplace(p_entity.id(), material); }); // Preparing the texture data before we update descriptor set 0 @@ -397,7 +399,8 @@ export namespace atlas { .scene_address = scene_ubo_address, .model_mat_array_address = objects_ubo_address, .model_idx = static_cast(m_model_matrices_lookup[p_entity.id()]), - .material_address = static_cast(m_material_table[p_entity.id()].diffuse_idx), + .diffuse_idx = static_cast(m_material_table[p_entity.id()].diffuse_idx), + .specular_idx = static_cast(m_material_table[p_entity.id()].specular_idx), }; m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag index b0d9bbac..71fb1a12 100644 --- a/builtin.shaders/pbr.frag +++ b/builtin.shaders/pbr.frag @@ -6,7 +6,7 @@ layout(location = 0) in vec3 fragColor; layout(location = 1) in vec2 fragTexCoords; layout(location = 2) in vec3 fragNormals; layout(location = 3) in flat int fragDiffuseIdx; -// layout(location = 4) in flat int fragSpecularIdx; +layout(location = 4) in flat int fragSpecularIdx; layout(location = 0) out vec4 outColor; @@ -25,7 +25,7 @@ vec2 SampleEquirectangular(vec3 v) { void main() { vec3 color = fragColor; vec4 diffuse = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); - // vec4 specular = texture(textures[nonuniformEXT(fragSpecularIdx)], fragTexCoords); + vec4 specular = texture(textures[nonuniformEXT(fragSpecularIdx)], fragTexCoords); vec3 albedo = diffuse.rgb; // Map the surface normal direction to the HDR map to get diffuse ambient light diff --git a/builtin.shaders/pbr.frag.spv b/builtin.shaders/pbr.frag.spv index 0c33824d5226fbf7763408b98f76489bfe12dcf6..be0595a427a434b11fc4b1e685ca315a836ef497 100644 GIT binary patch delta 1240 zcmZ9M%T7~K6oyxOdRhozqBX|EXuOOJ(L{|#G@zIitU>{iiZ?DhZave#aFw|ggko*ePg7jkAP8?q7W^hTo8 zQ18R(!6`Fa5b8g^l~Y~c3bH$`aAUh3v}KxaStDk%9c(T3^f&PPu1h^>0Z}!JswfSwECjoGeX93&+cp8JC4t@;sN`?e>>y) zB_}OVgD%b;;^)Qr@Yl5x&zIlb_PliWmQ1!z3AYt;Su3MW_=IfA@{P)$)%x7Aox2I& z5dZyaX8f%DuVs6}6@hwiwnaZ&RzC^RtA2M zuO8xz_@F6+Owo3jDe)?8mK#gn;wm)D0vI88qi7KC997QQGjddlKs3tlLC zlEX_x!^d#oV``6fSA<~!9Y4cFBUi_pvZo^4Cjtr21cFwzJ^hyjV$gY3+;wu47qan} z-BGv)l%%b7*=Pw5WOLk4YK@~+gmnS^OJA$XM&||5E_aER)Yz0wjf8K>CPuvLioO)N zBqW>EWD|t`vA@YH*%ZRZCZSfeq-Z1?Z9(xoZ~ZYC8egKdWTSC6`$4Kky(yAp{R18@%ZHu_ha1G#bavtTP)oW_H6WUPM+8 zUWH|jo;-S#c<}07k0SmzzF#|yU=NS3_o}L^t9rg3`Es~k3eVKc0^4tOdp4D7$(m z6cGwd)#8*>|MAn}Ed0sd@6v%Vy&%d}1L3mdMeU@r=ESSo?>hG8isu{RKfbpbC*^-4 zyClpDv?z7p2pO0x{_C3++*%^PXIunWOnL9?Rwo&pWE`g1oRPeqQiJV%Z&GQ+Qhx>B{CH zd=!baqxmyZ*=Q?@=V#jz&{$r3DjTiATY0fxh>WdWjB{Hy2atfjCs33>a(geH{uTTI Dn9pC8 diff --git a/builtin.shaders/pbr.vert b/builtin.shaders/pbr.vert index 9cdcd2a4..7e154dea 100644 --- a/builtin.shaders/pbr.vert +++ b/builtin.shaders/pbr.vert @@ -24,6 +24,16 @@ layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTexCoords; layout(location = 2) out vec3 fragNormals; layout(location = 3) out flat int fragDiffuseIdx; +layout(location = 4) out flat int fragSpecularIdx; + +// struct material { +// int diffuse_idx; +// int specular_idx; +// }; + +// layout(bufer_reference, scalar) buffer readonly MaterialUniforms { +// material materials[]; +// }; layout(buffer_reference, scalar) buffer readonly SceneUniforms { mat4 view; @@ -39,6 +49,7 @@ layout(push_constant) uniform Constants { ObjectsTable objects; int model_matrix_idx; int diffuse_idx; + int specular_idx; } push_const; @@ -53,4 +64,5 @@ void main() { fragTexCoords = inTexCoords; fragNormals = inNormals; fragDiffuseIdx = push_const.diffuse_idx; + fragSpecularIdx = push_const.specular_idx; } \ No newline at end of file diff --git a/builtin.shaders/pbr.vert.spv b/builtin.shaders/pbr.vert.spv index 81b64f1fc54250239057f8cb7f49dfccca2cfb3d..6c62799b77b41f42ba86004ada26925714779a3f 100644 GIT binary patch delta 260 zcmZ1=en*0rnMs+Qfq{{Mn}L@hY$9(WBmcyFQ^uf;3)2~;*%;Uv_!$@&Sb(^=AT_x( zC$T6#Go=E^-OSF^$|%mtz{U^+CV6m*24!Bat9g>(k}fz!py?B`3{Q*<75Z6 hS=?+4{0s~XY(UJr`6XL4)8-V;156x$f!ZyA7y#M}5!V0! From f7fc8d4298d753221046dea9bf21a7ce774461a7 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 10 Jun 2026 17:00:23 -0700 Subject: [PATCH 075/106] refactor: added parameter to be serialized for flipping the texture coords --- LevelScene | 3 ++ atlas/core/application.cppm | 4 ++- atlas/core/serialize/serializer.cppm | 1 + atlas/core/serialize/types.cppm | 2 ++ atlas/core/utilities/poll_state.cppm | 35 ++++++++---------------- atlas/core/utilities/state.cppm | 11 ++++++++ atlas/drivers/vulkan/render_context.cppm | 8 ------ editor/editor_world.cppm | 11 ++++++-- editor/icon.cppm | 5 +++- editor/level_scene.cppm | 14 ++++++++++ 10 files changed, 57 insertions(+), 37 deletions(-) diff --git a/LevelScene b/LevelScene index f7355b9b..4b88ca90 100644 --- a/LevelScene +++ b/LevelScene @@ -8,6 +8,7 @@ Entities: Rotation: [0, 0, 0] Quaternion: [0, 0, 0, 1] Mesh Source: + Flip: 0 Model Path: "" Diffuse: "" Specular: "" @@ -24,6 +25,7 @@ Entities: Rotation: [2.29999995, 95.9000015, 91.8000031] Quaternion: [0, 0, 0, 1] Mesh Source: + Flip: 1 Model Path: assets/models/viking_room.obj Diffuse: assets/models/viking_room.png Specular: "" @@ -56,6 +58,7 @@ Entities: Rotation: [2.9000001, 16.5, 0.600000024] Quaternion: [-1.5550123e-08, -1.33205403e-05, -1.63867355e-08, 1] Mesh Source: + Flip: 0 Model Path: assets/models/cube.obj Diffuse: assets/models/container_diffuse.png Specular: assets/models/wallace_gromit_image.jpg diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 84db514b..10c8683c 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -401,7 +401,6 @@ export namespace atlas { m_imgui_context->end(); current.end_rendering(); - m_images[m_next_image_frame_idx].memory_barrier( current, m_window->surface_properties().format.format, @@ -417,6 +416,9 @@ export namespace atlas { // Update platform window afterwards m_imgui_context->update_platforms(); } + + invoke_post_update(m_current_scene.get()); + invoke_post_update(m_world.get()); } // Experimental: Will look into later once we dive into scene diff --git a/atlas/core/serialize/serializer.cppm b/atlas/core/serialize/serializer.cppm index a82cf7a2..bcc32094 100644 --- a/atlas/core/serialize/serializer.cppm +++ b/atlas/core/serialize/serializer.cppm @@ -95,6 +95,7 @@ namespace atlas { auto mesh = p_entity_value["Mesh Source"]; if(!mesh["Model Path"].as().empty()) { p_deserialize_to_object.set({ + .flip = static_cast(mesh["Flip"].as()), .model_path = mesh["Model Path"].as(), .diffuse = mesh["Diffuse"].as(), diff --git a/atlas/core/serialize/types.cppm b/atlas/core/serialize/types.cppm index e576edae..731d730a 100644 --- a/atlas/core/serialize/types.cppm +++ b/atlas/core/serialize/types.cppm @@ -404,6 +404,8 @@ export namespace atlas { p_output << YAML::Key << "Mesh Source"; p_output << YAML::BeginMap; + p_output << YAML::Key << "Flip" << YAML::Value + << p_material->flip; p_output << YAML::Key << "Model Path" << YAML::Value << p_material->model_path; p_output << YAML::Key << "Diffuse" << YAML::Value diff --git a/atlas/core/utilities/poll_state.cppm b/atlas/core/utilities/poll_state.cppm index ebc93631..4568cbc6 100644 --- a/atlas/core/utilities/poll_state.cppm +++ b/atlas/core/utilities/poll_state.cppm @@ -1,5 +1,6 @@ module; +#include #include #include #include @@ -17,6 +18,8 @@ export namespace atlas { s_physica_update{}; inline std::unordered_map>> s_start{}; + inline std::unordered_map>> + s_post{}; void poll_update(void* p_address, const std::function& p_callback) { @@ -42,26 +45,8 @@ export namespace atlas { s_start[p_address].emplace_back(p_callback); } - // TEMP: This is a temporary solution, should look into doing this - // differently - void remove_update(void* p_address) { - s_update.erase(p_address); - } - - void remove_defer_update(void* p_address) { - s_defer_update.erase(p_address); - } - - void remove_physics_update(void* p_address) { - s_physica_update.erase(p_address); - } - - void remove_ui_update(void* p_address) { - s_ui_update.erase(p_address); - } - - void remove_start(void* p_address) { - s_start.erase(p_address); + void post_update_poll(void* p_address, const std::function& p_callback) { + s_post[p_address].emplace_back(p_callback); } /** @@ -82,10 +67,6 @@ export namespace atlas { * */ void invoke_on_update(void* p_scene, float p_delta_time) { - // for (auto& [address, on_update] : s_update) { - // on_update(p_delta_time); - // } - for (auto& on_update : s_update[p_scene]) { on_update(p_delta_time); } @@ -114,4 +95,10 @@ export namespace atlas { on_update(); } } + + void invoke_post_update(void* p_scene) { + for (auto& post_update : s_post[p_scene]) { + post_update(); + } + } }; \ No newline at end of file diff --git a/atlas/core/utilities/state.cppm b/atlas/core/utilities/state.cppm index 48a55ea3..05b53f4c 100644 --- a/atlas/core/utilities/state.cppm +++ b/atlas/core/utilities/state.cppm @@ -169,4 +169,15 @@ export namespace atlas { (p_instance->*p_callable)(); }); } + + + template + void register_post(UObject* p_instance, const UCallback& p_callable) { + static_assert(std::is_member_pointer_v, + "Cannot register a function that is not a member " + "function of a class object"); + post_update_poll(p_instance, [p_instance, p_callable]() { + (p_instance->*p_callable)(); + }); + } }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 846df980..c3b55c62 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -1,7 +1,6 @@ module; #include -#include #include #include #include @@ -244,8 +243,6 @@ export namespace atlas { all_meshes.each([this](flecs::entity p_entity){ const mesh_source* src = p_entity.get(); - - std::println("ID {}: prebake(): {}",p_entity.id(), src->model_path); vk::buffer_parameters vertex_params = { .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), @@ -284,11 +281,6 @@ export namespace atlas { if(!src->specular.empty()) { - std::println("Loading specular: {}", src->specular); - // gpu_image specular_store_image { - // .slot = m_texture_slot_index++, - // .texture_data = vk::texture(*m_device, &specular_img, config_texture), - // }; material.specular_idx = m_texture_slot_index++; m_gpu_textures.emplace_back(*m_device, &specular_img, config_texture); } diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index f27ad8e2..78cca9c3 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -1,5 +1,7 @@ module; +#include +#include #include #include @@ -97,6 +99,7 @@ public: atlas::register_update(this, &editor_world::update); atlas::register_physics(this, &editor_world::physics_update); atlas::register_ui(this, &editor_world::ui_update); + atlas::register_post(this, &editor_world::unload_assets); } ~editor_world() override = default; @@ -104,8 +107,7 @@ public: void preload_assets() { m_deserializer_test = atlas::serializer(); - if (!m_deserializer_test.load("LevelScene", *m_current_scene)) - { + if (!m_deserializer_test.load("LevelScene", *m_current_scene)) { console_log_error("Could not load yaml file LevelScene!!!"); } @@ -476,9 +478,12 @@ public: } } - void destruct() { + void unload_assets() { + // console_log_info("Unloading Assets"); + m_play_icon.destroy(); m_stop_icon.destroy(); + m_content_browser.destroy(); } private: diff --git a/editor/icon.cppm b/editor/icon.cppm index 749b07e8..47e54829 100644 --- a/editor/icon.cppm +++ b/editor/icon.cppm @@ -71,7 +71,10 @@ export namespace ui::experimental { return m_icon_image_id; } - void destroy() { m_icon_image.destruct(); } + void destroy() { + m_icon_image.destruct(); + ImGui_ImplVulkan_RemoveTexture(m_icon_image_id); + } private: std::shared_ptr m_device; diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index cf026b4c..f13ed5c4 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -72,6 +72,20 @@ public: .half_extent = { 15.f, 0.30f, 10.0f }, }); + atlas::game_object backpack = entity("Backpack"); + + backpack.set({ + .position = { 0.f, 2.10f, -7.30f }, + .scale = { 0.9f, 0.9f, 0.9f }, + }); + + backpack.set({ + .color = { 1.f, 1.f, 1.f, 1.f }, + .model_path = "assets/backpack/backpack.obj", + .diffuse = "assets/backpack/diffuse.jpg", + .specular = "assets/backpack/specular.jpg" + }); + // const size_t grid_width = 5; // const float spacing = 5; From 5d530881add6ef1bb84fcf809b6d2e9168bb3bf8 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Wed, 10 Jun 2026 20:00:43 -0700 Subject: [PATCH 076/106] refactor: re-added point lighting back to the rendering system --- atlas/drivers/vulkan/render_context.cppm | 55 ++++++++++++ builtin.shaders/pbr.frag | 110 ++++++++++++++++++++--- builtin.shaders/pbr.frag.spv | Bin 3128 -> 9240 bytes builtin.shaders/pbr.vert | 31 ++++++- builtin.shaders/pbr.vert.spv | Bin 3164 -> 4312 bytes 5 files changed, 183 insertions(+), 13 deletions(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index c3b55c62..640b26aa 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -47,6 +47,7 @@ export namespace atlas { uint32_t model_idx=0; uint32_t diffuse_idx=0; uint32_t specular_idx=0; + uint64_t point_light_address; }; struct scene_uniforms { @@ -63,6 +64,24 @@ export namespace atlas { uint64_t specular_idx=0; }; + struct gpu_point_light { + glm::vec4 position; // this is provided by the transform + glm::vec4 color = { 1.f, 1.f, 1.f, 1.f }; + float attenuation = 1.f; + float constant = 1.f; + float linear = 1.f; + float quadratic = 1.f; + + glm::vec4 ambient = glm::vec4(1.f); + glm::vec4 diffuse = glm::vec4(1.f); + glm::vec4 specular = glm::vec4(1.f); + }; + + struct light_scene_ubo { + alignas(16) uint32_t num_lights=0; + alignas(16) std::array point_lights{}; + }; + /** * @@ -228,6 +247,10 @@ export namespace atlas { uint32_t max_objects = 10'000; m_object_model_uniforms = vk::dyn::buffer(*m_device, sizeof(objects_uniform) * max_objects, uniform_params); + + // configuring uniforms for point lights + m_lighting_uniforms = vk::dyn::buffer(*m_device, sizeof(light_scene_ubo), uniform_params); + // Index 0 will default to a white texture vk::image_extent extent = { .width = 1, @@ -342,6 +365,35 @@ export namespace atlas { m_projection = p_proj; m_view = p_view; + + // querying for objects with point lights + flecs::query all_point_lights = m_world->query_builder().build(); + + int index = 0; + light_scene_ubo scene_point_lights{}; + all_point_lights.each([&index, &scene_point_lights](flecs::entity p_entity, point_light& p_light){ + const transform* t = p_entity.get(); + p_light.position = t->position; + + scene_point_lights.point_lights[index] = { + .position = glm::vec4(p_light.position, 1.f), + .color = p_light.color, + .attenuation = p_light.attenuation, + .constant = p_light.constant, + .linear = p_light.linear, + .quadratic = p_light.quadratic, + .ambient = p_light.ambient, + .diffuse = p_light.diffuse, + .specular = p_light.specular, + }; + + index++; + }); + + scene_point_lights.num_lights = index; + + m_lighting_uniforms.transfer(std::span(&scene_point_lights, 1)); + m_main_pipeline.bind(*m_current_command); flecs::query<> all_meshes = m_world->query_builder().build(); @@ -387,12 +439,14 @@ export namespace atlas { // Retrieving the buffer address that can be looked up from the glsl shader const uint64_t scene_ubo_address = m_scene_uniforms.get_device_address(); const uint64_t objects_ubo_address = m_object_model_uniforms.get_device_address(); + const uint64_t lighting_address = m_lighting_uniforms.get_device_address(); push_constant_data push = { .scene_address = scene_ubo_address, .model_mat_array_address = objects_ubo_address, .model_idx = static_cast(m_model_matrices_lookup[p_entity.id()]), .diffuse_idx = static_cast(m_material_table[p_entity.id()].diffuse_idx), .specular_idx = static_cast(m_material_table[p_entity.id()].specular_idx), + .point_light_address = lighting_address, }; m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); @@ -472,6 +526,7 @@ export namespace atlas { vk::dyn::buffer m_scene_uniforms; // uniform buffer to write all of our objects mat4 model matrices in vk::dyn::buffer m_object_model_uniforms; + vk::dyn::buffer m_lighting_uniforms; std::unordered_map m_meshes; diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag index 71fb1a12..6af81a8b 100644 --- a/builtin.shaders/pbr.frag +++ b/builtin.shaders/pbr.frag @@ -1,18 +1,61 @@ #version 450 #extension GL_EXT_nonuniform_qualifier : require +#extension GL_EXT_buffer_reference : require +#extension GL_EXT_scalar_block_layout : require layout(location = 0) in vec3 fragColor; layout(location = 1) in vec2 fragTexCoords; layout(location = 2) in vec3 fragNormals; layout(location = 3) in flat int fragDiffuseIdx; layout(location = 4) in flat int fragSpecularIdx; +layout(location = 5) in vec3 FragPos; layout(location = 0) out vec4 outColor; layout(set = 0, binding = 1) uniform sampler2D textures[]; layout(set = 0, binding = 2) uniform sampler2D environment_map; // used for IBL +struct point_light { + vec4 position; + vec4 color; + float attenuation; + float constant; + float linear; + float quadratic; + + vec4 ambient; // 4th channel is the intensity value + vec4 diffuse; + vec4 specular; +}; + +layout(buffer_reference, scalar) buffer readonly SceneUniforms { + mat4 view; + mat4 proj; +}; + +const int max_point_lights = 1000; +layout(buffer_reference, scalar) buffer readonly PointLightsUniforms { + int num_lights; + int pad_0; // 4 + int pad_1; // 8 + int pad_2; // 12 + point_light point_lights[max_point_lights]; +}; + +layout(buffer_reference, scalar) buffer ObjectsTable { + mat4 model[]; +}; + +layout(push_constant) uniform Constants { + SceneUniforms global_ubo; + ObjectsTable objects; + int model_matrix_idx; + int diffuse_idx; + int specular_idx; + PointLightsUniforms lights; +} push_const; + const vec2 invAtan = vec2(0.1591, 0.3183); vec2 SampleEquirectangular(vec3 v) { vec3 direction = normalize(v); @@ -22,24 +65,69 @@ vec2 SampleEquirectangular(vec3 v) { return uv; } +vec3 calc_point_light(point_light light, vec3 normal, vec3 fragPos, vec3 view_dir) { + vec3 light_pos = vec3(light.position); + vec3 dir_to_light = normalize(light_pos - fragPos); + + float diff = max(dot(normal, dir_to_light), 0.0); + + float material_shininess = 1.0f; + + vec3 reflect_dir = reflect(-dir_to_light, normal); + + float spec = pow(max(dot(view_dir, reflect_dir), 0.0), material_shininess); + + float dist = length(light_pos - fragPos); + float attenuation = light.attenuation / (light.constant + light.linear * dist + light.quadratic * pow(dist, 2)); + + + vec3 ambient = light.ambient.rgb * vec3(texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords)); + // vec3 diffuse = light.diffuse.xyz * diff * vec3(texture(diffuse_texture, fragTexCoords)); + // vec3 specular = light.specular.xyz * spec * vec3(texture(specular_texture, fragTexCoords)); + vec3 diffuse = light.diffuse.xyz * diff * vec3(texture(textures[fragDiffuseIdx], fragTexCoords)); + vec3 specular = light.specular.xyz * spec * vec3(texture(textures[fragSpecularIdx], fragTexCoords)); + + ambient *= attenuation; + diffuse *= attenuation; + specular *= attenuation; + + return (ambient + diffuse + specular); +} + void main() { vec3 color = fragColor; vec4 diffuse = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); vec4 specular = texture(textures[nonuniformEXT(fragSpecularIdx)], fragTexCoords); + // vec3 default_ambience = (vec3(texture(diffuse_texture, fragTexCoords)) * fragColor.rgb) * 0.1; + vec3 default_ambience = (vec3(texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords)) * fragColor.rgb) * 0.1; + vec3 final_color = default_ambience; + + PointLightsUniforms lights = push_const.lights; + + int num_point_lights = int(min(lights.num_lights, max_point_lights)); + + for(int i = 0; i < num_point_lights; i++) { + point_light src = lights.point_lights[i]; + vec3 view_pos = src.position.xyz; + vec3 dir_to_light = normalize(view_pos - FragPos.xyz); + final_color += calc_point_light(src, fragNormals, FragPos, dir_to_light) * (src.color.rgb * src.color.a); + } + + // Uncomment to calculate the irradiance mapping + // vec3 albedo = diffuse.rgb; + // // Map the surface normal direction to the HDR map to get diffuse ambient light + // vec3 N = normalize(fragNormals); + // vec2 envUV = SampleEquirectangular(N); + // // Low-frequency ambient lighting from the surrounding environment + // // vec3 ambientIrradiance = texture(environment_map, envUV).rgb; + // vec3 ambientIrradiance = textureLod(environment_map, envUV, 4.0).rgb; - vec3 albedo = diffuse.rgb; - // Map the surface normal direction to the HDR map to get diffuse ambient light - vec3 N = normalize(fragNormals); - vec2 envUV = SampleEquirectangular(N); - // Low-frequency ambient lighting from the surrounding environment - // vec3 ambientIrradiance = texture(environment_map, envUV).rgb; - vec3 ambientIrradiance = textureLod(environment_map, envUV, 4.0).rgb; + // // In a full PBR equation, this would be multiplied by your diffuse term (1.0 - metallic) * albedo + // vec3 ambient = ambientIrradiance * albedo * 0.05; // Dim down slightly for a basic placeholder balance - // In a full PBR equation, this would be multiplied by your diffuse term (1.0 - metallic) * albedo - vec3 ambient = ambientIrradiance * albedo * 0.05; // Dim down slightly for a basic placeholder balance + // // 4. Combine lighting components (Direct light + Ambient IBL) + // vec3 final_color = albedo + ambient * color; - // 4. Combine lighting components (Direct light + Ambient IBL) - vec3 final_color = albedo + ambient * color; outColor = vec4(final_color, 1.0); } \ No newline at end of file diff --git a/builtin.shaders/pbr.frag.spv b/builtin.shaders/pbr.frag.spv index be0595a427a434b11fc4b1e685ca315a836ef497..806d8c4eea826e5205253884a33ad72217b8b01c 100644 GIT binary patch literal 9240 zcmZvf37C~-6~{lAg+&w<5LCbcR8YXg-4w-8fkZ*UrOYmO?%aW^Gxv`7-a%+l$tc@w zv%Q|j$kZ}5O>MD7)Y42_t!%NyB{gj?Q%mdj`|fv!&yn}xaL)OkT(N_8#vF{%BerKc4J)@^K5O2xiH1DE33a-n;$x3^qp-p+KcCCgVWKcLau-I4Wtx#vq-e4KUdZD|oRywcHSKL?| zY?^zl@k>^$ShDLLC7y2sIa-pYEFPEB?^%R`t$^0tSQr}=t-k}4J{5m_5 z4k}BMfm)^7B-`3`O*+<@V!+^yO0!Z+d(xTtvecwh>#Nn_;cE|y&1SheSWMjmZ%civ zjb^dRD)ev7XARa~BuV&ofYFhjIw?vy-%jLWe|M!!iio%OJ(b?x!A5x~-gPtv%B4Zt zhsaEmIb+mX>?;*=3!Kwv)(1Rm8@=wD#)1xKy#J$Q)H-0hrb*I>t- ztDQ5IBvrPx*w@m>qxW(cSJoQXJ2*E z?a8bZ@9l*VJ1W@^-d}8%>lM%ax=NLPHb~-JbFp#y`ZyQqbk^s=w?8mE+LOcKJ(Whf zFUA~=p5H@#P7}*|ug}@&&GLrkV7+X)Af4%5ah=Dv_G4Mkh8FJq5no;2u((#M_q5j6 zp7evq-kI}4^q1~iXL|39U6t*pNv-D!eB)q6EadsZ{xe_d&|625y<{y>Zq))lG zIM~-LwANR$TrzefTj9NxDot(8Bz6~A?!2UDPRudkbbFA&Fb+bu>-L=;I z;?`8_K9^%}{i9P~YwEA{l=}+YmU?AFq2dYMmdpCG^OBl6>72Q&G0x4lm{v{h!?rp* zlOLe3DwV6{q3*S65_fp-<@QM|?OnZgu9$b|NAMM`x>pyw`_i+huec+vA8t>60v{M` ztmAmn7_m{wgJAB_%X`|E{1#g!jcrSwgg5G?G|xziNZ+H@(*s6#!M6AI`29PPdlqk* z-$L)*Dd~IX`^I|+Hc+e=`_sAFlkvm!U54osUZQuT-&Q_$ah210_QR)KU0f&W0 zx5V0(V)I>bOo7Z9x;Y);v{6c zdOAB#z8kHzwB8BSG@sn{XpdT3b+oXkE%r;lsD;!+u`zelqhIVz7qa#EzO-s+Pi559 z$NA$ua-UjrZS#qo;bR{h_DamUoh$OF56>f(&l7811n%Dd5boZ$^tSYUi(2EYi#bBy zHpjO2FlsZWZAML;LZb;VL1x+U2 zdeq&E>HLM^K8gjdEhun#7ZGDJKV!@_HuH5Z?K@<4@fl?F94Z^9Eoc(Ho{KJM1T;6( zCm}n`wHrLA3XR>>#U42W2MX$bve*b;< zEu76-??ir#;yqt?A;&&iW1a$+dnUdO?}8lWRsRn3L|c+fMZX)_d}7nddJo(lo&SAX#3bj5yyEV=Z-%z% z$i4~c`o)}L>OY2iPka;YvAVyN#I!$<$=0F%bGUU_qxvu5u17ug^dV$>H<6R^c;@$X z=4T(n@9)SXpx9gAq`dB%q#k>+I|^wN=bf3!)?&Q6ZE`#hY1q~MT^hRn{?-g#yT3K_y1zB^y1zBm7qVXO;AbH3 z-!XLKicHt$-hUSItyq=mS7q37bZias)sSzExG}yV*FfUx_WyHG89I{~=lwjSkGON% zU$L0;3&@+HnDaVhv6%CEWaku*Id4D~k2$}HoS*YXbbZ8~^IEuA%=snc{5o$&7mGRl z&FP%tF{i&h#beGdBj@M*3c5bxr?Pg>>Q^CgM_^w=7Gqn6u-h`sv$~Q<_v!19@%n3b zUh!{0?%!tSQ2!>RulQvdc001T@2czf%-#+~jysUWv~7i}yY>g*KZSfdmO=X83I7=+ zuK&H69=2bgiy7}b@+(Me610%Dc&>g8iMzg?p>doH@!vr9VK$`CLy&Vk2-l|UeKFT_ zME?%%{gppMZ4bjAfgIW&g=?2vpL0A0nIrT+Ae;Y2>U|vk1f-An^TeqC9x}JNlw+-b zM0Tx_>nUV&AICa<8~+69vl!Cm`tO4O8PXQ(_biM;|4U|rrTz2$`787!vu%lJg#Ra zWY?k1Z;E=%u`{yYZEb#E)Wfzbvh!>6TcaMfiO9~Q&F_x-k=dFjA@9O`&Sg$x^@+ai zhHO2aVe{Fy$zbBqw<*YCl0()y)1B#=-UA?V_&dWqo{>F~wZ;2571>RwR@xDD>*nA%@CSH98x>(#(ZDRSi?P0K(e{XDC z(c`Y{gD&O>Y~KtM4s3RY*_)Mg(q7I1GhTn~`-8a#e{X4fAsLYz0r{KBGvr=5#zBYU zHwM0ACi}Z%r<^=KC;PtJhh5?E8*2ixHH1Dbr_V&5HB8?xr#si&oUZ?Y!}P<4=||^u z<4+r=_Yc!A%=9>mlhIvk{tiz;7mptAjx6Q~Y!75H+Bt;nnPIKHXx-1LV8-jOJ-sh* z@!0$6$o4Jty^!s5-1{zMeZ=G5&p>u=?|m0!UVAMbdGGWV+>?dJ9DihK4v+s8njy@e^YYCJZ>!{@lnXHm|_oZ{hgJhFNG z?#5a@7viCxi0u5nf!1g5^%38cVM~$Ctu1oD8rj^-pvZL+vUuprkYy0aioSwF@CP*lEYe@TYr0Y33MP7J$oy% zG2;4o?%oD%hN5S0N496;`gqPRg~Zi8XYYXWJ$om*KH|}zcOi>A0(&>Im~{sBo(#+P z>@qOp_17LfdoQwU&~DEzgp0*`--qnoR38g}Kjc}A^?xA4^ow&U7V#fM&c|Pl?!H9) zhmghei#-#I_zxrJ<3ECKjS>G*WHJ4sezB-hwvk9hce64^Pz R=Tpe~iNDBcQ1|!M{{gpR-yZ+~ literal 3128 zcmZ9NTYFPg5QZ0RQc7D21B|Z$Rx6V&$ZfMi9jW-jUpu+?PC*Y)I;olgfjqMrHM@E9d@Dk(~M{6nz_UGw#Mw zt(i2+d)=TO)uJ#_e292qZLLsTE>~Kua=Y_=JuKIwI4oDAB&>9z{qV3(%8TMky<5!^ z@~V{WGw+VM5%o|C8m)S`yw~-mf_S%E50Y#9wd?wby!sp#XJ3-nzftLQ%O)R7{FHQ8 z1nR#nyV9&T6Cca_S=5qXcj*wzx$BBmqgt)o4t>p8`JM2f(@jEuba~C4`H}aa$6Ki$ zP=CPB6nry0SZX$tDhc$pEZuH}6N{bz39sL+%U|_5d4E>q ztm+7YdfW3i6$|72t;e2|b6e7_APE}YKkBxngT_u2#+{WU393;LS9Bc89dMsXD>q7- zaYONPBWU@WsJEo0I-UzXR-rjJDBM|_u1+(Ut-)TYCMv*dMg?GqeDCA=SvQE zpPrZx{b&6b{pb7);ImGP1#e1w@eSB#WerGAO3tYszb$;?lkx|p!4Trdq>1>yGrKgj(=FNNsTV_}oK_&&y_6{d=;BF$ehg_fyRB zA7*@J!TU-Maq4lWST?&az4vU<{EGa){w&VX-*>XPE6j#`e13Oe#*bw?_iW*o&WC%$ zTv>3Q3&~59%N^qVvvXnYymeWhcglSDyhT}`x5)f4*_#<3{?`9|-X7x<=UvJAyes%~ z>JQByFz(8{x~ErsVw}&163(WS`n(Td_w>|Wo!zr29}YNsGIKEa^t39Wk2Reb zGg(V9a29u|PeLx|L!4Z=pGr0)Bl-p5mn87ngBUrSA-Lu6cLR(V=ZAks^I=|3BqI`V z;+!`axy<)-3HKQv{udHB+uEIP`APx@oSwPs_FZ4gCXTSO-^INlZaqGg4Q75In{WS7 zee#_ JIv;G#@;^{*40Zqj diff --git a/builtin.shaders/pbr.vert b/builtin.shaders/pbr.vert index 7e154dea..88c1f8b3 100644 --- a/builtin.shaders/pbr.vert +++ b/builtin.shaders/pbr.vert @@ -25,6 +25,7 @@ layout(location = 1) out vec2 fragTexCoords; layout(location = 2) out vec3 fragNormals; layout(location = 3) out flat int fragDiffuseIdx; layout(location = 4) out flat int fragSpecularIdx; +layout(location = 5) out vec3 FragPos; // struct material { // int diffuse_idx; @@ -40,6 +41,29 @@ layout(buffer_reference, scalar) buffer readonly SceneUniforms { mat4 proj; }; +struct point_light { + vec4 position; + vec4 color; + + float attenuation; + float constant; + float linear; + float quadratic; + + vec4 ambient; // 4th channel is the intensity value + vec4 diffuse; + vec4 specular; +}; + +const int max_point_lights = 1000; +layout(buffer_reference, scalar) buffer readonly PointLightsUniforms { + int num_lights; + int pad_0; // 4 + int pad_1; // 8 + int pad_2; // 12 + point_light light_sources[max_point_lights]; +}; + layout(buffer_reference, scalar) buffer ObjectsTable { mat4 model[]; }; @@ -50,6 +74,7 @@ layout(push_constant) uniform Constants { int model_matrix_idx; int diffuse_idx; int specular_idx; + PointLightsUniforms point_lights; } push_const; @@ -58,11 +83,13 @@ void main() { SceneUniforms ubo = push_const.global_ubo; ObjectsTable object = push_const.objects; - - gl_Position = ubo.proj * ubo.view * object.model[push_const.model_matrix_idx] * vec4(inPosition, 1.0); + vec4 position_in_world = object.model[push_const.model_matrix_idx] * vec4(inPosition, 1.0); + // gl_Position = ubo.proj * ubo.view * object.model[push_const.model_matrix_idx] * vec4(inPosition, 1.0); + gl_Position = ubo.proj * ubo.view * position_in_world; fragColor = inColor; fragTexCoords = inTexCoords; fragNormals = inNormals; fragDiffuseIdx = push_const.diffuse_idx; fragSpecularIdx = push_const.specular_idx; + FragPos = position_in_world.xyz; } \ No newline at end of file diff --git a/builtin.shaders/pbr.vert.spv b/builtin.shaders/pbr.vert.spv index 6c62799b77b41f42ba86004ada26925714779a3f..d90ded59ec9bca0fb2d4931329c2fe0c2c1ee674 100644 GIT binary patch literal 4312 zcmZ9O?RFGJ5QaN!Hbf8*5by)yA|NP;h=3>}!2n4hl7$3BREF8z2@FnV*4bS?{N*j^ zC3!3AIsWhh{Np*kPfyn}C&Q_9*IOT5RbAC=W7DC{&P}+jZky}4>f7ly32~0~kJp{s z;$Cqp?Yq&9h1*g8@ryy)jk9PlEXw#%5_LvvYe^~lDQ`2sw6b(^FzlT?bM_S8w!4P= zQ$Fyw!@UONCPnLUnzKjg3(=zJy6C2;ExIjQ5#1Ht7d;R)^ly{a-{ox5ZFciZ(bapa zA%dt(6i1SG6UnAcHc+T>8FjLv`(u>FFN)C++bziFmzU?4u14K{U&*}4k|;~_Bi!Wj7f}MxEb8cQkk$`GSB=x_5+CeNx4H1f5XxD9xj1MVa-2J+Y*Ddwe6@^XI}I zWl=jR?S1 zgg1ka9C>eKdmFH!v64!Sorzi~G3XRLTV zLpXQJzfJhOQq9jIlLgLu1-=sI2LUnhhFue`;<$O`z*|A?3zD(tqaPRa*LZr4d93Ta zu|emMcs|pi)^$Jd8~uRQ{lMdARzz&PL;vXAX3zOmoYk8o*6XqoD{`}E9t^_8pZLLAqIuP4r&eZi*7FVj)>JV~`n}+B&bwgrz0A2e*1;zqG4h7+ zZNw}WiyJ-5rKP>uHiGTp8fLj1t6`SQi5f;OoO`N<5ii(m4Wpi5Z4q_Ys}m7m529eB>7cgzny>wc_0)Rx}jEvou# z($``}JRdUNjViaM--B=Ek3R0e-W4!%Fbo?o;xUXp80S+*-i()LRqq8nevtEC)OqR; zk8k9>5p|yT0iJV+o!>3n{eIH#>oVR4ld(r;aXkn;J+oV zPtUYO`{aSUfv;*lsb6i*WAHOVc~iikmU#064o`is2j`q^S~+KrWW?JNO^A@~(28s( z{La7zee{gbIUrqTmosOyXExzE&-{bU=yc|c94rrFF*2N$cz8crBEI8+-=qECD%5`Q z%nAO$X5@vwx43LYhd3-3bl~Y%;-yC~1fKs#!8i;1w?usCzpWJ+HGtC&+=p%7hyx~KGTX0*o?Ab&WH^R8N@jkv~nhL&VlFuWsBol*kgpYxboeAs!+EpqJd1ljf=hi8t_ zw|n^}@Yo|~e(Un@#4~Sp9`jt6$KvVHb9%qX3tc{R{uRR9W6Lb^j*>q-J;hsTJUw$H z@Rwyp5AGMyr}XAU+0c&%MBrcQ1pL9He^BeYBJ^7#^y$Y#B5?FM58h<&X%B||F|F^5 zus7-&>C+P;?1%~3Md9@AhazOufH}jSzTkH*y?RS$kn1M_(=x`+1Z<*) zoedcN+OnM1dQOBr`pD_|U*#9sry^oNhg_*87;#Xyiz4bpuH^A$z*>H-a<~-mdJfpm zit4tP16JKjW&4#daI^hQ=TMh95q^;q3$b1i5ue3=ReSWniSL@$c@eY68RP?xp4Ih+ z_RJQtMXm72mbBgyF(=5FCwQ}4)t(ta#_Yh`{om7``)4N5=l;JHfuqmtz?=T}+M~~m qnEnsigQI_6D?Bptjzr|WERNoIC<24{xPR)0Epzrz^qE-ULr-YzbkFLZ!NeJZ(Pg&tFD^NN@wlV-v2(--c^51X?k(Sm??ACoHP5T_%4`fA;z%&`Ia$r z=8S3W?gyLAXTjjbaUONsagYzwtbGs$ol(CZX3DSHoW@pbYbhW0mhRlWO||o;Wd2eO z>b0`>Kkm8RgDg}J zVbTrdoAth2ZML(Z6Q|vug1CL0j)vsU;cx8hG`2Q^?qHxnj^i+hqa+M^Q5JTG(W{U+ zTgSykNjDz#CIc#pn4F`c`RCMMs~aZa^Car0*|R>w z|Dx8xD1Q-j83L?q-WFE$h+Q=cvJc{5H_Z0KY#5Gv1Lwn+=Fu=p6GhM1c;>Wtlnh(Z zFRq8e$Gq~b#nE6r;^eyFIFDKJjpBIhd{QvAVFnh`yG_X=dZfmZwot zAj|=0iP;N}*3vZVabMJf$5C>Eg28KIx5bZkoZC2f9witLU*12$O)n>s5JdV|;h z=r;fzeieNd9G5x11A6sbCVy7qF>=6){)@Ph!&G`42X~31pN7tY_^M>Z+9k{3V*j$$ z1&`}Oa=p8=JOZc$s zS|{yQXHyqHJjCy9_=nA2_~G89z3FWBWiB{(-s)wm6YG8O&il~u(dR`~r~ZN>iABFD zjWhpS7js!U=UJ0nQ3iL4P3~3wKcf{4dtU$HDi~6e?dyPJb3WvQv(GuL>~l#z`m0H% zB=d@bOT-a_&&ze?!3*}7m(IOoQ{UGE!+ujManyR?Y<}CoZn-_-A0P3TwBlo5YXbk1#Zj?aW~fB2WQ;^WM?w>w(dmzwzRYMqjRQy&|?g3&jz_a(;s`iS_4(#WM( z>=kGGeC)cze7#lK)MNj3tJ5z^^M3@Q12MJ~r`i>Y9XjxJEqux-J1Hp8D9n*89?_K|b90Py$xuS1lKA zI-FT}FFyAp>65u1%LXfYEpk7R4eoP)*FFXJc*n-z_kDgUo&M+r9)2!i7WhdFcXC?- zUe`&`?-vsC*c0EfaO!_4!FPJ!uY}!lerm$QuO)E!srKdUzj2tBG4`#);E9iW;4t>s zRVEz&PC`EM_<0MzsV=@{3HuYnjJ%CUl0^yqb3fR``QFx~uR32{D>lA$txqIP33 Date: Wed, 10 Jun 2026 23:06:28 -0700 Subject: [PATCH 077/106] refactor: added example for using the environment map; does not actually do anything, but keeping them here as placeholders --- atlas/core/application.cppm | 4 +- atlas/drivers/vulkan/render_context.cppm | 6 +++ builtin.shaders/pbr.frag | 47 ++++++++++++++--------- builtin.shaders/pbr.frag.spv | Bin 9240 -> 10368 bytes builtin.shaders/pbr.vert | 4 ++ builtin.shaders/pbr.vert.spv | Bin 4312 -> 4376 bytes 6 files changed, 42 insertions(+), 19 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 10c8683c..a8ebfcbf 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -256,13 +256,15 @@ export namespace atlas { // TODO: Should consider changing this from // using tags in flecs for specifying active cameras. query_camera_objects.each( - [&](flecs::entity, + [&](flecs::entity p_entity, flecs::pair p_pair, perspective_camera& p_camera) { if (!p_camera.is_active) { return; } + const transform* t = p_entity.get(); + m_render_context.set_camera_pos(glm::vec4(t->position, 1.f)); m_projection = p_pair->projection; m_view = p_pair->view; }); diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 640b26aa..2f1b5381 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -53,6 +53,7 @@ export namespace atlas { struct scene_uniforms { glm::mat4 view=glm::mat4(1.f); glm::mat4 proj=glm::mat4(1.f); + glm::vec4 camera_pos=glm::vec4(1.f); }; struct objects_uniform { @@ -502,8 +503,13 @@ export namespace atlas { m_shader_resource.destruct(); m_main_pipeline.destruct(); } + + void set_camera_pos(const glm::vec4& p_camera_pos) { + m_camera_pos = p_camera_pos; + } private: + glm::vec4 m_camera_pos = glm::vec4(1.f); glm::mat4 m_projection; glm::mat4 m_view; uint32_t m_format; diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag index 6af81a8b..3835cfda 100644 --- a/builtin.shaders/pbr.frag +++ b/builtin.shaders/pbr.frag @@ -14,7 +14,7 @@ layout(location = 5) in vec3 FragPos; layout(location = 0) out vec4 outColor; layout(set = 0, binding = 1) uniform sampler2D textures[]; -layout(set = 0, binding = 2) uniform sampler2D environment_map; // used for IBL +layout(set = 0, binding = 2) uniform samplerCube environment_map; // used for IBL struct point_light { vec4 position; @@ -23,7 +23,7 @@ struct point_light { float constant; float linear; float quadratic; - + vec4 ambient; // 4th channel is the intensity value vec4 diffuse; vec4 specular; @@ -32,6 +32,7 @@ struct point_light { layout(buffer_reference, scalar) buffer readonly SceneUniforms { mat4 view; mat4 proj; + vec4 camera_pos; }; const int max_point_lights = 1000; @@ -95,12 +96,12 @@ vec3 calc_point_light(point_light light, vec3 normal, vec3 fragPos, vec3 view_di } void main() { - vec3 color = fragColor; vec4 diffuse = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); vec4 specular = texture(textures[nonuniformEXT(fragSpecularIdx)], fragTexCoords); - // vec3 default_ambience = (vec3(texture(diffuse_texture, fragTexCoords)) * fragColor.rgb) * 0.1; - vec3 default_ambience = (vec3(texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords)) * fragColor.rgb) * 0.1; - vec3 final_color = default_ambience; + + vec3 albedo = diffuse.rgb; + // vec3 albedo = fragColor.rgb; + vec3 final_color = (albedo * fragColor.rgb) * 0.1; PointLightsUniforms lights = push_const.lights; @@ -113,20 +114,30 @@ void main() { final_color += calc_point_light(src, fragNormals, FragPos, dir_to_light) * (src.color.rgb * src.color.a); } - // Uncomment to calculate the irradiance mapping - // vec3 albedo = diffuse.rgb; - // // Map the surface normal direction to the HDR map to get diffuse ambient light - // vec3 N = normalize(fragNormals); - // vec2 envUV = SampleEquirectangular(N); - // // Low-frequency ambient lighting from the surrounding environment - // // vec3 ambientIrradiance = texture(environment_map, envUV).rgb; - // vec3 ambientIrradiance = textureLod(environment_map, envUV, 4.0).rgb; + SceneUniforms ubo = push_const.global_ubo; + + // vec3 view_pos = vec3(inverse(ubo.view)[3]); + // vec3 view_dir = normalize(ubo.camera_pos.xyz - FragPos); + vec3 normal = normalize(fragNormals); + vec3 Incident = normalize(FragPos - ubo.camera_pos.xyz); + + + + // Calculating diffuse term + // vec2 diffuse_uv = SampleEquirectangular(normal); + vec3 ambient_irradiance = textureLod(environment_map, normal, 5.0).rgb; + vec3 ibl_diffuse = ambient_irradiance * albedo * 0.5; + + // Calculating the specular term + vec3 reflect_dir = reflect(Incident, normal); + // vec2 specular_uv = SampleEquirectangular(reflect_dir); + vec3 ambient_radiance = textureLod(environment_map, reflect_dir, 1.5).rgb; + + + vec3 ibl_specular = ambient_radiance * specular.rgb * 0.5; - // // In a full PBR equation, this would be multiplied by your diffuse term (1.0 - metallic) * albedo - // vec3 ambient = ambientIrradiance * albedo * 0.05; // Dim down slightly for a basic placeholder balance + final_color += (ibl_diffuse + ibl_specular); - // // 4. Combine lighting components (Direct light + Ambient IBL) - // vec3 final_color = albedo + ambient * color; outColor = vec4(final_color, 1.0); diff --git a/builtin.shaders/pbr.frag.spv b/builtin.shaders/pbr.frag.spv index 806d8c4eea826e5205253884a33ad72217b8b01c..8417d9dbf214edf9ed20f626d534a8901c3ae1c9 100644 GIT binary patch literal 10368 zcmZvf37DN_b;rNt-kF3DHVKb&5|rzlpUKLm+e}V<>RDmF-Vrl-?yUR?@#*mR zsb;^?Yt0V2y;`d?)!f(W?8bgfZog^EZME4w_w-whdb`%grM|mao1B}TZuXdWG@onp zwux;Q_6JiJUV7O@7IA!5$-crI)^S3%JgdT`nR=@O%U%vOp##t%=qR)p=k3sm#Olk! zkSeSq%RT~L1=+kUFSnSz)@xEjv(so|TN<`bw=>siO?P`UwO7v7+pXyqb(ZXXmQnB3 zCfnV{D{AffJ>9v1xtAHgdHeRw+is{eW@lOGJ?&<#-Rd-JQ>|XJF=*|j;FKr%wK|RV z+*H|N1dsAMN3szr%d**St1}?m?mYuKHkxC=;QiL1)y;b{ntbh9qucKG;Nfcz>VrYE zGgr^u1Fz)1o&KQSVHNrp^I3zn*GUq-BVcr7sz-`O$#)dFJ~P>Bk|N^m{ZwmudamD` zk9QsY*=A#o_8~IUX`C@?t+yMs(gM%z4|;Qr!MYN(ZtwJ^IZdx$H~$wHeErpXr!SeO zJa?57?HcTub5%K0S=M1&>+M260ezaoxTD+0KEk=lvc0Y5tK2Wd96K4F=b*rTj*Vt# z!*Qt%x@kjlyqc}a@#$$8u}iY&!)NM)X0PSB-_z>Q&pt_<>wIjSzBcC~pU(O``1S{e zM>V?wKGo{y`(n&B=;b}s=Qgp_dwpJpK4|V6%=Ma<3o@GD71w!vu^(Hf_7%AIM|@{< z-==Q2H&v{!n$3X6-kI}W^r!CIXnyaEok;s>QtLT56#L-QVyoFhVD%xk1S_41{9K7ShVOy+@I4TFrh6d%O!q*1_#TKo(>)L$z6WB% z_dx9F_h3o(2>1@~_%;u0|Mubm>gQ|J=IG4L6bFut@}7yi#@YH*&9f7jYZO~w!d#!& z#W_~Y=h{mBOy{MV9R|)BbKY&Q%4ksMdf*9Es%PrzsA z`g=IaG)!zs_9-y;?&-a*WS_y-%3~|p=i&WcBhPaLIe&|aX9sLF`vKT9y*o$2Z{)7T zJLd18cjuP;t@CZGW)-m6dav%?Rv#JCmkjC0JVmc$XP~>u#-5G5@Q#jTW9VBujn5IpWL|^^D}-1^iIQbCPXl9ln*TAVTK#)dny&^CI|-;cte%$}1ty zskR#Y(27E?m*mNLxtf2U7*pi0cD^KHHd;F0ewCHbu-`Ryh79VPjl^KvzR zH_hwVLjQbk9BT?Tk6DwLzj@*3*%uotVU>iPQ^KrSzjI62NWv~CVZMj@`8LHIzK3Gt zCCv9wYzJho{}^uUUAbP#-#KgBg6$Ew<8;WJp&RcAAJ zs5{s4l8-sdd7?k|*1bIp|7JQXk0BRpDc&&DJfGb4XpdTpItnami~Z8C0C2R^V&1t zzhV!o`TMnM-d5<`q-_Gq`u< zF~~lvKanu)A5XHisDBb}E!L_2=Wy4g9{c)N$o6jqr{f=!-j-@fx^?N}-8m24Ghlpq0O!NIb3TfG=D#2r#H>%< z?>dL|nCqfkKR6!x6@@*23$%~t`r&KMcMGy}TaWqFeMiM2{&w`UzOi~^=y#xBdE|kO z7qI6I{O&~8NBnZI#bBNZhk1^GjKIzBTXqnN`P3gQ>As5(4e9=$8vdT$!zJB)|J0D~ zw|)5A`_Gqj^B)<~e^Ao(_nST9_4k{-tozMg*8OG=-Tn7BD|F-iZZGR&L%QGWWxL#AY4p; zYx)D|Aheyg%J=x)keKA4E%{kA)-$EuSbg6EiG}_?NZo`l5pKb-WieHvZNc;BnPfW-Xm-@r|FFaHt}_fDM%EobH8 ze+{|5wU9o(ZO-9c(5CD?FxPj9{u{XWQ2rfi`#bpGLk{i#0M{WRB23hiv|b zsn_@OpCEn2zekMv-$Ld#mvXH23&@9)ZtgEa=Dv<~ehL0%=nK#$NSo{TP5ug`E!KZ4 zbG!FnO*UBGKi`qBLEd%O?E2O9iC}REt z*%;5DG3xpmW8eN0GRCzTV-NldGG+oYMqR&%`EO)njE|WAK{loX8KbUW#C!+Yn59s} z{4cUG_d&*}>lgO#B5Qa5JU7nwJxDz6`1cbg?r<;N8}l83Yd6+A{6k1A^#4QlxBNA% zTf4#fh%cujVvE4cc>|a z8M5UWzOh`en!u;TvbXfuF0^ot&CK^Bi5Z9*1{IkzI)x6ogVtWVs#n~?Pp51(zw<-2(^ zx|qK9Pn%fy??4ud-<@00#TCZ3e#-Cr( z^}lFHzhX$grlcEx+mJppq~Du#-w%J6PlH@*ykXXUdcvc}XCw?Z-}h%HjCRgrXC|!J zi{iKLEHLBs*X};pBk|b#mB?bDKL^=9$GbF!tdDrSORJEb+uzVJ$h`JiJo21_?B0d` zTx5OT%-a3kc^;&Xxc6P`T*$m~?Q0=(yKiF3?wMyQ@?L;!-upNMo~Lz?SlBN_wvKpH zUV!Wzn<0I*o7cV97IEv5J!7F?jI2-8e+jZa;!*#l$Wgy`>o?xDT?Scu_+E~zuX|&h zcI)uWX^VNUL@w{oRp{mYc_F$!;_i=gT@9K0MUZy$dUnMbVdP{YGTx_Z_r8d#{i9{R!KGY;J9l`^CuS-U>yon~=pr z--c}N=<6-W(N}FZLox4mWaIUTd3PW?x3<@&T5d(Q7uxKd_gu`nytg|c>zaV9V+s6r zNIZTE?ns!p!#Lv!6mXMqD4y-A_XYpy=7pAlox>eLQEcg~Zi8XFm&-d-ika`iMt= zejZue5!f#vi&G= literal 9240 zcmZvf37C~-6~{lAg+&w<5LCbcR8YXg-4w-8fkZ*UrOYmO?%aW^Gxv`7-a%+l$tc@w zv%Q|j$kZ}5O>MD7)Y42_t!%NyB{gj?Q%mdj`|fv!&yn}xaL)OkT(N_8#vF{%BerKc4J)@^K5O2xiH1DE33a-n;$x3^qp-p+KcCCgVWKcLau-I4Wtx#vq-e4KUdZD|oRywcHSKL?| zY?^zl@k>^$ShDLLC7y2sIa-pYEFPEB?^%R`t$^0tSQr}=t-k}4J{5m_5 z4k}BMfm)^7B-`3`O*+<@V!+^yO0!Z+d(xTtvecwh>#Nn_;cE|y&1SheSWMjmZ%civ zjb^dRD)ev7XARa~BuV&ofYFhjIw?vy-%jLWe|M!!iio%OJ(b?x!A5x~-gPtv%B4Zt zhsaEmIb+mX>?;*=3!Kwv)(1Rm8@=wD#)1xKy#J$Q)H-0hrb*I>t- ztDQ5IBvrPx*w@m>qxW(cSJoQXJ2*E z?a8bZ@9l*VJ1W@^-d}8%>lM%ax=NLPHb~-JbFp#y`ZyQqbk^s=w?8mE+LOcKJ(Whf zFUA~=p5H@#P7}*|ug}@&&GLrkV7+X)Af4%5ah=Dv_G4Mkh8FJq5no;2u((#M_q5j6 zp7evq-kI}4^q1~iXL|39U6t*pNv-D!eB)q6EadsZ{xe_d&|625y<{y>Zq))lG zIM~-LwANR$TrzefTj9NxDot(8Bz6~A?!2UDPRudkbbFA&Fb+bu>-L=;I z;?`8_K9^%}{i9P~YwEA{l=}+YmU?AFq2dYMmdpCG^OBl6>72Q&G0x4lm{v{h!?rp* zlOLe3DwV6{q3*S65_fp-<@QM|?OnZgu9$b|NAMM`x>pyw`_i+huec+vA8t>60v{M` ztmAmn7_m{wgJAB_%X`|E{1#g!jcrSwgg5G?G|xziNZ+H@(*s6#!M6AI`29PPdlqk* z-$L)*Dd~IX`^I|+Hc+e=`_sAFlkvm!U54osUZQuT-&Q_$ah210_QR)KU0f&W0 zx5V0(V)I>bOo7Z9x;Y);v{6c zdOAB#z8kHzwB8BSG@sn{XpdT3b+oXkE%r;lsD;!+u`zelqhIVz7qa#EzO-s+Pi559 z$NA$ua-UjrZS#qo;bR{h_DamUoh$OF56>f(&l7811n%Dd5boZ$^tSYUi(2EYi#bBy zHpjO2FlsZWZAML;LZb;VL1x+U2 zdeq&E>HLM^K8gjdEhun#7ZGDJKV!@_HuH5Z?K@<4@fl?F94Z^9Eoc(Ho{KJM1T;6( zCm}n`wHrLA3XR>>#U42W2MX$bve*b;< zEu76-??ir#;yqt?A;&&iW1a$+dnUdO?}8lWRsRn3L|c+fMZX)_d}7nddJo(lo&SAX#3bj5yyEV=Z-%z% z$i4~c`o)}L>OY2iPka;YvAVyN#I!$<$=0F%bGUU_qxvu5u17ug^dV$>H<6R^c;@$X z=4T(n@9)SXpx9gAq`dB%q#k>+I|^wN=bf3!)?&Q6ZE`#hY1q~MT^hRn{?-g#yT3K_y1zB^y1zBm7qVXO;AbH3 z-!XLKicHt$-hUSItyq=mS7q37bZias)sSzExG}yV*FfUx_WyHG89I{~=lwjSkGON% zU$L0;3&@+HnDaVhv6%CEWaku*Id4D~k2$}HoS*YXbbZ8~^IEuA%=snc{5o$&7mGRl z&FP%tF{i&h#beGdBj@M*3c5bxr?Pg>>Q^CgM_^w=7Gqn6u-h`sv$~Q<_v!19@%n3b zUh!{0?%!tSQ2!>RulQvdc001T@2czf%-#+~jysUWv~7i}yY>g*KZSfdmO=X83I7=+ zuK&H69=2bgiy7}b@+(Me610%Dc&>g8iMzg?p>doH@!vr9VK$`CLy&Vk2-l|UeKFT_ zME?%%{gppMZ4bjAfgIW&g=?2vpL0A0nIrT+Ae;Y2>U|vk1f-An^TeqC9x}JNlw+-b zM0Tx_>nUV&AICa<8~+69vl!Cm`tO4O8PXQ(_biM;|4U|rrTz2$`787!vu%lJg#Ra zWY?k1Z;E=%u`{yYZEb#E)Wfzbvh!>6TcaMfiO9~Q&F_x-k=dFjA@9O`&Sg$x^@+ai zhHO2aVe{Fy$zbBqw<*YCl0()y)1B#=-UA?V_&dWqo{>F~wZ;2571>RwR@xDD>*nA%@CSH98x>(#(ZDRSi?P0K(e{XDC z(c`Y{gD&O>Y~KtM4s3RY*_)Mg(q7I1GhTn~`-8a#e{X4fAsLYz0r{KBGvr=5#zBYU zHwM0ACi}Z%r<^=KC;PtJhh5?E8*2ixHH1Dbr_V&5HB8?xr#si&oUZ?Y!}P<4=||^u z<4+r=_Yc!A%=9>mlhIvk{tiz;7mptAjx6Q~Y!75H+Bt;nnPIKHXx-1LV8-jOJ-sh* z@!0$6$o4Jty^!s5-1{zMeZ=G5&p>u=?|m0!UVAMbdGGWV+>?dJ9DihK4v+s8njy@e^YYCJZ>!{@lnXHm|_oZ{hgJhFNG z?#5a@7viCxi0u5nf!1g5^%38cVM~$Ctu1oD8rj^-pvZL+vUuprkYy0aioSwF@CP*lEYe@TYr0Y33MP7J$oy% zG2;4o?%oD%hN5S0N496;`gqPRg~Zi8XYYXWJ$om*KH|}zcOi>A0(&>Im~{sBo(#+P z>@qOp_17LfdoQwU&~DEzgp0*`--qnoR38g}Kjc}A^?xA4^ow&U7V#fM&c|Pl?!H9) zhmghei#-#I_zxrJ<3ECKjS>G*WHJ4sezB-hwvk9hce64^Pz R=Tpe~iNDBcQ1|!M{{gpR-yZ+~ diff --git a/builtin.shaders/pbr.vert b/builtin.shaders/pbr.vert index 88c1f8b3..2c0a291c 100644 --- a/builtin.shaders/pbr.vert +++ b/builtin.shaders/pbr.vert @@ -39,6 +39,7 @@ layout(location = 5) out vec3 FragPos; layout(buffer_reference, scalar) buffer readonly SceneUniforms { mat4 view; mat4 proj; + vec4 camera_pos; }; struct point_light { @@ -88,7 +89,10 @@ void main() { gl_Position = ubo.proj * ubo.view * position_in_world; fragColor = inColor; fragTexCoords = inTexCoords; + // fragNormals = mat3(object.model[push_const.model_matrix_idx]) * inNormals; + // mat3 normal_mat = transpose(inverse(mat3(object.model[push_const.model_matrix_idx]))); fragNormals = inNormals; + // fragNormals = normal_mat * inNormals; fragDiffuseIdx = push_const.diffuse_idx; fragSpecularIdx = push_const.specular_idx; FragPos = position_in_world.xyz; diff --git a/builtin.shaders/pbr.vert.spv b/builtin.shaders/pbr.vert.spv index d90ded59ec9bca0fb2d4931329c2fe0c2c1ee674..122b0982c39fe1f62b6fd0c52483e10327686df2 100644 GIT binary patch delta 95 zcmcbiI74Ye52F|x0~-Su0|NsS5GN<*rWPf}7vvXj?qcj>QS@M7fy+q% Date: Thu, 11 Jun 2026 01:40:30 -0700 Subject: [PATCH 078/106] refactor: fixed the calculation for getting Image-Based Lighting to work better --- atlas/drivers/vulkan/render_context.cppm | 4 ++++ builtin.shaders/pbr.frag | 18 +++++++++--------- builtin.shaders/pbr.frag.spv | Bin 10368 -> 11148 bytes 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 2f1b5381..885f167d 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -403,6 +403,7 @@ export namespace atlas { scene_uniforms scene_ubo = { .view = p_view, .proj = p_proj, + .camera_pos = m_camera_pos, }; m_scene_uniforms.transfer(std::span(&scene_ubo, 1)); @@ -412,6 +413,9 @@ export namespace atlas { const transform* t = p_entity.get(); glm::mat4 model = glm::mat4(1.f); model = glm::translate(model, t->position); + + glm::mat4 rotation_mat = glm::mat4(glm::quat(t->rotation)); + model *= rotation_mat; model = glm::scale(model, t->scale); if(m_model_matrices_lookup.contains(p_entity.id())) { diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag index 3835cfda..f1b2ecf2 100644 --- a/builtin.shaders/pbr.frag +++ b/builtin.shaders/pbr.frag @@ -14,7 +14,7 @@ layout(location = 5) in vec3 FragPos; layout(location = 0) out vec4 outColor; layout(set = 0, binding = 1) uniform sampler2D textures[]; -layout(set = 0, binding = 2) uniform samplerCube environment_map; // used for IBL +layout(set = 0, binding = 2) uniform sampler2D environment_map; // used for IBL struct point_light { vec4 position; @@ -99,8 +99,8 @@ void main() { vec4 diffuse = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); vec4 specular = texture(textures[nonuniformEXT(fragSpecularIdx)], fragTexCoords); - vec3 albedo = diffuse.rgb; - // vec3 albedo = fragColor.rgb; + // vec3 albedo = diffuse.rgb; + vec3 albedo = fragColor.rgb; vec3 final_color = (albedo * fragColor.rgb) * 0.1; PointLightsUniforms lights = push_const.lights; @@ -124,21 +124,21 @@ void main() { // Calculating diffuse term - // vec2 diffuse_uv = SampleEquirectangular(normal); - vec3 ambient_irradiance = textureLod(environment_map, normal, 5.0).rgb; + vec2 diffuse_uv = SampleEquirectangular(normal); + // vec3 ambient_irradiance = textureLod(environment_map, normal, 5.0).rgb; + vec3 ambient_irradiance = textureLod(environment_map, diffuse_uv, 5.0).rgb; vec3 ibl_diffuse = ambient_irradiance * albedo * 0.5; // Calculating the specular term vec3 reflect_dir = reflect(Incident, normal); - // vec2 specular_uv = SampleEquirectangular(reflect_dir); - vec3 ambient_radiance = textureLod(environment_map, reflect_dir, 1.5).rgb; + vec2 specular_uv = SampleEquirectangular(reflect_dir); + // vec3 ambient_radiance = textureLod(environment_map, reflect_dir, 1.5).rgb; + vec3 ambient_radiance = textureLod(environment_map, specular_uv, 1.5).rgb; vec3 ibl_specular = ambient_radiance * specular.rgb * 0.5; final_color += (ibl_diffuse + ibl_specular); - - outColor = vec4(final_color, 1.0); } \ No newline at end of file diff --git a/builtin.shaders/pbr.frag.spv b/builtin.shaders/pbr.frag.spv index 8417d9dbf214edf9ed20f626d534a8901c3ae1c9..5d36726638c64666480b487a3614d2f5fb100d78 100644 GIT binary patch literal 11148 zcmZvg37p*JS;zm$9tjXafN(V-k7eo}6~VaLst$peSGjas!?>EcoyuUAH<$HwX%<{ixE z+P-Ue*Ja(Q(aWxS^W_$?Fzd@c!yMLeTDBnTXH+JtjTS?81bGBGj(ieXhT}@4i!35m zUls=HV-;EU1bjct_FZ|o#q5<%of_(`S{>W`u(jH)=~iQ`-I=J|H(hNu#v0UFvUgcV zwNn{swrlrRn$^SY=_zxcZ2a~;d$#Y|TB%J=ve3iLdZpQD)hnZoPQ5nOI9S&&pC|b> zTD9i%XxU)^kMcSP=-~qDAFfVJHtSpOo6b{JTjSHzu=?QGmFu%?fHj_i&p~8>|4w6^ zY&Tj{%szf#iVhFv95j5lG1X}2JseEFv?i;yo9zx`_}a7T)KtASUCrHt@5_B#-KlDe zRqJ2OXU(p)N|Nv$fTM$>9a7XvzJuWE#7Lt~iimfwMjK;e)7|<^{Cv3XWWDB6fy{JH zb~YpZuT@G5T-}}OOxLE?l&Cca$F9m{Z0(wvzu*|xuD5j|dG7w~4922k&efltiQeKE zRGWp)am>azynEYS>;u_Z=m#71``uq)&YjDcwmWaKd$Sa7n$0ohYH&UW3+U!CgW2XH zrZUw|8RYG<=T^G+Ok#OA_<$#>Q!Ga?bK{tbZ8J{xRUu zpWVqg+UVx{W=sXWyvO=X%cZ^1=Rx$T`k|@mPTg{02J?5%K3rGq*Ur&H1@HSPzps91 zOS|0}E!NkcJqjOtYtCcnuiV$c{5>{yIPJGdt>=lJ*e72V+n;>`uG$=_kG6|md=lMU zThf_!&QHlTS~RXW>2lA&mCj6l?&N%W-xK-X_eAcs-V^!PdQaqg-xImldQaqg-xIms z_eAd1@5#LES@^x)0lT~cy0;V;S~p*#HlNn?L~-EQDBnYQ*Em@nt#}Cs=NjeKmN?fZ zcSX(>^SQQCKht^X&rZPSXCB7BKaakpUECo$d0)u+j5pgOY|``yd+Gf0*3=%khof!% z^K;IcCfcL*W`#GR(>PRVcnW88SzkJHxoMEjnadjE?9Ij$^SBSQbq;1PpbyvTt@=#& zikjqoeD@u#Q!ejar+rVs74gfZ6Q zbQ|wa+;e`e`abQ>??Ugs{%jT8WVKVB$miX_O556(dT z<@Xi7K*Uv*Z6~jH?g|9cjK0zUp6%Q$M;I68xIf3sz@B$)?_&Jm;sU?Bgdd*4{rUGM zV~YHJ`Q01&j>Bv7Ju%-$86)4vO8Da?{O2Y7R0%&lgZqo`Xy`sW=$`kM&#GdW;jBq+ z5fXmBLvqVYoa>dlu*6xj-0BiHkhn`rocF4J-f=O9_p01biSu5S+l#m_|HNqQ{#@_N z?@Mdjf$dpFA3y)i8M^U4;p6(sKCxbF4)L- zFn%GOmFL05T8g_6HP7ehdbCHaMI8kfwZ(qv*N3b^NIer9b4NY;#ojCjTh9xOMGgHq zM$LVkUz?BnRLnK&6FI}jxqa-FoOKW6`s_X3o2R@l5o4aAJg&%NZRNRQ?ML7}AD?CP zd<^A!Uw)tKV;wIt`a~U}&(<+}|404i^e*;&G)~>SSlzt#%zL!h!~V=WZpDnP&{v}S z80%eQtk0QbFvkjV^f8Lh23h}d4*rQLO zUxd$`6mN}}AWJ{La-(*2?~`>ezklPU?2PlSLG+OipUc5Ko2+RaU^x;w)vrN(tm#@t zYjXV&e?8bI^c!>S$R>5;_apW`^cvW`3VjT0??Z2bJxA)UVG`jP3cJ4_<jheLGm2eb!(7 zk;FyqkD=SY&>shTMk4=laOD51g!R|1?r#R|(VI_$pML784HvVve*nM0W#$=v1{`PA zUX>;I*hA0ZKO&!FQ||i~CS6c;|}T-h=M#XOn#y_(ia~elf3{`sWzkBWtj)>Mtcu z`@be^E$aWq=$fok{Y#9lNj>)QzrglyF(>_N$#3qQ!p~lY-+Va!X7s_XB* zya|Q0ne(m#TgP)rzZTtfguVscy6l_lI?Cu>>l5eYrd&TZ6#8hc|IsG%cfigS@#@~i za&O^{^c{9TeB@q+@jZ2}YZ;$FtS|H@OS)(L6FvH;O1kIfL`k>jU+mHS%@Fw)fxl7G z&F^oAu&evKA$0xyEfBhPe+!iLi+gl`3xwU?`xzFx@%|nt>q8}d33h)AlU5FYA8458Zrzw-4R<{a#OT>A-#O3j0;-e$ zZ-i~-J}rE_cbvm_MVr|7#9Ut?`pb;Ir;cBywwH6B|K;P{?5m909j(tf{tq!n=>HEk z{|BhoyY1_UKJs5BM*V*gbDK*XYqi)DNjLW#baQWJopZr`E(RG(HrM|QxIfuq{Wmf9 zLihoAZ9ewTduI^cyTCQOes%pKW**oW{$^rMLNUhs*cf&Fj2VPK8ElO6JI@7-r=T0N zA2CKqpn}XEKV`=N-<}pn8#9#x_%LJc8c+Sih0gSF^{Jhb^XGA zUa}YGzxY1>Iym_~d{=P(C15$l$HBdEt={|EJ#+e=50(r40Jxpt6dY&ReD3oaIQi(?WnekQ$DugWgZY`h93pb~UBf({k+ooL zaR*)jHkW+dl~;nTQCqC%DzNwCL#fwqMwipqHENUdZu$z?`@+$9?}xWw^L{u&y!zGX za`B#OlPlkC-aC0u;MXJG#c`IN1HU!#&hKZqdeplS?7qc0*aYS;KL^^3@pE22Vm5=_ zPxa^UeH+-k*06=~Iz(<5Y}YfYUqgL=|} zr!zYY)~@(C=;J&$qG*pAZvo4Nek<6|<~U!sq3a_b=kRv0{N*Xh4Pe{3K)Kx(8iO@o_L$^!Hu}bLbcSZGz>a zzvE!Jm~#Sb&qHs4^@;br4c13Kd?vx=JK;WbIeqP)Ho5Sh0?Wnc-88zKPjCklCmr1V ziF1v6(^)+PXT1K}Z^Y)DU9h&V(UoS8Kazt(!Vjl0|707ZVd{%+=S&4+tg4R zNq3+9ZnqwBt?@bN{qWYr$NRD&aSSu>(8k2M|KYbOam9O8d|w)ZGhTn~?u|VfLfjjB z^)^H<^etff9G`91f%TD(_r&jC&h4n(y!Ki>@@xmYccJe9>+?R=?)lw`=p!HR#0_Bc zu12(9kC@wi(gvyLEWxw8gw{2bcHf9q8r#xeHw% z`M4YI2AkV`({5hRu6*1vRj_AoKN2;LfaSwy6s%7T37-Up7pYMVr2-VWG!ePZ4&*txa6 zC)F|qwinv$o$tAvbzRGNKVn@65$jmUcnFb?&-KHJllQTvxrqMj7#~88An|W5?@F9= z90k7{c@U8|<^jfs5qb5K7~g|Dg2cb`d|d@tDkJcdMnz7H%P{rP^doZ?gNk7wk4$TlRt^ZWqV z82RYo4}y;%(X$@{+cWv-*$;!|qh~(?F8Az5(e;s!Ui=tX-Y2*p2g{Xv_7jOK_v|O( zjMra#^z5g=u0gv!dz4WwdiH*>J$oF9p8YgfK6>^uU^&I7w`V^KH;hEjehzGmeDv(+ z!N-y4*)M?YnSAu@7s2w;vtI(2d-lud`p8Freg!P=6Wp(Y<;p$#wZxTs_UmxQ>#sd} z_5rYK&~DF;G0It&XXG~!-%WMT>u(~(SuFky;e(0OFV3l4#D54}j{h*a`x5>8EwG$^ zv1f7-|J&el{O_P2Ln8in!E*XV{c=(7N5Iw_`tO0A{~_)G*Yo>`KJwx72jF8!`1~PQ MKY71jsr&uvo4a0?wEzGB literal 10368 zcmZvf37DN_b;rNt-kF3DHVKb&5|rzlpUKLm+e}V<>RDmF-Vrl-?yUR?@#*mR zsb;^?Yt0V2y;`d?)!f(W?8bgfZog^EZME4w_w-whdb`%grM|mao1B}TZuXdWG@onp zwux;Q_6JiJUV7O@7IA!5$-crI)^S3%JgdT`nR=@O%U%vOp##t%=qR)p=k3sm#Olk! zkSeSq%RT~L1=+kUFSnSz)@xEjv(so|TN<`bw=>siO?P`UwO7v7+pXyqb(ZXXmQnB3 zCfnV{D{AffJ>9v1xtAHgdHeRw+is{eW@lOGJ?&<#-Rd-JQ>|XJF=*|j;FKr%wK|RV z+*H|N1dsAMN3szr%d**St1}?m?mYuKHkxC=;QiL1)y;b{ntbh9qucKG;Nfcz>VrYE zGgr^u1Fz)1o&KQSVHNrp^I3zn*GUq-BVcr7sz-`O$#)dFJ~P>Bk|N^m{ZwmudamD` zk9QsY*=A#o_8~IUX`C@?t+yMs(gM%z4|;Qr!MYN(ZtwJ^IZdx$H~$wHeErpXr!SeO zJa?57?HcTub5%K0S=M1&>+M260ezaoxTD+0KEk=lvc0Y5tK2Wd96K4F=b*rTj*Vt# z!*Qt%x@kjlyqc}a@#$$8u}iY&!)NM)X0PSB-_z>Q&pt_<>wIjSzBcC~pU(O``1S{e zM>V?wKGo{y`(n&B=;b}s=Qgp_dwpJpK4|V6%=Ma<3o@GD71w!vu^(Hf_7%AIM|@{< z-==Q2H&v{!n$3X6-kI}W^r!CIXnyaEok;s>QtLT56#L-QVyoFhVD%xk1S_41{9K7ShVOy+@I4TFrh6d%O!q*1_#TKo(>)L$z6WB% z_dx9F_h3o(2>1@~_%;u0|Mubm>gQ|J=IG4L6bFut@}7yi#@YH*&9f7jYZO~w!d#!& z#W_~Y=h{mBOy{MV9R|)BbKY&Q%4ksMdf*9Es%PrzsA z`g=IaG)!zs_9-y;?&-a*WS_y-%3~|p=i&WcBhPaLIe&|aX9sLF`vKT9y*o$2Z{)7T zJLd18cjuP;t@CZGW)-m6dav%?Rv#JCmkjC0JVmc$XP~>u#-5G5@Q#jTW9VBujn5IpWL|^^D}-1^iIQbCPXl9ln*TAVTK#)dny&^CI|-;cte%$}1ty zskR#Y(27E?m*mNLxtf2U7*pi0cD^KHHd;F0ewCHbu-`Ryh79VPjl^KvzR zH_hwVLjQbk9BT?Tk6DwLzj@*3*%uotVU>iPQ^KrSzjI62NWv~CVZMj@`8LHIzK3Gt zCCv9wYzJho{}^uUUAbP#-#KgBg6$Ew<8;WJp&RcAAJ zs5{s4l8-sdd7?k|*1bIp|7JQXk0BRpDc&&DJfGb4XpdTpItnami~Z8C0C2R^V&1t zzhV!o`TMnM-d5<`q-_Gq`u< zF~~lvKanu)A5XHisDBb}E!L_2=Wy4g9{c)N$o6jqr{f=!-j-@fx^?N}-8m24Ghlpq0O!NIb3TfG=D#2r#H>%< z?>dL|nCqfkKR6!x6@@*23$%~t`r&KMcMGy}TaWqFeMiM2{&w`UzOi~^=y#xBdE|kO z7qI6I{O&~8NBnZI#bBNZhk1^GjKIzBTXqnN`P3gQ>As5(4e9=$8vdT$!zJB)|J0D~ zw|)5A`_Gqj^B)<~e^Ao(_nST9_4k{-tozMg*8OG=-Tn7BD|F-iZZGR&L%QGWWxL#AY4p; zYx)D|Aheyg%J=x)keKA4E%{kA)-$EuSbg6EiG}_?NZo`l5pKb-WieHvZNc;BnPfW-Xm-@r|FFaHt}_fDM%EobH8 ze+{|5wU9o(ZO-9c(5CD?FxPj9{u{XWQ2rfi`#bpGLk{i#0M{WRB23hiv|b zsn_@OpCEn2zekMv-$Ld#mvXH23&@9)ZtgEa=Dv<~ehL0%=nK#$NSo{TP5ug`E!KZ4 zbG!FnO*UBGKi`qBLEd%O?E2O9iC}REt z*%;5DG3xpmW8eN0GRCzTV-NldGG+oYMqR&%`EO)njE|WAK{loX8KbUW#C!+Yn59s} z{4cUG_d&*}>lgO#B5Qa5JU7nwJxDz6`1cbg?r<;N8}l83Yd6+A{6k1A^#4QlxBNA% zTf4#fh%cujVvE4cc>|a z8M5UWzOh`en!u;TvbXfuF0^ot&CK^Bi5Z9*1{IkzI)x6ogVtWVs#n~?Pp51(zw<-2(^ zx|qK9Pn%fy??4ud-<@00#TCZ3e#-Cr( z^}lFHzhX$grlcEx+mJppq~Du#-w%J6PlH@*ykXXUdcvc}XCw?Z-}h%HjCRgrXC|!J zi{iKLEHLBs*X};pBk|b#mB?bDKL^=9$GbF!tdDrSORJEb+uzVJ$h`JiJo21_?B0d` zTx5OT%-a3kc^;&Xxc6P`T*$m~?Q0=(yKiF3?wMyQ@?L;!-upNMo~Lz?SlBN_wvKpH zUV!Wzn<0I*o7cV97IEv5J!7F?jI2-8e+jZa;!*#l$Wgy`>o?xDT?Scu_+E~zuX|&h zcI)uWX^VNUL@w{oRp{mYc_F$!;_i=gT@9K0MUZy$dUnMbVdP{YGTx_Z_r8d#{i9{R!KGY;J9l`^CuS-U>yon~=pr z--c}N=<6-W(N}FZLox4mWaIUTd3PW?x3<@&T5d(Q7uxKd_gu`nytg|c>zaV9V+s6r zNIZTE?ns!p!#Lv!6mXMqD4y-A_XYpy=7pAlox>eLQEcg~Zi8XFm&-d-ika`iMt= zejZue5!f#vi&G= From 5f01c6378022ca0c766c1c3452deed0113a3e4fc Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 11 Jun 2026 02:14:00 -0700 Subject: [PATCH 079/106] refactor: correctly destructed the skybox uniform buffer --- atlas/drivers/vulkan/environment_map.cppm | 1 + 1 file changed, 1 insertion(+) diff --git a/atlas/drivers/vulkan/environment_map.cppm b/atlas/drivers/vulkan/environment_map.cppm index 0e364302..bf83ba85 100644 --- a/atlas/drivers/vulkan/environment_map.cppm +++ b/atlas/drivers/vulkan/environment_map.cppm @@ -723,6 +723,7 @@ public: m_skybox_descriptor.destruct(); m_skybox_shaders.destruct(); m_skybox_pipeline.destruct(); + m_skybox_uniforms.reset(); } private: From e84ed9499f4fe4f477f427d85f06b5af459c6db3 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 11 Jun 2026 02:14:32 -0700 Subject: [PATCH 080/106] refactor: ensured uniform buffers were correctly destructed --- atlas/drivers/vulkan/render_context.cppm | 1 + 1 file changed, 1 insertion(+) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 885f167d..c774f87b 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -490,6 +490,7 @@ export namespace atlas { void destruct() { m_scene_uniforms.reset(); m_object_model_uniforms.reset(); + m_lighting_uniforms.reset(); m_environment_map.destruct(); From 98dc5bc25f441ce6eb912f2c15a35140523e710e Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 11 Jun 2026 02:20:13 -0700 Subject: [PATCH 081/106] refactor: removed dead commented code --- editor/editor_world.cppm | 3 --- 1 file changed, 3 deletions(-) diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 78cca9c3..099c82fd 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -428,9 +428,6 @@ public: ImVec4(button_active.x, button_active.y, button_active.z, 0.5f)); float button_size = 20.0f; - // if(ImGui::Begin("##toolbox")) { - // ImGui::End(); - // } if (ImGui::Begin("##toolbox")) { VkDescriptorSet button_id = (m_scene_state == scene_runtime::edit) From 9911c8adc1eb6c849e1e681cd6526c9f38f90d52 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 11 Jun 2026 16:00:41 -0700 Subject: [PATCH 082/106] refactor: fixed tartifacts related to texture wrapping in the environment mapings --- atlas/drivers/vulkan/environment_map.cppm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/atlas/drivers/vulkan/environment_map.cppm b/atlas/drivers/vulkan/environment_map.cppm index bf83ba85..8fb88b97 100644 --- a/atlas/drivers/vulkan/environment_map.cppm +++ b/atlas/drivers/vulkan/environment_map.cppm @@ -126,6 +126,8 @@ public: .aspect = vk::image_aspect_flags::color_bit, .usage = vk::image_usage::transfer_dst_bit | vk::image_usage::sampled_bit, + .address_mode_u = vk::sampler_address_mode::repeat, + .addrses_mode_v = vk::sampler_address_mode::clamp_to_edge, // .view_type = VK_IMAGE_VIEW_TYPE_CUBE, }; m_skybox_image = vk::sample_image(*m_device, skybox_params); From a102ada776ebc53e50bc5e7e8f851fe65f52719a Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Thu, 11 Jun 2026 16:01:37 -0700 Subject: [PATCH 083/106] refactor: fixed some portions of the IBL logic to ensure that it does not break anything and made sure the changes were close to correct --- builtin.shaders/pbr.frag | 149 +++++++++++++++++++++++++++++------ builtin.shaders/pbr.frag.spv | Bin 11148 -> 17452 bytes builtin.shaders/pbr.vert | 10 ++- 3 files changed, 129 insertions(+), 30 deletions(-) diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag index f1b2ecf2..9591e63a 100644 --- a/builtin.shaders/pbr.frag +++ b/builtin.shaders/pbr.frag @@ -9,7 +9,7 @@ layout(location = 1) in vec2 fragTexCoords; layout(location = 2) in vec3 fragNormals; layout(location = 3) in flat int fragDiffuseIdx; layout(location = 4) in flat int fragSpecularIdx; -layout(location = 5) in vec3 FragPos; +layout(location = 5) in vec3 FragPos; // contains world position layout(location = 0) out vec4 outColor; @@ -72,7 +72,9 @@ vec3 calc_point_light(point_light light, vec3 normal, vec3 fragPos, vec3 view_di float diff = max(dot(normal, dir_to_light), 0.0); - float material_shininess = 1.0f; + // float material_shininess = 1.0f; + float roughness = 0.5f; + float material_shininess = mix(128.0, 1.0, roughness); vec3 reflect_dir = reflect(-dir_to_light, normal); @@ -95,50 +97,145 @@ vec3 calc_point_light(point_light light, vec3 normal, vec3 fragPos, vec3 view_di return (ambient + diffuse + specular); } + + +const float PI = 3.14159265359; +float DistributionGGX(vec3 N, vec3 H, float roughness) { + float a = roughness*roughness; + float a2 = a*a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH*NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} + +float GeometrySchlickGGX(float NdotV, float roughness) { + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} + +float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} + +vec3 fresnelSchlick(float cosTheta, vec3 F0) { + return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); +} + + void main() { - vec4 diffuse = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); - vec4 specular = texture(textures[nonuniformEXT(fragSpecularIdx)], fragTexCoords); + SceneUniforms ubo = push_const.global_ubo; + + + vec4 diffuse_texture = texture(textures[nonuniformEXT(fragDiffuseIdx)], fragTexCoords); + vec4 specular_texture = texture(textures[nonuniformEXT(fragSpecularIdx)], fragTexCoords); + vec3 albedo = (fragColor.rgb * diffuse_texture.rgb); + vec3 final_color = (albedo * diffuse_texture.rgb) * 0.1; + + float roughness = 0.2; + float metallic = 0.2; + float ao = 0.2; + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + // vec3 view_pos = vec3(inverse(ubo.view)[3]); + // vec3 view_dir = normalize(ubo.camera_pos.xyz - FragPos); + + // N + vec3 normal = normalize(fragNormals); + + // V + vec3 view_dir = normalize(ubo.camera_pos.xyz - FragPos); // vec3 albedo = diffuse.rgb; - vec3 albedo = fragColor.rgb; - vec3 final_color = (albedo * fragColor.rgb) * 0.1; + // vec3 albedo = fragColor.rgb; + // vec3 final_color = (albedo * diffuse.rgb) * 0.1; PointLightsUniforms lights = push_const.lights; int num_point_lights = int(min(lights.num_lights, max_point_lights)); + vec3 Lo = vec3(0.0); for(int i = 0; i < num_point_lights; i++) { point_light src = lights.point_lights[i]; - vec3 view_pos = src.position.xyz; - vec3 dir_to_light = normalize(view_pos - FragPos.xyz); - final_color += calc_point_light(src, fragNormals, FragPos, dir_to_light) * (src.color.rgb * src.color.a); + + // L + vec3 dir_to_light = normalize(src.position.xyz - FragPos); + vec3 H = normalize(dir_to_light + view_dir); + float dist = length(src.position.xyz - FragPos); + // float attenuation = 1.0 / (dist * dist); + float attenuation = src.attenuation / (src.constant + src.linear * dist + src.quadratic * pow(dist, 2)); + vec3 radiance = src.color.rgb * attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(normal, H, roughness); + float G = GeometrySmith(normal, view_dir, dir_to_light, roughness); + vec3 F = fresnelSchlick(max(dot(H, view_dir) , 0.0), F0); + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(normal, view_dir), 0.0) * max(dot(normal, dir_to_light), 0.0) + 0.0001; + vec3 specular = numerator / denominator; + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + float NdotL = max(dot(normal, dir_to_light), 0.0); + + Lo += calc_point_light(src, fragNormals, FragPos, dir_to_light) * (src.color.rgb * src.color.a); + // vec3 direct_ambient = src.ambient.rgb * albedo * attenuation; + Lo += (kD * albedo / PI + specular) * radiance * NdotL; } - SceneUniforms ubo = push_const.global_ubo; - // vec3 view_pos = vec3(inverse(ubo.view)[3]); - // vec3 view_dir = normalize(ubo.camera_pos.xyz - FragPos); - vec3 normal = normalize(fragNormals); - vec3 Incident = normalize(FragPos - ubo.camera_pos.xyz); + vec3 kS = fresnelSchlick(max(dot(normal, view_dir), 0.0), F0); + vec3 kD = 1.0 - kS; + kD *= 1.0 - metallic; + vec2 environment_uv = SampleEquirectangular(normal); + // vec3 irradiance = texture(environment_map, environment_uv).rgb; + vec3 irradiance = textureLod(environment_map, environment_uv, 0.0).rgb; + vec3 diffuse = irradiance * albedo; + vec3 ambient = (kD * diffuse.rgb) * ao; + vec3 color = ambient + Lo; + + color = color / (color + vec3(1.0)); + color = pow(color, vec3(1.0/2.2)); // Calculating diffuse term - vec2 diffuse_uv = SampleEquirectangular(normal); - // vec3 ambient_irradiance = textureLod(environment_map, normal, 5.0).rgb; - vec3 ambient_irradiance = textureLod(environment_map, diffuse_uv, 5.0).rgb; - vec3 ibl_diffuse = ambient_irradiance * albedo * 0.5; + // vec2 diffuse_uv = SampleEquirectangular(normal); + // // vec3 ambient_irradiance = textureLod(environment_map, normal, 5.0).rgb; + // vec3 ambient_irradiance = textureLod(environment_map, diffuse_uv, 5.0).rgb; + // vec3 ibl_diffuse = ambient_irradiance * albedo * 0.5; + + // // Calculating the specular term + // vec3 reflect_dir = reflect(view_dir, normal); + // vec2 specular_uv = SampleEquirectangular(reflect_dir); + // // vec3 ambient_radiance = textureLod(environment_map, reflect_dir, 1.5).rgb; - // Calculating the specular term - vec3 reflect_dir = reflect(Incident, normal); - vec2 specular_uv = SampleEquirectangular(reflect_dir); - // vec3 ambient_radiance = textureLod(environment_map, reflect_dir, 1.5).rgb; - vec3 ambient_radiance = textureLod(environment_map, specular_uv, 1.5).rgb; + // vec3 ambient_radiance = textureLod(environment_map, specular_uv, 1.5).rgb; - vec3 ibl_specular = ambient_radiance * specular.rgb * 0.5; + // vec3 ibl_specular = ambient_radiance * specular_texture.rgb * 0.5; - final_color += (ibl_diffuse + ibl_specular); + // final_color += (ibl_diffuse + ibl_specular); - outColor = vec4(final_color, 1.0); + // outColor = vec4(final_color, 1.0); + outColor = vec4(color, 1.0); } \ No newline at end of file diff --git a/builtin.shaders/pbr.frag.spv b/builtin.shaders/pbr.frag.spv index 5d36726638c64666480b487a3614d2f5fb100d78..13d6999b114f1bd432777aea3461b44d34b86a65 100644 GIT binary patch literal 17452 zcmZvi34k0$^~M`!c9TFL+~Eiz30F80M9vt2KrSLN2_#@dVKdpCO@{2wEVH{I0fj_S zyu|}hQ8~Qvz7@Pc#S6S||KbG#3SKDU?eEv!Z&N$|+b!$+zW3@?)vN02?g^Eh51o)@ zJ7v3OyJg#V&hl%|Y-f}#v;OElMg6g|zN4&vMZHTlFqquvh&&ih)reD(6V!y|oj zPdw>K4r2GLlHE@qj$=wTIjd4z25XHbRdyrgR?1zJ^*CKYx!RgJ>_J<7nHZ?TEbzlt zMOnH$A8yfmPrJ?->doFdwuxbDwwj~OMt`e4*mLPpgvqcD;9`vAM2a-cRY*X!Z___N5M8 zc%<{}B8QV1|LWS{&_I3hrK5SMT64oFW0<|U|AhHj*2Nrm#b-06i~mib9%?n3BlNyu z;|Lk<&NXE8;l@a#mFKX#^d&V}Z)>2{rVd|oRvQ_qH%Du^d+3$iw>dmgYcgy7i~bz5 zbFC31e7n%dU|*XMy@_u(xHh=HQ71&Scdhyw{r#iE^|AI7(T0cWy-pQKPgAq~sL6kC zPcp&T!z1m{-jO+pG-q@FiFxTie$LomXw=8gH+50+*wt(=>LO$IRn7K>H`xZYfr7Ig zvwk-3s@5>}u54fU=0^Q8*B6K~DLa^YQG)?B){mOFrAyc5t7KRG$Ir*7k{yW8irl}F z9YlS0j=QpH)a};jhKwt$T0$cqe3iXoIzpdb{D7w6W1-@0xV`YUp3@ zAK;$Nm)4j~H1{G^-p43)AM0H3uIzF^dcWA_TD5YY8~63_k@}XAQSwx@>(0+H_tc_d z?=S1yV*Kv>Y*SxT-?FgPYWEd$u4cEHTwg&uP!U%ctE@PjadP2D)A(6wAmHBqfIrN z3g59`tJ$=Y7yGN4&4h2*u!Y`>@y&t{)!Mb9&uVs92S2j#KR*0tci4{}$GfvL;j4S= z&HDMpF>h`?ht$2ir>#R%9%{EPDYT-!=VNbeu->i}8`AkN#Bp?ei%4DB67a%SaZVQT zyK~JL8wOhI*>$?+educ+t@W3%<%ZEF=DzkZ*y^hf^srOgjV(P5cSmu)+QzfE+zYv> zo9COlXL0O_9c_v+c_!!g5rcA{osIv>qTe;O^#gUx`Iywb^8Trv(=xQ=jK!}z*YxXr zuIOus^tqz;|218!|NKr{<=1oowsel6<;Nh{{=qZD@3O zV^5xtVx7)Ii?uG#5IiSj&qNoDYTs@XbhwSo2ZKK7Y$eNXaSSXe&m)i$U#nrz2n zrPP{ey;NmQ=W|xC^JU6@YcQgB4kv~g|XXlmp zjDL1k^Y^zU_!ZCBYW8A$cI?#&*(;388vJk0D%o||mX~9>0qhy>J$VawxZMlx&Ta?u zjOln@RI)qKWc#lI@SSX?1}Q6fY82vsqxz_BhLrgr~VUs)HZX!RL(Qm24Tj z=%<>k7-y?yE64FlcAmcZIJ&b7!S&|mM!VG<v^<#XNN#$BfUT>t{ zJ;&7?PX~K;XnPa&M|cSp-<05+$8a@&Z?H`fzmmTTM7+DuwR!Fs!{;4CWbaqUo_(IJ zXEXMA7J7c}(c!ayhtHvKuZUycX&iZH9JMr#+&Bv;5y!EmK5~7wQ5?U|+egZL_}nYz zQatBy$$hPzkM`)p^FOqRS2L2+%DqWKJ3kn>9ZY%RuA z%`x&=UgG(>BQITJKF0KNj6SctIyGgr7`J{gml^2Mwo>{XmS{1T*@+f&@jX4-Iv4x! z*%q4PRa=l~=2LAI#XOu-=3!mVEBUi7@(|C`$YXHZd%5;%&M)*LtN$C#;4%)eOQ zB2J~lM{bf4%>_%#*)a$Q`%b z-!J5@h5h>cEB1FaKa*xAzMfID;9hwwc*NeDh{l{r4CgD}59E5zpiHGN*HNy02Hc#f zS+q~0)?UQ%*NrUK^waK{qTO6g=hufR)M}w?ixRrEeVJGLvCT}-o+Vc|eiVIOml*3z zA|3!YZun@QNyZK-b$Ovp$PO#D@U;&AW5C9htJ~KJrRLoCg`bq`{2$jbB|jN#PJ++V z$QArF@J=OnoM%y{{dU&r+T{x=r#^A(>Bll=`&mTMM?HL&g1OFc3@ZUMC=pZcedgtu z&!u)A<~G{bz+S=Y1zi}tKj+)dkQ?s`O3X=qCB=Oa_U&NTIrueT_h`g>DVS?P*k1*4 zt_Lu~>q_kS(<}Hv^mIK2{SF4-KrMG}ucP)-n_qIjp}n-ff!a8ZS-aflr<(RRQ+q|c zTfo}PyZ-W9OD)F!Zn*gj{wc8gBjVo$Hb%_-aqv&3EX(KaoF{0^vNOXzFXuNeIFh-Y z0e*mo%Kr4d0PLC-_fPS>RSVtmhriEa`B~JCP2G5lsEsFHT;l1B)@PGG+RaTAeax}X zDf^iY_BkXse#BGrp7xm%_pWnGOX#uhyjPxv|3hq?X~gmwV0*RcjM_6j#u2qX_8Vi@ zNB(qb*T{L8ce&q0YT8$p*g48;)cobS(O>Sjj#{k40Oa0#?l~=ZE9c9{?#p5LE&JBOL-?%CF`!=}o{KieW-?=IGn>M&> z@AEsjYwh=IaO3&S8eF^It-*a3-jZxb5+cmiH{eBH@JilL4?)PhO-$nd}4X(f6 zt||B1HRXPvrrht-l>2=uKa;!4GjtWjbJh2W)3~QRPtPs&)440X-{jgni&leuzOF90 z@5O4y^GxvF*ypplZG7(fj;t>C?0W|IR%_aL4y=Xiqi&zx(`wP@h2XpJi#~nNR*OD; z*S1gf=+k#@_2~0raN1`NTpxA&^xRO>-~9A~*O%Ne_JJMON}jFS>tHpDmldhaUcj8R z_ahiXKjV82sYU#aU^Th%8{jnlC2%#1msJ{n6M`}HdqvsjAXwe!oPB!Msfj)3eBOyY z;{toW1@>(7nHOUm1*-+$4307T9&j1lSgYc^2dhPyT;^&k8h`n}4;j-qTPTjj_}Zh7 z=YV~_PA+3U7tCL_n4--#p1JC_alc+gai6*$woz{{HQ#AZBaZofUa6ZypD(eF&qvp0 z@v_n<#`6M%t0~VfbNoUvMLouN4Vb@tjM^Qe&jEGEeP<2HV#M8T(DtH&gUc|2u8uucsK> zzQi%_TfxpdV!Z`y>@!)%w^F~2qR)2v)#myxqkcO@Tjb(g`gYylQQClcE`4WsCz{Vy z=WH(I`bC>}fsM!CSeti4Y~#C>ZRGmd#(UvCVB6TgYvx)1Ubt=ChqjUH7j51LwvF#O z(dPYd+xY!u8@Ybb<^y2cxQC<72jRBaUbd0z7i~TSwvF#m(dNT&+qfU?N3Nf3%-cu6 zwsCH@F>fD*+s1D@+sO5cHXj4q#`7=Qd>n2Yzo~2^*Du<90&E+fZPDhFaNGFZWgEGE zVZWoa7xzMOetrr~J?`sIgViivR_T5H8HDt{{w&-!>TzFx4$NPEUu$*c_yD{4!iU=J*w`n#Id1o#R&# z(m8$&ZX0#S;@aK=<}d&KLAztQn_AtmxR1XMb}YqtTKtCb4Y+#ve6#d%->q#~qx(5x{SdAm{6}D8drlhr z$6)^Q{}w}=zhOkbKY`m`pXm4h!1k@}Mdet23N{zo%-y}zYL3f$=4W8X<+To__PG#TfPhJ9oKz zWM8;G@t(RLSS^b8vgT&>$js?#619PzP0%sDG%E;uv)w)9t`$(6m|Xm&Qyyr zO$QGVOMl0B2)v(KJz~xP+b-63CRk11h^ZF-hl11G9|lize>hwp^~n7ZV1|*eul5?) z*nS6VGxiki;9JVM`%Ns5evbxUQQG`ImWS=Q{nok$KE{+?C;G{ zV(*@guD|w(cLvx!9OGF4)=xcr&II3=^m!IsKXrY~$3n3CA@Z>Zte<+sSqx6+z67qO zZ_HiIZ-^V|&-Z?7+xrc%6x$8(ZRAdVHeAj1wY@gA^c&?3WqWh|G;HbKKL?(kZOh^M zsK?%aI+zgo-q&6O+t&)PwwT*0aGdQc!SXoU&jow7+eVx1mr<)n`_*8zSi?17@AW8g zW}J_%O@HH@N3CWY*Wm(idS*NWZVdJ4Yc1Gzu~yFntLYmt)x!VTVDqNU-YhZoWvip6{Sr67noxeQ4ac}k_Xt#K|4nq667@$4I zSO=>G?+2&%$p*MS>bCErRtx_I*qj8v1guZoXPdzKsOw{{2f&vysL10WTt9XD*hsAw zFm_IH1^CsCY}+}}x0EP2e~c)0E2o6G;^&awJC zk~YU+40WF=e&?J*Q9GGp9QVPg6!q|V3RoZi%{P4JgVp0)c`Dex4xrdxd$d0tY3sGov1_<@g7-=AzF^mTDs`;) z3UI8qZPzB;wY#W;_jd5UgxkK6aN9RK_-F^eJmI##wu9f+!S5)!>+W~pc@*cqiem0O zA6HY<}`8`s>cN1Thnu4V8Zus-q5zYeUAdfX%H!N#3USx2c+jO{vV6T61) zN8@@gZlI|7yRv*E#TaubbxJ=)AKSX#+G9+YfF09SWiB>>)xtgib`Eh?`rnxw+y3>{ zZd~_`wrJM^yI+G3f%S>GUkcVoJ?7p9$K16$ciTIsVTxl9-x09B2U2XO-ElOjwMD<1 z!Rgvw22a;^3tS)dIA^wkjeQnHyK&w3>TzB@2kgGRf)ZnVE?7N$t^(_GB_({efz`w3 zd0>6EQ^M!@VD;cvgYDn*%UryGqL2FaQhOnI8%0~hei7K%*H9wXi^1x_UjjCEow;{=Mz3;F~Gx zai+WttnL-s+res%DYSQ#nq!Q!=bd2N>#sfDtKJ26e%j5CXQo=@=RIKa^KMGy=e=O{ z$j|%0Y8J0FKi%;6Q!b*!d)f!Uwo#89eh_R9BWE81n=|#u*@waEk+YA0)0}-2u8(@; z;$vWSuh2dYR!ejCiBd~*_DM9`>#sd>c01TPXg6oKQL9DHJ`FZ!pQ1$0J_A;doP8Fo zX7TFG+2_!jl*rkgVB36-5;^-k_%2H1>o&h^Z!Pv=@#?Y{#~+kY4C7^D67z-s!%_|;;(-v>M1;6DJ{|8~v* z=kr5~KI-A~Bd~ph&yT_Ssr#-bk9Re5bTGy107|@fADG~SO1wYyG>Y$M)2V$wQ~N2! zu>}7`2Y;Z0|E7cgu7m%fput`>PSzFPQK!D_*~N*;Oa zhU=pq^PUJ+pFlBhj!`XQ>;j%aSZ$719=6G)E%Qkw$m2v_5j;1 z=D82UKAu@8akqaLwmfceW~Yp<2D&5O2JvqQo5XTRn|9=5~5 z=31Nik^38IH`)zY;49j+kfoukCWwqJeX Qec`EK=b+7;$j!-r0f$%7761SM literal 11148 zcmZvg37p*JS;zm$9tjXafN(V-k7eo}6~VaLst$peSGjas!?>EcoyuUAH<$HwX%<{ixE z+P-Ue*Ja(Q(aWxS^W_$?Fzd@c!yMLeTDBnTXH+JtjTS?81bGBGj(ieXhT}@4i!35m zUls=HV-;EU1bjct_FZ|o#q5<%of_(`S{>W`u(jH)=~iQ`-I=J|H(hNu#v0UFvUgcV zwNn{swrlrRn$^SY=_zxcZ2a~;d$#Y|TB%J=ve3iLdZpQD)hnZoPQ5nOI9S&&pC|b> zTD9i%XxU)^kMcSP=-~qDAFfVJHtSpOo6b{JTjSHzu=?QGmFu%?fHj_i&p~8>|4w6^ zY&Tj{%szf#iVhFv95j5lG1X}2JseEFv?i;yo9zx`_}a7T)KtASUCrHt@5_B#-KlDe zRqJ2OXU(p)N|Nv$fTM$>9a7XvzJuWE#7Lt~iimfwMjK;e)7|<^{Cv3XWWDB6fy{JH zb~YpZuT@G5T-}}OOxLE?l&Cca$F9m{Z0(wvzu*|xuD5j|dG7w~4922k&efltiQeKE zRGWp)am>azynEYS>;u_Z=m#71``uq)&YjDcwmWaKd$Sa7n$0ohYH&UW3+U!CgW2XH zrZUw|8RYG<=T^G+Ok#OA_<$#>Q!Ga?bK{tbZ8J{xRUu zpWVqg+UVx{W=sXWyvO=X%cZ^1=Rx$T`k|@mPTg{02J?5%K3rGq*Ur&H1@HSPzps91 zOS|0}E!NkcJqjOtYtCcnuiV$c{5>{yIPJGdt>=lJ*e72V+n;>`uG$=_kG6|md=lMU zThf_!&QHlTS~RXW>2lA&mCj6l?&N%W-xK-X_eAcs-V^!PdQaqg-xImldQaqg-xIms z_eAd1@5#LES@^x)0lT~cy0;V;S~p*#HlNn?L~-EQDBnYQ*Em@nt#}Cs=NjeKmN?fZ zcSX(>^SQQCKht^X&rZPSXCB7BKaakpUECo$d0)u+j5pgOY|``yd+Gf0*3=%khof!% z^K;IcCfcL*W`#GR(>PRVcnW88SzkJHxoMEjnadjE?9Ij$^SBSQbq;1PpbyvTt@=#& zikjqoeD@u#Q!ejar+rVs74gfZ6Q zbQ|wa+;e`e`abQ>??Ugs{%jT8WVKVB$miX_O556(dT z<@Xi7K*Uv*Z6~jH?g|9cjK0zUp6%Q$M;I68xIf3sz@B$)?_&Jm;sU?Bgdd*4{rUGM zV~YHJ`Q01&j>Bv7Ju%-$86)4vO8Da?{O2Y7R0%&lgZqo`Xy`sW=$`kM&#GdW;jBq+ z5fXmBLvqVYoa>dlu*6xj-0BiHkhn`rocF4J-f=O9_p01biSu5S+l#m_|HNqQ{#@_N z?@Mdjf$dpFA3y)i8M^U4;p6(sKCxbF4)L- zFn%GOmFL05T8g_6HP7ehdbCHaMI8kfwZ(qv*N3b^NIer9b4NY;#ojCjTh9xOMGgHq zM$LVkUz?BnRLnK&6FI}jxqa-FoOKW6`s_X3o2R@l5o4aAJg&%NZRNRQ?ML7}AD?CP zd<^A!Uw)tKV;wIt`a~U}&(<+}|404i^e*;&G)~>SSlzt#%zL!h!~V=WZpDnP&{v}S z80%eQtk0QbFvkjV^f8Lh23h}d4*rQLO zUxd$`6mN}}AWJ{La-(*2?~`>ezklPU?2PlSLG+OipUc5Ko2+RaU^x;w)vrN(tm#@t zYjXV&e?8bI^c!>S$R>5;_apW`^cvW`3VjT0??Z2bJxA)UVG`jP3cJ4_<jheLGm2eb!(7 zk;FyqkD=SY&>shTMk4=laOD51g!R|1?r#R|(VI_$pML784HvVve*nM0W#$=v1{`PA zUX>;I*hA0ZKO&!FQ||i~CS6c;|}T-h=M#XOn#y_(ia~elf3{`sWzkBWtj)>Mtcu z`@be^E$aWq=$fok{Y#9lNj>)QzrglyF(>_N$#3qQ!p~lY-+Va!X7s_XB* zya|Q0ne(m#TgP)rzZTtfguVscy6l_lI?Cu>>l5eYrd&TZ6#8hc|IsG%cfigS@#@~i za&O^{^c{9TeB@q+@jZ2}YZ;$FtS|H@OS)(L6FvH;O1kIfL`k>jU+mHS%@Fw)fxl7G z&F^oAu&evKA$0xyEfBhPe+!iLi+gl`3xwU?`xzFx@%|nt>q8}d33h)AlU5FYA8458Zrzw-4R<{a#OT>A-#O3j0;-e$ zZ-i~-J}rE_cbvm_MVr|7#9Ut?`pb;Ir;cBywwH6B|K;P{?5m909j(tf{tq!n=>HEk z{|BhoyY1_UKJs5BM*V*gbDK*XYqi)DNjLW#baQWJopZr`E(RG(HrM|QxIfuq{Wmf9 zLihoAZ9ewTduI^cyTCQOes%pKW**oW{$^rMLNUhs*cf&Fj2VPK8ElO6JI@7-r=T0N zA2CKqpn}XEKV`=N-<}pn8#9#x_%LJc8c+Sih0gSF^{Jhb^XGA zUa}YGzxY1>Iym_~d{=P(C15$l$HBdEt={|EJ#+e=50(r40Jxpt6dY&ReD3oaIQi(?WnekQ$DugWgZY`h93pb~UBf({k+ooL zaR*)jHkW+dl~;nTQCqC%DzNwCL#fwqMwipqHENUdZu$z?`@+$9?}xWw^L{u&y!zGX za`B#OlPlkC-aC0u;MXJG#c`IN1HU!#&hKZqdeplS?7qc0*aYS;KL^^3@pE22Vm5=_ zPxa^UeH+-k*06=~Iz(<5Y}YfYUqgL=|} zr!zYY)~@(C=;J&$qG*pAZvo4Nek<6|<~U!sq3a_b=kRv0{N*Xh4Pe{3K)Kx(8iO@o_L$^!Hu}bLbcSZGz>a zzvE!Jm~#Sb&qHs4^@;br4c13Kd?vx=JK;WbIeqP)Ho5Sh0?Wnc-88zKPjCklCmr1V ziF1v6(^)+PXT1K}Z^Y)DU9h&V(UoS8Kazt(!Vjl0|707ZVd{%+=S&4+tg4R zNq3+9ZnqwBt?@bN{qWYr$NRD&aSSu>(8k2M|KYbOam9O8d|w)ZGhTn~?u|VfLfjjB z^)^H<^etff9G`91f%TD(_r&jC&h4n(y!Ki>@@xmYccJe9>+?R=?)lw`=p!HR#0_Bc zu12(9kC@wi(gvyLEWxw8gw{2bcHf9q8r#xeHw% z`M4YI2AkV`({5hRu6*1vRj_AoKN2;LfaSwy6s%7T37-Up7pYMVr2-VWG!ePZ4&*txa6 zC)F|qwinv$o$tAvbzRGNKVn@65$jmUcnFb?&-KHJllQTvxrqMj7#~88An|W5?@F9= z90k7{c@U8|<^jfs5qb5K7~g|Dg2cb`d|d@tDkJcdMnz7H%P{rP^doZ?gNk7wk4$TlRt^ZWqV z82RYo4}y;%(X$@{+cWv-*$;!|qh~(?F8Az5(e;s!Ui=tX-Y2*p2g{Xv_7jOK_v|O( zjMra#^z5g=u0gv!dz4WwdiH*>J$oF9p8YgfK6>^uU^&I7w`V^KH;hEjehzGmeDv(+ z!N-y4*)M?YnSAu@7s2w;vtI(2d-lud`p8Freg!P=6Wp(Y<;p$#wZxTs_UmxQ>#sd} z_5rYK&~DF;G0It&XXG~!-%WMT>u(~(SuFky;e(0OFV3l4#D54}j{h*a`x5>8EwG$^ zv1f7-|J&el{O_P2Ln8in!E*XV{c=(7N5Iw_`tO0A{~_)G*Yo>`KJwx72jF8!`1~PQ MKY71jsr&uvo4a0?wEzGB diff --git a/builtin.shaders/pbr.vert b/builtin.shaders/pbr.vert index 2c0a291c..7c15f697 100644 --- a/builtin.shaders/pbr.vert +++ b/builtin.shaders/pbr.vert @@ -83,10 +83,12 @@ layout(push_constant) uniform Constants { void main() { SceneUniforms ubo = push_const.global_ubo; ObjectsTable object = push_const.objects; - - vec4 position_in_world = object.model[push_const.model_matrix_idx] * vec4(inPosition, 1.0); + + // retrieve our 3D objects local position within the world + vec4 world_position = object.model[push_const.model_matrix_idx] * vec4(inPosition, 1.0); + // gl_Position = ubo.proj * ubo.view * object.model[push_const.model_matrix_idx] * vec4(inPosition, 1.0); - gl_Position = ubo.proj * ubo.view * position_in_world; + gl_Position = ubo.proj * ubo.view * world_position; fragColor = inColor; fragTexCoords = inTexCoords; // fragNormals = mat3(object.model[push_const.model_matrix_idx]) * inNormals; @@ -95,5 +97,5 @@ void main() { // fragNormals = normal_mat * inNormals; fragDiffuseIdx = push_const.diffuse_idx; fragSpecularIdx = push_const.specular_idx; - FragPos = position_in_world.xyz; + FragPos = world_position.xyz; } \ No newline at end of file From 3c4e97f24b666ac38f6d3e1e7c9b8bc8f1f10b42 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 12 Jun 2026 18:03:24 -0700 Subject: [PATCH 084/106] refactor: update builtin shaders to account for specularity color --- builtin.shaders/pbr.frag | 31 +++++-------------------------- builtin.shaders/pbr.frag.spv | Bin 17452 -> 17656 bytes 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/builtin.shaders/pbr.frag b/builtin.shaders/pbr.frag index 9591e63a..da09d0d0 100644 --- a/builtin.shaders/pbr.frag +++ b/builtin.shaders/pbr.frag @@ -148,7 +148,7 @@ void main() { float roughness = 0.2; float metallic = 0.2; - float ao = 0.2; + float ao = 0.5; vec3 F0 = vec3(0.04); F0 = mix(F0, albedo, metallic); @@ -180,7 +180,7 @@ void main() { float dist = length(src.position.xyz - FragPos); // float attenuation = 1.0 / (dist * dist); float attenuation = src.attenuation / (src.constant + src.linear * dist + src.quadratic * pow(dist, 2)); - vec3 radiance = src.color.rgb * attenuation; + vec3 radiance = src.color.rgb * src.color.a * attenuation; // cook-torrance brdf float NDF = DistributionGGX(normal, H, roughness); @@ -189,7 +189,7 @@ void main() { vec3 numerator = NDF * G * F; float denominator = 4.0 * max(dot(normal, view_dir), 0.0) * max(dot(normal, dir_to_light), 0.0) + 0.0001; - vec3 specular = numerator / denominator; + vec3 specular = numerator / denominator * specular_texture.rgb; vec3 kS = F; vec3 kD = vec3(1.0) - kS; @@ -202,13 +202,13 @@ void main() { Lo += (kD * albedo / PI + specular) * radiance * NdotL; } - + float max_texture_mip_levels = 0.0; vec3 kS = fresnelSchlick(max(dot(normal, view_dir), 0.0), F0); vec3 kD = 1.0 - kS; kD *= 1.0 - metallic; vec2 environment_uv = SampleEquirectangular(normal); // vec3 irradiance = texture(environment_map, environment_uv).rgb; - vec3 irradiance = textureLod(environment_map, environment_uv, 0.0).rgb; + vec3 irradiance = textureLod(environment_map, environment_uv, max_texture_mip_levels).rgb; vec3 diffuse = irradiance * albedo; vec3 ambient = (kD * diffuse.rgb) * ao; vec3 color = ambient + Lo; @@ -216,26 +216,5 @@ void main() { color = color / (color + vec3(1.0)); color = pow(color, vec3(1.0/2.2)); - - - // Calculating diffuse term - // vec2 diffuse_uv = SampleEquirectangular(normal); - // // vec3 ambient_irradiance = textureLod(environment_map, normal, 5.0).rgb; - // vec3 ambient_irradiance = textureLod(environment_map, diffuse_uv, 5.0).rgb; - // vec3 ibl_diffuse = ambient_irradiance * albedo * 0.5; - - // // Calculating the specular term - // vec3 reflect_dir = reflect(view_dir, normal); - // vec2 specular_uv = SampleEquirectangular(reflect_dir); - // // vec3 ambient_radiance = textureLod(environment_map, reflect_dir, 1.5).rgb; - - // vec3 ambient_radiance = textureLod(environment_map, specular_uv, 1.5).rgb; - - - // vec3 ibl_specular = ambient_radiance * specular_texture.rgb * 0.5; - - // final_color += (ibl_diffuse + ibl_specular); - - // outColor = vec4(final_color, 1.0); outColor = vec4(color, 1.0); } \ No newline at end of file diff --git a/builtin.shaders/pbr.frag.spv b/builtin.shaders/pbr.frag.spv index 13d6999b114f1bd432777aea3461b44d34b86a65..c974e556a54b9efce21b1b9df0e91ee9d651a1aa 100644 GIT binary patch delta 4071 zcmZ9O$#Yay7{zZ7NeCnii6)T%5)fqw5I~fOL{cIV!6b+xs2G~ite?Ig{lyu^Tp zja61FS}v?|sih067gn*eT)A+;KR^|ZIH2GN&gb{~eeyafF87@CP50gVz5DvT$;j2y zk=j^vag}osH^bGs)34Ni9GUpw+~Mh+7bDJfZ`tZ9T-<#loK55s8RvZd-4uSQjK|z% z@vg!@4<_B^^ zgPG*uNZ)9_^Z*CSVk%rRT8P%xZA(pY&m^+`X{Dtf97v@`hm$_fiYGD$29(n0dGY?C z^#40LQQTL%J>EjP7HyFx*QF+aFB0YtK2iK+&f-dMz368;x0vP?k}EY&C&rC!Hh!ac z)qw92YpbBn}Nnr&=U+*@!z?s^_ieD&Fj9Tqnxj%H(_i#NCzBv5>&28rMk#qp-& z5xEkfJT-Z0a*(37jkOfXxhdt?PM&0lUm6@9Z5(!>jl(=&ywqGDjdrFCifgt5J>cYris3SZDbH=nPBKh-dwuZ8hL?@-g7*NlcgIldJ>R%$1~&Q{ZVS6AYzw2u;q7Wj7IsZ|ndU2+$w@3e)VS;k;9y1m6z1uT z|0T?VUe)%K>~CRw&})Jx|3_H=+|t0F&`fe(CTx}~qE5((W8=kwd+kcgnM6faX(k9G zPQ0Dy_LOm9w$pfpINz{S!Qv{#@jKW@0%izvKE`Xr!#hwb zjt{!+z)WF<_&b0-A#979CC){QkL8>#T&khBmZzU1;jA*)HrI*cglup14+=-le;CU+H@Euu*{#_Ns1+1@0KQ*Ur2bA{1tOa`xDvowOS6U&W0Pk66Z z*Q2K6f#!>&&5IT~<~Mi?1PMcCEnJgmww8s$oDw#!Ot{$=3!_a0xEe$N%<_m zxdS+kJA@lFQ>;ycSbRFQM?0n8Da?YneaXj>ZiqIP40fjNa@xQsTv*=d-4zN6U)UR^ zW3!#TTbM|6-U*hoNth*Jv*mXPzozoEFFyB(qv6XVVM7c28{B3Qj?fZx3hysOS{tja zf$uH6zoN0w*4pI%?zF^P<+nxSzEEtJ@Oc%m1>P@?A3FKzqiw<*q&?UJ!uX-v8nz3E zA7Y2Nw3!ZPdx{-}f!1d4K`F1R zHKSYnW5Q^5Dvt}NTp_=*&U-=-iVLB8HKP&AmhTe|zsgUFrvly5_emqpj%B|v8orhj z&HVd?*(=#R|JMvcyAGjRi4O|bXy#WA!3oW11fP-qlyEBG_&+U-k1cpWn8VqlW8oco zMwl4<^w0VB;GH}a)yE$P27ep|kitoULmIZ~j4+zCXVR< delta 3902 zcmZ9O+f$WQ7{=FTZ$Jf9qCoM8XlWp(rb)I@N5V)0%?@S(ZUvHLZxBJvoqjmhjNUk7 zyR7M=8E>6#8ZMgQuIai9{{d$@YbQIWmDTh6_IjCb!?;|}^Sr0^z2EySxP2k^!TDH4 zyr{m^xtJ?+74Gb%icezM53ik=mHIN~Tt{o0D|QL@mGE$CB$ak9&eJ{Sl z`~Fa1OSoIca~H~1Y>&G?#M`{@-)8gtp8{U&{u9rPrTa!wqeCO1Pq8b`RhCx;RYlGn z8}2(aHkiVoQ^wsqX-D?vaV@wtfBI#@9lb-NyL^=g#G_BQY8r2t##a~cxN9$R-M&!5 zbrcvAuCsv0-P7XvgOs@a!hMdt`ZKuOqd^dcH(Ab zeMwLvT7r)o-`XG2G=lMH(8|MJbaFlmX<4kST&eTRZQw!fV zv0`CaQPEIrV%_4)rEe}zgcJF>`uVBWMNK$fUkHDuh2ElZxvm{8smZ|pweTr#V@lv= zyCM9sw=pqrY)tyM!WnO4dc*_QtdtnPldwoT2?@l3;@q6rtiX@LR-6%oo9!pzGg`!P zGs4aGi}0kk{j43Hbb22Y|4qbB#&p7)H7eMC7ha{EVk9LPABr&Z*saK)!aTk4+rk{^ zEp?V$cZBglFXzDniGPXcpIhl2Qrbz*XMoL;-4!0u!p0{7Z&q4f$-lx)+KIu251$n} z@f7EBqMOEJ;sH)Y&H_&X!ufuZxPM>ONDto#%G8}J1|omA9Qsf z2v0UkL@{9pa7YQ;p~}R$GV!sb<-*Y-72=ahU~Qf)jt_d+X62hBY&EdwYgFam%UlT* z!s%@8+RCbcXX9SEN6X6IE6nr4Y3P08`0VyCp;{Qt)_MOu)kq^2J9)XE&@AtKVS0>> zyGlHmGA@*Wc+MwVB+Rb}bON}`(Cko)g@=_4e-61syk9%I6(@%&o*^zkMxJoInh-u67tJ(twao+ zKFK;^w6(cQ4K=~TLKeaAX`*QU24QU0=#9ceqBGze=MiC!gw2k>N%(D5KkI#(#nJHP zk+7k8|BdcZ5#FdJ*erZNPFCbGaeUBiT$8!3#+qb{6s$>>@A?*DhSbV$6~+(Ue6|T+ z&m|jcDp7dY?NWHT7jx;xC3Vr`w@H0mt5wU6-0RO5+TYV|r+8Af=wR*?k6t&s#PLD5!F)5u!A5+$c65v1D~x6he@2*3(bhSaYiTM8o|TLVchd030GjpnIpOFR{k%9S z(5=)yVd8AiUJypZ*K(qn|4YL3O|~HX>jI%!FJYz5B1Jgz>Sj;)w7-p#L!7#260>A609tm1%Jt(J69RJDMdO5=JvVEF2yFqvH6W z6Q9wJX8ys52%-tcJh!iJR2+?4-+rZx2@{9SlA>9T<`kTzC697#ATPf9wn`MYF=#?&?UJ+(gIPt5yF4 D7aV$f From 5076f03a2fb85ea882d204564e28d25371de98a8 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 12 Jun 2026 18:04:01 -0700 Subject: [PATCH 085/106] refactor: removed old unused glsl shaders from builtin.shaders --- builtin.shaders/test.frag | 120 ---------------------------------- builtin.shaders/test.frag.spv | Bin 7356 -> 0 bytes builtin.shaders/test.vert | 45 ------------- builtin.shaders/test.vert.spv | Bin 2928 -> 0 bytes 4 files changed, 165 deletions(-) delete mode 100644 builtin.shaders/test.frag delete mode 100644 builtin.shaders/test.frag.spv delete mode 100644 builtin.shaders/test.vert delete mode 100644 builtin.shaders/test.vert.spv diff --git a/builtin.shaders/test.frag b/builtin.shaders/test.frag deleted file mode 100644 index b56bf390..00000000 --- a/builtin.shaders/test.frag +++ /dev/null @@ -1,120 +0,0 @@ -#version 460 - -layout(location = 0) in vec4 fragColor; -layout(location = 1) in vec3 fragNormals; -layout(location = 2) in vec2 fragTexCoords; -layout(location = 3) in vec4 materialColor; -layout(location = 4) in vec3 FragPos; - -layout(location = 0) out vec4 outColor; - -struct directional_light { - vec3 direction; - vec3 view_position; - vec4 ambient; // 4th channel represents the intensity - vec4 diffuse; - vec4 specular; - vec4 color; -}; - -struct point_light { - vec4 position; - vec4 color; - float attenuation; - float constant; - float linear; - float quadratic; - vec4 ambient; // 4th channel is the intensity value - vec4 diffuse; - vec4 specular; -}; - -// we should only ever have a max of 1000 point lights in a given scene -const int max_point_lights = 1000; - -layout(set = 0, binding = 1) uniform light_ubo { - int num_lights; - point_light sources[max_point_lights]; -} light_src; - - -layout(set = 1, binding = 1) uniform sampler2D diffuse_texture; -layout(set = 1, binding = 2) uniform sampler2D specular_texture; - -layout(set = 1, binding = 3) uniform material_ubo { - vec4 ambient; - vec4 diffuse; - vec4 specular; - float shininess; -} material; - -vec3 calc_dir_light(directional_light light, vec3 normal, vec3 view_dir) { - vec3 light_dir = normalize(-light.direction); - - // diffuse shading - float diff = max(dot(normal, light_dir), 0.0); - - // specular shading - vec3 reflect_dir = reflect(-light_dir, normal); - float spec = pow(max(dot(view_dir, reflect_dir), 0.0), material.shininess); - - // final result computation - // because of alignment we set the ambient, diffuse, specular to vec3 and - // use the 4th channel as the intensity values at least for ambient strength - vec3 ambient_offset = light.ambient.rgb * light.ambient.a; - vec3 diffuse_offset = light.diffuse.rgb * light.diffuse.a; - vec3 specular_offset = light.specular.rgb; - vec3 ambient = ambient_offset * vec3(texture(diffuse_texture, fragTexCoords)); - vec3 diffuse = (diffuse_offset * light.color.rgb) * diff * vec3(texture(diffuse_texture, fragTexCoords)); - vec3 specular = specular_offset * spec * vec3(texture(specular_texture, fragTexCoords)); - - return (ambient + diffuse + specular); -} - -vec3 calc_point_light(point_light light, vec3 normal, vec3 fragPos, vec3 view_dir) { - vec3 light_pos = vec3(light.position); - vec3 dir_to_light = normalize(light_pos - fragPos); - - float diff = max(dot(normal, dir_to_light), 0.0); - - vec3 reflect_dir = reflect(-dir_to_light, normal); - - float spec = pow(max(dot(view_dir, reflect_dir), 0.0), material.shininess); - - float dist = length(light_pos - fragPos); - float attenuation = light.attenuation / (light.constant + light.linear * dist + light.quadratic * pow(dist, 2)); - - vec3 ambient = light.ambient.rgb * vec3(texture(diffuse_texture, fragTexCoords)); - vec3 diffuse = - light.diffuse.xyz * diff * vec3(texture(diffuse_texture, fragTexCoords)); - vec3 specular = light.specular.xyz * spec * vec3(texture(specular_texture, fragTexCoords)); - - ambient *= attenuation; - diffuse *= attenuation; - specular *= attenuation; - - return (ambient + diffuse + specular); -} - -void main() { - - // default ambience is used if there are no point lights assigned in a given scene - vec3 default_ambience = (vec3(texture(diffuse_texture, fragTexCoords)) * fragColor.rgb) * 0.1; - vec3 result = default_ambience; - - // we only want to select the most minimal size of point lights. - // if we have 2 point lights out of 1000, we iterate 2 point lights - // if the cases that we try to have 1005 point lights, we only iterate the 1000'th point light - // since that is how much we allocated to iterate that many point lights - int num_point_lights = int(min(light_src.num_lights, max_point_lights)); - - // iterate through all of the point lights in a given environment - for (int i = 0; i < num_point_lights; i++) { - point_light source_light = light_src.sources[i]; - vec3 view_pos = source_light.position.xyz; - vec3 dir_to_light = normalize(view_pos - FragPos.xyz); - result += calc_point_light(source_light, fragNormals, FragPos, dir_to_light) * (source_light.color.rgb * source_light.color.a); - } - - outColor = vec4(result, 1.0); -} \ No newline at end of file diff --git a/builtin.shaders/test.frag.spv b/builtin.shaders/test.frag.spv deleted file mode 100644 index d334191367bdcbea5bc8ac6b4c8da038e2922b9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7356 zcmZve2bi2y6^8$0cNT%r1cC^}4M71R5u_V|jYt-CB|(~sI1ID1Fu1!Dri8?nAfni? z;q%xfwkX)JVaH(CU~i~sR1gpw78DTlegC;9Tu1J+-*e9SPPzAmUOz4OAbHc5Ce8BhRQf&b|PvRDQ0TTSsgX70c-&` zgL}bTf_Em*I3`3JVwR%V3_o0KSBy_o$5*TvpE$8vU$v^*>8_n_RHvJ>jp}5x-Kck) zs~g5WB#Ud#)~9=uc|e7Td>xgdLPk-nYBguOR6FndE;|}2IcWG!v)gQyYaU6lET^cq zrdw@f#JbK}x7(QQ)ynYT?LxgZ+v(P3yQswX=W`9Ny+)CUt-xK_t4+2kQO{yW&}%d2 zHXD?PeET!moSN!&8e8+-M`u-|-kY{+!AyG;yCCbe>3TKW-~pX(yI1cn&Zxz!rw%VM zb?D-)f59OSUAlVeu&pR-4|5ybgB^3OVa~iLW?Su<+H~LE345wtJ8xyHgTKPr7RBmj z<08)swd8h1mNi&lr{qS8eUOAyyRCE}B|ls&D*34?M45XavfY@P=IqOou3-tBJ?O`b z6o;YA)Vhs!vo>Aro!gSPhw_fRuX3Jk-d8!#Ht(zFCGXjG&Tr0gjGYd;dprUe^P$2F z7fX?o%}#m##*AU-cg2{~<wHsuPl<&r#p4M1%LaWuD?9V$~ zG#`j3u2QVQ&evSwMXk%YtwrJVz0v%}RINANt@hVZ=QZ{Bv;payC!{;?dN;zg8y&*? z`B!1j_Ga>H=F-ZwT#d}`8oL-NB6->T~vE^dKaRcqH~klMEn*tZYZ zcl?iCDZk&XUN^2txgNjg@fN}{&i)P~*YiAyD0Ro8zSzpyCpo_v5oeCvXvPgC&L5p| z*6sUS2;{@w7u|Z=zAOE?o%?I}769im-Zx`>Zs+kE@EPxLo!%3N>vRO?d~&fLhsZD^C;MZ zc=xGo{RRBL;U49J*B1z0IZDR1Db5^gZI@!5OaJ!CFTaqA^N{N1=?m;m>~7ejU=BDa z*}J1VtTi7Q^K09qSflZ-aev@gfaUv$_=q#_aCrNme`&J4`*Jbwk?669qms}1;a`@x zu$N=ozpy9Jy=U6yd0!Y~;XeaIeos2_%%r>Te1yFhD>(~?ajySaDM-%sYx_1Go7DohauhgRoAw96Z5+>bi`-9^E}!_sd9YIJfq%kovsa&ZE5r$c62@)sB7KiOw`-{yj-| z-^OeEuJs#lkM09SvHp1dSEBjOt#>3h&9!*{9OnEBrh+uqH|GB+QCoXsW_vzY4cPvU zM!auzQ)Zj*Z)o_n{rwEv_**ht|E&Y|?F055$v&3#davIEywloM>a>-Vl2IX^`=XDu*C+qm%m3|+tH=eaxI z&w+frxnCqs-Z2MwHrBflso&h~kiP_SVgDL^3%G=R>;DZfMt)v;`@coE=7~VRb#Fq- zTgUzU4r~JYZb^2`aU1r{$#*MKJAA)K-vZ3@o2MPVKcG90KEHq3$E5GfAJKOK&Sgz= zjfuYf3ElNv53IKh^3Om%`u3N^$vfPmee>Pzi~K8y8h4^w$2;=3Qq6=ZLp*Kf0VFxc{Kb*^A&bLr+!{1)-m1pIc z2aY0cTjUN&-yXSRrtg&LJEPl&ha%&*dRKJU5cWQq?YS+=Y-=Bw+4`3Z*h>fOvCKCA z^Z~m$V6RDb+`T=p-CO=3&s&JoeB<@ocY7iq zXT1PjF6>93+t+yKqv*!S$2(t$?%clfQD9wrD<5_CL-(x0ek8gvS8&e0jYk1v63#61Pw+WMmQQ_-zG0ixE)=<;E&K(}`E^%V5ztG<;W z=6xEv`NqV&r=mNzzRS{DPD8gB`t02pQqFbFN1h2>*BQWdY=e9{kdNPvXCzME;hN?G zj~=@{Zsd=yKK%ZYpuk7yqB1hi<;{`r~)#e00~U z-@W=RlZ(AR2i?710AjDx=<>1G8FV?}$oJ}b&w@oDeh*vd=Ez4sR-xzpxDY$(g&P)*$6vr)PT^7)!R_+?N6GQ0(pHi8C(lmt5q(0(~sm=D!ly^T>Zy z;*5*)kc<4w(Z`Z){;Pp&jQrOm&bU~=ocYGT7P#K9Ux)7eejoI|9vCAZF;}2FN5s4V O-8lLCdF9&vZ}VTrjRfuh diff --git a/builtin.shaders/test.vert b/builtin.shaders/test.vert deleted file mode 100644 index ebd6260b..00000000 --- a/builtin.shaders/test.vert +++ /dev/null @@ -1,45 +0,0 @@ -#version 460 - -#extension GL_EXT_nonuniform_qualifier : enable // Required for descriptor indexing - -layout(location = 0) in vec3 inPosition; -layout(location = 1) in vec3 inColor; -layout(location = 2) in vec3 inNormals; -layout(location = 3) in vec2 inTexCoords; - -layout(location = 0) out vec4 fragColor; -layout(location = 1) out vec3 fragNormals; -layout(location = 2) out vec2 fragTexCoords; -layout(location = 3) out vec4 materialColor; -layout(location = 4) out vec3 FragPos; - -layout (set = 0, binding = 0) uniform UniformBuffer { - mat4 proj_view; -} ubo; - -// To create a set=1, you just create another vk::descriptor_set object after the first descriptor set, because thats automatic. -layout (set = 1, binding = 0) uniform geometry_ubo { - mat4 model; - vec4 color; // base color for object (NOTE: if materialColor uses this, we get error because we do not have a specific descriptor set for this layout yet, come back after getting food) -} geometry_src; - -void main() { - // FragPos = material_src.model * vec4(inPositoin, 1.0); - vec4 pos_to_world = geometry_src.model * vec4(inPosition, 1.0); - - // vec3 normalize_mat = normalize(mat3(ubo.proj_view) * inNormals); - mat3 normalize_worldspace = mat3(transpose(inverse(geometry_src.model))); - - - vec3 normal = normalize(normalize_worldspace * inNormals); - - gl_Position = ubo.proj_view * pos_to_world; - - // FragPos = vec3(geometry_src.model * vec4(inPosition, 1.0)); - FragPos = pos_to_world.xyz; - // gl_Position = (ubo.proj_view * geometry_src.model) * vec4(inPosition, 1.0); - fragColor = vec4(inColor, 1.0); - fragTexCoords = inTexCoords; - fragNormals = normal; - materialColor = geometry_src.color; -} \ No newline at end of file diff --git a/builtin.shaders/test.vert.spv b/builtin.shaders/test.vert.spv deleted file mode 100644 index e7b11cca922bcedd55c83a3e73bbf5df23e575d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2928 zcmZ9N*>W326oxytMhV#g zH*Q`><@knTn55G%Ps5jK77xWb@DtkiqjVhQ+3RrjTMFKk1e`Tahf%EE zFzPW#<22Kb{VDBp`)M{1D?BLb&bY117o^ohB^eUk6#YV=G-ZzS7{ z{p6va=KVzBn2ZTPHjCrAEKon`Ig9*nYkyjHvNaox)WtF$aMmPCe-B^y=%vosey5!> zlP`0#o%Qz>u=t>up^^B_d3_tjO!=flxR3clrx(52Ow(*w)+H!r&L;;b{+K~@t%BGy zljD9KWxgNVJ#EEBzp2HJ;Ny)`ITJ7atmg;6Dq$g6zo$o_Ln^eM~zTbW!~A>Wq9zJoPdR{gdMH3x22K=`q+j@u#&f zi^%6{#h1UH<$cT#y7(lXv)YM=c=7*^c5K1%56_I4KXfmMocrrO@qVBax@J!;$ORmK zS1Z2mj~T-s@qSh4=}U`v;lCCkza;*KcJ2gQ(usMq8X|+Z=azP2Ku+B7{7!%^>6_Uh zXLP^SP7T1&g=cQSkl)vi9rwU*RJ`Q?->NX|(ch}^)NEUHL`01{+R4HE|D-ei!Lf&D z?!dTjS39;Qhvz>H4E+u5%pv-Af3M=L=TF6>kH2Tyxtn}$>4kA-zF7G9R|xM8U(6%_ zRp`RgPyRQIr=QmHIA_jJ3y(*`* z3L`e|x*`H&?W%I*`Jo6LV&R9_&E_MWu>m)mk97uzSch#s5rz$Z%;r;_!6BB}bd>{d z?=umx;2T|PK_9{C2|AyPz^q4K=*-)smgI6>gbp~h0sB(KUCcXj{4x*VR^vN5^PcMS z@V$6&?xJ>gMfAq{c28$?!12SIdLZHrLI^)A?@=#|mh-Edwwk009<=WPH zTSQ-)+IK`?EW>`#84N#${a9i2!shXj&e)@moO$F9eBIHh?rU4wB`Q1!qMmL!~ds9Z;Sp1Er{uU From d7582510f56a555701644d395bb8292a3d0d10b0 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 12 Jun 2026 18:41:17 -0700 Subject: [PATCH 086/106] refactor: disable window resizing temporarily --- atlas/drivers/vulkan/imgui_context.cppm | 19 +++++++++++++++++++ atlas/drivers/vulkan/window.cppm | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index 29b21ce1..edc69f75 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -13,6 +13,7 @@ module; #include #include #include +#include export module atlas.drivers.vulkan:imgui_context; @@ -146,6 +147,24 @@ namespace atlas { IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); + io.IniFilename = nullptr; + + std::filesystem::path path = std::filesystem::current_path() / "imgui.ini"; + + std::string data_source=""; + if(std::filesystem::exists(path)) { + std::ifstream file(path.string()); + + if(!file) { + std::println("Cannot load {}", path.string()); + } + + std::stringstream ss; + ss << file.rdbuf(); + data_source = ss.str(); + } + + ImGui::LoadIniSettingsFromMemory(data_source.c_str(), data_source.size()); io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index d76ca3cd..5b204509 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -36,7 +36,7 @@ export namespace atlas { m_instance = p_context->instance_handle(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); m_window = glfwCreateWindow(static_cast(p_params.width), static_cast(p_params.height), From 8ba2d8f4b34e8dbb8853389dd2e4505ae7194cf2 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Fri, 12 Jun 2026 22:33:33 -0700 Subject: [PATCH 087/106] refactor: moved gpu-specific data to gpu_uniforms.cppm --- atlas/drivers/vulkan/gpu_uniforms.cppm | 83 ++++++++++++++++++++++++ atlas/drivers/vulkan/render_context.cppm | 69 +------------------- 2 files changed, 85 insertions(+), 67 deletions(-) create mode 100644 atlas/drivers/vulkan/gpu_uniforms.cppm diff --git a/atlas/drivers/vulkan/gpu_uniforms.cppm b/atlas/drivers/vulkan/gpu_uniforms.cppm new file mode 100644 index 00000000..5eb9da73 --- /dev/null +++ b/atlas/drivers/vulkan/gpu_uniforms.cppm @@ -0,0 +1,83 @@ +module; + +#include + +#define GLM_FORCE_RADIANS +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include + +export module atlas.drivers.vulkan:gpu_uniforms; + +import vk; + + +export namespace atlas { + struct gpu_mesh_data { + vk::vertex_buffer vertex; + vk::index_buffer index; + uint32_t index_count=0; + uint32_t instance=1; + uint32_t first_index=0; + uint32_t vertex_offset=0; + uint32_t first_instance=0; + bool has_indices_buffer=false; + uint32_t vertices_size = 0; + uint32_t indices_size=0; + }; + + struct push_constant_data { + uint64_t scene_address=0; + uint64_t model_mat_array_address=0; + uint32_t model_idx=0; + uint32_t diffuse_idx=0; + uint32_t specular_idx=0; + uint64_t point_light_address; + }; + + struct scene_uniforms { + glm::mat4 view=glm::mat4(1.f); + glm::mat4 proj=glm::mat4(1.f); + glm::vec4 camera_pos=glm::vec4(1.f); + }; + + struct objects_uniform { + std::span model_matrices; + }; + + struct gpu_material { + uint64_t diffuse_idx=0; + uint64_t specular_idx=0; + }; + + struct gpu_point_light { + glm::vec4 position; // this is provided by the transform + glm::vec4 color = { 1.f, 1.f, 1.f, 1.f }; + float attenuation = 1.f; + float constant = 1.f; + float linear = 1.f; + float quadratic = 1.f; + + glm::vec4 ambient = glm::vec4(1.f); + glm::vec4 diffuse = glm::vec4(1.f); + glm::vec4 specular = glm::vec4(1.f); + }; + + struct light_scene_ubo { + alignas(16) uint32_t num_lights=0; + alignas(16) std::array point_lights{}; + }; + + + /** + * + * @brief slot is the index into the texture array to retrieve this specific texture data + * + * vk::texture is the texture data to configure the GPU-visible image resource + */ + struct gpu_image { + uint64_t slot=0; + vk::texture texture_data; + }; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index c774f87b..2fe39b54 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -13,6 +13,7 @@ module; #include #define GLM_ENABLE_EXPERIMENTAL #include + export module atlas.drivers.vulkan:render_context; import atlas.core.scene; @@ -24,77 +25,11 @@ import atlas.core.utilities; import :graphics_context; import :environment_map; +import :gpu_uniforms; import vk; export namespace atlas { - struct gpu_mesh_data { - vk::vertex_buffer vertex; - vk::index_buffer index; - uint32_t index_count=0; - uint32_t instance=1; - uint32_t first_index=0; - uint32_t vertex_offset=0; - uint32_t first_instance=0; - bool has_indices_buffer=false; - uint32_t vertices_size = 0; - uint32_t indices_size=0; - }; - - struct push_constant_data { - uint64_t scene_address=0; - uint64_t model_mat_array_address=0; - uint32_t model_idx=0; - uint32_t diffuse_idx=0; - uint32_t specular_idx=0; - uint64_t point_light_address; - }; - - struct scene_uniforms { - glm::mat4 view=glm::mat4(1.f); - glm::mat4 proj=glm::mat4(1.f); - glm::vec4 camera_pos=glm::vec4(1.f); - }; - - struct objects_uniform { - std::span model_matrices; - }; - - struct gpu_material { - uint64_t diffuse_idx=0; - uint64_t specular_idx=0; - }; - - struct gpu_point_light { - glm::vec4 position; // this is provided by the transform - glm::vec4 color = { 1.f, 1.f, 1.f, 1.f }; - float attenuation = 1.f; - float constant = 1.f; - float linear = 1.f; - float quadratic = 1.f; - - glm::vec4 ambient = glm::vec4(1.f); - glm::vec4 diffuse = glm::vec4(1.f); - glm::vec4 specular = glm::vec4(1.f); - }; - - struct light_scene_ubo { - alignas(16) uint32_t num_lights=0; - alignas(16) std::array point_lights{}; - }; - - - /** - * - * @brief slot is the index into the texture array to retrieve this specific texture data - * - * vk::texture is the texture data to configure the GPU-visible image resource - */ - struct gpu_image { - uint64_t slot=0; - vk::texture texture_data; - }; - /** * @brief Core render context to schedule images and barriers for coordinating rendering operations * From 1fd6d242a5a4e9750d537896475a850ee3697002 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sat, 13 Jun 2026 00:04:09 -0700 Subject: [PATCH 088/106] refactor: update project CMakeLists.txt to include gpu_uniforms.cppm --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c96af4fd..d3baa7cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,6 +205,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/vulkan/utilities.cppm atlas/drivers/vulkan/environment_map.cppm atlas/drivers/vulkan/stb_image.cppm + atlas/drivers/vulkan/gpu_uniforms.cppm atlas/drivers/vulkan/hash.cppm atlas/drivers/vulkan/shader_resource_group.cppm From 14d656267b3dd1213e102777a3e468e6525f6813 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sat, 13 Jun 2026 23:10:10 -0700 Subject: [PATCH 089/106] refactor: fixed logger imports to be a module partition rather then representing as an indivudal primary module --- atlas/core/entry_point/main.cpp | 2 +- atlas/core/filesystem/file_dialog.cppm | 2 +- atlas/core/logger.cppm | 2 +- atlas/core/scene/level_streamer.cppm | 2 +- atlas/core/serialize/serializer.cppm | 2 +- atlas/core/utilities/utilities.cppm | 3 ++- atlas/drivers/jolt_cpp/contact_listener.cppm | 3 ++- atlas/drivers/vulkan/shader_resource_group.cppm | 3 ++- atlas/drivers/vulkan/utilities.cppm | 3 ++- editor/content_browser_panel.cppm | 2 +- 10 files changed, 14 insertions(+), 10 deletions(-) diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 80737005..99375aff 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -20,7 +20,7 @@ import atlas.application; import atlas.common; -import atlas.logger; +import atlas.core.utilities; import atlas.graphics_api; import atlas.drivers.vulkan; import atlas.core.event; diff --git a/atlas/core/filesystem/file_dialog.cppm b/atlas/core/filesystem/file_dialog.cppm index 03954ba5..ae31d2cf 100644 --- a/atlas/core/filesystem/file_dialog.cppm +++ b/atlas/core/filesystem/file_dialog.cppm @@ -6,7 +6,7 @@ module; export module atlas.core.filesystem.file_dialog; -import atlas.logger; +import atlas.core.utilities; export namespace atlas::filesystem { std::string load_from_file_dialog( diff --git a/atlas/core/logger.cppm b/atlas/core/logger.cppm index e71f24b6..3c4157fa 100644 --- a/atlas/core/logger.cppm +++ b/atlas/core/logger.cppm @@ -10,7 +10,7 @@ module; #include #include -export module atlas.logger; +export module atlas.core.utilities:logger; export import atlas.common; export namespace atlas { diff --git a/atlas/core/scene/level_streamer.cppm b/atlas/core/scene/level_streamer.cppm index d4be6a16..75f9f550 100644 --- a/atlas/core/scene/level_streamer.cppm +++ b/atlas/core/scene/level_streamer.cppm @@ -8,7 +8,7 @@ module; export module atlas.core.level_streamer; -import atlas.logger; +import atlas.core.utilities; import atlas.core.scene; import atlas.core.scene.uuid; import atlas.core.event; diff --git a/atlas/core/serialize/serializer.cppm b/atlas/core/serialize/serializer.cppm index bcc32094..b6c95988 100644 --- a/atlas/core/serialize/serializer.cppm +++ b/atlas/core/serialize/serializer.cppm @@ -15,7 +15,7 @@ import atlas.common; import atlas.core.scene; import atlas.core.serialize.types; import atlas.core.scene.components; -import atlas.logger; +import atlas.core.utilities; namespace atlas { // used to serialize entities diff --git a/atlas/core/utilities/utilities.cppm b/atlas/core/utilities/utilities.cppm index fbc783e5..22f4ce6e 100644 --- a/atlas/core/utilities/utilities.cppm +++ b/atlas/core/utilities/utilities.cppm @@ -1,6 +1,7 @@ export module atlas.core.utilities; -export import atlas.logger; +// export import atlas.logger; +export import :logger; export import atlas.common; export import :types; export import atlas.core.utilities.state; diff --git a/atlas/drivers/jolt_cpp/contact_listener.cppm b/atlas/drivers/jolt_cpp/contact_listener.cppm index d5ba6a54..560d81d3 100644 --- a/atlas/drivers/jolt_cpp/contact_listener.cppm +++ b/atlas/drivers/jolt_cpp/contact_listener.cppm @@ -33,7 +33,8 @@ module; #include export module atlas.drivers.jolt_cpp.contact_listener; -import atlas.logger; +// import atlas.logger; +import atlas.core.utilities; // import atlas.core.event.types; import atlas.core.event; diff --git a/atlas/drivers/vulkan/shader_resource_group.cppm b/atlas/drivers/vulkan/shader_resource_group.cppm index f5c789f3..9d0b2a91 100644 --- a/atlas/drivers/vulkan/shader_resource_group.cppm +++ b/atlas/drivers/vulkan/shader_resource_group.cppm @@ -8,7 +8,8 @@ module; export module atlas.drivers.vulkan.shader_resource_group; -import atlas.logger; +// import atlas.logger; +import atlas.core.utilities; import vk; namespace atlas::vulkan { diff --git a/atlas/drivers/vulkan/utilities.cppm b/atlas/drivers/vulkan/utilities.cppm index ee23cf15..8c25898e 100644 --- a/atlas/drivers/vulkan/utilities.cppm +++ b/atlas/drivers/vulkan/utilities.cppm @@ -4,7 +4,8 @@ module; #include export module atlas.drivers.vulkan.utilities; -import atlas.logger; +// import atlas.logger; +import atlas.core.utilities; export namespace atlas { namespace vulkan { diff --git a/editor/content_browser_panel.cppm b/editor/content_browser_panel.cppm index e59f663c..1bb4f9d3 100644 --- a/editor/content_browser_panel.cppm +++ b/editor/content_browser_panel.cppm @@ -9,7 +9,7 @@ module; export module editor:content_browser; -import atlas.logger; +import atlas.core.utilities; import atlas.drivers.vulkan; import atlas.drivers.vulkan.stb_image; import vk; From 096cbbdab2348efcfcde46a9c3db0e40dc6f253e Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sat, 13 Jun 2026 23:11:15 -0700 Subject: [PATCH 090/106] refactor: removed unused logger imports as it is replaced with the utilities import instead --- atlas/core/utilities/utilities.cppm | 1 - atlas/drivers/jolt_cpp/contact_listener.cppm | 2 -- atlas/drivers/jolt_cpp/context.cppm | 2 -- atlas/drivers/vulkan/shader_resource_group.cppm | 1 - atlas/drivers/vulkan/utilities.cppm | 2 +- 5 files changed, 1 insertion(+), 7 deletions(-) diff --git a/atlas/core/utilities/utilities.cppm b/atlas/core/utilities/utilities.cppm index 22f4ce6e..5a68d1cd 100644 --- a/atlas/core/utilities/utilities.cppm +++ b/atlas/core/utilities/utilities.cppm @@ -1,6 +1,5 @@ export module atlas.core.utilities; -// export import atlas.logger; export import :logger; export import atlas.common; export import :types; diff --git a/atlas/drivers/jolt_cpp/contact_listener.cppm b/atlas/drivers/jolt_cpp/contact_listener.cppm index 560d81d3..2aae06dc 100644 --- a/atlas/drivers/jolt_cpp/contact_listener.cppm +++ b/atlas/drivers/jolt_cpp/contact_listener.cppm @@ -33,9 +33,7 @@ module; #include export module atlas.drivers.jolt_cpp.contact_listener; -// import atlas.logger; import atlas.core.utilities; -// import atlas.core.event.types; import atlas.core.event; export namespace atlas::physics { diff --git a/atlas/drivers/jolt_cpp/context.cppm b/atlas/drivers/jolt_cpp/context.cppm index 2d874ace..0b3e52c0 100644 --- a/atlas/drivers/jolt_cpp/context.cppm +++ b/atlas/drivers/jolt_cpp/context.cppm @@ -37,8 +37,6 @@ module; export module atlas.drivers.jolt_cpp.context; -// import atlas.logger; -// import atlas.common; import atlas.core.utilities; import atlas.core.event; import atlas.core.scene.components; diff --git a/atlas/drivers/vulkan/shader_resource_group.cppm b/atlas/drivers/vulkan/shader_resource_group.cppm index 9d0b2a91..4ce45da1 100644 --- a/atlas/drivers/vulkan/shader_resource_group.cppm +++ b/atlas/drivers/vulkan/shader_resource_group.cppm @@ -8,7 +8,6 @@ module; export module atlas.drivers.vulkan.shader_resource_group; -// import atlas.logger; import atlas.core.utilities; import vk; diff --git a/atlas/drivers/vulkan/utilities.cppm b/atlas/drivers/vulkan/utilities.cppm index 8c25898e..f7cb0ec1 100644 --- a/atlas/drivers/vulkan/utilities.cppm +++ b/atlas/drivers/vulkan/utilities.cppm @@ -4,7 +4,7 @@ module; #include export module atlas.drivers.vulkan.utilities; -// import atlas.logger; + import atlas.core.utilities; export namespace atlas { From e7ff24e280d978d4c42a8c20a87b88d8efa8d03e Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sat, 13 Jun 2026 23:16:52 -0700 Subject: [PATCH 091/106] refactor: changed import atlas.common to making common.cppm as a module partition --- atlas/core/common.cppm | 2 +- atlas/core/core.cppm | 2 +- atlas/core/entry_point/main.cpp | 1 - atlas/core/logger.cppm | 2 +- atlas/core/scene/world.cppm | 2 +- atlas/core/serialize/serializer.cppm | 1 - atlas/core/utilities/utilities.cppm | 2 +- atlas/drivers/jolt_cpp/broad_phase.cppm | 2 +- atlas/drivers/physics_context.cppm | 2 +- atlas/drivers/vulkan/imgui_context.cppm | 2 +- atlas/drivers/vulkan/window.cppm | 1 - atlas/physics/physics_engine.cppm | 2 +- editor/application.cpp | 2 +- 13 files changed, 10 insertions(+), 13 deletions(-) diff --git a/atlas/core/common.cppm b/atlas/core/common.cppm index 62f1de6d..b84a8c0f 100644 --- a/atlas/core/common.cppm +++ b/atlas/core/common.cppm @@ -3,7 +3,7 @@ module; #include #include -export module atlas.common; +export module atlas.core.utilities:common; export namespace atlas { /** diff --git a/atlas/core/core.cppm b/atlas/core/core.cppm index 7c580ddc..b47ba83e 100644 --- a/atlas/core/core.cppm +++ b/atlas/core/core.cppm @@ -1,7 +1,7 @@ export module core; // export import :common; -export import atlas.common; +// export import atlas.common; // export import :application; // export import :logger; diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 99375aff..176248ea 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -19,7 +19,6 @@ #endif import atlas.application; -import atlas.common; import atlas.core.utilities; import atlas.graphics_api; import atlas.drivers.vulkan; diff --git a/atlas/core/logger.cppm b/atlas/core/logger.cppm index 3c4157fa..7feed1e3 100644 --- a/atlas/core/logger.cppm +++ b/atlas/core/logger.cppm @@ -11,7 +11,7 @@ module; #include export module atlas.core.utilities:logger; -export import atlas.common; +export import :common; export namespace atlas { /** diff --git a/atlas/core/scene/world.cppm b/atlas/core/scene/world.cppm index a72102cf..000a6d71 100644 --- a/atlas/core/scene/world.cppm +++ b/atlas/core/scene/world.cppm @@ -6,7 +6,7 @@ module; export module atlas.core.scene.world; -import atlas.common; +import atlas.core.utilities; import atlas.core.scene; import atlas.core.level_streamer; import atlas.core.event; diff --git a/atlas/core/serialize/serializer.cppm b/atlas/core/serialize/serializer.cppm index b6c95988..e7aa8a49 100644 --- a/atlas/core/serialize/serializer.cppm +++ b/atlas/core/serialize/serializer.cppm @@ -11,7 +11,6 @@ module; export module atlas.core.serialize; -import atlas.common; import atlas.core.scene; import atlas.core.serialize.types; import atlas.core.scene.components; diff --git a/atlas/core/utilities/utilities.cppm b/atlas/core/utilities/utilities.cppm index 5a68d1cd..dc5d8c40 100644 --- a/atlas/core/utilities/utilities.cppm +++ b/atlas/core/utilities/utilities.cppm @@ -1,6 +1,6 @@ export module atlas.core.utilities; export import :logger; -export import atlas.common; +export import :common; export import :types; export import atlas.core.utilities.state; diff --git a/atlas/drivers/jolt_cpp/broad_phase.cppm b/atlas/drivers/jolt_cpp/broad_phase.cppm index cb4d9b71..3c036de1 100644 --- a/atlas/drivers/jolt_cpp/broad_phase.cppm +++ b/atlas/drivers/jolt_cpp/broad_phase.cppm @@ -34,7 +34,7 @@ module; export module atlas.drivers.jolt_cpp.broad_phase; -import atlas.common; +import atlas.core.utilities; export namespace atlas::physics { diff --git a/atlas/drivers/physics_context.cppm b/atlas/drivers/physics_context.cppm index 2418b33c..aa65fed9 100644 --- a/atlas/drivers/physics_context.cppm +++ b/atlas/drivers/physics_context.cppm @@ -5,7 +5,7 @@ module; export module atlas.drivers.physics_context; -import atlas.common; +import atlas.core.utilities; import atlas.core.scene.components; import atlas.core.event; diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index edc69f75..b0dbea16 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -19,7 +19,7 @@ export module atlas.drivers.vulkan:imgui_context; import :graphics_context; -import atlas.common; +import atlas.core.utilities; import vk; import atlas.core.utilities; diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index 5b204509..a1fa470d 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -20,7 +20,6 @@ module; export module atlas.drivers.vulkan:window; -import atlas.common; import atlas.core.utilities; import vk; import :graphics_context; diff --git a/atlas/physics/physics_engine.cppm b/atlas/physics/physics_engine.cppm index 99717614..bb86cb0c 100644 --- a/atlas/physics/physics_engine.cppm +++ b/atlas/physics/physics_engine.cppm @@ -5,7 +5,7 @@ module; export module atlas.physics.engine; -import atlas.common; +import atlas.core.utilities; import atlas.core.scene.components; import atlas.core.event; import atlas.drivers.physics_context; diff --git a/editor/application.cpp b/editor/application.cpp index 3de3d8f5..f3640ab2 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -3,7 +3,7 @@ #include import atlas.application; -import atlas.common; +import atlas.core.utilities; import atlas.core.level_streamer; import atlas.core.event; import editor; From f4b68346b03893d4a73a3fb350526d98d4b84c57 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sat, 13 Jun 2026 23:19:14 -0700 Subject: [PATCH 092/106] refactor: remove graphics_api enum as there is no reason for an RHI abstraction --- atlas/core/api.cppm | 9 --------- atlas/core/entry_point/main.cpp | 1 - 2 files changed, 10 deletions(-) delete mode 100644 atlas/core/api.cppm diff --git a/atlas/core/api.cppm b/atlas/core/api.cppm deleted file mode 100644 index cc0af195..00000000 --- a/atlas/core/api.cppm +++ /dev/null @@ -1,9 +0,0 @@ -module; - -#include - -export module atlas.graphics_api; - -export namespace atlas { - enum class graphics_api : uint8_t { vulkan, dx11, fx12, undefined }; -}; \ No newline at end of file diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 176248ea..b233246f 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -20,7 +20,6 @@ import atlas.application; import atlas.core.utilities; -import atlas.graphics_api; import atlas.drivers.vulkan; import atlas.core.event; import vk; From 1b4a2d5f91b92bc4b00b7b1c6d9257f561632673 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sat, 13 Jun 2026 23:49:47 -0700 Subject: [PATCH 093/106] refactor: move state.cppm and poll_state.cppm as module partitions --- atlas/core/application.cppm | 1 - atlas/core/utilities/poll_state.cppm | 2 +- atlas/core/utilities/state.cppm | 4 ++-- atlas/core/utilities/utilities.cppm | 3 ++- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index a8ebfcbf..59b42ada 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -24,7 +24,6 @@ module; export module atlas.application; import atlas.core.utilities; -import atlas.core.utilities.poll_state; import atlas.core.event; import vk; import atlas.drivers.vulkan; diff --git a/atlas/core/utilities/poll_state.cppm b/atlas/core/utilities/poll_state.cppm index 4568cbc6..300bacae 100644 --- a/atlas/core/utilities/poll_state.cppm +++ b/atlas/core/utilities/poll_state.cppm @@ -5,7 +5,7 @@ module; #include #include -export module atlas.core.utilities.poll_state; +export module atlas.core.utilities:poll_state; export namespace atlas { inline std::unordered_map>> diff --git a/atlas/core/utilities/state.cppm b/atlas/core/utilities/state.cppm index 05b53f4c..9f277ead 100644 --- a/atlas/core/utilities/state.cppm +++ b/atlas/core/utilities/state.cppm @@ -3,9 +3,9 @@ module; #include #include -export module atlas.core.utilities.state; +export module atlas.core.utilities:state; -import atlas.core.utilities.poll_state; +import :poll_state; export namespace atlas { /** diff --git a/atlas/core/utilities/utilities.cppm b/atlas/core/utilities/utilities.cppm index dc5d8c40..0779c2dc 100644 --- a/atlas/core/utilities/utilities.cppm +++ b/atlas/core/utilities/utilities.cppm @@ -3,4 +3,5 @@ export module atlas.core.utilities; export import :logger; export import :common; export import :types; -export import atlas.core.utilities.state; +export import :poll_state; +export import :state; From 1399033803a7175505b576b7a5b78d32fa7b9a72 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 00:02:03 -0700 Subject: [PATCH 094/106] refactor: added ui.cppm for partitioning the moudle units for widgets and imgui_stdlib.cppm --- atlas/core/ui/imgui_stdlib.cppm | 2 +- atlas/core/ui/ui.cppm | 7 +++++++ atlas/core/ui/widgets.cppm | 2 +- editor/editor_world.cppm | 3 +-- editor/utilities.cppm | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 atlas/core/ui/ui.cppm diff --git a/atlas/core/ui/imgui_stdlib.cppm b/atlas/core/ui/imgui_stdlib.cppm index 888093bd..52cb5490 100644 --- a/atlas/core/ui/imgui_stdlib.cppm +++ b/atlas/core/ui/imgui_stdlib.cppm @@ -3,7 +3,7 @@ module; #include #include -export module atlas.core.ui.widgets.imgui_stdlib; +export module atlas.core.ui:imgui_stdlib; struct InputTextCallback_UserData { std::string* Str; diff --git a/atlas/core/ui/ui.cppm b/atlas/core/ui/ui.cppm new file mode 100644 index 00000000..c71aa14a --- /dev/null +++ b/atlas/core/ui/ui.cppm @@ -0,0 +1,7 @@ +module; + +export module atlas.core.ui; + + +export import :widgets; +export import :imgui_stdlib; \ No newline at end of file diff --git a/atlas/core/ui/widgets.cppm b/atlas/core/ui/widgets.cppm index b6459ddb..8318acc8 100644 --- a/atlas/core/ui/widgets.cppm +++ b/atlas/core/ui/widgets.cppm @@ -8,7 +8,7 @@ module; #include #include -export module atlas.core.ui.widgets; +export module atlas.core.ui:widgets; import atlas.core.filesystem.file_dialog; import atlas.core.scene.components; diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 099c82fd..e2a497a4 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -25,9 +25,8 @@ import atlas.drivers.renderer_system; import atlas.core.scene.uuid; import atlas.core.level_streamer; import atlas.core.scene; -import atlas.core.ui.widgets; +import atlas.core.ui; import atlas.physics.engine; -import atlas.core.ui.widgets.imgui_stdlib; import :level_scene; import :icon; diff --git a/editor/utilities.cppm b/editor/utilities.cppm index 90a585de..6fb057d2 100644 --- a/editor/utilities.cppm +++ b/editor/utilities.cppm @@ -7,7 +7,7 @@ module; export module editor:utilities; -import atlas.core.ui.widgets; +import atlas.core.ui; import atlas.core.scene.components; export void From 44f5e3fe24cb17db6fa9408a3d156a0bb0fad1b0 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 00:02:58 -0700 Subject: [PATCH 095/106] refactor: minor fixes in ui.cppm --- atlas/core/ui/ui.cppm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atlas/core/ui/ui.cppm b/atlas/core/ui/ui.cppm index c71aa14a..98680ba2 100644 --- a/atlas/core/ui/ui.cppm +++ b/atlas/core/ui/ui.cppm @@ -4,4 +4,4 @@ export module atlas.core.ui; export import :widgets; -export import :imgui_stdlib; \ No newline at end of file +export import :imgui_stdlib; \ No newline at end of file From cc7d422fda08a97ce34bd23f4ea412452c190b42 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 00:12:27 -0700 Subject: [PATCH 096/106] refactor: scenes to represent imports as module partitions rather then individual partition units --- atlas/core/application.cppm | 2 +- atlas/core/core.cppm | 6 ------ atlas/core/scene/components.cppm | 2 +- atlas/core/scene/game_object.cppm | 4 ++-- atlas/core/scene/level_streamer.cppm | 1 - atlas/core/scene/scene.cppm | 6 +++--- atlas/core/scene/uuid.cppm | 2 +- atlas/core/serialize/serializer.cppm | 1 - atlas/core/serialize/types.cppm | 2 +- atlas/core/ui/widgets.cppm | 2 +- atlas/drivers/jolt_cpp/context.cppm | 2 +- atlas/drivers/physics_context.cppm | 2 +- atlas/drivers/vulkan/render_context.cppm | 1 - atlas/physics/physics_engine.cppm | 2 +- editor/editor_world.cppm | 3 +-- editor/level_scene.cppm | 2 -- editor/level_scene2.cppm | 2 -- editor/utilities.cppm | 2 +- tests/entity_component_system.test.cppm | 1 - tests/scene.test.cppm | 2 -- 20 files changed, 15 insertions(+), 32 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 59b42ada..2809e0ba 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -30,7 +30,7 @@ import atlas.drivers.vulkan; import atlas.core.scene; import atlas.core.scene.world; -import atlas.core.scene.components; +import atlas.core.scene; import atlas.core.math; export namespace atlas { diff --git a/atlas/core/core.cppm b/atlas/core/core.cppm index b47ba83e..fefccbc8 100644 --- a/atlas/core/core.cppm +++ b/atlas/core/core.cppm @@ -1,8 +1,2 @@ export module core; -// export import :common; -// export import atlas.common; -// export import :application; -// export import :logger; - -export namespace atlas {}; \ No newline at end of file diff --git a/atlas/core/scene/components.cppm b/atlas/core/scene/components.cppm index 41d36647..6a525d46 100644 --- a/atlas/core/scene/components.cppm +++ b/atlas/core/scene/components.cppm @@ -5,7 +5,7 @@ module; #include #include -export module atlas.core.scene.components; +export module atlas.core.scene:components; import atlas.core.math; diff --git a/atlas/core/scene/game_object.cppm b/atlas/core/scene/game_object.cppm index 381e3955..664cded5 100644 --- a/atlas/core/scene/game_object.cppm +++ b/atlas/core/scene/game_object.cppm @@ -3,8 +3,8 @@ module; #include #include -export module atlas.core.scene.game_object; -import atlas.core.scene.components; +export module atlas.core.scene:game_object; +import :components; export namespace atlas { /** diff --git a/atlas/core/scene/level_streamer.cppm b/atlas/core/scene/level_streamer.cppm index 75f9f550..9e661f6d 100644 --- a/atlas/core/scene/level_streamer.cppm +++ b/atlas/core/scene/level_streamer.cppm @@ -10,7 +10,6 @@ export module atlas.core.level_streamer; import atlas.core.utilities; import atlas.core.scene; -import atlas.core.scene.uuid; import atlas.core.event; export namespace atlas { diff --git a/atlas/core/scene/scene.cppm b/atlas/core/scene/scene.cppm index 746222f7..81b9747c 100644 --- a/atlas/core/scene/scene.cppm +++ b/atlas/core/scene/scene.cppm @@ -7,9 +7,9 @@ export module atlas.core.scene; import atlas.core.utilities; import atlas.core.event; -import atlas.core.scene.game_object; -import atlas.core.scene.uuid; -import atlas.core.scene.components; +export import :game_object; +export import :uuid; +export import :components; export namespace atlas { /** diff --git a/atlas/core/scene/uuid.cppm b/atlas/core/scene/uuid.cppm index 590c6199..138725cb 100644 --- a/atlas/core/scene/uuid.cppm +++ b/atlas/core/scene/uuid.cppm @@ -2,7 +2,7 @@ module; #include #include -export module atlas.core.scene.uuid; +export module atlas.core.scene:uuid; export namespace atlas { diff --git a/atlas/core/serialize/serializer.cppm b/atlas/core/serialize/serializer.cppm index e7aa8a49..70447fa5 100644 --- a/atlas/core/serialize/serializer.cppm +++ b/atlas/core/serialize/serializer.cppm @@ -13,7 +13,6 @@ export module atlas.core.serialize; import atlas.core.scene; import atlas.core.serialize.types; -import atlas.core.scene.components; import atlas.core.utilities; namespace atlas { diff --git a/atlas/core/serialize/types.cppm b/atlas/core/serialize/types.cppm index 731d730a..c74a0a96 100644 --- a/atlas/core/serialize/types.cppm +++ b/atlas/core/serialize/types.cppm @@ -4,7 +4,7 @@ module; #include export module atlas.core.serialize.types; -import atlas.core.scene.components; +import atlas.core.scene; namespace YAML { /** diff --git a/atlas/core/ui/widgets.cppm b/atlas/core/ui/widgets.cppm index 8318acc8..dcac9168 100644 --- a/atlas/core/ui/widgets.cppm +++ b/atlas/core/ui/widgets.cppm @@ -11,7 +11,7 @@ module; export module atlas.core.ui:widgets; import atlas.core.filesystem.file_dialog; -import atlas.core.scene.components; +import atlas.core.scene; export namespace atlas::ui { using ::ImGui::InputText; diff --git a/atlas/drivers/jolt_cpp/context.cppm b/atlas/drivers/jolt_cpp/context.cppm index 0b3e52c0..3e6aef5a 100644 --- a/atlas/drivers/jolt_cpp/context.cppm +++ b/atlas/drivers/jolt_cpp/context.cppm @@ -39,7 +39,7 @@ export module atlas.drivers.jolt_cpp.context; import atlas.core.utilities; import atlas.core.event; -import atlas.core.scene.components; +import atlas.core.scene; import atlas.drivers.jolt_cpp.broad_phase; import atlas.drivers.jolt_cpp.contact_listener; diff --git a/atlas/drivers/physics_context.cppm b/atlas/drivers/physics_context.cppm index aa65fed9..5fc13c32 100644 --- a/atlas/drivers/physics_context.cppm +++ b/atlas/drivers/physics_context.cppm @@ -6,7 +6,7 @@ module; export module atlas.drivers.physics_context; import atlas.core.utilities; -import atlas.core.scene.components; +import atlas.core.scene; import atlas.core.event; namespace atlas::physics { diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 2fe39b54..c2bd6ebb 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -19,7 +19,6 @@ import atlas.core.scene; import atlas.drivers.importer; import atlas.core.scene; -import atlas.core.scene.components; import atlas.drivers.vulkan.stb_image; import atlas.core.utilities; diff --git a/atlas/physics/physics_engine.cppm b/atlas/physics/physics_engine.cppm index bb86cb0c..b811d631 100644 --- a/atlas/physics/physics_engine.cppm +++ b/atlas/physics/physics_engine.cppm @@ -6,7 +6,7 @@ module; export module atlas.physics.engine; import atlas.core.utilities; -import atlas.core.scene.components; +import atlas.core.scene; import atlas.core.event; import atlas.drivers.physics_context; import atlas.drivers.jolt_cpp.context; diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index e2a497a4..8391e6b5 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -19,12 +19,11 @@ module; export module editor:world; import atlas.core.utilities; +import atlas.core.scene; import atlas.core.scene.world; import atlas.core.event; import atlas.drivers.renderer_system; -import atlas.core.scene.uuid; import atlas.core.level_streamer; -import atlas.core.scene; import atlas.core.ui; import atlas.physics.engine; diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index f13ed5c4..acda4858 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -19,8 +19,6 @@ export module editor:level_scene; import atlas.application; import atlas.core.event; import atlas.core.scene; -import atlas.core.scene.game_object; -import atlas.core.scene.components; import atlas.core.utilities; import atlas.core.math; diff --git a/editor/level_scene2.cppm b/editor/level_scene2.cppm index e7222739..adf811bd 100644 --- a/editor/level_scene2.cppm +++ b/editor/level_scene2.cppm @@ -15,8 +15,6 @@ export module editor:level_scene2; import atlas.application; import atlas.core.event; import atlas.core.scene; -import atlas.core.scene.game_object; -import atlas.core.scene.components; import atlas.core.utilities; import atlas.core.math; diff --git a/editor/utilities.cppm b/editor/utilities.cppm index 6fb057d2..59961e50 100644 --- a/editor/utilities.cppm +++ b/editor/utilities.cppm @@ -8,7 +8,7 @@ module; export module editor:utilities; import atlas.core.ui; -import atlas.core.scene.components; +import atlas.core.scene; export void ui_component_list(flecs::entity& p_selected_entity) { diff --git a/tests/entity_component_system.test.cppm b/tests/entity_component_system.test.cppm index 14a75636..403a5452 100644 --- a/tests/entity_component_system.test.cppm +++ b/tests/entity_component_system.test.cppm @@ -8,7 +8,6 @@ module; export module atlas.tests:entity_component_system; import atlas.core.scene; -import atlas.core.scene.game_object; import atlas.core.math.types; import atlas.core.event; import atlas.drivers.jolt_cpp.types; diff --git a/tests/scene.test.cppm b/tests/scene.test.cppm index 17092db4..fa0b8add 100644 --- a/tests/scene.test.cppm +++ b/tests/scene.test.cppm @@ -3,8 +3,6 @@ module; export module atlas.tests:scene; import atlas.core.scene; -import atlas.core.scene.game_object; -import atlas.core.scene.components; import atlas.core.event; export void From 6211cfa4265d45f5f542eb6195b86288b88a926c Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 00:20:05 -0700 Subject: [PATCH 097/106] refactor: made jolt_cpp implementation imports be represented as module partitions --- atlas/drivers/jolt_cpp/broad_phase.cppm | 2 +- atlas/drivers/jolt_cpp/contact_listener.cppm | 2 +- atlas/drivers/jolt_cpp/context.cppm | 14 ++++++-------- atlas/drivers/jolt_cpp/jolt_cpp.cppm | 6 ++++++ atlas/drivers/jolt_cpp/math.cppm | 2 +- atlas/physics/physics_engine.cppm | 2 +- 6 files changed, 16 insertions(+), 12 deletions(-) create mode 100644 atlas/drivers/jolt_cpp/jolt_cpp.cppm diff --git a/atlas/drivers/jolt_cpp/broad_phase.cppm b/atlas/drivers/jolt_cpp/broad_phase.cppm index 3c036de1..85fa99cb 100644 --- a/atlas/drivers/jolt_cpp/broad_phase.cppm +++ b/atlas/drivers/jolt_cpp/broad_phase.cppm @@ -32,7 +32,7 @@ module; #include #include -export module atlas.drivers.jolt_cpp.broad_phase; +export module atlas.drivers.jolt_cpp:broad_phase; import atlas.core.utilities; diff --git a/atlas/drivers/jolt_cpp/contact_listener.cppm b/atlas/drivers/jolt_cpp/contact_listener.cppm index 2aae06dc..146a36ac 100644 --- a/atlas/drivers/jolt_cpp/contact_listener.cppm +++ b/atlas/drivers/jolt_cpp/contact_listener.cppm @@ -32,7 +32,7 @@ module; #include #include -export module atlas.drivers.jolt_cpp.contact_listener; +export module atlas.drivers.jolt_cpp:contact_listener; import atlas.core.utilities; import atlas.core.event; diff --git a/atlas/drivers/jolt_cpp/context.cppm b/atlas/drivers/jolt_cpp/context.cppm index 3e6aef5a..39c7b268 100644 --- a/atlas/drivers/jolt_cpp/context.cppm +++ b/atlas/drivers/jolt_cpp/context.cppm @@ -35,18 +35,16 @@ module; #include #include -export module atlas.drivers.jolt_cpp.context; +export module atlas.drivers.jolt_cpp:context; + +import :broad_phase; +import :contact_listener; +import :math; import atlas.core.utilities; import atlas.core.event; import atlas.core.scene; - -import atlas.drivers.jolt_cpp.broad_phase; -import atlas.drivers.jolt_cpp.contact_listener; - -import atlas.drivers.jolt_cpp.types; import atlas.drivers.physics_context; -import atlas.drivers.jolt_cpp.types; namespace atlas::physics { @@ -97,7 +95,7 @@ namespace atlas::physics { uint32_t max_contact_constraints = 8192; }; - static void trace_impl(const char* p_in_fmt, ...) { + void trace_impl(const char* p_in_fmt, ...) { va_list list; va_start(list, p_in_fmt); char buffer[1024]; diff --git a/atlas/drivers/jolt_cpp/jolt_cpp.cppm b/atlas/drivers/jolt_cpp/jolt_cpp.cppm new file mode 100644 index 00000000..461de37f --- /dev/null +++ b/atlas/drivers/jolt_cpp/jolt_cpp.cppm @@ -0,0 +1,6 @@ +export module atlas.drivers.jolt_cpp; + +export import :context; +export import :broad_phase; +export import :contact_listener; +export import :math; \ No newline at end of file diff --git a/atlas/drivers/jolt_cpp/math.cppm b/atlas/drivers/jolt_cpp/math.cppm index 828b3a56..82711fc5 100644 --- a/atlas/drivers/jolt_cpp/math.cppm +++ b/atlas/drivers/jolt_cpp/math.cppm @@ -9,7 +9,7 @@ module; #include #define GLM_ENABLE_EXPERIMENTAL #include -export module atlas.drivers.jolt_cpp.types; +export module atlas.drivers.jolt_cpp:math; import atlas.core.math.types; export namespace atlas { diff --git a/atlas/physics/physics_engine.cppm b/atlas/physics/physics_engine.cppm index b811d631..83831810 100644 --- a/atlas/physics/physics_engine.cppm +++ b/atlas/physics/physics_engine.cppm @@ -9,7 +9,7 @@ import atlas.core.utilities; import atlas.core.scene; import atlas.core.event; import atlas.drivers.physics_context; -import atlas.drivers.jolt_cpp.context; +import atlas.drivers.jolt_cpp; namespace atlas::physics { From 051a114126aed67a24b39121f7af456ac8d54d6b Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 00:20:53 -0700 Subject: [PATCH 098/106] refactor: update the project CMakeLists.txt --- CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d3baa7cd..516f7fe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,10 +132,6 @@ target_sources(${PROJECT_NAME} PUBLIC FILE_SET CXX_MODULES TYPE CXX_MODULES FILES - - # core - # atlas/atlas.cppm - atlas/core/api.cppm atlas/core/common.cppm atlas/core/utilities/types.cppm atlas/core/utilities/utilities.cppm @@ -170,6 +166,7 @@ target_sources(${PROJECT_NAME} PUBLIC # editor atlas/core/editor/dockspace.cppm atlas/core/editor/menu_item.cppm + atlas/core/ui/ui.cppm atlas/core/ui/widgets.cppm atlas/core/filesystem/file_dialog.cppm @@ -192,6 +189,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/physics/physics_engine.cppm # jolt_cpp + atlas/drivers/jolt_cpp/jolt_cpp.cppm atlas/drivers/jolt_cpp/math.cppm atlas/drivers/jolt_cpp/broad_phase.cppm atlas/drivers/jolt_cpp/contact_listener.cppm From 39356bc05444a47910bcdf9469a3df63b0a0516b Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 00:36:45 -0700 Subject: [PATCH 099/106] refactor: migrated some module units for math to be imported as module units --- atlas/core/logger.cppm | 2 +- atlas/core/math/math.cppm | 1 + atlas/core/math/types.cppm | 2 +- atlas/drivers/jolt_cpp/math.cppm | 2 +- tests/entity_component_system.test.cppm | 4 ++-- tests/math.test.cppm | 4 ++-- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/atlas/core/logger.cppm b/atlas/core/logger.cppm index 7feed1e3..54b4a1a8 100644 --- a/atlas/core/logger.cppm +++ b/atlas/core/logger.cppm @@ -11,7 +11,7 @@ module; #include export module atlas.core.utilities:logger; -export import :common; +import :common; export namespace atlas { /** diff --git a/atlas/core/math/math.cppm b/atlas/core/math/math.cppm index 580bb924..6d88fa7a 100644 --- a/atlas/core/math/math.cppm +++ b/atlas/core/math/math.cppm @@ -4,6 +4,7 @@ module; #include export module atlas.core.math; +export import :types; export namespace atlas { diff --git a/atlas/core/math/types.cppm b/atlas/core/math/types.cppm index 330b18bc..0c3811b1 100644 --- a/atlas/core/math/types.cppm +++ b/atlas/core/math/types.cppm @@ -3,7 +3,7 @@ module; #include #include -export module atlas.core.math.types; +export module atlas.core.math:types; export namespace atlas { diff --git a/atlas/drivers/jolt_cpp/math.cppm b/atlas/drivers/jolt_cpp/math.cppm index 82711fc5..432d05ec 100644 --- a/atlas/drivers/jolt_cpp/math.cppm +++ b/atlas/drivers/jolt_cpp/math.cppm @@ -10,7 +10,7 @@ module; #define GLM_ENABLE_EXPERIMENTAL #include export module atlas.drivers.jolt_cpp:math; -import atlas.core.math.types; +import atlas.core.math; export namespace atlas { template<> diff --git a/tests/entity_component_system.test.cppm b/tests/entity_component_system.test.cppm index 403a5452..4b62be9b 100644 --- a/tests/entity_component_system.test.cppm +++ b/tests/entity_component_system.test.cppm @@ -8,9 +8,9 @@ module; export module atlas.tests:entity_component_system; import atlas.core.scene; -import atlas.core.math.types; +import atlas.core.math; import atlas.core.event; -import atlas.drivers.jolt_cpp.types; +import atlas.drivers.jolt_cpp; namespace atlas { /** diff --git a/tests/math.test.cppm b/tests/math.test.cppm index 4ec9c3f3..889ee3e4 100644 --- a/tests/math.test.cppm +++ b/tests/math.test.cppm @@ -5,8 +5,8 @@ module; #include export module atlas.tests:math; -import atlas.core.math.types; -import atlas.drivers.jolt_cpp.types; +import atlas.core.math; +import atlas.drivers.jolt_cpp; /** * @name MockTestTransform From ff6c6cebf05404460d2b44b1034c22badadb950f Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 12:00:46 -0700 Subject: [PATCH 100/106] refactor: added core editor module units to be represented as module partitions --- atlas/core/editor/dockspace.cppm | 2 +- atlas/core/editor/editor.cppm | 7 +++++++ atlas/core/editor/menu_item.cppm | 2 +- editor/editor_world.cppm | 3 +-- 4 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 atlas/core/editor/editor.cppm diff --git a/atlas/core/editor/dockspace.cppm b/atlas/core/editor/dockspace.cppm index 4dd6f438..2a37d59c 100644 --- a/atlas/core/editor/dockspace.cppm +++ b/atlas/core/editor/dockspace.cppm @@ -6,7 +6,7 @@ module; #include -export module atlas.core.editor.dockspace; +export module atlas.core.editor:dockspace; export namespace atlas::ui { /** diff --git a/atlas/core/editor/editor.cppm b/atlas/core/editor/editor.cppm new file mode 100644 index 00000000..f147ad61 --- /dev/null +++ b/atlas/core/editor/editor.cppm @@ -0,0 +1,7 @@ +module; + +export module atlas.core.editor; + + +export import :menu_item; +export import :dockspace; \ No newline at end of file diff --git a/atlas/core/editor/menu_item.cppm b/atlas/core/editor/menu_item.cppm index 9ff2209a..2f0035d3 100644 --- a/atlas/core/editor/menu_item.cppm +++ b/atlas/core/editor/menu_item.cppm @@ -6,7 +6,7 @@ module; #include #include -export module atlas.core.editor.menu_item; +export module atlas.core.editor:menu_item; export namespace atlas::ui { struct block { diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 8391e6b5..8a98416a 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -33,8 +33,7 @@ import :utilities; import :content_browser; // import :level_scene2; -import atlas.core.editor.dockspace; -import atlas.core.editor.menu_item; +import atlas.core.editor; import atlas.core.serialize; import atlas.physics.engine; import vk; From 4b067dc993b918ae56656b01b2c57cd78abaef3d Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 12:23:33 -0700 Subject: [PATCH 101/106] refactor: removed some unused vulkan module imports --- atlas/drivers/vulkan/render_context.cppm | 12 ++++++------ atlas/drivers/vulkan/stb_image.cppm | 2 +- atlas/drivers/vulkan/vulkan.cppm | 3 ++- editor/application.cpp | 2 +- editor/content_browser_panel.cppm | 2 -- editor/editor_world.cppm | 1 - editor/icon.cppm | 2 +- editor/level_scene.cppm | 2 -- 8 files changed, 11 insertions(+), 15 deletions(-) diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index c2bd6ebb..44f5393e 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -15,16 +15,16 @@ module; #include export module atlas.drivers.vulkan:render_context; -import atlas.core.scene; - -import atlas.drivers.importer; -import atlas.core.scene; -import atlas.drivers.vulkan.stb_image; -import atlas.core.utilities; +import :stb_image; import :graphics_context; import :environment_map; import :gpu_uniforms; + +import atlas.core.scene; +import atlas.drivers.importer; +import atlas.core.utilities; + import vk; export namespace atlas { diff --git a/atlas/drivers/vulkan/stb_image.cppm b/atlas/drivers/vulkan/stb_image.cppm index 6d8e7478..25c4e2b8 100644 --- a/atlas/drivers/vulkan/stb_image.cppm +++ b/atlas/drivers/vulkan/stb_image.cppm @@ -11,7 +11,7 @@ module; #include #endif -export module atlas.drivers.vulkan.stb_image; +export module atlas.drivers.vulkan:stb_image; import vk; diff --git a/atlas/drivers/vulkan/vulkan.cppm b/atlas/drivers/vulkan/vulkan.cppm index e31c2a7d..75c1b376 100644 --- a/atlas/drivers/vulkan/vulkan.cppm +++ b/atlas/drivers/vulkan/vulkan.cppm @@ -6,4 +6,5 @@ export module atlas.drivers.vulkan; export import :window; export import :graphics_context; export import :render_context; -export import :imgui_context; \ No newline at end of file +export import :imgui_context; +export import :stb_image; \ No newline at end of file diff --git a/editor/application.cpp b/editor/application.cpp index f3640ab2..f01c400d 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -5,9 +5,9 @@ import atlas.application; import atlas.core.utilities; import atlas.core.level_streamer; +import atlas.drivers.vulkan; import atlas.core.event; import editor; -import atlas.drivers.vulkan; class editor_application : public atlas::application { public: diff --git a/editor/content_browser_panel.cppm b/editor/content_browser_panel.cppm index 1bb4f9d3..7459d07b 100644 --- a/editor/content_browser_panel.cppm +++ b/editor/content_browser_panel.cppm @@ -10,8 +10,6 @@ module; export module editor:content_browser; import atlas.core.utilities; -import atlas.drivers.vulkan; -import atlas.drivers.vulkan.stb_image; import vk; import :icon; diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 8a98416a..6b1e6ddb 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -22,7 +22,6 @@ import atlas.core.utilities; import atlas.core.scene; import atlas.core.scene.world; import atlas.core.event; -import atlas.drivers.renderer_system; import atlas.core.level_streamer; import atlas.core.ui; import atlas.physics.engine; diff --git a/editor/icon.cppm b/editor/icon.cppm index 47e54829..be20bc53 100644 --- a/editor/icon.cppm +++ b/editor/icon.cppm @@ -11,7 +11,7 @@ export module editor:icon; import atlas.core.utilities; import vk; -import atlas.drivers.vulkan.stb_image; +import atlas.drivers.vulkan; export namespace ui::experimental { /** diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index acda4858..072cc2b2 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -22,8 +22,6 @@ import atlas.core.scene; import atlas.core.utilities; import atlas.core.math; -import atlas.drivers.vulkan; - export class level_scene final : public atlas::scene { public: level_scene(const std::string& p_name, atlas::event::bus& p_bus) From 922b15299ec458f1a3dbd28499284e0038165ea3 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 14:36:26 -0700 Subject: [PATCH 102/106] refactor: added extensive documentation comments and fixed some redundant parameter specification types; include some additional module partition organization --- CMakeLists.txt | 6 +- atlas/core/application.cppm | 13 +--- atlas/core/entry_point/main.cpp | 2 - atlas/core/utilities/types.cppm | 24 ------- atlas/core/utilities/utilities.cppm | 15 ++++- atlas/drivers/vulkan/environment_map.cppm | 19 +++++- atlas/drivers/vulkan/graphics_context.cppm | 25 ++------ atlas/drivers/vulkan/render_context.cppm | 6 +- atlas/drivers/vulkan/render_system.cppm | 15 ----- atlas/drivers/vulkan/stb_image.cppm | 19 +++--- atlas/drivers/vulkan/uniforms.cppm | 75 ---------------------- editor/application.cpp | 8 ++- editor/editor_world.cppm | 2 - 13 files changed, 60 insertions(+), 169 deletions(-) delete mode 100644 atlas/core/utilities/types.cppm delete mode 100644 atlas/drivers/vulkan/render_system.cppm delete mode 100644 atlas/drivers/vulkan/uniforms.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index 516f7fe4..0c5845f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -133,8 +133,6 @@ target_sources(${PROJECT_NAME} PUBLIC TYPE CXX_MODULES FILES atlas/core/common.cppm - atlas/core/utilities/types.cppm - atlas/core/utilities/utilities.cppm atlas/core/core.cppm atlas/core/logger.cppm atlas/core/application.cppm @@ -151,6 +149,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/core/scene/level_streamer.cppm atlas/core/scene/uuid.cppm + atlas/core/utilities/utilities.cppm atlas/core/utilities/state.cppm atlas/core/utilities/poll_state.cppm @@ -164,6 +163,7 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/core/event/types.cppm # editor + atlas/core/editor/editor.cppm atlas/core/editor/dockspace.cppm atlas/core/editor/menu_item.cppm atlas/core/ui/ui.cppm @@ -207,8 +207,6 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/vulkan/hash.cppm atlas/drivers/vulkan/shader_resource_group.cppm - atlas/drivers/vulkan/render_system.cppm - atlas/drivers/vulkan/uniforms.cppm # 3D Model Importers diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index 2809e0ba..ce274def 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -39,9 +39,7 @@ export namespace atlas { * @brief application properties settings for the window */ struct application_settings { - std::string name = "Undefined"; - uint32_t width = 0; - uint32_t height = 0; + window_params extent{}; glm::vec4 background_color = { 1.f, 0.5f, 0.5f, 1.f }; }; @@ -57,16 +55,11 @@ export namespace atlas { m_physical = p_context->physical_device(); m_device = p_context->logical_device(); - // Constructing the application - m_window_params = { - .width = p_params.width, - .height = p_params.height, - .name = p_params.name, - }; + m_window_params = p_params.extent; // m_window = std::allocate_shared(, // m_context->instance_handle(), params); - m_window = std::make_shared(p_context, m_window_params); + m_window = std::make_shared(p_context, p_params.extent); m_aspect_ratio = static_cast(m_window_params.width) / static_cast(m_window_params.height); event::set_window_size(m_window->glfw_window()); diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index b233246f..870f63ce 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -174,7 +174,5 @@ main() { logical_device->wait(); app->post_destroy(); - - context->post_cleanup(); return 0; } \ No newline at end of file diff --git a/atlas/core/utilities/types.cppm b/atlas/core/utilities/types.cppm deleted file mode 100644 index d3a4e3e6..00000000 --- a/atlas/core/utilities/types.cppm +++ /dev/null @@ -1,24 +0,0 @@ -module; - -#include -#include -#include - -export module atlas.core.utilities:types; - -import vk; - -export namespace atlas { - struct window_params { - uint32_t width; - uint32_t height; - std::string name = ""; - vk::surface_params surface_properties{}; - }; - - // TODO: Move this into atlas.drivers.vulkan.utilities - struct surface_properties { - VkSurfaceCapabilitiesKHR surface_capabilities; - VkSurfaceFormatKHR surface_format; - }; -}; \ No newline at end of file diff --git a/atlas/core/utilities/utilities.cppm b/atlas/core/utilities/utilities.cppm index 0779c2dc..60eeb298 100644 --- a/atlas/core/utilities/utilities.cppm +++ b/atlas/core/utilities/utilities.cppm @@ -1,7 +1,20 @@ +module; + +#include +#include + export module atlas.core.utilities; export import :logger; export import :common; -export import :types; export import :poll_state; export import :state; + + +namespace atlas { + export struct window_params { + uint32_t width; + uint32_t height; + std::string name = ""; + }; +}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/environment_map.cppm b/atlas/drivers/vulkan/environment_map.cppm index 8fb88b97..69fa8133 100644 --- a/atlas/drivers/vulkan/environment_map.cppm +++ b/atlas/drivers/vulkan/environment_map.cppm @@ -41,6 +41,11 @@ struct environment_push_constant { uint64_t scene_environment_address=0; }; +/** + * + * @brief Vulkan-specific implementation for loading GPU resources associated to loading environent maps. + * +*/ export class environment_map { public: environment_map() = default; @@ -64,6 +69,9 @@ public: construct(p_color, p_extent); } + /** + * @brief loads in a new HDRI environment map + */ void construct(const std::string& p_filename) { bool res = create_hdr(p_filename); @@ -77,6 +85,9 @@ public: create_pipelines(); } + /** + * @brief loads in raw pixels and texture dimensions to receive in raw pixels data if no HDRI is provided. + */ void construct(std::span p_color, const vk::image_extent& p_extent) { bool res = create_hdr(p_color, p_extent); @@ -90,6 +101,9 @@ public: create_pipelines(); } + /** + * @brief performs the loading operation to read in the pixel float data of the actual HDRI metadata. + */ bool create_hdr(const std::string& p_filename) { stbi_set_flip_vertically_on_load(true); int w, h, channels; @@ -117,7 +131,7 @@ public: vk::buffer staging_buffer = vk::buffer(*m_device, image_size, staging_params); - // Creating image handle to storing the HDR + // Creating GPU image resource vk::image_params skybox_params = { .extent = { .width = static_cast(width), .height = static_cast(height), }, .format = texture_format, @@ -132,7 +146,7 @@ public: }; m_skybox_image = vk::sample_image(*m_device, skybox_params); - // Transferring data from the CPU + // Transferring CPU data to GPU-visible data std::span pixels_data( reinterpret_cast(pixels), image_size); staging_buffer.transfer(pixels_data); @@ -150,6 +164,7 @@ public: upload_cmd.begin(vk::command_usage::one_time_submit); + // Performing image layout transitions to ensure we do not lose any data transferring over to the GPU. // Begin Memory Barrier: Undefined to TRANSFER_DST m_skybox_image.memory_barrier(upload_cmd, texture_format, diff --git a/atlas/drivers/vulkan/graphics_context.cppm b/atlas/drivers/vulkan/graphics_context.cppm index 45598eb5..666d593b 100644 --- a/atlas/drivers/vulkan/graphics_context.cppm +++ b/atlas/drivers/vulkan/graphics_context.cppm @@ -25,6 +25,9 @@ import vk; export namespace atlas { + /** + * @brief graphics context to manage core resources that is used as the primary resource access to the core Vulkan handles. + */ class graphics_context { public: graphics_context() = default; @@ -33,43 +36,29 @@ export namespace atlas { std::shared_ptr p_device) : m_api_instance(p_api_instance) , m_physical(&p_physical) - , m_device(p_device) { + , m_device(/*NOLINT*/p_device) { // Constructing the graphics context - - s_instance = this; } ~graphics_context() = default; - void post_cleanup() { - for (const auto& callback : m_submit_resource_free) { - callback(); - } - } - + //! @return vk::instance [[nodiscard]] vk::instance instance_handle() const { return m_api_instance; } + //! @return vk::physical_device [[nodiscard]] vk::physical_device physical_device() const { return *m_physical; } + //! @return shared_ptr std::shared_ptr logical_device() { return m_device; } - static void submit_resource_free( - const std::function& p_callback) { - s_instance->m_submit_resource_free.emplace_back(p_callback); - } - private: vk::instance m_api_instance; vk::physical_device* m_physical = nullptr; std::shared_ptr m_device = nullptr; std::deque> m_submit_resource_free{}; - static graphics_context* s_instance; }; - - graphics_context* graphics_context::s_instance = nullptr; - }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 44f5393e..6a98465b 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -30,9 +30,11 @@ import vk; export namespace atlas { /** - * @brief Core render context to schedule images and barriers for coordinating rendering operations * - * Manages multiple render contexts + * @brief Context that translates the ECS rendering-specific components to GPU-visible resources + * + * Manages the dispatching of task workloads to performing data transfers and draw calls. + * */ class render_context { public: diff --git a/atlas/drivers/vulkan/render_system.cppm b/atlas/drivers/vulkan/render_system.cppm deleted file mode 100644 index f1e8d2cb..00000000 --- a/atlas/drivers/vulkan/render_system.cppm +++ /dev/null @@ -1,15 +0,0 @@ -module; - -#include -#include -#include -#include -#include -#include - -#include - -export module atlas.drivers.vulkan.render_system; - -export namespace atlas::vulkan { -}; \ No newline at end of file diff --git a/atlas/drivers/vulkan/stb_image.cppm b/atlas/drivers/vulkan/stb_image.cppm index 25c4e2b8..dcf01dfd 100644 --- a/atlas/drivers/vulkan/stb_image.cppm +++ b/atlas/drivers/vulkan/stb_image.cppm @@ -16,11 +16,18 @@ export module atlas.drivers.vulkan:stb_image; import vk; export namespace atlas { + + /** + * @brief Implementing image loading that utilizes stb_image to decode disk-based images into uncompressed streams of bytes. + * + * Provides size extents of uncompressed of the total image size. + * + */ class stb_image : public vk::image { public: stb_image() = default; - stb_image(std::string_view p_path, vk::texture_params p_params) { + stb_image(std::string_view p_path, const vk::texture_params& p_params) { image_load(p_path, p_params); } @@ -57,16 +64,6 @@ export namespace atlas { // Retrieving total image size to the count of the image layers uint32_t size = size_bytes * p_params.layer_count; - // vk::image_params image_options = { - // .extent = m_extent, - // .format = texture_format, - // .memory_mask = p_params.memory_mask, - // .usage = - // vk::image_usage::transfer_dst_bit | - // vk::image_usage::sampled_bit, .mip_levels = - // p_params.mip_levels, .layer_count = p_params.layer_count, - // }; - m_bytes.reserve(size); std::span bytes_view = std::span(image_pixel_data, size); diff --git a/atlas/drivers/vulkan/uniforms.cppm b/atlas/drivers/vulkan/uniforms.cppm deleted file mode 100644 index 79c786ee..00000000 --- a/atlas/drivers/vulkan/uniforms.cppm +++ /dev/null @@ -1,75 +0,0 @@ -module; - -#include -#include - -export module atlas.drivers.vulkan.uniforms; - -import vk; - -export namespace atlas::vulkan { - struct vertex_input { - glm::vec3 position; - glm::vec3 color; - glm::vec3 normals; - glm::vec2 uv; - - bool operator==(const vertex_input& other) const { - return position == other.position and color == other.color and - uv == other.uv and normals == other.normals; - } - }; - - //! @brief Going to remove this - //! @brief This is being used by descriptor sets and vk_renderer - //! TODO: Modify vk_descriptor_set and vk_renderer and add uniforms.hpp - //! inside renderer/ (dir) for used across vk_renderer and the renderer - struct camera_ubo { - glm::mat4 projection{ 1.f }; - glm::mat4 view{ 1.f }; - }; - - //! @brief Just for testing purposes for sending this struct over to the - //! shader - struct global_ubo { - glm::mat4 mvp = { 1.f }; - }; - - /** - * @brief material is going to define properties about how a scene object - * itself gets rendered - * - */ - struct geometry_uniform { - glm::mat4 model{ 1.f }; - glm::vec4 color{ 1.f }; - }; - - /** - * @brief Represents a vulkan specific mateiral to pass in two textures and - * offset for handling shininess - */ - struct material_uniform { - float shininess = 1.f; - vk::texture diffuse; - vk::texture specular; - }; - - struct point_light_ubo { - glm::vec4 position; // this is provided by the transform - glm::vec4 color = { 1.f, 1.f, 1.f, 1.f }; - float attenuation = 1.f; - float constant = 1.f; - float linear = 1.f; - float quadratic = 1.f; - - glm::vec4 ambient = glm::vec4(1.f); - glm::vec4 diffuse = glm::vec4(1.f); - glm::vec4 specular = glm::vec4(1.f); - }; - - struct light_scene_ubo { - alignas(16) uint32_t num_lights; - alignas(16) std::array light_sources; - }; -}; \ No newline at end of file diff --git a/editor/application.cpp b/editor/application.cpp index f01c400d..1644c9aa 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -36,9 +36,11 @@ class editor_application : public atlas::application { atlas::ref initialize_application(/*NOLINT*/std::shared_ptr p_context, atlas::event::bus& p_bus) { atlas::application_settings settings = { - .name = "Editor", - .width = 1510, - .height = 877, + .extent = { + .width = 1510, + .height = 877, + .name = "Editor", + }, .background_color = { 0.f, 0.f, 0.f, 0.f }, }; return create_ref(p_context, settings, p_bus); diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 6b1e6ddb..2d757caa 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -1,7 +1,5 @@ module; -#include -#include #include #include From e1b19522dfe29b70721a74dc9f0dc7fe98e74443 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 15:16:46 -0700 Subject: [PATCH 103/106] refactor: removed vulkan::shader_resource_group --- CMakeLists.txt | 3 +- .../drivers/vulkan/shader_resource_group.cppm | 444 ------------------ 2 files changed, 1 insertion(+), 446 deletions(-) delete mode 100644 atlas/drivers/vulkan/shader_resource_group.cppm diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c5845f4..ad7ae4be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,7 +180,6 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/renderer_system.cppm # imgui/UI - atlas/drivers/vulkan/imgui_context.cppm atlas/core/ui/imgui_stdlib.cppm # physics @@ -200,13 +199,13 @@ target_sources(${PROJECT_NAME} PUBLIC atlas/drivers/vulkan/graphics_context.cppm atlas/drivers/vulkan/window.cppm atlas/drivers/vulkan/render_context.cppm + atlas/drivers/vulkan/imgui_context.cppm atlas/drivers/vulkan/utilities.cppm atlas/drivers/vulkan/environment_map.cppm atlas/drivers/vulkan/stb_image.cppm atlas/drivers/vulkan/gpu_uniforms.cppm atlas/drivers/vulkan/hash.cppm - atlas/drivers/vulkan/shader_resource_group.cppm # 3D Model Importers diff --git a/atlas/drivers/vulkan/shader_resource_group.cppm b/atlas/drivers/vulkan/shader_resource_group.cppm deleted file mode 100644 index 4ce45da1..00000000 --- a/atlas/drivers/vulkan/shader_resource_group.cppm +++ /dev/null @@ -1,444 +0,0 @@ -module; - -#include -#include -#include -#include -#include - -export module atlas.drivers.vulkan.shader_resource_group; - -import atlas.core.utilities; -import vk; - -namespace atlas::vulkan { - // Reading the raw .spv binaries - static std::vector read_raw_spirv(const std::string& p_file) { - std::vector out_buffer; - std::ifstream ins(p_file, std::ios::ate | std::ios::binary); - - if (!ins) { - throw std::runtime_error("Cannot load in .spv files!!"); - } - - uint32_t file_size = (uint32_t)ins.tellg(); - out_buffer.resize(file_size); - ins.seekg(0); - ins.read(out_buffer.data(), file_size); - return out_buffer; - } - - //! @brief Ensure file reads are valid before reading raw .spv binaries - static std::vector compile_binary_shader_source( - const ::vk::shader_source& p_shader_source) { - - if (!std::filesystem::is_regular_file(p_shader_source.filename)) { - throw std::runtime_error("Cannot load .spv file"); - } - - return read_raw_spirv(p_shader_source.filename); - } - -#if ENABLE_SHADERC - static std::string read_shader_source_code(const std::string& p_filename) { - std::ifstream ins(p_filename, std::ios::ate | std::ios::binary); - - if (!ins.is_open()) { - console_log_warn("Could not open filename = {}", p_filename); - return { 'a' }; - } - - size_t file_size = (size_t)ins.tellg(); - std::string output; - output.resize(file_size); - ins.seekg(0); - ins.read(output.data(), static_cast(file_size)); - - return output; - } -#endif - - /** - * compiles source code from the shader directly without needing manual - * recompilation - * - * shaderc requires these parameters to compile - * text_source_code: the std::string version of the entire source code to - * compile type: shader stage this shader corresponds to filename: input - * filename text entry_point: the entry point to this shader options: - * compiler-specific options to enable when compiling the shader sources - */ -#if ENABLE_SHADERC - static std::vector compile_source_from_file( - const ::vk::shader_source& p_shader_source) { - shaderc::CompileOptions options; - options.SetTargetEnvironment(shaderc_target_env_vulkan, - shaderc_env_version_vulkan_1_3); - options.SetWarningsAsErrors(); - - shaderc_shader_kind type; - - switch (p_shader_source.stage) { - case ::vk::shader_stage::vertex: - type = shaderc_glsl_vertex_shader; - break; - case ::vk::shader_stage::fragment: - type = shaderc_glsl_fragment_shader; - break; - default: - throw std::runtime_error("shader_stage unspecified!~!!"); - } - - shaderc::Compiler compiler; - std::string text_source_code = - read_shader_source_code(p_shader_source.filename); - - // Prints out the text of the shader source code - // console_log_warn("Source Text Code!!!"); - // console_log_info("{}", text_source_code); - shaderc::CompilationResult result = - compiler.CompileGlslToSpv(text_source_code, - type, - p_shader_source.filename.c_str(), - "main", - options); - - std::vector blob; - - if (result.GetCompilationStatus() != - shaderc_compilation_status_success) { - throw std::runtime_error( - std::format("Shader Compilation Error! Failed with reason {}\n{}", - p_shader_source.filename, - result.GetErrorMessage()) - .c_str()); - } - - for (auto blob_chunk : result) { - blob.push_back(blob_chunk); - } - - return blob; - } -#endif - /** - * @brief resource group for loading shader sources that give you back - * VkShaderModule handles - * - * Responsibility is to load stages of shader sources whether that be - * through precompiler .spv files or through shaderc runtime shader - * compilation - * - * Responsibility is loading and streaming the amount of bytes from the - * compiled shader sources into the vulkan shader module handles - * - * resource groups up the creation and management of vulkan shader modules. - */ - export class shader_resource_group { - public: - shader_resource_group() = default; - /** - * @brief constructs a new shader_resource_group - * - * @param p_device is the logical device required to creating the vulkan - * shader module - * @param p_info has the properties such as specified shader sources to - * load/compile - */ - shader_resource_group(const VkDevice& p_device, - const ::vk::shader_resource_info& p_info) - : m_device(p_device) { - - // We go through all of the specified shader source and their - // specific stage Compile them through shader compiler or if - // provided a .spv, then we compile and read in the stream of bytes - // directly - for (size_t i = 0; i < p_info.sources.size(); i++) { - const vk::shader_source shader_src = p_info.sources[i]; - std::filesystem::path filepath = - std::filesystem::path(shader_src.filename); -#ifndef ENABLE_SHADERC - if (filepath.extension().string() == ".spv") { - std::vector blob = - compile_binary_shader_source(shader_src); - - if (blob.empty()) { - m_resource_valid = false; - throw std::runtime_error( - "Cannot load in vector " - "blob of compiled down data!!!"); - } - - create_module(blob, shader_src); - } -#endif - -#ifdef ENABLE_SHADERC - if (filepath.extension().string() != ".spv") { - std::string text_source_code = - read_shader_source_code(filepath.string()); - std::vector blob = - compile_source_from_file(shader_src); - create_module(blob, shader_src); - } -#endif - } - } - - ~shader_resource_group() = default; - - /** - * @return true if resources are valid, otherwise return false - */ - [[nodiscard]] bool valid() const { return m_resource_valid; } - - /** - * @brief sets the vertex attributes with the shader modules that gets - * used by ::vk::pipeline (graphics pipeline) - * - * @param p_attributes is the high-level specifications for setting up - * vertex attributes that correspond with these shaders - */ - void vertex_attributes( - std::span p_attributes) { - /* - -- These comments are a reminder to myself -- - - this function simplifies the need to separately define vertex - attributes and the vertex binding attributes as shown below: - - - vertex attributes specify the types of data within the vertex - - - vertex binding attribute specifies the rate of reading that - data layout specified by the vertex attributes - - - Interpret the following vertex attributes below with this - shader code with `layout(location = n)` specified where by default - these are set to binding zero by the shader - - layout(location = 0) in vec3 inPosition; - layout(location = 1) in vec3 inColor; - layout(location = 2) in vec3 inNormals; - layout(location = 3) in vec2 inTexCoords; - - m_shader_group.set_vertex_attributes(VkVertexInputAttributeDescription{ - { .location = 0, .binding = 0, .format = - VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, - position), - }, { .location = 1, .binding = 0, .format = - VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, color), - }, { .location = 2, .binding = 0, .format = - VK_FORMAT_R32G32B32_SFLOAT, .offset = offsetof(vk::vertex, normals), - }, { .location = 3, .binding = 0, .format = VK_FORMAT_R32G32_SFLOAT, - .offset = offsetof(vk::vertex, uv), }, - }); - - m_shader_group.set_vertex_bind_attributes(VkVertexInputBindingDescription{ - {.binding = 0, .stride = sizeof(vk::vertex), .inputRate = - VK_VERTEX_INPUT_RATE_VERTEX,}, - }); - - Which gets handled in specifying the following below - */ - - m_vertex_binding_attributes.resize(p_attributes.size()); - - for (size_t i = 0; i < m_vertex_binding_attributes.size(); i++) { - // setting up vertex binding - const ::vk::vertex_attribute attribute = p_attributes[i]; - m_vertex_attributes.resize(attribute.entries.size()); - m_vertex_binding_attributes[i] = { - .binding = attribute.binding, - .stride = attribute.stride, - .inputRate = - static_cast(attribute.input_rate), - }; - - // then setting up the vertex attributes for the vertex data - // layouts - for (size_t j = 0; j < attribute.entries.size(); j++) { - const ::vk::vertex_attribute_entry entry = - attribute.entries[j]; - m_vertex_attributes[j] = { .location = entry.location, - .binding = attribute.binding, - .format = static_cast( - entry.format), - .offset = entry.stride }; - } - } - } - - /** - * @brief this gives you back the shader module handles along with each - * of their stages they have been compiled with - * - * Returns the vector to retain the shader modules that are needed by - * the graphics pipeline. - * - * It is required by vulkan specs the graphics pipeline to contain valid - * shader modules of the compiled shaders - * - * @return vector<::vk::shader_handle> - */ - [[nodiscard]] std::vector<::vk::shader_handle> handles() const { - return map_to_vector(); - } - - /** - * @return span - */ - [[nodiscard]] std::span - vertex_attributes() const { - return m_vertex_attributes; - } - - /** - * @return span - */ - [[nodiscard]] std::span - vertex_bind_attributes() const { - return m_vertex_binding_attributes; - } - - /** - * @brief explicit cleanup to the VkShaderModule handles created with - * this particular resource group - */ - void destroy() { - for (auto& [filename, shader_handle] : m_modules) { - if (shader_handle.module != nullptr) { - vkDestroyShaderModule( - m_device, shader_handle.module, nullptr); - } - } - } - - /** - * @brief ideally used for requesting for reload - * - * Planning to use this for invalidation when for runtime shader - * hot-reloading - * - * @note this is not used at the moment as shader runtime hot reloading - * is currently not supported. - */ - [[nodiscard]] bool reload_requested() const { - return m_reload_requested; - } - - private: - /** - * converts unordered_map to - * vector - */ - [[nodiscard]] std::vector<::vk::shader_handle> map_to_vector() const { - // Using C++'s std::views to extract all of the values in - // unordered_map to a - // vector that gets passed to graphics pipeline TEMP: - // Removing this. Will add this back in later. return (m_modules | - // std::views::values | - // std::ranges::to()); - std::vector<::vk::shader_handle> result; - - result.reserve(m_modules.size()); - - for (auto const& [name, handle] : m_modules) { - result.push_back(handle); - } - - return result; - } - - void create_module(std::span p_blob, - const ::vk::shader_source& p_source) { - VkShaderModuleCreateInfo shader_module_ci = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .codeSize = p_blob.size(), - .pCode = reinterpret_cast(p_blob.data()) - }; - - std::filesystem::path filepath(p_source.filename); - std::string filename = filepath.filename().string(); - - // Setting m_shader_module_handlers[i]'s stage and the - // VkShaderModule handle altogether construct this beforehand and - // then we are going set that shader module - m_modules.emplace(filename, ::vk::shader_handle{}); - ::vk::vk_check(vkCreateShaderModule(m_device, - &shader_module_ci, - nullptr, - &m_modules[filename].module), - "vkCreateShaderModule"); - m_modules[filename].stage = p_source.stage; - } - - void create_module(std::span p_blob, - const ::vk::shader_source& p_source) { - VkShaderModuleCreateInfo shader_module_ci = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .codeSize = p_blob.size_bytes(), - .pCode = p_blob.data() - }; - - // console_log_info("map key = {}", p_source.filename); - std::filesystem::path filepath(p_source.filename); - - std::string filename = filepath.filename().string(); - - console_log_info("Key = {}", filename); - - // Setting m_shader_module_handlers[i]'s stage and the - // VkShaderModule handle altogether construct this beforehand and - // then we are going set that shader module - m_modules.emplace(filename, ::vk::shader_handle{}); - ::vk::vk_check(vkCreateShaderModule(m_device, - &shader_module_ci, - nullptr, - &m_modules[filename].module), - "vkCreateShaderModule"); - m_modules[filename].stage = p_source.stage; - } - - /* - // TODO: Re-add this when shaderc works again. - void reload_shader(const ::vk::shader_source& p_source) { - console_log_info("p_source.filename = {}", p_source.filename); - if (m_modules[p_source.filename].module != nullptr) { - vkDestroyShaderModule( - m_device, m_modules[p_source.filename].module, nullptr); - } - - auto& handle = m_modules[p_source.filename]; - - std::filesystem::path filepath(p_source.filename); - std::string text_source_code = - read_shader_source_code(filepath.string()); - std::vector blob = compile_source_from_file(p_source); - std::span view_blob(blob.data(), blob.size()); - // create_module(blob, p_source); - VkShaderModuleCreateInfo shader_module_ci = { - .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, - .pNext = nullptr, - .codeSize = view_blob.size_bytes(), - .pCode = view_blob.data() - }; - - ::vk::vk_check(vkCreateShaderModule( - m_device, &shader_module_ci, nullptr, - &handle.module), "vkCreateShaderModule"); - } - */ - - private: - VkDevice m_device = nullptr; - std::vector m_vertex_attributes; - std::vector - m_vertex_binding_attributes; - bool m_resource_valid = false; - // shader module handles - std::unordered_map m_modules; - // ref m_watcher; - bool m_reload_requested = false; - }; -}; \ No newline at end of file From 15e85335f84bdad32def63647c1c73499cbf5ac4 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 16:26:33 -0700 Subject: [PATCH 104/106] fixed code formatting --- atlas/core/application.cppm | 53 +-- atlas/core/core.cppm | 1 - atlas/core/entry_point/main.cpp | 6 +- atlas/core/event/event.cppm | 12 +- atlas/core/scene/level_streamer.cppm | 8 +- atlas/core/serialize/serializer.cppm | 18 +- atlas/core/serialize/types.cppm | 3 +- atlas/core/ui/ui.cppm | 3 +- atlas/core/utilities/poll_state.cppm | 3 +- atlas/core/utilities/state.cppm | 1 - atlas/core/utilities/utilities.cppm | 1 - atlas/drivers/importer/obj_loader.cppm | 35 +- atlas/drivers/vulkan/environment_map.cppm | 159 +++++---- atlas/drivers/vulkan/gpu_uniforms.cppm | 54 +-- atlas/drivers/vulkan/graphics_context.cppm | 7 +- atlas/drivers/vulkan/imgui_context.cppm | 14 +- atlas/drivers/vulkan/render_context.cppm | 362 ++++++++++++--------- atlas/drivers/vulkan/stb_image.cppm | 9 +- atlas/drivers/vulkan/vulkan.cppm | 1 - atlas/drivers/vulkan/window.cppm | 35 +- atlas/renderer/renderer.cppm | 3 +- editor/application.cpp | 16 +- editor/content_browser_panel.cppm | 28 +- editor/editor.cppm | 1 - editor/editor_world.cppm | 6 +- editor/level_scene.cppm | 31 +- editor/level_scene2.cppm | 19 +- editor/utilities.cppm | 1 - 28 files changed, 493 insertions(+), 397 deletions(-) diff --git a/atlas/core/application.cppm b/atlas/core/application.cppm index ce274def..1f3cf5dc 100644 --- a/atlas/core/application.cppm +++ b/atlas/core/application.cppm @@ -56,12 +56,13 @@ export namespace atlas { m_device = p_context->logical_device(); m_window_params = p_params.extent; - + // m_window = std::allocate_shared(, // m_context->instance_handle(), params); m_window = std::make_shared(p_context, p_params.extent); - m_aspect_ratio = static_cast(m_window_params.width) / static_cast(m_window_params.height); + m_aspect_ratio = static_cast(m_window_params.width) / + static_cast(m_window_params.height); event::set_window_size(m_window->glfw_window()); m_bus->create_listener(); @@ -139,15 +140,16 @@ export namespace atlas { m_render_context = render_context(m_context, m_color_format, m_depth_format); - m_imgui_context = std::make_shared(p_context, - m_window->glfw_window(), - m_window->swapchain_handle(), - m_window->request_images().size(), - m_window->present_queue(), - // VK_FORMAT_B8G8R8A8_UNORM, - m_color_format, - m_depth_format, - m_window_params); + m_imgui_context = + std::make_shared(p_context, + m_window->glfw_window(), + m_window->swapchain_handle(), + m_window->request_images().size(), + m_window->present_queue(), + // VK_FORMAT_B8G8R8A8_UNORM, + m_color_format, + m_depth_format, + m_window_params); std::println("images.size() = {}", images.size()); m_window->center_window(); @@ -173,8 +175,8 @@ export namespace atlas { transform, perspective_camera>() .each([this](flecs::pair p_pair, - transform& p_transform, - perspective_camera& p_camera) { + transform& p_transform, + perspective_camera& p_camera) { if (!p_camera.is_active) { return; } @@ -256,7 +258,8 @@ export namespace atlas { } const transform* t = p_entity.get(); - m_render_context.set_camera_pos(glm::vec4(t->position, 1.f)); + m_render_context.set_camera_pos( + glm::vec4(t->position, 1.f)); m_projection = p_pair->projection; m_view = p_pair->view; }); @@ -267,8 +270,8 @@ export namespace atlas { m_imgui_context->image_memory_barrier( current, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); m_imgui_context->depth_image_memory_barrier( current, @@ -316,13 +319,16 @@ export namespace atlas { .min_depth = 0.0f, .max_depth = 1.0f, }; - current.set_viewport(0, 1, std::span(&viewport, 1)); + current.set_viewport( + 0, 1, std::span(&viewport, 1)); vk::scissor_params scissor = { .offset = { 0, 0 }, - .extent = {static_cast(m_window_params.width), static_cast(m_window_params.height)}, + .extent = { static_cast(m_window_params.width), + static_cast(m_window_params.height) }, }; - current.set_scissor(0, 1, std::span(&scissor, 1)); + current.set_scissor( + 0, 1, std::span(&scissor, 1)); current.begin_rendering(ui_begin_params); @@ -338,7 +344,7 @@ export namespace atlas { /** * Presenting to Swapchain Memory Barriers - */ + */ vk::rendering_attachment present_color_render_attachment = { .image_view = m_images[m_next_image_frame_idx].image_view(), @@ -374,7 +380,7 @@ export namespace atlas { m_images[m_next_image_frame_idx].memory_barrier( current, - m_color_format, + m_color_format, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); @@ -385,7 +391,6 @@ export namespace atlas { VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); - current.begin_rendering(present_begin_params); m_imgui_context->begin(); m_imgui_context->set_current_command(current); @@ -410,7 +415,7 @@ export namespace atlas { // Update platform window afterwards m_imgui_context->update_platforms(); } - + invoke_post_update(m_current_scene.get()); invoke_post_update(m_world.get()); } @@ -453,7 +458,7 @@ export namespace atlas { } private: - float m_aspect_ratio=0.f; + float m_aspect_ratio = 0.f; uint32_t m_next_image_frame_idx = 0; VkFormat m_color_format; VkFormat m_depth_format; diff --git a/atlas/core/core.cppm b/atlas/core/core.cppm index fefccbc8..3f1869ec 100644 --- a/atlas/core/core.cppm +++ b/atlas/core/core.cppm @@ -1,2 +1 @@ export module core; - diff --git a/atlas/core/entry_point/main.cpp b/atlas/core/entry_point/main.cpp index 870f63ce..724d3fb8 100644 --- a/atlas/core/entry_point/main.cpp +++ b/atlas/core/entry_point/main.cpp @@ -97,11 +97,9 @@ main() { // specify to using vulkan 1.4 .version = vk::api_version::vk_1_4, // .validation takes in a std::span - .validations = - validation_layers, + .validations = validation_layers, // .extensions also takes in std::span - .extensions = - global_extensions + .extensions = global_extensions }; // 1. Setting up vk instance diff --git a/atlas/core/event/event.cppm b/atlas/core/event/event.cppm index 33e95707..376c48fd 100644 --- a/atlas/core/event/event.cppm +++ b/atlas/core/event/event.cppm @@ -27,10 +27,10 @@ namespace atlas { enum input_state { None, Idle, Pressed, Released }; export enum cursor_mode : uint32_t { - normal=0x00034001, - hidden=0x00034002, - disabled=0x00034003, - captured=0x00034004, + normal = 0x00034001, + hidden = 0x00034002, + disabled = 0x00034003, + captured = 0x00034004, }; struct joystick_button { @@ -150,9 +150,9 @@ namespace atlas { s_window_address = p_window; } - void set_cursor_mode(cursor_mode p_mode) { - glfwSetInputMode(s_window_address, GLFW_CURSOR, static_cast(p_mode)); + glfwSetInputMode( + s_window_address, GLFW_CURSOR, static_cast(p_mode)); } // specfying listening for events diff --git a/atlas/core/scene/level_streamer.cppm b/atlas/core/scene/level_streamer.cppm index 9e661f6d..4f2124df 100644 --- a/atlas/core/scene/level_streamer.cppm +++ b/atlas/core/scene/level_streamer.cppm @@ -33,7 +33,7 @@ export namespace atlas { * @return the currently active scene to retrieve */ ref current_scene(const std::string& p_name) { - if(!m_scenes.contains(p_name)) { + if (!m_scenes.contains(p_name)) { return nullptr; } @@ -43,11 +43,7 @@ export namespace atlas { template void default_scene(const std::string& p_name, event::bus& p_bus) { m_scenes.emplace( - p_name, - std::allocate_shared( - m_allocator, - p_name, - p_bus)) ; + p_name, std::allocate_shared(m_allocator, p_name, p_bus)); } // Experimental: This was just for testing. Will come back to later. diff --git a/atlas/core/serialize/serializer.cppm b/atlas/core/serialize/serializer.cppm index 70447fa5..3d66df17 100644 --- a/atlas/core/serialize/serializer.cppm +++ b/atlas/core/serialize/serializer.cppm @@ -91,13 +91,12 @@ namespace atlas { // Deserialize atlas::material component if (p_entity_value["Mesh Source"]) { auto mesh = p_entity_value["Mesh Source"]; - if(!mesh["Model Path"].as().empty()) { + if (!mesh["Model Path"].as().empty()) { p_deserialize_to_object.set({ - .flip = static_cast(mesh["Flip"].as()), - .model_path = - mesh["Model Path"].as(), - .diffuse = mesh["Diffuse"].as(), - .specular = mesh["Specular"].as(), + .flip = static_cast(mesh["Flip"].as()), + .model_path = mesh["Model Path"].as(), + .diffuse = mesh["Diffuse"].as(), + .specular = mesh["Specular"].as(), }); } } @@ -178,7 +177,7 @@ namespace atlas { * serialization/deserialization to */ serializer(ref p_scene) - : m_current_scene_ctx(/*NOLINT*/p_scene) {} + : m_current_scene_ctx(/*NOLINT*/ p_scene) {} /** * @param p_filepath is the specified path to save the file @@ -245,8 +244,9 @@ namespace atlas { environment_map_data); } - if(!environment_map_data.empty()) { - p_registry.set({ .filepath = environment_map_data }); + if (!environment_map_data.empty()) { + p_registry.set( + { .filepath = environment_map_data }); } YAML::Node entity_objects = data["Entities"]; diff --git a/atlas/core/serialize/types.cppm b/atlas/core/serialize/types.cppm index c74a0a96..f8464c61 100644 --- a/atlas/core/serialize/types.cppm +++ b/atlas/core/serialize/types.cppm @@ -404,8 +404,7 @@ export namespace atlas { p_output << YAML::Key << "Mesh Source"; p_output << YAML::BeginMap; - p_output << YAML::Key << "Flip" << YAML::Value - << p_material->flip; + p_output << YAML::Key << "Flip" << YAML::Value << p_material->flip; p_output << YAML::Key << "Model Path" << YAML::Value << p_material->model_path; p_output << YAML::Key << "Diffuse" << YAML::Value diff --git a/atlas/core/ui/ui.cppm b/atlas/core/ui/ui.cppm index 98680ba2..9bf9a9ca 100644 --- a/atlas/core/ui/ui.cppm +++ b/atlas/core/ui/ui.cppm @@ -2,6 +2,5 @@ module; export module atlas.core.ui; - export import :widgets; -export import :imgui_stdlib; \ No newline at end of file +export import :imgui_stdlib; \ No newline at end of file diff --git a/atlas/core/utilities/poll_state.cppm b/atlas/core/utilities/poll_state.cppm index 300bacae..e384967b 100644 --- a/atlas/core/utilities/poll_state.cppm +++ b/atlas/core/utilities/poll_state.cppm @@ -45,7 +45,8 @@ export namespace atlas { s_start[p_address].emplace_back(p_callback); } - void post_update_poll(void* p_address, const std::function& p_callback) { + void post_update_poll(void* p_address, + const std::function& p_callback) { s_post[p_address].emplace_back(p_callback); } diff --git a/atlas/core/utilities/state.cppm b/atlas/core/utilities/state.cppm index 9f277ead..cf4f7f94 100644 --- a/atlas/core/utilities/state.cppm +++ b/atlas/core/utilities/state.cppm @@ -170,7 +170,6 @@ export namespace atlas { }); } - template void register_post(UObject* p_instance, const UCallback& p_callable) { static_assert(std::is_member_pointer_v, diff --git a/atlas/core/utilities/utilities.cppm b/atlas/core/utilities/utilities.cppm index 60eeb298..0b48cb03 100644 --- a/atlas/core/utilities/utilities.cppm +++ b/atlas/core/utilities/utilities.cppm @@ -10,7 +10,6 @@ export import :common; export import :poll_state; export import :state; - namespace atlas { export struct window_params { uint32_t width; diff --git a/atlas/drivers/importer/obj_loader.cppm b/atlas/drivers/importer/obj_loader.cppm index 732bcdc6..42d76fc1 100644 --- a/atlas/drivers/importer/obj_loader.cppm +++ b/atlas/drivers/importer/obj_loader.cppm @@ -36,7 +36,8 @@ namespace std { export namespace atlas { class obj_importer { public: - obj_importer(const std::string& p_path, bool p_flip) : m_flip(p_flip) { + obj_importer(const std::string& p_path, bool p_flip) + : m_flip(p_flip) { m_load = load(p_path); } @@ -47,22 +48,24 @@ export namespace atlas { std::string warn; std::string err; - if(!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, p_path.c_str())) { + if (!tinyobj::LoadObj( + &attrib, &shapes, &materials, &warn, &err, p_path.c_str())) { return false; } std::unordered_map unique_vertices{}; - for(const auto& shape_face : shapes) { - for(const auto& index : shape_face.mesh.indices) { + for (const auto& shape_face : shapes) { + for (const auto& index : shape_face.mesh.indices) { vk::vertex_input vertex{}; - if(!unique_vertices.contains(vertex)) { - unique_vertices[vertex] = static_cast(m_vertices.size()); + if (!unique_vertices.contains(vertex)) { + unique_vertices[vertex] = + static_cast(m_vertices.size()); m_vertices.push_back(vertex); } - if(index.vertex_index >= 0) { + if (index.vertex_index >= 0) { vertex.position = { attrib.vertices[3 * index.vertex_index + 0], attrib.vertices[3 * index.vertex_index + 1], @@ -113,7 +116,7 @@ export namespace atlas { if (!unique_vertices.contains(vertex)) { unique_vertices[vertex] = - static_cast(m_vertices.size()); + static_cast(m_vertices.size()); m_vertices.push_back(vertex); } @@ -124,24 +127,18 @@ export namespace atlas { return true; } - [[nodiscard]] bool is_load() const { - return m_load; - } + [[nodiscard]] bool is_load() const { return m_load; } //! @return the geometry vertices - std::span vertices() { - return m_vertices; - } + std::span vertices() { return m_vertices; } //! @return the geometry indices - std::span indices() { - return m_indices; - } + std::span indices() { return m_indices; } private: std::vector m_vertices; std::vector m_indices; - bool m_flip=false; - bool m_load=false; + bool m_flip = false; + bool m_load = false; }; }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/environment_map.cppm b/atlas/drivers/vulkan/environment_map.cppm index 69fa8133..0a9c2a87 100644 --- a/atlas/drivers/vulkan/environment_map.cppm +++ b/atlas/drivers/vulkan/environment_map.cppm @@ -38,40 +38,54 @@ struct environment_uniforms { }; struct environment_push_constant { - uint64_t scene_environment_address=0; + uint64_t scene_environment_address = 0; }; /** - * - * @brief Vulkan-specific implementation for loading GPU resources associated to loading environent maps. - * -*/ + * + * @brief Vulkan-specific implementation for loading GPU resources associated to + * loading environent maps. + * + */ export class environment_map { public: environment_map() = default; environment_map(std::shared_ptr p_device, vk::physical_device& p_physical, - const std::string& p_filename, /*NOLINT*/VkFormat p_color_format, VkFormat p_depth_format) : m_color_format(p_color_format), m_depth_format(p_depth_format) { + const std::string& p_filename, + /*NOLINT*/ VkFormat p_color_format, + VkFormat p_depth_format) + : m_color_format(p_color_format) + , m_depth_format(p_depth_format) { /*NOLINT*/ m_device = p_device; m_physical = p_physical; - m_memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit); + m_memory_mask = + m_physical->memory_properties(vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit); construct(p_filename); } environment_map(std::shared_ptr p_device, vk::physical_device& p_physical, - std::span p_color, const vk::image_extent& p_extent, /*NOLINT*/VkFormat p_color_format, VkFormat p_depth_format) : m_color_format(p_color_format), m_depth_format(p_depth_format) { + std::span p_color, + const vk::image_extent& p_extent, + /*NOLINT*/ VkFormat p_color_format, + VkFormat p_depth_format) + : m_color_format(p_color_format) + , m_depth_format(p_depth_format) { /*NOLINT*/ m_device = p_device; m_physical = p_physical; - m_memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit); + m_memory_mask = + m_physical->memory_properties(vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit); construct(p_color, p_extent); } /** * @brief loads in a new HDRI environment map - */ + */ void construct(const std::string& p_filename) { bool res = create_hdr(p_filename); @@ -86,9 +100,11 @@ public: } /** - * @brief loads in raw pixels and texture dimensions to receive in raw pixels data if no HDRI is provided. - */ - void construct(std::span p_color, const vk::image_extent& p_extent) { + * @brief loads in raw pixels and texture dimensions to receive in raw + * pixels data if no HDRI is provided. + */ + void construct(std::span p_color, + const vk::image_extent& p_extent) { bool res = create_hdr(p_color, p_extent); if (!res) { @@ -102,8 +118,9 @@ public: } /** - * @brief performs the loading operation to read in the pixel float data of the actual HDRI metadata. - */ + * @brief performs the loading operation to read in the pixel float data of + * the actual HDRI metadata. + */ bool create_hdr(const std::string& p_filename) { stbi_set_flip_vertically_on_load(true); int w, h, channels; @@ -164,8 +181,9 @@ public: upload_cmd.begin(vk::command_usage::one_time_submit); - // Performing image layout transitions to ensure we do not lose any data transferring over to the GPU. - // Begin Memory Barrier: Undefined to TRANSFER_DST + // Performing image layout transitions to ensure we do not lose any data + // transferring over to the GPU. Begin Memory Barrier: Undefined to + // TRANSFER_DST m_skybox_image.memory_barrier(upload_cmd, texture_format, VK_IMAGE_LAYOUT_UNDEFINED, @@ -208,12 +226,14 @@ public: return true; } - bool create_hdr(std::span p_colors, const vk::image_extent& p_extent) { + bool create_hdr(std::span p_colors, + const vk::image_extent& p_extent) { VkFormat texture_format = VK_FORMAT_R32G32B32A32_SFLOAT; const uint64_t bytes_per_pixel_channel = 16; // float are 4 bytes const uint64_t total_size_bytes = - static_cast(static_cast(p_extent.width) * p_extent.height * bytes_per_pixel_channel); + static_cast(static_cast(p_extent.width) * + p_extent.height * bytes_per_pixel_channel); const uint64_t image_size = total_size_bytes; vk::buffer_parameters staging_params = { @@ -242,7 +262,6 @@ public: reinterpret_cast(p_colors.data()), image_size); staging_buffer.transfer(pixels_data); - // 6. Record and Execute Upload vk::command_params upload_params = { .levels = vk::command_levels::primary, @@ -540,49 +559,48 @@ public: m_skybox_vbo = vk::vertex_buffer(*m_device, vertices, vertex_params); } - void create_pipelines() { create_buffers(); std::array attribute_entries = { vk::vertex_attribute_entry{ - .location = 0, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position), + .location = 0, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, position), }, vk::vertex_attribute_entry{ - .location = 1, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color), + .location = 1, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, color), }, vk::vertex_attribute_entry{ - .location = 2, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals), + .location = 2, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, normals), }, vk::vertex_attribute_entry{ - .location = 3, - .format = vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv), + .location = 3, + .format = vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, uv), } }; std::array attribute = { vk::vertex_attribute{ - // layout (set = 0, binding = 0) - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = vk::input_rate::vertex, + // layout (set = 0, binding = 0) + .binding = 0, + .entries = attribute_entries, + .stride = sizeof(vk::vertex_input), + .input_rate = vk::input_rate::vertex, }, }; const std::array sources = { vk::shader_source{ - .filename = "builtin.shaders/skybox/skybox.vert.spv", - .stage = vk::shader_stage::vertex, + .filename = "builtin.shaders/skybox/skybox.vert.spv", + .stage = vk::shader_stage::vertex, }, vk::shader_source{ - .filename = "builtin.shaders/skybox/skybox.frag.spv", - .stage = vk::shader_stage::fragment, + .filename = "builtin.shaders/skybox/skybox.frag.spv", + .stage = vk::shader_stage::fragment, }, }; @@ -592,7 +610,6 @@ public: m_skybox_shaders = vk::shader_resource(*m_device, shader_info); m_skybox_shaders.vertex_attributes(attribute); - // Specifying descriptors std::array entries = { @@ -609,7 +626,6 @@ public: }, }; - // layout(set = 0, ...) uint32_t max_descriptors = 1; vk::descriptor_layout set0_layout = { @@ -618,20 +634,25 @@ public: .entries = entries, // descriptor layout entries description .descriptor_counts = std::span(&max_descriptors, 1), }; - m_skybox_descriptor = vk::descriptor_resource(*m_device, set0_layout, vk::descriptor_layout_flags::update_after_bind_pool); - + m_skybox_descriptor = vk::descriptor_resource( + *m_device, + set0_layout, + vk::descriptor_layout_flags::update_after_bind_pool); // specifying push constant for pipelines - std::array color_blend_attachments = { - vk::color_blend_attachment_state{}, - }; + std::array + color_blend_attachments = { + vk::color_blend_attachment_state{}, + }; std::array dynamic_states = { - vk::dynamic_state::viewport, vk::dynamic_state::scissor, + vk::dynamic_state::viewport, + vk::dynamic_state::scissor, }; uint32_t vertex_mask = static_cast(vk::shader_stage::vertex); - uint32_t fragment_mask = static_cast(vk::shader_stage::fragment); + uint32_t fragment_mask = + static_cast(vk::shader_stage::fragment); uint32_t stage_mask = vertex_mask | fragment_mask; m_stage = static_cast(stage_mask); vk::push_constant_range range = { @@ -669,12 +690,16 @@ public: m_skybox_pipeline = vk::pipeline(*m_device, skybox_pipeline_params); vk::buffer_parameters uniform_params = { - .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::uniform_buffer_bit | vk::buffer_usage::shader_device_address_bit, + .memory_mask = m_physical->memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | + vk::buffer_usage::shader_device_address_bit, .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, }; - m_skybox_uniforms = vk::dyn::buffer(*m_device, sizeof(environment_uniforms), uniform_params); + m_skybox_uniforms = vk::dyn::buffer( + *m_device, sizeof(environment_uniforms), uniform_params); vk::write_image environment_image = { .sampler = m_skybox_image.sampler(), @@ -684,8 +709,9 @@ public: std::array write_descriptors = { // layout(set = 0, binding = 1) sampler2D environment; vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = std::span(&environment_image, 1), + .dst_binding = 1, + .sample_images = + std::span(&environment_image, 1), }, }; @@ -696,7 +722,6 @@ public: m_current_command = &p_current; } - void begin(const glm::mat4& p_proj, const glm::mat4& p_view) { m_proj_view = p_proj * glm::mat4(glm::mat3(p_view)); @@ -705,25 +730,33 @@ public: .proj_view = m_proj_view, }; - m_skybox_uniforms.transfer(std::span(&scene_ubo, 1)); + m_skybox_uniforms.transfer( + std::span(&scene_ubo, 1)); const VkDescriptorSet skybox_descriptor = m_skybox_descriptor; - m_current_command->bind_descriptors(m_skybox_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&skybox_descriptor, 1)); + m_current_command->bind_descriptors( + m_skybox_pipeline.layout(), + VK_PIPELINE_BIND_POINT_GRAPHICS, + std::span(&skybox_descriptor, 1)); } void end() { - const uint64_t scene_environment = m_skybox_uniforms.get_device_address(); + const uint64_t scene_environment = + m_skybox_uniforms.get_device_address(); environment_push_constant environment_push_const = { .scene_environment_address = scene_environment, }; - m_skybox_pipeline.push_constant(*m_current_command, environment_push_const, m_stage, 0); + m_skybox_pipeline.push_constant( + *m_current_command, environment_push_const, m_stage, 0); // Binding our vertex buffers here const VkBuffer& skybox_vertex = m_skybox_vbo; uint64_t offset = 0; - m_current_command->bind_vertex_buffers(std::span(&skybox_vertex, 1), std::span(&offset, 1)); + m_current_command->bind_vertex_buffers( + std::span(&skybox_vertex, 1), + std::span(&offset, 1)); vkCmdDraw(*m_current_command, m_vertices_size, 1, 0, 0); } @@ -746,7 +779,7 @@ public: private: glm::mat4 m_proj_view; vk::command_buffer* m_current_command; - uint64_t m_vertices_size=0; + uint64_t m_vertices_size = 0; std::shared_ptr m_device; std::optional m_physical; vk::vertex_buffer m_skybox_vbo; diff --git a/atlas/drivers/vulkan/gpu_uniforms.cppm b/atlas/drivers/vulkan/gpu_uniforms.cppm index 5eb9da73..5677a7d2 100644 --- a/atlas/drivers/vulkan/gpu_uniforms.cppm +++ b/atlas/drivers/vulkan/gpu_uniforms.cppm @@ -12,34 +12,33 @@ export module atlas.drivers.vulkan:gpu_uniforms; import vk; - export namespace atlas { struct gpu_mesh_data { vk::vertex_buffer vertex; vk::index_buffer index; - uint32_t index_count=0; - uint32_t instance=1; - uint32_t first_index=0; - uint32_t vertex_offset=0; - uint32_t first_instance=0; - bool has_indices_buffer=false; + uint32_t index_count = 0; + uint32_t instance = 1; + uint32_t first_index = 0; + uint32_t vertex_offset = 0; + uint32_t first_instance = 0; + bool has_indices_buffer = false; uint32_t vertices_size = 0; - uint32_t indices_size=0; + uint32_t indices_size = 0; }; struct push_constant_data { - uint64_t scene_address=0; - uint64_t model_mat_array_address=0; - uint32_t model_idx=0; - uint32_t diffuse_idx=0; - uint32_t specular_idx=0; + uint64_t scene_address = 0; + uint64_t model_mat_array_address = 0; + uint32_t model_idx = 0; + uint32_t diffuse_idx = 0; + uint32_t specular_idx = 0; uint64_t point_light_address; }; struct scene_uniforms { - glm::mat4 view=glm::mat4(1.f); - glm::mat4 proj=glm::mat4(1.f); - glm::vec4 camera_pos=glm::vec4(1.f); + glm::mat4 view = glm::mat4(1.f); + glm::mat4 proj = glm::mat4(1.f); + glm::vec4 camera_pos = glm::vec4(1.f); }; struct objects_uniform { @@ -47,8 +46,8 @@ export namespace atlas { }; struct gpu_material { - uint64_t diffuse_idx=0; - uint64_t specular_idx=0; + uint64_t diffuse_idx = 0; + uint64_t specular_idx = 0; }; struct gpu_point_light { @@ -64,20 +63,21 @@ export namespace atlas { glm::vec4 specular = glm::vec4(1.f); }; - struct light_scene_ubo { - alignas(16) uint32_t num_lights=0; + struct light_scene_ubo { + alignas(16) uint32_t num_lights = 0; alignas(16) std::array point_lights{}; }; - /** - * - * @brief slot is the index into the texture array to retrieve this specific texture data - * - * vk::texture is the texture data to configure the GPU-visible image resource - */ + * + * @brief slot is the index into the texture array to retrieve this specific + * texture data + * + * vk::texture is the texture data to configure the GPU-visible image + * resource + */ struct gpu_image { - uint64_t slot=0; + uint64_t slot = 0; vk::texture texture_data; }; }; \ No newline at end of file diff --git a/atlas/drivers/vulkan/graphics_context.cppm b/atlas/drivers/vulkan/graphics_context.cppm index 666d593b..9f9e7242 100644 --- a/atlas/drivers/vulkan/graphics_context.cppm +++ b/atlas/drivers/vulkan/graphics_context.cppm @@ -26,8 +26,9 @@ import vk; export namespace atlas { /** - * @brief graphics context to manage core resources that is used as the primary resource access to the core Vulkan handles. - */ + * @brief graphics context to manage core resources that is used as the + * primary resource access to the core Vulkan handles. + */ class graphics_context { public: graphics_context() = default; @@ -36,7 +37,7 @@ export namespace atlas { std::shared_ptr p_device) : m_api_instance(p_api_instance) , m_physical(&p_physical) - , m_device(/*NOLINT*/p_device) { + , m_device(/*NOLINT*/ p_device) { // Constructing the graphics context } diff --git a/atlas/drivers/vulkan/imgui_context.cppm b/atlas/drivers/vulkan/imgui_context.cppm index b0dbea16..5a167309 100644 --- a/atlas/drivers/vulkan/imgui_context.cppm +++ b/atlas/drivers/vulkan/imgui_context.cppm @@ -148,14 +148,15 @@ namespace atlas { ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); io.IniFilename = nullptr; - - std::filesystem::path path = std::filesystem::current_path() / "imgui.ini"; - std::string data_source=""; - if(std::filesystem::exists(path)) { + std::filesystem::path path = + std::filesystem::current_path() / "imgui.ini"; + + std::string data_source = ""; + if (std::filesystem::exists(path)) { std::ifstream file(path.string()); - if(!file) { + if (!file) { std::println("Cannot load {}", path.string()); } @@ -164,7 +165,8 @@ namespace atlas { data_source = ss.str(); } - ImGui::LoadIniSettingsFromMemory(data_source.c_str(), data_source.size()); + ImGui::LoadIniSettingsFromMemory(data_source.c_str(), + data_source.size()); io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls diff --git a/atlas/drivers/vulkan/render_context.cppm b/atlas/drivers/vulkan/render_context.cppm index 6a98465b..de80a8e9 100644 --- a/atlas/drivers/vulkan/render_context.cppm +++ b/atlas/drivers/vulkan/render_context.cppm @@ -30,16 +30,20 @@ import vk; export namespace atlas { /** - * - * @brief Context that translates the ECS rendering-specific components to GPU-visible resources - * - * Manages the dispatching of task workloads to performing data transfers and draw calls. - * - */ + * + * @brief Context that translates the ECS rendering-specific components to + * GPU-visible resources + * + * Manages the dispatching of task workloads to performing data transfers + * and draw calls. + * + */ class render_context { public: render_context() = default; - render_context(/*NOLINT*/std::shared_ptr p_context, VkFormat p_color_format, VkFormat p_depth_format) { + render_context(/*NOLINT*/ std::shared_ptr p_context, + VkFormat p_color_format, + VkFormat p_depth_format) { m_physical = p_context->physical_device(); m_device = p_context->logical_device(); m_color_format = p_color_format; @@ -48,42 +52,42 @@ export namespace atlas { // Vertex Attributes Parameters std::array attribute_entries = { vk::vertex_attribute_entry{ - .location = 0, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, position), + .location = 0, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, position), }, vk::vertex_attribute_entry{ - .location = 1, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, color), + .location = 1, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, color), }, vk::vertex_attribute_entry{ - .location = 2, - .format = vk::format::rg32_sfloat, - .stride = offsetof(vk::vertex_input, uv), + .location = 2, + .format = vk::format::rg32_sfloat, + .stride = offsetof(vk::vertex_input, uv), }, vk::vertex_attribute_entry{ - .location = 3, - .format = vk::format::rgb32_sfloat, - .stride = offsetof(vk::vertex_input, normals), + .location = 3, + .format = vk::format::rgb32_sfloat, + .stride = offsetof(vk::vertex_input, normals), } }; std::array attributes = { vk::vertex_attribute{ - .binding = 0, - .entries = attribute_entries, - .stride = sizeof(vk::vertex_input), - .input_rate = vk::input_rate::vertex, + .binding = 0, + .entries = attribute_entries, + .stride = sizeof(vk::vertex_input), + .input_rate = vk::input_rate::vertex, }, }; std::array shader_sources = { vk::shader_source{ - .filename = "builtin.shaders/pbr.vert.spv", - .stage = vk::shader_stage::vertex, + .filename = "builtin.shaders/pbr.vert.spv", + .stage = vk::shader_stage::vertex, }, vk::shader_source{ - .filename = "builtin.shaders/pbr.frag.spv", - .stage = vk::shader_stage::fragment, + .filename = "builtin.shaders/pbr.frag.spv", + .stage = vk::shader_stage::fragment, }, }; @@ -94,7 +98,6 @@ export namespace atlas { m_shader_resource = vk::shader_resource(*m_device, shader_info); m_shader_resource.vertex_attributes(attributes); - // Configuring Descriptor Set 0 -- specify to vk::pipeline // Descriptor Set 0 uint32_t max_descriptors = 1000; @@ -127,22 +130,31 @@ export namespace atlas { vk::descriptor_layout set0_layout = { .slot = 0, .max_sets = max_descriptors, - .entries = entries_set1, // descriptor layout entries description - .descriptor_counts = std::span(&max_descriptors, 1), + .entries = + entries_set1, // descriptor layout entries description + .descriptor_counts = + std::span(&max_descriptors, 1), }; - m_set0_resource = vk::descriptor_resource(*m_device, set0_layout, vk::descriptor_layout_flags::update_after_bind_pool); + m_set0_resource = vk::descriptor_resource( + *m_device, + set0_layout, + vk::descriptor_layout_flags::update_after_bind_pool); - std::array color_blend_attachments = { - vk::color_blend_attachment_state{}, - }; + std::array + color_blend_attachments = { + vk::color_blend_attachment_state{}, + }; std::array dynamic_states = { - vk::dynamic_state::viewport, vk::dynamic_state::scissor, + vk::dynamic_state::viewport, + vk::dynamic_state::scissor, }; m_format = static_cast(p_color_format); - uint32_t vertex_mask = static_cast(vk::shader_stage::vertex); - uint32_t fragment_mask = static_cast(vk::shader_stage::fragment); + uint32_t vertex_mask = + static_cast(vk::shader_stage::vertex); + uint32_t fragment_mask = + static_cast(vk::shader_stage::fragment); uint32_t stage_mask = vertex_mask | fragment_mask; m_stage = static_cast(stage_mask); vk::push_constant_range range = { @@ -172,77 +184,102 @@ export namespace atlas { m_main_pipeline = vk::pipeline(*m_device, pipeline_configuration); vk::buffer_parameters uniform_params = { - .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::uniform_buffer_bit | vk::buffer_usage::shader_device_address_bit, - .allocate_flags = vk::memory_allocate_flags::device_address_bit_khr, + .memory_mask = m_physical->memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::uniform_buffer_bit | + vk::buffer_usage::shader_device_address_bit, + .allocate_flags = + vk::memory_allocate_flags::device_address_bit_khr, }; - m_scene_uniforms = vk::dyn::buffer(*m_device, sizeof(scene_uniforms), uniform_params); + m_scene_uniforms = vk::dyn::buffer( + *m_device, sizeof(scene_uniforms), uniform_params); - // We are setting to the maximum of objects that should be managed in this uniform buffer - // This uniform buffer is responsible for managing the model matrices of every object in a given scene. + // We are setting to the maximum of objects that should be managed + // in this uniform buffer This uniform buffer is responsible for + // managing the model matrices of every object in a given scene. uint32_t max_objects = 10'000; - m_object_model_uniforms = vk::dyn::buffer(*m_device, sizeof(objects_uniform) * max_objects, uniform_params); - + m_object_model_uniforms = vk::dyn::buffer( + *m_device, sizeof(objects_uniform) * max_objects, uniform_params); // configuring uniforms for point lights - m_lighting_uniforms = vk::dyn::buffer(*m_device, sizeof(light_scene_ubo), uniform_params); + m_lighting_uniforms = vk::dyn::buffer( + *m_device, sizeof(light_scene_ubo), uniform_params); // Index 0 will default to a white texture vk::image_extent extent = { .width = 1, .height = 1, }; - std::array white_color = {0xff, 0xff, 0xff, 0xff}; - m_gpu_textures.emplace_back(*m_device, extent, white_color, m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit)); - + std::array white_color = { 0xff, 0xff, 0xff, 0xff }; + m_gpu_textures.emplace_back( + *m_device, + extent, + white_color, + m_physical->memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit)); } void prebake() { - flecs::query<> all_meshes = m_world->query_builder().build(); + flecs::query<> all_meshes = + m_world->query_builder().build(); - all_meshes.each([this](flecs::entity p_entity){ + all_meshes.each([this](flecs::entity p_entity) { const mesh_source* src = p_entity.get(); - + vk::buffer_parameters vertex_params = { - .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), - .usage = vk::buffer_usage::transfer_dst_bit | vk::buffer_usage::vertex_buffer_bit, + .memory_mask = m_physical->memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), + .usage = vk::buffer_usage::transfer_dst_bit | + vk::buffer_usage::vertex_buffer_bit, }; vk::buffer_parameters index_params = { - .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + .memory_mask = m_physical->memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), .usage = vk::buffer_usage::index_buffer_bit, }; // importing .obj 3d models here obj_importer importer(src->model_path, src->flip); gpu_mesh_data gpu_mesh{}; - gpu_mesh.vertex = vk::vertex_buffer(*m_device, importer.vertices(), vertex_params); - gpu_mesh.index = vk::index_buffer(*m_device, importer.indices(), index_params); - gpu_mesh.has_indices_buffer = (importer.indices().size() >= 0) ? true : false; + gpu_mesh.vertex = vk::vertex_buffer( + *m_device, importer.vertices(), vertex_params); + gpu_mesh.index = + vk::index_buffer(*m_device, importer.indices(), index_params); + gpu_mesh.has_indices_buffer = + (importer.indices().size() >= 0) ? true : false; gpu_mesh.vertices_size = importer.vertices().size(); gpu_mesh.indices_size = importer.indices().size(); m_meshes.emplace(p_entity.id(), gpu_mesh); - + vk::texture_params config_texture = { - .memory_mask = m_physical->memory_properties(vk::memory_property::host_visible_bit | vk::memory_property::host_cached_bit), + .memory_mask = m_physical->memory_properties( + vk::memory_property::host_visible_bit | + vk::memory_property::host_cached_bit), }; // Loading texture and setting up VkSampler and VkImageView stb_image diffuse_img = stb_image(src->diffuse, config_texture); - stb_image specular_img = stb_image(src->specular, config_texture); + stb_image specular_img = + stb_image(src->specular, config_texture); // Reminder: Use diffuse_idx gpu_material material = {}; - if(!src->diffuse.empty()) { + if (!src->diffuse.empty()) { material.diffuse_idx = m_texture_slot_index++; - m_gpu_textures.emplace_back(*m_device, &diffuse_img, config_texture); + m_gpu_textures.emplace_back( + *m_device, &diffuse_img, config_texture); } - - if(!src->specular.empty()) { + if (!src->specular.empty()) { material.specular_idx = m_texture_slot_index++; - m_gpu_textures.emplace_back(*m_device, &specular_img, config_texture); + m_gpu_textures.emplace_back( + *m_device, &specular_img, config_texture); } m_material_table.emplace(p_entity.id(), material); @@ -250,7 +287,7 @@ export namespace atlas { // Preparing the texture data before we update descriptor set 0 // Storing all of our texture via one contiguous array of textures - for(auto& image : m_gpu_textures) { + for (auto& image : m_gpu_textures) { vk::write_image viking_room_texture = { .sampler = image.image().sampler(), .view = image.image().image_view(), @@ -259,16 +296,26 @@ export namespace atlas { m_gpu_images.emplace_back(viking_room_texture); } - // Ensure that we load the environment // We should never load an invalid environment - if(m_world->has()) { - const environment* environment_data = m_world->get(); - m_environment_map = environment_map(m_device, m_physical.value(), environment_data->filepath, m_color_format, m_depth_format); + if (m_world->has()) { + const environment* environment_data = + m_world->get(); + m_environment_map = environment_map(m_device, + m_physical.value(), + environment_data->filepath, + m_color_format, + m_depth_format); } else { - std::array black_color = {0.f, 0.f, 0.f, 0.f}; - m_environment_map = environment_map(m_device, m_physical.value(), black_color, vk::image_extent{.width=1, .height=1}, m_color_format, m_depth_format); + std::array black_color = { 0.f, 0.f, 0.f, 0.f }; + m_environment_map = + environment_map(m_device, + m_physical.value(), + black_color, + vk::image_extent{ .width = 1, .height = 1 }, + m_color_format, + m_depth_format); } vk::write_image environment_image = { @@ -279,21 +326,18 @@ export namespace atlas { std::array set0_samples = { // layout(set = 0, binding = 1) sampler2D[] vk::write_image_descriptor{ - .dst_binding = 1, - .sample_images = m_gpu_images, + .dst_binding = 1, + .sample_images = m_gpu_images, }, // layout(set = 0, binding = 2) sampler2D environment; vk::write_image_descriptor{ - .dst_binding = 2, - .sample_images = std::span(&environment_image, 1), + .dst_binding = 2, + .sample_images = + std::span(&environment_image, 1), } }; - - - m_set0_resource.update({}, set0_samples); - } void begin(const glm::mat4& p_proj, const glm::mat4& p_view) { @@ -302,50 +346,57 @@ export namespace atlas { m_projection = p_proj; m_view = p_view; - // querying for objects with point lights - flecs::query all_point_lights = m_world->query_builder().build(); + flecs::query all_point_lights = + m_world->query_builder().build(); int index = 0; light_scene_ubo scene_point_lights{}; - all_point_lights.each([&index, &scene_point_lights](flecs::entity p_entity, point_light& p_light){ - const transform* t = p_entity.get(); - p_light.position = t->position; - - scene_point_lights.point_lights[index] = { - .position = glm::vec4(p_light.position, 1.f), - .color = p_light.color, - .attenuation = p_light.attenuation, - .constant = p_light.constant, - .linear = p_light.linear, - .quadratic = p_light.quadratic, - .ambient = p_light.ambient, - .diffuse = p_light.diffuse, - .specular = p_light.specular, - }; - - index++; - }); + all_point_lights.each( + [&index, &scene_point_lights](flecs::entity p_entity, + point_light& p_light) { + const transform* t = p_entity.get(); + p_light.position = t->position; + + scene_point_lights.point_lights[index] = { + .position = glm::vec4(p_light.position, 1.f), + .color = p_light.color, + .attenuation = p_light.attenuation, + .constant = p_light.constant, + .linear = p_light.linear, + .quadratic = p_light.quadratic, + .ambient = p_light.ambient, + .diffuse = p_light.diffuse, + .specular = p_light.specular, + }; + + index++; + }); scene_point_lights.num_lights = index; - m_lighting_uniforms.transfer(std::span(&scene_point_lights, 1)); + m_lighting_uniforms.transfer( + std::span(&scene_point_lights, 1)); m_main_pipeline.bind(*m_current_command); - flecs::query<> all_meshes = m_world->query_builder().build(); + flecs::query<> all_meshes = + m_world->query_builder().build(); - // Camera projection/view matrices calculated for worldspace calculation + // Camera projection/view matrices calculated for worldspace + // calculation scene_uniforms scene_ubo = { .view = p_view, .proj = p_proj, .camera_pos = m_camera_pos, }; - m_scene_uniforms.transfer(std::span(&scene_ubo, 1)); + m_scene_uniforms.transfer( + std::span(&scene_ubo, 1)); - // Calculating model matrix based on object's transforms specifications (pos, scale, rotation) - all_meshes.each([this](flecs::entity p_entity){ + // Calculating model matrix based on object's transforms + // specifications (pos, scale, rotation) + all_meshes.each([this](flecs::entity p_entity) { const transform* t = p_entity.get(); glm::mat4 model = glm::mat4(1.f); model = glm::translate(model, t->position); @@ -354,60 +405,79 @@ export namespace atlas { model *= rotation_mat; model = glm::scale(model, t->scale); - if(m_model_matrices_lookup.contains(p_entity.id())) { - // hash table to lookup specific index, using the entitys main ID has a hash key - // This way we can use the hash value as the location in the index to modify that model matrix. - m_model_matrices[m_model_matrices_lookup[p_entity.id()]] = model; + if (m_model_matrices_lookup.contains(p_entity.id())) { + // hash table to lookup specific index, using the entitys + // main ID has a hash key This way we can use the hash value + // as the location in the index to modify that model matrix. + m_model_matrices[m_model_matrices_lookup[p_entity.id()]] = + model; } else { // Add model matrix if non existant in the array m_model_matrices.push_back(model); - // Keeping track of the location to that model matrix for book keeping. - m_model_matrices_lookup.emplace(p_entity.id(), m_model_matrix_index_count++); + // Keeping track of the location to that model matrix for + // book keeping. + m_model_matrices_lookup.emplace( + p_entity.id(), m_model_matrix_index_count++); } }); - m_object_model_uniforms.transfer(std::span(m_model_matrices.data(), m_model_matrices.size())); - + m_object_model_uniforms.transfer(std::span( + m_model_matrices.data(), m_model_matrices.size())); + const VkDescriptorSet set0 = m_set0_resource; - m_current_command->bind_descriptors(m_main_pipeline.layout(), VK_PIPELINE_BIND_POINT_GRAPHICS, std::span(&set0, 1)); + m_current_command->bind_descriptors( + m_main_pipeline.layout(), + VK_PIPELINE_BIND_POINT_GRAPHICS, + std::span(&set0, 1)); } - + void end() { - flecs::query<> all_meshes = m_world->query_builder().build(); + flecs::query<> all_meshes = + m_world->query_builder().build(); all_meshes.each([this](flecs::entity p_entity) { - // Retrieving the buffer address that can be looked up from the glsl shader - const uint64_t scene_ubo_address = m_scene_uniforms.get_device_address(); - const uint64_t objects_ubo_address = m_object_model_uniforms.get_device_address(); - const uint64_t lighting_address = m_lighting_uniforms.get_device_address(); + // Retrieving the buffer address that can be looked up from the + // glsl shader + const uint64_t scene_ubo_address = + m_scene_uniforms.get_device_address(); + const uint64_t objects_ubo_address = + m_object_model_uniforms.get_device_address(); + const uint64_t lighting_address = + m_lighting_uniforms.get_device_address(); push_constant_data push = { .scene_address = scene_ubo_address, .model_mat_array_address = objects_ubo_address, - .model_idx = static_cast(m_model_matrices_lookup[p_entity.id()]), - .diffuse_idx = static_cast(m_material_table[p_entity.id()].diffuse_idx), - .specular_idx = static_cast(m_material_table[p_entity.id()].specular_idx), + .model_idx = static_cast( + m_model_matrices_lookup[p_entity.id()]), + .diffuse_idx = static_cast( + m_material_table[p_entity.id()].diffuse_idx), + .specular_idx = static_cast( + m_material_table[p_entity.id()].specular_idx), .point_light_address = lighting_address, }; - m_main_pipeline.push_constant(*m_current_command, push, m_stage, 0); + m_main_pipeline.push_constant( + *m_current_command, push, m_stage, 0); - // TODO: Use Vulkan Indirect Command Draw call for this to reduce draw calls + // TODO: Use Vulkan Indirect Command Draw call for this to + // reduce draw calls const auto& mesh = m_meshes[p_entity.id()]; const VkBuffer vertex = mesh.vertex; uint64_t offset = 0; - m_current_command->bind_vertex_buffers(std::span(&vertex, 1), std::span(&offset, 1)); + m_current_command->bind_vertex_buffers( + std::span(&vertex, 1), + std::span(&offset, 1)); if (mesh.has_indices_buffer) { m_current_command->bind_index_buffers32(mesh.index); - vkCmdDrawIndexed(*m_current_command, mesh.indices_size, 1, 0, 0, 0); + vkCmdDrawIndexed( + *m_current_command, mesh.indices_size, 1, 0, 0, 0); } else { vkCmdDraw(*m_current_command, mesh.vertices_size, 1, 0, 0); } }); - - // Draw Environments m_environment_map.begin(m_projection, m_view); @@ -419,9 +489,7 @@ export namespace atlas { m_environment_map.set_current_command(*m_current_command); } - void current_scene(flecs::world& p_world) { - m_world = &p_world; - } + void current_scene(flecs::world& p_world) { m_world = &p_world; } void destruct() { m_scene_uniforms.reset(); @@ -431,11 +499,11 @@ export namespace atlas { m_environment_map.destruct(); // destroying vector - for(auto& image : m_gpu_textures) { + for (auto& image : m_gpu_textures) { image.destruct(); } - for(auto&[id, mesh] : m_meshes) { + for (auto& [id, mesh] : m_meshes) { mesh.vertex.destruct(); mesh.index.destruct(); } @@ -448,7 +516,7 @@ export namespace atlas { void set_camera_pos(const glm::vec4& p_camera_pos) { m_camera_pos = p_camera_pos; } - + private: glm::vec4 m_camera_pos = glm::vec4(1.f); glm::mat4 m_projection; @@ -458,7 +526,7 @@ export namespace atlas { VkFormat m_depth_format; std::optional m_physical; std::shared_ptr m_device; - vk::command_buffer* m_current_command=nullptr; + vk::command_buffer* m_current_command = nullptr; vk::shader_resource m_shader_resource; vk::pipeline m_main_pipeline; std::vector m_indirect_commands; @@ -467,9 +535,10 @@ export namespace atlas { /** * 3 Specific Buffers for accessing data * 1.) Scene Uniform Buffer (proj/view) - * 2.) Object Uniforms (model matrix): Another use is for instancing having multiple mat4's referencing to instancing copies - * 3.) Material Uniforms (diffuse/specular/etc...) - */ + * 2.) Object Uniforms (model matrix): Another use is for instancing + * having multiple mat4's referencing to instancing copies 3.) Material + * Uniforms (diffuse/specular/etc...) + */ vk::dyn::buffer m_scene_uniforms; // uniform buffer to write all of our objects mat4 model matrices in vk::dyn::buffer m_object_model_uniforms; @@ -479,7 +548,8 @@ export namespace atlas { uint64_t m_texture_slot_index = 1; - // Represents the index to retrieve the location to access the model matrix + // Represents the index to retrieve the location to access the model + // matrix // inside of the vector array uint64_t m_model_matrix_index_count = 0; @@ -487,16 +557,16 @@ export namespace atlas { std::unordered_map m_model_matrices_lookup; std::vector m_model_matrices; - // material lookups - // is to search for specific indices that correspond to various material surfaces - // indices to search inside of vector + // is to search for specific indices that + // correspond to various material surfaces indices to search inside of + // vector std::unordered_map m_material_table; std::vector m_gpu_textures; std::vector m_gpu_images; vk::shader_stage m_stage; - flecs::world* m_world=nullptr; + flecs::world* m_world = nullptr; environment_map m_environment_map; }; diff --git a/atlas/drivers/vulkan/stb_image.cppm b/atlas/drivers/vulkan/stb_image.cppm index dcf01dfd..26fe7a7b 100644 --- a/atlas/drivers/vulkan/stb_image.cppm +++ b/atlas/drivers/vulkan/stb_image.cppm @@ -18,11 +18,12 @@ import vk; export namespace atlas { /** - * @brief Implementing image loading that utilizes stb_image to decode disk-based images into uncompressed streams of bytes. - * + * @brief Implementing image loading that utilizes stb_image to decode + * disk-based images into uncompressed streams of bytes. + * * Provides size extents of uncompressed of the total image size. - * - */ + * + */ class stb_image : public vk::image { public: stb_image() = default; diff --git a/atlas/drivers/vulkan/vulkan.cppm b/atlas/drivers/vulkan/vulkan.cppm index 75c1b376..4aaae17e 100644 --- a/atlas/drivers/vulkan/vulkan.cppm +++ b/atlas/drivers/vulkan/vulkan.cppm @@ -2,7 +2,6 @@ module; export module atlas.drivers.vulkan; - export import :window; export import :graphics_context; export import :render_context; diff --git a/atlas/drivers/vulkan/window.cppm b/atlas/drivers/vulkan/window.cppm index a1fa470d..21d8e88c 100644 --- a/atlas/drivers/vulkan/window.cppm +++ b/atlas/drivers/vulkan/window.cppm @@ -48,16 +48,20 @@ export namespace atlas { m_surface = std::make_shared( p_context->instance_handle(), m_window); - int framebuffer_width=0; - int framebuffer_height=0; - glfwGetFramebufferSize(m_window, &framebuffer_width, &framebuffer_height); - - // Weird issue where the frame buffer size is different then the window size. - // Causing majority of the portion of the window to render pink pixels, indicating an error. + int framebuffer_width = 0; + int framebuffer_height = 0; + glfwGetFramebufferSize( + m_window, &framebuffer_width, &framebuffer_height); + + // Weird issue where the frame buffer size is different then the + // window size. Causing majority of the portion of the window to + // render pink pixels, indicating an error. m_params.width = static_cast(framebuffer_width); m_params.height = static_cast(framebuffer_height); - std::println("Window created with extent: {}x{}", m_params.width, m_params.height); + std::println("Window created with extent: {}x{}", + m_params.width, + m_params.height); vk::swapchain_params swapchain_params = { .width = static_cast(m_params.width), @@ -65,15 +69,15 @@ export namespace atlas { .present_index = 0, }; - m_surface_properties = - p_context->physical_device().request_surface(*m_surface, VK_FORMAT_B8G8R8A8_UNORM); + m_surface_properties = p_context->physical_device().request_surface( + *m_surface, VK_FORMAT_B8G8R8A8_UNORM); m_swapchain = std::make_shared(*p_context->logical_device(), *m_surface, swapchain_params, m_surface_properties); - + center_window(); vk::queue_params present_params = { .family = 0, @@ -122,15 +126,14 @@ export namespace atlas { } void center_window() { - int window_width=0; - int window_height=0; + int window_width = 0; + int window_height = 0; glfwGetWindowSize(m_window, &window_width, &window_height); GLFWmonitor* monitor = glfwGetPrimaryMonitor(); const GLFWvidmode* mode = glfwGetVideoMode(monitor); int width = (mode->width / 2) - (window_width / 2); int height = (mode->height / 2) - (window_height / 2); - glfwSetWindowPos( - m_window, width, height); + glfwSetWindowPos(m_window, width, height); } void submit(std::span p_commands) { @@ -145,9 +148,7 @@ export namespace atlas { return !glfwWindowShouldClose(m_window); } - [[nodiscard]] window_params extent() const { - return m_params; - } + [[nodiscard]] window_params extent() const { return m_params; } private: vk::instance m_instance; diff --git a/atlas/renderer/renderer.cppm b/atlas/renderer/renderer.cppm index 9abe892d..0d646104 100644 --- a/atlas/renderer/renderer.cppm +++ b/atlas/renderer/renderer.cppm @@ -5,5 +5,4 @@ module; export module atlas.renderer; -export namespace atlas { -}; \ No newline at end of file +export namespace atlas {}; \ No newline at end of file diff --git a/editor/application.cpp b/editor/application.cpp index 1644c9aa..d4a5d206 100644 --- a/editor/application.cpp +++ b/editor/application.cpp @@ -11,18 +11,18 @@ import editor; class editor_application : public atlas::application { public: - editor_application(/*NOLINT*/std::shared_ptr p_context, - const atlas::application_settings& p_settings, - atlas::event::bus& p_bus) + editor_application( + /*NOLINT*/ std::shared_ptr p_context, + const atlas::application_settings& p_settings, + atlas::event::bus& p_bus) : atlas::application(p_context, p_settings, p_bus) { - m_world = - std::make_shared(p_context, "Editor World", p_bus, m_stream); + m_world = std::make_shared( + p_context, "Editor World", p_bus, m_stream); current_world(m_world); } - // ~editor_application() { // m_world->destruct(); // } @@ -34,7 +34,9 @@ class editor_application : public atlas::application { }; atlas::ref -initialize_application(/*NOLINT*/std::shared_ptr p_context, atlas::event::bus& p_bus) { +initialize_application( + /*NOLINT*/ std::shared_ptr p_context, + atlas::event::bus& p_bus) { atlas::application_settings settings = { .extent = { .width = 1510, diff --git a/editor/content_browser_panel.cppm b/editor/content_browser_panel.cppm index 7459d07b..a1143252 100644 --- a/editor/content_browser_panel.cppm +++ b/editor/content_browser_panel.cppm @@ -17,19 +17,18 @@ export class content_browser_panel { public: content_browser_panel() = default; - content_browser_panel( - std::shared_ptr p_device, - uint32_t p_memory_properties) { - /*NOLINT*/m_device = p_device; + content_browser_panel(std::shared_ptr p_device, + uint32_t p_memory_properties) { + /*NOLINT*/ m_device = p_device; - m_directory_icon = ui::experimental::icon(m_device, p_memory_properties, - "assets/icons/DirectoryIcon.png"); + m_directory_icon = ui::experimental::icon( + m_device, p_memory_properties, "assets/icons/DirectoryIcon.png"); - m_file_icon = ui::experimental::icon(m_device, p_memory_properties, - "assets/icons/FileIcon.png"); + m_file_icon = ui::experimental::icon( + m_device, p_memory_properties, "assets/icons/FileIcon.png"); - m_back_icon = ui::experimental::icon(m_device, p_memory_properties, - "assets/icons/Back.png"); + m_back_icon = ui::experimental::icon( + m_device, p_memory_properties, "assets/icons/Back.png"); } void run() { @@ -38,8 +37,9 @@ public: // if(ImGui::Button("<-")){ // m_current_directory = m_current_directory.parent_path(); // } - if (ImGui::ImageButton( - "##BackButton", m_back_icon.texture_id(), ImVec2(10, 10))) { + if (ImGui::ImageButton("##BackButton", + m_back_icon.texture_id(), + ImVec2(10, 10))) { m_current_directory = m_current_directory.parent_path(); } } @@ -75,8 +75,8 @@ public: ImGui::PushID(filename.c_str()); VkDescriptorSet icon = dir_entry.is_directory() - ? m_directory_icon.texture_id() - : m_file_icon.texture_id(); + ? m_directory_icon.texture_id() + : m_file_icon.texture_id(); ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0)); ImGui::ImageButton("##Button", diff --git a/editor/editor.cppm b/editor/editor.cppm index 813455f2..49dc3745 100644 --- a/editor/editor.cppm +++ b/editor/editor.cppm @@ -1,6 +1,5 @@ module; - export module editor; export import :world; diff --git a/editor/editor_world.cppm b/editor/editor_world.cppm index 2d757caa..16606299 100644 --- a/editor/editor_world.cppm +++ b/editor/editor_world.cppm @@ -451,8 +451,10 @@ public: m_scene_state = scene_runtime::edit; m_physics_engine.stop(); - if (!m_deserializer_test.load("LevelScene", *m_current_scene)) { - console_log_error("Could not load yaml file LevelScene!!!"); + if (!m_deserializer_test.load("LevelScene", + *m_current_scene)) { + console_log_error( + "Could not load yaml file LevelScene!!!"); } } } diff --git a/editor/level_scene.cppm b/editor/level_scene.cppm index 072cc2b2..8d3ac496 100644 --- a/editor/level_scene.cppm +++ b/editor/level_scene.cppm @@ -75,15 +75,13 @@ public: .scale = { 0.9f, 0.9f, 0.9f }, }); - backpack.set({ - .color = { 1.f, 1.f, 1.f, 1.f }, - .model_path = "assets/backpack/backpack.obj", - .diffuse = "assets/backpack/diffuse.jpg", - .specular = "assets/backpack/specular.jpg" - }); - + backpack.set( + { .color = { 1.f, 1.f, 1.f, 1.f }, + .model_path = "assets/backpack/backpack.obj", + .diffuse = "assets/backpack/diffuse.jpg", + .specular = "assets/backpack/specular.jpg" }); - // const size_t grid_width = 5; + // const size_t grid_width = 5; // const float spacing = 5; // for(size_t i = 0; i < 50; i++) { @@ -173,7 +171,7 @@ public: m_is_first_frame = false; } - if(atlas::event::is_mouse_pressed(mouse_button_middle)) { + if (atlas::event::is_mouse_pressed(mouse_button_middle)) { atlas::event::set_cursor_mode(atlas::cursor_mode::disabled); // sensitivity is how fast the cursor rotates float mouse_sensitivity = 0.01; @@ -186,8 +184,9 @@ public: } // The first frame when presseing left shift is to - // continue rotating the camera from where the original position left off - if(atlas::event::is_mouse_released(mouse_button_middle)) { + // continue rotating the camera from where the original position left + // off + if (atlas::event::is_mouse_released(mouse_button_middle)) { m_is_first_frame = true; atlas::event::set_cursor_mode(atlas::cursor_mode::normal); } @@ -208,15 +207,13 @@ public: void physics_update() {} - void ui_update() { - } + void ui_update() {} - private: std::optional m_editor_camera; float m_movement_speed = 10.f; glm::vec2 m_last_cursor_pos{}; - float m_yaw=0.f; - float m_pitch=0.f; - bool m_is_first_frame=true; + float m_yaw = 0.f; + float m_pitch = 0.f; + bool m_is_first_frame = true; }; \ No newline at end of file diff --git a/editor/level_scene2.cppm b/editor/level_scene2.cppm index adf811bd..962a8d55 100644 --- a/editor/level_scene2.cppm +++ b/editor/level_scene2.cppm @@ -24,9 +24,9 @@ public: level_scene2(const std::string& p_name, atlas::event::bus& p_bus) : atlas::scene(p_name, p_bus) { - m_editor_camera = entity("Editor Camera"); - m_editor_camera->add>(); + m_editor_camera + ->add>(); m_editor_camera->set({ .position = { 3.50f, 4.90f, 36.40f }, .scale{ 1.f }, @@ -45,8 +45,8 @@ public: }); cube.set({ - .model_path = "assets/models/cube.obj", - .diffuse = "assets/models/container_diffuse.png", + .model_path = "assets/models/cube.obj", + .diffuse = "assets/models/container_diffuse.png", }); atlas::register_start(this, &level_scene2::start); @@ -56,8 +56,7 @@ public: ~level_scene2() override = default; - void start() { - } + void start() {} void on_update(float p_delta_time) { atlas::transform* t = m_editor_camera->get_mut(); @@ -109,7 +108,7 @@ public: } // Signal to trigger this kind of scene transition - if(atlas::event::is_key_pressed(key_n)) { + if (atlas::event::is_key_pressed(key_n)) { std::println("Signaling to transition to level scene"); atlas::event::scene_transition scene_transition = { .next_scene = "Level Scene", @@ -120,9 +119,9 @@ public: t->set_rotation(t->rotation); } - // TODO: Have this physics_update be executed during the physics fixed-update framerate - void physics_update() { - } + // TODO: Have this physics_update be executed during the physics + // fixed-update framerate + void physics_update() {} // void on_signal(atlas::event::scene_transition& p_transition) { // p_transition.next_scene = "Level Scene 2"; diff --git a/editor/utilities.cppm b/editor/utilities.cppm index 59961e50..f05f7e10 100644 --- a/editor/utilities.cppm +++ b/editor/utilities.cppm @@ -5,7 +5,6 @@ module; #include #include - export module editor:utilities; import atlas.core.ui; import atlas.core.scene; From 3ba741c56a7bcc8526159fb6b62d8d52f8035e69 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 16:29:05 -0700 Subject: [PATCH 105/106] fixed editor.cppm formatting --- editor/editor.cppm | 2 -- 1 file changed, 2 deletions(-) diff --git a/editor/editor.cppm b/editor/editor.cppm index 49dc3745..764d9dd4 100644 --- a/editor/editor.cppm +++ b/editor/editor.cppm @@ -1,5 +1,3 @@ -module; - export module editor; export import :world; From d10d9edb6003049cb4caac54b6fa3ed734028f39 Mon Sep 17 00:00:00 2001 From: SpinnerX Date: Sun, 14 Jun 2026 16:31:28 -0700 Subject: [PATCH 106/106] fixed the right editor.cppm to be formatted correctly --- atlas/core/editor/editor.cppm | 1 - editor/editor.cppm | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/atlas/core/editor/editor.cppm b/atlas/core/editor/editor.cppm index f147ad61..936b7285 100644 --- a/atlas/core/editor/editor.cppm +++ b/atlas/core/editor/editor.cppm @@ -2,6 +2,5 @@ module; export module atlas.core.editor; - export import :menu_item; export import :dockspace; \ No newline at end of file diff --git a/editor/editor.cppm b/editor/editor.cppm index 764d9dd4..49dc3745 100644 --- a/editor/editor.cppm +++ b/editor/editor.cppm @@ -1,3 +1,5 @@ +module; + export module editor; export import :world;