-
Notifications
You must be signed in to change notification settings - Fork 0
feat: presenter #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
alexcu2718
wants to merge
11
commits into
alex_stuff
Choose a base branch
from
feat/presenter
base: alex_stuff
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
0342c90
chore: split frame from vulkan_context and add documentation to macros
gituser12981u2 32b664b
feat: replace fence with timeline semaphore for submit add request fe…
gituser12981u2 44c1ec1
feat: add global timeline semaphore and make queue based retirement s…
gituser12981u2 da54204
feat: add frame registry using the retirement system
gituser12981u2 a3f1035
feat: add vk12/vk13 and presenter builder abstraction
alexcu2718 953ff79
fix: attempt fix at CI on mac/windows
alexcu2718 859b2cf
fix: attempt fix at CI on mac/windows
alexcu2718 824ebb0
feat: add custom feature chain builder because MoltenVk needs a diffe…
gituser12981u2 c45eb79
feat: remove apple specific path from device_feature_chain_builder
gituser12981u2 349396b
fix: small edge case bugs
alexcu2718 56c7420
chore: remove separate physical API log and update main physical API …
gituser12981u2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| # RFC-0001 | ||
|
|
||
| **Status:** Draft | ||
| **Author:** | ||
| **Target:** Internal Engine Architecture | ||
| **Date:** March, 2026 | ||
|
|
||
| ## 1. Abstract | ||
|
|
||
| ## 2. Motivation | ||
|
|
||
| ## 3. Design Principles | ||
|
|
||
| The following principles guide this design: | ||
|
|
||
| ### 3.1 Shape over semantics | ||
|
|
||
| Concepts enforce type shape and API presence. | ||
|
|
||
| ### 3.2 Minimal Sufficiency | ||
|
|
||
| Concepts should require only what is necessary for correctness and interoperability. | ||
|
|
||
| ### 3.3 Non-intrusiveness | ||
|
|
||
| Concepts must not impose unnecessary contraints on layout, | ||
| performance, or implementation strategy. | ||
|
|
||
| ## 4 Concepts | ||
|
|
||
| ### 4.1 MoveOnlyNoexcept | ||
|
|
||
| #### 4.1.1 Definition | ||
|
|
||
| A type satisfying MoveOnlyNoexcept: | ||
|
|
||
| - Is moveable | ||
| - Is not copyable | ||
| - Has noexcept move construction and assignment | ||
|
|
||
| #### 4.1.2 Rationale | ||
|
|
||
| Registries and bundles represent ownership domains and must: | ||
|
|
||
| - Avoid accidental copying | ||
| - Be safely relocatable | ||
|
|
||
| Noexcept move is required to preserve strong exception safety | ||
| guarantees in higher-level systems. | ||
|
|
||
| #### 4.1.3 Specification | ||
|
|
||
| ```cpp | ||
| template <class T> | ||
| concept MoveOnlyNoexcept = | ||
| std::moveable<T> && | ||
| !std::copy_constructible<T> && | ||
| !std::copy_assignable_v<T> && | ||
| std::is_nothrow_move_constructible_v<T> && | ||
| std::is_nothrow_move_assignable_v<T>; | ||
| ``` | ||
|
|
||
| ### 4.2 RegistrySlot | ||
|
|
||
| #### 4.2.1 Definition | ||
|
|
||
| A type satisfying RegistrySlot: | ||
|
|
||
| - Tracks whether the slot is live | ||
| - Tracks the current generation of the slot | ||
|
|
||
| #### 4.2.2 Rationale | ||
|
|
||
| Slots represent storage locations for registry managed objects. | ||
| They must: | ||
|
|
||
| - Distinguish between live and free states | ||
| - Participate in generation-based validation | ||
|
|
||
| This enables: | ||
|
|
||
| - Detection of stale handles | ||
| - Safe reuse of slot indices | ||
|
|
||
| #### 4.2.3 Specification | ||
|
|
||
| ```cpp | ||
| template <class S> | ||
| concept RegistrySlot = | ||
| requires(S slot) { | ||
| { slot.live } -> std::convertible_to<bool>; | ||
| { slot.generation } -> std::convertible_to<uint32_t>; | ||
| }; | ||
| ``` | ||
|
|
||
| Layer 1: common concepts | ||
| • BundleLike | ||
|
|
||
| The following are explicitly out of scope for these concepts: | ||
| • Enforcing transactional creation | ||
| • Enforcing correct retirement semantics | ||
| • Preventing logical misuse of handles | ||
| • Guaranteeing destruction ordering | ||
| • Enforcing trivial move or standard layout | ||
|
|
||
| Layer 2: registry CRTP base | ||
|
|
||
| Responsible for: | ||
| • retire_queue_ | ||
| • slots_ | ||
| • free_ | ||
| • alive() | ||
| • allocate_handle_() | ||
| • get_slot_if_live_() | ||
| • retire_slot_() | ||
| • clear() | ||
|
|
||
| Layer 3: concrete registry | ||
|
|
||
| FrameRegistry implements: | ||
| • create() | ||
| • make_retired_payload_() | ||
| • retired payload destroy/cleanup trampolines | ||
| • frame-specific accessors |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| #pragma once | ||
|
|
||
| // TODO: replace with gpu timeline interface i.e. abstracted from vulkan | ||
| #include "quark/vk/sync/gpu_timeline.hpp" | ||
|
|
||
| #include <cstddef> | ||
| #include <cstdint> | ||
| #include <quark/utils/raii.hpp> | ||
| #include <quark/utils/result.hpp> | ||
| #include <vector> | ||
|
|
||
| namespace quark::vk { | ||
|
|
||
| /** | ||
| * @brief CPU-side deferred destruction queue keyed by a GPU timeline value. | ||
| * | ||
| * Each entry is scheduled with a retire value (retire_at) on a global timeline. | ||
| * It is safe to run the entry once completed_value() >= retire_at. | ||
| * | ||
| * Performance: | ||
| * - enqueue: O(1) | ||
| * - drain: O(k) where k is the number of ready items drained | ||
| * | ||
| * Invariant: | ||
| * - Internally maintains a monotonic retire_at sequence. | ||
| * If the caller enqueues an out-of-order retire_at, it is clamped | ||
| * to the last enqueued retire_at to preserve monotonicity and allow O(k) | ||
| * front-drain. | ||
| * | ||
| * Correctness assumptions: | ||
| * - All retire_at values refer to the same total order clock as timeline_. | ||
| * - destroy() is called only when it is safe to execute all pending callbacks | ||
| * (e.g. after vkDeviceWaitIdle()). | ||
| */ | ||
| class RetirementQueue final { | ||
| public: | ||
| /** | ||
| * @brief Type-erased task invoked on retirement. | ||
| * | ||
| * fn(ctx) is executed when the entry is drained. | ||
| * cleanup(ctx) is executed afterwards to free ctx memory. | ||
| */ | ||
| struct Task { | ||
| void (*fn)(void *ctx) noexcept = nullptr; | ||
| void (*cleanup)(void *ctx) noexcept = nullptr; | ||
| void *ctx = nullptr; | ||
| }; | ||
|
|
||
| struct CreateInfo { | ||
| const GpuTimeline *timeline = nullptr; | ||
|
|
||
| /// Optional; pre-reserve capacity | ||
| std::size_t reserve = 0; | ||
| }; | ||
|
|
||
| RetirementQueue() = default; | ||
| ~RetirementQueue() { destroy(); } | ||
|
|
||
| QUARK_MOVE_ONLY(RetirementQueue); | ||
|
|
||
| [[nodiscard]] util::Status create(const CreateInfo &ci); | ||
| void destroy() noexcept; | ||
|
|
||
| [[nodiscard]] bool valid() const noexcept { return timeline_ != nullptr; } | ||
|
|
||
| /** | ||
| * @brief Enqueue a task to run after retire_at is completed. | ||
| * | ||
| * Fast-path: | ||
| * - If retire_at <= timeline.completed_value(), task executed immediately. | ||
| * | ||
| * Ordering: | ||
| * - If retire_at < last_enqueued_retire_at_, it is clamped upward to | ||
| * last_enqueued_retire_at_ to preserver monotonicity. | ||
| * | ||
| * @return Status::OK on Success, or OutOfMemory if internal growth fails. | ||
| */ | ||
| [[nodiscard]] util::Status enqueue(uint64_t retire_at, Task task); | ||
|
|
||
| /** | ||
| * @brief Drain all ready tasks (completed_value >= retire_at). | ||
| * | ||
| * Runs tasks in FIFO order for the ready prefix. | ||
| * Does not block; it only checks timeline completed. | ||
| * | ||
| * @return the number of tasks executed. | ||
| */ | ||
| [[nodiscard]] util::Result<std::size_t> drain() noexcept; | ||
|
|
||
| /** | ||
| * @brief Number of tasks currently queued (including the ones not yet ready). | ||
| */ | ||
| [[nodiscard]] std::size_t pending() const noexcept { | ||
| return (entries_.size() >= head_) ? (entries_.size() - head_) : 0; | ||
| } | ||
|
|
||
| private: | ||
| struct Entry { | ||
| uint64_t retire_at = 0; | ||
| Task task{}; | ||
| }; | ||
|
|
||
| static void run_task_(Task &t) noexcept; | ||
|
|
||
| /** | ||
| * @brief Avoid O(n) erase every frame by compacting when head is large | ||
| * enough. | ||
| * | ||
| * Two Part Heuristic: | ||
| * 1) dead >= live, i.e. at least half the buffer is garbage, OR | ||
| * 2) dead is large enough to matter in absolute terms | ||
| */ | ||
| void compact_if_needed_() noexcept; | ||
|
|
||
| const GpuTimeline *timeline_ = nullptr; // non-owning | ||
|
|
||
| std::vector<Entry> entries_; | ||
| std::size_t head_ = 0; | ||
| uint64_t last_enqueued_retire_at_ = 0; | ||
| }; | ||
|
|
||
| } // namespace quark::vk |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.