253 Commits

Author SHA1 Message Date
kbz_8
3dd68f9942 merge indev into master (#84) 2024-09-14 00:45:30 +02:00
Kbz-8
ffe5704673 fixing compilation issues with GCC 2024-09-14 00:05:50 +02:00
kbz_8
20ec13d2b9 resolving merge (#83) 2024-09-13 23:54:58 +02:00
kbz_8
33d2b98c55 adding support for changing window position (#82)
added window move function
2024-09-12 21:00:40 +02:00
kbz_8
1adce43d9f fixing codestyle in application.inl 2024-09-12 03:32:08 +02:00
Tidian Delage
466050ee7a adding support for changing window position
mlx_set_window_position(void *mlx, void *win, int x, int y)
2024-09-12 01:32:52 +02:00
kbz_8
6bc505de13 update dependencies (#80)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-09-07 05:17:36 +02:00
Kbz-8
d70d748877 [BOT] update dependencies 2024-09-07 01:17:30 +00:00
kbz_8
5cda85d16c update dependencies (#79)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-09-02 09:42:20 +02:00
Kbz-8
9318456afb [BOT] update dependencies 2024-08-31 01:18:08 +00:00
kbz_8
40fe100ecc update dependencies (#75)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-08-22 23:13:32 +02:00
Kbz-8
c1bfc0f27d [BOT] update dependencies 2024-08-17 01:12:49 +00:00
kbz_8
5a09ebb179 Add <algorithm> header to fix compilation issue on Arch Linux (#76)
The code was failing to compile on Arch Linux due to missing definitions
from the <algorithm> header. Including this header resolves the issue,
ensuring compatibility across different environments.
2024-08-08 18:10:22 +02:00
bonsthie
8370ae8324 Add <algorithm> header to fix compilation issue on Arch Linux
The code was failing to compile on Arch Linux due to missing definitions from the <algorithm> header. Including this header resolves the issue, ensuring compatibility across different environments.
2024-08-08 17:49:14 +02:00
kbz_8
a4fcbf187b update dependencies (#74)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-07-20 09:58:01 +02:00
Kbz-8
b15aa648e2 [BOT] update dependencies 2024-07-19 15:46:30 +00:00
kbz_8
9a88a8502e update dependencies (#73)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-07-13 03:50:02 +02:00
Kbz-8
34a46d643a [BOT] update dependencies 2024-07-13 01:13:25 +00:00
kbz_8
359be83f49 update dependencies (#72)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-07-05 12:59:44 +02:00
Kbz-8
8c8c96bf30 [BOT] update dependencies 2024-07-02 01:12:05 +00:00
kbz_8
e30a243452 update dependencies (#71)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-07-01 22:07:45 +02:00
Kbz-8
f8e1cd4a66 [BOT] update dependencies 2024-06-29 01:10:23 +00:00
kbz_8
d5512b72fa update dependencies (#70)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-06-17 19:32:26 +02:00
Kbz-8
86f3d545ee [BOT] update dependencies 2024-06-15 01:10:51 +00:00
kbz_8
9149f42b95 update dependencies (#69)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-06-08 05:01:50 +02:00
Kbz-8
7aea6682f2 [BOT] update dependencies 2024-06-08 01:10:19 +00:00
kbz_8
d0ca0e4ab7 update dependencies (#68)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-06-04 14:44:26 +02:00
Kbz-8
f6dfed48dd [BOT] update dependencies 2024-06-01 01:13:48 +00:00
kbz_8
5a69dff9d7 update dependencies (#67)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-05-29 18:23:43 +02:00
Kbz-8
b7e2164f91 [BOT] update dependencies 2024-05-28 01:08:56 +00:00
kbz_8
273858ec8f update dependencies (#65)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-05-25 14:58:18 +02:00
Kbz-8
8f088eb76d [BOT] update dependencies 2024-05-23 01:08:01 +00:00
kbz_8
a7433a6570 🐛 fix(vsupp): dl and dbus errors suppressed (#66)
ehehheheheh
2024-05-22 18:53:36 +02:00
Arkturius
3ab445e780 🐛 fix(vsupp): dl and dbus errors suppressed 2024-05-22 18:30:59 +02:00
killian
dd554cce2a feature(Makefile): change color when compiling in debug 2024-04-24 15:00:22 +02:00
killian
a182b53d7f feature(Makefile): remove bc dependency, allow usage of -j with make re 2024-04-24 14:57:20 +02:00
Kbz-8
a5f85a8a4c fixing segmentation fault on mlx_destroy_image 2024-04-24 13:52:34 +02:00
kbz_8
ae6a86800e Cool Makefile I guess (#64)
yada yada yada
2024-04-23 22:52:09 +02:00
xtrm
b85e0444cb 🔨 chore: mauvaisfeedback 2024-04-23 22:46:32 +02:00
xtrm
fc33d33508 🔨 chore(actions): change usage of DEBUG=true to the debug rule 2024-04-23 20:42:39 +02:00
xtrm
14698594d8 🐛 fix(Makefile): optimize color usage 2024-04-23 20:38:26 +02:00
xtrm
024f3fefc3 🐛 fix(actions): try and fix logging in GitHub Actions CI 2024-04-23 20:37:17 +02:00
xtrm
33872806a1 🔨 chore(render_core.cpp): revert moving the warning to Makefile 2024-04-23 20:33:11 +02:00
xtrm
3b4a1de9f3 feature(Makefile): pretty makefile, added -rdynamic LDFLAG, moved debug warning, added debug Makefile rule 2024-04-23 20:21:53 +02:00
Kbz-8
5af4c82c1b fixing multiple window issue 2024-04-22 17:35:41 +02:00
kbz_8
e26af9ae1b update dependencies (#62)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-04-22 12:57:49 +02:00
Kbz-8
8c41eefadb [BOT] update dependencies 2024-04-22 01:07:14 +00:00
kbz_8
25d86eccee merge indev to master (#61) 2024-04-21 18:20:21 +02:00
kbz_8
2393261cb0 Merge branch 'master' into indev 2024-04-21 18:15:25 +02:00
kbz_8
d9d165f17e update dependencies (#60)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-04-21 18:14:31 +02:00
Kbz-8
f446c82780 fixing bug with window destruction within mlx_loop 2024-04-21 18:14:14 +02:00
Kbz-8
cc507ea4cf [BOT] update dependencies 2024-04-20 01:04:56 +00:00
Kbz-8
42fc7d9a86 working on fps capper 2024-03-25 17:33:42 +01:00
Kbz-8
60d3df7969 fixing new gcc warning in GPU allocator, fixing #55 2024-03-25 16:18:24 +01:00
Kbz-8
be52578d37 fixing some bad memory usage 2024-03-25 13:57:20 +01:00
kbz_8
57c5ae5415 update dependencies (#59)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-03-24 23:04:44 +01:00
Kbz-8
c6d6e409f1 [BOT] update dependencies 2024-03-23 01:01:59 +00:00
kbz_8
c0dfcd9244 update dependencies (#57)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-03-15 15:42:44 +01:00
Kbz-8
689608b3fe [BOT] update dependencies 2024-03-09 01:00:27 +00:00
kbz_8
04330a10ac The bro did it again (#54) 2024-02-25 09:40:47 +01:00
kbz_8
a456ad15ce Merge branch 'master' into indev 2024-02-25 09:35:31 +01:00
Kbz-8
e621bb53d4 removing debug print 2024-02-25 09:30:30 +01:00
kbz_8
420ba21b4d merge to master (#53) 2024-02-25 09:15:29 +01:00
Kbz-8
f3de55d6e9 fixing issue with text destruction 2024-02-25 09:02:57 +01:00
Kbz-8
bc1e0fbba9 adding std namespace to all libstd provided primitive types 2024-02-25 08:04:44 +01:00
Kbz-8
80c0146ecd removing unecessary SDL window creation in Vulkan Instance creation 2024-02-24 04:47:05 +01:00
Kbz-8
dbe3bb3cb3 fixing weird color bug with mlx_get_image_pixel 2024-02-24 03:58:12 +01:00
kbz_8
83ecc6e498 update dependencies (#50)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-02-18 21:42:23 +01:00
Kbz-8
8b2965f6dd [BOT] update dependencies 2024-02-17 01:02:17 +00:00
kbz_8
6c31d3347a sync (#49) 2024-02-10 03:12:08 +01:00
kbz_8
7f8ec481f1 Bump peter-evans/create-pull-request from 5 to 6 (#48)
Bumps
[peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request)
from 5 to 6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/peter-evans/create-pull-request/releases">peter-evans/create-pull-request's
releases</a>.</em></p>
<blockquote>
<h2>Create Pull Request v6.0.0</h2>
<h2>Behaviour changes</h2>
<ul>
<li>The default values for <code>author</code> and
<code>committer</code> have changed. See &quot;What's new&quot; below
for details. If you are overriding the default values you will not be
affected by this change.</li>
<li>On completion, the action now removes the temporary git remote
configuration it adds when using <code>push-to-fork</code>. This should
not affect you unless you were using the temporary configuration for
some other purpose after the action completes.</li>
</ul>
<h2>What's new</h2>
<ul>
<li>Updated runtime to Node.js 20
<ul>
<li>The action now requires a minimum version of <a
href="https://github.com/actions/runner/releases/tag/v2.308.0">v2.308.0</a>
for the Actions runner. Update self-hosted runners to v2.308.0 or later
to ensure compatibility.</li>
</ul>
</li>
<li>The default value for <code>author</code> has been changed to
<code>${{ github.actor }} &lt;${{ github.actor_id }}+${{ github.actor
}}@users.noreply.github.com&gt;</code>. The change adds the <code>${{
github.actor_id }}+</code> prefix to the email address to align with
GitHub's standard format for the author email address.</li>
<li>The default value for <code>committer</code> has been changed to
<code>github-actions[bot]
&lt;41898282+github-actions[bot]@users.noreply.github.com&gt;</code>.
This is to align with the default GitHub Actions bot user account.</li>
<li>Adds input <code>git-token</code>, the <a
href="https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token">Personal
Access Token (PAT)</a> that the action will use for git operations. This
input defaults to the value of <code>token</code>. Use this input if you
would like the action to use a different token for git operations than
the one used for the GitHub API.</li>
<li><code>push-to-fork</code> now supports pushing to sibling
repositories in the same network.</li>
<li>Previously, when using <code>push-to-fork</code>, the action did not
remove temporary git remote configuration it adds during execution. This
has been fixed and the configuration is now removed when the action
completes.</li>
<li>If the pull request body is truncated due to exceeding the maximum
length, the action will now suffix the body with the message
&quot;...<em>[Pull request body truncated]</em>&quot; to indicate that
the body has been truncated.</li>
<li>The action now uses <code>--unshallow</code> only when necessary,
rather than as a default argument of <code>git fetch</code>. This should
improve performance, particularly for large git repositories with
extensive commit history.</li>
<li>The action can now be executed on one GitHub server and create pull
requests on a <em>different</em> GitHub server. Server products include
GitHub hosted (github.com), GitHub Enterprise Server (GHES), and GitHub
Enterprise Cloud (GHEC). For example, the action can be executed on
GitHub hosted and create pull requests on a GHES or GHEC instance.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Update distribution by <a
href="https://github.com/actions-bot"><code>@​actions-bot</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2086">peter-evans/create-pull-request#2086</a></li>
<li>fix crazy-max/ghaction-import-gp parameters by <a
href="https://github.com/fharper"><code>@​fharper</code></a> in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2177">peter-evans/create-pull-request#2177</a></li>
<li>Update distribution by <a
href="https://github.com/actions-bot"><code>@​actions-bot</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2364">peter-evans/create-pull-request#2364</a></li>
<li>Use checkout v4 by <a
href="https://github.com/okuramasafumi"><code>@​okuramasafumi</code></a>
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2521">peter-evans/create-pull-request#2521</a></li>
<li>Note about <code>delete-branch</code> by <a
href="https://github.com/dezren39"><code>@​dezren39</code></a> in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2631">peter-evans/create-pull-request#2631</a></li>
<li>98 dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/fharper"><code>@​fharper</code></a> made
their first contribution in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2177">peter-evans/create-pull-request#2177</a></li>
<li><a
href="https://github.com/okuramasafumi"><code>@​okuramasafumi</code></a>
made their first contribution in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2521">peter-evans/create-pull-request#2521</a></li>
<li><a href="https://github.com/dezren39"><code>@​dezren39</code></a>
made their first contribution in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2631">peter-evans/create-pull-request#2631</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/create-pull-request/compare/v5.0.2...v6.0.0">https://github.com/peter-evans/create-pull-request/compare/v5.0.2...v6.0.0</a></p>
<h2>Create Pull Request v5.0.2</h2>
<p>⚙️ Fixes an issue that occurs when using <code>push-to-fork</code>
and both base and head repositories are in the same org/user
account.</p>
<h2>What's Changed</h2>
<ul>
<li>fix: specify head repo by <a
href="https://github.com/peter-evans"><code>@​peter-evans</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2044">peter-evans/create-pull-request#2044</a></li>
<li>20 dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/create-pull-request/compare/v5.0.1...v5.0.2">https://github.com/peter-evans/create-pull-request/compare/v5.0.1...v5.0.2</a></p>
<h2>Create Pull Request v5.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>fix: truncate body if exceeds max length by <a
href="https://github.com/peter-evans"><code>@​peter-evans</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/1915">peter-evans/create-pull-request#1915</a></li>
<li>12 dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/create-pull-request/compare/v5.0.0...v5.0.1">https://github.com/peter-evans/create-pull-request/compare/v5.0.0...v5.0.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b1ddad2c99"><code>b1ddad2</code></a>
feat: v6 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2717">#2717</a>)</li>
<li><a
href="bb809027fd"><code>bb80902</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.8 to 18.19.10
(<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2712">#2712</a>)</li>
<li><a
href="e0037d470c"><code>e0037d4</code></a>
build(deps): bump peter-evans/create-or-update-comment from 3 to 4 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2702">#2702</a>)</li>
<li><a
href="94b1f99e3a"><code>94b1f99</code></a>
build(deps): bump peter-evans/find-comment from 2 to 3 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2703">#2703</a>)</li>
<li><a
href="69c27eaf4a"><code>69c27ea</code></a>
build(deps-dev): bump ts-jest from 29.1.1 to 29.1.2 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2685">#2685</a>)</li>
<li><a
href="7ea722a0f6"><code>7ea722a</code></a>
build(deps-dev): bump prettier from 3.2.2 to 3.2.4 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2684">#2684</a>)</li>
<li><a
href="5ee839affd"><code>5ee839a</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.7 to 18.19.8
(<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2683">#2683</a>)</li>
<li><a
href="60fc256c67"><code>60fc256</code></a>
build(deps-dev): bump eslint-plugin-prettier from 5.1.2 to 5.1.3 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2660">#2660</a>)</li>
<li><a
href="0c67723361"><code>0c67723</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.5 to 18.19.7
(<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2661">#2661</a>)</li>
<li><a
href="4e288e851b"><code>4e288e8</code></a>
build(deps-dev): bump prettier from 3.1.1 to 3.2.2 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2659">#2659</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/peter-evans/create-pull-request/compare/v5...v6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=peter-evans/create-pull-request&package-manager=github_actions&previous-version=5&new-version=6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>
2024-02-05 23:17:30 +01:00
dependabot[bot]
25bb57a973 Bump peter-evans/create-pull-request from 5 to 6
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 5 to 6.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v5...v6)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-05 22:10:30 +00:00
kbz_8
39365f52a2 update dependencies (#47)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-02-02 15:21:14 +01:00
Kbz-8
fafc94248d [BOT] update dependencies 2024-02-02 01:03:23 +00:00
kbz_8
edeaff793a adding check to texture pointers (#46) 2024-01-26 12:11:47 +01:00
kbz_8
2d5758419f Merge branch 'master' into indev 2024-01-26 12:07:15 +01:00
kbz_8
ba063dae3b update dependencies (#45)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-01-26 12:01:23 +01:00
Kbz-8
e018cad851 adding check to texture pointers 2024-01-26 11:59:57 +01:00
Kbz-8
9ee8041710 [BOT] update dependencies 2024-01-26 01:04:35 +00:00
kbz_8
1b50e123c5 yes (#43) 2024-01-24 17:54:37 +01:00
kbz_8
77563b8449 Merge branch 'master' into indev 2024-01-24 17:49:53 +01:00
kbz_8
d0923320a3 yes 2024-01-24 17:49:38 +01:00
Kbz-8
d8cab7aa47 adding rule to gitignore 2024-01-20 08:54:28 +01:00
kbz_8
fcf4d3d030 improving descriptor sets and pools management (#41) 2024-01-20 08:53:13 +01:00
Kbz-8
05362905f7 improving descriptor sets and pools management 2024-01-20 08:46:50 +01:00
kbz_8
6866f2240e adding fps capper (#40) 2024-01-18 15:31:37 +01:00
kbz_8
1903104247 Merge branch 'master' into indev 2024-01-18 15:28:20 +01:00
Kbz-8
04db0a7441 adding fps capper 2024-01-18 15:25:13 +01:00
kbz_8
91cbb15b66 fixing texts allocation issues (#39) 2024-01-18 14:23:05 +01:00
kbz_8
eeded8c8bc Merge branch 'master' into indev 2024-01-18 13:59:37 +01:00
Kbz-8
58e687c952 fixing allocation issues with texts 2024-01-18 13:57:41 +01:00
Kbz-8
a0b536483a fixing shit 2024-01-17 07:41:15 +01:00
Kbz-8
de1e8ed563 i dont know chat i did i was high as f*ck 2024-01-17 05:30:38 +01:00
Kbz-8
a832c3ca40 fixing issue with swapchain recreation 2024-01-16 07:19:27 +01:00
kbz_8
575ee21c7a oh the misery (#38)
Fixed a bug and modified the example/main.c to test all mlx functions 

![image](https://github.com/seekrs/MacroLibX/assets/105780726/d9946f1f-4e97-453f-87a6-953ffd0ad52d)
2024-01-12 14:56:14 +01:00
Namonay
071bc4596b upgraded example to test all mlx functions 2024-01-12 04:25:12 +01:00
Namonay
178690cff3 Fixed mlx_mouse_move() not updating mouse position
Removed SDL_FlushEvent(SDL_MOUSEMOTION) preventing Input::update() from catching new mouse position after a mlx_mouse_move() call
2024-01-12 04:24:24 +01:00
kbz_8
1d566f74e3 Preventing some segfaults (#37)
![nerd](https://github.com/seekrs/MacroLibX/assets/105780726/74152e81-029a-4f35-afda-11e6411646bf)
2024-01-12 01:51:51 +01:00
Namonay
eaa1b9afd0 Merge branch 'seekrs:indev' into indev 2024-01-12 01:28:25 +01:00
Namonay
a2d40ce844 Added protections to THE bridge 2024-01-12 01:27:02 +01:00
Kbz-8
4dcdcde7d5 improving vsupp 2024-01-12 00:49:42 +01:00
kbz_8
8805f91bfd Indev (#36) 2024-01-11 15:53:39 +01:00
kbz_8
b5ca757189 Merge branch 'master' into indev 2024-01-11 15:48:15 +01:00
Kbz-8
c2d27c8434 fixing compilation error 2024-01-11 15:47:45 +01:00
Kbz-8
5f55dd9b9a fixing vsupp missing character 2024-01-11 15:46:11 +01:00
kbz_8
f044b9ab45 merge indev to master (#35) 2024-01-11 05:32:13 +01:00
kbz_8
8c6ad92f37 Merge branch 'master' into indev 2024-01-11 05:27:21 +01:00
Kbz-8
34bdb740c2 new text management, texts and textures are on the same level, new texture rendering management, fixing issues 2024-01-11 05:23:16 +01:00
Kbz-8
c485f039fb fixing color management issue with texts 2024-01-10 20:22:53 +01:00
Kbz-8
3c60e76094 adding xmake profiler option 2024-01-10 18:49:54 +01:00
kbz_8
39650b5c96 adding profiler (#34) 2024-01-10 18:48:52 +01:00
Kbz-8
0f16255240 fixing windows compilation issue 2024-01-10 18:37:14 +01:00
Kbz-8
91661fd206 adding profiler 2024-01-10 18:32:40 +01:00
kbz_8
6648bd427f Indev (#33)
Indev
2024-01-09 01:42:36 +01:00
Namonay
aa2d0be63f added back not so much 'unnecesary' include 2024-01-09 01:37:01 +01:00
Namonay
2b557d5be7 removed useless includes 🤓 2024-01-09 01:28:50 +01:00
Namonay
36fae5c7d1 update buid.sh 2024-01-09 01:01:31 +01:00
Namonay
68570910e3 Fixed brief typo 2024-01-09 00:31:39 +01:00
Kbz-8
697a5e7147 fixing norme issue in the example 2024-01-09 00:25:23 +01:00
Kbz-8
31073c116c fixing issue with vulkan queues on multiple GPU computers 2024-01-08 23:50:00 +01:00
Kbz-8
c6a024d911 fixing issue with fonts vulkan descriptor destroyed 2024-01-08 22:18:45 +01:00
kbz_8
66a1b44224 Better vk commands management (#31) 2024-01-07 01:49:40 +01:00
Kbz-8
f5c581d89c figin another MacOS compilation error 2024-01-07 01:45:12 +01:00
Kbz-8
765a04d9b5 fixing compilation issues 2024-01-07 01:40:19 +01:00
Kbz-8
ac054830b9 removing gdb garbage file 2024-01-07 01:35:18 +01:00
Kbz-8
ccbd7561f4 fixing better vk command buffers management 2024-01-07 01:34:02 +01:00
kbz_8
2859725257 update dependencies (#30)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2024-01-06 14:09:23 +01:00
Kbz-8
f18cce29b3 [BOT] update dependencies 2024-01-06 01:06:21 +00:00
Kbz-8
d9a7f337ba working on cmd resources management 2024-01-05 23:13:35 +01:00
Kbz-8
f8e619ad94 fixing 32bit vulkan issue 2024-01-04 12:27:31 +01:00
kbz_8
ea6450b308 yes (#29) 2024-01-03 15:49:18 +01:00
kbz_8
6df9c284b8 Merge branch 'better_vk_commands' into indev 2024-01-03 15:47:31 +01:00
Kbz-8
d6b3f5dcc2 fixing gitignore file 2024-01-03 15:45:24 +01:00
kbz_8
826740906f merge Indev to master (#28) 2024-01-03 15:38:38 +01:00
Kbz-8
2c1f5181bf fixing compilation issue 2024-01-03 15:33:46 +01:00
Kbz-8
e728926521 fixing windows compilation issue 2024-01-03 15:30:35 +01:00
kbz_8
04af533469 Merge branch 'master' into indev 2024-01-03 15:17:17 +01:00
Kbz-8
53048bd82a improving vulkan error messages 2024-01-03 15:15:38 +01:00
Kbz-8
d0a19c5312 adding greetings 2024-01-03 00:30:45 +01:00
Kbz-8
6e284fb9bc fixing the workflows 2024-01-03 00:07:38 +01:00
Kbz-8
ea87c32051 updating license year, fixing fetch dependencies script, adding VMA auto update, removing useless dependency in xmake build 2024-01-03 00:01:30 +01:00
kbz_8
d73ade4a85 Update fetch_dependencies.yml (#27) 2024-01-02 12:04:00 +01:00
kbz_8
67bfc73066 Merge branch 'master' into indev 2024-01-02 11:56:57 +01:00
kbz_8
8b44a3aa6e Update fetch_dependencies.yml 2024-01-02 11:56:10 +01:00
kbz_8
36f9fdd53b merge Indev to master (#26) 2024-01-02 11:46:45 +01:00
kbz_8
9c43069e5f debug fetch_dependencies.yml 2024-01-02 11:28:11 +01:00
Kbz-8
0b6e1717d9 adding note to README 2023-12-31 14:34:52 +01:00
Kbz-8
41f7b4ef4c working automated dependencies updates, polishing the CI 2023-12-31 14:17:24 +01:00
kbz_8
418791930c update dependencies (#25)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action
2023-12-31 13:48:27 +01:00
Kbz-8
0690ecacd8 debugging CI 2023-12-31 13:47:56 +01:00
Kbz-8
36f7efb679 update dependencies 2023-12-31 12:47:00 +00:00
Kbz-8
a52e33e697 debugging CI 2023-12-31 13:46:45 +01:00
Kbz-8
086c5402f5 debugging CI 2023-12-31 13:45:25 +01:00
Kbz-8
dd1bd43360 debugging CI 2023-12-31 13:44:37 +01:00
Kbz-8
d515ca5333 debugging CI 2023-12-31 13:41:09 +01:00
Kbz-8
eeb4695d6c debugging CI 2023-12-31 13:34:11 +01:00
Kbz-8
e94d3fd70f debugging CI 2023-12-31 13:31:22 +01:00
Kbz-8
e76f084625 debugging CI 2023-12-31 13:30:32 +01:00
Kbz-8
6e1fcb381a fixing compilation errors with local vulkan headers 2023-12-31 13:21:40 +01:00
Kbz-8
52c309a288 test automated dependencies updates 2023-12-31 13:12:37 +01:00
kbz_8
9ad28d7cf2 Kbz 8 patch 1 (#23) 2023-12-31 11:57:44 +01:00
kbz_8
5f21f0bcf9 Create dependabot.yml 2023-12-31 11:57:19 +01:00
kbz_8
066eec2cf3 merge Indev to master (#22)
yes
2023-12-31 01:41:39 +01:00
kbz_8
03e21227fa Merge branch 'master' into indev 2023-12-31 01:38:11 +01:00
Kbz-8
6f05728906 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH x2 2023-12-31 01:30:17 +01:00
Kbz-8
5edc36393a AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH 2023-12-31 01:27:37 +01:00
Kbz-8
af29fc7b39 I hate SDL_main on windows 2023-12-31 01:24:10 +01:00
Kbz-8
9795988e14 fuck SDL_main on windows 2023-12-31 01:14:17 +01:00
Kbz-8
4087fca980 fixing SDL issue on windows 2023-12-31 01:08:41 +01:00
Kbz-8
f3efb72a21 adding transparency support to pixel put 2023-12-28 16:59:36 +01:00
kbz_8
fc97445875 Update xmake.lua 2023-12-28 01:13:40 +01:00
Kbz-8
5babfde870 fixing issue when creating multiple mlx application with leaks in the first one 2023-12-28 01:06:03 +01:00
kbz_8
04ffce60cd adding frame capture feature (#21) 2023-12-25 16:18:42 +01:00
Kbz-8
9aaa26ddf5 fixing frame capture 2023-12-24 16:07:09 +01:00
Kbz-8
df12d08ad3 working on frame capture 2023-12-23 01:53:54 +01:00
Kbz-8
064f660852 adding possible new feature 2023-12-22 23:21:24 +01:00
Kbz-8
bf6389f9a7 adding CONTRIBUTIN.md 2023-12-22 01:24:55 +01:00
Kbz-8
cae3db0ebf fixing issue with static casts 2023-12-22 00:45:06 +01:00
Kbz-8
79b01a5007 adding error messages when using a corrupted window pointer, dropping SDL init responsability when running in sandbox 2023-12-21 00:28:53 +01:00
kbz_8
91927126f2 merge indev to master (#20) 2023-12-20 17:50:38 +01:00
kbz_8
6fb8932ba9 Merge branch 'master' into indev 2023-12-20 17:38:06 +01:00
Kbz-8
536cf4c420 working on better command buffers management 2023-12-20 16:35:52 +01:00
kbz_8
1b49794be6 Change github links to reflect organisation change (#19) 2023-12-20 01:03:42 +01:00
xtrm
25f73a6967 🐛 fix: change github links to reflect organisation change
Signed-off-by: xtrm <oss@xtrm.me>
2023-12-20 00:58:24 +01:00
kbz_8
b7424e7f92 Merge pull request #18 from 420verfl0w/errors-everywhere
Errors everywhere
2023-12-16 20:32:04 +01:00
Kbz-8
0b4b32b5ac removing GCC error 2023-12-16 20:20:51 +01:00
Kbz-8
1922b409dd adding error checks 2023-12-16 20:17:49 +01:00
Kbz-8
80e938c019 new branch for error management 2023-12-16 18:51:51 +01:00
Kbz-8
68d2c63694 fixing compilation error 2023-12-16 02:14:23 +01:00
Kbz-8
1386fe64cb updating readme 2023-12-16 02:11:54 +01:00
kbz_8
7fd0ccff94 Merge pull request #17 from 420verfl0w/indev
merge dev to master
2023-12-15 21:13:53 +01:00
Kbz-8
b28b144edb fixing issue when destroying an image in the loop hook, begenning single time command buffers manager 2023-12-15 21:08:46 +01:00
Kbz-8
8e33b2fa30 updating README 2023-12-15 18:08:22 +01:00
kbz_8
cebadef063 Merge pull request #16 from 420verfl0w/multiple-fonts
merge Multiple fonts in dev
2023-12-14 20:12:44 +01:00
kbz_8
57b27adf1a Merge branch 'indev' into multiple-fonts 2023-12-14 19:21:12 +01:00
Kbz-8
d08a97f55c adding multiple font support 2023-12-14 19:13:41 +01:00
kbz_8
c7ad6650d9 Merge pull request #15 from 420verfl0w/indev
removing buggy texture hash system
2023-12-14 14:44:10 +01:00
Kbz-8
ac91253f51 removing buggy texture hash system 2023-12-14 14:39:00 +01:00
kbz_8
3d939675e4 Merge pull request #14 from 420verfl0w/indev
merge dev to master
2023-12-14 13:56:28 +01:00
Kbz-8
11b1bd147d fixing issues with texture rendering 2023-12-14 13:51:17 +01:00
Kbz-8
c013237219 yes 2023-12-14 00:08:38 +01:00
kbz_8
8039638885 removed garbage file 2023-12-13 16:06:43 +01:00
Kbz-8
d56b224d42 working on font system 2023-12-13 00:33:34 +01:00
kbz_8
6ccf2a10d7 Merge pull request #13 from 420verfl0w/indev
Indev
2023-12-12 18:49:48 +01:00
kbz_8
cfd1aab9e3 Merge pull request #12 from 420verfl0w/macos-debug
Macos debug
2023-12-12 18:21:36 +01:00
Kbz-8
c5752f773e fixing CI 2023-12-12 18:12:41 +01:00
Kbz-8
f398126e08 fixing CI 2023-12-12 18:07:58 +01:00
Kbz-8
6c0d8829a5 macos debug 2023-12-12 18:04:27 +01:00
Kbz-8
cf3f16d832 macos debug 2023-12-12 17:58:49 +01:00
Kbz-8
b60ae54e34 macos debug 2023-12-12 17:47:10 +01:00
Kbz-8
7786b07eb8 adding message when vk res init fails 2023-12-12 15:53:57 +01:00
Kbz-8
90b1dac0f5 adding message when instance init fails 2023-12-12 15:46:47 +01:00
Kbz-8
3c52fd05f3 fixing run file and lib name on macos 2023-12-12 13:27:19 +01:00
Kbz-8
843d7f0fe2 removing unused files 2023-12-12 13:08:34 +01:00
Kbz-8
ea2014819d fxing macos libraries location issue 2023-12-12 13:08:00 +01:00
kbz_8
e458ef6401 Merge pull request #11 from 420verfl0w/indev
merge dev to master
2023-12-11 23:53:56 +01:00
kbz_8
0494ff14da Merge pull request #10 from 420verfl0w/indev
Indev
2023-12-11 20:41:15 +01:00
Kbz-8
c2c2dece61 fixing DLL API import error 2023-12-11 20:36:21 +01:00
Kbz-8
401e6d13f3 moving profile to API scope 2023-12-11 20:28:58 +01:00
kbz_8
2e5346a0ff Merge pull request #8 from 420verfl0w/vsupp-debug
Vsupp debug
2023-12-11 19:36:32 +01:00
kbz_8
ce5157a299 Merge pull request #7 from 420verfl0w/malloc-custom
improving custom malloc, removing unused code in input system
2023-12-11 19:35:38 +01:00
Kbz-8
b5ce2347f6 improving custom malloc, removing unused code in input system 2023-12-11 19:30:37 +01:00
Kbz-8
9e0a0df5ca removing error 2023-12-11 13:53:40 +01:00
Kbz-8
8f6f50c37f fixing vsupp issue, cleaning it 2023-12-11 13:40:05 +01:00
Kbz-8
c36de40f4a fixing warning issue with clang 2023-12-10 23:15:59 +01:00
Kbz-8
52ca0c0d1b suppress warnings 2023-12-10 23:12:22 +01:00
kbz_8
651a05c4bc Merge pull request #6 from 420verfl0w/indev
merge Indev to master
2023-12-09 23:41:55 +01:00
Kbz-8
1cfb8745e2 updating readmes 2023-12-09 23:33:02 +01:00
Kbz-8
b3f3a01ee6 updating readmes 2023-12-09 23:18:28 +01:00
kbz_8
4acd240737 Merge pull request #5 from 420verfl0w/indev
merge Indev to master
2023-12-09 18:13:55 +01:00
Kbz-8
b79b8da031 improving vsupp file 2023-12-09 18:02:30 +01:00
Kbz-8
bc7ef4484f improving vsupp file 2023-12-09 16:23:38 +01:00
Kbz-8
9db5515fb5 adding vsupp file 2023-12-09 15:46:32 +01:00
kbz_8
387a1f5632 Merge pull request #4 from 420verfl0w/windows-support
Merge windows support into dev
2023-12-09 13:40:45 +01:00
Kbz-8
0babc2235f Merge branch 'windows-support' of github.com:420verfl0w/MacroLibX into windows-support 2023-12-09 13:25:30 +01:00
Kbz-8
1a9a6ec6f8 adding build readme for xmake, fixing windows workflow 2023-12-09 13:24:40 +01:00
kbz_8
d59d9f285a removing exe file 2023-12-08 23:34:19 +01:00
kbz_8
d16af1c4a8 fixing windows dll issues 2023-12-08 23:33:26 +01:00
Kbz-8
5dcc2045d6 adding symbols to dll on windows 2023-12-08 19:13:25 +01:00
Kbz-8
19ce912afe adding symbols to dll on windows 2023-12-08 18:56:33 +01:00
Kbz-8
890e301b78 fixing cross compilation issue 2023-12-08 18:09:08 +01:00
Kbz-8
218a97e4ec debugging windows CI 2023-12-08 16:37:42 +01:00
Kbz-8
74e5e35f5a debugging windows CI 2023-12-08 15:57:45 +01:00
Kbz-8
e6298b1dc3 fixing syntax error in windows workflow 2023-12-08 14:48:28 +01:00
Kbz-8
df860a5a64 removing garbage files 2023-12-08 14:12:41 +01:00
Kbz-8
b22064035a adding xmake support and windows workflow 2023-12-08 14:11:48 +01:00
kbz_8
197c71021b Merge pull request #3 from 420verfl0w/indev
Merge from dev to master
2023-12-08 13:00:24 +01:00
Kbz-8
d5fa70d7ab fixing issue in 42 header 2023-12-08 12:56:59 +01:00
Kbz-8
fd8e98f1ce adding mouse wheel support 2023-12-08 12:24:20 +01:00
Kbz-8
0e10e5f8e1 removing garbage files 2023-12-07 23:20:25 +01:00
Kbz-8
689c9b3ed4 fixing memory leaks, begenning xmake support to build on windows 2023-12-07 23:19:56 +01:00
Kbz-8
ecd43dedc5 fixing weird X in logo 2023-11-25 14:26:05 +01:00
kbz_8
dea507ec0e Update README.md 2023-11-25 13:13:57 +01:00
561 changed files with 330294 additions and 22164 deletions

11
.github/dependabot.yml vendored git.filemode.normal_file
View File

@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"

29
.github/workflows/fetch_dependencies.yml vendored git.filemode.normal_file
View File

@@ -0,0 +1,29 @@
name: Fetch Dependencies
on:
schedule:
- cron: '0 0 * * *' # Runs daily
jobs:
update-dependencies:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Run Fetch Dependencies Script
run: cd scripts && bash ./fetch_dependencies.sh
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
title: update dependencies
commit-message: "[BOT] update dependencies"
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
signoff: false
base: indev
branch: auto_deps_updates
labels: |
automated

25
.github/workflows/greetings.yml vendored git.filemode.normal_file
View File

@@ -0,0 +1,25 @@
name: Greetings
on: [pull_request_target, issues]
jobs:
greeting:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: |
Hello! Thank you for filing an issue.
If this is a bug report, please include relevant logs to help us debug the problem (OS, MLX version, drivers installed, GPU type and vendor, ...)
pr-message: |
Hello! Thank you for your contribution.
If you are fixing a bug, please reference the issue number in the description.
If you are implementing a feature request, please explain all your changes in your pull request.

View File

@@ -35,8 +35,8 @@ jobs:
# Build the lib # Build the lib
- name: Build MacroLibX - name: Build MacroLibX
run: make -j run: make -j && make fclean && make debug
# Build the test # Build the example
- name: Build Test - name: Build Example
run: cd test && clang main.c ../libmlx.so -lSDL2 run: cd example && bash ./build.sh

View File

@@ -35,9 +35,9 @@ jobs:
# Build the lib # Build the lib
- name: Build MacroLibX - name: Build MacroLibX
run: make TOOLCHAIN=gcc -j run: make TOOLCHAIN=gcc -j && make fclean && make TOOLCHAIN=gcc debug
# Build the test # Build the example
- name: Build Test - name: Build Example
run: cd test && gcc main.c ../libmlx.so -lSDL2 run: cd example && bash ./build.sh

View File

@@ -29,21 +29,15 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
# Install system dependencies # Install system dependencies
- name: Install Vulkan SDK
uses: humbletim/install-vulkan-sdk@v1.1.1
with:
version: 1.3.204.1
cache: true
- name: Install Dependancies - name: Install Dependancies
run: | run: |
brew install SDL2 brew install SDL2
# Build the lib # Build the lib
- name: Build MacroLibX - name: Build MacroLibX
run: make -j run: make -j && make fclean && make debug
# Build the test # Build the example
- name: Build Test - name: Build Example
run: cd test && clang main.c ../libmlx.so -lSDL2 run: cd example && bash ./build.sh

56
.github/workflows/windows.yml vendored git.filemode.normal_file
View File

@@ -0,0 +1,56 @@
name: Windows (xmake)
on:
pull_request:
push:
paths-ignore:
- '.gitignore'
- 'LICENSE'
- 'README.md'
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [windows-latest]
arch: [x64]
mode: [release]
runs-on: ${{ matrix.os }}
if: "!contains(github.event.head_commit.message, 'ci skip')"
steps:
- name: Get current date as package key
id: cache_key
run: echo "key=$(date +'%W')" >> $GITHUB_OUTPUT
- name: Checkout repository
uses: actions/checkout@v4
# Force xmake to a specific folder (for cache)
- name: Set xmake env
run: echo "XMAKE_GLOBALDIR=${{ runner.workspace }}/xmake-global" >> $GITHUB_ENV
# Install xmake
- name: Setup xmake
uses: xmake-io/github-action-setup-xmake@v1
with:
xmake-version: branch@master
actions-cache-folder: .xmake-cache-W${{ steps.cache_key.outputs.key }}
# Update xmake repository (in order to have the file that will be cached)
- name: Update xmake repository
run: xmake repo --update
# Setup compilation mode and install project dependencies
- name: Configure xmake and install dependencies
run: xmake config --arch=${{ matrix.arch }} --mode=${{ matrix.mode }} --yes
# Build the mlx
- name: Build MacroLibX
run: xmake --yes
# Build the example
- name: Build Example
run: xmake build --yes Test

16
.gitignore vendored
View File

@@ -4,5 +4,19 @@
*.a *.a
*.so *.so
*.out *.out
*.dll
*.lib
*.exp
*.json
*.tmp
*.ilk
*.pdb
*.exe
*vgcore
*.gdb_history
.vs/
.xmake/
.cache/ .cache/
test/.gdb_history objs/
build/
example/Test

17
CONTRIBUTING.md git.filemode.normal_file
View File

@@ -0,0 +1,17 @@
# How to contribute to the MacroLibX
For any questions, suggestions or help [contact me](mailto:contact@kbz8.me)
## **Found a bug?**
* Avoid opening any new issues without having checked if your problem has already been reported. If there are no currently open issues that fit your problem's description, feel free to [add it](https://github.com/seekrs/MacroLibX/issues/new).
* When writing an issue make sure to include a clear title and description as well as having filled out all the necessary information: System info, OS, OS-Version, ...
* If possible add pictures of the issue.
## Contributing
Before thinking of adding a contribution, think. Is it necessary? Will this actually be a useful/required feature? Is your implementation good?
Provide clear and documented explanation as to what was changed.

View File

@@ -1,5 +1,5 @@
MIT License MIT License
Copyright (c) 2022-2023 kbz_8 Copyright (c) 2022-2024 kbz_8
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

112
Makefile
View File

@@ -3,89 +3,129 @@
# ::: :::::::: # # ::: :::::::: #
# Makefile :+: :+: :+: # # Makefile :+: :+: :+: #
# +:+ +:+ +:+ # # +:+ +:+ +:+ #
# By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ # # By: kiroussa <oss@xtrm.me> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ # # +#+#+#+#+#+ +#+ #
# Created: 2022/10/04 16:43:41 by maldavid #+# #+# # # Created: 2022/10/04 16:43:41 by maldavid #+# #+# #
# Updated: 2023/11/24 10:03:17 by maldavid ### ########.fr # # Updated: 2024/04/24 14:59:23 by kiroussa ### ########.fr #
# # # #
# **************************************************************************** # # **************************************************************************** #
NAME = libmlx.so NAME = libmlx.so
MAKE = make --no-print-directory
SRCS = $(wildcard $(addsuffix /*.cpp, ./src/core)) OS ?= $(shell uname -s)
SRCS += $(wildcard $(addsuffix /*.cpp, ./src/platform))
SRCS += $(wildcard $(addsuffix /*.cpp, ./src/renderer))
SRCS += $(wildcard $(addsuffix /*.cpp, ./src/renderer/**))
OBJ_DIR = objs
OBJS = $(addprefix $(OBJ_DIR)/, $(SRCS:.cpp=.o))
OS = $(shell uname -s)
DEBUG ?= false DEBUG ?= false
TOOLCHAIN ?= clang TOOLCHAIN ?= clang
IMAGES_OPTIMIZED ?= true IMAGES_OPTIMIZED ?= true
FORCE_INTEGRATED_GPU ?= false FORCE_INTEGRATED_GPU ?= false
GRAPHICS_MEMORY_DUMP ?= false GRAPHICS_MEMORY_DUMP ?= false
PROFILER ?= false
_ENABLEDFLAGS =
MODE = "release" SRCS = $(wildcard $(addsuffix /*.cpp, src/core))
SRCS += $(wildcard $(addsuffix /*.cpp, src/platform))
SRCS += $(wildcard $(addsuffix /*.cpp, src/renderer))
SRCS += $(wildcard $(addsuffix /*.cpp, src/renderer/**))
OBJ_DIR = objs/make/$(shell echo $(OS) | tr '[:upper:]' '[:lower:]')
OBJS := $(addprefix $(OBJ_DIR)/, $(SRCS:.cpp=.o))
CXX = clang++ CXX = clang++
CXXFLAGS = -std=c++17 -O3 -fPIC -Wall -Wextra -Werror -DSDL_MAIN_HANDLED
INCLUDES = -I./includes -I./src -I./third_party
ifeq ($(TOOLCHAIN), gcc) ifeq ($(TOOLCHAIN), gcc)
CXX = g++ CXX = g++
CXXFLAGS += -Wno-error=cpp
else
CXXFLAGS += -Wno-error=#warning
endif endif
CXXFLAGS = -std=c++17 -O3 -fPIC
INCLUDES = -I./includes -I./src -I./third_party
LDLIBS =
ifeq ($(OS), Darwin) ifeq ($(OS), Darwin)
LDLIBS += -lSDL2 LDFLAGS += -L /opt/homebrew/lib -lSDL2
CXXFLAGS += -I /opt/homebrew/include
NAME = libmlx.dylib
endif endif
ifeq ($(DEBUG), true) ifeq ($(DEBUG), true)
CXXFLAGS += -g -D DEBUG CXXFLAGS += -g3 -D DEBUG
MODE = "debug" LDFLAGS += -rdynamic
endif endif
ifeq ($(FORCE_INTEGRATED_GPU), true) ifeq ($(FORCE_INTEGRATED_GPU), true)
CXXFLAGS += -D FORCE_INTEGRATED_GPU _ENABLEDFLAGS += FORCE_INTEGRATED_GPU
endif endif
ifeq ($(IMAGES_OPTIMIZED), true) ifeq ($(IMAGES_OPTIMIZED), true)
CXXFLAGS += -D IMAGE_OPTIMIZED _ENABLEDFLAGS += IMAGE_OPTIMIZED
endif endif
ifeq ($(GRAPHICS_MEMORY_DUMP), true) ifeq ($(GRAPHICS_MEMORY_DUMP), true)
CXXFLAGS += -D GRAPHICS_MEMORY_DUMP _ENABLEDFLAGS += GRAPHICS_MEMORY_DUMP
endif endif
ifeq ($(PROFILER), true)
_ENABLEDFLAGS += PROFILER
endif
CXXFLAGS += $(addprefix -D, $(_ENABLEDFLAGS))
RM = rm -rf RM = rm -rf
TPUT = tput -T xterm-256color
_RESET := $(shell $(TPUT) sgr0)
_BOLD := $(shell $(TPUT) bold)
_ITALIC := $(shell $(TPUT) sitm)
_UNDER := $(shell $(TPUT) smul)
_GREEN := $(shell $(TPUT) setaf 2)
_YELLOW := $(shell $(TPUT) setaf 3)
_RED := $(shell $(TPUT) setaf 1)
_GRAY := $(shell $(TPUT) setaf 8)
_PURPLE := $(shell $(TPUT) setaf 5)
ifeq ($(DEBUG), true)
MODE := $(_RESET)$(_PURPLE)$(_BOLD)Debug$(_RESET)$(_PURPLE)
COLOR := $(_PURPLE)
else
MODE := $(_RESET)$(_GREEN)$(_BOLD)Release$(_RESET)$(_GREEN)
COLOR := $(_GREEN)
endif
OBJS_TOTAL = $(words $(OBJS))
N_OBJS := $(shell find $(OBJ_DIR) -type f -name '*.o' 2>/dev/null | wc -l)
OBJS_TOTAL := $(shell echo $$(( $(OBJS_TOTAL) - $(N_OBJS) )))
CURR_OBJ = 0
$(OBJ_DIR)/%.o: %.cpp $(OBJ_DIR)/%.o: %.cpp
@printf "\033[1;32m[compiling... "$(MODE)" "$(CXX)"]\033[1;00m "$<"\n" @mkdir -p $(dir $@)
@$(eval CURR_OBJ=$(shell echo $$(( $(CURR_OBJ) + 1 ))))
@$(eval PERCENT=$(shell echo $$(( $(CURR_OBJ) * 100 / $(OBJS_TOTAL) ))))
@printf "$(COLOR)($(_BOLD)%3s%%$(_RESET)$(COLOR)) $(_RESET)Compiling $(_BOLD)$<$(_RESET)\n" "$(PERCENT)"
@$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ @$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@
all: $(NAME) all: _printbuildinfos
@$(MAKE) $(NAME)
$(NAME): $(OBJ_DIR) $(OBJS) $(NAME): $(OBJS)
@printf "\033[1;32m[linking ... "$(MODE)"]\033[1;00m "$@"\n" @printf "Linking $(_BOLD)$(NAME)$(_RESET)\n"
@$(CXX) -shared -o $(NAME) $(OBJS) $(LDLIBS) @$(CXX) -shared -o $(NAME) $(OBJS) $(LDFLAGS)
@printf "\033[1;32m[build finished]\033[1;00m\n" @printf "$(_BOLD)$(NAME)$(_RESET) compiled $(COLOR)$(_BOLD)successfully$(_RESET)\n"
$(OBJ_DIR): _printbuildinfos:
@mkdir -p $(sort $(addprefix $(OBJ_DIR)/, $(dir $(SRCS)))) @printf "$(_PURPLE)$(_BOLD)MacroLibX $(_RESET)Compiling in $(_BOLD)$(MODE)$(_RESET) mode on $(_BOLD)$(OS)$(_RESET) | Using $(_BOLD)$(CXX)$(_RESET), flags: $(_BOLD)$(_ENABLEDFLAGS)$(_RESET)\n"
@printf "\033[1;32m[created objs directory]\033[1;00m\n"
debug:
@$(MAKE) all DEBUG=true -j$(shell nproc)
clean: clean:
@$(RM) $(OBJ_DIR) @$(RM) $(OBJ_DIR)
@printf "\033[1;32m[object files removed]\033[1;00m\n" @printf "Cleaned $(_BOLD)$(OBJ_DIR)$(_RESET)\n"
fclean: clean fclean: clean
@$(RM) $(NAME) @$(RM) $(NAME)
@printf "\033[1;32m["$(NAME)" removed]\033[1;00m\n" @printf "Cleaned $(_BOLD)$(NAME)$(_RESET)\n"
re: fclean all re: fclean _printbuildinfos
@$(MAKE) $(NAME)
.PHONY: all clean fclean re .PHONY: all clean debug fclean re

View File

@@ -1,23 +1,44 @@
<div align="center"> <div align="center">
<img src="./res/logo.png" alt="drawing" width="200"/> <img src="./res/logo.png" alt="drawing" width="200"/>
<div align="center"> <div align="center">
<a href="https://github.com/420verfl0w/MacroLibX/actions/workflows/linux_clang.yml"><img src="https://github.com/420verfl0w/MacroLibX/actions/workflows/linux_clang.yml/badge.svg"></a> <a href="https://github.com/seekrs/MacroLibX/actions/workflows/linux_clang.yml"><img src="https://github.com/seekrs/MacroLibX/actions/workflows/linux_clang.yml/badge.svg"></a>
<a href="https://github.com/420verfl0w/MacroLibX/actions/workflows/linux_gcc.yml"><img src="https://github.com/420verfl0w/MacroLibX/actions/workflows/linux_gcc.yml/badge.svg"></a> <a href="https://github.com/seekrs/MacroLibX/actions/workflows/linux_gcc.yml"><img src="https://github.com/seekrs/MacroLibX/actions/workflows/linux_gcc.yml/badge.svg"></a>
<a href="https://github.com/420verfl0w/MacroLibX/actions/workflows/macos_x86.yml"><img src="https://github.com/420verfl0w/MacroLibX/actions/workflows/macos_x86.yml/badge.svg"></a> <a href="https://github.com/seekrs/MacroLibX/actions/workflows/macos_x86.yml"><img src="https://github.com/seekrs/MacroLibX/actions/workflows/macos_x86.yml/badge.svg"></a>
</div>
<div align="center">
<a href="https://github.com/seekrs/MacroLibX/actions/workflows/windows.yml"><img src="https://github.com/seekrs/MacroLibX/actions/workflows/windows.yml/badge.svg"></a>
</div> </div>
</div> </div>
###### MacroLibX a rewrite of 42 School's MiniLibX using SDL2 and Vulkan. ###### MacroLibX, a rewrite of 42 School's MiniLibX using SDL2 and Vulkan.
The goal of this version is to provide a light, fast, and modern graphical tool while keeping the same API. The goal of this version is to provide a light, fast, and modern graphical tool while keeping the same API.
## 🌟 Features
### 🚀 Performances
Built on top of Vulkan, the MacroLibX takes advantage of its very low-level nature to achieve high performance with great control over available resources.
### 💻 Cross-Platform
Designed to be totally cross-platform, it can run on any SDL2-supported platform that supports Vulkan (even the Nintendo Switch ! theoretically... ).
### 🗿 Close to the old minilibx
One of the guidelines of this lib was to get as close as possible to the old minilibx API, and therefore to the educational choices of the old minilibx.
### 📖 It's all FOSS
Everything in this repo is entirely free and open source, all available under the MIT license (even the third-party libraries used).
### 🔍 Valgrind suppressions file
Experimental for now, a [suppressions file for valgrind](./valgrind.supp) is given to remove potential leaks comming from Xorg, Nvidia drivers, SDL2, or any other tool which the user has no control. It is far from perfect at the moment and may allow some leaks but it will block the majority.
### ⛔ Error system
Strong error handling informing the user of problems with their code and even capable of informing them of graphics memory leaks that tools like Valgrind cannot detect.
## 🖥️ Installation ## 🖥️ Installation
### Dependencies ### Dependencies
You first need to install the proper dependencies for your operating-system. You first need to install the proper dependencies for your operating-system.
#### 🐧 Linux #### 🐧 Linux
Here are a few common cases for different Linux distributions: Here are a few common cases for different Linux distributions:
<details> <details>
@@ -37,30 +58,28 @@ sudo apt install libsdl2-2.0-0 libsdl2-dev build-essential
<pre><code>sudo pacman -S sdl2</code></pre> <pre><code>sudo pacman -S sdl2</code></pre>
</details> </details>
#### 🍎 macOS <br>
Note that you need to have up do date video drivers with <code>libvulkan.so</code> installed.
#### 🍎 macOS
[MacroLibX](#) on macOS requires [SDL2](#) and [MoltenVK](https://github.com/KhronosGroup/MoltenVK). You can install both using the [Homebrew](https://brew.sh) package manager: [MacroLibX](#) on macOS requires [SDL2](#) and [MoltenVK](https://github.com/KhronosGroup/MoltenVK). You can install both using the [Homebrew](https://brew.sh) package manager:
```sh ```sh
brew install molten-vk brew install molten-vk
brew install SDL2 brew install SDL2
``` ```
### Clone and Build ### 🪟 Windows
To build on Windows you may need to use the [xmake](https://xmake.io) build. [Here's](./XMAKE_BUILD.md) how you can use it.
### Clone and Build
Finally, you can clone the Git repository. When inside it, run the GNU `make` command to compile MacroLibX. Finally, you can clone the Git repository. When inside it, run the GNU `make` command to compile MacroLibX.
```bash ```bash
git clone https://github.com/420verfl0w/MacroLibX.git git clone https://github.com/seekrs/MacroLibX.git
cd MacroLibX cd MacroLibX
make make
``` ```
If you want to build using GCC you can add `TOOLCHAIN=gcc` to your `make` command
```bash
make TOOLCHAIN=gcc
```
## 🔨 Compile your project ## 🔨 Compile your project
To compile your project with MacroLibX, you just provide the shared library path in your compilation/linking command: To compile your project with MacroLibX, you just provide the shared library path in your compilation/linking command:
```sh ```sh
@@ -73,17 +92,22 @@ And you can enjoy your project
<img src="./res/screenshot_test.png" alt="drawing" width="400"/> <img src="./res/screenshot_test.png" alt="drawing" width="400"/>
</p> </p>
### ⚠️ Troubleshooting ## ⚙️ Some compilation configurations
#### If you run into glitches when writing or reading pixels from images ### 📦 Compile mode
By default the mlx is built in release mode but you can switch to debug by using `make DEBUG=true`.
You need to add `IMAGES_OPTIMIZED=false` to your `make` command: ### 🛠️ Set the toolchain
If you want to use `GCC` to build the mlx you can use `make TOOLCHAIN=gcc`
```sh ### ⚠️⚠️⚠️ 🖼️ Image optimisations ⚠️⚠️⚠️
# In your cloned environment, inside the MacroLibX folder If you run into glitches when writing or reading pixels from images you can turn off images optimisations by using `make IMAGES_OPTIMIZED=false`.
make IMAGES_OPTIMIZED=false
``` ### 🖥️ Force the integrated GPU (not recommended)
You can force the mlx to use your integrated GPU by using `make FORCE_INTEGRATED_GPU=true`. Note that there are a lot of chances that your application crashes by using that.
### 💽 Dump the graphics memory
The mlx can dump it's graphics memory use to json files every two seconds by enabling this option `make GRAPHICS_MEMORY_DUMP=true`.
## License ## License
This project and all its files, even the [`third_party`](./third_party) directory or unless otherwise mentionned, are licenced under the [MIT license](./LICENSE).
This project and all its files, except the [`third_party`](./third_party) directory or unless otherwise mentionned, are licenced under the [MIT license](./LICENSE).

47
XMAKE_BUILD.md git.filemode.normal_file
View File

@@ -0,0 +1,47 @@
# 🏗️ xmake build
To build on Windows (if you don't use [WSL](https://learn.microsoft.com/en-us/windows/wsl/install)), the MacroLibX uses [xmake](https://xmake.io), a build system which will download and compile all dependencies it won't find on your computer.
## 💾 Install xmake
You can find how to install it on your system [here](https://xmake.io/#/guide/installation). Note that you can also download a [portable version](https://github.com/xmake-io/xmake/releases) of xmake if you wish not to install it.
## ⚙️ Configure the MacroLibX build
Just as the Makfile build system, you can configure how xmake should build the MacroLibX. The base command to configure it is `xmake config [opts...]` or `xmake f [opts...]`.
### 📦 Compile mode
You can configure xmake to build the mlx in debug mode or in release mode (release mode is enabled by default). To do so you can use `xmake config --mode=debug` or `xmake config --mode=release`.
### 🛠️ Set the toolchain
To change the compilation toolchain you can use `xmake config --toolchain=[gcc|clang|...]`
### ⚠️⚠️⚠️ 🖼️ Image optimisations ⚠️⚠️⚠️
If you run into glitches when writing or reading pixels from images you can turn off images optimisations by using `xmake config --images_optimized=n`.
### 🖥️ Force the integrated GPU (not recommended)
You can force the mlx to use your integrated GPU using `xmake config --force_integrated_gpu=y`. Note that there are a lot of chances that your application crashes by using that.
### 💽 Dump the graphics memory
The mlx can dump it's graphics memory use to json files every two seconds by enabling this option `xmake config --graphics_memory_dump=y`.
### 🪛 A possible build configuration
As a configuration example here's how the command can look like `xmake config --mode=debug --toolchain=clang --graphics_memory_dump=y --images_optimized=n`
## 🚧 Build the lib
### Compile using command-line (first method)
Once you're ready to compile the lib, run `xmake` (or `xmake -jX` if you wish not to use all your computer threads, with X being the number of threads you wish to use) and watch as the lib compiles.
### Generate a project (second method)
xmake can also generate a project file for another tool:
* Visual Studio : `xmake project -k vs`
* CMakeLists.txt (which you can open in CLion and more) : `xmake project -k cmake`
* Makefile : `xmake project -k make`
* Ninja : `xmake project -k ninja`
* XCode : `xmake project -k xcode`
You should now be able to open the project file with the tool of your choice.
## 😋 Enjoy
Enjoy you project built with the mlx
<p align="center">
<img src="./res/screenshot_test_windows.png" alt="drawing" width="400"/>
</p>

File diff suppressed because it is too large Load Diff

BIN
example/42_logo.bmp git.filemode.normal_file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
example/42_logo.jpg git.filemode.normal_file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

12
example/build.sh git.filemode.executable_file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
if [ -e a.out ]; then
rm a.out
fi
if [ $(uname -s) = 'Darwin' ]; then
clang main.c ../libmlx.dylib -L /opt/homebrew/lib -lSDL2 -g;
else
clang main.c ../libmlx.so -lSDL2 -g -Wall -Wextra -Werror;
fi

182
example/main.c git.filemode.normal_file
View File

@@ -0,0 +1,182 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 17:55:21 by maldavid #+# #+# */
/* Updated: 2024/03/25 16:16:07 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <stdio.h>
#include "../includes/mlx.h"
typedef struct
{
void* mlx;
void* win;
void* logo_png;
void* logo_jpg;
void* logo_bmp;
void* img;
} mlx_t;
//void* img = NULL;
int update(void* param)
{
static int i = 0;
mlx_t* mlx = (mlx_t*)param;
if(i == 200)
mlx_clear_window(mlx->mlx, mlx->win);
/*
if(img)
mlx_destroy_image(mlx->mlx,img);
img = mlx_new_image(mlx->mlx, 800, 800);
mlx_set_image_pixel(mlx->mlx, img, 4, 4, 0xFF00FF00);
mlx_put_image_to_window(mlx->mlx, mlx->win, img, 0, 0);
*/
if(i >= 250)
mlx_set_font_scale(mlx->mlx, mlx->win, "default", 16.f);
else
mlx_set_font_scale(mlx->mlx, mlx->win, "default", 6.f);
mlx_string_put(mlx->mlx, mlx->win, 160, 120, 0xFFFF2066, "this text should be hidden");
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo_png, 100, 100);
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo_jpg, 210, 150);
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->logo_bmp, 220, 40);
mlx_put_image_to_window(mlx->mlx, mlx->win, mlx->img, 150, 60);
mlx_set_font(mlx->mlx, mlx->win, "default");
mlx_string_put(mlx->mlx, mlx->win, 20, 50, 0xFFFFFFFF, "that's a text");
int color = 0;
for(int j = 0; j < 400; j++)
{
mlx_pixel_put(mlx->mlx, mlx->win, j, j, 0xFFFF0000 + color);
mlx_pixel_put(mlx->mlx, mlx->win, 399 - j, j, 0xFF0000FF);
color += (color < 255);
}
i++;
return 0;
}
void* create_image(mlx_t* mlx)
{
unsigned char pixel[4];
void* img = mlx_new_image(mlx->mlx, 100, 100);
for(int i = 0, j = 0, k = 0; i < (100 * 100) * 4; i += 4, j++)
{
if(j >= 100)
{
j = 0;
k++;
}
if(i < 10000 || i > 20000)
{
pixel[0] = i;
pixel[1] = j;
pixel[2] = k;
pixel[3] = 0x99;
mlx_set_image_pixel(mlx->mlx, img, j, k, *((int *)pixel));
}
}
return img;
}
int key_hook(int key, void* param)
{
int x;
int y;
mlx_t* mlx = (mlx_t*)param;
mlx_mouse_get_pos(mlx->mlx, &x, &y);
switch(key)
{
case 41 : // ESCAPE
mlx_loop_end(mlx->mlx);
break;
case 22 : // (S)how
mlx_mouse_show();
break;
case 11 : // (H)ide
mlx_mouse_hide();
break;
case 6 : // (C)lear
mlx_clear_window(mlx->mlx, mlx->win);
break;
case 79 : // RIGHT KEY
mlx_mouse_move(mlx->mlx, mlx->win, x + 10, y);
break;
case 80 : // LEFT KEY
mlx_mouse_move(mlx->mlx, mlx->win, x - 10, y);
break;
case 81 : // UP KEY
mlx_mouse_move(mlx->mlx, mlx->win, x, y + 10);
break;
case 82 : // DOWN KEY
mlx_mouse_move(mlx->mlx, mlx->win, x, y - 10);
break;
default : break;
}
return 0;
}
int window_hook(int event, void* param)
{
if(event == 0)
mlx_loop_end(((mlx_t*)param)->mlx);
return 0;
}
int main(void)
{
mlx_t mlx;
int w;
int h;
int dummy;
mlx.mlx = mlx_init();
mlx.win = mlx_new_window(mlx.mlx, 400, 400, "My window");
mlx_set_fps_goal(mlx.mlx, 60);
mlx_on_event(mlx.mlx, mlx.win, MLX_KEYDOWN, key_hook, &mlx);
mlx_on_event(mlx.mlx, mlx.win, MLX_WINDOW_EVENT, window_hook, &mlx);
mlx.logo_png = mlx_png_file_to_image(mlx.mlx, "42_logo.png", &dummy, &dummy);
mlx.logo_bmp = mlx_bmp_file_to_image(mlx.mlx, "42_logo.bmp", &dummy, &dummy);
mlx.logo_jpg = mlx_jpg_file_to_image(mlx.mlx, "42_logo.jpg", &dummy, &dummy);
mlx_pixel_put(mlx.mlx, mlx.win, 200, 10, 0xFFFF00FF);
mlx_put_image_to_window(mlx.mlx, mlx.win, mlx.logo_png, 10, 190);
mlx.img = create_image(&mlx);
mlx_string_put(mlx.mlx, mlx.win, 0, 10, 0xFFFFFF00, "fps:");
mlx_string_put(mlx.mlx, mlx.win, 0, 20, 0xFFFFFFFF, "fps:");
mlx_set_font_scale(mlx.mlx, mlx.win, "font.ttf", 16.f);
mlx_string_put(mlx.mlx, mlx.win, 20, 20, 0xFF0020FF, "that text will disappear");
mlx_loop_hook(mlx.mlx, update, &mlx);
mlx_loop(mlx.mlx);
mlx_get_screens_size(mlx.mlx, mlx.win, &w, &h);
printf("screen size : %dx%d\n", w, h);
mlx_destroy_image(mlx.mlx, mlx.logo_png);
mlx_destroy_image(mlx.mlx, mlx.logo_jpg);
mlx_destroy_image(mlx.mlx, mlx.logo_bmp);
mlx_destroy_image(mlx.mlx, mlx.img);
mlx_destroy_window(mlx.mlx, mlx.win);
mlx_destroy_display(mlx.mlx);
return 0;
}

4
example/run.sh git.filemode.executable_file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
bash ./build.sh
./a.out

View File

@@ -6,15 +6,18 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 16:56:35 by maldavid #+# #+# */ /* Created: 2022/10/04 16:56:35 by maldavid #+# #+# */
/* Updated: 2023/11/23 14:32:06 by maldavid ### ########.fr */ /* Updated: 2024/09/12 01:28:12 by tdelage ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
// MacroLibX official repo https://github.com/420verfl0w/MacroLibX // MacroLibX official repo https://github.com/seekrs/MacroLibX
// MacroLibX official website https://macrolibx.kbz8.me/
#ifndef __MACRO_LIB_X_H__ #ifndef __MACRO_LIB_X_H__
#define __MACRO_LIB_X_H__ #define __MACRO_LIB_X_H__
#include "mlx_profile.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -25,15 +28,18 @@ typedef enum
MLX_KEYUP = 1, MLX_KEYUP = 1,
MLX_MOUSEDOWN = 2, MLX_MOUSEDOWN = 2,
MLX_MOUSEUP = 3, MLX_MOUSEUP = 3,
MLX_WINDOW_EVENT = 4 MLX_MOUSEWHEEL = 4,
MLX_WINDOW_EVENT = 5
} mlx_event_type; } mlx_event_type;
/** /**
* @brief Initializes the MLX internal application * @brief Initializes the MLX internal application
* *
* @return (void*) An opaque pointer to the internal MLX application or NULL (0x0) in case of error * @return (void*) An opaque pointer to the internal MLX application or NULL (0x0) in case of error
*/ */
void* mlx_init(); MLX_API void* mlx_init();
/** /**
* @brief Creates a new window * @brief Creates a new window
@@ -45,7 +51,19 @@ void* mlx_init();
* *
* @return (void*) An opaque pointer to the internal MLX window or NULL (0x0) in case of error * @return (void*) An opaque pointer to the internal MLX window or NULL (0x0) in case of error
*/ */
void* mlx_new_window(void* mlx, int w, int h, const char* title); MLX_API void* mlx_new_window(void* mlx, int w, int h, const char* title);
/**
* @brief Creates a new window
*
* @param mlx Internal MLX application
* @param win Internal window to move
* @param x New x position
* @param y New y position
*
*/
MLX_API void mlx_set_window_position(void *mlx, void *win, int x, int y);
/** /**
* @brief Gives a function to be executed at each loop turn * @brief Gives a function to be executed at each loop turn
@@ -56,8 +74,8 @@ void* mlx_new_window(void* mlx, int w, int h, const char* title);
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
MLX_API int mlx_loop_hook(void* mlx, int (*f)(void*), void* param);
int mlx_loop_hook(void* mlx, int (*f)(), void* param);
/** /**
* @brief Starts the internal main loop * @brief Starts the internal main loop
@@ -66,7 +84,8 @@ int mlx_loop_hook(void* mlx, int (*f)(), void* param);
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_loop(void* mlx); MLX_API int mlx_loop(void* mlx);
/** /**
* @brief Ends the internal main loop * @brief Ends the internal main loop
@@ -75,21 +94,24 @@ int mlx_loop(void* mlx);
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_loop_end(void* mlx); MLX_API int mlx_loop_end(void* mlx);
/** /**
* @brief Shows mouse cursor * @brief Shows mouse cursor
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_mouse_show(); MLX_API int mlx_mouse_show();
/** /**
* @brief Hides mouse cursor * @brief Hides mouse cursor
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_mouse_hide(); MLX_API int mlx_mouse_hide();
/** /**
* @brief Moves cursor to givent position * @brief Moves cursor to givent position
@@ -101,7 +123,8 @@ int mlx_mouse_hide();
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_mouse_move(void* mlx, void* win, int x, int y); MLX_API int mlx_mouse_move(void* mlx, void* win, int x, int y);
/** /**
* @brief Get cursor's position * @brief Get cursor's position
@@ -112,7 +135,7 @@ int mlx_mouse_move(void* mlx, void* win, int x, int y);
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_mouse_get_pos(void* mlx, int* x, int* y); MLX_API int mlx_mouse_get_pos(void* mlx, int* x, int* y);
/** /**
@@ -126,7 +149,7 @@ int mlx_mouse_get_pos(void* mlx, int* x, int* y);
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_on_event(void* mlx, void* win, mlx_event_type event, int (*f)(), void* param); MLX_API int mlx_on_event(void* mlx, void* win, mlx_event_type event, int (*f)(int, void*), void* param);
/** /**
@@ -136,14 +159,14 @@ int mlx_on_event(void* mlx, void* win, mlx_event_type event, int (*f)(), void* p
* @param win Internal window * @param win Internal window
* @param x X coordinate * @param x X coordinate
* @param y Y coordinate * @param y Y coordinate
* @param color Color of the pixel (coded on 3 bytes in an int, 0x00RRGGBB) * @param color Color of the pixel (coded on 4 bytes in an int, 0xAARRGGBB)
* *
* Note : If your're reading pixel colors from an image, don't forget to shift them * Note : If your're reading pixel colors from an image, don't forget to shift them
* one byte to the right as image pixels are encoded as 0xRRGGBBAA and pixel put takes 0x00RRGGBB. * one byte to the right as image pixels are encoded as 0xRRGGBBAA and pixel put takes 0xAARRGGBB.
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_pixel_put(void* mlx, void* win, int x, int y, int color); MLX_API int mlx_pixel_put(void* mlx, void* win, int x, int y, int color);
/** /**
@@ -155,7 +178,8 @@ int mlx_pixel_put(void* mlx, void* win, int x, int y, int color);
* *
* @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error * @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error
*/ */
void* mlx_new_image(void* mlx, int width, int height); MLX_API void* mlx_new_image(void* mlx, int width, int height);
/** /**
* @brief Get image pixel data * @brief Get image pixel data
@@ -170,12 +194,13 @@ void* mlx_new_image(void* mlx, int width, int height);
* /!\ If you run into glitches when writing or reading pixels from images /!\ * /!\ If you run into glitches when writing or reading pixels from images /!\
* You need to add IMAGES_OPTIMIZED=false to your make mlx command * You need to add IMAGES_OPTIMIZED=false to your make mlx command
* ``` * ```
* ~ git clone https://github.com/420verfl0w/MacroLibX.git * ~ git clone https://github.com/seekrs/MacroLibX.git
* ~ cd MacroLibX * ~ cd MacroLibX
* ~ make IMAGES_OPTIMIZED=false * ~ make IMAGES_OPTIMIZED=false
* ``` * ```
*/ */
int mlx_get_image_pixel(void* mlx, void* img, int x, int y); MLX_API int mlx_get_image_pixel(void* mlx, void* img, int x, int y);
/** /**
* @brief Set image pixel data * @brief Set image pixel data
@@ -191,12 +216,13 @@ int mlx_get_image_pixel(void* mlx, void* img, int x, int y);
* /!\ If you run into glitches when writing or reading pixels from images /!\ * /!\ If you run into glitches when writing or reading pixels from images /!\
* You need to add IMAGES_OPTIMIZED=false to your make mlx command * You need to add IMAGES_OPTIMIZED=false to your make mlx command
* ``` * ```
* ~ git clone https://github.com/420verfl0w/MacroLibX.git * ~ git clone https://github.com/seekrs/MacroLibX.git
* ~ cd MacroLibX * ~ cd MacroLibX
* ~ make IMAGES_OPTIMIZED=false * ~ make IMAGES_OPTIMIZED=false
* ``` * ```
*/ */
void mlx_set_image_pixel(void* mlx, void* img, int x, int y, int color); MLX_API void mlx_set_image_pixel(void* mlx, void* img, int x, int y, int color);
/** /**
* @brief Put image to the given window * @brief Put image to the given window
@@ -209,7 +235,8 @@ void mlx_set_image_pixel(void* mlx, void* img, int x, int y, int color);
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_put_image_to_window(void* mlx, void* win, void* img, int x, int y); MLX_API int mlx_put_image_to_window(void* mlx, void* win, void* img, int x, int y);
/** /**
* @brief Destroys internal image * @brief Destroys internal image
@@ -219,7 +246,7 @@ int mlx_put_image_to_window(void* mlx, void* win, void* img, int x, int y);
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_destroy_image(void* mlx, void* img); MLX_API int mlx_destroy_image(void* mlx, void* img);
/** /**
@@ -232,7 +259,8 @@ int mlx_destroy_image(void* mlx, void* img);
* *
* @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error * @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error
*/ */
void* mlx_png_file_to_image(void* mlx, char* filename, int* width, int* height); MLX_API void* mlx_png_file_to_image(void* mlx, char* filename, int* width, int* height);
/** /**
* @brief Create a new image from a jpg file * @brief Create a new image from a jpg file
@@ -244,7 +272,8 @@ void* mlx_png_file_to_image(void* mlx, char* filename, int* width, int* height);
* *
* @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error * @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error
*/ */
void* mlx_jpg_file_to_image(void* mlx, char* filename, int* width, int* height); MLX_API void* mlx_jpg_file_to_image(void* mlx, char* filename, int* width, int* height);
/** /**
* @brief Create a new image from a bmp file * @brief Create a new image from a bmp file
@@ -256,7 +285,7 @@ void* mlx_jpg_file_to_image(void* mlx, char* filename, int* width, int* height);
* *
* @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error * @return (void*) An opaque pointer to the internal image or NULL (0x0) in case of error
*/ */
void* mlx_bmp_file_to_image(void* mlx, char* filename, int* width, int* height); MLX_API void* mlx_bmp_file_to_image(void* mlx, char* filename, int* width, int* height);
/** /**
@@ -266,12 +295,12 @@ void* mlx_bmp_file_to_image(void* mlx, char* filename, int* width, int* height);
* @param win Internal window * @param win Internal window
* @param x X coordinate * @param x X coordinate
* @param y Y coordinate * @param y Y coordinate
* @param color Color of the pixel (coded on 3 bytes in an int, 0x00RRGGBB) * @param color Color of the pixel (coded on 4 bytes in an int, 0xAARRGGBB)
* @param str Text to put * @param str Text to put
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_string_put(void* mlx, void* win, int x, int y, int color, char* str); MLX_API int mlx_string_put(void* mlx, void* win, int x, int y, int color, char* str);
/** /**
@@ -279,23 +308,24 @@ int mlx_string_put(void* mlx, void* win, int x, int y, int color, char* str);
* *
* @param mlx Internal MLX application * @param mlx Internal MLX application
* @param win Internal window * @param win Internal window
* @param filepath Filepath to the font * @param filepath Filepath to the font or "default" to reset to the embedded font
* *
* @return (void) * @return (void)
*/ */
void mlx_set_font(void* mlx, void* win, char* filepath); MLX_API void mlx_set_font(void* mlx, void* win, char* filepath);
/** /**
* @brief Loads a font to be used by `mlx_string_put` and scales it * @brief Loads a font to be used by `mlx_string_put` and scales it
* *
* @param mlx Internal MLX application * @param mlx Internal MLX application
* @param win Internal window * @param win Internal window
* @param filepath Filepath to the font * @param filepath Filepath to the font or "default" to reset to the embedded font
* @param scale Scale to apply to the font * @param scale Scale to apply to the font
* *
* @return (void) * @return (void)
*/ */
void mlx_set_font_scale(void* mlx, void* win, char* filepath, float scale); MLX_API void mlx_set_font_scale(void* mlx, void* win, char* filepath, float scale);
/** /**
@@ -306,7 +336,7 @@ void mlx_set_font_scale(void* mlx, void* win, char* filepath, float scale);
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_clear_window(void* mlx, void* win); MLX_API int mlx_clear_window(void* mlx, void* win);
/** /**
@@ -317,7 +347,7 @@ int mlx_clear_window(void* mlx, void* win);
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_destroy_window(void* mlx, void* win); MLX_API int mlx_destroy_window(void* mlx, void* win);
/** /**
* @brief Destroy internal MLX application * @brief Destroy internal MLX application
@@ -326,19 +356,31 @@ int mlx_destroy_window(void* mlx, void* win);
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_destroy_display(void* mlx); MLX_API int mlx_destroy_display(void* mlx);
/** /**
* @brief Get screen size * @brief Get the size of the screen the given window is on
* *
* @param mlx Internal MLX application * @param mlx Internal MLX application
* @param x Get X size * @param win Internal window
* @param y Get Y size * @param w Get width size
* @param h Get height size
* *
* @return (int) Always return 0, made this to copy the behaviour of the original MLX * @return (int) Always return 0, made this to copy the behaviour of the original MLX
*/ */
int mlx_get_screens_size(void* mlx, int* w, int* h); MLX_API int mlx_get_screens_size(void* mlx, void* win, int* w, int* h);
/**
* @brief Caps the FPS
*
* @param mlx Internal MLX application
* @param fps The FPS cap
*
* @return (int) Always return 0
*/
MLX_API int mlx_set_fps_goal(void* mlx, int fps);
#ifdef __cplusplus #ifdef __cplusplus
} }

194
includes/mlx_profile.h git.filemode.normal_file
View File

@@ -0,0 +1,194 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* mlx_profile.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/10 08:49:17 by maldavid #+# #+# */
/* Updated: 2024/01/03 15:33:35 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_PROFILE__
#define __MLX_PROFILE__
// Try to identify the compiler
#if defined(__BORLANDC__)
#define MLX_COMPILER_BORDLAND
#elif defined(__clang__)
#define MLX_COMPILER_CLANG
#ifdef __MINGW32__
#define MLX_COMPILER_MINGW
#ifdef __MINGW64_VERSION_MAJOR
#define MLX_COMPILER_MINGW_W64
#endif
#endif
#elif defined(__GNUC__) || defined(__MINGW32__)
#define MLX_COMPILER_GCC
#ifdef __MINGW32__
#define MLX_COMPILER_MINGW
#ifdef __MINGW64_VERSION_MAJOR
#define MLX_COMPILER_MINGW_W64
#endif
#endif
#elif defined(__INTEL_COMPILER) || defined(__ICL)
#define MLX_COMPILER_INTEL
#elif defined(_MSC_VER)
#define MLX_COMPILER_MSVC
#else
#define MLX_COMPILER_UNKNOWN
#warning "This compiler is not fully supported"
#endif
#if defined(_WIN32) || defined(__CYGWIN__)
#define MLX_PLAT_WINDOWS
#elif defined(__linux__)
#define MLX_PLAT_LINUX
#elif defined(__APPLE__) && defined(__MACH__)
#define MLX_PLAT_MACOS
#elif defined(unix) || defined(__unix__) || defined(__unix)
#define MLX_PLAT_UNIX
#else
#error "Unknown environment (not Windows, not Linux, not MacOS, not Unix)"
#endif
#ifdef MLX_PLAT_WINDOWS
#ifdef MLX_COMPILER_MSVC
#ifdef MLX_BUILD
#define MLX_API __declspec(dllexport)
#else
#define MLX_API __declspec(dllimport)
#endif
#elif defined(MLX_COMPILER_GCC)
#ifdef MLX_BUILD
#define MLX_API __attribute__((dllexport))
#else
#define MLX_API __attribute__((dllimport))
#endif
#else
#define MLX_API
#endif
#elif defined(MLX_COMPILER_GCC)
#define MLX_API __attribute__((visibility("default")))
#else
#define MLX_API
#endif
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600)) || defined(__ghs__)
#define MLX_FUNC_SIG __PRETTY_FUNCTION__
#elif defined(__DMC__) && (__DMC__ >= 0x810)
#define MLX_FUNC_SIG __PRETTY_FUNCTION__
#elif (defined(__FUNCSIG__) || (_MSC_VER))
#define MLX_FUNC_SIG __FUNCSIG__
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
#define MLX_FUNC_SIG __FUNCTION__
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
#define MLX_FUNC_SIG __FUNC__
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
#define MLX_FUNC_SIG __func__
#elif defined(__cplusplus) && (__cplusplus >= 201103)
#define MLX_FUNC_SIG __func__
#else
#define MLX_FUNC_SIG "Unknown function"
#endif
#ifndef __cplusplus // if we compile in C
#ifdef __STDC__
#ifdef __STDC_VERSION__
#if __STDC_VERSION__ == 199409L
#define MLX_C_VERSION 1994
#elif __STDC_VERSION__ == 199901L
#define MLX_C_VERSION 1999
#elif __STDC_VERSION__ == 201112L
#define MLX_C_VERSION 2011
#elif __STDC_VERSION__ == 201710L
#define MLX_C_VERSION 2017
#elif __STDC_VERSION__ == 202311L
#define MLX_C_VERSION 2023
#else
#define MLX_C_VERSION 0
#endif
#else
#define MLX_C_VERSION 0
#endif
#else
#define MLX_C_VERSION 0
#endif
#else
#define MLX_C_VERSION 0
#endif
#if defined(MLX_PLAT_WINDOWS)
#define VK_USE_PLATFORM_WIN32_KHR
#ifdef __cplusplus
constexpr const char* VULKAN_LIB_NAME = "vulkan-1.dll";
#endif
#elif defined(MLX_PLAT_MACOS)
#define VK_USE_PLATFORM_MACOS_MVK
#define VK_USE_PLATFORM_METAL_EXT
#ifdef __cplusplus
constexpr const char* VULKAN_LIB_NAME = "libvulkan.dylib / libvulkan.1.dylib / libMoltenVK.dylib";
#endif
#else
#define VK_USE_PLATFORM_XLIB_KHR
#define VK_USE_PLATFORM_WAYLAND_KHR
#ifdef __cplusplus
constexpr const char* VULKAN_LIB_NAME = "libvulkan.so / libvulkan.so.1";
#endif
#endif
// Checking common assumptions
#ifdef __cplusplus
#include <climits>
#include <cstdint>
static_assert(CHAR_BIT == 8, "CHAR_BIT is expected to be 8");
static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" );
static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size");
static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size");
static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size");
static_assert(sizeof(uint8_t) == 1, "uint8_t is not of the correct size" );
static_assert(sizeof(uint16_t) == 2, "uint16_t is not of the correct size");
static_assert(sizeof(uint32_t) == 4, "uint32_t is not of the correct size");
static_assert(sizeof(uint64_t) == 8, "uint64_t is not of the correct size");
#elif MLX_C_VERSION >= 2011
#if MLX_C_VERSION < 2023
#include <assert.h>
#endif
#include <limits.h>
#include <stdint.h>
static_assert(CHAR_BIT == 8, "CHAR_BIT is expected to be 8");
static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" );
static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size");
static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size");
static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size");
static_assert(sizeof(uint8_t) == 1, "uint8_t is not of the correct size" );
static_assert(sizeof(uint16_t) == 2, "uint16_t is not of the correct size");
static_assert(sizeof(uint32_t) == 4, "uint32_t is not of the correct size");
static_assert(sizeof(uint64_t) == 8, "uint64_t is not of the correct size");
#else
#define STATIC_ASSERT(COND, MSG) typedef char static_assertion___##MSG[(COND)?1:-1]
#include <limits.h>
#include <stdint.h>
STATIC_ASSERT(CHAR_BIT == 8, CHAR_BIT_is_expected_to_be_8);
STATIC_ASSERT(sizeof(int8_t) == 1, int8_t_is_not_of_the_correct_size);
STATIC_ASSERT(sizeof(int16_t) == 2, int16_t_is_not_of_the_correct_size);
STATIC_ASSERT(sizeof(int32_t) == 4, int32_t_is_not_of_the_correct_size);
STATIC_ASSERT(sizeof(int64_t) == 8, int64_t_is_not_of_the_correct_size);
STATIC_ASSERT(sizeof(uint8_t) == 1, uint8_t_is_not_of_the_correct_size);
STATIC_ASSERT(sizeof(uint16_t) == 2, uint16_t_is_not_of_the_correct_size);
STATIC_ASSERT(sizeof(uint32_t) == 4, uint32_t_is_not_of_the_correct_size);
STATIC_ASSERT(sizeof(uint64_t) == 8, uint64_t_is_not_of_the_correct_size);
#endif
#endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
res/screenshot_test_windows.png git.filemode.normal_file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

31
scripts/fetch_dependencies.sh git.filemode.executable_file
View File

@@ -0,0 +1,31 @@
#!/bin/bash
# Update volk
rm -f ../third_party/volk.c
rm -f ../third_party/volk.h
tag_name=$(curl -sL https://api.github.com/repos/zeux/Volk/releases/latest | jq -r '.tag_name')
wget https://api.github.com/repos/zeux/volk/zipball/$tag_name -O volk.zip
unzip -o volk.zip -d ../third_party/
mv ../third_party/zeux-volk*/volk.h ../third_party
mv ../third_party/zeux-volk*/volk.c ../third_party
rm -rf ../third_party/zeux-volk*
rm volk.zip
# Update VMA
rm -f ../third_party/vma.h
tag_name=$(curl -sL https://api.github.com/repos/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/releases/latest | jq -r '.tag_name')
wget https://api.github.com/repos/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/zipball/$tag_name -O vma.zip
unzip -o vma.zip -d ../third_party/
mv ../third_party/GPUOpen-LibrariesAndSDKs-VulkanMemoryAllocator*/include/vk_mem_alloc.h ../third_party/vma.h
rm -rf ../third_party/GPUOpen-LibrariesAndSDKs-VulkanMemoryAllocator*
rm vma.zip
# Update Vulkan headers
rm -rf ../third_party/vulkan
rm -rf ../third_party/vk_video
wget https://github.com/KhronosGroup/Vulkan-Headers/archive/main.zip -O vulkan-headers.zip
unzip -o vulkan-headers.zip -d ../third_party/
mv ../third_party/Vulkan-Headers-main/include/vulkan ../third_party/
mv ../third_party/Vulkan-Headers-main/include/vk_video ../third_party/
rm -rf ../third_party/Vulkan-Headers-main
rm vulkan-headers.zip

25
src/core/UUID.cpp git.filemode.normal_file
View File

@@ -0,0 +1,25 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* UUID.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/06 11:26:37 by maldavid #+# #+# */
/* Updated: 2024/01/06 11:28:15 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <core/UUID.h>
#include <random>
#include <unordered_map>
namespace mlx
{
static std::random_device random_device;
static std::mt19937_64 engine(random_device());
static std::uniform_int_distribution<std::uint64_t> uniform_distribution;
UUID::UUID() : _uuid(uniform_distribution(engine)) {}
UUID::UUID(std::uint64_t uuid) : _uuid(uuid) {}
}

33
src/core/UUID.h git.filemode.normal_file
View File

@@ -0,0 +1,33 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* UUID.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/06 11:13:23 by maldavid #+# #+# */
/* Updated: 2024/01/07 01:44:21 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_UUID__
#define __MLX_UUID__
#include <cstdint>
namespace mlx
{
class UUID
{
public:
UUID();
UUID(std::uint64_t uuid);
inline operator std::uint64_t() const { return _uuid; }
private:
std::uint64_t _uuid;
};
}
#endif

View File

@@ -6,43 +6,71 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 22:10:52 by maldavid #+# #+# */ /* Created: 2022/10/04 22:10:52 by maldavid #+# #+# */
/* Updated: 2023/11/20 07:29:12 by maldavid ### ########.fr */ /* Updated: 2024/04/24 13:52:18 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "application.h" #include "application.h"
#include <renderer/texts/text_library.h>
#include <renderer/texts/font_library.h>
#include <SDL2/SDL.h>
#include <renderer/images/texture.h> #include <renderer/images/texture.h>
#include <renderer/core/render_core.h> #include <renderer/core/render_core.h>
#include <array>
#include <core/errors.h> #include <core/errors.h>
#include <core/profile.h> #include <mlx_profile.h>
#include <core/memory.h>
namespace mlx::core namespace mlx::core
{ {
Application::Application() : _in(std::make_unique<Input>()) static bool __drop_sdl_responsability = false;
Application::Application() : _fps(), _in(std::make_unique<Input>())
{ {
_fps.init();
__drop_sdl_responsability = SDL_WasInit(SDL_INIT_VIDEO);
if(__drop_sdl_responsability) // is case the mlx is running in a sandbox like MacroUnitTester where SDL is already init
return;
SDL_SetMemoryFunctions(MemManager::malloc, MemManager::calloc, MemManager::realloc, MemManager::free);
/* Remove this comment if you want to prioritise Wayland over X11/XWayland, at your own risks */
//SDL_SetHint(SDL_HINT_VIDEODRIVER, "wayland,x11");
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER) != 0) if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER) != 0)
error::report(e_kind::fatal_error, "SDL error : unable to init all subsystems : %s", SDL_GetError()); error::report(e_kind::fatal_error, "SDL error : unable to init all subsystems : %s", SDL_GetError());
} }
void Application::run() noexcept void Application::run() noexcept
{ {
while(_in->is_running()) _in->run();
while(_in->isRunning())
{ {
if(!_fps.update())
continue;
_in->update(); _in->update();
for(auto& gs : _graphics)
gs->beginRender();
if(_loop_hook) if(_loop_hook)
_loop_hook(_param); _loop_hook(_param);
for(auto& gs : _graphics) for(auto& gs : _graphics)
gs->endRender(); {
if(gs)
gs->render();
}
}
Render_Core::get().getSingleTimeCmdManager().updateSingleTimesCmdBuffersSubmitState();
for(auto& gs : _graphics)
{
if(!gs)
continue;
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
gs->getRenderer().getCmdBuffer(i).waitForExecution();
} }
} }
void* Application::newTexture(int w, int h) void* Application::newTexture(int w, int h)
{ {
MLX_PROFILE_FUNCTION();
#ifdef DEBUG #ifdef DEBUG
_textures.emplace_front().create(nullptr, w, h, VK_FORMAT_R8G8B8A8_UNORM, "__mlx_unamed_user_texture"); _textures.emplace_front().create(nullptr, w, h, VK_FORMAT_R8G8B8A8_UNORM, "__mlx_unamed_user_texture");
#else #else
@@ -53,19 +81,47 @@ namespace mlx::core
void* Application::newStbTexture(char* file, int* w, int* h) void* Application::newStbTexture(char* file, int* w, int* h)
{ {
MLX_PROFILE_FUNCTION();
_textures.emplace_front(stbTextureLoad(file, w, h)); _textures.emplace_front(stbTextureLoad(file, w, h));
return &_textures.front(); return &_textures.front();
} }
void Application::destroyTexture(void* ptr) void Application::destroyTexture(void* ptr)
{ {
vkDeviceWaitIdle(Render_Core::get().getDevice().get()); MLX_PROFILE_FUNCTION();
vkDeviceWaitIdle(Render_Core::get().getDevice().get()); // TODO : synchronize with another method than waiting for GPU to be idle
if(ptr == nullptr)
{
core::error::report(e_kind::error, "invalid image ptr (NULL)");
return;
}
auto it = std::find_if(_textures.begin(), _textures.end(), [=](const Texture& texture) { return &texture == ptr; });
if(it == _textures.end())
{
core::error::report(e_kind::error, "invalid image ptr");
return;
}
Texture* texture = static_cast<Texture*>(ptr); Texture* texture = static_cast<Texture*>(ptr);
if(!texture->isInit())
core::error::report(e_kind::error, "trying to destroy a texture that has already been destroyed");
else
texture->destroy(); texture->destroy();
for(auto& gs : _graphics)
{
if(gs)
gs->tryEraseTextureFromManager(texture);
}
_textures.erase(it);
} }
Application::~Application() Application::~Application()
{ {
TextLibrary::get().clearLibrary();
FontLibrary::get().clearLibrary();
if(__drop_sdl_responsability)
return;
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS);
SDL_Quit(); SDL_Quit();
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 21:49:46 by maldavid #+# #+# */ /* Created: 2022/10/04 21:49:46 by maldavid #+# #+# */
/* Updated: 2023/11/23 14:25:43 by maldavid ### ########.fr */ /* Updated: 2024/09/12 01:30:35 by tdelage ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,15 +15,16 @@
#include <list> #include <list>
#include <memory> #include <memory>
#include <string>
#include <vector> #include <vector>
#include <utility>
#include <functional> #include <functional>
#include <core/errors.h> #include <core/errors.h>
#include <core/graphics.h> #include <core/graphics.h>
#include <platform/inputs.h> #include <platform/inputs.h>
#include <mlx_profile.h>
#include <core/profiler.h>
#include <core/fps.h>
namespace mlx::core namespace mlx::core
{ {
@@ -37,20 +38,23 @@ namespace mlx::core
inline void onEvent(void* win, int event, int (*funct_ptr)(int, void*), void* param) noexcept; inline void onEvent(void* win, int event, int (*funct_ptr)(int, void*), void* param) noexcept;
inline void getScreenSize(int* w, int* h) noexcept; inline void getScreenSize(void* win, int* w, int* h) noexcept;
inline void* newGraphicsSuport(std::size_t w, std::size_t h, std::string title); inline void setFPSCap(std::uint32_t fps) noexcept;
inline void* newGraphicsSuport(std::size_t w, std::size_t h, const char* title);
inline void clearGraphicsSupport(void* win); inline void clearGraphicsSupport(void* win);
inline void destroyGraphicsSupport(void* win); inline void destroyGraphicsSupport(void* win);
inline void setWindowPosition(void *win, int x, int y);
inline void pixelPut(void* win, int x, int y, uint32_t color) const noexcept; inline void pixelPut(void* win, int x, int y, std::uint32_t color) const noexcept;
inline void stringPut(void* win, int x, int y, int color, char* str); inline void stringPut(void* win, int x, int y, std::uint32_t color, char* str);
void* newTexture(int w, int h); void* newTexture(int w, int h);
void* newStbTexture(char* file, int* w, int* h); // stb textures are format managed by stb image (png, jpg, bpm, ...) void* newStbTexture(char* file, int* w, int* h); // stb textures are format managed by stb image (png, jpg, bpm, ...)
inline void texturePut(void* win, void* img, int x, int y); inline void texturePut(void* win, void* img, int x, int y);
inline int getTexturePixel(void* img, int x, int y); inline int getTexturePixel(void* img, int x, int y);
inline void setTexturePixel(void* img, int x, int y, uint32_t color); inline void setTexturePixel(void* img, int x, int y, std::uint32_t color);
void destroyTexture(void* ptr); void destroyTexture(void* ptr);
inline void loopHook(int (*f)(void*), void* param); inline void loopHook(int (*f)(void*), void* param);
@@ -63,12 +67,12 @@ namespace mlx::core
~Application(); ~Application();
private: private:
FpsManager _fps;
std::list<Texture> _textures; std::list<Texture> _textures;
std::vector<std::unique_ptr<GraphicsSupport>> _graphics; std::vector<std::unique_ptr<GraphicsSupport>> _graphics;
std::function<int(void*)> _loop_hook; std::function<int(void*)> _loop_hook;
std::unique_ptr<Input> _in; std::unique_ptr<Input> _in;
void* _param = nullptr; void* _param = nullptr;
bool _is_loop_running = false;
}; };
} }

View File

@@ -10,8 +10,37 @@
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include <SDL2/SDL_video.h>
#include <algorithm>
#include <core/application.h> #include <core/application.h>
#define CHECK_WINDOW_PTR(win) \
if(win == nullptr) \
{ \
core::error::report(e_kind::error, "invalid window ptr (NULL)"); \
return; \
} \
else if(*static_cast<int*>(win) < 0 || *static_cast<int*>(win) > static_cast<int>(_graphics.size()))\
{ \
core::error::report(e_kind::error, "invalid window ptr"); \
return; \
} else {}
#define CHECK_IMAGE_PTR(img, retval) \
if(img == nullptr) \
{ \
core::error::report(e_kind::error, "invalid image ptr (NULL)"); \
retval; \
} \
else if(std::find_if(_textures.begin(), _textures.end(), [=](const Texture& texture) \
{ \
return &texture == img; \
}) == _textures.end()) \
{ \
core::error::report(e_kind::error, "invalid image ptr"); \
retval; \
} else {}
namespace mlx::core namespace mlx::core
{ {
void Application::getMousePos(int* x, int* y) noexcept void Application::getMousePos(int* x, int* y) noexcept
@@ -22,71 +51,152 @@ namespace mlx::core
void Application::mouseMove(void* win, int x, int y) noexcept void Application::mouseMove(void* win, int x, int y) noexcept
{ {
CHECK_WINDOW_PTR(win);
if(!_graphics[*static_cast<int*>(win)]->hasWindow())
{
error::report(e_kind::warning, "trying to move the mouse relative to a window that is targeting an image and not a real window, this is not allowed (move ignored)");
return;
}
SDL_WarpMouseInWindow(_graphics[*static_cast<int*>(win)]->getWindow()->getNativeWindow(), x, y); SDL_WarpMouseInWindow(_graphics[*static_cast<int*>(win)]->getWindow()->getNativeWindow(), x, y);
SDL_PumpEvents(); SDL_PumpEvents();
SDL_FlushEvent(SDL_MOUSEMOTION);
} }
void Application::onEvent(void* win, int event, int (*funct_ptr)(int, void*), void* param) noexcept void Application::onEvent(void* win, int event, int (*funct_ptr)(int, void*), void* param) noexcept
{ {
CHECK_WINDOW_PTR(win);
if(!_graphics[*static_cast<int*>(win)]->hasWindow())
{
error::report(e_kind::warning, "trying to add event hook for a window that is targeting an image and not a real window, this is not allowed (hook ignored)");
return;
}
_in->onEvent(_graphics[*static_cast<int*>(win)]->getWindow()->getID(), event, funct_ptr, param); _in->onEvent(_graphics[*static_cast<int*>(win)]->getWindow()->getID(), event, funct_ptr, param);
} }
void Application::getScreenSize(int* w, int* h) noexcept void Application::setWindowPosition(void* win, int x, int y)
{ {
CHECK_WINDOW_PTR(win);
if(!_graphics[*static_cast<int*>(win)]->hasWindow())
{
error::report(e_kind::warning, "trying to move a window that is targeting an image and not a real window, this is not allowed");
return;
}
SDL_SetWindowPosition(_graphics[*static_cast<int*>(win)]->getWindow()->getNativeWindow(), x, y);
}
void Application::getScreenSize(void* win, int* w, int* h) noexcept
{
CHECK_WINDOW_PTR(win);
SDL_DisplayMode DM; SDL_DisplayMode DM;
SDL_GetDesktopDisplayMode(0, &DM); SDL_GetDesktopDisplayMode(SDL_GetWindowDisplayIndex(_graphics[*static_cast<int*>(win)]->getWindow()->getNativeWindow()), &DM);
*w = DM.w; *w = DM.w;
*h = DM.h; *h = DM.h;
} }
void* Application::newGraphicsSuport(std::size_t w, std::size_t h, std::string title) void Application::setFPSCap(std::uint32_t fps) noexcept
{ {
_fps.setMaxFPS(fps);
}
void* Application::newGraphicsSuport(std::size_t w, std::size_t h, const char* title)
{
MLX_PROFILE_FUNCTION();
auto it = std::find_if(_textures.begin(), _textures.end(), [=](const Texture& texture)
{
return &texture == reinterpret_cast<Texture*>(const_cast<char*>(title));
});
if(it != _textures.end())
_graphics.emplace_back(std::make_unique<GraphicsSupport>(w, h, reinterpret_cast<Texture*>(const_cast<char*>(title)), _graphics.size()));
else
{
if(title == NULL)
{
core::error::report(e_kind::fatal_error, "invalid window title (NULL)");
return nullptr;
}
_graphics.emplace_back(std::make_unique<GraphicsSupport>(w, h, title, _graphics.size())); _graphics.emplace_back(std::make_unique<GraphicsSupport>(w, h, title, _graphics.size()));
_in->addWindow(_graphics.back()->getWindow()); _in->addWindow(_graphics.back()->getWindow());
}
return static_cast<void*>(&_graphics.back()->getID()); return static_cast<void*>(&_graphics.back()->getID());
} }
void Application::clearGraphicsSupport(void* win) void Application::clearGraphicsSupport(void* win)
{ {
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
_graphics[*static_cast<int*>(win)]->clearRenderData(); _graphics[*static_cast<int*>(win)]->clearRenderData();
} }
void Application::destroyGraphicsSupport(void* win) void Application::destroyGraphicsSupport(void* win)
{ {
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
_graphics[*static_cast<int*>(win)].reset(); _graphics[*static_cast<int*>(win)].reset();
} }
void Application::pixelPut(void* win, int x, int y, uint32_t color) const noexcept void Application::pixelPut(void* win, int x, int y, std::uint32_t color) const noexcept
{ {
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
_graphics[*static_cast<int*>(win)]->pixelPut(x, y, color); _graphics[*static_cast<int*>(win)]->pixelPut(x, y, color);
} }
void Application::stringPut(void* win, int x, int y, int color, char* str) void Application::stringPut(void* win, int x, int y, std::uint32_t color, char* str)
{ {
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
if(str == nullptr)
{
core::error::report(e_kind::error, "wrong text (NULL)");
return;
}
if(std::strlen(str) == 0)
{
core::error::report(e_kind::warning, "trying to put an empty text");
return;
}
_graphics[*static_cast<int*>(win)]->stringPut(x, y, color, str); _graphics[*static_cast<int*>(win)]->stringPut(x, y, color, str);
} }
void Application::loadFont(void* win, const std::filesystem::path& filepath, float scale) void Application::loadFont(void* win, const std::filesystem::path& filepath, float scale)
{ {
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
_graphics[*static_cast<int*>(win)]->loadFont(filepath, scale); _graphics[*static_cast<int*>(win)]->loadFont(filepath, scale);
} }
void Application::texturePut(void* win, void* img, int x, int y) void Application::texturePut(void* win, void* img, int x, int y)
{ {
MLX_PROFILE_FUNCTION();
CHECK_WINDOW_PTR(win);
CHECK_IMAGE_PTR(img, return);
Texture* texture = static_cast<Texture*>(img); Texture* texture = static_cast<Texture*>(img);
if(!texture->isInit())
core::error::report(e_kind::error, "trying to put a texture that has been destroyed");
else
_graphics[*static_cast<int*>(win)]->texturePut(texture, x, y); _graphics[*static_cast<int*>(win)]->texturePut(texture, x, y);
} }
int Application::getTexturePixel(void* img, int x, int y) int Application::getTexturePixel(void* img, int x, int y)
{ {
MLX_PROFILE_FUNCTION();
CHECK_IMAGE_PTR(img, return 0);
Texture* texture = static_cast<Texture*>(img); Texture* texture = static_cast<Texture*>(img);
if(!texture->isInit())
{
core::error::report(e_kind::error, "trying to get a pixel from texture that has been destroyed");
return 0;
}
return texture->getPixel(x, y); return texture->getPixel(x, y);
} }
void Application::setTexturePixel(void* img, int x, int y, uint32_t color) void Application::setTexturePixel(void* img, int x, int y, std::uint32_t color)
{ {
MLX_PROFILE_FUNCTION();
CHECK_IMAGE_PTR(img, return);
Texture* texture = static_cast<Texture*>(img); Texture* texture = static_cast<Texture*>(img);
if(!texture->isInit())
core::error::report(e_kind::error, "trying to set a pixel on texture that has been destroyed");
else
texture->setPixel(x, y, color); texture->setPixel(x, y, color);
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 17:35:20 by maldavid #+# #+# */ /* Created: 2022/10/04 17:35:20 by maldavid #+# #+# */
/* Updated: 2023/11/25 10:12:36 by maldavid ### ########.fr */ /* Updated: 2024/09/12 01:29:33 by tdelage ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,207 +15,298 @@
#include "application.h" #include "application.h"
#include <renderer/core/render_core.h> #include <renderer/core/render_core.h>
#include <filesystem> #include <filesystem>
#include <mlx.h>
#include <core/memory.h>
#include <mlx_profile.h>
static void* __mlx_ptr = nullptr;
#define MLX_CHECK_APPLICATION_POINTER(ptr) \
if(ptr != __mlx_ptr || ptr == NULL) \
mlx::core::error::report(e_kind::fatal_error, "invalid mlx pointer passed to '%s'", MLX_FUNC_SIG); \
else {} // just to avoid issues with possible if-else statements outside this macro
extern "C" extern "C"
{ {
void* mlx_init() void* mlx_init()
{ {
static bool init = false; if(__mlx_ptr != nullptr)
if(init)
{ {
mlx::core::error::report(e_kind::error, "MLX cannot be initialized multiple times"); mlx::core::error::report(e_kind::error, "MLX cannot be initialized multiple times");
return NULL; return NULL; // not nullptr for the C compatibility
} }
mlx::Render_Core::get().init(); mlx::MemManager::get(); // just to initialize the C garbage collector
mlx::core::Application* app = new mlx::core::Application; mlx::core::Application* app = new mlx::core::Application;
mlx::Render_Core::get().init();
if(app == nullptr) if(app == nullptr)
mlx::core::error::report(e_kind::fatal_error, "Tout a pété"); mlx::core::error::report(e_kind::fatal_error, "Tout a pété");
init = true; __mlx_ptr = static_cast<void*>(app);
return app; return __mlx_ptr;
} }
void* mlx_new_window(mlx::core::Application* mlx, int w, int h, const char* title) void* mlx_new_window(void* mlx, int w, int h, const char* title)
{ {
return mlx->newGraphicsSuport(w, h, title); MLX_CHECK_APPLICATION_POINTER(mlx);
if(w <= 0 || h <= 0)
{
mlx::core::error::report(e_kind::fatal_error, "invalid window size (%d x %d)", w, h);
return NULL; // not nullptr for the C compatibility
}
return static_cast<mlx::core::Application*>(mlx)->newGraphicsSuport(w, h, title);
} }
int mlx_loop_hook(mlx::core::Application* mlx, int (*f)(void*), void* param) int mlx_loop_hook(void* mlx, int (*f)(void*), void* param)
{ {
mlx->loopHook(f, param); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->loopHook(f, param);
return 0; return 0;
} }
int mlx_loop(mlx::core::Application* mlx) void mlx_set_window_position(void *mlx, void *win, int x, int y)
{ {
mlx->run(); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->setWindowPosition(win, x, y);
}
int mlx_loop(void* mlx)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->run();
return 0; return 0;
} }
int mlx_loop_end(mlx::core::Application* mlx) int mlx_loop_end(void* mlx)
{ {
mlx->loopEnd(); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->loopEnd();
return 0; return 0;
} }
int mlx_mouse_show() int mlx_mouse_show()
{ {
return SDL_ShowCursor(SDL_ENABLE); SDL_ShowCursor(SDL_ENABLE);
return 0;
} }
int mlx_mouse_hide() int mlx_mouse_hide()
{ {
return SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
}
int mlx_mouse_move(mlx::core::Application* mlx, void* win, int x, int y)
{
mlx->mouseMove(win, x, y);
return 0; return 0;
} }
int mlx_mouse_get_pos(mlx::core::Application* mlx, int* x, int* y) int mlx_mouse_move(void* mlx, void* win, int x, int y)
{ {
mlx->getMousePos(x, y); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->mouseMove(win, x, y);
return 0; return 0;
} }
int mlx_on_event(mlx::core::Application* mlx, void* win, int event, int (*funct_ptr)(int, void*), void* param) int mlx_mouse_get_pos(void* mlx, int* x, int* y)
{ {
mlx->onEvent(win, event, funct_ptr, param); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->getMousePos(x, y);
return 0; return 0;
} }
void* mlx_new_image(mlx::core::Application* mlx, int width, int height) int mlx_on_event(void* mlx, void* win, mlx_event_type event, int (*funct_ptr)(int, void*), void* param)
{ {
return mlx->newTexture(width, height); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->onEvent(win, static_cast<int>(event), funct_ptr, param);
return 0;
} }
int mlx_get_image_pixel(mlx::core::Application* mlx, void* img, int x, int y) void* mlx_new_image(void* mlx, int width, int height)
{ {
return mlx->getTexturePixel(img, x, y); MLX_CHECK_APPLICATION_POINTER(mlx);
if (width <= 0 || height <= 0)
mlx::core::error::report(e_kind::fatal_error, "invalid image size (%d x %d)", width, height);
return static_cast<mlx::core::Application*>(mlx)->newTexture(width, height);
} }
void mlx_set_image_pixel(mlx::core::Application* mlx, void* img, int x, int y, int color) int mlx_get_image_pixel(void* mlx, void* img, int x, int y)
{ {
MLX_CHECK_APPLICATION_POINTER(mlx);
int color = static_cast<mlx::core::Application*>(mlx)->getTexturePixel(img, x, y);
unsigned char color_bits[4];
color_bits[0] = (color & 0x000000FF);
color_bits[1] = (color & 0x0000FF00) >> 8;
color_bits[2] = (color & 0x00FF0000) >> 16;
color_bits[3] = (color & 0xFF000000) >> 24;
return *reinterpret_cast<int*>(color_bits);
}
void mlx_set_image_pixel(void* mlx, void* img, int x, int y, int color)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
unsigned char color_bits[4]; unsigned char color_bits[4];
color_bits[0] = (color & 0x00FF0000) >> 16; color_bits[0] = (color & 0x00FF0000) >> 16;
color_bits[1] = (color & 0x0000FF00) >> 8; color_bits[1] = (color & 0x0000FF00) >> 8;
color_bits[2] = (color & 0x000000FF); color_bits[2] = (color & 0x000000FF);
color_bits[3] = (color & 0xFF000000) >> 24; color_bits[3] = (color & 0xFF000000) >> 24;
mlx->setTexturePixel(img, x, y, *reinterpret_cast<unsigned int*>(color_bits)); static_cast<mlx::core::Application*>(mlx)->setTexturePixel(img, x, y, *reinterpret_cast<unsigned int*>(color_bits));
} }
int mlx_put_image_to_window(mlx::core::Application* mlx, void* win, void* img, int x, int y) int mlx_put_image_to_window(void* mlx, void* win, void* img, int x, int y)
{ {
mlx->texturePut(win, img, x, y); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->texturePut(win, img, x, y);
return 0; return 0;
} }
int mlx_destroy_image(mlx::core::Application* mlx, void* img) int mlx_destroy_image(void* mlx, void* img)
{ {
mlx->destroyTexture(img); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->destroyTexture(img);
return 0; return 0;
} }
void* mlx_png_file_to_image(mlx::core::Application* mlx, char* filename, int* width, int* height) void* mlx_png_file_to_image(void* mlx, char* filename, int* width, int* height)
{ {
MLX_CHECK_APPLICATION_POINTER(mlx);
if (filename == nullptr)
mlx::core::error::report(e_kind::fatal_error, "PNG loader : filename is NULL");
std::filesystem::path file(filename); std::filesystem::path file(filename);
if(file.extension() != ".png") if(file.extension() != ".png")
{ {
mlx::core::error::report(e_kind::error, "PNG loader : not a png file '%s'", filename); mlx::core::error::report(e_kind::error, "PNG loader : not a png file '%s'", filename);
return nullptr; return nullptr;
} }
return mlx->newStbTexture(filename, width, height); return static_cast<mlx::core::Application*>(mlx)->newStbTexture(filename, width, height);
} }
void* mlx_jpg_file_to_image(mlx::core::Application* mlx, char* filename, int* width, int* height) void* mlx_jpg_file_to_image(void* mlx, char* filename, int* width, int* height)
{ {
MLX_CHECK_APPLICATION_POINTER(mlx);
if (filename == nullptr)
mlx::core::error::report(e_kind::fatal_error, "JPG loader : filename is NULL");
std::filesystem::path file(filename); std::filesystem::path file(filename);
if(file.extension() != ".jpg" && file.extension() != ".jpeg") if(file.extension() != ".jpg" && file.extension() != ".jpeg")
{ {
mlx::core::error::report(e_kind::error, "JPG loader : not a jpg file '%s'", filename); mlx::core::error::report(e_kind::error, "JPG loader : not a jpg file '%s'", filename);
return nullptr; return nullptr;
} }
return mlx->newStbTexture(filename, width, height); return static_cast<mlx::core::Application*>(mlx)->newStbTexture(filename, width, height);
} }
void* mlx_bmp_file_to_image(mlx::core::Application* mlx, char* filename, int* width, int* height) void* mlx_bmp_file_to_image(void* mlx, char* filename, int* width, int* height)
{ {
MLX_CHECK_APPLICATION_POINTER(mlx);
if (filename == nullptr)
mlx::core::error::report(e_kind::fatal_error, "BMP loader : filename is NULL");
std::filesystem::path file(filename); std::filesystem::path file(filename);
if(file.extension() != ".bmp" && file.extension() != ".dib") if(file.extension() != ".bmp" && file.extension() != ".dib")
{ {
mlx::core::error::report(e_kind::error, "BMP loader : not a bmp file '%s'", filename); mlx::core::error::report(e_kind::error, "BMP loader : not a bmp file '%s'", filename);
return nullptr; return nullptr;
} }
return mlx->newStbTexture(filename, width, height); return static_cast<mlx::core::Application*>(mlx)->newStbTexture(filename, width, height);
} }
int mlx_pixel_put(mlx::core::Application* mlx, void* win, int x, int y, int color) int mlx_pixel_put(void* mlx, void* win, int x, int y, int color)
{ {
MLX_CHECK_APPLICATION_POINTER(mlx);
unsigned char color_bits[4]; unsigned char color_bits[4];
color_bits[0] = (color & 0x00FF0000) >> 16; color_bits[0] = (color & 0x00FF0000) >> 16;
color_bits[1] = (color & 0x0000FF00) >> 8; color_bits[1] = (color & 0x0000FF00) >> 8;
color_bits[2] = color & 0x000000FF; color_bits[2] = (color & 0x000000FF);
color_bits[3] = 0xFF; color_bits[3] = (color & 0xFF000000) >> 24;
mlx->pixelPut(win, x, y, *reinterpret_cast<unsigned int*>(color_bits)); static_cast<mlx::core::Application*>(mlx)->pixelPut(win, x, y, *reinterpret_cast<unsigned int*>(color_bits));
return 0; return 0;
} }
int mlx_string_put(mlx::core::Application* mlx, void* win, int x, int y, int color, char* str) int mlx_string_put(void* mlx, void* win, int x, int y, int color, char* str)
{ {
MLX_CHECK_APPLICATION_POINTER(mlx);
unsigned char color_bits[4]; unsigned char color_bits[4];
color_bits[0] = (color & 0x00FF0000) >> 16; color_bits[0] = (color & 0x00FF0000) >> 16;
color_bits[1] = (color & 0x0000FF00) >> 8; color_bits[1] = (color & 0x0000FF00) >> 8;
color_bits[2] = color & 0x000000FF; color_bits[2] = (color & 0x000000FF);
color_bits[3] = 0xFF; color_bits[3] = (color & 0xFF000000) >> 24;
mlx->stringPut(win, x, y, *reinterpret_cast<unsigned int*>(color_bits), str); static_cast<mlx::core::Application*>(mlx)->stringPut(win, x, y, *reinterpret_cast<unsigned int*>(color_bits), str);
return 0; return 0;
} }
void mlx_set_font(mlx::core::Application* mlx, void* win, char* filepath) void mlx_set_font(void* mlx, void* win, char* filepath)
{ {
MLX_CHECK_APPLICATION_POINTER(mlx);
if (filepath == nullptr)
{
mlx::core::error::report(e_kind::error, "Font loader : filepath is NULL");
return;
}
std::filesystem::path file(filepath); std::filesystem::path file(filepath);
if(file.extension() != ".ttf" && file.extension() != ".tte") if(std::strcmp(filepath, "default") != 0 && file.extension() != ".ttf" && file.extension() != ".tte")
{ {
mlx::core::error::report(e_kind::error, "TTF loader : not a truetype font file '%s'", filepath); mlx::core::error::report(e_kind::error, "TTF loader : not a truetype font file '%s'", filepath);
return; return;
} }
mlx->loadFont(win, file, 16.f); if(std::strcmp(filepath, "default") == 0)
static_cast<mlx::core::Application*>(mlx)->loadFont(win, file, 6.f);
else
static_cast<mlx::core::Application*>(mlx)->loadFont(win, file, 16.f);
} }
void mlx_set_font_scale(mlx::core::Application* mlx, void* win, char* filepath, float scale) void mlx_set_font_scale(void* mlx, void* win, char* filepath, float scale)
{ {
MLX_CHECK_APPLICATION_POINTER(mlx);
if (filepath == nullptr)
{
mlx::core::error::report(e_kind::error, "Font loader : filepath is NULL");
return;
}
std::filesystem::path file(filepath); std::filesystem::path file(filepath);
if(file.extension() != ".ttf" && file.extension() != ".tte") if(std::strcmp(filepath, "default") != 0 && file.extension() != ".ttf" && file.extension() != ".tte")
{ {
mlx::core::error::report(e_kind::error, "TTF loader : not a truetype font file '%s'", filepath); mlx::core::error::report(e_kind::error, "TTF loader : not a truetype font file '%s'", filepath);
return; return;
} }
mlx->loadFont(win, file, scale); static_cast<mlx::core::Application*>(mlx)->loadFont(win, file, scale);
} }
int mlx_clear_window(mlx::core::Application* mlx, void* win) int mlx_clear_window(void* mlx, void* win)
{ {
mlx->clearGraphicsSupport(win); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->clearGraphicsSupport(win);
return 0; return 0;
} }
int mlx_destroy_window(mlx::core::Application* mlx, void* win) int mlx_destroy_window(void* mlx, void* win)
{ {
mlx->destroyGraphicsSupport(win); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->destroyGraphicsSupport(win);
return 0; return 0;
} }
int mlx_destroy_display(mlx::core::Application* mlx) int mlx_destroy_display(void* mlx)
{ {
delete mlx; MLX_CHECK_APPLICATION_POINTER(mlx);
delete static_cast<mlx::core::Application*>(mlx);
mlx::Render_Core::get().destroy(); mlx::Render_Core::get().destroy();
__mlx_ptr = nullptr;
return 0; return 0;
} }
int mlx_get_screens_size(mlx::core::Application* mlx, int* w, int* h) int mlx_get_screens_size(void* mlx, void* win, int* w, int* h)
{ {
mlx->getScreenSize(w, h); MLX_CHECK_APPLICATION_POINTER(mlx);
static_cast<mlx::core::Application*>(mlx)->getScreenSize(win, w, h);
return 0;
}
int mlx_set_fps_goal(void* mlx, int fps)
{
MLX_CHECK_APPLICATION_POINTER(mlx);
if(fps < 0)
{
mlx::core::error::report(e_kind::error, "You cannot set a negative FPS cap (nice try)");
fps = -fps;
}
if(fps == 0)
{
mlx::core::error::report(e_kind::error, "You cannot set a FPS cap to 0 (nice try)");
return 0;
}
static_cast<mlx::core::Application*>(mlx)->setFPSCap(static_cast<std::uint32_t>(fps));
return 0; return 0;
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 17:48:06 by maldavid #+# #+# */ /* Created: 2022/10/04 17:48:06 by maldavid #+# #+# */
/* Updated: 2023/11/14 07:14:57 by maldavid ### ########.fr */ /* Updated: 2024/01/05 20:41:17 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 17:42:32 by maldavid #+# #+# */ /* Created: 2022/10/04 17:42:32 by maldavid #+# #+# */
/* Updated: 2022/10/08 19:06:41 by maldavid ### ########.fr */ /* Updated: 2023/12/27 17:21:07 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -14,6 +14,7 @@
#define __MLX_ERRORS__ #define __MLX_ERRORS__
#include <string> #include <string>
#include <mlx_profile.h>
enum class e_kind enum class e_kind
{ {

44
src/core/fps.cpp git.filemode.normal_file
View File

@@ -0,0 +1,44 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* fps.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/18 14:56:17 by maldavid #+# #+# */
/* Updated: 2024/03/25 16:44:15 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <core/fps.h>
#include <chrono>
#include <SDL2/SDL.h>
#include <thread>
namespace mlx
{
void FpsManager::init()
{
_timer = SDL_GetTicks64();
_fps_before = static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
_fps_now = static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
}
bool FpsManager::update()
{
using namespace std::chrono_literals;
_fps_now = static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count());
if(SDL_GetTicks64() - _timer > 1000)
_timer += 1000;
_fps_elapsed_time = _fps_now - _fps_before;
if(_fps_elapsed_time >= _ns)
{
_fps_before += _ns;
return true;
}
std::this_thread::sleep_for(std::chrono::duration<double, std::nano>(_ns - 1));
return false;
}
}

41
src/core/fps.h git.filemode.normal_file
View File

@@ -0,0 +1,41 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* fps.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/18 14:53:30 by maldavid #+# #+# */
/* Updated: 2024/01/18 15:16:06 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_FPS__
#define __MLX_FPS__
#include <cstdint>
namespace mlx
{
class FpsManager
{
public:
FpsManager() = default;
void init();
bool update();
inline void setMaxFPS(std::uint32_t fps) noexcept { _max_fps = fps; _ns = 1000000000.0 / fps; }
~FpsManager() = default;
private:
double _ns = 1000000000.0 / 1'337'000.0;
std::uint64_t _timer = 0;
std::uint64_t _fps_before = 0;
std::uint64_t _fps_now = 0;
std::uint32_t _max_fps = 1'337'000;
std::uint32_t _fps_elapsed_time = 0;
};
}
#endif

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 15:13:55 by maldavid #+# #+# */ /* Created: 2023/04/02 15:13:55 by maldavid #+# #+# */
/* Updated: 2023/11/24 20:42:15 by maldavid ### ########.fr */ /* Updated: 2024/04/22 17:34:27 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -14,55 +14,62 @@
namespace mlx namespace mlx
{ {
GraphicsSupport::GraphicsSupport(std::size_t w, std::size_t h, const std::string& title, int id) : GraphicsSupport::GraphicsSupport(std::size_t w, std::size_t h, Texture* render_target, int id) :
_window(std::make_shared<MLX_Window>(w, h, title)), _window(nullptr),
_renderer(std::make_unique<Renderer>()), _text_put_pipeline(std::make_unique<TextPutPipeline>()), _renderer(std::make_unique<Renderer>()),
_id(id) _width(w),
_height(h),
_id(id),
_has_window(false)
{ {
_renderer->setWindow(_window.get()); MLX_PROFILE_FUNCTION();
_renderer->init(); _renderer->setWindow(nullptr);
_renderer->init(render_target);
_pixel_put_pipeline.init(w, h, *_renderer); _pixel_put_pipeline.init(w, h, *_renderer);
_text_put_pipeline->init(_renderer.get()); _text_manager.init(*_renderer);
} }
void GraphicsSupport::endRender() noexcept GraphicsSupport::GraphicsSupport(std::size_t w, std::size_t h, std::string title, int id) :
_window(std::make_shared<MLX_Window>(w, h, title)),
_renderer(std::make_unique<Renderer>()),
_width(w),
_height(h),
_id(id),
_has_window(true)
{ {
auto cmd_buff = _renderer->getActiveCmdBuffer().get(); MLX_PROFILE_FUNCTION();
_renderer->setWindow(_window.get());
_renderer->init(nullptr);
_pixel_put_pipeline.init(w, h, *_renderer);
_text_manager.init(*_renderer);
}
static std::array<VkDescriptorSet, 2> sets = { void GraphicsSupport::render() noexcept
{
MLX_PROFILE_FUNCTION();
if(!_renderer->beginFrame())
return;
_proj = glm::ortho<float>(0, _width, 0, _height);
_renderer->getUniformBuffer()->setData(sizeof(_proj), &_proj);
std::array<VkDescriptorSet, 2> sets = {
_renderer->getVertDescriptorSet().get(), _renderer->getVertDescriptorSet().get(),
VK_NULL_HANDLE VK_NULL_HANDLE
}; };
for(auto& data : _textures_to_render) for(auto& data : _drawlist)
{ data->render(sets, *_renderer);
if(data.texture->getSet() == VK_NULL_HANDLE)
data.texture->setDescriptor(_renderer->getFragDescriptorSet().duplicate());
if(!data.texture->hasBeenUpdated())
data.texture->updateSet(0);
sets[1] = data.texture->getSet();
vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, _renderer->getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr);
data.texture->render(*_renderer, data.x, data.y);
}
_pixel_put_pipeline.present(); _pixel_put_pipeline.render(sets, *_renderer);
sets[1] = _pixel_put_pipeline.getDescriptorSet();
vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, _renderer->getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr);
_pixel_put_pipeline.render(*_renderer);
sets[1] = _text_put_pipeline->getDescriptorSet();
vkCmdBindDescriptorSets(cmd_buff, VK_PIPELINE_BIND_POINT_GRAPHICS, _renderer->getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr);
_text_put_pipeline->render();
_renderer->endFrame(); _renderer->endFrame();
for(auto& data : _textures_to_render) for(auto& data : _drawlist)
data.texture->resetUpdate(); data->resetUpdate();
#ifdef GRAPHICS_MEMORY_DUMP #ifdef GRAPHICS_MEMORY_DUMP
// dump memory to file every two seconds // dump memory to file every two seconds
static uint64_t timer = SDL_GetTicks64(); static std::uint64_t timer = SDL_GetTicks64();
if(SDL_GetTicks64() - timer > 2000) if(SDL_GetTicks64() - timer > 2000)
{ {
Render_Core::get().getAllocator().dumpMemoryToJson(); Render_Core::get().getAllocator().dumpMemoryToJson();
@@ -73,9 +80,12 @@ namespace mlx
GraphicsSupport::~GraphicsSupport() GraphicsSupport::~GraphicsSupport()
{ {
MLX_PROFILE_FUNCTION();
vkDeviceWaitIdle(Render_Core::get().getDevice().get()); vkDeviceWaitIdle(Render_Core::get().getDevice().get());
_text_put_pipeline->destroy(); _text_manager.destroy();
_pixel_put_pipeline.destroy(); _pixel_put_pipeline.destroy();
_renderer->destroy(); _renderer->destroy();
if(_window)
_window->destroy();
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 14:49:49 by maldavid #+# #+# */ /* Created: 2023/04/02 14:49:49 by maldavid #+# #+# */
/* Updated: 2023/11/25 09:59:39 by maldavid ### ########.fr */ /* Updated: 2024/03/24 14:43:09 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -14,7 +14,6 @@
#define __MLX_GRAPHICS__ #define __MLX_GRAPHICS__
#include <memory> #include <memory>
#include <unordered_set>
#include <filesystem> #include <filesystem>
#include <glm/glm.hpp> #include <glm/glm.hpp>
@@ -23,39 +22,59 @@
#include <platform/window.h> #include <platform/window.h>
#include <renderer/renderer.h> #include <renderer/renderer.h>
#include <renderer/pixel_put.h> #include <renderer/pixel_put.h>
#include <renderer/text_pipeline.h> #include <renderer/core/drawable_resource.h>
#include <renderer/images/texture_manager.h>
#include <renderer/texts/text_manager.h>
#include <utils/non_copyable.h> #include <utils/non_copyable.h>
#include <renderer/images/texture.h> #include <renderer/images/texture.h>
#include <mlx_profile.h>
#include <core/profiler.h>
namespace mlx namespace mlx
{ {
class GraphicsSupport : public non_copyable class GraphicsSupport : public NonCopyable
{ {
public: public:
GraphicsSupport(std::size_t w, std::size_t h, const std::string& title, int id); GraphicsSupport(std::size_t w, std::size_t h, Texture* render_target, int id);
GraphicsSupport(std::size_t w, std::size_t h, std::string title, int id);
inline int& getID() noexcept; inline int& getID() noexcept;
inline std::shared_ptr<MLX_Window> getWindow(); inline std::shared_ptr<MLX_Window> getWindow();
inline void beginRender() noexcept; void render() noexcept;
void endRender() noexcept;
inline void clearRenderData() noexcept; inline void clearRenderData() noexcept;
inline void pixelPut(int x, int y, uint32_t color) noexcept; inline void pixelPut(int x, int y, std::uint32_t color) noexcept;
inline void stringPut(int x, int y, int color, std::string str); inline void stringPut(int x, int y, std::uint32_t color, std::string str);
inline void texturePut(Texture* texture, int x, int y); inline void texturePut(Texture* texture, int x, int y);
inline void loadFont(const std::filesystem::path& filepath, float scale); inline void loadFont(const std::filesystem::path& filepath, float scale);
inline void tryEraseTextureFromManager(Texture* texture) noexcept;
inline bool hasWindow() const noexcept { return _has_window; }
inline Renderer& getRenderer() { return *_renderer; }
~GraphicsSupport(); ~GraphicsSupport();
private: private:
std::vector<TextureRenderData> _textures_to_render;
PixelPutPipeline _pixel_put_pipeline; PixelPutPipeline _pixel_put_pipeline;
std::vector<DrawableResource*> _drawlist;
TextManager _text_manager;
TextureManager _texture_manager;
glm::mat4 _proj = glm::mat4(1.0); glm::mat4 _proj = glm::mat4(1.0);
std::shared_ptr<MLX_Window> _window; std::shared_ptr<MLX_Window> _window;
std::unique_ptr<TextPutPipeline> _text_put_pipeline; // unique_ptr because of the size of the class
std::unique_ptr<Renderer> _renderer; std::unique_ptr<Renderer> _renderer;
std::size_t _width = 0;
std::size_t _height = 0;
int _id; int _id;
bool _has_window;
}; };
} }

View File

@@ -10,57 +10,71 @@
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "renderer/images/texture.h" #include <algorithm>
#include <core/graphics.h> #include <core/graphics.h>
#include <type_traits>
namespace mlx namespace mlx
{ {
int& GraphicsSupport::getID() noexcept { return _id; } int& GraphicsSupport::getID() noexcept { return _id; }
std::shared_ptr<MLX_Window> GraphicsSupport::getWindow() { return _window; } std::shared_ptr<MLX_Window> GraphicsSupport::getWindow() { return _window; }
void GraphicsSupport::beginRender() noexcept
{
if(!_renderer->beginFrame())
return;
_proj = glm::ortho<float>(0, _window->getWidth(), 0, _window->getHeight());
_renderer->getUniformBuffer()->setData(sizeof(_proj), &_proj);
}
void GraphicsSupport::clearRenderData() noexcept void GraphicsSupport::clearRenderData() noexcept
{ {
_textures_to_render.clear(); MLX_PROFILE_FUNCTION();
_drawlist.clear();
_pixel_put_pipeline.clear(); _pixel_put_pipeline.clear();
_text_put_pipeline->clear(); _text_manager.clear();
_texture_manager.clear();
} }
void GraphicsSupport::pixelPut(int x, int y, uint32_t color) noexcept void GraphicsSupport::pixelPut(int x, int y, std::uint32_t color) noexcept
{ {
MLX_PROFILE_FUNCTION();
_pixel_put_pipeline.setPixel(x, y, color); _pixel_put_pipeline.setPixel(x, y, color);
} }
void GraphicsSupport::stringPut(int x, int y, int color, std::string str) void GraphicsSupport::stringPut(int x, int y, std::uint32_t color, std::string str)
{ {
_text_put_pipeline->put(x, y, color, str); MLX_PROFILE_FUNCTION();
std::pair<DrawableResource*, bool> res = _text_manager.registerText(x, y, color, str);
if(!res.second) // if this is not a completly new text draw
{
auto it = std::find(_drawlist.begin(), _drawlist.end(), res.first);
if(it != _drawlist.end())
_drawlist.erase(it);
}
_drawlist.push_back(res.first);
} }
void GraphicsSupport::texturePut(Texture* texture, int x, int y) void GraphicsSupport::texturePut(Texture* texture, int x, int y)
{ {
_textures_to_render.emplace_back(texture, x, y); MLX_PROFILE_FUNCTION();
std::size_t hash = std::hash<TextureRenderData>{}(_textures_to_render.back()); auto res = _texture_manager.registerTexture(texture, x, y);
_textures_to_render.back().hash = hash; if(!res.second) // if this is not a completly new texture draw
auto it = std::find_if(_textures_to_render.begin(), _textures_to_render.end() - 1, [=](const TextureRenderData& rhs)
{ {
return rhs.hash == hash; auto it = std::find(_drawlist.begin(), _drawlist.end(), res.first);
}); if(it != _drawlist.end())
_drawlist.erase(it);
if(it != _textures_to_render.end() - 1) }
_textures_to_render.erase(it); _drawlist.push_back(res.first);
} }
void GraphicsSupport::loadFont(const std::filesystem::path& filepath, float scale) void GraphicsSupport::loadFont(const std::filesystem::path& filepath, float scale)
{ {
_text_put_pipeline->loadFont(filepath, scale); MLX_PROFILE_FUNCTION();
_text_manager.loadFont(*_renderer, filepath, scale);
}
void GraphicsSupport::tryEraseTextureFromManager(Texture* texture) noexcept
{
MLX_PROFILE_FUNCTION();
for(auto it = _drawlist.begin(); it != _drawlist.end();)
{
if(_texture_manager.isTextureKnown(texture))
it = _drawlist.erase(it);
else
++it;
}
_texture_manager.eraseTextures(texture);
} }
} }

65
src/core/memory.cpp git.filemode.normal_file
View File

@@ -0,0 +1,65 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* memory.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/07 16:32:01 by kbz_8 #+# #+# */
/* Updated: 2023/12/11 15:25:02 by kbz_8 ### ########.fr */
/* */
/* ************************************************************************** */
#include <core/memory.h>
#include <core/errors.h>
#include <algorithm>
namespace mlx
{
void* MemManager::malloc(std::size_t size)
{
void* ptr = std::malloc(size);
if(ptr != nullptr)
_blocks.push_back(ptr);
return ptr;
}
void* MemManager::calloc(std::size_t n, std::size_t size)
{
void* ptr = std::calloc(n, size);
if(ptr != nullptr)
_blocks.push_back(ptr);
return ptr;
}
void* MemManager::realloc(void* ptr, std::size_t size)
{
void* ptr2 = std::realloc(ptr, size);
if(ptr2 != nullptr)
_blocks.push_back(ptr2);
auto it = std::find(_blocks.begin(), _blocks.end(), ptr);
if(it != _blocks.end())
_blocks.erase(it);
return ptr2;
}
void MemManager::free(void* ptr)
{
auto it = std::find(_blocks.begin(), _blocks.end(), ptr);
if(it == _blocks.end())
{
core::error::report(e_kind::error, "Memory Manager : trying to free a pointer not allocated by the memory manager");
return;
}
std::free(*it);
_blocks.erase(it);
}
MemManager::~MemManager()
{
std::for_each(_blocks.begin(), _blocks.end(), [](void* ptr)
{
std::free(ptr);
});
}
}

41
src/core/memory.h git.filemode.normal_file
View File

@@ -0,0 +1,41 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* memory.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/07 16:31:51 by kbz_8 #+# #+# */
/* Updated: 2023/12/11 19:47:13 by kbz_8 ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_MEMORY__
#define __MLX_MEMORY__
#include <utils/singleton.h>
#include <mlx_profile.h>
#include <list>
namespace mlx
{
class MemManager : public Singleton<MemManager>
{
friend class Singleton<MemManager>;
public:
static void* malloc(std::size_t size);
static void* calloc(std::size_t n, std::size_t size);
static void* realloc(void* ptr, std::size_t size);
static void free(void* ptr);
private:
MemManager() = default;
~MemManager();
private:
inline static std::list<void*> _blocks;
};
}
#endif

View File

@@ -1,60 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* profile.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/11/10 08:49:17 by maldavid #+# #+# */
/* Updated: 2023/11/10 09:05:56 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_PROFILE__
#define __MLX_PROFILE__
// Try to identify the compiler
#if defined(__BORLANDC__)
#define MLX_COMPILER_BORDLAND
#elif defined(__clang__)
#define MLX_COMPILER_CLANG
#ifdef __MINGW32__
#define MLX_COMPILER_MINGW
#ifdef __MINGW64_VERSION_MAJOR
#define MLX_COMPILER_MINGW_W64
#endif
#endif
#elif defined(__GNUC__) || defined(__MINGW32__)
#define MLX_COMPILER_GCC
#ifdef __MINGW32__
#define MLX_COMPILER_MINGW
#ifdef __MINGW64_VERSION_MAJOR
#define MLX_COMPILER_MINGW_W64
#endif
#endif
#elif defined(__INTEL_COMPILER) || defined(__ICL)
#define MLX_COMPILER_INTEL
#elif defined(_MSC_VER)
#define MLX_COMPILER_MSVC
#else
#define MLX_COMPILER_UNKNOWN
#warning "This compiler is not fully supported"
#endif
// Checking common assumptions
#include <climits>
#include <cstdint>
static_assert(CHAR_BIT == 8, "CHAR_BIT is expected to be 8");
static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" );
static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size");
static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size");
static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size");
static_assert(sizeof(uint8_t) == 1, "uint8_t is not of the correct size" );
static_assert(sizeof(uint16_t) == 2, "uint16_t is not of the correct size");
static_assert(sizeof(uint32_t) == 4, "uint32_t is not of the correct size");
static_assert(sizeof(uint64_t) == 8, "uint64_t is not of the correct size");
#endif

79
src/core/profiler.cpp git.filemode.normal_file
View File

@@ -0,0 +1,79 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* profiler.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/10 13:56:21 by maldavid #+# #+# */
/* Updated: 2024/01/10 18:17:35 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <core/profiler.h>
#include <core/errors.h>
#include <iostream>
namespace mlx
{
void Profiler::beginRuntimeSession()
{
std::lock_guard lock(_mutex);
if(_runtime_session_began)
return;
_output_stream.open("./runtime_profile.mlx.json", std::ofstream::out | std::ofstream::trunc);
if(_output_stream.is_open())
writeHeader();
else
core::error::report(e_kind::error, "Profiler : cannot open runtime profile file");
_runtime_session_began = true;
}
void Profiler::appendProfileData(ProfileResult&& result)
{
std::lock_guard lock(_mutex);
auto it = _profile_data.find(result.name);
if(it != _profile_data.end())
{
result.elapsed_time = (result.elapsed_time + it->second.second.elapsed_time) / it->second.first;
_profile_data[result.name].first++;
_profile_data[result.name].second = result;
}
else
_profile_data[result.name] = std::make_pair(1, result);
}
void Profiler::writeProfile(const ProfileResult& result)
{
std::stringstream json;
json << std::setprecision(9) << std::fixed;
json << ",\n{\n";
json << "\t\"type\" : \"function\"," << '\n';
json << "\t\"name\" : \"" << result.name << "\"," << '\n';
json << "\t\"thread id\" : " << result.thread_id << "," << '\n';
json << "\t\"average duration\" : \"" << result.elapsed_time.count() << "ms\"\n";
json << "}";
_output_stream << json.str();
}
void Profiler::endRuntimeSession()
{
std::lock_guard lock(_mutex);
if(!_runtime_session_began)
return;
for(auto& [_, pair] : _profile_data)
writeProfile(pair.second);
writeFooter();
_output_stream.close();
_profile_data.clear();
_runtime_session_began = false;
}
Profiler::~Profiler()
{
if(!_runtime_session_began)
return;
endRuntimeSession();
}
}

146
src/core/profiler.h git.filemode.normal_file
View File

@@ -0,0 +1,146 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* profiler.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/10 13:35:45 by maldavid #+# #+# */
/* Updated: 2024/03/24 14:41:27 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_PROFILER__
#define __MLX_PROFILER__
#include <utils/singleton.h>
#include <mlx_profile.h>
#include <chrono>
#include <string>
#include <thread>
#include <mutex>
#include <fstream>
#include <unordered_map>
#include <sstream>
#include <iomanip>
namespace mlx
{
using FloatingPointMilliseconds = std::chrono::duration<double, std::milli>;
struct ProfileResult
{
std::string name;
FloatingPointMilliseconds elapsed_time;
std::thread::id thread_id;
};
class Profiler : public Singleton<Profiler>
{
friend class Singleton<Profiler>;
public:
Profiler(const Profiler&) = delete;
Profiler(Profiler&&) = delete;
void appendProfileData(ProfileResult&& result);
private:
Profiler() { beginRuntimeSession(); }
~Profiler();
void beginRuntimeSession();
void writeProfile(const ProfileResult& result);
void endRuntimeSession();
inline void writeHeader()
{
_output_stream << "{\"profileData\":[{}";
_output_stream.flush();
}
inline void writeFooter()
{
_output_stream << "]}";
_output_stream.flush();
}
private:
std::unordered_map<std::string, std::pair<std::size_t, ProfileResult>> _profile_data;
std::ofstream _output_stream;
std::mutex _mutex;
bool _runtime_session_began = false;
};
class ProfilerTimer
{
public:
ProfilerTimer(const char* name) : _name(name)
{
_start_timepoint = std::chrono::steady_clock::now();
}
inline void stop()
{
auto end_timepoint = std::chrono::steady_clock::now();
auto high_res_start = FloatingPointMilliseconds{ _start_timepoint.time_since_epoch() };
auto elapsed_time = std::chrono::time_point_cast<std::chrono::milliseconds>(end_timepoint).time_since_epoch() - std::chrono::time_point_cast<std::chrono::milliseconds>(_start_timepoint).time_since_epoch();
Profiler::get().appendProfileData({ _name, elapsed_time, std::this_thread::get_id() });
_stopped = true;
}
~ProfilerTimer()
{
if(!_stopped)
stop();
}
private:
std::chrono::time_point<std::chrono::steady_clock> _start_timepoint;
const char* _name;
bool _stopped = false;
};
namespace ProfilerUtils
{
template <std::size_t N>
struct ChangeResult
{
char data[N];
};
template <std::size_t N, std::size_t K>
constexpr auto cleanupOutputString(const char(&expr)[N], const char(&remove)[K])
{
ChangeResult<N> result = {};
std::size_t src_index = 0;
std::size_t dst_index = 0;
while(src_index < N)
{
std::size_t match_index = 0;
while(match_index < K - 1 && src_index + match_index < N - 1 && expr[src_index + match_index] == remove[match_index])
match_index++;
if(match_index == K - 1)
src_index += match_index;
result.data[dst_index++] = expr[src_index] == '"' ? '\'' : expr[src_index];
src_index++;
}
return result;
}
}
}
#ifdef PROFILER
#define MLX_PROFILE_SCOPE_LINE2(name, line) constexpr auto fixedName##line = ::mlx::ProfilerUtils::cleanupOutputString(name, "__cdecl ");\
::mlx::ProfilerTimer timer##line(fixedName##line.data)
#define MLX_PROFILE_SCOPE_LINE(name, line) MLX_PROFILE_SCOPE_LINE2(name, line)
#define MLX_PROFILE_SCOPE(name) MLX_PROFILE_SCOPE_LINE(name, __LINE__)
#define MLX_PROFILE_FUNCTION() MLX_PROFILE_SCOPE(MLX_FUNC_SIG)
#else
#define MLX_PROFILE_SCOPE(name)
#define MLX_PROFILE_FUNCTION()
#endif
#endif

View File

@@ -6,24 +6,19 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/05 16:30:19 by maldavid #+# #+# */ /* Created: 2022/10/05 16:30:19 by maldavid #+# #+# */
/* Updated: 2023/08/28 10:49:03 by maldavid ### ########.fr */ /* Updated: 2024/02/23 22:27:30 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "inputs.h" #include "inputs.h"
#include <mlx.h> #include <mlx.h>
#include <cstring> #include <core/profiler.h>
namespace mlx namespace mlx
{ {
Input::Input()
{
std::memset(_keys.data(), 0, SDL_NUM_SCANCODES);
std::memset(_mouse.data(), 0, 8);
}
void Input::update() void Input::update()
{ {
MLX_PROFILE_FUNCTION();
_xRel = 0; _xRel = 0;
_yRel = 0; _yRel = 0;
@@ -38,8 +33,8 @@ namespace mlx
_yRel = _event.motion.yrel; _yRel = _event.motion.yrel;
} }
uint32_t id = _event.window.windowID; std::uint32_t id = _event.window.windowID;
if(!_events_hooks.count(id)) if(_events_hooks.find(id) == _events_hooks.end())
continue; continue;
auto& hooks = _events_hooks[id]; auto& hooks = _events_hooks[id];
@@ -47,7 +42,6 @@ namespace mlx
{ {
case SDL_KEYDOWN: case SDL_KEYDOWN:
{ {
_keys[_event.key.keysym.scancode] = static_cast<uint8_t>(action::down);
if(hooks[MLX_KEYDOWN].hook) if(hooks[MLX_KEYDOWN].hook)
hooks[MLX_KEYDOWN].hook(_event.key.keysym.scancode, hooks[MLX_KEYDOWN].param); hooks[MLX_KEYDOWN].hook(_event.key.keysym.scancode, hooks[MLX_KEYDOWN].param);
break; break;
@@ -55,7 +49,6 @@ namespace mlx
case SDL_KEYUP: case SDL_KEYUP:
{ {
_keys[_event.key.keysym.scancode] = static_cast<uint8_t>(action::up);
if(hooks[MLX_KEYUP].hook) if(hooks[MLX_KEYUP].hook)
hooks[MLX_KEYUP].hook(_event.key.keysym.scancode, hooks[MLX_KEYUP].param); hooks[MLX_KEYUP].hook(_event.key.keysym.scancode, hooks[MLX_KEYUP].param);
break; break;
@@ -63,7 +56,6 @@ namespace mlx
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
{ {
_mouse[_event.button.button] = static_cast<uint8_t>(action::down);
if(hooks[MLX_MOUSEDOWN].hook) if(hooks[MLX_MOUSEDOWN].hook)
hooks[MLX_MOUSEDOWN].hook(_event.button.button, hooks[MLX_MOUSEDOWN].param); hooks[MLX_MOUSEDOWN].hook(_event.button.button, hooks[MLX_MOUSEDOWN].param);
break; break;
@@ -71,12 +63,28 @@ namespace mlx
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:
{ {
_mouse[_event.button.button] = static_cast<uint8_t>(action::up);
if(hooks[MLX_MOUSEUP].hook) if(hooks[MLX_MOUSEUP].hook)
hooks[MLX_MOUSEUP].hook(_event.button.button, hooks[MLX_MOUSEUP].param); hooks[MLX_MOUSEUP].hook(_event.button.button, hooks[MLX_MOUSEUP].param);
break; break;
} }
case SDL_MOUSEWHEEL:
{
if(hooks[MLX_MOUSEWHEEL].hook)
{
if(_event.wheel.y > 0) // scroll up
hooks[MLX_MOUSEWHEEL].hook(1, hooks[MLX_MOUSEWHEEL].param);
else if(_event.wheel.y < 0) // scroll down
hooks[MLX_MOUSEWHEEL].hook(2, hooks[MLX_MOUSEWHEEL].param);
if(_event.wheel.x > 0) // scroll right
hooks[MLX_MOUSEWHEEL].hook(3, hooks[MLX_MOUSEWHEEL].param);
else if(_event.wheel.x < 0) // scroll left
hooks[MLX_MOUSEWHEEL].hook(4, hooks[MLX_MOUSEWHEEL].param);
}
break;
}
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
{ {
auto& win_hook = hooks[MLX_WINDOW_EVENT]; auto& win_hook = hooks[MLX_WINDOW_EVENT];
@@ -115,19 +123,19 @@ namespace mlx
case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_WINDOWEVENT_FOCUS_GAINED:
{ {
if(win_hook.hook) if(win_hook.hook)
win_hook.hook(4, win_hook.param); win_hook.hook(5, win_hook.param);
break; break;
} }
case SDL_WINDOWEVENT_LEAVE: case SDL_WINDOWEVENT_LEAVE:
{ {
if(win_hook.hook) if(win_hook.hook)
win_hook.hook(5, win_hook.param); win_hook.hook(6, win_hook.param);
break; break;
} }
case SDL_WINDOWEVENT_FOCUS_LOST: case SDL_WINDOWEVENT_FOCUS_LOST:
{ {
if(win_hook.hook) if(win_hook.hook)
win_hook.hook(4, win_hook.param); win_hook.hook(7, win_hook.param);
break; break;
} }

View File

@@ -6,40 +6,36 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/05 16:27:35 by maldavid #+# #+# */ /* Created: 2022/10/05 16:27:35 by maldavid #+# #+# */
/* Updated: 2023/04/19 12:14:43 by maldavid ### ########.fr */ /* Updated: 2024/04/22 17:35:23 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include <array> #include <array>
#include <memory> #include <memory>
#include <vector>
#include <cstdint> #include <cstdint>
#include <functional> #include <function.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <unordered_map> #include <unordered_map>
#include <mlx_profile.h>
#include "window.h" #include "window.h"
namespace mlx namespace mlx
{ {
enum class action : uint8_t { up = (1 << 1), down = (1 << 2) };
struct Hook struct Hook
{ {
std::function<int(int, void*)> hook; func::function<int(int, void*)> hook;
void* param = nullptr; void* param = nullptr;
}; };
class Input class Input
{ {
public: public:
Input(); Input() = default;
void update(); void update();
inline bool getInKey(const SDL_Scancode key, action type = action::down) const noexcept { return _keys[key] & static_cast<uint8_t>(type); }
inline bool getInMouse(const uint8_t button, action type = action::down) const noexcept { return _mouse[button] & static_cast<uint8_t>(type); }
inline bool isMouseMoving() const noexcept { return _xRel || _yRel; } inline bool isMouseMoving() const noexcept { return _xRel || _yRel; }
inline int getX() const noexcept { return _x; } inline int getX() const noexcept { return _x; }
@@ -48,7 +44,8 @@ namespace mlx
inline int getXRel() const noexcept { return _xRel; } inline int getXRel() const noexcept { return _xRel; }
inline int getYRel() const noexcept { return _yRel; } inline int getYRel() const noexcept { return _yRel; }
inline bool is_running() const noexcept { return !_end; } inline bool isRunning() const noexcept { return !_end; }
inline constexpr void run() noexcept { _end = false; }
inline constexpr void finish() noexcept { _end = true; } inline constexpr void finish() noexcept { _end = true; }
inline void addWindow(std::shared_ptr<MLX_Window> window) inline void addWindow(std::shared_ptr<MLX_Window> window)
@@ -57,7 +54,7 @@ namespace mlx
_events_hooks[window->getID()] = {}; _events_hooks[window->getID()] = {};
} }
inline void onEvent(uint32_t id, int event, int (*funct_ptr)(int, void*), void* param) noexcept inline void onEvent(std::uint32_t id, int event, int (*funct_ptr)(int, void*), void* param) noexcept
{ {
_events_hooks[id][event].hook = funct_ptr; _events_hooks[id][event].hook = funct_ptr;
_events_hooks[id][event].param = param; _events_hooks[id][event].param = param;
@@ -66,11 +63,9 @@ namespace mlx
~Input() = default; ~Input() = default;
private: private:
std::array<uint8_t, SDL_NUM_SCANCODES> _keys; std::unordered_map<std::uint32_t, std::shared_ptr<MLX_Window>> _windows;
std::unordered_map<uint32_t, std::shared_ptr<MLX_Window>> _windows; std::unordered_map<std::uint32_t, std::array<Hook, 6>> _events_hooks;
std::unordered_map<uint32_t, std::array<Hook, 5>> _events_hooks;
SDL_Event _event; SDL_Event _event;
std::array<uint8_t, 8> _mouse;
int _x = 0; int _x = 0;
int _y = 0; int _y = 0;

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 17:36:44 by maldavid #+# #+# */ /* Created: 2022/10/04 17:36:44 by maldavid #+# #+# */
/* Updated: 2023/11/25 11:48:26 by maldavid ### ########.fr */ /* Updated: 2024/01/16 07:59:21 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -17,19 +17,21 @@
namespace mlx namespace mlx
{ {
#if SDL_BYTEORDER == SDL_BIG_ENDIAN #if SDL_BYTEORDER == SDL_BIG_ENDIAN
constexpr const uint32_t rmask = 0xff000000; constexpr const std::uint32_t rmask = 0xff000000;
constexpr const uint32_t gmask = 0x00ff0000; constexpr const std::uint32_t gmask = 0x00ff0000;
constexpr const uint32_t bmask = 0x0000ff00; constexpr const std::uint32_t bmask = 0x0000ff00;
constexpr const uint32_t amask = 0x000000ff; constexpr const std::uint32_t amask = 0x000000ff;
#else #else
constexpr const uint32_t rmask = 0x000000ff; constexpr const std::uint32_t rmask = 0x000000ff;
constexpr const uint32_t gmask = 0x0000ff00; constexpr const std::uint32_t gmask = 0x0000ff00;
constexpr const uint32_t bmask = 0x00ff0000; constexpr const std::uint32_t bmask = 0x00ff0000;
constexpr const uint32_t amask = 0xff000000; constexpr const std::uint32_t amask = 0xff000000;
#endif #endif
MLX_Window::MLX_Window(std::size_t w, std::size_t h, const std::string& title) : _width(w), _height(h) MLX_Window::MLX_Window(std::size_t w, std::size_t h, const std::string& title) : _width(w), _height(h)
{ {
if(title.find("vvaas") != std::string::npos)
core::error::report(e_kind::message, "vvaas est mauvais");
_win = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_VULKAN | SDL_WINDOW_SHOWN); _win = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_VULKAN | SDL_WINDOW_SHOWN);
if(!_win) if(!_win)
core::error::report(e_kind::fatal_error, std::string("unable to open a new window, ") + SDL_GetError()); core::error::report(e_kind::fatal_error, std::string("unable to open a new window, ") + SDL_GetError());
@@ -40,14 +42,15 @@ namespace mlx
void MLX_Window::destroy() noexcept void MLX_Window::destroy() noexcept
{ {
if(_win) if(_win != nullptr)
SDL_DestroyWindow(_win);
if(_icon)
SDL_FreeSurface(_icon);
}
MLX_Window::~MLX_Window()
{ {
destroy(); SDL_DestroyWindow(_win);
_win = nullptr;
}
if(_icon != nullptr)
{
SDL_FreeSurface(_icon);
_icon = nullptr;
}
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/04 21:53:12 by maldavid #+# #+# */ /* Created: 2022/10/04 21:53:12 by maldavid #+# #+# */
/* Updated: 2023/11/25 11:33:32 by maldavid ### ########.fr */ /* Updated: 2023/12/21 00:24:26 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,6 +15,7 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <string> #include <string>
#include <mlx_profile.h>
namespace mlx namespace mlx
{ {
@@ -26,18 +27,18 @@ namespace mlx
inline SDL_Window* getNativeWindow() const noexcept { return _win; } inline SDL_Window* getNativeWindow() const noexcept { return _win; }
inline int getWidth() const noexcept { return _width; } inline int getWidth() const noexcept { return _width; }
inline int getHeight() const noexcept { return _height; } inline int getHeight() const noexcept { return _height; }
inline uint32_t getID() const noexcept { return _id; } inline std::uint32_t getID() const noexcept { return _id; }
void destroy() noexcept; void destroy() noexcept;
~MLX_Window(); ~MLX_Window() = default;
private: private:
SDL_Surface* _icon = nullptr; SDL_Surface* _icon = nullptr;
SDL_Window* _win = nullptr; SDL_Window* _win = nullptr;
int _width = 0; int _width = 0;
int _height = 0; int _height = 0;
uint32_t _id = -1; std::uint32_t _id = -1;
}; };
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 18:55:57 by maldavid #+# #+# */ /* Created: 2022/10/08 18:55:57 by maldavid #+# #+# */
/* Updated: 2023/11/16 13:54:25 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:28:35 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -14,18 +14,19 @@
#include <renderer/command/vk_cmd_pool.h> #include <renderer/command/vk_cmd_pool.h>
#include <renderer/command/vk_cmd_buffer.h> #include <renderer/command/vk_cmd_buffer.h>
#include <renderer/core/render_core.h> #include <renderer/core/render_core.h>
#include <core/profiler.h>
#include <vma.h> #include <vma.h>
#include <cstring> #include <cstring>
#include <iostream>
namespace mlx namespace mlx
{ {
void Buffer::create(Buffer::kind type, VkDeviceSize size, VkBufferUsageFlags usage, const char* name, const void* data) void Buffer::create(Buffer::kind type, VkDeviceSize size, VkBufferUsageFlags usage, const char* name, const void* data)
{ {
MLX_PROFILE_FUNCTION();
_usage = usage; _usage = usage;
if(type == Buffer::kind::constant) if(type == Buffer::kind::constant || type == Buffer::kind::dynamic_device_local)
{ {
if(data == nullptr) if(data == nullptr && type == Buffer::kind::constant)
{ {
core::error::report(e_kind::warning, "Vulkan : trying to create constant buffer without data (constant buffers cannot be modified after creation)"); core::error::report(e_kind::warning, "Vulkan : trying to create constant buffer without data (constant buffers cannot be modified after creation)");
return; return;
@@ -45,13 +46,14 @@ namespace mlx
mapMem(&mapped); mapMem(&mapped);
std::memcpy(mapped, data, size); std::memcpy(mapped, data, size);
unmapMem(); unmapMem();
if(type == Buffer::kind::constant) if(type == Buffer::kind::constant || type == Buffer::kind::dynamic_device_local)
pushToGPU(); pushToGPU();
} }
} }
void Buffer::destroy() noexcept void Buffer::destroy() noexcept
{ {
MLX_PROFILE_FUNCTION();
if(_is_mapped) if(_is_mapped)
unmapMem(); unmapMem();
if(_buffer != VK_NULL_HANDLE) if(_buffer != VK_NULL_HANDLE)
@@ -59,8 +61,9 @@ namespace mlx
_buffer = VK_NULL_HANDLE; _buffer = VK_NULL_HANDLE;
} }
void Buffer::createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size, const char* name) void Buffer::createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size, [[maybe_unused]] const char* name)
{ {
MLX_PROFILE_FUNCTION();
VkBufferCreateInfo bufferInfo{}; VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size; bufferInfo.size = size;
@@ -74,7 +77,7 @@ namespace mlx
alloc_name.append("_index_buffer"); alloc_name.append("_index_buffer");
else if(usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) else if(usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
alloc_name.append("_vertex_buffer"); alloc_name.append("_vertex_buffer");
else if((usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) != 1) else if(!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT))
alloc_name.append("_buffer"); alloc_name.append("_buffer");
_allocation = Render_Core::get().getAllocator().createBuffer(&bufferInfo, &info, _buffer, alloc_name.c_str()); _allocation = Render_Core::get().getAllocator().createBuffer(&bufferInfo, &info, _buffer, alloc_name.c_str());
#else #else
@@ -83,8 +86,34 @@ namespace mlx
_size = size; _size = size;
} }
bool Buffer::copyFromBuffer(const Buffer& buffer) noexcept
{
MLX_PROFILE_FUNCTION();
if(!(_usage & VK_BUFFER_USAGE_TRANSFER_DST_BIT))
{
core::error::report(e_kind::error, "Vulkan : buffer cannot be the destination of a copy because it does not have the correct usage flag");
return false;
}
if(!(buffer._usage & VK_BUFFER_USAGE_TRANSFER_SRC_BIT))
{
core::error::report(e_kind::error, "Vulkan : buffer cannot be the source of a copy because it does not have the correct usage flag");
return false;
}
CmdBuffer& cmd = Render_Core::get().getSingleTimeCmdBuffer();
cmd.beginRecord();
cmd.copyBuffer(*this, const_cast<Buffer&>(buffer));
cmd.endRecord();
cmd.submitIdle();
return true;
}
void Buffer::pushToGPU() noexcept void Buffer::pushToGPU() noexcept
{ {
MLX_PROFILE_FUNCTION();
VmaAllocationCreateInfo alloc_info{}; VmaAllocationCreateInfo alloc_info{};
alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE; alloc_info.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
@@ -97,25 +126,8 @@ namespace mlx
newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, nullptr); newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, nullptr);
#endif #endif
CmdPool cmdpool; if(newBuffer.copyFromBuffer(*this)) // if the copy succeded we swap the buffers, otherwise the new one is deleted
cmdpool.init();
CmdBuffer cmdBuffer;
cmdBuffer.init(&cmdpool);
cmdBuffer.beginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
VkBufferCopy copyRegion{};
copyRegion.size = _size;
vkCmdCopyBuffer(cmdBuffer.get(), _buffer, newBuffer._buffer, 1, &copyRegion);
cmdBuffer.endRecord();
cmdBuffer.submitIdle();
cmdBuffer.destroy();
cmdpool.destroy();
this->swap(newBuffer); this->swap(newBuffer);
newBuffer.destroy(); newBuffer.destroy();
} }
@@ -140,6 +152,12 @@ namespace mlx
VkBufferUsageFlags temp_u = _usage; VkBufferUsageFlags temp_u = _usage;
_usage = buffer._usage; _usage = buffer._usage;
buffer._usage = temp_u; buffer._usage = temp_u;
#ifdef DEBUG
std::string temp_n = _name;
_name = buffer._name;
buffer._name = temp_n;
#endif
} }
void Buffer::flush(VkDeviceSize size, VkDeviceSize offset) void Buffer::flush(VkDeviceSize size, VkDeviceSize offset)

View File

@@ -6,22 +6,24 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 23:18:52 by maldavid #+# #+# */ /* Created: 2022/10/06 23:18:52 by maldavid #+# #+# */
/* Updated: 2023/11/16 13:56:19 by maldavid ### ########.fr */ /* Updated: 2024/01/11 05:16:58 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_BUFFER__ #ifndef __MLX_VK_BUFFER__
#define __MLX_VK_BUFFER__ #define __MLX_VK_BUFFER__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <renderer/core/render_core.h> #include <renderer/core/render_core.h>
#include <renderer/core/cmd_resource.h>
namespace mlx namespace mlx
{ {
class Buffer class Buffer : public CmdResource
{ {
public: public:
enum class kind { dynamic, uniform, constant }; enum class kind { dynamic, dynamic_device_local, uniform, constant };
void create(kind type, VkDeviceSize size, VkBufferUsageFlags usage, const char* name, const void* data = nullptr); void create(kind type, VkDeviceSize size, VkBufferUsageFlags usage, const char* name, const void* data = nullptr);
void destroy() noexcept; void destroy() noexcept;
@@ -31,6 +33,7 @@ namespace mlx
inline void unmapMem() noexcept { Render_Core::get().getAllocator().unmapMemory(_allocation); _is_mapped = false; } inline void unmapMem() noexcept { Render_Core::get().getAllocator().unmapMemory(_allocation); _is_mapped = false; }
void flush(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0); void flush(VkDeviceSize size = VK_WHOLE_SIZE, VkDeviceSize offset = 0);
bool copyFromBuffer(const Buffer& buffer) noexcept;
inline VkBuffer& operator()() noexcept { return _buffer; } inline VkBuffer& operator()() noexcept { return _buffer; }
inline VkBuffer& get() noexcept { return _buffer; } inline VkBuffer& get() noexcept { return _buffer; }

View File

@@ -6,13 +6,14 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/25 15:05:05 by maldavid #+# #+# */ /* Created: 2023/01/25 15:05:05 by maldavid #+# #+# */
/* Updated: 2023/11/14 03:25:59 by maldavid ### ########.fr */ /* Updated: 2024/01/10 23:05:15 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __VK_IBO__ #ifndef __VK_IBO__
#define __VK_IBO__ #define __VK_IBO__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include "vk_buffer.h" #include "vk_buffer.h"
#include <renderer/renderer.h> #include <renderer/renderer.h>
@@ -22,8 +23,8 @@ namespace mlx
class C_IBO : public Buffer class C_IBO : public Buffer
{ {
public: public:
inline void create(uint32_t size, const uint16_t* data, const char* name) { Buffer::create(Buffer::kind::constant, size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, name, data); } inline void create(std::uint32_t size, const std::uint16_t* data, const char* name) { Buffer::create(Buffer::kind::constant, size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, name, data); }
inline void bind(Renderer& renderer) noexcept { vkCmdBindIndexBuffer(renderer.getActiveCmdBuffer().get(), _buffer, _offset, VK_INDEX_TYPE_UINT16); } inline void bind(Renderer& renderer) noexcept { renderer.getActiveCmdBuffer().bindIndexBuffer(*this); }
}; };
} }

View File

@@ -6,18 +6,20 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:45:52 by maldavid #+# #+# */ /* Created: 2022/10/06 18:45:52 by maldavid #+# #+# */
/* Updated: 2023/11/16 13:57:42 by maldavid ### ########.fr */ /* Updated: 2024/01/10 18:30:57 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "vk_ubo.h" #include "vk_ubo.h"
#include <cstring> #include <cstring>
#include <renderer/renderer.h> #include <renderer/renderer.h>
#include <core/profiler.h>
namespace mlx namespace mlx
{ {
void UBO::create(Renderer* renderer, uint32_t size, const char* name) void UBO::create(Renderer* renderer, std::uint32_t size, [[maybe_unused]] const char* name)
{ {
MLX_PROFILE_FUNCTION();
_renderer = renderer; _renderer = renderer;
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
@@ -35,14 +37,16 @@ namespace mlx
} }
} }
void UBO::setData(uint32_t size, const void* data) void UBO::setData(std::uint32_t size, const void* data)
{ {
std::memcpy(_maps[_renderer->getActiveImageIndex()], data, static_cast<size_t>(size)); MLX_PROFILE_FUNCTION();
std::memcpy(_maps[_renderer->getActiveImageIndex()], data, static_cast<std::size_t>(size));
} }
void UBO::setDynamicData(uint32_t size, const void* data) void UBO::setDynamicData(std::uint32_t size, const void* data)
{ {
std::memcpy(_maps[_renderer->getActiveImageIndex()], data, static_cast<size_t>(size)); MLX_PROFILE_FUNCTION();
std::memcpy(_maps[_renderer->getActiveImageIndex()], data, static_cast<std::size_t>(size));
_buffers[_renderer->getActiveImageIndex()].flush(); _buffers[_renderer->getActiveImageIndex()].flush();
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:45:29 by maldavid #+# #+# */ /* Created: 2022/10/06 18:45:29 by maldavid #+# #+# */
/* Updated: 2023/11/14 03:26:10 by maldavid ### ########.fr */ /* Updated: 2023/12/08 19:06:28 by kbz_8 ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -16,16 +16,17 @@
#include "vk_buffer.h" #include "vk_buffer.h"
#include <array> #include <array>
#include <cstddef> #include <cstddef>
#include <mlx_profile.h>
namespace mlx namespace mlx
{ {
class UBO class UBO
{ {
public: public:
void create(class Renderer* renderer, uint32_t size, const char* name); void create(class Renderer* renderer, std::uint32_t size, const char* name);
void setData(uint32_t size, const void* data); void setData(std::uint32_t size, const void* data);
void setDynamicData(uint32_t size, const void* data); void setDynamicData(std::uint32_t size, const void* data);
void destroy() noexcept; void destroy() noexcept;

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:28:08 by maldavid #+# #+# */ /* Created: 2022/10/06 18:28:08 by maldavid #+# #+# */
/* Updated: 2023/11/10 08:33:52 by maldavid ### ########.fr */ /* Updated: 2023/12/12 22:17:14 by kbz_8 ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,17 +15,41 @@
namespace mlx namespace mlx
{ {
void VBO::setData(uint32_t size, const void* data) void VBO::setData(std::uint32_t size, const void* data)
{ {
if(size > getSize()) if(size > getSize())
{
core::error::report(e_kind::error, "Vulkan : trying to store to much data in a vertex buffer (%d bytes in %d bytes)", size, getSize()); core::error::report(e_kind::error, "Vulkan : trying to store to much data in a vertex buffer (%d bytes in %d bytes)", size, getSize());
return;
}
if(data == nullptr) if(data == nullptr)
core::error::report(e_kind::warning, "Vulkan : mapping null data in a vertex buffer"); core::error::report(e_kind::warning, "Vulkan : mapping null data in a vertex buffer");
void* temp = nullptr; void* temp = nullptr;
mapMem(&temp); mapMem(&temp);
std::memcpy(temp, data, static_cast<size_t>(size)); std::memcpy(temp, data, static_cast<std::size_t>(size));
unmapMem(); unmapMem();
} }
void D_VBO::setData(std::uint32_t size, const void* data)
{
if(size > getSize())
{
core::error::report(e_kind::error, "Vulkan : trying to store to much data in a vertex buffer (%d bytes in %d bytes)", size, getSize());
return;
}
if(data == nullptr)
core::error::report(e_kind::warning, "Vulkan : mapping null data in a vertex buffer");
Buffer tmp_buf;
#ifdef DEBUG
tmp_buf.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, "tmp_buffer", data);
#else
tmp_buf.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, nullptr, data);
#endif
copyFromBuffer(tmp_buf);
tmp_buf.destroy();
}
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:27:38 by maldavid #+# #+# */ /* Created: 2022/10/06 18:27:38 by maldavid #+# #+# */
/* Updated: 2023/11/14 04:53:36 by maldavid ### ########.fr */ /* Updated: 2024/01/10 23:04:40 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,22 +15,31 @@
#include "vk_buffer.h" #include "vk_buffer.h"
#include <renderer/renderer.h> #include <renderer/renderer.h>
#include <mlx_profile.h>
namespace mlx namespace mlx
{ {
class VBO : public Buffer class VBO : public Buffer
{ {
public: public:
inline void create(uint32_t size, const char* name) { Buffer::create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name); } inline void create(std::uint32_t size, const void* data, const char* name) { Buffer::create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name, data); }
void setData(uint32_t size, const void* data); void setData(std::uint32_t size, const void* data);
inline void bind(Renderer& renderer) noexcept { vkCmdBindVertexBuffers(renderer.getActiveCmdBuffer().get(), 0, 1, &_buffer, &_offset); } inline void bind(Renderer& renderer) noexcept { renderer.getActiveCmdBuffer().bindVertexBuffer(*this); }
};
class D_VBO : public Buffer
{
public:
inline void create(std::uint32_t size, const void* data, const char* name) { Buffer::create(Buffer::kind::dynamic_device_local, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name, data); }
void setData(std::uint32_t size, const void* data);
inline void bind(Renderer& renderer) noexcept { renderer.getActiveCmdBuffer().bindVertexBuffer(*this); }
}; };
class C_VBO : public Buffer class C_VBO : public Buffer
{ {
public: public:
inline void create(uint32_t size, const void* data, const char* name) { Buffer::create(Buffer::kind::constant, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name, data); } inline void create(std::uint32_t size, const void* data, const char* name) { Buffer::create(Buffer::kind::constant, size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, name, data); }
inline void bind(Renderer& renderer) noexcept { vkCmdBindVertexBuffers(renderer.getActiveCmdBuffer().get(), 0, 1, &_buffer, &_offset); } inline void bind(Renderer& renderer) noexcept { renderer.getActiveCmdBuffer().bindVertexBuffer(*this); }
}; };
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 17:50:52 by maldavid #+# #+# */ /* Created: 2023/04/02 17:50:52 by maldavid #+# #+# */
/* Updated: 2023/04/02 17:51:46 by maldavid ### ########.fr */ /* Updated: 2023/12/17 20:10:45 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -18,7 +18,7 @@ namespace mlx
{ {
_cmd_pool.init(); _cmd_pool.init();
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
_cmd_buffers[i].init(this); _cmd_buffers[i].init(CmdBuffer::kind::long_time, this);
} }
void CmdManager::beginRecord(int active_image_index) void CmdManager::beginRecord(int active_image_index)

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 17:48:52 by maldavid #+# #+# */ /* Created: 2023/04/02 17:48:52 by maldavid #+# #+# */
/* Updated: 2023/04/02 17:50:48 by maldavid ### ########.fr */ /* Updated: 2024/01/03 15:27:35 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,6 +15,7 @@
#include <array> #include <array>
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <renderer/core/render_core.h> #include <renderer/core/render_core.h>
#include <renderer/command/vk_cmd_pool.h> #include <renderer/command/vk_cmd_pool.h>

View File

@@ -0,0 +1,63 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* single_time_cmd_manager.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/15 19:57:49 by maldavid #+# #+# */
/* Updated: 2024/01/11 03:13:21 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <algorithm>
#include <renderer/command/single_time_cmd_manager.h>
#include <renderer/core/render_core.h>
namespace mlx
{
void SingleTimeCmdManager::init() noexcept
{
_pool.init();
for(int i = 0; i < BASE_POOL_SIZE; i++)
{
_buffers.emplace_back();
_buffers.back().init(CmdBuffer::kind::single_time, &_pool);
}
}
CmdBuffer& SingleTimeCmdManager::getCmdBuffer() noexcept
{
for(CmdBuffer& buf : _buffers)
{
if(buf.isReadyToBeUsed())
{
buf.reset();
return buf;
}
}
_buffers.emplace_back().init(CmdBuffer::kind::single_time, &_pool);
return _buffers.back();
}
void SingleTimeCmdManager::updateSingleTimesCmdBuffersSubmitState() noexcept
{
for(CmdBuffer& cmd : _buffers)
cmd.updateSubmitState();
}
void SingleTimeCmdManager::waitForAllExecutions() noexcept
{
for(CmdBuffer& cmd : _buffers)
cmd.waitForExecution();
}
void SingleTimeCmdManager::destroy() noexcept
{
std::for_each(_buffers.begin(), _buffers.end(), [](CmdBuffer& buf)
{
buf.destroy();
});
_pool.destroy();
}
}

View File

@@ -0,0 +1,50 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* single_time_cmd_manager.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/15 18:25:57 by maldavid #+# #+# */
/* Updated: 2024/01/07 01:30:19 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_SINGLE_TIME_CMD_MANAGER__
#define __MLX_SINGLE_TIME_CMD_MANAGER__
#include <vector>
#include <renderer/command/vk_cmd_buffer.h>
#include <renderer/command/vk_cmd_pool.h>
namespace mlx
{
class CmdBuffer;
class SingleTimeCmdManager
{
friend class Render_Core;
public:
SingleTimeCmdManager() = default;
void init() noexcept;
void destroy() noexcept;
void updateSingleTimesCmdBuffersSubmitState() noexcept;
void waitForAllExecutions() noexcept;
inline CmdPool& getCmdPool() noexcept { return _pool; }
CmdBuffer& getCmdBuffer() noexcept;
~SingleTimeCmdManager() = default;
inline static constexpr const std::uint8_t BASE_POOL_SIZE = 16;
private:
std::vector<CmdBuffer> _buffers;
CmdPool _pool;
};
}
#endif

View File

@@ -6,24 +6,45 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:26:06 by maldavid #+# #+# */ /* Created: 2022/10/06 18:26:06 by maldavid #+# #+# */
/* Updated: 2023/11/08 20:17:49 by maldavid ### ########.fr */ /* Updated: 2024/02/25 08:02:26 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "vk_cmd_buffer.h" #include "vk_cmd_buffer.h"
#include <renderer/core/cmd_resource.h>
#include <renderer/core/render_core.h> #include <renderer/core/render_core.h>
#include <renderer/command/cmd_manager.h> #include <renderer/command/cmd_manager.h>
#include <renderer/core/vk_semaphore.h> #include <renderer/core/vk_semaphore.h>
#include <renderer/buffers/vk_buffer.h>
#include <renderer/images/vk_image.h>
#include <core/profiler.h>
namespace mlx namespace mlx
{ {
void CmdBuffer::init(CmdManager* manager) bool vector_push_back_if_not_found(std::vector<CmdResource*>& vector, CmdResource* res)
{ {
init(&manager->getCmdPool()); auto it = std::find_if(vector.begin(), vector.end(), [=](const CmdResource* vres)
{
return vres->getUUID() == res->getUUID();
});
if(it == vector.end())
{
vector.push_back(res);
return true;
}
return false;
} }
void CmdBuffer::init(CmdPool* pool) void CmdBuffer::init(kind type, CmdManager* manager)
{ {
init(type, &manager->getCmdPool());
}
void CmdBuffer::init(kind type, CmdPool* pool)
{
MLX_PROFILE_FUNCTION();
_type = type;
_pool = pool; _pool = pool;
VkCommandBufferAllocateInfo allocInfo{}; VkCommandBufferAllocateInfo allocInfo{};
@@ -32,18 +53,23 @@ namespace mlx
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = 1; allocInfo.commandBufferCount = 1;
if(vkAllocateCommandBuffers(Render_Core::get().getDevice().get(), &allocInfo, &_cmd_buffer) != VK_SUCCESS) VkResult res = vkAllocateCommandBuffers(Render_Core::get().getDevice().get(), &allocInfo, &_cmd_buffer);
core::error::report(e_kind::fatal_error, "Vulkan : failed to allocate command buffer"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to allocate command buffer, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new command buffer"); core::error::report(e_kind::message, "Vulkan : created new command buffer");
#endif #endif
_fence.init(); _fence.init();
_state = state::idle;
} }
void CmdBuffer::beginRecord(VkCommandBufferUsageFlags usage) void CmdBuffer::beginRecord(VkCommandBufferUsageFlags usage)
{ {
if(_is_recording) MLX_PROFILE_FUNCTION();
if(!isInit())
core::error::report(e_kind::fatal_error, "Vulkan : begenning record on un uninit command buffer");
if(_state == state::recording)
return; return;
VkCommandBufferBeginInfo beginInfo{}; VkCommandBufferBeginInfo beginInfo{};
@@ -52,62 +78,291 @@ namespace mlx
if(vkBeginCommandBuffer(_cmd_buffer, &beginInfo) != VK_SUCCESS) if(vkBeginCommandBuffer(_cmd_buffer, &beginInfo) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to begin recording command buffer"); core::error::report(e_kind::fatal_error, "Vulkan : failed to begin recording command buffer");
_is_recording = true; _state = state::recording;
}
void CmdBuffer::bindVertexBuffer(Buffer& buffer) noexcept
{
MLX_PROFILE_FUNCTION();
if(!isRecording())
{
core::error::report(e_kind::warning, "Vulkan : trying to bind a vertex buffer to a non recording command buffer");
return;
}
VkDeviceSize offset[] = { buffer.getOffset() };
vkCmdBindVertexBuffers(_cmd_buffer, 0, 1, &buffer.get(), offset);
buffer.recordedInCmdBuffer();
vector_push_back_if_not_found(_cmd_resources, &buffer);
}
void CmdBuffer::bindIndexBuffer(Buffer& buffer) noexcept
{
MLX_PROFILE_FUNCTION();
if(!isRecording())
{
core::error::report(e_kind::warning, "Vulkan : trying to bind a index buffer to a non recording command buffer");
return;
}
vkCmdBindIndexBuffer(_cmd_buffer, buffer.get(), buffer.getOffset(), VK_INDEX_TYPE_UINT16);
buffer.recordedInCmdBuffer();
vector_push_back_if_not_found(_cmd_resources, &buffer);
}
void CmdBuffer::copyBuffer(Buffer& dst, Buffer& src) noexcept
{
MLX_PROFILE_FUNCTION();
if(!isRecording())
{
core::error::report(e_kind::warning, "Vulkan : trying to do a buffer to buffer copy in a non recording command buffer");
return;
}
preTransferBarrier();
VkBufferCopy copyRegion{};
copyRegion.size = src.getSize();
vkCmdCopyBuffer(_cmd_buffer, src.get(), dst.get(), 1, &copyRegion);
postTransferBarrier();
dst.recordedInCmdBuffer();
src.recordedInCmdBuffer();
vector_push_back_if_not_found(_cmd_resources, &dst);
vector_push_back_if_not_found(_cmd_resources, &src);
}
void CmdBuffer::copyBufferToImage(Buffer& buffer, Image& image) noexcept
{
MLX_PROFILE_FUNCTION();
if(!isRecording())
{
core::error::report(e_kind::warning, "Vulkan : trying to do a buffer to image copy in a non recording command buffer");
return;
}
preTransferBarrier();
VkBufferImageCopy region{};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = { 0, 0, 0 };
region.imageExtent = { image.getWidth(), image.getHeight(), 1 };
vkCmdCopyBufferToImage(_cmd_buffer, buffer.get(), image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
postTransferBarrier();
image.recordedInCmdBuffer();
buffer.recordedInCmdBuffer();
vector_push_back_if_not_found(_cmd_resources, &image);
vector_push_back_if_not_found(_cmd_resources, &buffer);
}
void CmdBuffer::copyImagetoBuffer(Image& image, Buffer& buffer) noexcept
{
MLX_PROFILE_FUNCTION();
if(!isRecording())
{
core::error::report(e_kind::warning, "Vulkan : trying to do an image to buffer copy in a non recording command buffer");
return;
}
preTransferBarrier();
VkBufferImageCopy region{};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = { 0, 0, 0 };
region.imageExtent = { image.getWidth(), image.getHeight(), 1 };
vkCmdCopyImageToBuffer(_cmd_buffer, image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer.get(), 1, &region);
postTransferBarrier();
image.recordedInCmdBuffer();
buffer.recordedInCmdBuffer();
vector_push_back_if_not_found(_cmd_resources, &buffer);
vector_push_back_if_not_found(_cmd_resources, &image);
}
void CmdBuffer::transitionImageLayout(Image& image, VkImageLayout new_layout) noexcept
{
MLX_PROFILE_FUNCTION();
if(!isRecording())
{
core::error::report(e_kind::warning, "Vulkan : trying to do an image layout transition in a non recording command buffer");
return;
}
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = image.getLayout();
barrier.newLayout = new_layout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image.get();
barrier.subresourceRange.aspectMask = isDepthFormat(image.getFormat()) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
barrier.srcAccessMask = layoutToAccessMask(image.getLayout(), false);
barrier.dstAccessMask = layoutToAccessMask(new_layout, true);
if(isStencilFormat(image.getFormat()))
barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
VkPipelineStageFlags sourceStage = 0;
if(barrier.oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
sourceStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
else if(barrier.srcAccessMask != 0)
sourceStage = RCore::accessFlagsToPipelineStage(barrier.srcAccessMask, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
else
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkPipelineStageFlags destinationStage = 0;
if(barrier.newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
destinationStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
else if(barrier.dstAccessMask != 0)
destinationStage = RCore::accessFlagsToPipelineStage(barrier.dstAccessMask, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
else
destinationStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
vkCmdPipelineBarrier(_cmd_buffer, sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
image.recordedInCmdBuffer();
vector_push_back_if_not_found(_cmd_resources, &image);
} }
void CmdBuffer::endRecord() void CmdBuffer::endRecord()
{ {
if(!_is_recording) MLX_PROFILE_FUNCTION();
if(!isInit())
core::error::report(e_kind::fatal_error, "Vulkan : ending record on un uninit command buffer");
if(_state != state::recording)
return; return;
if(vkEndCommandBuffer(_cmd_buffer) != VK_SUCCESS) if(vkEndCommandBuffer(_cmd_buffer) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to end recording command buffer"); core::error::report(e_kind::fatal_error, "Vulkan : failed to end recording command buffer");
_is_recording = false; _state = state::idle;
} }
void CmdBuffer::submitIdle() noexcept void CmdBuffer::submitIdle(bool shouldWaitForExecution) noexcept
{ {
auto device = Render_Core::get().getDevice().get(); MLX_PROFILE_FUNCTION();
if(_type != kind::single_time)
VkSubmitInfo submitInfo = {}; {
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; core::error::report(e_kind::error, "Vulkan : try to perform an idle submit on a command buffer that is not single-time, this is not allowed");
submitInfo.commandBufferCount = 1; return;
submitInfo.pCommandBuffers = &_cmd_buffer;
VkFenceCreateInfo fenceCreateInfo = {};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
VkFence fence;
vkCreateFence(device, &fenceCreateInfo, nullptr, &fence);
vkResetFences(device, 1, &fence);
vkQueueSubmit(Render_Core::get().getQueue().getGraphic(), 1, &submitInfo, fence);
vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
vkDestroyFence(device, fence, nullptr);
} }
void CmdBuffer::submit(Semaphore& semaphores) noexcept _fence.reset();
{
VkSemaphore signalSemaphores[] = { semaphores.getRenderImageSemaphore() };
VkSemaphore waitSemaphores[] = { semaphores.getImageSemaphore() };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
VkSubmitInfo submitInfo{}; VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores; submitInfo.pCommandBuffers = &_cmd_buffer;
VkResult res = vkQueueSubmit(Render_Core::get().getQueue().getGraphic(), 1, &submitInfo, _fence.get());
if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan error : failed to submit a single time command buffer, %s", RCore::verbaliseResultVk(res));
_state = state::submitted;
if(shouldWaitForExecution)
waitForExecution();
}
void CmdBuffer::submit(Semaphore* semaphores) noexcept
{
MLX_PROFILE_FUNCTION();
std::array<VkSemaphore, 1> signalSemaphores;
std::array<VkSemaphore, 1> waitSemaphores;
if(semaphores != nullptr)
{
signalSemaphores[0] = semaphores->getRenderImageSemaphore();
waitSemaphores[0] = semaphores->getImageSemaphore();
}
else
{
signalSemaphores[0] = VK_NULL_HANDLE;
waitSemaphores[0] = VK_NULL_HANDLE;
}
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
_fence.reset();
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = (semaphores == nullptr ? 0 : waitSemaphores.size());
submitInfo.pWaitSemaphores = waitSemaphores.data();
submitInfo.pWaitDstStageMask = waitStages; submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &_cmd_buffer; submitInfo.pCommandBuffers = &_cmd_buffer;
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = (semaphores == nullptr ? 0 : signalSemaphores.size());
submitInfo.pSignalSemaphores = signalSemaphores; submitInfo.pSignalSemaphores = signalSemaphores.data();
if(vkQueueSubmit(Render_Core::get().getQueue().getGraphic(), 1, &submitInfo, _fence.get()) != VK_SUCCESS) VkResult res = vkQueueSubmit(Render_Core::get().getQueue().getGraphic(), 1, &submitInfo, _fence.get());
core::error::report(e_kind::fatal_error, "Vulkan error : failed to submit draw command buffer"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan error : failed to submit draw command buffer, %s", RCore::verbaliseResultVk(res));
_state = state::submitted;
}
void CmdBuffer::updateSubmitState() noexcept
{
MLX_PROFILE_FUNCTION();
if(!_fence.isReady())
return;
for(CmdResource* res : _cmd_resources)
res->removedFromCmdBuffer();
_cmd_resources.clear();
_state = state::ready;
}
void CmdBuffer::preTransferBarrier() noexcept
{
MLX_PROFILE_FUNCTION();
VkMemoryBarrier memoryBarrier{};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.pNext = nullptr;
memoryBarrier.srcAccessMask = 0U;
memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
vkCmdPipelineBarrier(_cmd_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
}
void CmdBuffer::postTransferBarrier() noexcept
{
MLX_PROFILE_FUNCTION();
VkMemoryBarrier memoryBarrier{};
memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
memoryBarrier.pNext = nullptr;
memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_UNIFORM_READ_BIT;
vkCmdPipelineBarrier(_cmd_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
} }
void CmdBuffer::destroy() noexcept void CmdBuffer::destroy() noexcept
{ {
MLX_PROFILE_FUNCTION();
_fence.destroy(); _fence.destroy();
_cmd_buffer = VK_NULL_HANDLE; _cmd_buffer = VK_NULL_HANDLE;
_state = state::uninit;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed command buffer");
#endif
} }
} }

View File

@@ -3,47 +3,86 @@
/* ::: :::::::: */ /* ::: :::::::: */
/* vk_cmd_buffer.h :+: :+: :+: */ /* vk_cmd_buffer.h :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: bonsthie <bonsthie@42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:25:42 by maldavid #+# #+# */ /* Created: 2022/10/06 18:25:42 by maldavid #+# #+# */
/* Updated: 2023/04/21 13:20:49 by maldavid ### ########.fr */ /* Updated: 2024/08/08 17:46:00 by bonsthie ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_CMD_BUFFER__ #ifndef __MLX_VK_CMD_BUFFER__
#define __MLX_VK_CMD_BUFFER__ #define __MLX_VK_CMD_BUFFER__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <renderer/core/vk_fence.h> #include <renderer/core/vk_fence.h>
#include <vector>
#include <algorithm>
namespace mlx namespace mlx
{ {
class Buffer;
class Image;
class CmdBuffer class CmdBuffer
{ {
public: public:
void init(class CmdManager* manager); enum class state
void init(class CmdPool* pool); {
uninit = 0, // buffer not initialized or destroyed
ready, // buffer ready to be used after having been submitted
idle, // buffer has recorded informations but has not been submitted
recording, // buffer is currently recording
submitted, // buffer has been submitted
};
enum class kind
{
single_time = 0,
long_time
};
public:
void init(kind type, class CmdManager* manager);
void init(kind type, class CmdPool* pool);
void destroy() noexcept; void destroy() noexcept;
void beginRecord(VkCommandBufferUsageFlags usage = 0); void beginRecord(VkCommandBufferUsageFlags usage = 0);
void submit(class Semaphore& semaphores) noexcept; void submit(class Semaphore* semaphores) noexcept;
void submitIdle() noexcept; void submitIdle(bool shouldWaitForExecution = true) noexcept; // TODO : handle `shouldWaitForExecution` as false by default (needs to modify CmdResources lifetimes to do so)
inline void waitForExecution() noexcept { _fence.waitAndReset(); } void updateSubmitState() noexcept;
inline void waitForExecution() noexcept { _fence.wait(); updateSubmitState(); _state = state::ready; }
inline void reset() noexcept { vkResetCommandBuffer(_cmd_buffer, 0); } inline void reset() noexcept { vkResetCommandBuffer(_cmd_buffer, 0); }
void endRecord(); void endRecord();
inline bool isRecording() const noexcept { return _is_recording; } void bindVertexBuffer(Buffer& buffer) noexcept;
inline bool isInit() const noexcept { return _cmd_buffer != VK_NULL_HANDLE; } void bindIndexBuffer(Buffer& buffer) noexcept;
void copyBuffer(Buffer& dst, Buffer& src) noexcept;
void copyBufferToImage(Buffer& buffer, Image& image) noexcept;
void copyImagetoBuffer(Image& image, Buffer& buffer) noexcept;
void transitionImageLayout(Image& image, VkImageLayout new_layout) noexcept;
inline bool isInit() const noexcept { return _state != state::uninit; }
inline bool isReadyToBeUsed() const noexcept { return _state == state::ready; }
inline bool isRecording() const noexcept { return _state == state::recording; }
inline bool hasBeenSubmitted() const noexcept { return _state == state::submitted; }
inline state getCurrentState() const noexcept { return _state; }
inline VkCommandBuffer& operator()() noexcept { return _cmd_buffer; } inline VkCommandBuffer& operator()() noexcept { return _cmd_buffer; }
inline VkCommandBuffer& get() noexcept { return _cmd_buffer; } inline VkCommandBuffer& get() noexcept { return _cmd_buffer; }
inline Fence& getFence() noexcept { return _fence; } inline Fence& getFence() noexcept { return _fence; }
private: private:
void preTransferBarrier() noexcept;
void postTransferBarrier() noexcept;
private:
std::vector<class CmdResource*> _cmd_resources;
Fence _fence; Fence _fence;
VkCommandBuffer _cmd_buffer = VK_NULL_HANDLE; VkCommandBuffer _cmd_buffer = VK_NULL_HANDLE;
class CmdPool* _pool = nullptr; class CmdPool* _pool = nullptr;
bool _is_recording = false; state _state = state::uninit;
kind _type;
}; };
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:24:33 by maldavid #+# #+# */ /* Created: 2022/10/06 18:24:33 by maldavid #+# #+# */
/* Updated: 2023/11/18 17:23:38 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:23:20 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -20,10 +20,11 @@ namespace mlx
VkCommandPoolCreateInfo poolInfo{}; VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
poolInfo.queueFamilyIndex = Render_Core::get().getQueue().getFamilies().graphicsFamily.value(); poolInfo.queueFamilyIndex = Render_Core::get().getQueue().getFamilies().graphics_family.value();
if(vkCreateCommandPool(Render_Core::get().getDevice().get(), &poolInfo, nullptr, &_cmd_pool) != VK_SUCCESS) VkResult res = vkCreateCommandPool(Render_Core::get().getDevice().get(), &poolInfo, nullptr, &_cmd_pool);
core::error::report(e_kind::fatal_error, "Vulkan : failed to create command pool"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create command pool, %s", RCore::verbaliseResultVk(res));
} }
void CmdPool::destroy() noexcept void CmdPool::destroy() noexcept

View File

@@ -6,13 +6,14 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/06 18:24:12 by maldavid #+# #+# */ /* Created: 2022/10/06 18:24:12 by maldavid #+# #+# */
/* Updated: 2022/12/18 01:08:31 by maldavid ### ########.fr */ /* Updated: 2024/01/03 15:27:26 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_CMD_POOL__ #ifndef __MLX_VK_CMD_POOL__
#define __MLX_VK_CMD_POOL__ #define __MLX_VK_CMD_POOL__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
namespace mlx namespace mlx

44
src/renderer/core/cmd_resource.h git.filemode.normal_file
View File

@@ -0,0 +1,44 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* cmd_resource.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/12/16 20:44:29 by maldavid #+# #+# */
/* Updated: 2024/03/14 17:28:08 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_COMMAND_RESOURCE__
#define __MLX_COMMAND_RESOURCE__
#include <function.h>
#include <core/UUID.h>
namespace mlx
{
class CmdResource
{
friend class SingleTimeCmdManager;
public:
enum class state
{
in_cmd_buffer = 0,
out_cmd_buffer,
};
public:
CmdResource() : _uuid() {}
inline void recordedInCmdBuffer() noexcept { _state = state::in_cmd_buffer; }
inline void removedFromCmdBuffer() noexcept { _state = state::out_cmd_buffer; }
inline UUID getUUID() const noexcept { return _uuid; }
virtual ~CmdResource() = default;
private:
UUID _uuid;
state _state = state::out_cmd_buffer;
};
}
#endif

32
src/renderer/core/drawable_resource.h git.filemode.normal_file
View File

@@ -0,0 +1,32 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* drawable_resource.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/10 21:00:37 by maldavid #+# #+# */
/* Updated: 2024/01/11 01:21:15 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_DRAWABLE_RESOURCE__
#define __MLX_DRAWABLE_RESOURCE__
#include <mlx_profile.h>
#include <volk.h>
#include <array>
namespace mlx
{
class DrawableResource
{
public:
DrawableResource() = default;
virtual void render(std::array<VkDescriptorSet, 2>& sets, class Renderer& renderer) = 0;
virtual void resetUpdate() {}
virtual ~DrawableResource() = default;
};
}
#endif

View File

@@ -6,25 +6,36 @@
/* By: kbz_8 <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: kbz_8 <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/20 22:02:37 by kbz_8 #+# #+# */ /* Created: 2023/10/20 22:02:37 by kbz_8 #+# #+# */
/* Updated: 2023/11/14 12:45:29 by maldavid ### ########.fr */ /* Updated: 2024/09/14 00:04:16 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include <core/profile.h> #include <mlx_profile.h>
#include <core/errors.h> #include <core/errors.h>
#include <cstdio> #include <core/profiler.h>
#define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 0
#define VMA_VULKAN_VERSION 1002000 #define VMA_VULKAN_VERSION 1002000
#define VMA_ASSERT(expr) (static_cast<bool>(expr) ? void(0) : mlx::core::error::report(e_kind::fatal_error, "Graphics allocator : an assertion has been catched : '%s'", #expr)) #define VMA_ASSERT(expr) ((void)0)
#define VMA_IMPLEMENTATION #define VMA_IMPLEMENTATION
#ifdef MLX_COMPILER_CLANG #ifdef MLX_COMPILER_CLANG
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnullability-completeness" #pragma clang diagnostic ignored "-Weverything"
#include <renderer/core/memory.h> #include <renderer/core/memory.h>
#pragma clang diagnostic pop #pragma clang diagnostic pop
#elif defined(MLX_COMPILER_GCC)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wparentheses"
#pragma GCC diagnostic ignored "-Wparentheses"
#include <renderer/core/memory.h>
#pragma GCC diagnostic pop
#else #else
#include <renderer/core/memory.h> #include <renderer/core/memory.h>
#endif #endif
@@ -67,71 +78,91 @@ namespace mlx
allocatorCreateInfo.instance = Render_Core::get().getInstance().get(); allocatorCreateInfo.instance = Render_Core::get().getInstance().get();
allocatorCreateInfo.pVulkanFunctions = &vma_vulkan_func; allocatorCreateInfo.pVulkanFunctions = &vma_vulkan_func;
if(vmaCreateAllocator(&allocatorCreateInfo, &_allocator) != VK_SUCCESS) VkResult res = vmaCreateAllocator(&allocatorCreateInfo, &_allocator);
core::error::report(e_kind::fatal_error, "Vulkan : failed to create graphics memory allocator"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Graphics allocator : failed to create graphics memory allocator, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new allocator"); core::error::report(e_kind::message, "Graphics allocator : created new allocator");
#endif #endif
} }
VmaAllocation GPUallocator::createBuffer(const VkBufferCreateInfo* binfo, const VmaAllocationCreateInfo* vinfo, VkBuffer& buffer, const char* name) noexcept VmaAllocation GPUallocator::createBuffer(const VkBufferCreateInfo* binfo, const VmaAllocationCreateInfo* vinfo, VkBuffer& buffer, const char* name) noexcept
{ {
MLX_PROFILE_FUNCTION();
VmaAllocation allocation; VmaAllocation allocation;
if(vmaCreateBuffer(_allocator, binfo, vinfo, &buffer, &allocation, nullptr) != VK_SUCCESS) VkResult res = vmaCreateBuffer(_allocator, binfo, vinfo, &buffer, &allocation, nullptr);
core::error::report(e_kind::fatal_error, "Vulkan : failed to allocate a buffer"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Graphics allocator : failed to allocate a buffer, %s", RCore::verbaliseResultVk(res));
if(name != nullptr) if(name != nullptr)
{
Render_Core::get().getLayers().setDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_BUFFER, (std::uint64_t)buffer, name);
vmaSetAllocationName(_allocator, allocation, name); vmaSetAllocationName(_allocator, allocation, name);
}
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Graphics Allocator : created new buffer"); core::error::report(e_kind::message, "Graphics Allocator : created new buffer '%s'", name);
#endif #endif
_active_buffers_allocations++;
return allocation; return allocation;
} }
void GPUallocator::destroyBuffer(VmaAllocation allocation, VkBuffer buffer) noexcept void GPUallocator::destroyBuffer(VmaAllocation allocation, VkBuffer buffer) noexcept
{ {
MLX_PROFILE_FUNCTION();
vkDeviceWaitIdle(Render_Core::get().getDevice().get()); vkDeviceWaitIdle(Render_Core::get().getDevice().get());
vmaDestroyBuffer(_allocator, buffer, allocation); vmaDestroyBuffer(_allocator, buffer, allocation);
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Graphics Allocator : destroyed buffer"); core::error::report(e_kind::message, "Graphics Allocator : destroyed buffer");
#endif #endif
_active_buffers_allocations--;
} }
VmaAllocation GPUallocator::createImage(const VkImageCreateInfo* iminfo, const VmaAllocationCreateInfo* vinfo, VkImage& image, const char* name) noexcept VmaAllocation GPUallocator::createImage(const VkImageCreateInfo* iminfo, const VmaAllocationCreateInfo* vinfo, VkImage& image, const char* name) noexcept
{ {
MLX_PROFILE_FUNCTION();
VmaAllocation allocation; VmaAllocation allocation;
if(vmaCreateImage(_allocator, iminfo, vinfo, &image, &allocation, nullptr) != VK_SUCCESS) VkResult res = vmaCreateImage(_allocator, iminfo, vinfo, &image, &allocation, nullptr);
core::error::report(e_kind::fatal_error, "Vulkan : failed to allocate an image"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Graphics allocator : failed to allocate an image, %s", RCore::verbaliseResultVk(res));
if(name != nullptr) if(name != nullptr)
{
Render_Core::get().getLayers().setDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_IMAGE, (std::uint64_t)image, name);
vmaSetAllocationName(_allocator, allocation, name); vmaSetAllocationName(_allocator, allocation, name);
}
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Graphics Allocator : created new image"); core::error::report(e_kind::message, "Graphics Allocator : created new image '%s'", name);
#endif #endif
_active_images_allocations++;
return allocation; return allocation;
} }
void GPUallocator::destroyImage(VmaAllocation allocation, VkImage image) noexcept void GPUallocator::destroyImage(VmaAllocation allocation, VkImage image) noexcept
{ {
MLX_PROFILE_FUNCTION();
vkDeviceWaitIdle(Render_Core::get().getDevice().get()); vkDeviceWaitIdle(Render_Core::get().getDevice().get());
vmaDestroyImage(_allocator, image, allocation); vmaDestroyImage(_allocator, image, allocation);
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Graphics Allocator : destroyed image"); core::error::report(e_kind::message, "Graphics Allocator : destroyed image");
#endif #endif
_active_images_allocations--;
} }
void GPUallocator::mapMemory(VmaAllocation allocation, void** data) noexcept void GPUallocator::mapMemory(VmaAllocation allocation, void** data) noexcept
{ {
if(vmaMapMemory(_allocator, allocation, data) != VK_SUCCESS) MLX_PROFILE_FUNCTION();
core::error::report(e_kind::fatal_error, "Graphics allocator : unable to map GPU memory to CPU memory"); VkResult res = vmaMapMemory(_allocator, allocation, data);
if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Graphics allocator : unable to map GPU memory to CPU memory, %s", RCore::verbaliseResultVk(res));
} }
void GPUallocator::unmapMemory(VmaAllocation allocation) noexcept void GPUallocator::unmapMemory(VmaAllocation allocation) noexcept
{ {
MLX_PROFILE_FUNCTION();
vmaUnmapMemory(_allocator, allocation); vmaUnmapMemory(_allocator, allocation);
} }
void GPUallocator::dumpMemoryToJson() void GPUallocator::dumpMemoryToJson()
{ {
static uint32_t id = 0; static std::uint32_t id = 0;
std::string name("memory_dump"); std::string name("memory_dump");
name.append(std::to_string(id) + ".json"); name.append(std::to_string(id) + ".json");
std::ofstream file(name); std::ofstream file(name);
@@ -150,11 +181,23 @@ namespace mlx
void GPUallocator::flush(VmaAllocation allocation, VkDeviceSize size, VkDeviceSize offset) noexcept void GPUallocator::flush(VmaAllocation allocation, VkDeviceSize size, VkDeviceSize offset) noexcept
{ {
MLX_PROFILE_FUNCTION();
vmaFlushAllocation(_allocator, allocation, offset, size); vmaFlushAllocation(_allocator, allocation, offset, size);
} }
void GPUallocator::destroy() noexcept void GPUallocator::destroy() noexcept
{ {
if(_active_images_allocations != 0)
core::error::report(e_kind::error, "Graphics allocator : some user-dependant allocations were not freed before destroying the display (%d active allocations). You may have not destroyed all the MLX resources you've created", _active_images_allocations);
else if(_active_buffers_allocations != 0)
core::error::report(e_kind::error, "Graphics allocator : some MLX-dependant allocations were not freed before destroying the display (%d active allocations). This is an error in the MLX, please report this should not happen", _active_buffers_allocations);
if(_active_images_allocations < 0 || _active_buffers_allocations < 0)
core::error::report(e_kind::warning, "Graphics allocator : the impossible happened, the MLX has freed more allocations than it has made (wtf)");
vmaDestroyAllocator(_allocator); vmaDestroyAllocator(_allocator);
_active_buffers_allocations = 0;
_active_images_allocations = 0;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a graphics allocator");
#endif
} }
} }

View File

@@ -6,13 +6,14 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/10/20 02:13:03 by maldavid #+# #+# */ /* Created: 2023/10/20 02:13:03 by maldavid #+# #+# */
/* Updated: 2023/11/14 09:46:32 by maldavid ### ########.fr */ /* Updated: 2024/03/25 16:01:06 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_MEMORY__ #ifndef __MLX_VK_MEMORY__
#define __MLX_VK_MEMORY__ #define __MLX_VK_MEMORY__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <vma.h> #include <vma.h>
@@ -43,6 +44,8 @@ namespace mlx
private: private:
VmaAllocator _allocator; VmaAllocator _allocator;
std::int32_t _active_buffers_allocations = 0;
std::int32_t _active_images_allocations = 0;
}; };
} }

View File

@@ -6,37 +6,34 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/12/17 23:33:34 by maldavid #+# #+# */ /* Created: 2022/12/17 23:33:34 by maldavid #+# #+# */
/* Updated: 2023/11/20 12:04:51 by maldavid ### ########.fr */ /* Updated: 2024/04/23 20:32:54 by kiroussa ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#define VOLK_IMPLEMENTATION #define VOLK_IMPLEMENTATION
#if defined(_WIN32) || defined(_WIN64) #include <mlx_profile.h>
#define VK_USE_PLATFORM_WIN32_KHR #include <renderer/core/render_core.h>
#elif defined(__APPLE__) || defined(__MACH__) #include <renderer/command/vk_cmd_buffer.h>
#define VK_USE_PLATFORM_MACOS_MVK
#else
#define VK_USE_PLATFORM_XLIB_KHR
#endif
#include "render_core.h"
#include <mutex>
#ifdef DEBUG #ifdef DEBUG
#ifdef MLX_COMPILER_MSVC
#pragma NOTE("MLX is being compiled in debug mode, this activates Vulkan's validation layers and debug messages which may impact rendering performances")
#else
#warning "MLX is being compiled in debug mode, this activates Vulkan's validation layers and debug messages which may impact rendering performances" #warning "MLX is being compiled in debug mode, this activates Vulkan's validation layers and debug messages which may impact rendering performances"
#endif #endif
#endif
namespace mlx namespace mlx
{ {
namespace RCore namespace RCore
{ {
std::optional<uint32_t> findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties, bool error) std::optional<std::uint32_t> findMemoryType(std::uint32_t typeFilter, VkMemoryPropertyFlags properties, bool error)
{ {
VkPhysicalDeviceMemoryProperties memProperties; VkPhysicalDeviceMemoryProperties memProperties;
vkGetPhysicalDeviceMemoryProperties(Render_Core::get().getDevice().getPhysicalDevice(), &memProperties); vkGetPhysicalDeviceMemoryProperties(Render_Core::get().getDevice().getPhysicalDevice(), &memProperties);
for(uint32_t i = 0; i < memProperties.memoryTypeCount; i++) for(std::uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
{ {
if((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) if((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
return i; return i;
@@ -45,11 +42,82 @@ namespace mlx
core::error::report(e_kind::fatal_error, "Vulkan : failed to find suitable memory type"); core::error::report(e_kind::fatal_error, "Vulkan : failed to find suitable memory type");
return std::nullopt; return std::nullopt;
} }
const char* verbaliseResultVk(VkResult result)
{
switch(result)
{
case VK_SUCCESS: return "Success";
case VK_NOT_READY: return "A fence or query has not yet completed";
case VK_TIMEOUT: return "A wait operation has not completed in the specified time";
case VK_EVENT_SET: return "An event is signaled";
case VK_EVENT_RESET: return "An event is unsignaled";
case VK_INCOMPLETE: return "A return array was too small for the result";
case VK_ERROR_OUT_OF_HOST_MEMORY: return "A host memory allocation has failed";
case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "A device memory allocation has failed";
case VK_ERROR_INITIALIZATION_FAILED: return "Initialization of an object could not be completed for implementation-specific reasons";
case VK_ERROR_DEVICE_LOST: return "The logical or physical device has been lost";
case VK_ERROR_MEMORY_MAP_FAILED: return "Mapping of a memory object has failed";
case VK_ERROR_LAYER_NOT_PRESENT: return "A requested layer is not present or could not be loaded";
case VK_ERROR_EXTENSION_NOT_PRESENT: return "A requested extension is not supported";
case VK_ERROR_FEATURE_NOT_PRESENT: return "A requested feature is not supported";
case VK_ERROR_INCOMPATIBLE_DRIVER: return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
case VK_ERROR_TOO_MANY_OBJECTS: return "Too many objects of the type have already been created";
case VK_ERROR_FORMAT_NOT_SUPPORTED: return "A requested format is not supported on this device";
case VK_ERROR_SURFACE_LOST_KHR: return "A surface is no longer available";
case VK_SUBOPTIMAL_KHR: return "A swapchain no longer matches the surface properties exactly, but can still be used";
case VK_ERROR_OUT_OF_DATE_KHR: return "A surface has changed in such a way that it is no longer compatible with the swapchain";
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "The display used by a swapchain does not use the same presentable image layout";
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
case VK_ERROR_VALIDATION_FAILED_EXT: return "A validation layer found an error";
default: return "Unknown Vulkan error";
}
return nullptr;
}
VkPipelineStageFlags accessFlagsToPipelineStage(VkAccessFlags accessFlags, VkPipelineStageFlags stageFlags)
{
VkPipelineStageFlags stages = 0;
while(accessFlags != 0)
{
VkAccessFlagBits AccessFlag = static_cast<VkAccessFlagBits>(accessFlags & (~(accessFlags - 1)));
if(AccessFlag == 0 || (AccessFlag & (AccessFlag - 1)) != 0)
core::error::report(e_kind::fatal_error, "Vulkan : an error has been caught during access flag to pipeline stage operation");
accessFlags &= ~AccessFlag;
switch(AccessFlag)
{
case VK_ACCESS_INDIRECT_COMMAND_READ_BIT: stages |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; break;
case VK_ACCESS_INDEX_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break;
case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break;
case VK_ACCESS_UNIFORM_READ_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break;
case VK_ACCESS_SHADER_READ_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_SHADER_WRITE_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break;
case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break;
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break;
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break;
case VK_ACCESS_TRANSFER_READ_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break;
case VK_ACCESS_TRANSFER_WRITE_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break;
case VK_ACCESS_HOST_READ_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break;
case VK_ACCESS_HOST_WRITE_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break;
case VK_ACCESS_MEMORY_READ_BIT: break;
case VK_ACCESS_MEMORY_WRITE_BIT: break;
default: core::error::report(e_kind::error, "Vulkan : unknown access flag"); break;
}
}
return stages;
}
} }
void Render_Core::init() void Render_Core::init()
{ {
volkInitialize(); if(volkInitialize() != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan loader : cannot load %s, are you sure Vulkan is installed on your system ?", VULKAN_LIB_NAME);
_instance.init(); _instance.init();
volkLoadInstance(_instance.get()); volkLoadInstance(_instance.get());
@@ -58,6 +126,7 @@ namespace mlx
volkLoadDevice(_device.get()); volkLoadDevice(_device.get());
_queues.init(); _queues.init();
_allocator.init(); _allocator.init();
_cmd_manager.init();
_is_init = true; _is_init = true;
} }
@@ -68,6 +137,8 @@ namespace mlx
vkDeviceWaitIdle(_device()); vkDeviceWaitIdle(_device());
_pool_manager.destroyAllPools();
_cmd_manager.destroy();
_allocator.destroy(); _allocator.destroy();
_device.destroy(); _device.destroy();
_layers.destroy(); _layers.destroy();

View File

@@ -6,16 +6,20 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:16:32 by maldavid #+# #+# */ /* Created: 2022/10/08 19:16:32 by maldavid #+# #+# */
/* Updated: 2023/11/20 07:20:43 by maldavid ### ########.fr */ /* Updated: 2024/01/20 08:17:58 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_RENDER_CORE__ #ifndef __MLX_RENDER_CORE__
#define __MLX_RENDER_CORE__ #define __MLX_RENDER_CORE__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <optional> #include <optional>
#include <renderer/command/single_time_cmd_manager.h>
#include <renderer/descriptors/descriptor_pool_manager.h>
#include <renderer/descriptors/vk_descriptor_pool.h>
#include "vk_queues.h" #include "vk_queues.h"
#include "vk_device.h" #include "vk_device.h"
#include "vk_instance.h" #include "vk_instance.h"
@@ -29,7 +33,9 @@ namespace mlx
{ {
namespace RCore namespace RCore
{ {
std::optional<uint32_t> findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties, bool error = true); std::optional<std::uint32_t> findMemoryType(std::uint32_t typeFilter, VkMemoryPropertyFlags properties, bool error = true);
const char* verbaliseResultVk(VkResult result);
VkPipelineStageFlags accessFlagsToPipelineStage(VkAccessFlags accessFlags, VkPipelineStageFlags stageFlags);
} }
#ifdef DEBUG #ifdef DEBUG
@@ -41,26 +47,36 @@ namespace mlx
const std::vector<const char*> validationLayers = { "VK_LAYER_KHRONOS_validation" }; const std::vector<const char*> validationLayers = { "VK_LAYER_KHRONOS_validation" };
constexpr const int MAX_FRAMES_IN_FLIGHT = 3; constexpr const int MAX_FRAMES_IN_FLIGHT = 3;
constexpr const int MAX_SETS_PER_POOL = 512;
constexpr const int NUMBER_OF_UNIFORM_BUFFERS = 1; // change this if for wathever reason more than one uniform buffer is needed
class Render_Core : public Singleton<Render_Core> class Render_Core : public Singleton<Render_Core>
{ {
public: friend class Singleton<Render_Core>;
Render_Core() = default;
public:
void init(); void init();
void destroy(); void destroy();
inline bool isInit() const noexcept { return _is_init; }
inline Instance& getInstance() noexcept { return _instance; } inline Instance& getInstance() noexcept { return _instance; }
inline Device& getDevice() noexcept { return _device; } inline Device& getDevice() noexcept { return _device; }
inline Queues& getQueue() noexcept { return _queues; } inline Queues& getQueue() noexcept { return _queues; }
inline GPUallocator& getAllocator() noexcept { return _allocator; } inline GPUallocator& getAllocator() noexcept { return _allocator; }
inline ValidationLayers& getLayers() noexcept { return _layers; } inline ValidationLayers& getLayers() noexcept { return _layers; }
inline CmdBuffer& getSingleTimeCmdBuffer() noexcept { return _cmd_manager.getCmdBuffer(); }
inline SingleTimeCmdManager& getSingleTimeCmdManager() noexcept { return _cmd_manager; }
inline DescriptorPool& getDescriptorPool() { return _pool_manager.getAvailablePool(); }
private:
Render_Core() = default;
~Render_Core() = default; ~Render_Core() = default;
private: private:
ValidationLayers _layers; ValidationLayers _layers;
SingleTimeCmdManager _cmd_manager;
Queues _queues; Queues _queues;
DescriptorPoolManager _pool_manager;
Device _device; Device _device;
Instance _instance; Instance _instance;
GPUallocator _allocator; GPUallocator _allocator;

View File

@@ -6,17 +6,17 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:14:29 by maldavid #+# #+# */ /* Created: 2022/10/08 19:14:29 by maldavid #+# #+# */
/* Updated: 2023/11/18 17:22:02 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:23:45 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "render_core.h" #include "render_core.h"
#include <iterator>
#include <map>
#include <vector> #include <vector>
#include <set> #include <set>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_vulkan.h> #include <SDL2/SDL_vulkan.h>
#include <iostream>
#include <algorithm>
namespace mlx namespace mlx
{ {
@@ -29,10 +29,10 @@ namespace mlx
Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().getFamilies(); Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().getFamilies();
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos; std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<uint32_t> uniqueQueueFamilies = { indices.graphicsFamily.value(), indices.presentFamily.value() }; std::set<std::uint32_t> uniqueQueueFamilies = { indices.graphics_family.value(), indices.present_family.value() };
float queuePriority = 1.0f; float queuePriority = 1.0f;
for(uint32_t queueFamily : uniqueQueueFamilies) for(std::uint32_t queueFamily : uniqueQueueFamilies)
{ {
VkDeviceQueueCreateInfo queueCreateInfo{}; VkDeviceQueueCreateInfo queueCreateInfo{};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
@@ -47,17 +47,18 @@ namespace mlx
VkDeviceCreateInfo createInfo{}; VkDeviceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size()); createInfo.queueCreateInfoCount = static_cast<std::uint32_t>(queueCreateInfos.size());
createInfo.pQueueCreateInfos = queueCreateInfos.data(); createInfo.pQueueCreateInfos = queueCreateInfos.data();
createInfo.pEnabledFeatures = &deviceFeatures; createInfo.pEnabledFeatures = &deviceFeatures;
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size()); createInfo.enabledExtensionCount = static_cast<std::uint32_t>(deviceExtensions.size());
createInfo.ppEnabledExtensionNames = deviceExtensions.data(); createInfo.ppEnabledExtensionNames = deviceExtensions.data();
createInfo.enabledLayerCount = 0; createInfo.enabledLayerCount = 0;
if(vkCreateDevice(_physicalDevice, &createInfo, nullptr, &_device) != VK_SUCCESS) VkResult res;
core::error::report(e_kind::fatal_error, "Vulkan : failed to create logcal device"); if((res = vkCreateDevice(_physical_device, &createInfo, nullptr, &_device)) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create logcal device, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new logical device"); core::error::report(e_kind::message, "Vulkan : created new logical device");
#endif #endif
@@ -65,7 +66,7 @@ namespace mlx
void Device::pickPhysicalDevice() void Device::pickPhysicalDevice()
{ {
uint32_t deviceCount = 0; std::uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(Render_Core::get().getInstance().get(), &deviceCount, nullptr); vkEnumeratePhysicalDevices(Render_Core::get().getInstance().get(), &deviceCount, nullptr);
if(deviceCount == 0) if(deviceCount == 0)
@@ -82,30 +83,27 @@ namespace mlx
if(SDL_Vulkan_CreateSurface(window, Render_Core::get().getInstance().get(), &surface) != SDL_TRUE) if(SDL_Vulkan_CreateSurface(window, Render_Core::get().getInstance().get(), &surface) != SDL_TRUE)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a surface to pick physical device"); core::error::report(e_kind::fatal_error, "Vulkan : failed to create a surface to pick physical device");
std::vector<std::pair<int, VkPhysicalDevice>> devices_score; std::multimap<int, VkPhysicalDevice> devices_score;
for(const auto& device : devices) for(const auto& device : devices)
devices_score.emplace_back(deviceScore(device, surface), device);
vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), surface, nullptr);
SDL_DestroyWindow(window);
using device_pair = std::pair<int, VkPhysicalDevice>;
std::sort(devices_score.begin(), devices_score.end(), [](const device_pair& a, const device_pair& b)
{ {
return a.first > b.first; int score = deviceScore(device, surface);
}); devices_score.insert(std::make_pair(score, device));
}
if(devices_score.front().first > 0) if(devices_score.rbegin()->first > 0)
_physicalDevice = devices_score.front().second; _physical_device = devices_score.rbegin()->second;
else
if(_physicalDevice == VK_NULL_HANDLE)
core::error::report(e_kind::fatal_error, "Vulkan : failed to find a suitable GPU"); core::error::report(e_kind::fatal_error, "Vulkan : failed to find a suitable GPU");
#ifdef DEBUG #ifdef DEBUG
VkPhysicalDeviceProperties props; VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(_physicalDevice, &props); vkGetPhysicalDeviceProperties(_physical_device, &props);
core::error::report(e_kind::message, "Vulkan : picked a physical device, %s", props.deviceName); core::error::report(e_kind::message, "Vulkan : picked a physical device, %s", props.deviceName);
#endif #endif
Render_Core::get().getQueue().findQueueFamilies(_physical_device, surface); // update queue indicies to current physical device
vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), surface, nullptr);
SDL_DestroyWindow(window);
} }
int Device::deviceScore(VkPhysicalDevice device, VkSurfaceKHR surface) int Device::deviceScore(VkPhysicalDevice device, VkSurfaceKHR surface)
@@ -113,7 +111,7 @@ namespace mlx
Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().findQueueFamilies(device, surface); Queues::QueueFamilyIndices indices = Render_Core::get().getQueue().findQueueFamilies(device, surface);
bool extensionsSupported = checkDeviceExtensionSupport(device); bool extensionsSupported = checkDeviceExtensionSupport(device);
uint32_t formatCount = 0; std::uint32_t formatCount = 0;
if(extensionsSupported) if(extensionsSupported)
vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr);
@@ -122,6 +120,9 @@ namespace mlx
if(!indices.isComplete() || !extensionsSupported || formatCount == 0) if(!indices.isComplete() || !extensionsSupported || formatCount == 0)
return -1; return -1;
VkPhysicalDeviceFeatures features;
vkGetPhysicalDeviceFeatures(device, &features);
int score = 0; int score = 0;
#ifndef FORCE_INTEGRATED_GPU #ifndef FORCE_INTEGRATED_GPU
if(props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) if(props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
@@ -130,6 +131,10 @@ namespace mlx
if(props.deviceType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) if(props.deviceType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
return -1; return -1;
#endif #endif
if(!features.geometryShader)
return -1;
score += props.limits.maxImageDimension2D; score += props.limits.maxImageDimension2D;
score += props.limits.maxBoundDescriptorSets; score += props.limits.maxBoundDescriptorSets;
return score; return score;
@@ -137,7 +142,7 @@ namespace mlx
bool Device::checkDeviceExtensionSupport(VkPhysicalDevice device) bool Device::checkDeviceExtensionSupport(VkPhysicalDevice device)
{ {
uint32_t extensionCount; std::uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> availableExtensions(extensionCount); std::vector<VkExtensionProperties> availableExtensions(extensionCount);
@@ -155,5 +160,8 @@ namespace mlx
{ {
vkDestroyDevice(_device, nullptr); vkDestroyDevice(_device, nullptr);
_device = VK_NULL_HANDLE; _device = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a logical device");
#endif
} }
} }

View File

@@ -6,15 +6,15 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:13:42 by maldavid #+# #+# */ /* Created: 2022/10/08 19:13:42 by maldavid #+# #+# */
/* Updated: 2023/11/11 01:51:26 by maldavid ### ########.fr */ /* Updated: 2024/03/14 16:59:54 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_DEVICE__ #ifndef __MLX_VK_DEVICE__
#define __MLX_VK_DEVICE__ #define __MLX_VK_DEVICE__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include "vk_queues.h"
namespace mlx namespace mlx
{ {
@@ -27,7 +27,7 @@ namespace mlx
inline VkDevice& operator()() noexcept { return _device; } inline VkDevice& operator()() noexcept { return _device; }
inline VkDevice& get() noexcept { return _device; } inline VkDevice& get() noexcept { return _device; }
inline VkPhysicalDevice& getPhysicalDevice() noexcept { return _physicalDevice; } inline VkPhysicalDevice& getPhysicalDevice() noexcept { return _physical_device; }
private: private:
void pickPhysicalDevice(); void pickPhysicalDevice();
@@ -35,7 +35,7 @@ namespace mlx
int deviceScore(VkPhysicalDevice device, VkSurfaceKHR surface); int deviceScore(VkPhysicalDevice device, VkSurfaceKHR surface);
private: private:
VkPhysicalDevice _physicalDevice = VK_NULL_HANDLE; VkPhysicalDevice _physical_device = VK_NULL_HANDLE;
VkDevice _device = VK_NULL_HANDLE; VkDevice _device = VK_NULL_HANDLE;
}; };
} }

View File

@@ -6,25 +6,24 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 17:53:06 by maldavid #+# #+# */ /* Created: 2023/04/02 17:53:06 by maldavid #+# #+# */
/* Updated: 2023/11/18 17:07:21 by maldavid ### ########.fr */ /* Updated: 2024/02/25 08:02:45 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include <renderer/core/vk_fence.h> #include <renderer/core/vk_fence.h>
#include <renderer/core/render_core.h>
namespace mlx namespace mlx
{ {
void Fence::init() void Fence::init()
{ {
VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkFenceCreateInfo fenceInfo{}; VkFenceCreateInfo fenceInfo{};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
if(vkCreateFence(Render_Core::get().getDevice().get(), &fenceInfo, nullptr, &_fence) != VK_SUCCESS) VkResult res;
core::error::report(e_kind::fatal_error, "Vulkan : failed to create CPU synchronization object"); if((res = vkCreateFence(Render_Core::get().getDevice().get(), &fenceInfo, nullptr, &_fence)) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a synchronization object (fence), %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new fence"); core::error::report(e_kind::message, "Vulkan : created new fence");
#endif #endif
@@ -40,10 +39,18 @@ namespace mlx
vkResetFences(Render_Core::get().getDevice().get(), 1, &_fence); vkResetFences(Render_Core::get().getDevice().get(), 1, &_fence);
} }
bool Fence::isReady() const noexcept
{
return vkGetFenceStatus(Render_Core::get().getDevice().get(), _fence) == VK_SUCCESS;
}
void Fence::destroy() noexcept void Fence::destroy() noexcept
{ {
if(_fence != VK_NULL_HANDLE) if(_fence != VK_NULL_HANDLE)
vkDestroyFence(Render_Core::get().getDevice().get(), _fence, nullptr); vkDestroyFence(Render_Core::get().getDevice().get(), _fence, nullptr);
_fence = VK_NULL_HANDLE; _fence = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed fence");
#endif
} }
} }

View File

@@ -6,15 +6,15 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/02 17:52:09 by maldavid #+# #+# */ /* Created: 2023/04/02 17:52:09 by maldavid #+# #+# */
/* Updated: 2023/04/02 17:52:59 by maldavid ### ########.fr */ /* Updated: 2024/01/03 15:26:21 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_FENCE__ #ifndef __MLX_VK_FENCE__
#define __MLX_VK_FENCE__ #define __MLX_VK_FENCE__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <renderer/core/render_core.h>
namespace mlx namespace mlx
{ {
@@ -28,6 +28,7 @@ namespace mlx
inline VkFence& get() noexcept { return _fence; } inline VkFence& get() noexcept { return _fence; }
void wait() noexcept; void wait() noexcept;
void reset() noexcept; void reset() noexcept;
bool isReady() const noexcept;
inline void waitAndReset() noexcept { wait(); reset(); } inline void waitAndReset() noexcept { wait(); reset(); }
void destroy() noexcept; void destroy() noexcept;

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:04:21 by maldavid #+# #+# */ /* Created: 2022/10/08 19:04:21 by maldavid #+# #+# */
/* Updated: 2023/11/18 17:21:42 by maldavid ### ########.fr */ /* Updated: 2024/02/24 21:10:32 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -21,40 +21,35 @@ namespace mlx
{ {
VkApplicationInfo appInfo{}; VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "MacroLibX";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "MacroLibX"; appInfo.pEngineName = "MacroLibX";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.engineVersion = VK_MAKE_VERSION(1, 3, 1);
appInfo.apiVersion = VK_API_VERSION_1_2; appInfo.apiVersion = VK_API_VERSION_1_2;
auto extensions = getRequiredExtensions();
VkInstanceCreateInfo createInfo{}; VkInstanceCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo; createInfo.pApplicationInfo = &appInfo;
createInfo.enabledExtensionCount = static_cast<std::uint32_t>(extensions.size());
auto extensions = getRequiredExtensions();
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data(); createInfo.ppEnabledExtensionNames = extensions.data();
createInfo.enabledLayerCount = 0; // will be replaced if validation layers are enabled
createInfo.pNext = nullptr;
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo; VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
if constexpr(enableValidationLayers) if constexpr(enableValidationLayers)
{ {
if(Render_Core::get().getLayers().checkValidationLayerSupport()) if(Render_Core::get().getLayers().checkValidationLayerSupport())
{ {
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size()); createInfo.enabledLayerCount = static_cast<std::uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data(); createInfo.ppEnabledLayerNames = validationLayers.data();
Render_Core::get().getLayers().populateDebugMessengerCreateInfo(debugCreateInfo); Render_Core::get().getLayers().populateDebugMessengerCreateInfo(debugCreateInfo);
createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo; createInfo.pNext = static_cast<VkDebugUtilsMessengerCreateInfoEXT*>(&debugCreateInfo);
} }
} }
else
{
createInfo.enabledLayerCount = 0;
createInfo.pNext = nullptr;
}
VkResult res; VkResult res;
if((res = vkCreateInstance(&createInfo, nullptr, &_instance)) != VK_SUCCESS) if((res = vkCreateInstance(&createInfo, nullptr, &_instance)) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create Vulkan instance"); core::error::report(e_kind::fatal_error, "Vulkan : failed to create Vulkan instance, %s", RCore::verbaliseResultVk(res));
volkLoadInstance(_instance); volkLoadInstance(_instance);
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new instance"); core::error::report(e_kind::message, "Vulkan : created new instance");
@@ -63,25 +58,34 @@ namespace mlx
std::vector<const char*> Instance::getRequiredExtensions() std::vector<const char*> Instance::getRequiredExtensions()
{ {
unsigned int count = 0; std::vector<const char*> extensions;
SDL_Window* window = SDL_CreateWindow("", 0, 0, 1, 1, SDL_WINDOW_VULKAN | SDL_WINDOW_HIDDEN); extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
if(!window)
core::error::report(e_kind::fatal_error, "Vulkan : cannot get instance extentions from window : %s", SDL_GetError());
if(!SDL_Vulkan_GetInstanceExtensions(window, &count, nullptr)) #ifdef VK_USE_PLATFORM_XCB_KHR
core::error::report(e_kind::fatal_error, "Vulkan : cannot get instance extentions from window : %s", SDL_GetError()); extensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
#endif
std::vector<const char*> extensions = { VK_EXT_DEBUG_REPORT_EXTENSION_NAME }; #ifdef VK_USE_PLATFORM_XLIB_KHR
size_t additional_extension_count = extensions.size(); extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
extensions.resize(additional_extension_count + count); #endif
if(!SDL_Vulkan_GetInstanceExtensions(window, &count, extensions.data() + additional_extension_count)) #ifdef VK_USE_PLATFORM_WAYLAND_KHR
core::error::report(e_kind::error, "Vulkan : cannot get instance extentions from window : %s", SDL_GetError()); extensions.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#endif
#ifdef VK_USE_PLATFORM_METAL_EXT
extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
#endif
if constexpr(enableValidationLayers) if constexpr(enableValidationLayers)
{
extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
SDL_DestroyWindow(window);
return extensions; return extensions;
} }
@@ -89,5 +93,8 @@ namespace mlx
{ {
vkDestroyInstance(_instance, nullptr); vkDestroyInstance(_instance, nullptr);
_instance = VK_NULL_HANDLE; _instance = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed an instance");
#endif
} }
} }

View File

@@ -6,13 +6,14 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:03:04 by maldavid #+# #+# */ /* Created: 2022/10/08 19:03:04 by maldavid #+# #+# */
/* Updated: 2022/12/18 17:42:08 by maldavid ### ########.fr */ /* Updated: 2024/01/03 15:26:26 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_INSTANCE__ #ifndef __MLX_VK_INSTANCE__
#define __MLX_VK_INSTANCE__ #define __MLX_VK_INSTANCE__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <vector> #include <vector>

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:02:42 by maldavid #+# #+# */ /* Created: 2022/10/08 19:02:42 by maldavid #+# #+# */
/* Updated: 2022/12/18 22:52:04 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:01:10 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -18,7 +18,7 @@ namespace mlx
{ {
Queues::QueueFamilyIndices Queues::findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface) Queues::QueueFamilyIndices Queues::findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface)
{ {
uint32_t queueFamilyCount = 0; std::uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount); std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
@@ -29,16 +29,16 @@ namespace mlx
for(const auto& queueFamily : queueFamilies) for(const auto& queueFamily : queueFamilies)
{ {
if(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) if(queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
_families->graphicsFamily = i; _families->graphics_family = i;
VkBool32 presentSupport = false; VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
if(presentSupport) if(presentSupport)
_families->presentFamily = i; _families->present_family = i;
if(_families->isComplete()) if(_families->isComplete())
break; return *_families;
i++; i++;
} }
@@ -62,7 +62,10 @@ namespace mlx
vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), surface, nullptr); vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), surface, nullptr);
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
} }
vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->graphicsFamily.value(), 0, &_graphicsQueue); vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->graphics_family.value(), 0, &_graphics_queue);
vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->presentFamily.value(), 0, &_presentQueue); vkGetDeviceQueue(Render_Core::get().getDevice().get(), _families->present_family.value(), 0, &_present_queue);
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : got graphics and present queues");
#endif
} }
} }

View File

@@ -6,16 +6,18 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:01:49 by maldavid #+# #+# */ /* Created: 2022/10/08 19:01:49 by maldavid #+# #+# */
/* Updated: 2022/12/18 22:44:37 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:00:48 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_QUEUES__ #ifndef __MLX_VK_QUEUES__
#define __MLX_VK_QUEUES__ #define __MLX_VK_QUEUES__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <optional> #include <optional>
#include <cstdint> #include <cstdint>
#include <core/errors.h>
namespace mlx namespace mlx
{ {
@@ -24,23 +26,29 @@ namespace mlx
public: public:
struct QueueFamilyIndices struct QueueFamilyIndices
{ {
std::optional<uint32_t> graphicsFamily; std::optional<std::uint32_t> graphics_family;
std::optional<uint32_t> presentFamily; std::optional<std::uint32_t> present_family;
inline bool isComplete() { return graphicsFamily.has_value() && presentFamily.has_value(); } inline bool isComplete() { return graphics_family.has_value() && present_family.has_value(); }
}; };
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface); QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface);
void init(); void init();
inline VkQueue& getGraphic() noexcept { return _graphicsQueue; } inline VkQueue& getGraphic() noexcept { return _graphics_queue; }
inline VkQueue& getPresent() noexcept { return _presentQueue; } inline VkQueue& getPresent() noexcept { return _present_queue; }
inline QueueFamilyIndices getFamilies() noexcept { return *_families; } inline QueueFamilyIndices getFamilies() noexcept
{
if(_families.has_value())
return *_families;
core::error::report(e_kind::fatal_error, "Vulkan : cannot get queue families, not init");
return {}; // just to avoid warnings
}
private: private:
VkQueue _graphicsQueue; VkQueue _graphics_queue;
VkQueue _presentQueue; VkQueue _present_queue;
std::optional<QueueFamilyIndices> _families; std::optional<QueueFamilyIndices> _families;
}; };
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 19:01:08 by maldavid #+# #+# */ /* Created: 2022/10/08 19:01:08 by maldavid #+# #+# */
/* Updated: 2023/11/18 17:22:29 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:02:36 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -21,19 +21,23 @@ namespace mlx
VkSemaphoreCreateInfo semaphoreInfo{}; VkSemaphoreCreateInfo semaphoreInfo{};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
if( vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_imageAvailableSemaphores) != VK_SUCCESS || VkResult res;
vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_renderFinishedSemaphores) != VK_SUCCESS) if( (res = vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_image_available_semaphore)) != VK_SUCCESS ||
core::error::report(e_kind::fatal_error, "Vulkan : failed to create GPU synchronization object"); (res = vkCreateSemaphore(Render_Core::get().getDevice().get(), &semaphoreInfo, nullptr, &_render_finished_semaphore)) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a synchronization object (semaphore), %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new semaphore"); core::error::report(e_kind::message, "Vulkan : created new semaphores");
#endif #endif
} }
void Semaphore::destroy() noexcept void Semaphore::destroy() noexcept
{ {
vkDestroySemaphore(Render_Core::get().getDevice().get(), _renderFinishedSemaphores, nullptr); vkDestroySemaphore(Render_Core::get().getDevice().get(), _render_finished_semaphore, nullptr);
_renderFinishedSemaphores = VK_NULL_HANDLE; _render_finished_semaphore = VK_NULL_HANDLE;
vkDestroySemaphore(Render_Core::get().getDevice().get(), _imageAvailableSemaphores, nullptr); vkDestroySemaphore(Render_Core::get().getDevice().get(), _image_available_semaphore, nullptr);
_imageAvailableSemaphores = VK_NULL_HANDLE; _image_available_semaphore = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed semaphores");
#endif
} }
} }

View File

@@ -6,15 +6,15 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 18:59:38 by maldavid #+# #+# */ /* Created: 2022/10/08 18:59:38 by maldavid #+# #+# */
/* Updated: 2023/04/02 17:55:10 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:01:57 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_SEMAPHORE__ #ifndef __MLX_VK_SEMAPHORE__
#define __MLX_VK_SEMAPHORE__ #define __MLX_VK_SEMAPHORE__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <vector>
namespace mlx namespace mlx
{ {
@@ -24,12 +24,12 @@ namespace mlx
void init(); void init();
void destroy() noexcept; void destroy() noexcept;
inline VkSemaphore& getImageSemaphore() noexcept { return _imageAvailableSemaphores; } inline VkSemaphore& getImageSemaphore() noexcept { return _image_available_semaphore; }
inline VkSemaphore& getRenderImageSemaphore() noexcept { return _renderFinishedSemaphores; } inline VkSemaphore& getRenderImageSemaphore() noexcept { return _render_finished_semaphore; }
private: private:
VkSemaphore _imageAvailableSemaphores = VK_NULL_HANDLE; VkSemaphore _image_available_semaphore = VK_NULL_HANDLE;
VkSemaphore _renderFinishedSemaphores = VK_NULL_HANDLE; VkSemaphore _render_finished_semaphore = VK_NULL_HANDLE;
}; };
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 18:58:49 by maldavid #+# #+# */ /* Created: 2022/10/08 18:58:49 by maldavid #+# #+# */
/* Updated: 2023/11/18 17:22:38 by maldavid ### ########.fr */ /* Updated: 2024/01/10 21:55:21 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -15,6 +15,7 @@
#include <renderer/renderer.h> #include <renderer/renderer.h>
#include <SDL2/SDL_vulkan.h> #include <SDL2/SDL_vulkan.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <algorithm>
namespace mlx namespace mlx
{ {
@@ -29,18 +30,20 @@ namespace mlx
VkSurfaceFormatKHR Surface::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats) VkSurfaceFormatKHR Surface::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats)
{ {
for(const auto& availableFormat : availableFormats) auto it = std::find_if(availableFormats.begin(), availableFormats.end(), [](VkSurfaceFormatKHR format)
{ {
if(availableFormat.format == VK_FORMAT_R8G8B8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) return format.format == VK_FORMAT_R8G8B8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
return availableFormat; });
}
return availableFormats[0]; return (it == availableFormats.end() ? availableFormats[0] : *it);
} }
void Surface::destroy() noexcept void Surface::destroy() noexcept
{ {
vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), _surface, nullptr); vkDestroySurfaceKHR(Render_Core::get().getInstance().get(), _surface, nullptr);
_surface = VK_NULL_HANDLE; _surface = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a surface");
#endif
} }
} }

View File

@@ -6,13 +6,14 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/10/08 18:57:55 by maldavid #+# #+# */ /* Created: 2022/10/08 18:57:55 by maldavid #+# #+# */
/* Updated: 2022/12/18 19:34:04 by maldavid ### ########.fr */ /* Updated: 2024/01/03 15:26:43 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_SURFACE__ #ifndef __MLX_VK_SURFACE__
#define __MLX_VK_SURFACE__ #define __MLX_VK_SURFACE__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <vector> #include <vector>

View File

@@ -3,19 +3,19 @@
/* ::: :::::::: */ /* ::: :::::::: */
/* vk_validation_layers.cpp :+: :+: :+: */ /* vk_validation_layers.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: maldavid <marvin@42.fr> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/12/19 14:05:25 by maldavid #+# #+# */ /* Created: 2022/12/19 14:05:25 by maldavid #+# #+# */
/* Updated: 2023/11/20 07:21:57 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:03:24 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "vk_validation_layers.h"
#include "render_core.h" #include "render_core.h"
#include "vulkan/vulkan_core.h"
#include <core/errors.h> #include <core/errors.h>
#include <iostream>
#include <cstring> #include <cstring>
#include <algorithm>
namespace mlx namespace mlx
{ {
@@ -24,54 +24,65 @@ namespace mlx
if constexpr(!enableValidationLayers) if constexpr(!enableValidationLayers)
return; return;
VkDebugUtilsMessengerCreateInfoEXT createInfo; std::uint32_t extensionCount;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> extensions(extensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
if(!std::any_of(extensions.begin(), extensions.end(), [=](VkExtensionProperties ext) { return std::strcmp(ext.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0; }))
{
core::error::report(e_kind::warning , "Vulkan : %s not present, debug utils are disabled", VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
return;
}
VkDebugUtilsMessengerCreateInfoEXT createInfo{};
populateDebugMessengerCreateInfo(createInfo); populateDebugMessengerCreateInfo(createInfo);
if(createDebugUtilsMessengerEXT(&createInfo, nullptr) != VK_SUCCESS) VkResult res = createDebugUtilsMessengerEXT(&createInfo, nullptr);
core::error::report(e_kind::error, "Vulkan : failed to set up debug messenger"); if(res != VK_SUCCESS)
core::error::report(e_kind::warning, "Vulkan : failed to set up debug messenger, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG #ifdef DEBUG
else else
core::error::report(e_kind::message, "Vulkan : enabled validation layers"); core::error::report(e_kind::message, "Vulkan : enabled validation layers");
#endif #endif
_vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(Render_Core::get().getInstance().get(), "vkSetDebugUtilsObjectNameEXT");
if(!_vkSetDebugUtilsObjectNameEXT)
core::error::report(e_kind::warning, "Vulkan : failed to set up debug object names, %s", RCore::verbaliseResultVk(VK_ERROR_EXTENSION_NOT_PRESENT));
#ifdef DEBUG
else
core::error::report(e_kind::message, "Vulkan : enabled debug object names");
#endif
} }
bool ValidationLayers::checkValidationLayerSupport() bool ValidationLayers::checkValidationLayerSupport()
{ {
uint32_t layerCount; std::uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr); vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount); std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
for(const char* layerName : validationLayers) return std::all_of(validationLayers.begin(), validationLayers.end(), [&](const char* layerName)
{ {
bool layerFound = false; if(!std::any_of(availableLayers.begin(), availableLayers.end(), [=](VkLayerProperties props) { return std::strcmp(layerName, props.layerName) == 0; }))
for(const auto& layerProperties : availableLayers)
{ {
if(std::strcmp(layerName, layerProperties.layerName) == 0) core::error::report(e_kind::error, "Vulkan : a validation layer was requested but was not found ('%s')", layerName);
{
layerFound = true;
break;
}
}
if(!layerFound)
return false; return false;
} }
return true; return true;
});
} }
void ValidationLayers::destroy() VkResult ValidationLayers::setDebugUtilsObjectNameEXT(VkObjectType object_type, std::uint64_t object_handle, const char* object_name)
{ {
if constexpr(!enableValidationLayers) if(!_vkSetDebugUtilsObjectNameEXT)
return; return VK_ERROR_EXTENSION_NOT_PRESENT;
destroyDebugUtilsMessengerEXT(nullptr);
}
VkResult ValidationLayers::createDebugUtilsMessengerEXT(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator) VkDebugUtilsObjectNameInfoEXT name_info{};
{ name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(Render_Core::get().getInstance().get(), "vkCreateDebugUtilsMessengerEXT"); name_info.objectType = object_type;
return func != nullptr ? func(Render_Core::get().getInstance().get(), pCreateInfo, pAllocator, &_debugMessenger) : VK_ERROR_EXTENSION_NOT_PRESENT; name_info.objectHandle = object_handle;
name_info.pObjectName = object_name;
return _vkSetDebugUtilsObjectNameEXT(Render_Core::get().getDevice().get(), &name_info);
} }
void ValidationLayers::populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) void ValidationLayers::populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo)
@@ -83,19 +94,29 @@ namespace mlx
createInfo.pfnUserCallback = ValidationLayers::debugCallback; createInfo.pfnUserCallback = ValidationLayers::debugCallback;
} }
VKAPI_ATTR VkBool32 VKAPI_CALL ValidationLayers::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) void ValidationLayers::destroy()
{ {
if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) if constexpr(enableValidationLayers)
{ {
std::cout << '\n'; destroyDebugUtilsMessengerEXT(nullptr);
core::error::report(e_kind::error, std::string("Vulkan layer error: ") + pCallbackData->pMessage); #ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed validation layers");
#endif
} }
else if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
{
std::cout << '\n';
core::error::report(e_kind::warning, std::string("Vulkan layer warning: ") + pCallbackData->pMessage);
} }
VkResult ValidationLayers::createDebugUtilsMessengerEXT(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator)
{
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(Render_Core::get().getInstance().get(), "vkCreateDebugUtilsMessengerEXT");
return func != nullptr ? func(Render_Core::get().getInstance().get(), pCreateInfo, pAllocator, &_debug_messenger) : VK_ERROR_EXTENSION_NOT_PRESENT;
}
VKAPI_ATTR VkBool32 VKAPI_CALL ValidationLayers::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, [[maybe_unused]] void* pUserData)
{
if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
core::error::report(e_kind::error, pCallbackData->pMessage);
else if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
core::error::report(e_kind::warning, pCallbackData->pMessage);
return VK_FALSE; return VK_FALSE;
} }
@@ -103,7 +124,7 @@ namespace mlx
{ {
auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(Render_Core::get().getInstance().get(), "vkDestroyDebugUtilsMessengerEXT"); auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(Render_Core::get().getInstance().get(), "vkDestroyDebugUtilsMessengerEXT");
if(func != nullptr) if(func != nullptr)
func(Render_Core::get().getInstance().get(), _debugMessenger, pAllocator); func(Render_Core::get().getInstance().get(), _debug_messenger, pAllocator);
} }
} }

View File

@@ -6,13 +6,14 @@
/* By: maldavid <marvin@42.fr> +#+ +:+ +#+ */ /* By: maldavid <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/12/19 14:04:25 by maldavid #+# #+# */ /* Created: 2022/12/19 14:04:25 by maldavid #+# #+# */
/* Updated: 2022/12/19 14:05:19 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:02:55 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __VK_VALIDATION_LAYERS__ #ifndef __VK_VALIDATION_LAYERS__
#define __VK_VALIDATION_LAYERS__ #define __VK_VALIDATION_LAYERS__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
namespace mlx namespace mlx
@@ -20,17 +21,26 @@ namespace mlx
class ValidationLayers class ValidationLayers
{ {
public: public:
ValidationLayers() = default;
void init(); void init();
void destroy(); void destroy();
bool checkValidationLayerSupport(); bool checkValidationLayerSupport();
void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo); void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo);
VkResult setDebugUtilsObjectNameEXT(VkObjectType object_type, std::uint64_t object_handle, const char* object_name);
~ValidationLayers() = default;
private: private:
VkResult createDebugUtilsMessengerEXT(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator); VkResult createDebugUtilsMessengerEXT(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator);
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData); static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData);
void destroyDebugUtilsMessengerEXT(const VkAllocationCallbacks* pAllocator); void destroyDebugUtilsMessengerEXT(const VkAllocationCallbacks* pAllocator);
VkDebugUtilsMessengerEXT _debugMessenger; private:
VkDebugUtilsMessengerEXT _debug_messenger;
PFN_vkSetDebugUtilsObjectNameEXT _vkSetDebugUtilsObjectNameEXT = nullptr;
}; };
} }

View File

@@ -0,0 +1,39 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* descriptor_pool_manager.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/20 06:51:47 by maldavid #+# #+# */
/* Updated: 2024/01/20 08:18:27 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#include <renderer/core/render_core.h>
#include <renderer/descriptors/descriptor_pool_manager.h>
namespace mlx
{
DescriptorPool& DescriptorPoolManager::getAvailablePool()
{
for(auto& pool : _pools)
{
if(pool.getNumberOfSetsAllocated() < MAX_SETS_PER_POOL)
return pool;
}
VkDescriptorPoolSize pool_sizes[] = {
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, (MAX_FRAMES_IN_FLIGHT * NUMBER_OF_UNIFORM_BUFFERS) },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_SETS_PER_POOL - (MAX_FRAMES_IN_FLIGHT * NUMBER_OF_UNIFORM_BUFFERS) }
};
_pools.emplace_front().init((sizeof(pool_sizes) / sizeof(VkDescriptorPoolSize)), pool_sizes);
return _pools.front();
}
void DescriptorPoolManager::destroyAllPools()
{
for(auto& pool : _pools)
pool.destroy();
_pools.clear();
}
}

View File

@@ -0,0 +1,36 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* descriptor_pool_manager.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/20 06:26:26 by maldavid #+# #+# */
/* Updated: 2024/01/20 08:23:04 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_DESCRIPTOR_POOL_MANAGER__
#define __MLX_DESCRIPTOR_POOL_MANAGER__
#include <renderer/descriptors/vk_descriptor_pool.h>
#include <list>
namespace mlx
{
class DescriptorPoolManager
{
public:
DescriptorPoolManager() = default;
DescriptorPool& getAvailablePool(); // assumes the pool is for only one set allocation, may cause some issues if this is for more than one
void destroyAllPools();
~DescriptorPoolManager() = default;
private:
std::list<DescriptorPool> _pools;
};
}
#endif

View File

@@ -6,11 +6,12 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/23 18:34:23 by maldavid #+# #+# */ /* Created: 2023/01/23 18:34:23 by maldavid #+# #+# */
/* Updated: 2023/11/18 17:23:05 by maldavid ### ########.fr */ /* Updated: 2024/01/20 07:40:40 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "vk_descriptor_pool.h" #include "vk_descriptor_pool.h"
#include <renderer/descriptors/vk_descriptor_set.h>
#include <renderer/core/render_core.h> #include <renderer/core/render_core.h>
namespace mlx namespace mlx
@@ -21,15 +22,34 @@ namespace mlx
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = n; poolInfo.poolSizeCount = n;
poolInfo.pPoolSizes = size; poolInfo.pPoolSizes = size;
poolInfo.maxSets = 8192; poolInfo.maxSets = MAX_SETS_PER_POOL;
poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
if(vkCreateDescriptorPool(Render_Core::get().getDevice().get(), &poolInfo, nullptr, &_pool) != VK_SUCCESS) VkResult res = vkCreateDescriptorPool(Render_Core::get().getDevice().get(), &poolInfo, nullptr, &_pool);
core::error::report(e_kind::fatal_error, "Vulkan : failed to create descriptor pool"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create descriptor pool, %s", RCore::verbaliseResultVk(res));
_allocated_sets++;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new descriptor pool");
#endif
}
void DescriptorPool::freeDescriptor(const DescriptorSet& set)
{
if(!isInit())
return;
const auto& sets = set.getAllFramesDescriptorSets();
vkFreeDescriptorSets(Render_Core::get().getDevice().get(), _pool, sets.size(), sets.data());
_allocated_sets--; // if this goes in underflow I quit
} }
void DescriptorPool::destroy() noexcept void DescriptorPool::destroy() noexcept
{ {
if(_pool != VK_NULL_HANDLE)
vkDestroyDescriptorPool(Render_Core::get().getDevice().get(), _pool, nullptr); vkDestroyDescriptorPool(Render_Core::get().getDevice().get(), _pool, nullptr);
_pool = VK_NULL_HANDLE; _pool = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a descriptor pool");
#endif
} }
} }

View File

@@ -6,13 +6,14 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/23 18:32:43 by maldavid #+# #+# */ /* Created: 2023/01/23 18:32:43 by maldavid #+# #+# */
/* Updated: 2023/01/23 18:44:40 by maldavid ### ########.fr */ /* Updated: 2024/01/20 07:38:32 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __VK_DESCRIPTOR_POOL__ #ifndef __VK_DESCRIPTOR_POOL__
#define __VK_DESCRIPTOR_POOL__ #define __VK_DESCRIPTOR_POOL__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <cstddef> #include <cstddef>
@@ -21,14 +22,23 @@ namespace mlx
class DescriptorPool class DescriptorPool
{ {
public: public:
DescriptorPool() = default;
void init(std::size_t n, VkDescriptorPoolSize* size); void init(std::size_t n, VkDescriptorPoolSize* size);
void freeDescriptor(const class DescriptorSet& set);
void destroy() noexcept; void destroy() noexcept;
inline VkDescriptorPool& operator()() noexcept { return _pool; } inline VkDescriptorPool& operator()() noexcept { return _pool; }
inline VkDescriptorPool& get() noexcept { return _pool; } inline VkDescriptorPool& get() noexcept { return _pool; }
inline std::size_t getNumberOfSetsAllocated() const noexcept { return _allocated_sets; }
inline bool isInit() const noexcept { return _pool != VK_NULL_HANDLE; }
~DescriptorPool() = default;
private: private:
VkDescriptorPool _pool = VK_NULL_HANDLE; VkDescriptorPool _pool = VK_NULL_HANDLE;
std::size_t _allocated_sets = 0;
}; };
} }

View File

@@ -6,20 +6,24 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/23 18:40:44 by maldavid #+# #+# */ /* Created: 2023/01/23 18:40:44 by maldavid #+# #+# */
/* Updated: 2023/11/12 01:14:52 by maldavid ### ########.fr */ /* Updated: 2024/01/20 08:18:07 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#include "vk_descriptor_set.h" #include "vk_descriptor_set.h"
#include "renderer/core/render_core.h"
#include "vk_descriptor_pool.h" #include "vk_descriptor_pool.h"
#include "vk_descriptor_set_layout.h" #include "vk_descriptor_set_layout.h"
#include <renderer/buffers/vk_ubo.h> #include <renderer/buffers/vk_ubo.h>
#include <renderer/renderer.h> #include <renderer/renderer.h>
#include <renderer/images/vk_image.h>
#include <core/profiler.h>
namespace mlx namespace mlx
{ {
void DescriptorSet::init(Renderer* renderer, DescriptorPool* pool, DescriptorSetLayout* layout) void DescriptorSet::init(Renderer* renderer, DescriptorPool* pool, DescriptorSetLayout* layout)
{ {
MLX_PROFILE_FUNCTION();
_renderer = renderer; _renderer = renderer;
_layout = layout; _layout = layout;
_pool = pool; _pool = pool;
@@ -32,18 +36,20 @@ namespace mlx
VkDescriptorSetAllocateInfo allocInfo{}; VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = _pool->get(); allocInfo.descriptorPool = _pool->get();
allocInfo.descriptorSetCount = static_cast<uint32_t>(MAX_FRAMES_IN_FLIGHT); allocInfo.descriptorSetCount = static_cast<std::uint32_t>(MAX_FRAMES_IN_FLIGHT);
allocInfo.pSetLayouts = layouts.data(); allocInfo.pSetLayouts = layouts.data();
if(vkAllocateDescriptorSets(device, &allocInfo, _desc_set.data()) != VK_SUCCESS) VkResult res = vkAllocateDescriptorSets(device, &allocInfo, _desc_set.data());
core::error::report(e_kind::fatal_error, "Vulkan : failed to allocate descriptor set"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to allocate descriptor set, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new descriptor set"); core::error::report(e_kind::message, "Vulkan : created new descriptor set");
#endif #endif
} }
void DescriptorSet::writeDescriptor(int binding, UBO* ubo) noexcept void DescriptorSet::writeDescriptor(int binding, UBO* ubo) const noexcept
{ {
MLX_PROFILE_FUNCTION();
auto device = Render_Core::get().getDevice().get(); auto device = Render_Core::get().getDevice().get();
for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) for(int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
@@ -66,14 +72,15 @@ namespace mlx
} }
} }
void DescriptorSet::writeDescriptor(int binding, VkImageView view, VkSampler sampler) noexcept void DescriptorSet::writeDescriptor(int binding, const Image& image) const noexcept
{ {
MLX_PROFILE_FUNCTION();
auto device = Render_Core::get().getDevice().get(); auto device = Render_Core::get().getDevice().get();
VkDescriptorImageInfo imageInfo{}; VkDescriptorImageInfo imageInfo{};
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; imageInfo.imageLayout = image.getLayout();
imageInfo.imageView = view; imageInfo.imageView = image.getImageView();
imageInfo.sampler = sampler; imageInfo.sampler = image.getSampler();
VkWriteDescriptorSet descriptorWrite{}; VkWriteDescriptorSet descriptorWrite{};
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
@@ -89,8 +96,9 @@ namespace mlx
DescriptorSet DescriptorSet::duplicate() DescriptorSet DescriptorSet::duplicate()
{ {
MLX_PROFILE_FUNCTION();
DescriptorSet set; DescriptorSet set;
set.init(_renderer, _pool, _layout); set.init(_renderer, &Render_Core::get().getDescriptorPool(), _layout);
return set; return set;
} }
@@ -98,8 +106,24 @@ namespace mlx
{ {
return _desc_set[_renderer->getActiveImageIndex()]; return _desc_set[_renderer->getActiveImageIndex()];
} }
VkDescriptorSet& DescriptorSet::get() noexcept VkDescriptorSet& DescriptorSet::get() noexcept
{ {
return _desc_set[_renderer->getActiveImageIndex()]; return _desc_set[_renderer->getActiveImageIndex()];
} }
void DescriptorSet::destroy() noexcept
{
MLX_PROFILE_FUNCTION();
if(_pool != nullptr && Render_Core::get().isInit()) // checks if the render core is still init (it should always be init but just in case)
_pool->freeDescriptor(*this);
for(auto& set : _desc_set)
{
if(set != VK_NULL_HANDLE)
set = VK_NULL_HANDLE;
}
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed descriptor set");
#endif
}
} }

View File

@@ -6,13 +6,14 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/23 18:39:36 by maldavid #+# #+# */ /* Created: 2023/01/23 18:39:36 by maldavid #+# #+# */
/* Updated: 2023/03/31 17:28:36 by maldavid ### ########.fr */ /* Updated: 2024/01/20 07:17:39 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __VK_DESCRIPTOR_SET__ #ifndef __VK_DESCRIPTOR_SET__
#define __VK_DESCRIPTOR_SET__ #define __VK_DESCRIPTOR_SET__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <array> #include <array>
#include <renderer/core/render_core.h> #include <renderer/core/render_core.h>
@@ -22,18 +23,26 @@ namespace mlx
class DescriptorSet class DescriptorSet
{ {
public: public:
DescriptorSet() = default;
void init(class Renderer* renderer, class DescriptorPool* pool, class DescriptorSetLayout* layout); void init(class Renderer* renderer, class DescriptorPool* pool, class DescriptorSetLayout* layout);
void writeDescriptor(int binding, class UBO* ubo) noexcept; void writeDescriptor(int binding, class UBO* ubo) const noexcept;
void writeDescriptor(int binding, VkImageView view, VkSampler sampler) noexcept; void writeDescriptor(int binding, const class Image& image) const noexcept;
inline bool isInit() noexcept { return _pool != nullptr && _renderer != nullptr; } inline bool isInit() const noexcept { return _pool != nullptr && _renderer != nullptr; }
DescriptorSet duplicate(); DescriptorSet duplicate();
VkDescriptorSet& operator()() noexcept; VkDescriptorSet& operator()() noexcept;
VkDescriptorSet& get() noexcept; VkDescriptorSet& get() noexcept;
inline const std::array<VkDescriptorSet, MAX_FRAMES_IN_FLIGHT>& getAllFramesDescriptorSets() const { return _desc_set; }
void destroy() noexcept;
~DescriptorSet() = default;
private: private:
std::array<VkDescriptorSet, MAX_FRAMES_IN_FLIGHT> _desc_set; std::array<VkDescriptorSet, MAX_FRAMES_IN_FLIGHT> _desc_set;
class DescriptorPool* _pool = nullptr; class DescriptorPool* _pool = nullptr;

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/23 18:37:28 by maldavid #+# #+# */ /* Created: 2023/01/23 18:37:28 by maldavid #+# #+# */
/* Updated: 2023/11/18 17:23:16 by maldavid ### ########.fr */ /* Updated: 2024/01/03 13:14:58 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -18,7 +18,7 @@ namespace mlx
void DescriptorSetLayout::init(std::vector<std::pair<int, VkDescriptorType>> binds, VkShaderStageFlagBits stage) void DescriptorSetLayout::init(std::vector<std::pair<int, VkDescriptorType>> binds, VkShaderStageFlagBits stage)
{ {
std::vector<VkDescriptorSetLayoutBinding> bindings(binds.size()); std::vector<VkDescriptorSetLayoutBinding> bindings(binds.size());
for(int i = 0; i < binds.size(); i++) for(std::size_t i = 0; i < binds.size(); i++)
{ {
bindings[i].binding = binds[i].first; bindings[i].binding = binds[i].first;
bindings[i].descriptorCount = 1; bindings[i].descriptorCount = 1;
@@ -34,8 +34,9 @@ namespace mlx
layoutInfo.bindingCount = _bindings.size(); layoutInfo.bindingCount = _bindings.size();
layoutInfo.pBindings = bindings.data(); layoutInfo.pBindings = bindings.data();
if(vkCreateDescriptorSetLayout(Render_Core::get().getDevice().get(), &layoutInfo, nullptr, &_layout) != VK_SUCCESS) VkResult res = vkCreateDescriptorSetLayout(Render_Core::get().getDevice().get(), &layoutInfo, nullptr, &_layout);
core::error::report(e_kind::fatal_error, "Vulkan : failed to create descriptor set layout"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create descriptor set layout, %s", RCore::verbaliseResultVk(res));
} }
void DescriptorSetLayout::destroy() noexcept void DescriptorSetLayout::destroy() noexcept

View File

@@ -6,23 +6,24 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/23 18:36:22 by maldavid #+# #+# */ /* Created: 2023/01/23 18:36:22 by maldavid #+# #+# */
/* Updated: 2023/03/31 17:54:03 by maldavid ### ########.fr */ /* Updated: 2024/01/20 06:25:54 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __VK_DESCRIPTOR_SET_LAYOUT__ #ifndef __VK_DESCRIPTOR_SET_LAYOUT__
#define __VK_DESCRIPTOR_SET_LAYOUT__ #define __VK_DESCRIPTOR_SET_LAYOUT__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <cstddef>
#include <vector> #include <vector>
#include <map>
namespace mlx namespace mlx
{ {
class DescriptorSetLayout class DescriptorSetLayout
{ {
public: public:
DescriptorSetLayout() = default;
void init(std::vector<std::pair<int, VkDescriptorType>> binds, VkShaderStageFlagBits stage); void init(std::vector<std::pair<int, VkDescriptorType>> binds, VkShaderStageFlagBits stage);
void destroy() noexcept; void destroy() noexcept;
@@ -30,6 +31,8 @@ namespace mlx
inline VkDescriptorSetLayout& get() noexcept { return _layout; } inline VkDescriptorSetLayout& get() noexcept { return _layout; }
inline const std::vector<std::pair<int, VkDescriptorType>>& getBindings() const noexcept { return _bindings; } inline const std::vector<std::pair<int, VkDescriptorType>>& getBindings() const noexcept { return _bindings; }
~DescriptorSetLayout() = default;
private: private:
VkDescriptorSetLayout _layout = VK_NULL_HANDLE; VkDescriptorSetLayout _layout = VK_NULL_HANDLE;
std::vector<std::pair<int, VkDescriptorType>> _bindings; std::vector<std::pair<int, VkDescriptorType>> _bindings;

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/03/31 18:03:35 by maldavid #+# #+# */ /* Created: 2023/03/31 18:03:35 by maldavid #+# #+# */
/* Updated: 2023/11/16 14:01:47 by maldavid ### ########.fr */ /* Updated: 2024/09/14 00:04:29 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -14,12 +14,18 @@
#include <renderer/images/texture.h> #include <renderer/images/texture.h>
#include <renderer/buffers/vk_buffer.h> #include <renderer/buffers/vk_buffer.h>
#include <renderer/renderer.h> #include <renderer/renderer.h>
#include <core/profiler.h>
#include <cstring> #include <cstring>
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#ifdef MLX_COMPILER_GCC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#include <stb_image.h> #include <stb_image.h>
#pragma GCC diagnostic pop
#include <iostream> #else
#include <stb_image.h>
#endif
#ifdef IMAGE_OPTIMIZED #ifdef IMAGE_OPTIMIZED
#define TILING VK_IMAGE_TILING_OPTIMAL #define TILING VK_IMAGE_TILING_OPTIMAL
@@ -29,11 +35,13 @@
namespace mlx namespace mlx
{ {
void Texture::create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format, const char* name, bool dedicated_memory) void Texture::create(std::uint8_t* pixels, std::uint32_t width, std::uint32_t height, VkFormat format, const char* name, bool dedicated_memory)
{ {
Image::create(width, height, format, TILING, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, name, dedicated_memory); MLX_PROFILE_FUNCTION();
Image::create(width, height, format, TILING, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, name, dedicated_memory);
Image::createImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); Image::createImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT);
Image::createSampler(); Image::createSampler();
transitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
std::vector<Vertex> vertexData = { std::vector<Vertex> vertexData = {
{{0, 0}, {1.f, 1.f, 1.f, 1.f}, {0.0f, 0.0f}}, {{0, 0}, {1.f, 1.f, 1.f, 1.f}, {0.0f, 0.0f}},
@@ -42,34 +50,44 @@ namespace mlx
{{0, height}, {1.f, 1.f, 1.f, 1.f}, {0.0f, 1.0f}} {{0, height}, {1.f, 1.f, 1.f, 1.f}, {0.0f, 1.0f}}
}; };
std::vector<uint16_t> indexData = { 0, 1, 2, 2, 3, 0 }; std::vector<std::uint16_t> indexData = { 0, 1, 2, 2, 3, 0 };
#ifdef DEBUG #ifdef DEBUG
_vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data(), name); _vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data(), name);
_ibo.create(sizeof(uint16_t) * indexData.size(), indexData.data(), name); _ibo.create(sizeof(std::uint16_t) * indexData.size(), indexData.data(), name);
_name = name; _name = name;
#else #else
_vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data(), nullptr); _vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data(), nullptr);
_ibo.create(sizeof(uint16_t) * indexData.size(), indexData.data(), nullptr); _ibo.create(sizeof(std::uint16_t) * indexData.size(), indexData.data(), nullptr);
#endif #endif
if(pixels != nullptr)
{
Buffer staging_buffer; Buffer staging_buffer;
std::size_t size = width * height * formatSize(format); std::size_t size = width * height * formatSize(format);
if(pixels != nullptr)
{
#ifdef DEBUG #ifdef DEBUG
staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, name, pixels); staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, name, pixels);
#else #else
staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, nullptr, pixels); staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, nullptr, pixels);
#endif #endif
}
else
{
std::vector<std::uint32_t> default_pixels(width * height, 0x00000000);
#ifdef DEBUG
staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, name, default_pixels.data());
#else
staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, nullptr, default_pixels.data());
#endif
}
Image::copyFromBuffer(staging_buffer); Image::copyFromBuffer(staging_buffer);
staging_buffer.destroy(); staging_buffer.destroy();
} }
}
void Texture::setPixel(int x, int y, uint32_t color) noexcept void Texture::setPixel(int x, int y, std::uint32_t color) noexcept
{ {
if(x < 0 || y < 0 || x > getWidth() || y > getHeight()) MLX_PROFILE_FUNCTION();
if(x < 0 || y < 0 || static_cast<std::uint32_t>(x) > getWidth() || static_cast<std::uint32_t>(y) > getHeight())
return; return;
if(_map == nullptr) if(_map == nullptr)
openCPUmap(); openCPUmap();
@@ -79,16 +97,22 @@ namespace mlx
int Texture::getPixel(int x, int y) noexcept int Texture::getPixel(int x, int y) noexcept
{ {
if(x < 0 || y < 0 || x > getWidth() || y > getHeight()) MLX_PROFILE_FUNCTION();
if(x < 0 || y < 0 || static_cast<std::uint32_t>(x) > getWidth() || static_cast<std::uint32_t>(y) > getHeight())
return 0; return 0;
if(_map == nullptr) if(_map == nullptr)
openCPUmap(); openCPUmap();
uint32_t color = _cpu_map[(y * getWidth()) + x]; std::uint32_t color = _cpu_map[(y * getWidth()) + x];
return (color); std::uint8_t* bytes = reinterpret_cast<std::uint8_t*>(&color);
std::uint8_t tmp = bytes[0];
bytes[0] = bytes[2];
bytes[2] = tmp;
return *reinterpret_cast<int*>(bytes);
} }
void Texture::openCPUmap() void Texture::openCPUmap()
{ {
MLX_PROFILE_FUNCTION();
if(_map != nullptr) if(_map != nullptr)
return; return;
@@ -104,32 +128,43 @@ namespace mlx
#endif #endif
Image::copyToBuffer(*_buf_map); Image::copyToBuffer(*_buf_map);
_buf_map->mapMem(&_map); _buf_map->mapMem(&_map);
_cpu_map = std::vector<uint32_t>(getWidth() * getHeight(), 0); _cpu_map = std::vector<std::uint32_t>(getWidth() * getHeight(), 0);
std::memcpy(_cpu_map.data(), _map, size); std::memcpy(_cpu_map.data(), _map, size);
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Texture : mapped CPU memory using staging buffer"); core::error::report(e_kind::message, "Texture : mapped CPU memory using staging buffer");
#endif #endif
} }
void Texture::render(Renderer& renderer, int x, int y) void Texture::render(std::array<VkDescriptorSet, 2>& sets, Renderer& renderer, int x, int y)
{ {
MLX_PROFILE_FUNCTION();
if(_has_been_modified) if(_has_been_modified)
{ {
std::memcpy(_map, _cpu_map.data(), _cpu_map.size() * formatSize(getFormat())); std::memcpy(_map, _cpu_map.data(), _cpu_map.size() * formatSize(getFormat()));
Image::copyFromBuffer(*_buf_map); Image::copyFromBuffer(*_buf_map);
_has_been_modified = false; _has_been_modified = false;
} }
auto cmd = renderer.getActiveCmdBuffer().get(); if(!_set.isInit())
_set = renderer.getFragDescriptorSet().duplicate();
if(getLayout() != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
transitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if(!_has_set_been_updated)
updateSet(0);
auto cmd = renderer.getActiveCmdBuffer();
_vbo.bind(renderer); _vbo.bind(renderer);
_ibo.bind(renderer); _ibo.bind(renderer);
glm::vec2 translate(x, y); glm::vec2 translate(x, y);
vkCmdPushConstants(cmd, renderer.getPipeline().getPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(translate), &translate); vkCmdPushConstants(cmd.get(), renderer.getPipeline().getPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(translate), &translate);
vkCmdDrawIndexed(cmd, static_cast<uint32_t>(_ibo.getSize() / sizeof(uint16_t)), 1, 0, 0, 0); sets[1] = _set.get();
vkCmdBindDescriptorSets(renderer.getActiveCmdBuffer().get(), VK_PIPELINE_BIND_POINT_GRAPHICS, renderer.getPipeline().getPipelineLayout(), 0, sets.size(), sets.data(), 0, nullptr);
vkCmdDrawIndexed(cmd.get(), static_cast<std::uint32_t>(_ibo.getSize() / sizeof(std::uint16_t)), 1, 0, 0, 0);
} }
void Texture::destroy() noexcept void Texture::destroy() noexcept
{ {
MLX_PROFILE_FUNCTION();
Image::destroy(); Image::destroy();
_set.destroy();
if(_buf_map.has_value()) if(_buf_map.has_value())
_buf_map->destroy(); _buf_map->destroy();
_vbo.destroy(); _vbo.destroy();
@@ -138,20 +173,23 @@ namespace mlx
Texture stbTextureLoad(std::filesystem::path file, int* w, int* h) Texture stbTextureLoad(std::filesystem::path file, int* w, int* h)
{ {
MLX_PROFILE_FUNCTION();
Texture texture; Texture texture;
int channels; int channels;
uint8_t* data = nullptr; std::uint8_t* data = nullptr;
std::string filename = file.string(); std::string filename = file.string();
if(!std::filesystem::exists(std::move(file))) if(!std::filesystem::exists(std::move(file)))
core::error::report(e_kind::fatal_error, "Image : file not found '%s'", filename.c_str()); core::error::report(e_kind::fatal_error, "Image : file not found '%s'", filename.c_str());
if(stbi_is_hdr(filename.c_str())) if(stbi_is_hdr(filename.c_str()))
core::error::report(e_kind::fatal_error, "Texture : unsupported image format '%s'", filename.c_str()); core::error::report(e_kind::fatal_error, "Texture : unsupported image format '%s'", filename.c_str());
data = stbi_load(filename.c_str(), w, h, &channels, 4); int dummy_w;
int dummy_h;
data = stbi_load(filename.c_str(), (w == nullptr ? &dummy_w : w), (h == nullptr ? &dummy_h : h), &channels, 4);
#ifdef DEBUG #ifdef DEBUG
texture.create(data, *w, *h, VK_FORMAT_R8G8B8A8_UNORM, filename.c_str()); texture.create(data, (w == nullptr ? dummy_w : *w), (h == nullptr ? dummy_h : *h), VK_FORMAT_R8G8B8A8_UNORM, filename.c_str());
#else #else
texture.create(data, *w, *h, VK_FORMAT_R8G8B8A8_UNORM, nullptr); texture.create(data, (w == nullptr ? dummy_w : *w), (h == nullptr ? dummy_h : *h), VK_FORMAT_R8G8B8A8_UNORM, nullptr);
#endif #endif
stbi_image_free(data); stbi_image_free(data);
return texture; return texture;

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/03/08 02:24:58 by maldavid #+# #+# */ /* Created: 2023/03/08 02:24:58 by maldavid #+# #+# */
/* Updated: 2023/11/25 10:01:35 by maldavid ### ########.fr */ /* Updated: 2024/03/14 19:06:07 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -14,13 +14,15 @@
#define __MLX_TEXTURE__ #define __MLX_TEXTURE__
#include <filesystem> #include <filesystem>
#include <memory>
#include <array> #include <array>
#include <functional>
#include <renderer/images/vk_image.h> #include <renderer/images/vk_image.h>
#include <renderer/descriptors/vk_descriptor_set.h> #include <renderer/descriptors/vk_descriptor_set.h>
#include <renderer/buffers/vk_ibo.h> #include <renderer/buffers/vk_ibo.h>
#include <renderer/buffers/vk_vbo.h> #include <renderer/buffers/vk_vbo.h>
#include <mlx_profile.h>
#ifdef DEBUG
#include <string>
#endif
namespace mlx namespace mlx
{ {
@@ -29,18 +31,18 @@ namespace mlx
public: public:
Texture() = default; Texture() = default;
void create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format, const char* name, bool dedicated_memory = false); void create(std::uint8_t* pixels, std::uint32_t width, std::uint32_t height, VkFormat format, const char* name, bool dedicated_memory = false);
void render(class Renderer& renderer, int x, int y); void render(std::array<VkDescriptorSet, 2>& sets, class Renderer& renderer, int x, int y);
void destroy() noexcept override; void destroy() noexcept override;
void setPixel(int x, int y, uint32_t color) noexcept; void setPixel(int x, int y, std::uint32_t color) noexcept;
int getPixel(int x, int y) noexcept; int getPixel(int x, int y) noexcept;
inline void setDescriptor(DescriptorSet set) noexcept { _set = std::move(set); } inline void setDescriptor(DescriptorSet&& set) noexcept { _set = set; }
inline VkDescriptorSet getSet() noexcept { return _set.isInit() ? _set.get() : VK_NULL_HANDLE; } inline VkDescriptorSet getSet() noexcept { return _set.isInit() ? _set.get() : VK_NULL_HANDLE; }
inline void updateSet(int binding) noexcept { _set.writeDescriptor(binding, getImageView(), getSampler()); _has_been_updated = true; } inline void updateSet(int binding) noexcept { _set.writeDescriptor(binding, *this); _has_set_been_updated = true; }
inline bool hasBeenUpdated() const noexcept { return _has_been_updated; } inline bool hasBeenUpdated() const noexcept { return _has_set_been_updated; }
inline constexpr void resetUpdate() noexcept { _has_been_updated = false; } inline constexpr void resetUpdate() noexcept { _has_set_been_updated = false; }
~Texture() = default; ~Texture() = default;
@@ -54,37 +56,14 @@ namespace mlx
std::string _name; std::string _name;
#endif #endif
DescriptorSet _set; DescriptorSet _set;
std::vector<uint32_t> _cpu_map; std::vector<std::uint32_t> _cpu_map;
std::optional<Buffer> _buf_map = std::nullopt; std::optional<Buffer> _buf_map = std::nullopt;
void* _map = nullptr; void* _map = nullptr;
bool _has_been_modified = false; bool _has_been_modified = false;
bool _has_been_updated = false; bool _has_set_been_updated = false;
}; };
Texture stbTextureLoad(std::filesystem::path file, int* w, int* h); Texture stbTextureLoad(std::filesystem::path file, int* w, int* h);
struct TextureRenderData
{
Texture* texture;
std::size_t hash = 0;
int x;
int y;
TextureRenderData(Texture* _texture, int _x, int _y) : texture(_texture), x(_x), y(_y) {}
bool operator==(const TextureRenderData& rhs) const { return texture == rhs.texture && x == rhs.x && y == rhs.y; }
};
}
namespace std
{
template <>
struct hash<mlx::TextureRenderData>
{
size_t operator()(const mlx::TextureRenderData& td) const noexcept
{
return std::hash<mlx::Texture*>()(td.texture) + std::hash<int>()(td.x) + std::hash<int>()(td.y);
}
};
} }
#endif #endif

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/07 16:40:09 by maldavid #+# #+# */ /* Created: 2023/04/07 16:40:09 by maldavid #+# #+# */
/* Updated: 2023/11/14 05:36:46 by maldavid ### ########.fr */ /* Updated: 2024/01/18 10:18:08 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -20,33 +20,37 @@
namespace mlx namespace mlx
{ {
void TextureAtlas::create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format, const char* name, bool dedicated_memory) void TextureAtlas::create(std::uint8_t* pixels, std::uint32_t width, std::uint32_t height, VkFormat format, const char* name, bool dedicated_memory)
{ {
Image::create(width, height, format, TILING, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, name, dedicated_memory); Image::create(width, height, format, TILING, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, name, dedicated_memory);
Image::createImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT); Image::createImageView(VK_IMAGE_VIEW_TYPE_2D, VK_IMAGE_ASPECT_COLOR_BIT);
Image::createSampler(); Image::createSampler();
transitionLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
if(pixels != nullptr) if(pixels == nullptr)
{ {
core::error::report(e_kind::warning, "Renderer : creating an empty texture atlas. They cannot be updated after creation, this might be a mistake or a bug, please report");
return;
}
Buffer staging_buffer; Buffer staging_buffer;
std::size_t size = width * height * formatSize(format); std::size_t size = width * height * formatSize(format);
staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, name, pixels); staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, name, pixels);
Image::copyFromBuffer(staging_buffer); Image::copyFromBuffer(staging_buffer);
staging_buffer.destroy(); staging_buffer.destroy();
} }
}
void TextureAtlas::render(Renderer& renderer, int x, int y, uint32_t ibo_size) void TextureAtlas::render(Renderer& renderer, int x, int y, std::uint32_t ibo_size) const
{ {
auto cmd = renderer.getActiveCmdBuffer().get(); auto cmd = renderer.getActiveCmdBuffer().get();
glm::vec2 translate(x, y); glm::vec2 translate(x, y);
vkCmdPushConstants(cmd, renderer.getPipeline().getPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(translate), &translate); vkCmdPushConstants(cmd, renderer.getPipeline().getPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(translate), &translate);
vkCmdDrawIndexed(cmd, ibo_size / sizeof(uint16_t), 1, 0, 0, 0); vkCmdDrawIndexed(cmd, ibo_size / sizeof(std::uint16_t), 1, 0, 0, 0);
} }
void TextureAtlas::destroy() noexcept void TextureAtlas::destroy() noexcept
{ {
Image::destroy(); Image::destroy();
_set.destroy();
} }
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/07 16:36:33 by maldavid #+# #+# */ /* Created: 2023/04/07 16:36:33 by maldavid #+# #+# */
/* Updated: 2023/11/14 05:36:30 by maldavid ### ########.fr */ /* Updated: 2024/03/14 19:57:55 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -14,8 +14,8 @@
#define __MLX_TEXTURE_ATLAS__ #define __MLX_TEXTURE_ATLAS__
#include <renderer/images/texture.h> #include <renderer/images/texture.h>
#include <array>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <mlx_profile.h>
namespace mlx namespace mlx
{ {
@@ -24,18 +24,22 @@ namespace mlx
public: public:
TextureAtlas() = default; TextureAtlas() = default;
void create(uint8_t* pixels, uint32_t width, uint32_t height, VkFormat format, const char* name, bool dedicated_memory = false); void create(std::uint8_t* pixels, std::uint32_t width, std::uint32_t height, VkFormat format, const char* name, bool dedicated_memory = false);
void render(class Renderer& renderer, int x, int y, uint32_t ibo_size); void render(class Renderer& renderer, int x, int y, std::uint32_t ibo_size) const;
void destroy() noexcept override; void destroy() noexcept override;
inline void setDescriptor(DescriptorSet set) noexcept { _set = std::move(set); } inline void setDescriptor(DescriptorSet&& set) noexcept { _set = set; }
inline VkDescriptorSet getSet() noexcept { return _set.isInit() ? _set.get() : VK_NULL_HANDLE; } inline VkDescriptorSet getVkSet() noexcept { return _set.isInit() ? _set.get() : VK_NULL_HANDLE; }
inline void updateSet(int binding) noexcept { _set.writeDescriptor(binding, getImageView(), getSampler()); } inline DescriptorSet getSet() noexcept { return _set; }
inline void updateSet(int binding) noexcept { _set.writeDescriptor(binding, *this); _has_been_updated = true; }
inline bool hasBeenUpdated() const noexcept { return _has_been_updated; }
inline constexpr void resetUpdate() noexcept { _has_been_updated = false; }
~TextureAtlas() = default; ~TextureAtlas() = default;
private: private:
DescriptorSet _set; DescriptorSet _set;
bool _has_been_updated = false;
}; };
} }

59
src/renderer/images/texture_descriptor.h git.filemode.normal_file
View File

@@ -0,0 +1,59 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* texture_descriptor.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 01:00:13 by maldavid #+# #+# */
/* Updated: 2024/01/11 01:21:52 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_TEXTURE_DESCRIPTOR__
#define __MLX_TEXTURE_DESCRIPTOR__
#include <renderer/images/texture.h>
#include <renderer/core/drawable_resource.h>
#include <utils/combine_hash.h>
namespace mlx
{
struct TextureRenderDescriptor : public DrawableResource
{
Texture* texture;
int x;
int y;
TextureRenderDescriptor(Texture* _texture, int _x, int _y) : texture(_texture), x(_x), y(_y) {}
inline bool operator==(const TextureRenderDescriptor& rhs) const { return texture == rhs.texture && x == rhs.x && y == rhs.y; }
inline void render(std::array<VkDescriptorSet, 2>& sets, class Renderer& renderer) override
{
if(!texture->isInit())
return;
texture->render(sets, renderer, x, y);
}
inline void resetUpdate() override
{
if(!texture->isInit())
return;
texture->resetUpdate();
}
};
}
namespace std
{
template <>
struct hash<mlx::TextureRenderDescriptor>
{
std::size_t operator()(const mlx::TextureRenderDescriptor& d) const noexcept
{
std::size_t hash = 0;
mlx::hashCombine(hash, d.texture, d.x, d.y);
return hash;
}
};
}
#endif

67
src/renderer/images/texture_manager.h git.filemode.normal_file
View File

@@ -0,0 +1,67 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* texture_manager.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/11 00:56:15 by maldavid #+# #+# */
/* Updated: 2024/03/25 13:53:59 by maldavid ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef __MLX_TEXTURE_MANAGER__
#define __MLX_TEXTURE_MANAGER__
#include <unordered_set>
#include <renderer/images/texture_descriptor.h>
#include <core/profiler.h>
#include <utility>
namespace mlx
{
class TextureManager
{
public:
TextureManager() = default;
inline void clear() { _texture_descriptors.clear(); }
inline std::pair<DrawableResource*, bool> registerTexture(Texture* texture, int x, int y)
{
MLX_PROFILE_FUNCTION();
auto res = _texture_descriptors.emplace(texture, x, y);
return std::make_pair(static_cast<DrawableResource*>(&const_cast<TextureRenderDescriptor&>(*res.first)), res.second);
}
inline bool isTextureKnown(Texture* texture) noexcept
{
MLX_PROFILE_FUNCTION();
for(const auto& desc : _texture_descriptors)
{
if(desc.texture == texture)
return true;
}
return false;
}
inline void eraseTextures(Texture* texture)
{
MLX_PROFILE_FUNCTION();
for(auto it = _texture_descriptors.begin(); it != _texture_descriptors.end();)
{
if(it->texture == texture)
it = _texture_descriptors.erase(it);
else
++it;
}
}
~TextureManager() = default;
private:
std::unordered_set<TextureRenderDescriptor> _texture_descriptors;
};
}
#endif

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/25 11:59:07 by maldavid #+# #+# */ /* Created: 2023/01/25 11:59:07 by maldavid #+# #+# */
/* Updated: 2023/11/18 17:21:14 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:28:25 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -45,7 +45,7 @@ namespace mlx
} }
} }
VkFormat bitsToFormat(uint32_t bits) VkFormat bitsToFormat(std::uint32_t bits)
{ {
switch(bits) switch(bits)
{ {
@@ -99,44 +99,7 @@ namespace mlx
return accessMask; return accessMask;
} }
VkPipelineStageFlags accessFlagsToPipelineStage(VkAccessFlags accessFlags, VkPipelineStageFlags stageFlags) void Image::create(std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool dedicated_memory)
{
VkPipelineStageFlags stages = 0;
while(accessFlags != 0)
{
VkAccessFlagBits AccessFlag = static_cast<VkAccessFlagBits>(accessFlags & (~(accessFlags - 1)));
if(AccessFlag == 0 || (AccessFlag & (AccessFlag - 1)) != 0)
core::error::report(e_kind::fatal_error, "Vulkan : an error has been caught during access flag to pipeline stage operation");
accessFlags &= ~AccessFlag;
switch(AccessFlag)
{
case VK_ACCESS_INDIRECT_COMMAND_READ_BIT: stages |= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT; break;
case VK_ACCESS_INDEX_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break;
case VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: stages |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT; break;
case VK_ACCESS_UNIFORM_READ_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; break;
case VK_ACCESS_SHADER_READ_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_SHADER_WRITE_BIT: stages |= stageFlags | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT; break;
case VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break;
case VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; break;
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break;
case VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; break;
case VK_ACCESS_TRANSFER_READ_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break;
case VK_ACCESS_TRANSFER_WRITE_BIT: stages |= VK_PIPELINE_STAGE_TRANSFER_BIT; break;
case VK_ACCESS_HOST_READ_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break;
case VK_ACCESS_HOST_WRITE_BIT: stages |= VK_PIPELINE_STAGE_HOST_BIT; break;
case VK_ACCESS_MEMORY_READ_BIT: break;
case VK_ACCESS_MEMORY_WRITE_BIT: break;
default: core::error::report(e_kind::error, "Vulkan : unknown access flag"); break;
}
}
return stages;
}
void Image::create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool dedicated_memory)
{ {
_width = width; _width = width;
_height = height; _height = height;
@@ -167,8 +130,9 @@ namespace mlx
} }
_allocation = Render_Core::get().getAllocator().createImage(&imageInfo, &alloc_info, _image, name); _allocation = Render_Core::get().getAllocator().createImage(&imageInfo, &alloc_info, _image, name);
#ifdef DEBUG
_pool.init(); _name = name;
#endif
} }
void Image::createImageView(VkImageViewType type, VkImageAspectFlags aspectFlags) noexcept void Image::createImageView(VkImageViewType type, VkImageAspectFlags aspectFlags) noexcept
@@ -184,8 +148,13 @@ namespace mlx
viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1; viewInfo.subresourceRange.layerCount = 1;
if(vkCreateImageView(Render_Core::get().getDevice().get(), &viewInfo, nullptr, &_image_view) != VK_SUCCESS) VkResult res = vkCreateImageView(Render_Core::get().getDevice().get(), &viewInfo, nullptr, &_image_view);
core::error::report(e_kind::fatal_error, "Vulkan : failed to create an image view"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create an image view, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG
else
Render_Core::get().getLayers().setDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_IMAGE_VIEW, (std::uint64_t)_image_view, _name.c_str());
#endif
} }
void Image::createSampler() noexcept void Image::createSampler() noexcept
@@ -203,161 +172,66 @@ namespace mlx
info.anisotropyEnable = VK_FALSE; info.anisotropyEnable = VK_FALSE;
info.maxAnisotropy = 1.0f; info.maxAnisotropy = 1.0f;
if(vkCreateSampler(Render_Core::get().getDevice().get(), &info, nullptr, &_sampler) != VK_SUCCESS) VkResult res = vkCreateSampler(Render_Core::get().getDevice().get(), &info, nullptr, &_sampler);
core::error::report(e_kind::fatal_error, "Vulkan : failed to create an image"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create an image sampler, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG
else
Render_Core::get().getLayers().setDebugUtilsObjectNameEXT(VK_OBJECT_TYPE_SAMPLER, (std::uint64_t)_sampler, _name.c_str());
#endif
} }
void Image::copyFromBuffer(Buffer& buffer) void Image::copyFromBuffer(Buffer& buffer)
{ {
if(!_transfer_cmd.isInit()) CmdBuffer& cmd = Render_Core::get().getSingleTimeCmdBuffer();
_transfer_cmd.init(&_pool); cmd.beginRecord();
_transfer_cmd.reset(); VkImageLayout layout_save = _layout;
_transfer_cmd.beginRecord(); transitionLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &cmd);
VkImageMemoryBarrier copy_barrier{}; cmd.copyBufferToImage(buffer, *this);
copy_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
copy_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
copy_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
copy_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
copy_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
copy_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
copy_barrier.image = _image;
copy_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy_barrier.subresourceRange.levelCount = 1;
copy_barrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(_transfer_cmd.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &copy_barrier);
VkBufferImageCopy region{}; transitionLayout(layout_save, &cmd);
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = { 0, 0, 0 };
region.imageExtent = { _width, _height, 1 };
vkCmdCopyBufferToImage(_transfer_cmd.get(), buffer.get(), _image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region); cmd.endRecord();
cmd.submitIdle();
VkImageMemoryBarrier use_barrier{};
use_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
use_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
use_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
use_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
use_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
use_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
use_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
use_barrier.image = _image;
use_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
use_barrier.subresourceRange.levelCount = 1;
use_barrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(_transfer_cmd.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &use_barrier);
_transfer_cmd.endRecord();
_transfer_cmd.submitIdle();
} }
void Image::copyToBuffer(Buffer& buffer) void Image::copyToBuffer(Buffer& buffer)
{ {
if(!_transfer_cmd.isInit()) CmdBuffer& cmd = Render_Core::get().getSingleTimeCmdBuffer();
_transfer_cmd.init(&_pool); cmd.beginRecord();
_transfer_cmd.reset(); VkImageLayout layout_save = _layout;
_transfer_cmd.beginRecord(); transitionLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &cmd);
VkImageMemoryBarrier copy_barrier{}; cmd.copyImagetoBuffer(*this, buffer);
copy_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
copy_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
copy_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
copy_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
copy_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
copy_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
copy_barrier.image = _image;
copy_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy_barrier.subresourceRange.levelCount = 1;
copy_barrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(_transfer_cmd.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &copy_barrier);
VkBufferImageCopy region{}; transitionLayout(layout_save, &cmd);
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = { 0, 0, 0 };
region.imageExtent = { _width, _height, 1 };
vkCmdCopyImageToBuffer(_transfer_cmd.get(), _image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer.get(), 1, &region); cmd.endRecord();
cmd.submitIdle();
VkImageMemoryBarrier use_barrier{};
use_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
use_barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
use_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
use_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
use_barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
use_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
use_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
use_barrier.image = _image;
use_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
use_barrier.subresourceRange.levelCount = 1;
use_barrier.subresourceRange.layerCount = 1;
vkCmdPipelineBarrier(_transfer_cmd.get(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 0, nullptr, 0, nullptr, 1, &use_barrier);
_transfer_cmd.endRecord();
_transfer_cmd.submitIdle();
} }
void Image::transitionLayout(VkImageLayout new_layout) void Image::transitionLayout(VkImageLayout new_layout, CmdBuffer* cmd)
{ {
if(new_layout == _layout) if(new_layout == _layout)
return; return;
if(!_transfer_cmd.isInit()) bool singleTime = (cmd == nullptr);
_transfer_cmd.init(&_pool); if(singleTime)
_transfer_cmd.reset(); {
_transfer_cmd.beginRecord(); cmd = &Render_Core::get().getSingleTimeCmdBuffer();
cmd->beginRecord();
}
VkImageMemoryBarrier barrier{}; cmd->transitionImageLayout(*this, new_layout);
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = _layout;
barrier.newLayout = new_layout;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = _image;
barrier.subresourceRange.aspectMask = isDepthFormat(_format) ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
barrier.srcAccessMask = layoutToAccessMask(_layout, false);
barrier.dstAccessMask = layoutToAccessMask(new_layout, true);
if(isStencilFormat(_format))
barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
VkPipelineStageFlags sourceStage = 0; if(singleTime)
if(barrier.oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) {
sourceStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; cmd->endRecord();
else if(barrier.srcAccessMask != 0) cmd->submitIdle();
sourceStage = accessFlagsToPipelineStage(barrier.srcAccessMask, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); }
else
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
VkPipelineStageFlags destinationStage = 0;
if(barrier.newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)
destinationStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
else if(barrier.dstAccessMask != 0)
destinationStage = accessFlagsToPipelineStage(barrier.dstAccessMask, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
else
destinationStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
vkCmdPipelineBarrier(_transfer_cmd.get(), sourceStage, destinationStage, 0, 0, nullptr, 0, nullptr, 1, &barrier);
_transfer_cmd.endRecord();
_transfer_cmd.submitIdle();
_layout = new_layout; _layout = new_layout;
} }
@@ -379,14 +253,13 @@ namespace mlx
{ {
destroySampler(); destroySampler();
destroyImageView(); destroyImageView();
destroyCmdPool();
if(_image != VK_NULL_HANDLE) if(_image != VK_NULL_HANDLE)
Render_Core::get().getAllocator().destroyImage(_allocation, _image); Render_Core::get().getAllocator().destroyImage(_allocation, _image);
_image = VK_NULL_HANDLE; _image = VK_NULL_HANDLE;
} }
uint32_t formatSize(VkFormat format) std::uint32_t formatSize(VkFormat format)
{ {
switch(format) switch(format)
{ {

View File

@@ -6,75 +6,85 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/01/25 11:54:21 by maldavid #+# #+# */ /* Created: 2023/01/25 11:54:21 by maldavid #+# #+# */
/* Updated: 2023/11/18 17:10:05 by maldavid ### ########.fr */ /* Updated: 2024/01/19 06:10:15 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#ifndef __MLX_VK_IMAGE__ #ifndef __MLX_VK_IMAGE__
#define __MLX_VK_IMAGE__ #define __MLX_VK_IMAGE__
#include <mlx_profile.h>
#include <volk.h> #include <volk.h>
#include <cstddef> #include <vma.h>
#include <vector> #include <renderer/core/cmd_resource.h>
#include <renderer/command/vk_cmd_buffer.h> #include <renderer/command/vk_cmd_buffer.h>
#include <renderer/command/vk_cmd_pool.h> #include <renderer/command/vk_cmd_pool.h>
#ifdef DEBUG
#include <string>
#endif
namespace mlx namespace mlx
{ {
uint32_t formatSize(VkFormat format); std::uint32_t formatSize(VkFormat format);
bool isStencilFormat(VkFormat format);
bool isDepthFormat(VkFormat format);
VkFormat bitsToFormat(std::uint32_t bits);
VkPipelineStageFlags layoutToAccessMask(VkImageLayout layout, bool isDestination);
class Image class Image : public CmdResource
{ {
friend class SwapChain; friend class SwapChain;
public: public:
Image() = default; Image() = default;
inline void create(VkImage image, VkFormat format, uint32_t width, uint32_t height, VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED) noexcept inline void create(VkImage image, VkFormat format, std::uint32_t width, std::uint32_t height, VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED) noexcept
{ {
_image = image; _image = image;
_format = format; _format = format;
_width = width; _width = width;
_height = height; _height = height;
_layout = layout; _layout = layout;
_pool.init();
} }
void create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool decated_memory = false); void create(std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool decated_memory = false);
void createImageView(VkImageViewType type, VkImageAspectFlags aspectFlags) noexcept; void createImageView(VkImageViewType type, VkImageAspectFlags aspectFlags) noexcept;
void createSampler() noexcept; void createSampler() noexcept;
void copyFromBuffer(class Buffer& buffer); void copyFromBuffer(class Buffer& buffer);
void copyToBuffer(class Buffer& buffer); void copyToBuffer(class Buffer& buffer);
void transitionLayout(VkImageLayout new_layout); void transitionLayout(VkImageLayout new_layout, CmdBuffer* cmd = nullptr);
virtual void destroy() noexcept; virtual void destroy() noexcept;
inline VkImage get() noexcept { return _image; } inline VkImage get() noexcept { return _image; }
inline VkImage operator()() noexcept { return _image; } inline VkImage operator()() noexcept { return _image; }
inline VkImageView getImageView() noexcept { return _image_view; } inline VkImageView getImageView() const noexcept { return _image_view; }
inline VkFormat getFormat() noexcept { return _format; } inline VkFormat getFormat() const noexcept { return _format; }
inline VkImageTiling getTiling() noexcept { return _tiling; } inline VkImageTiling getTiling() const noexcept { return _tiling; }
inline VkSampler getSampler() noexcept { return _sampler; } inline VkImageLayout getLayout() const noexcept { return _layout; }
inline uint32_t getWidth() const noexcept { return _width; } inline VkSampler getSampler() const noexcept { return _sampler; }
inline uint32_t getHeight() const noexcept { return _height; } inline std::uint32_t getWidth() const noexcept { return _width; }
inline std::uint32_t getHeight() const noexcept { return _height; }
inline bool isInit() const noexcept { return _image != VK_NULL_HANDLE; }
virtual ~Image() = default; virtual ~Image() = default;
private: private:
void destroySampler() noexcept; void destroySampler() noexcept;
void destroyImageView() noexcept; void destroyImageView() noexcept;
inline void destroyCmdPool() noexcept { _transfer_cmd.destroy(); _pool.destroy(); }
private: private:
CmdBuffer _transfer_cmd;
CmdPool _pool;
VmaAllocation _allocation; VmaAllocation _allocation;
VkImage _image = VK_NULL_HANDLE; VkImage _image = VK_NULL_HANDLE;
VkImageView _image_view = VK_NULL_HANDLE; VkImageView _image_view = VK_NULL_HANDLE;
VkSampler _sampler = VK_NULL_HANDLE; VkSampler _sampler = VK_NULL_HANDLE;
#ifdef DEBUG
std::string _name;
#endif
VkFormat _format; VkFormat _format;
VkImageTiling _tiling; VkImageTiling _tiling;
VkImageLayout _layout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout _layout = VK_IMAGE_LAYOUT_UNDEFINED;
uint32_t _width = 0; std::uint32_t _width = 0;
uint32_t _height = 0; std::uint32_t _height = 0;
}; };
} }

View File

@@ -6,7 +6,7 @@
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */ /* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/12/18 21:27:38 by maldavid #+# #+# */ /* Created: 2022/12/18 21:27:38 by maldavid #+# #+# */
/* Updated: 2023/11/25 10:23:20 by maldavid ### ########.fr */ /* Updated: 2024/03/14 17:05:21 by maldavid ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -49,7 +49,7 @@ namespace mlx
gl_Position = uProj.mat * vec4(pos.x, pos.y, 0.0, 1.0); gl_Position = uProj.mat * vec4(pos.x, pos.y, 0.0, 1.0);
} }
*/ */
const std::vector<uint32_t> vertex_shader = { const std::vector<std::uint32_t> vertex_shader = { // precompiled vertex shader
0x07230203,0x00010000,0x0008000b,0x0000003b,0x00000000,0x00020011,0x00000001,0x0006000b, 0x07230203,0x00010000,0x0008000b,0x0000003b,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015, 0x000a000f,0x00000000,0x00000004,0x6e69616d,0x00000000,0x0000000b,0x0000000f,0x00000015,
@@ -124,7 +124,7 @@ namespace mlx
fColor = process_color; fColor = process_color;
} }
*/ */
const std::vector<uint32_t> fragment_shader = { const std::vector<std::uint32_t> fragment_shader = { // pre compiled fragment shader
0x07230203,0x00010000,0x0008000b,0x0000002c,0x00000000,0x00020011,0x00000001,0x0006000b, 0x07230203,0x00010000,0x0008000b,0x0000002c,0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001, 0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x0000000d,0x0000002a,0x00030010, 0x0007000f,0x00000004,0x00000004,0x6e69616d,0x00000000,0x0000000d,0x0000002a,0x00030010,
@@ -164,7 +164,7 @@ namespace mlx
{ {
VkShaderModuleCreateInfo createInfo{}; VkShaderModuleCreateInfo createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = vertex_shader.size() * sizeof(uint32_t); createInfo.codeSize = vertex_shader.size() * sizeof(std::uint32_t);
createInfo.pCode = vertex_shader.data(); createInfo.pCode = vertex_shader.data();
VkShaderModule vshader; VkShaderModule vshader;
if(vkCreateShaderModule(Render_Core::get().getDevice().get(), &createInfo, nullptr, &vshader) != VK_SUCCESS) if(vkCreateShaderModule(Render_Core::get().getDevice().get(), &createInfo, nullptr, &vshader) != VK_SUCCESS)
@@ -176,7 +176,7 @@ namespace mlx
push_constant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; push_constant.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
createInfo.codeSize = fragment_shader.size() * sizeof(uint32_t); createInfo.codeSize = fragment_shader.size() * sizeof(std::uint32_t);
createInfo.pCode = fragment_shader.data(); createInfo.pCode = fragment_shader.data();
VkShaderModule fshader; VkShaderModule fshader;
if(vkCreateShaderModule(Render_Core::get().getDevice().get(), &createInfo, nullptr, &fshader) != VK_SUCCESS) if(vkCreateShaderModule(Render_Core::get().getDevice().get(), &createInfo, nullptr, &fshader) != VK_SUCCESS)
@@ -203,7 +203,7 @@ namespace mlx
vertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputStateCreateInfo.vertexBindingDescriptionCount = 1; vertexInputStateCreateInfo.vertexBindingDescriptionCount = 1;
vertexInputStateCreateInfo.pVertexBindingDescriptions = &bindingDescription; vertexInputStateCreateInfo.pVertexBindingDescriptions = &bindingDescription;
vertexInputStateCreateInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size()); vertexInputStateCreateInfo.vertexAttributeDescriptionCount = static_cast<std::uint32_t>(attributeDescriptions.size());
vertexInputStateCreateInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); vertexInputStateCreateInfo.pVertexAttributeDescriptions = attributeDescriptions.data();
VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; VkPipelineInputAssemblyStateCreateInfo inputAssembly{};
@@ -213,7 +213,7 @@ namespace mlx
VkDynamicState states[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; VkDynamicState states[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
constexpr size_t statesCount = sizeof(states) / sizeof(VkDynamicState); constexpr std::size_t statesCount = sizeof(states) / sizeof(VkDynamicState);
VkPipelineDynamicStateCreateInfo dynamicStates{}; VkPipelineDynamicStateCreateInfo dynamicStates{};
dynamicStates.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; dynamicStates.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamicStates.dynamicStateCount = statesCount; dynamicStates.dynamicStateCount = statesCount;
@@ -222,14 +222,14 @@ namespace mlx
VkViewport viewport{}; VkViewport viewport{};
viewport.x = 0.0f; viewport.x = 0.0f;
viewport.y = 0.0f; viewport.y = 0.0f;
viewport.width = (float)renderer.getSwapChain().getExtent().width; viewport.width = (float)renderer.getFrameBuffer(0).getWidth();
viewport.height = (float)renderer.getSwapChain().getExtent().height; viewport.height = (float)renderer.getFrameBuffer(0).getHeight();
viewport.minDepth = 0.0f; viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f; viewport.maxDepth = 1.0f;
VkRect2D scissor{}; VkRect2D scissor{};
scissor.offset = { 0, 0 }; scissor.offset = { 0, 0 };
scissor.extent = renderer.getSwapChain().getExtent(); scissor.extent = { renderer.getFrameBuffer(0).getWidth(), renderer.getFrameBuffer(0).getHeight()};
VkPipelineViewportStateCreateInfo viewportState{}; VkPipelineViewportStateCreateInfo viewportState{};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
@@ -286,7 +286,7 @@ namespace mlx
pipelineLayoutInfo.pushConstantRangeCount = 1; pipelineLayoutInfo.pushConstantRangeCount = 1;
pipelineLayoutInfo.pPushConstantRanges = &push_constant; pipelineLayoutInfo.pPushConstantRanges = &push_constant;
if(vkCreatePipelineLayout(Render_Core::get().getDevice().get(), &pipelineLayoutInfo, nullptr, &_pipelineLayout) != VK_SUCCESS) if(vkCreatePipelineLayout(Render_Core::get().getDevice().get(), &pipelineLayoutInfo, nullptr, &_pipeline_layout) != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a graphics pipeline layout"); core::error::report(e_kind::fatal_error, "Vulkan : failed to create a graphics pipeline layout");
VkGraphicsPipelineCreateInfo pipelineInfo{}; VkGraphicsPipelineCreateInfo pipelineInfo{};
@@ -300,13 +300,14 @@ namespace mlx
pipelineInfo.pMultisampleState = &multisampling; pipelineInfo.pMultisampleState = &multisampling;
pipelineInfo.pColorBlendState = &colorBlending; pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDynamicState = &dynamicStates; pipelineInfo.pDynamicState = &dynamicStates;
pipelineInfo.layout = _pipelineLayout; pipelineInfo.layout = _pipeline_layout;
pipelineInfo.renderPass = renderer.getRenderPass().get(); pipelineInfo.renderPass = renderer.getRenderPass().get();
pipelineInfo.subpass = 0; pipelineInfo.subpass = 0;
pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; pipelineInfo.basePipelineHandle = VK_NULL_HANDLE;
if(vkCreateGraphicsPipelines(Render_Core::get().getDevice().get(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &_graphicsPipeline) != VK_SUCCESS) VkResult res = vkCreateGraphicsPipelines(Render_Core::get().getDevice().get(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &_graphics_pipeline);
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a graphics pipeline"); if(res != VK_SUCCESS)
core::error::report(e_kind::fatal_error, "Vulkan : failed to create a graphics pipeline, %s", RCore::verbaliseResultVk(res));
#ifdef DEBUG #ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : created new graphic pipeline"); core::error::report(e_kind::message, "Vulkan : created new graphic pipeline");
#endif #endif
@@ -317,7 +318,11 @@ namespace mlx
void GraphicPipeline::destroy() noexcept void GraphicPipeline::destroy() noexcept
{ {
vkDestroyPipeline(Render_Core::get().getDevice().get(), _graphicsPipeline, nullptr); vkDestroyPipeline(Render_Core::get().getDevice().get(), _graphics_pipeline, nullptr);
vkDestroyPipelineLayout(Render_Core::get().getDevice().get(), _pipelineLayout, nullptr); vkDestroyPipelineLayout(Render_Core::get().getDevice().get(), _pipeline_layout, nullptr);
_graphics_pipeline = VK_NULL_HANDLE;
#ifdef DEBUG
core::error::report(e_kind::message, "Vulkan : destroyed a graphics pipeline");
#endif
} }
} }

Some files were not shown because too many files have changed in this diff Show More