Compare commits
293 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
226430f01e | ||
|
|
ae3be69081 | ||
|
|
307270532f | ||
|
|
04f9cb1d95 | ||
|
|
c45a76a5bf | ||
|
|
09561328ed | ||
|
|
baa0ab0a2c | ||
|
|
fd56e83c7b | ||
|
|
ea2ee83a3e | ||
|
|
5be3c86de4 | ||
|
|
ae02055e18 | ||
|
|
74e2d04b7b | ||
|
|
6ad95ca4c4 | ||
|
|
f08b1f6c8a | ||
|
|
4d640ed70c | ||
|
|
85ada83d57 | ||
|
|
c9ca2187b3 | ||
|
|
6a0f4fd8dc | ||
|
|
3dd68f9942 | ||
|
|
ffe5704673 | ||
|
|
20ec13d2b9 | ||
|
|
33d2b98c55 | ||
|
|
1adce43d9f | ||
|
|
466050ee7a | ||
|
|
6bc505de13 | ||
|
|
d70d748877 | ||
|
|
5cda85d16c | ||
|
|
9318456afb | ||
|
|
40fe100ecc | ||
|
|
c1bfc0f27d | ||
|
|
5a09ebb179 | ||
|
|
8370ae8324 | ||
|
|
a4fcbf187b | ||
|
|
b15aa648e2 | ||
|
|
9a88a8502e | ||
|
|
34a46d643a | ||
|
|
359be83f49 | ||
|
|
8c8c96bf30 | ||
|
|
e30a243452 | ||
|
|
f8e1cd4a66 | ||
|
|
d5512b72fa | ||
|
|
86f3d545ee | ||
|
|
9149f42b95 | ||
|
|
7aea6682f2 | ||
|
|
d0ca0e4ab7 | ||
|
|
f6dfed48dd | ||
|
|
5a69dff9d7 | ||
|
|
b7e2164f91 | ||
|
|
273858ec8f | ||
|
|
8f088eb76d | ||
|
|
a7433a6570 | ||
|
|
3ab445e780 | ||
|
|
dd554cce2a | ||
|
|
a182b53d7f | ||
|
|
a5f85a8a4c | ||
|
|
ae6a86800e | ||
|
|
b85e0444cb | ||
|
|
fc33d33508 | ||
|
|
14698594d8 | ||
|
|
024f3fefc3 | ||
|
|
33872806a1 | ||
|
|
3b4a1de9f3 | ||
|
|
5af4c82c1b | ||
|
|
e26af9ae1b | ||
|
|
8c41eefadb | ||
|
|
25d86eccee | ||
|
|
2393261cb0 | ||
|
|
d9d165f17e | ||
|
|
f446c82780 | ||
|
|
cc507ea4cf | ||
|
|
42fc7d9a86 | ||
|
|
60d3df7969 | ||
|
|
be52578d37 | ||
|
|
57c5ae5415 | ||
|
|
c6d6e409f1 | ||
|
|
c0dfcd9244 | ||
|
|
689608b3fe | ||
|
|
04330a10ac | ||
|
|
a456ad15ce | ||
|
|
e621bb53d4 | ||
|
|
420ba21b4d | ||
|
|
f3de55d6e9 | ||
|
|
bc1e0fbba9 | ||
|
|
80c0146ecd | ||
|
|
dbe3bb3cb3 | ||
|
|
83ecc6e498 | ||
|
|
8b2965f6dd | ||
|
|
6c31d3347a | ||
|
|
7f8ec481f1 | ||
|
|
25bb57a973 | ||
|
|
39365f52a2 | ||
|
|
fafc94248d | ||
|
|
edeaff793a | ||
|
|
2d5758419f | ||
|
|
ba063dae3b | ||
|
|
e018cad851 | ||
|
|
9ee8041710 | ||
|
|
1b50e123c5 | ||
|
|
77563b8449 | ||
|
|
d0923320a3 | ||
|
|
d8cab7aa47 | ||
|
|
fcf4d3d030 | ||
|
|
05362905f7 | ||
|
|
6866f2240e | ||
|
|
1903104247 | ||
|
|
04db0a7441 | ||
|
|
91cbb15b66 | ||
|
|
eeded8c8bc | ||
|
|
58e687c952 | ||
|
|
a0b536483a | ||
|
|
de1e8ed563 | ||
|
|
a832c3ca40 | ||
|
|
575ee21c7a | ||
|
|
071bc4596b | ||
|
|
178690cff3 | ||
|
|
1d566f74e3 | ||
|
|
eaa1b9afd0 | ||
|
|
a2d40ce844 | ||
|
|
4dcdcde7d5 | ||
|
|
8805f91bfd | ||
|
|
b5ca757189 | ||
|
|
c2d27c8434 | ||
|
|
5f55dd9b9a | ||
|
|
f044b9ab45 | ||
|
|
8c6ad92f37 | ||
|
|
34bdb740c2 | ||
|
|
c485f039fb | ||
|
|
3c60e76094 | ||
|
|
39650b5c96 | ||
|
|
0f16255240 | ||
|
|
91661fd206 | ||
|
|
6648bd427f | ||
|
|
aa2d0be63f | ||
|
|
2b557d5be7 | ||
|
|
36fae5c7d1 | ||
|
|
68570910e3 | ||
|
|
697a5e7147 | ||
|
|
31073c116c | ||
|
|
c6a024d911 | ||
|
|
66a1b44224 | ||
|
|
f5c581d89c | ||
|
|
765a04d9b5 | ||
|
|
ac054830b9 | ||
|
|
ccbd7561f4 | ||
|
|
2859725257 | ||
|
|
f18cce29b3 | ||
|
|
d9a7f337ba | ||
|
|
f8e619ad94 | ||
|
|
ea6450b308 | ||
|
|
6df9c284b8 | ||
|
|
d6b3f5dcc2 | ||
|
|
826740906f | ||
|
|
2c1f5181bf | ||
|
|
e728926521 | ||
|
|
04af533469 | ||
|
|
53048bd82a | ||
|
|
d0a19c5312 | ||
|
|
6e284fb9bc | ||
|
|
ea87c32051 | ||
|
|
d73ade4a85 | ||
|
|
67bfc73066 | ||
|
|
8b44a3aa6e | ||
|
|
36f9fdd53b | ||
|
|
9c43069e5f | ||
|
|
0b6e1717d9 | ||
|
|
41f7b4ef4c | ||
|
|
418791930c | ||
|
|
0690ecacd8 | ||
|
|
36f7efb679 | ||
|
|
a52e33e697 | ||
|
|
086c5402f5 | ||
|
|
dd1bd43360 | ||
|
|
d515ca5333 | ||
|
|
eeb4695d6c | ||
|
|
e94d3fd70f | ||
|
|
e76f084625 | ||
|
|
6e1fcb381a | ||
|
|
52c309a288 | ||
|
|
9ad28d7cf2 | ||
|
|
5f21f0bcf9 | ||
|
|
066eec2cf3 | ||
|
|
03e21227fa | ||
|
|
6f05728906 | ||
|
|
5edc36393a | ||
|
|
af29fc7b39 | ||
|
|
9795988e14 | ||
|
|
4087fca980 | ||
|
|
f3efb72a21 | ||
|
|
fc97445875 | ||
|
|
5babfde870 | ||
|
|
04ffce60cd | ||
|
|
9aaa26ddf5 | ||
|
|
df12d08ad3 | ||
|
|
064f660852 | ||
|
|
bf6389f9a7 | ||
|
|
cae3db0ebf | ||
|
|
79b01a5007 | ||
|
|
91927126f2 | ||
|
|
6fb8932ba9 | ||
|
|
536cf4c420 | ||
|
|
1b49794be6 | ||
|
|
25f73a6967 | ||
|
|
b7424e7f92 | ||
|
|
0b4b32b5ac | ||
|
|
1922b409dd | ||
|
|
80e938c019 | ||
|
|
68d2c63694 | ||
|
|
1386fe64cb | ||
|
|
7fd0ccff94 | ||
|
|
b28b144edb | ||
|
|
8e33b2fa30 | ||
|
|
cebadef063 | ||
|
|
57b27adf1a | ||
|
|
d08a97f55c | ||
|
|
c7ad6650d9 | ||
|
|
ac91253f51 | ||
|
|
3d939675e4 | ||
|
|
11b1bd147d | ||
|
|
c013237219 | ||
|
|
8039638885 | ||
|
|
d56b224d42 | ||
|
|
6ccf2a10d7 | ||
|
|
cfd1aab9e3 | ||
|
|
c5752f773e | ||
|
|
f398126e08 | ||
|
|
6c0d8829a5 | ||
|
|
cf3f16d832 | ||
|
|
b60ae54e34 | ||
|
|
7786b07eb8 | ||
|
|
90b1dac0f5 | ||
|
|
3c52fd05f3 | ||
|
|
843d7f0fe2 | ||
|
|
ea2014819d | ||
|
|
e458ef6401 | ||
|
|
0494ff14da | ||
|
|
c2c2dece61 | ||
|
|
401e6d13f3 | ||
|
|
2e5346a0ff | ||
|
|
ce5157a299 | ||
|
|
b5ce2347f6 | ||
|
|
9e0a0df5ca | ||
|
|
8f6f50c37f | ||
|
|
c36de40f4a | ||
|
|
52ca0c0d1b | ||
|
|
651a05c4bc | ||
|
|
1cfb8745e2 | ||
|
|
b3f3a01ee6 | ||
|
|
4acd240737 | ||
|
|
b79b8da031 | ||
|
|
bc7ef4484f | ||
|
|
9db5515fb5 | ||
|
|
387a1f5632 | ||
|
|
0babc2235f | ||
|
|
1a9a6ec6f8 | ||
|
|
d59d9f285a | ||
|
|
d16af1c4a8 | ||
|
|
5dcc2045d6 | ||
|
|
19ce912afe | ||
|
|
890e301b78 | ||
|
|
218a97e4ec | ||
|
|
74e5e35f5a | ||
|
|
e6298b1dc3 | ||
|
|
df860a5a64 | ||
|
|
b22064035a | ||
|
|
197c71021b | ||
|
|
d5fa70d7ab | ||
|
|
fd8e98f1ce | ||
|
|
0e10e5f8e1 | ||
|
|
689c9b3ed4 | ||
|
|
ecd43dedc5 | ||
|
|
dea507ec0e | ||
|
|
39501f2940 | ||
|
|
372f818da4 | ||
|
|
1651f9ba97 | ||
|
|
c7e09f1d8c | ||
|
|
82529d6dc9 | ||
|
|
4e30bd02bf | ||
|
|
f8c2abb20b | ||
|
|
880ac98ca9 | ||
|
|
49c211cebc | ||
|
|
38768c85c9 | ||
|
|
c7433ec419 | ||
|
|
d6b6dd955c | ||
|
|
c125dde951 | ||
|
|
9934b34bba | ||
|
|
3e3f20513f | ||
|
|
c93d7854d0 | ||
|
|
9fdb514541 | ||
|
|
35f5f41258 | ||
|
|
f6201014aa | ||
|
|
c583f1abc8 | ||
|
|
f7cf64cbb9 | ||
|
|
b882771a18 |
11
.github/dependabot.yml
vendored
git.filemode.normal_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
@@ -0,0 +1,29 @@
|
|||||||
|
name: Fetch Dependencies
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0' # Runs weekly
|
||||||
|
|
||||||
|
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
@@ -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.
|
||||||
|
|
||||||
8
.github/workflows/linux_clang.yml
vendored
@@ -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
|
||||||
|
|||||||
8
.github/workflows/linux_gcc.yml
vendored
@@ -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
|
||||||
|
|
||||||
|
|||||||
14
.github/workflows/macos_x86.yml
vendored
@@ -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
@@ -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
|
||||||
15
.gitignore
vendored
@@ -4,4 +4,19 @@
|
|||||||
*.a
|
*.a
|
||||||
*.so
|
*.so
|
||||||
*.out
|
*.out
|
||||||
|
*.dll
|
||||||
|
*.lib
|
||||||
|
*.exp
|
||||||
|
*.json
|
||||||
|
*.tmp
|
||||||
|
*.ilk
|
||||||
|
*.pdb
|
||||||
|
*.exe
|
||||||
|
*vgcore
|
||||||
|
*.gdb_history
|
||||||
|
.vs/
|
||||||
|
.xmake/
|
||||||
.cache/
|
.cache/
|
||||||
|
objs/
|
||||||
|
build/
|
||||||
|
example/Test
|
||||||
|
|||||||
17
CONTRIBUTING.md
git.filemode.normal_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.
|
||||||
|
|
||||||
354
LICENSE
@@ -1,340 +1,20 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
MIT License
|
||||||
Version 2, June 1991
|
Copyright (c) 2022-2024 kbz_8
|
||||||
|
|
||||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
in the Software without restriction, including without limitation the rights
|
||||||
of this license document, but changing it is not allowed.
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
Preamble
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
The licenses for most software are designed to take away your
|
|
||||||
freedom to share and change it. By contrast, the GNU General Public
|
|
||||||
License is intended to guarantee your freedom to share and change free
|
|
||||||
software--to make sure the software is free for all its users. This
|
|
||||||
General Public License applies to most of the Free Software
|
|
||||||
Foundation's software and to any other program whose authors commit to
|
|
||||||
using it. (Some other Free Software Foundation software is covered by
|
|
||||||
the GNU Lesser General Public License instead.) You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
|
||||||
have the freedom to distribute copies of free software (and charge for
|
|
||||||
this service if you wish), that you receive source code or can get it
|
|
||||||
if you want it, that you can change the software or use pieces of it
|
|
||||||
in new free programs; and that you know you can do these things.
|
|
||||||
|
|
||||||
To protect your rights, we need to make restrictions that forbid
|
|
||||||
anyone to deny you these rights or to ask you to surrender the rights.
|
|
||||||
These restrictions translate to certain responsibilities for you if you
|
|
||||||
distribute copies of the software, or if you modify it.
|
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
|
||||||
gratis or for a fee, you must give the recipients all the rights that
|
|
||||||
you have. You must make sure that they, too, receive or can get the
|
|
||||||
source code. And you must show them these terms so they know their
|
|
||||||
rights.
|
|
||||||
|
|
||||||
We protect your rights with two steps: (1) copyright the software, and
|
|
||||||
(2) offer you this license which gives you legal permission to copy,
|
|
||||||
distribute and/or modify the software.
|
|
||||||
|
|
||||||
Also, for each author's protection and ours, we want to make certain
|
|
||||||
that everyone understands that there is no warranty for this free
|
|
||||||
software. If the software is modified by someone else and passed on, we
|
|
||||||
want its recipients to know that what they have is not the original, so
|
|
||||||
that any problems introduced by others will not reflect on the original
|
|
||||||
authors' reputations.
|
|
||||||
|
|
||||||
Finally, any free program is threatened constantly by software
|
|
||||||
patents. We wish to avoid the danger that redistributors of a free
|
|
||||||
program will individually obtain patent licenses, in effect making the
|
|
||||||
program proprietary. To prevent this, we have made it clear that any
|
|
||||||
patent must be licensed for everyone's free use or not licensed at all.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
|
||||||
modification follow.
|
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
|
||||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
||||||
|
|
||||||
0. This License applies to any program or other work which contains
|
|
||||||
a notice placed by the copyright holder saying it may be distributed
|
|
||||||
under the terms of this General Public License. The "Program", below,
|
|
||||||
refers to any such program or work, and a "work based on the Program"
|
|
||||||
means either the Program or any derivative work under copyright law:
|
|
||||||
that is to say, a work containing the Program or a portion of it,
|
|
||||||
either verbatim or with modifications and/or translated into another
|
|
||||||
language. (Hereinafter, translation is included without limitation in
|
|
||||||
the term "modification".) Each licensee is addressed as "you".
|
|
||||||
|
|
||||||
Activities other than copying, distribution and modification are not
|
|
||||||
covered by this License; they are outside its scope. The act of
|
|
||||||
running the Program is not restricted, and the output from the Program
|
|
||||||
is covered only if its contents constitute a work based on the
|
|
||||||
Program (independent of having been made by running the Program).
|
|
||||||
Whether that is true depends on what the Program does.
|
|
||||||
|
|
||||||
1. You may copy and distribute verbatim copies of the Program's
|
|
||||||
source code as you receive it, in any medium, provided that you
|
|
||||||
conspicuously and appropriately publish on each copy an appropriate
|
|
||||||
copyright notice and disclaimer of warranty; keep intact all the
|
|
||||||
notices that refer to this License and to the absence of any warranty;
|
|
||||||
and give any other recipients of the Program a copy of this License
|
|
||||||
along with the Program.
|
|
||||||
|
|
||||||
You may charge a fee for the physical act of transferring a copy, and
|
|
||||||
you may at your option offer warranty protection in exchange for a fee.
|
|
||||||
|
|
||||||
2. You may modify your copy or copies of the Program or any portion
|
|
||||||
of it, thus forming a work based on the Program, and copy and
|
|
||||||
distribute such modifications or work under the terms of Section 1
|
|
||||||
above, provided that you also meet all of these conditions:
|
|
||||||
|
|
||||||
a) You must cause the modified files to carry prominent notices
|
|
||||||
stating that you changed the files and the date of any change.
|
|
||||||
|
|
||||||
b) You must cause any work that you distribute or publish, that in
|
|
||||||
whole or in part contains or is derived from the Program or any
|
|
||||||
part thereof, to be licensed as a whole at no charge to all third
|
|
||||||
parties under the terms of this License.
|
|
||||||
|
|
||||||
c) If the modified program normally reads commands interactively
|
|
||||||
when run, you must cause it, when started running for such
|
|
||||||
interactive use in the most ordinary way, to print or display an
|
|
||||||
announcement including an appropriate copyright notice and a
|
|
||||||
notice that there is no warranty (or else, saying that you provide
|
|
||||||
a warranty) and that users may redistribute the program under
|
|
||||||
these conditions, and telling the user how to view a copy of this
|
|
||||||
License. (Exception: if the Program itself is interactive but
|
|
||||||
does not normally print such an announcement, your work based on
|
|
||||||
the Program is not required to print an announcement.)
|
|
||||||
|
|
||||||
These requirements apply to the modified work as a whole. If
|
|
||||||
identifiable sections of that work are not derived from the Program,
|
|
||||||
and can be reasonably considered independent and separate works in
|
|
||||||
themselves, then this License, and its terms, do not apply to those
|
|
||||||
sections when you distribute them as separate works. But when you
|
|
||||||
distribute the same sections as part of a whole which is a work based
|
|
||||||
on the Program, the distribution of the whole must be on the terms of
|
|
||||||
this License, whose permissions for other licensees extend to the
|
|
||||||
entire whole, and thus to each and every part regardless of who wrote it.
|
|
||||||
|
|
||||||
Thus, it is not the intent of this section to claim rights or contest
|
|
||||||
your rights to work written entirely by you; rather, the intent is to
|
|
||||||
exercise the right to control the distribution of derivative or
|
|
||||||
collective works based on the Program.
|
|
||||||
|
|
||||||
In addition, mere aggregation of another work not based on the Program
|
|
||||||
with the Program (or with a work based on the Program) on a volume of
|
|
||||||
a storage or distribution medium does not bring the other work under
|
|
||||||
the scope of this License.
|
|
||||||
|
|
||||||
3. You may copy and distribute the Program (or a work based on it,
|
|
||||||
under Section 2) in object code or executable form under the terms of
|
|
||||||
Sections 1 and 2 above provided that you also do one of the following:
|
|
||||||
|
|
||||||
a) Accompany it with the complete corresponding machine-readable
|
|
||||||
source code, which must be distributed under the terms of Sections
|
|
||||||
1 and 2 above on a medium customarily used for software interchange; or,
|
|
||||||
|
|
||||||
b) Accompany it with a written offer, valid for at least three
|
|
||||||
years, to give any third party, for a charge no more than your
|
|
||||||
cost of physically performing source distribution, a complete
|
|
||||||
machine-readable copy of the corresponding source code, to be
|
|
||||||
distributed under the terms of Sections 1 and 2 above on a medium
|
|
||||||
customarily used for software interchange; or,
|
|
||||||
|
|
||||||
c) Accompany it with the information you received as to the offer
|
|
||||||
to distribute corresponding source code. (This alternative is
|
|
||||||
allowed only for noncommercial distribution and only if you
|
|
||||||
received the program in object code or executable form with such
|
|
||||||
an offer, in accord with Subsection b above.)
|
|
||||||
|
|
||||||
The source code for a work means the preferred form of the work for
|
|
||||||
making modifications to it. For an executable work, complete source
|
|
||||||
code means all the source code for all modules it contains, plus any
|
|
||||||
associated interface definition files, plus the scripts used to
|
|
||||||
control compilation and installation of the executable. However, as a
|
|
||||||
special exception, the source code distributed need not include
|
|
||||||
anything that is normally distributed (in either source or binary
|
|
||||||
form) with the major components (compiler, kernel, and so on) of the
|
|
||||||
operating system on which the executable runs, unless that component
|
|
||||||
itself accompanies the executable.
|
|
||||||
|
|
||||||
If distribution of executable or object code is made by offering
|
|
||||||
access to copy from a designated place, then offering equivalent
|
|
||||||
access to copy the source code from the same place counts as
|
|
||||||
distribution of the source code, even though third parties are not
|
|
||||||
compelled to copy the source along with the object code.
|
|
||||||
|
|
||||||
4. You may not copy, modify, sublicense, or distribute the Program
|
|
||||||
except as expressly provided under this License. Any attempt
|
|
||||||
otherwise to copy, modify, sublicense or distribute the Program is
|
|
||||||
void, and will automatically terminate your rights under this License.
|
|
||||||
However, parties who have received copies, or rights, from you under
|
|
||||||
this License will not have their licenses terminated so long as such
|
|
||||||
parties remain in full compliance.
|
|
||||||
|
|
||||||
5. You are not required to accept this License, since you have not
|
|
||||||
signed it. However, nothing else grants you permission to modify or
|
|
||||||
distribute the Program or its derivative works. These actions are
|
|
||||||
prohibited by law if you do not accept this License. Therefore, by
|
|
||||||
modifying or distributing the Program (or any work based on the
|
|
||||||
Program), you indicate your acceptance of this License to do so, and
|
|
||||||
all its terms and conditions for copying, distributing or modifying
|
|
||||||
the Program or works based on it.
|
|
||||||
|
|
||||||
6. Each time you redistribute the Program (or any work based on the
|
|
||||||
Program), the recipient automatically receives a license from the
|
|
||||||
original licensor to copy, distribute or modify the Program subject to
|
|
||||||
these terms and conditions. You may not impose any further
|
|
||||||
restrictions on the recipients' exercise of the rights granted herein.
|
|
||||||
You are not responsible for enforcing compliance by third parties to
|
|
||||||
this License.
|
|
||||||
|
|
||||||
7. If, as a consequence of a court judgment or allegation of patent
|
|
||||||
infringement or for any other reason (not limited to patent issues),
|
|
||||||
conditions are imposed on you (whether by court order, agreement or
|
|
||||||
otherwise) that contradict the conditions of this License, they do not
|
|
||||||
excuse you from the conditions of this License. If you cannot
|
|
||||||
distribute so as to satisfy simultaneously your obligations under this
|
|
||||||
License and any other pertinent obligations, then as a consequence you
|
|
||||||
may not distribute the Program at all. For example, if a patent
|
|
||||||
license would not permit royalty-free redistribution of the Program by
|
|
||||||
all those who receive copies directly or indirectly through you, then
|
|
||||||
the only way you could satisfy both it and this License would be to
|
|
||||||
refrain entirely from distribution of the Program.
|
|
||||||
|
|
||||||
If any portion of this section is held invalid or unenforceable under
|
|
||||||
any particular circumstance, the balance of the section is intended to
|
|
||||||
apply and the section as a whole is intended to apply in other
|
|
||||||
circumstances.
|
|
||||||
|
|
||||||
It is not the purpose of this section to induce you to infringe any
|
|
||||||
patents or other property right claims or to contest validity of any
|
|
||||||
such claims; this section has the sole purpose of protecting the
|
|
||||||
integrity of the free software distribution system, which is
|
|
||||||
implemented by public license practices. Many people have made
|
|
||||||
generous contributions to the wide range of software distributed
|
|
||||||
through that system in reliance on consistent application of that
|
|
||||||
system; it is up to the author/donor to decide if he or she is willing
|
|
||||||
to distribute software through any other system and a licensee cannot
|
|
||||||
impose that choice.
|
|
||||||
|
|
||||||
This section is intended to make thoroughly clear what is believed to
|
|
||||||
be a consequence of the rest of this License.
|
|
||||||
|
|
||||||
8. If the distribution and/or use of the Program is restricted in
|
|
||||||
certain countries either by patents or by copyrighted interfaces, the
|
|
||||||
original copyright holder who places the Program under this License
|
|
||||||
may add an explicit geographical distribution limitation excluding
|
|
||||||
those countries, so that distribution is permitted only in or among
|
|
||||||
countries not thus excluded. In such case, this License incorporates
|
|
||||||
the limitation as if written in the body of this License.
|
|
||||||
|
|
||||||
9. The Free Software Foundation may publish revised and/or new versions
|
|
||||||
of the General Public License from time to time. Such new versions will
|
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
|
||||||
address new problems or concerns.
|
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the Program
|
|
||||||
specifies a version number of this License which applies to it and "any
|
|
||||||
later version", you have the option of following the terms and conditions
|
|
||||||
either of that version or of any later version published by the Free
|
|
||||||
Software Foundation. If the Program does not specify a version number of
|
|
||||||
this License, you may choose any version ever published by the Free Software
|
|
||||||
Foundation.
|
|
||||||
|
|
||||||
10. If you wish to incorporate parts of the Program into other free
|
|
||||||
programs whose distribution conditions are different, write to the author
|
|
||||||
to ask for permission. For software which is copyrighted by the Free
|
|
||||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
|
||||||
make exceptions for this. Our decision will be guided by the two goals
|
|
||||||
of preserving the free status of all derivatives of our free software and
|
|
||||||
of promoting the sharing and reuse of software generally.
|
|
||||||
|
|
||||||
NO WARRANTY
|
|
||||||
|
|
||||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
|
||||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
|
||||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
|
||||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
|
||||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
|
||||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
|
||||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
|
||||||
REPAIR OR CORRECTION.
|
|
||||||
|
|
||||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
|
||||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
|
||||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
|
||||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
|
||||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
|
||||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
|
||||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
||||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
How to Apply These Terms to Your New Programs
|
|
||||||
|
|
||||||
If you develop a new program, and you want it to be of the greatest
|
|
||||||
possible use to the public, the best way to achieve this is to make it
|
|
||||||
free software which everyone can redistribute and change under these terms.
|
|
||||||
|
|
||||||
To do so, attach the following notices to the program. It is safest
|
|
||||||
to attach them to the start of each source file to most effectively
|
|
||||||
convey the exclusion of warranty; and each file should have at least
|
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
|
||||||
|
|
||||||
<one line to give the program's name and a brief idea of what it does.>
|
|
||||||
Copyright (C) <year> <name of author>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
|
||||||
|
|
||||||
If the program is interactive, make it output a short notice like this
|
|
||||||
when it starts in an interactive mode:
|
|
||||||
|
|
||||||
Gnomovision version 69, Copyright (C) year name of author
|
|
||||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
|
||||||
This is free software, and you are welcome to redistribute it
|
|
||||||
under certain conditions; type `show c' for details.
|
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, the commands you use may
|
|
||||||
be called something other than `show w' and `show c'; they could even be
|
|
||||||
mouse-clicks or menu items--whatever suits your program.
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or your
|
|
||||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
|
||||||
necessary. Here is a sample; alter the names:
|
|
||||||
|
|
||||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
|
||||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
|
||||||
|
|
||||||
<signature of Ty Coon>, 1 April 1989
|
|
||||||
Ty Coon, President of Vice
|
|
||||||
|
|
||||||
This General Public License does not permit incorporating your program into
|
|
||||||
proprietary programs. If your program is a subroutine library, you may
|
|
||||||
consider it more useful to permit linking proprietary applications with the
|
|
||||||
library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License.
|
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|||||||
124
Makefile
@@ -3,79 +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/13 06:08:16 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))
|
DEBUG ?= false
|
||||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./src/renderer))
|
TOOLCHAIN ?= clang
|
||||||
SRCS += $(wildcard $(addsuffix /*.cpp, ./src/renderer/**))
|
IMAGES_OPTIMIZED ?= true
|
||||||
|
FORCE_INTEGRATED_GPU ?= false
|
||||||
|
GRAPHICS_MEMORY_DUMP ?= false
|
||||||
|
PROFILER ?= false
|
||||||
|
_ENABLEDFLAGS =
|
||||||
|
|
||||||
OBJS = $(SRCS:.cpp=.o)
|
SRCS = $(wildcard $(addsuffix /*.cpp, src/core))
|
||||||
|
SRCS += $(wildcard $(addsuffix /*.cpp, src/platform))
|
||||||
|
SRCS += $(wildcard $(addsuffix /*.cpp, src/renderer))
|
||||||
|
SRCS += $(wildcard $(addsuffix /*.cpp, src/renderer/**))
|
||||||
|
|
||||||
OS = $(shell uname -s)
|
OBJ_DIR = objs/make/$(shell echo $(OS) | tr '[:upper:]' '[:lower:]')
|
||||||
DEBUG ?= false
|
OBJS := $(addprefix $(OBJ_DIR)/, $(SRCS:.cpp=.o))
|
||||||
TOOLCHAIN ?= clang
|
|
||||||
IMAGES_OPTIMIZED ?= true
|
|
||||||
FORCE_INTEGRATED_GPU ?= false
|
|
||||||
GRAPHICS_MEMORY_DUMP ?= false
|
|
||||||
|
|
||||||
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
|
||||||
|
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
|
||||||
|
|
||||||
RM = rm -f
|
ifeq ($(PROFILER), true)
|
||||||
|
_ENABLEDFLAGS += PROFILER
|
||||||
|
endif
|
||||||
|
|
||||||
%.o: %.cpp
|
CXXFLAGS += $(addprefix -D, $(_ENABLEDFLAGS))
|
||||||
@echo "\e[1;32m[compiling... "$(CXX)"]\e[1;00m "$<
|
|
||||||
|
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
|
||||||
|
@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): $(OBJS)
|
$(NAME): $(OBJS)
|
||||||
@echo "\e[1;32m[linking ...]\e[1;00m "$@
|
@printf "Linking $(_BOLD)$(NAME)$(_RESET)\n"
|
||||||
@$(CXX) -shared -o $(NAME) $(OBJS) $(LDLIBS)
|
@$(CXX) -shared -o $(NAME) $(OBJS) $(LDFLAGS)
|
||||||
@echo "\e[1;32m[build finished]\e[1;00m"
|
@printf "$(_BOLD)$(NAME)$(_RESET) compiled $(COLOR)$(_BOLD)successfully$(_RESET)\n"
|
||||||
|
|
||||||
|
_printbuildinfos:
|
||||||
|
@printf "$(_PURPLE)$(_BOLD)MacroLibX $(_RESET)Compiling in $(_BOLD)$(MODE)$(_RESET) mode on $(_BOLD)$(OS)$(_RESET) | Using $(_BOLD)$(CXX)$(_RESET), flags: $(_BOLD)$(_ENABLEDFLAGS)$(_RESET)\n"
|
||||||
|
|
||||||
|
debug:
|
||||||
|
@$(MAKE) all DEBUG=true -j$(shell nproc)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(RM) $(OBJS)
|
@$(RM) $(OBJ_DIR)
|
||||||
|
@printf "Cleaned $(_BOLD)$(OBJ_DIR)$(_RESET)\n"
|
||||||
|
|
||||||
fclean: clean
|
fclean: clean
|
||||||
@$(RM) $(NAME)
|
@$(RM) $(NAME)
|
||||||
|
@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
|
||||||
|
|||||||
90
README.md
@@ -1,16 +1,44 @@
|
|||||||
# MacroLibX [![linux clang workflow][linux-clang_badge]][linux-clang_wf] [![linux gcc workflow][linux-gcc_badge]][linux-gcc_wf] [![macos workflow][macos_badge]][macos_wf]
|
<div align="center">
|
||||||
###### A rewrite of 42 School's MiniLibX using SDL2 and Vulkan.
|
<img src="./res/logo.png" alt="drawing" width="200"/>
|
||||||
|
<div align="center">
|
||||||
|
<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/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/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>
|
||||||
|
|
||||||
|
###### 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>
|
||||||
@@ -30,56 +58,56 @@ 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
|
||||||
clang myApp.c /path/to/MacroLibX/libmlx.so -lSDL2
|
clang myApp.c /path/to/MacroLibX/libmlx.so -lSDL2
|
||||||
```
|
```
|
||||||
|
|
||||||
### ⚠️ Troubleshooting
|
And you can enjoy your project
|
||||||
|
|
||||||
#### If you run into glitches when writing or reading pixels from images
|
<p align="center">
|
||||||
|
<img src="./res/screenshot_test.png" alt="drawing" width="400"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
You need to add `IMAGES_OPTIMIZED=false` to your `make` command:
|
## ⚙️ Some compilation configurations
|
||||||
|
|
||||||
```sh
|
### 📦 Compile mode
|
||||||
# In your cloned environment, inside the MacroLibX folder
|
By default the mlx is built in release mode but you can switch to debug by using `make DEBUG=true`.
|
||||||
make IMAGES_OPTIMIZED=false
|
|
||||||
```
|
### 🛠️ Set the toolchain
|
||||||
|
If you want to use `GCC` to build the mlx you can use `make TOOLCHAIN=gcc`
|
||||||
|
|
||||||
|
### ⚠️⚠️⚠️ 🖼️ Image optimisations ⚠️⚠️⚠️
|
||||||
|
If you run into glitches when writing or reading pixels from images you can turn off images optimisations by using `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 [GNU GPL v2.0](./LICENSE).
|
|
||||||
|
|
||||||
<!-- Links -->
|
|
||||||
|
|
||||||
[linux-clang_badge]: https://github.com/420verfl0w/MacroLibX/actions/workflows/linux_clang.yml/badge.svg
|
|
||||||
[linux-gcc_badge]: https://github.com/420verfl0w/MacroLibX/actions/workflows/linux_gcc.yml/badge.svg
|
|
||||||
[macos_badge]: https://github.com/420verfl0w/MacroLibX/actions/workflows/macos_x86.yml/badge.svg
|
|
||||||
[linux-clang_wf]: https://github.com/420verfl0w/MacroLibX/actions/workflows/linux_clang.yml
|
|
||||||
[linux-gcc_wf]: https://github.com/420verfl0w/MacroLibX/actions/workflows/linux_gcc.yml
|
|
||||||
[macos_wf]: https://github.com/420verfl0w/MacroLibX/actions/workflows/macos_x86.yml
|
|
||||||
|
|||||||
47
XMAKE_BUILD.md
git.filemode.normal_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>
|
||||||
BIN
example/42_logo.bmp
git.filemode.normal_file
|
After Width: | Height: | Size: 30 KiB |
BIN
example/42_logo.jpg
git.filemode.normal_file
|
After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
12
example/build.sh
git.filemode.executable_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
|
||||||
|
|
||||||
BIN
example/font.ttf
git.filemode.normal_file
182
example/main.c
git.filemode.normal_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
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
bash ./build.sh
|
||||||
|
./a.out
|
||||||
138
includes/mlx.h
@@ -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/04/25 15:09:04 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,24 +94,27 @@ 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 given position
|
||||||
*
|
*
|
||||||
* @param mlx Internal MLX application
|
* @param mlx Internal MLX application
|
||||||
* @param win Internal window from which cursor moves
|
* @param win Internal window from which cursor moves
|
||||||
@@ -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,37 @@ 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);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Loads a font to be used by `mlx_string_put`
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window
|
||||||
|
* @param filepath Filepath to the font or "default" to reset to the embedded font
|
||||||
|
*
|
||||||
|
* @return (void)
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* @param mlx Internal MLX application
|
||||||
|
* @param win Internal window
|
||||||
|
* @param filepath Filepath to the font or "default" to reset to the embedded font
|
||||||
|
* @param scale Scale to apply to the font
|
||||||
|
*
|
||||||
|
* @return (void)
|
||||||
|
*/
|
||||||
|
MLX_API void mlx_set_font_scale(void* mlx, void* win, char* filepath, float scale);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -282,7 +336,7 @@ int mlx_string_put(void* mlx, void* win, int x, int y, int color, char* str);
|
|||||||
*
|
*
|
||||||
* @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);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -293,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
|
||||||
@@ -302,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
@@ -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
|
||||||
BIN
res/logo.png
git.filemode.normal_file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
res/screenshot_test.png
git.filemode.normal_file
|
After Width: | Height: | Size: 14 KiB |
BIN
res/screenshot_test_windows.png
git.filemode.normal_file
|
After Width: | Height: | Size: 13 KiB |
31
scripts/fetch_dependencies.sh
git.filemode.executable_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
@@ -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) {}
|
||||||
|
}
|
||||||
@@ -1,27 +1,33 @@
|
|||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
/* */
|
/* */
|
||||||
/* ::: :::::::: */
|
/* ::: :::::::: */
|
||||||
/* endian.h :+: :+: :+: */
|
/* UUID.h :+: :+: :+: */
|
||||||
/* +:+ +:+ +:+ */
|
/* +:+ +:+ +:+ */
|
||||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2023/04/06 15:33:15 by maldavid #+# #+# */
|
/* Created: 2024/01/06 11:13:23 by maldavid #+# #+# */
|
||||||
/* Updated: 2023/04/06 15:35:25 by maldavid ### ########.fr */
|
/* Updated: 2024/01/07 01:44:21 by maldavid ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
#ifndef __MLX_ENDIAN__
|
#ifndef __MLX_UUID__
|
||||||
#define __MLX_ENDIAN__
|
#define __MLX_UUID__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace mlx
|
namespace mlx
|
||||||
{
|
{
|
||||||
inline bool isSystemBigEndian()
|
class UUID
|
||||||
{
|
{
|
||||||
const int value = 0x01;
|
public:
|
||||||
const void* address = static_cast<const void*>(&value);
|
UUID();
|
||||||
const unsigned char* least_significant_address = static_cast<const unsigned char*>(address);
|
UUID(std::uint64_t uuid);
|
||||||
return (*least_significant_address != 0x01);
|
|
||||||
}
|
inline operator std::uint64_t() const { return _uuid; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::uint64_t _uuid;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -6,63 +6,124 @@
|
|||||||
/* 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/14 03:20:40 by maldavid ### ########.fr */
|
/* Updated: 2024/10/19 10:49:21 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 <utils/endian.h>
|
#include <mlx_profile.h>
|
||||||
#include <core/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)
|
||||||
{
|
{
|
||||||
_textures.emplace_front().create(nullptr, w, h, VK_FORMAT_R8G8B8A8_UNORM, "__mlx_unamed_user_texture");
|
MLX_PROFILE_FUNCTION();
|
||||||
|
#ifdef DEBUG
|
||||||
|
_textures.emplace_front().create(nullptr, w, h, VK_FORMAT_R8G8B8A8_UNORM, "__mlx_unamed_user_texture");
|
||||||
|
#else
|
||||||
|
_textures.emplace_front().create(nullptr, w, h, VK_FORMAT_R8G8B8A8_UNORM, nullptr);
|
||||||
|
#endif
|
||||||
return &_textures.front();
|
return &_textures.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
texture->destroy();
|
if(!texture->isInit())
|
||||||
|
core::error::report(e_kind::error, "trying to destroy a texture that has already been destroyed");
|
||||||
|
else
|
||||||
|
texture->destroy();
|
||||||
|
for(auto& gs : _graphics)
|
||||||
|
{
|
||||||
|
if(gs)
|
||||||
|
gs->tryEraseTextureFromManager(texture);
|
||||||
|
}
|
||||||
|
_textures.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application()
|
Application::~Application()
|
||||||
{
|
{
|
||||||
|
TextLibrary::get().clearLibrary();
|
||||||
|
TextLibrary::get().reset();
|
||||||
|
FontLibrary::get().clearLibrary();
|
||||||
|
FontLibrary::get().reset();
|
||||||
|
if(__drop_sdl_responsability)
|
||||||
|
return;
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_EVENTS);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/08/28 10:19:35 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,36 +38,41 @@ 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);
|
||||||
inline void loopEnd() noexcept;
|
inline void loopEnd() noexcept;
|
||||||
|
|
||||||
|
inline void loadFont(void* win, const std::filesystem::path& filepath, float scale);
|
||||||
|
|
||||||
void run() noexcept;
|
void run() noexcept;
|
||||||
|
|
||||||
~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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,67 +51,153 @@ 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
|
||||||
{
|
{
|
||||||
_graphics.emplace_back(std::make_unique<GraphicsSupport>(w, h, title, _graphics.size()));
|
_fps.setMaxFPS(fps);
|
||||||
_in->addWindow(_graphics.back()->getWindow());
|
}
|
||||||
|
|
||||||
|
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()));
|
||||||
|
_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)
|
||||||
|
{
|
||||||
|
MLX_PROFILE_FUNCTION();
|
||||||
|
CHECK_WINDOW_PTR(win);
|
||||||
|
_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);
|
||||||
_graphics[*static_cast<int*>(win)]->texturePut(texture, x, y);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
texture->setPixel(x, y, color);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::loopHook(int (*f)(void*), void* param)
|
void Application::loopHook(int (*f)(void*), void* param)
|
||||||
|
|||||||
@@ -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/14 11:43:30 by maldavid ### ########.fr */
|
/* Updated: 2024/09/12 01:29:33 by tdelage ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@@ -15,182 +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::MemManager::get(); // just to initialize the C garbage collector
|
||||||
|
mlx::core::Application* app = new mlx::core::Application;
|
||||||
mlx::Render_Core::get().init();
|
mlx::Render_Core::get().init();
|
||||||
init = true;
|
if(app == nullptr)
|
||||||
return new mlx::core::Application();
|
mlx::core::error::report(e_kind::fatal_error, "Tout a pété");
|
||||||
|
__mlx_ptr = static_cast<void*>(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_CHECK_APPLICATION_POINTER(mlx);
|
||||||
|
static_cast<mlx::core::Application*>(mlx)->setWindowPosition(win, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mlx_loop(void* mlx)
|
||||||
{
|
{
|
||||||
mlx->run();
|
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] = 0xFF;
|
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, "PNG 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, "PNG loader : not a jpg 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mlx_clear_window(mlx::core::Application* mlx, void* win)
|
void mlx_set_font(void* mlx, void* win, char* filepath)
|
||||||
{
|
{
|
||||||
mlx->clearGraphicsSupport(win);
|
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);
|
||||||
|
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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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(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);
|
||||||
|
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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static_cast<mlx::core::Application*>(mlx)->loadFont(win, file, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mlx_clear_window(void* mlx, void* 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
@@ -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/14 06:59:12 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()
|
||||||
{
|
{
|
||||||
vkDeviceWaitIdle(Render_Core::get().getDevice().get());
|
MLX_PROFILE_FUNCTION();
|
||||||
|
vkDeviceWaitIdle(Render_Core::get().getDevice().get());
|
||||||
|
_text_manager.destroy();
|
||||||
_pixel_put_pipeline.destroy();
|
_pixel_put_pipeline.destroy();
|
||||||
_text_put_pipeline->destroy();
|
|
||||||
_renderer->destroy();
|
_renderer->destroy();
|
||||||
|
if(_window)
|
||||||
|
_window->destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/14 11:39:55 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,38 +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 tryEraseTextureFromManager(Texture* texture) noexcept;
|
||||||
|
|
||||||
|
inline bool hasWindow() const noexcept { return _has_window; }
|
||||||
|
|
||||||
|
inline Renderer& getRenderer() { return *_renderer; }
|
||||||
|
|
||||||
~GraphicsSupport();
|
~GraphicsSupport();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_set<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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <core/graphics.h>
|
#include <core/graphics.h>
|
||||||
|
|
||||||
namespace mlx
|
namespace mlx
|
||||||
@@ -17,33 +18,63 @@ 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(texture, x, y);
|
MLX_PROFILE_FUNCTION();
|
||||||
|
auto res = _texture_manager.registerTexture(texture, x, y);
|
||||||
|
if(!res.second) // if this is not a completly new texture 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::loadFont(const std::filesystem::path& filepath, float 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
@@ -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
@@ -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
|
||||||
@@ -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
@@ -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
@@ -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
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -6,31 +6,51 @@
|
|||||||
/* 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/08 20:24:38 by maldavid ### ########.fr */
|
/* Updated: 2024/01/16 07:59:21 by maldavid ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
#include <platform/window.h>
|
#include <platform/window.h>
|
||||||
#include <core/errors.h>
|
#include <core/errors.h>
|
||||||
|
#include <utils/icon_mlx.h>
|
||||||
|
|
||||||
namespace mlx
|
namespace mlx
|
||||||
{
|
{
|
||||||
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||||
|
constexpr const std::uint32_t rmask = 0xff000000;
|
||||||
|
constexpr const std::uint32_t gmask = 0x00ff0000;
|
||||||
|
constexpr const std::uint32_t bmask = 0x0000ff00;
|
||||||
|
constexpr const std::uint32_t amask = 0x000000ff;
|
||||||
|
#else
|
||||||
|
constexpr const std::uint32_t rmask = 0x000000ff;
|
||||||
|
constexpr const std::uint32_t gmask = 0x0000ff00;
|
||||||
|
constexpr const std::uint32_t bmask = 0x00ff0000;
|
||||||
|
constexpr const std::uint32_t amask = 0xff000000;
|
||||||
|
#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());
|
||||||
_id = SDL_GetWindowID(_win);
|
_id = SDL_GetWindowID(_win);
|
||||||
|
_icon = SDL_CreateRGBSurfaceFrom(static_cast<void*>(logo_mlx), logo_mlx_width, logo_mlx_height, 32, 4 * logo_mlx_width, rmask, gmask, bmask, amask);
|
||||||
|
SDL_SetWindowIcon(_win, _icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MLX_Window::destroy() noexcept
|
void MLX_Window::destroy() noexcept
|
||||||
{
|
{
|
||||||
if(_win)
|
if(_win != nullptr)
|
||||||
|
{
|
||||||
SDL_DestroyWindow(_win);
|
SDL_DestroyWindow(_win);
|
||||||
}
|
_win = nullptr;
|
||||||
|
}
|
||||||
MLX_Window::~MLX_Window()
|
if(_icon != nullptr)
|
||||||
{
|
{
|
||||||
destroy();
|
SDL_FreeSurface(_icon);
|
||||||
|
_icon = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/08 20:24:46 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,17 +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_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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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/14 09:31:58 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,56 +61,73 @@ 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;
|
||||||
bufferInfo.usage = usage;
|
bufferInfo.usage = usage;
|
||||||
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
|
||||||
_name = name;
|
#ifdef DEBUG
|
||||||
std::string alloc_name = _name;
|
_name = name;
|
||||||
if(usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
|
std::string alloc_name = _name;
|
||||||
alloc_name.append("_index_buffer");
|
if(usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT)
|
||||||
else if(usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
alloc_name.append("_index_buffer");
|
||||||
alloc_name.append("_vertex_buffer");
|
else if(usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||||||
else if((usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) != 1)
|
alloc_name.append("_vertex_buffer");
|
||||||
alloc_name.append("_buffer");
|
else if(!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT))
|
||||||
_allocation = Render_Core::get().getAllocator().createBuffer(&bufferInfo, &info, _buffer, alloc_name.c_str());
|
alloc_name.append("_buffer");
|
||||||
|
_allocation = Render_Core::get().getAllocator().createBuffer(&bufferInfo, &info, _buffer, alloc_name.c_str());
|
||||||
|
#else
|
||||||
|
_allocation = Render_Core::get().getAllocator().createBuffer(&bufferInfo, &info, _buffer, nullptr);
|
||||||
|
#endif
|
||||||
_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;
|
||||||
|
|
||||||
std::string new_name = _name + "_GPU";
|
|
||||||
|
|
||||||
Buffer newBuffer;
|
Buffer newBuffer;
|
||||||
newBuffer._usage = (_usage & 0xFFFFFFFC) | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
newBuffer._usage = (_usage & 0xFFFFFFFC) | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||||
newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, new_name.c_str());
|
#ifdef DEBUG
|
||||||
|
std::string new_name = _name + "_GPU";
|
||||||
CmdPool cmdpool;
|
newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, new_name.c_str());
|
||||||
cmdpool.init();
|
#else
|
||||||
CmdBuffer cmdBuffer;
|
newBuffer.createBuffer(newBuffer._usage, alloc_info, _size, nullptr);
|
||||||
cmdBuffer.init(&cmdpool);
|
#endif
|
||||||
|
|
||||||
cmdBuffer.beginRecord(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
|
|
||||||
|
|
||||||
VkBufferCopy copyRegion{};
|
|
||||||
copyRegion.size = _size;
|
|
||||||
vkCmdCopyBuffer(cmdBuffer.get(), _buffer, newBuffer._buffer, 1, ©Region);
|
|
||||||
|
|
||||||
cmdBuffer.endRecord();
|
|
||||||
cmdBuffer.submitIdle();
|
|
||||||
|
|
||||||
cmdBuffer.destroy();
|
|
||||||
cmdpool.destroy();
|
|
||||||
|
|
||||||
this->swap(newBuffer);
|
|
||||||
|
|
||||||
|
if(newBuffer.copyFromBuffer(*this)) // if the copy succeded we swap the buffers, otherwise the new one is deleted
|
||||||
|
this->swap(newBuffer);
|
||||||
newBuffer.destroy();
|
newBuffer.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,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)
|
||||||
|
|||||||
@@ -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/14 03:24:12 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; }
|
||||||
@@ -51,7 +54,9 @@ namespace mlx
|
|||||||
void createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size, const char* name);
|
void createBuffer(VkBufferUsageFlags usage, VmaAllocationCreateInfo info, VkDeviceSize size, const char* name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _name;
|
#ifdef DEBUG
|
||||||
|
std::string _name;
|
||||||
|
#endif
|
||||||
VkBufferUsageFlags _usage = 0;
|
VkBufferUsageFlags _usage = 0;
|
||||||
bool _is_mapped = false;
|
bool _is_mapped = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,39 +6,47 @@
|
|||||||
/* 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/14 03:27:08 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++)
|
||||||
{
|
{
|
||||||
std::string name_frame = name;
|
#ifdef DEBUG
|
||||||
name_frame.append(std::to_string(i));
|
std::string name_frame = name;
|
||||||
_buffers[i].create(Buffer::kind::uniform, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, name_frame.c_str());
|
name_frame.append(std::to_string(i));
|
||||||
|
_buffers[i].create(Buffer::kind::uniform, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, name_frame.c_str());
|
||||||
|
#else
|
||||||
|
_buffers[i].create(Buffer::kind::uniform, size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, nullptr);
|
||||||
|
#endif
|
||||||
_buffers[i].mapMem(&_maps[i]);
|
_buffers[i].mapMem(&_maps[i]);
|
||||||
if(_maps[i] == nullptr)
|
if(_maps[i] == nullptr)
|
||||||
core::error::report(e_kind::fatal_error, "Vulkan : unable to map a uniform buffer");
|
core::error::report(e_kind::fatal_error, "Vulkan : unable to map a uniform buffer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
64
src/renderer/command/single_time_cmd_manager.cpp
git.filemode.normal_file
@@ -0,0 +1,64 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* single_time_cmd_manager.cpp :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2023/12/15 19:57:49 by maldavid #+# #+# */
|
||||||
|
/* Updated: 2024/10/19 10:47:04 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();
|
||||||
|
_buffers.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/renderer/command/single_time_cmd_manager.h
git.filemode.normal_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
|
||||||
@@ -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, ©Region);
|
||||||
|
|
||||||
|
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, ®ion);
|
||||||
|
|
||||||
|
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, ®ion);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VkSubmitInfo submitInfo = {};
|
_fence.reset();
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
||||||
submitInfo.commandBufferCount = 1;
|
|
||||||
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
|
|
||||||
{
|
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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: 2022/12/18 22:56:26 by maldavid ### ########.fr */
|
/* Updated: 2024/03/14 17:23:20 by maldavid ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@@ -20,14 +20,16 @@ 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
|
||||||
{
|
{
|
||||||
vkDestroyCommandPool(Render_Core::get().getDevice().get(), _cmd_pool, nullptr);
|
vkDestroyCommandPool(Render_Core::get().getDevice().get(), _cmd_pool, nullptr);
|
||||||
|
_cmd_pool = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
@@ -1,34 +1,32 @@
|
|||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
/* */
|
/* */
|
||||||
/* ::: :::::::: */
|
/* ::: :::::::: */
|
||||||
/* vk_imageview.h :+: :+: :+: */
|
/* drawable_resource.h :+: :+: :+: */
|
||||||
/* +:+ +:+ +:+ */
|
/* +:+ +:+ +:+ */
|
||||||
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
/* By: maldavid <kbz_8.dev@akel-engine.com> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2022/10/06 18:20:19 by maldavid #+# #+# */
|
/* Created: 2024/01/10 21:00:37 by maldavid #+# #+# */
|
||||||
/* Updated: 2022/12/18 19:54:44 by maldavid ### ########.fr */
|
/* Updated: 2024/01/11 01:21:15 by maldavid ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
#ifndef __MLX_VK_IMAGE_VIEW__
|
#ifndef __MLX_DRAWABLE_RESOURCE__
|
||||||
#define __MLX_VK_IMAGE_VIEW__
|
#define __MLX_DRAWABLE_RESOURCE__
|
||||||
|
|
||||||
|
#include <mlx_profile.h>
|
||||||
#include <volk.h>
|
#include <volk.h>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace mlx
|
namespace mlx
|
||||||
{
|
{
|
||||||
class ImageView
|
class DrawableResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void init(class SwapChain& swapchain, VkImage& image);
|
DrawableResource() = default;
|
||||||
void destroy() noexcept;
|
virtual void render(std::array<VkDescriptorSet, 2>& sets, class Renderer& renderer) = 0;
|
||||||
|
virtual void resetUpdate() {}
|
||||||
inline VkImageView& operator()() noexcept { return _image; }
|
virtual ~DrawableResource() = default;
|
||||||
inline VkImageView& get() noexcept { return _image; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
VkImageView _image = VK_NULL_HANDLE;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __MLX_VK_IMAGE_VIEW__
|
#endif
|
||||||
@@ -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);
|
||||||
@@ -147,14 +178,26 @@ namespace mlx
|
|||||||
file.close();
|
file.close();
|
||||||
id++;
|
id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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/14 08:15:42 by maldavid ### ########.fr */
|
/* Updated: 2024/10/19 10:50:13 by maldavid ### ########.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
|
||||||
#warning MLX is being compiled in debug mode, this activates Vulkan's validation layers and debug messages which may impact rendering performances
|
#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"
|
||||||
|
#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,84 @@ 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(_is_init)
|
||||||
|
return;
|
||||||
|
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 +128,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,11 +139,15 @@ namespace mlx
|
|||||||
|
|
||||||
vkDeviceWaitIdle(_device());
|
vkDeviceWaitIdle(_device());
|
||||||
|
|
||||||
|
_pool_manager.destroyAllPools();
|
||||||
|
_cmd_manager.destroy();
|
||||||
_allocator.destroy();
|
_allocator.destroy();
|
||||||
_device.destroy();
|
_device.destroy();
|
||||||
_layers.destroy();
|
_layers.destroy();
|
||||||
_instance.destroy();
|
_instance.destroy();
|
||||||
|
|
||||||
|
volkFinalize();
|
||||||
|
|
||||||
_is_init = false;
|
_is_init = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/14 05:00:44 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,43 +33,55 @@ 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
|
||||||
constexpr const bool enableValidationLayers = true;
|
constexpr const bool enableValidationLayers = true;
|
||||||
#else
|
#else
|
||||||
constexpr const bool enableValidationLayers = false;
|
constexpr const bool enableValidationLayers = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
void init();
|
public:
|
||||||
void destroy();
|
void init();
|
||||||
|
void destroy();
|
||||||
|
|
||||||
inline Instance& getInstance() noexcept { return _instance; }
|
inline bool isInit() const noexcept { return _is_init; }
|
||||||
inline Device& getDevice() noexcept { return _device; }
|
inline Instance& getInstance() noexcept { return _instance; }
|
||||||
inline Queues& getQueue() noexcept { return _queues; }
|
inline Device& getDevice() noexcept { return _device; }
|
||||||
|
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;
|
||||||
Queues _queues;
|
SingleTimeCmdManager _cmd_manager;
|
||||||
Device _device;
|
Queues _queues;
|
||||||
Instance _instance;
|
DescriptorPoolManager _pool_manager;
|
||||||
|
Device _device;
|
||||||
|
Instance _instance;
|
||||||
GPUallocator _allocator;
|
GPUallocator _allocator;
|
||||||
bool _is_init = false;
|
bool _is_init = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __MLX_RENDER_CORE__
|
#endif // __MLX_RENDER_CORE__
|
||||||
|
|||||||
@@ -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/11 10:38:01 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);
|
||||||
@@ -154,5 +159,9 @@ namespace mlx
|
|||||||
void Device::destroy() noexcept
|
void Device::destroy() noexcept
|
||||||
{
|
{
|
||||||
vkDestroyDevice(_device, nullptr);
|
vkDestroyDevice(_device, nullptr);
|
||||||
|
_device = VK_NULL_HANDLE;
|
||||||
|
#ifdef DEBUG
|
||||||
|
core::error::report(e_kind::message, "Vulkan : destroyed a logical device");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/08 20:14:23 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,8 +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
|
||||||
{
|
{
|
||||||
vkDestroyFence(Render_Core::get().getDevice().get(), _fence, nullptr);
|
if(_fence != VK_NULL_HANDLE)
|
||||||
|
vkDestroyFence(Render_Core::get().getDevice().get(), _fence, nullptr);
|
||||||
|
_fence = VK_NULL_HANDLE;
|
||||||
|
#ifdef DEBUG
|
||||||
|
core::error::report(e_kind::message, "Vulkan : destroyed fence");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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/08 20:13:30 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,30 +58,43 @@ 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());
|
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||||
|
extensions.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(!SDL_Vulkan_GetInstanceExtensions(window, &count, nullptr))
|
#ifdef VK_USE_PLATFORM_XLIB_KHR
|
||||||
core::error::report(e_kind::fatal_error, "Vulkan : cannot get instance extentions from window : %s", SDL_GetError());
|
extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||||
|
#endif
|
||||||
|
|
||||||
std::vector<const char*> extensions = { VK_EXT_DEBUG_REPORT_EXTENSION_NAME };
|
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
||||||
size_t additional_extension_count = extensions.size();
|
extensions.push_back(VK_KHR_WAYLAND_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_WIN32_KHR
|
||||||
core::error::report(e_kind::error, "Vulkan : cannot get instance extentions from window : %s", SDL_GetError());
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::destroy() noexcept
|
void Instance::destroy() noexcept
|
||||||
{
|
{
|
||||||
vkDestroyInstance(_instance, nullptr);
|
vkDestroyInstance(_instance, nullptr);
|
||||||
|
_instance = VK_NULL_HANDLE;
|
||||||
|
#ifdef DEBUG
|
||||||
|
core::error::report(e_kind::message, "Vulkan : destroyed an instance");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/08 20:14:36 by maldavid ### ########.fr */
|
/* Updated: 2024/03/14 17:02:36 by maldavid ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@@ -21,17 +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);
|
||||||
vkDestroySemaphore(Render_Core::get().getDevice().get(), _imageAvailableSemaphores, nullptr);
|
_render_finished_semaphore = VK_NULL_HANDLE;
|
||||||
|
vkDestroySemaphore(Render_Core::get().getDevice().get(), _image_available_semaphore, nullptr);
|
||||||
|
_image_available_semaphore = VK_NULL_HANDLE;
|
||||||
|
#ifdef DEBUG
|
||||||
|
core::error::report(e_kind::message, "Vulkan : destroyed semaphores");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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/08 20:14:48 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,17 +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;
|
||||||
|
#ifdef DEBUG
|
||||||
|
core::error::report(e_kind::message, "Vulkan : destroyed a surface");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
@@ -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/08 20:15:36 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,78 +24,99 @@ 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;
|
|
||||||
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
|
||||||
|
|
||||||
std::vector<VkLayerProperties> availableLayers(layerCount);
|
|
||||||
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
|
|
||||||
|
|
||||||
for(const char* layerName : validationLayers)
|
|
||||||
{
|
|
||||||
bool layerFound = false;
|
|
||||||
|
|
||||||
for(const auto& layerProperties : availableLayers)
|
|
||||||
{
|
|
||||||
if(std::strcmp(layerName, layerProperties.layerName) == 0)
|
|
||||||
{
|
|
||||||
layerFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!layerFound)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValidationLayers::destroy()
|
|
||||||
{
|
{
|
||||||
if constexpr(!enableValidationLayers)
|
std::uint32_t layerCount;
|
||||||
return;
|
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
||||||
destroyDebugUtilsMessengerEXT(nullptr);
|
|
||||||
|
std::vector<VkLayerProperties> availableLayers(layerCount);
|
||||||
|
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
|
||||||
|
|
||||||
|
return std::all_of(validationLayers.begin(), validationLayers.end(), [&](const char* layerName)
|
||||||
|
{
|
||||||
|
if(!std::any_of(availableLayers.begin(), availableLayers.end(), [=](VkLayerProperties props) { return std::strcmp(layerName, props.layerName) == 0; }))
|
||||||
|
{
|
||||||
|
core::error::report(e_kind::error, "Vulkan : a validation layer was requested but was not found ('%s')", layerName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
VkResult ValidationLayers::createDebugUtilsMessengerEXT(const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator)
|
VkResult ValidationLayers::setDebugUtilsObjectNameEXT(VkObjectType object_type, std::uint64_t object_handle, const char* object_name)
|
||||||
{
|
{
|
||||||
auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(Render_Core::get().getInstance().get(), "vkCreateDebugUtilsMessengerEXT");
|
if(!_vkSetDebugUtilsObjectNameEXT)
|
||||||
return func != nullptr ? func(Render_Core::get().getInstance().get(), pCreateInfo, pAllocator, &_debugMessenger) : VK_ERROR_EXTENSION_NOT_PRESENT;
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
|
||||||
|
VkDebugUtilsObjectNameInfoEXT name_info{};
|
||||||
|
name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
|
||||||
|
name_info.objectType = object_type;
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
createInfo = {};
|
createInfo = {};
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||||
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||||
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||||
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 constexpr(enableValidationLayers)
|
||||||
|
{
|
||||||
|
destroyDebugUtilsMessengerEXT(nullptr);
|
||||||
|
#ifdef DEBUG
|
||||||
|
core::error::report(e_kind::message, "Vulkan : destroyed validation layers");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)
|
||||||
{
|
core::error::report(e_kind::error, pCallbackData->pMessage);
|
||||||
std::cout << '\n';
|
|
||||||
core::error::report(e_kind::error, std::string("Vulkan layer error: ") + pCallbackData->pMessage);
|
|
||||||
}
|
|
||||||
else if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
|
else if(messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT)
|
||||||
{
|
core::error::report(e_kind::warning, pCallbackData->pMessage);
|
||||||
std::cout << '\n';
|
|
||||||
core::error::report(e_kind::warning, std::string("Vulkan layer 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
39
src/renderer/descriptors/descriptor_pool_manager.cpp
git.filemode.normal_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();
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/renderer/descriptors/descriptor_pool_manager.h
git.filemode.normal_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
|
||||||
@@ -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/01/23 18:44:51 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,14 +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::destroy() noexcept
|
void DescriptorPool::freeDescriptor(const DescriptorSet& set)
|
||||||
{
|
{
|
||||||
vkDestroyDescriptorPool(Render_Core::get().getDevice().get(), _pool, nullptr);
|
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
|
||||||
|
{
|
||||||
|
if(_pool != VK_NULL_HANDLE)
|
||||||
|
vkDestroyDescriptorPool(Render_Core::get().getDevice().get(), _pool, nullptr);
|
||||||
|
_pool = VK_NULL_HANDLE;
|
||||||
|
#ifdef DEBUG
|
||||||
|
core::error::report(e_kind::message, "Vulkan : destroyed a descriptor pool");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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/03/31 16:37:09 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,12 +34,14 @@ 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
|
||||||
{
|
{
|
||||||
vkDestroyDescriptorSetLayout(Render_Core::get().getDevice().get(), _layout, nullptr);
|
vkDestroyDescriptorSetLayout(Render_Core::get().getDevice().get(), _layout, nullptr);
|
||||||
|
_layout = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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/14 04:57:55 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
|
||||||
#include <stb_image.h>
|
#ifdef MLX_COMPILER_GCC
|
||||||
|
#pragma GCC diagnostic push
|
||||||
#include <iostream>
|
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||||
|
#include <stb_image.h>
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#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,25 +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 };
|
||||||
|
|
||||||
_vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data(), name);
|
#ifdef DEBUG
|
||||||
_ibo.create(sizeof(uint16_t) * indexData.size(), indexData.data(), name);
|
_vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data(), name);
|
||||||
|
_ibo.create(sizeof(std::uint16_t) * indexData.size(), indexData.data(), name);
|
||||||
|
_name = name;
|
||||||
|
#else
|
||||||
|
_vbo.create(sizeof(Vertex) * vertexData.size(), vertexData.data(), nullptr);
|
||||||
|
_ibo.create(sizeof(std::uint16_t) * indexData.size(), indexData.data(), nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Buffer staging_buffer;
|
||||||
|
std::size_t size = width * height * formatSize(format);
|
||||||
if(pixels != nullptr)
|
if(pixels != nullptr)
|
||||||
{
|
{
|
||||||
Buffer staging_buffer;
|
#ifdef DEBUG
|
||||||
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);
|
#else
|
||||||
Image::copyFromBuffer(staging_buffer);
|
staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, nullptr, pixels);
|
||||||
staging_buffer.destroy();
|
#endif
|
||||||
}
|
}
|
||||||
_name = name;
|
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);
|
||||||
|
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();
|
||||||
@@ -70,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;
|
||||||
|
|
||||||
@@ -88,35 +121,50 @@ namespace mlx
|
|||||||
#endif
|
#endif
|
||||||
std::size_t size = getWidth() * getHeight() * formatSize(getFormat());
|
std::size_t size = getWidth() * getHeight() * formatSize(getFormat());
|
||||||
_buf_map.emplace();
|
_buf_map.emplace();
|
||||||
_buf_map->create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, _name.c_str());
|
#ifdef DEBUG
|
||||||
|
_buf_map->create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, _name.c_str());
|
||||||
|
#else
|
||||||
|
_buf_map->create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, nullptr);
|
||||||
|
#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();
|
||||||
@@ -125,17 +173,24 @@ 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;
|
||||||
texture.create(data, *w, *h, VK_FORMAT_R8G8B8A8_UNORM, filename.c_str());
|
int dummy_h;
|
||||||
|
data = stbi_load(filename.c_str(), (w == nullptr ? &dummy_w : w), (h == nullptr ? &dummy_h : h), &channels, 4);
|
||||||
|
#ifdef DEBUG
|
||||||
|
texture.create(data, (w == nullptr ? dummy_w : *w), (h == nullptr ? dummy_h : *h), VK_FORMAT_R8G8B8A8_UNORM, filename.c_str());
|
||||||
|
#else
|
||||||
|
texture.create(data, (w == nullptr ? dummy_w : *w), (h == nullptr ? dummy_h : *h), VK_FORMAT_R8G8B8A8_UNORM, nullptr);
|
||||||
|
#endif
|
||||||
stbi_image_free(data);
|
stbi_image_free(data);
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/14 04:57:39 by maldavid ### ########.fr */
|
/* Updated: 2024/03/14 19:06:07 by maldavid ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@@ -14,33 +14,35 @@
|
|||||||
#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
|
||||||
{
|
{
|
||||||
class Texture : public Image
|
class Texture : public Image
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
|
||||||
@@ -50,38 +52,18 @@ namespace mlx
|
|||||||
private:
|
private:
|
||||||
C_VBO _vbo;
|
C_VBO _vbo;
|
||||||
C_IBO _ibo;
|
C_IBO _ibo;
|
||||||
std::string _name;
|
#ifdef DEBUG
|
||||||
|
std::string _name;
|
||||||
|
#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;
|
|
||||||
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
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
Buffer staging_buffer;
|
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");
|
||||||
std::size_t size = width * height * formatSize(format);
|
return;
|
||||||
staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, name, pixels);
|
|
||||||
Image::copyFromBuffer(staging_buffer);
|
|
||||||
staging_buffer.destroy();
|
|
||||||
}
|
}
|
||||||
|
Buffer staging_buffer;
|
||||||
|
std::size_t size = width * height * formatSize(format);
|
||||||
|
staging_buffer.create(Buffer::kind::dynamic, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, name, pixels);
|
||||||
|
Image::copyFromBuffer(staging_buffer);
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
@@ -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/14 09:31:39 by maldavid ### ########.fr */
|
/* Updated: 2024/03/14 17:28:25 by maldavid ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@@ -18,7 +18,88 @@
|
|||||||
|
|
||||||
namespace mlx
|
namespace mlx
|
||||||
{
|
{
|
||||||
void Image::create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool dedicated_memory)
|
bool isStencilFormat(VkFormat format)
|
||||||
|
{
|
||||||
|
switch(format)
|
||||||
|
{
|
||||||
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||||
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDepthFormat(VkFormat format)
|
||||||
|
{
|
||||||
|
switch(format)
|
||||||
|
{
|
||||||
|
case VK_FORMAT_D16_UNORM:
|
||||||
|
case VK_FORMAT_D32_SFLOAT:
|
||||||
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||||
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||||
|
case VK_FORMAT_D16_UNORM_S8_UINT:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkFormat bitsToFormat(std::uint32_t bits)
|
||||||
|
{
|
||||||
|
switch(bits)
|
||||||
|
{
|
||||||
|
case 8: return VK_FORMAT_R8_UNORM;
|
||||||
|
case 16: return VK_FORMAT_R8G8_UNORM;
|
||||||
|
case 24: return VK_FORMAT_R8G8B8_UNORM;
|
||||||
|
case 32: return VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
case 48: return VK_FORMAT_R16G16B16_SFLOAT;
|
||||||
|
case 64: return VK_FORMAT_R16G16B16A16_SFLOAT;
|
||||||
|
case 96: return VK_FORMAT_R32G32B32_SFLOAT;
|
||||||
|
case 128: return VK_FORMAT_R32G32B32A32_SFLOAT;
|
||||||
|
|
||||||
|
default:
|
||||||
|
core::error::report(e_kind::fatal_error, "Vulkan : unsupported image bit-depth");
|
||||||
|
return VK_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPipelineStageFlags layoutToAccessMask(VkImageLayout layout, bool isDestination)
|
||||||
|
{
|
||||||
|
VkPipelineStageFlags accessMask = 0;
|
||||||
|
|
||||||
|
switch(layout)
|
||||||
|
{
|
||||||
|
case VK_IMAGE_LAYOUT_UNDEFINED:
|
||||||
|
if(isDestination)
|
||||||
|
core::error::report(e_kind::error, "Vulkan : the new layout used in a transition must not be VK_IMAGE_LAYOUT_UNDEFINED");
|
||||||
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_GENERAL: accessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT; break;
|
||||||
|
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: accessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; break;
|
||||||
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: accessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; break;
|
||||||
|
case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
|
||||||
|
accessMask = VK_ACCESS_SHADER_READ_BIT; // VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
|
||||||
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: accessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; break;
|
||||||
|
case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: accessMask = VK_ACCESS_TRANSFER_READ_BIT; break;
|
||||||
|
case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: accessMask = VK_ACCESS_TRANSFER_WRITE_BIT; break;
|
||||||
|
case VK_IMAGE_LAYOUT_PREINITIALIZED:
|
||||||
|
if(!isDestination)
|
||||||
|
accessMask = VK_ACCESS_HOST_WRITE_BIT;
|
||||||
|
else
|
||||||
|
core::error::report(e_kind::error, "Vulkan : the new layout used in a transition must not be VK_IMAGE_LAYOUT_PREINITIALIZED");
|
||||||
|
break;
|
||||||
|
case VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL: accessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; break;
|
||||||
|
case VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL: accessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; break;
|
||||||
|
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: accessMask = VK_ACCESS_MEMORY_READ_BIT; break;
|
||||||
|
|
||||||
|
default: core::error::report(e_kind::error, "Vulkan : unexpected image layout"); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return accessMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::create(std::uint32_t width, std::uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool dedicated_memory)
|
||||||
{
|
{
|
||||||
_width = width;
|
_width = width;
|
||||||
_height = height;
|
_height = height;
|
||||||
@@ -49,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
|
||||||
@@ -66,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
|
||||||
@@ -85,130 +172,94 @@ 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, ©_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, ®ion);
|
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, ©_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, ®ion);
|
cmd.endRecord();
|
||||||
|
cmd.submitIdle();
|
||||||
|
}
|
||||||
|
|
||||||
VkImageMemoryBarrier use_barrier{};
|
void Image::transitionLayout(VkImageLayout new_layout, CmdBuffer* cmd)
|
||||||
use_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
{
|
||||||
use_barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
if(new_layout == _layout)
|
||||||
use_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
return;
|
||||||
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();
|
bool singleTime = (cmd == nullptr);
|
||||||
_transfer_cmd.submitIdle();
|
if(singleTime)
|
||||||
|
{
|
||||||
|
cmd = &Render_Core::get().getSingleTimeCmdBuffer();
|
||||||
|
cmd->beginRecord();
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd->transitionImageLayout(*this, new_layout);
|
||||||
|
|
||||||
|
if(singleTime)
|
||||||
|
{
|
||||||
|
cmd->endRecord();
|
||||||
|
cmd->submitIdle();
|
||||||
|
}
|
||||||
|
_layout = new_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::destroySampler() noexcept
|
||||||
|
{
|
||||||
|
if(_sampler != VK_NULL_HANDLE)
|
||||||
|
vkDestroySampler(Render_Core::get().getDevice().get(), _sampler, nullptr);
|
||||||
|
_sampler = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::destroyImageView() noexcept
|
||||||
|
{
|
||||||
|
if(_image_view != VK_NULL_HANDLE)
|
||||||
|
vkDestroyImageView(Render_Core::get().getDevice().get(), _image_view, nullptr);
|
||||||
|
_image_view = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::destroy() noexcept
|
void Image::destroy() noexcept
|
||||||
{
|
{
|
||||||
if(_sampler != VK_NULL_HANDLE)
|
destroySampler();
|
||||||
vkDestroySampler(Render_Core::get().getDevice().get(), _sampler, nullptr);
|
destroyImageView();
|
||||||
if(_image_view != VK_NULL_HANDLE)
|
|
||||||
vkDestroyImageView(Render_Core::get().getDevice().get(), _image_view, nullptr);
|
|
||||||
|
|
||||||
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;
|
||||||
if(_transfer_cmd.isInit())
|
|
||||||
_transfer_cmd.destroy();
|
|
||||||
_pool.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t formatSize(VkFormat format)
|
std::uint32_t formatSize(VkFormat format)
|
||||||
{
|
{
|
||||||
switch(format)
|
switch(format)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,57 +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/14 03:15:18 by maldavid ### ########.fr */
|
/* Updated: 2024/01/19 06:10:15 by maldavid ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
#ifndef __VK_IMAGE__
|
#ifndef __MLX_VK_IMAGE__
|
||||||
#define __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;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Image() = default;
|
Image() = default;
|
||||||
|
|
||||||
void create(uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, const char* name, bool decated_memory = false);
|
inline void create(VkImage image, VkFormat format, std::uint32_t width, std::uint32_t height, VkImageLayout layout = VK_IMAGE_LAYOUT_UNDEFINED) noexcept
|
||||||
|
{
|
||||||
|
_image = image;
|
||||||
|
_format = format;
|
||||||
|
_width = width;
|
||||||
|
_height = height;
|
||||||
|
_layout = layout;
|
||||||
|
}
|
||||||
|
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, 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:
|
||||||
CmdBuffer _transfer_cmd;
|
void destroySampler() noexcept;
|
||||||
CmdPool _pool;
|
void destroyImageView() noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
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;
|
||||||
uint32_t _width = 0;
|
VkImageLayout _layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
uint32_t _height = 0;
|
std::uint32_t _width = 0;
|
||||||
|
std::uint32_t _height = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||