Compare commits
1 commit
main
...
feat/test_
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ce413a1d7 |
161 changed files with 2796 additions and 3833 deletions
5
.clangd
5
.clangd
|
|
@ -1,5 +0,0 @@
|
||||||
CompileFlags:
|
|
||||||
DriverMode: cl
|
|
||||||
Add:
|
|
||||||
- /EHsc
|
|
||||||
- /std:c++latest
|
|
||||||
286
.drone.yml
286
.drone.yml
|
|
@ -1,42 +1,42 @@
|
||||||
---
|
# ---
|
||||||
kind: pipeline
|
# kind: pipeline
|
||||||
type: exec
|
# type: exec
|
||||||
name: amd64 — msvc
|
# name: amd64 — msvc
|
||||||
trigger:
|
# trigger:
|
||||||
branch:
|
# branch:
|
||||||
- main
|
# - main
|
||||||
platform:
|
# platform:
|
||||||
os: windows
|
# os: windows
|
||||||
arch: amd64
|
# arch: amd64
|
||||||
|
#
|
||||||
steps:
|
# steps:
|
||||||
- name: unit tests
|
# - name: unit tests
|
||||||
shell: powershell
|
# shell: powershell
|
||||||
commands:
|
# commands:
|
||||||
- ./tools/ci/amd64/msvc/unit_tests.ps1
|
# - ./tools/ci/amd64/msvc/unit_tests.ps1
|
||||||
|
#
|
||||||
---
|
# ---
|
||||||
kind: pipeline
|
# kind: pipeline
|
||||||
type: docker
|
# type: docker
|
||||||
name: amd64 — gcc
|
# name: amd64 — gcc
|
||||||
trigger:
|
# trigger:
|
||||||
branch:
|
# branch:
|
||||||
- main
|
# - main
|
||||||
|
#
|
||||||
steps:
|
# steps:
|
||||||
- name: unit tests
|
# - name: unit tests
|
||||||
image: ci:latest
|
# image: ci:latest
|
||||||
pull: if-not-exists
|
# pull: if-not-exists
|
||||||
commands:
|
# commands:
|
||||||
- ./tools/ci/amd64/gcc/unit_tests.sh
|
# - ./tools/ci/amd64/gcc/unit_tests.sh
|
||||||
|
#
|
||||||
- name: valgrind
|
# - name: valgrind
|
||||||
image: ci:latest
|
# image: ci:latest
|
||||||
pull: if-not-exists
|
# pull: if-not-exists
|
||||||
commands:
|
# commands:
|
||||||
- ./tools/ci/amd64/gcc/valgrind.sh
|
# - ./tools/ci/amd64/gcc/valgrind.sh
|
||||||
|
#
|
||||||
---
|
# ---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
type: docker
|
type: docker
|
||||||
name: amd64 — clang
|
name: amd64 — clang
|
||||||
|
|
@ -45,110 +45,114 @@ trigger:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: code coverage
|
# - name: code coverage
|
||||||
image: ci:latest
|
# image: ci:latest
|
||||||
pull: if-not-exists
|
# pull: if-not-exists
|
||||||
environment:
|
# environment:
|
||||||
CODECOV_TOKEN:
|
# CODECOV_TOKEN:
|
||||||
from_secret: CODECOV_TOKEN
|
# from_secret: CODECOV_TOKEN
|
||||||
commands:
|
# commands:
|
||||||
- ./tools/ci/amd64/clang/coverage.sh
|
# - ./tools/ci/amd64/clang/coverage.sh
|
||||||
|
#
|
||||||
- name: leak sanitizer
|
# - name: leak sanitizer
|
||||||
image: ci:latest
|
# image: ci:latest
|
||||||
pull: if-not-exists
|
# pull: if-not-exists
|
||||||
commands:
|
# commands:
|
||||||
- ./tools/ci/amd64/clang/lsan.sh
|
# - ./tools/ci/amd64/clang/lsan.sh
|
||||||
|
#
|
||||||
- name: memory sanitizer
|
- name: memory sanitizer
|
||||||
image: ci:latest
|
image: ci:latest
|
||||||
pull: if-not-exists
|
pull: if-not-exists
|
||||||
commands:
|
commands:
|
||||||
- ./tools/ci/amd64/clang/msan.sh
|
- ./tools/ci/amd64/clang/msan.sh
|
||||||
|
#
|
||||||
---
|
# ---
|
||||||
kind: pipeline
|
# kind: pipeline
|
||||||
type: docker
|
# type: docker
|
||||||
name: static analysis
|
# name: static analysis
|
||||||
trigger:
|
# trigger:
|
||||||
branch:
|
# branch:
|
||||||
- main
|
# - main
|
||||||
|
#
|
||||||
steps:
|
# steps:
|
||||||
- name: clang tidy
|
# - name: clang tidy
|
||||||
image: ci:latest
|
# image: ci:latest
|
||||||
pull: if-not-exists
|
# pull: if-not-exists
|
||||||
privileged: true
|
# privileged: true
|
||||||
commands:
|
# commands:
|
||||||
- ./tools/ci/static_analysis/clang_tidy.sh
|
# - ./tools/ci/static_analysis/clang_tidy.sh
|
||||||
|
#
|
||||||
- name: shell check
|
# - name: shell check
|
||||||
image: ci:latest
|
# image: ci:latest
|
||||||
pull: if-not-exists
|
# pull: if-not-exists
|
||||||
commands:
|
# commands:
|
||||||
- ./tools/ci/static_analysis/shell_check.sh
|
# - ./tools/ci/static_analysis/shell_check.sh
|
||||||
|
#
|
||||||
- name: clang format
|
# - name: clang format
|
||||||
image: ci:latest
|
# image: ci:latest
|
||||||
pull: if-not-exists
|
# pull: if-not-exists
|
||||||
commands:
|
# commands:
|
||||||
- ./tools/ci/static_analysis/clang_format.sh
|
# - ./tools/ci/static_analysis/clang_format.sh
|
||||||
|
#
|
||||||
- name: cmake format
|
# - name: cmake format
|
||||||
image: ci:latest
|
# image: ci:latest
|
||||||
pull: if-not-exists
|
# pull: if-not-exists
|
||||||
commands:
|
# commands:
|
||||||
- ./tools/ci/static_analysis/cmake_format.sh
|
# - ./tools/ci/static_analysis/cmake_format.sh
|
||||||
|
#
|
||||||
- name: shell format
|
# - name: shell format
|
||||||
image: ci:latest
|
# image: ci:latest
|
||||||
pull: if-not-exists
|
# pull: if-not-exists
|
||||||
commands:
|
# commands:
|
||||||
- ./tools/ci/static_analysis/shell_format.sh
|
# - ./tools/ci/static_analysis/shell_format.sh
|
||||||
|
#
|
||||||
---
|
# ---
|
||||||
kind: pipeline
|
# kind: pipeline
|
||||||
type: docker
|
# type: docker
|
||||||
name: documentation — development
|
# name: documentation — development
|
||||||
node:
|
# node:
|
||||||
environment: ryali
|
# environment: ryali
|
||||||
trigger:
|
# trigger:
|
||||||
branch:
|
# branch:
|
||||||
- main
|
# - main
|
||||||
|
#
|
||||||
steps:
|
# steps:
|
||||||
- name: build and deploy
|
# - name: build and deploy
|
||||||
image: documentation:latest
|
# image: documentation:latest
|
||||||
pull: if-not-exists
|
# pull: if-not-exists
|
||||||
commands:
|
# commands:
|
||||||
- cd docs
|
# - pwd
|
||||||
- sphinx-build -M html . .
|
# - cd docs
|
||||||
|
# - mkdir generated
|
||||||
- rm -rf /light_docs_dev/*
|
# - touch generated/changelogs.rst
|
||||||
- mv ./html/* /light_docs_dev/
|
# - touch generated/api.rst
|
||||||
|
# - sphinx-build -M html . .
|
||||||
---
|
#
|
||||||
|
# - rm -rf /light_docs_dev/*
|
||||||
kind: pipeline
|
# - mv ./html/* /light_docs_dev/
|
||||||
type: docker
|
#
|
||||||
name: documentation — production
|
# ---
|
||||||
node:
|
#
|
||||||
environment: ryali
|
# kind: pipeline
|
||||||
trigger:
|
# type: docker
|
||||||
event:
|
# name: documentation — production
|
||||||
- tag
|
# node:
|
||||||
|
# environment: ryali
|
||||||
steps:
|
# trigger:
|
||||||
- name: build and deploy
|
# event:
|
||||||
image: documentation:latest
|
# - tag
|
||||||
pull: if-not-exists
|
#
|
||||||
commands:
|
# steps:
|
||||||
- cd docs
|
# - name: build and deploy
|
||||||
- mkdir generated
|
# image: documentation:latest
|
||||||
- touch generated/changelogs.rst
|
# pull: if-not-exists
|
||||||
- touch generated/api.rst
|
# commands:
|
||||||
- sphinx-build -M html . .
|
# - cd docs
|
||||||
|
# - mkdir generated
|
||||||
- rm -rf /light_docs/*
|
# - touch generated/changelogs.rst
|
||||||
- mv ./html/* /light_docs/
|
# - touch generated/api.rst
|
||||||
|
# - sphinx-build -M html . .
|
||||||
|
#
|
||||||
|
# - rm -rf /light_docs/*
|
||||||
|
# - mv ./html/* /light_docs/
|
||||||
|
#
|
||||||
|
|
|
||||||
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, religion, or sexual identity
|
||||||
|
and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the
|
||||||
|
overall community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or
|
||||||
|
advances of any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email
|
||||||
|
address, without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
Discord: Light7734#4652.
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series
|
||||||
|
of actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or
|
||||||
|
permanent ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within
|
||||||
|
the community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.0, available at
|
||||||
|
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||||
|
enforcement ladder](https://github.com/mozilla/diversity).
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
https://www.contributor-covenant.org/faq. Translations are available at
|
||||||
|
https://www.contributor-covenant.org/translations.
|
||||||
Binary file not shown.
|
|
@ -1,26 +1,21 @@
|
||||||
#version 450 core
|
#version 450 core
|
||||||
|
|
||||||
layout(push_constant ) uniform pc {
|
vec2 positions[3] = vec2[](
|
||||||
mat4 view_projection;
|
vec2(0.0, -0.5),
|
||||||
};
|
vec2(0.5, 0.5),
|
||||||
|
vec2(-0.5, 0.5)
|
||||||
vec3 positions[3] = vec3[](
|
|
||||||
vec3(0.0, -0.5, 0.5),
|
|
||||||
vec3(0.5, 0.5, 0.5),
|
|
||||||
vec3(-0.5, 0.5, 0.5)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
vec3 colors[3] = vec3[](
|
vec3 colors[3] = vec3[](
|
||||||
vec3(0.0, 0.0, 0.0),
|
vec3(1.0, 0.0, 0.0),
|
||||||
vec3(0.0, 0.0, 0.0),
|
vec3(0.0, 1.0, 0.0),
|
||||||
vec3(0.0, 0.0, 0.0)
|
vec3(0.0, 0.0, 1.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
layout(location = 0) out vec3 out_frag_color;
|
layout(location = 0) out vec3 out_frag_color;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = view_projection * vec4(positions[gl_VertexIndex], 1.0);
|
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
|
||||||
out_frag_color = colors[gl_VertexIndex];
|
out_frag_color = colors[gl_VertexIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
2
docs/.gitignore
vendored
2
docs/.gitignore
vendored
|
|
@ -1,5 +1,3 @@
|
||||||
_build/
|
_build/
|
||||||
generated/
|
generated/
|
||||||
html/
|
|
||||||
xml/
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
TARGET = ./
|
|
||||||
INPUT = "../modules"
|
|
||||||
RECURSIVE = YES
|
|
||||||
|
|
||||||
PROJECT_NAME = "Light"
|
|
||||||
JAVADOC_AUTOBRIEF = YES
|
|
||||||
JAVADOC_BANNER = YES
|
|
||||||
GENERATE_XML = YES
|
|
||||||
|
|
||||||
EXTRACT_PRIVATE = NO
|
|
||||||
EXTRACT_STATIC = NO
|
|
||||||
EXTRACT_LOCAL_CLASSES = NO
|
|
||||||
HIDE_UNDOC_RELATIONS = YES
|
|
||||||
HAVE_DOT = NO
|
|
||||||
|
|
||||||
GENERATE_TODOLIST = NO
|
|
||||||
GENERATE_HTML = NO
|
|
||||||
GENERATE_DOCSET = NO
|
|
||||||
GENERATE_HTMLHELP = NO
|
|
||||||
GENERATE_CHI = NO
|
|
||||||
GENERATE_QHP = NO
|
|
||||||
GENERATE_ECLIPSEHELP = NO
|
|
||||||
GENERATE_TREEVIEW = NO
|
|
||||||
GENERATE_LATEX = NO
|
|
||||||
GENERATE_RTF = NO
|
|
||||||
GENERATE_MAN = NO
|
|
||||||
GENERATE_DOCBOOK = NO
|
|
||||||
GENERATE_AUTOGEN_DEF = NO
|
|
||||||
GENERATE_SQLITE3 = NO
|
|
||||||
GENERATE_PERLMOD = NO
|
|
||||||
GENERATE_TAGFILE = NO
|
|
||||||
GENERATE_LEGEND = NO
|
|
||||||
GENERATE_TESTLIST = NO
|
|
||||||
GENERATE_BUGLIST = NO
|
|
||||||
GENERATE_DEPRECATEDLIST= NO
|
|
||||||
|
|
||||||
FILE_PATTERNS = *.c \
|
|
||||||
*.cc \
|
|
||||||
*.cxx \
|
|
||||||
*.cxxm \
|
|
||||||
*.cpp \
|
|
||||||
*.cppm \
|
|
||||||
*.ccm \
|
|
||||||
*.c++ \
|
|
||||||
*.c++m \
|
|
||||||
*.java \
|
|
||||||
*.ii \
|
|
||||||
*.ixx \
|
|
||||||
*.ipp \
|
|
||||||
*.i++ \
|
|
||||||
*.inl \
|
|
||||||
*.idl \
|
|
||||||
*.ddl \
|
|
||||||
*.odl \
|
|
||||||
*.h \
|
|
||||||
*.hh \
|
|
||||||
*.hxx \
|
|
||||||
*.hpp \
|
|
||||||
*.h++ \
|
|
||||||
*.l \
|
|
||||||
*.cs \
|
|
||||||
*.d \
|
|
||||||
*.php \
|
|
||||||
*.php4 \
|
|
||||||
*.php5 \
|
|
||||||
*.phtml \
|
|
||||||
*.inc \
|
|
||||||
*.m \
|
|
||||||
*.markdown \
|
|
||||||
*.md \
|
|
||||||
*.mm \
|
|
||||||
*.dox \
|
|
||||||
*.py \
|
|
||||||
*.pyw \
|
|
||||||
*.f90 \
|
|
||||||
*.f95 \
|
|
||||||
*.f03 \
|
|
||||||
*.f08 \
|
|
||||||
*.f18 \
|
|
||||||
*.f \
|
|
||||||
*.for \
|
|
||||||
*.vhd \
|
|
||||||
*.vhdl \
|
|
||||||
*.ucf \
|
|
||||||
*.qsf \
|
|
||||||
*.ice
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
Application
|
|
||||||
===================================================================================================
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 3
|
|
||||||
:caption: App
|
|
||||||
|
|
||||||
Functions
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
.. doxygenfunction:: main
|
|
||||||
|
|
||||||
Classes
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
.. doxygenclass:: lt::app::ISystem
|
|
||||||
|
|
||||||
.. doxygenstruct:: lt::app::TickInfo
|
|
||||||
|
|
||||||
.. doxygenstruct:: lt::app::TickResult
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
Renderer
|
|
||||||
===================================================================================================
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 3
|
|
||||||
:caption: App
|
|
||||||
|
|
||||||
Classes
|
|
||||||
---------------------------------------------------------------------------------------------------
|
|
||||||
.. doxygenenum:: lt::renderer::Api
|
|
||||||
|
|
||||||
.. doxygenclass:: lt::renderer::System
|
|
||||||
|
|
||||||
.. doxygenstruct:: lt::renderer::components::Sprite
|
|
||||||
14
docs/conf.py
14
docs/conf.py
|
|
@ -13,21 +13,13 @@ author = 'light7734'
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||||
|
|
||||||
extensions = ['breathe']
|
extensions = []
|
||||||
|
|
||||||
breathe_projects = {"Light": "./xml"}
|
|
||||||
breathe_default_project = "Light"
|
|
||||||
breathe_default_members = ()
|
|
||||||
|
|
||||||
# Tell sphinx what the primary language being documented is.
|
|
||||||
primary_domain = 'cpp'
|
|
||||||
|
|
||||||
# Tell sphinx what the pygments highlight language should be.
|
|
||||||
highlight_language = 'cpp'
|
|
||||||
|
|
||||||
templates_path = ['_templates']
|
templates_path = ['_templates']
|
||||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output -------------------------------------------------
|
# -- Options for HTML output -------------------------------------------------
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
|
||||||
|
|
||||||
|
|
|
||||||
68
docs/generate_changelog.py
Normal file
68
docs/generate_changelog.py
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
from git import Repo
|
||||||
|
import re
|
||||||
|
|
||||||
|
repo = Repo(search_parent_directories=True)
|
||||||
|
assert not repo.bare
|
||||||
|
|
||||||
|
file_path = "generated/changelog.rst"
|
||||||
|
|
||||||
|
messages = []
|
||||||
|
short_shas = []
|
||||||
|
hex_shas = []
|
||||||
|
logs = []
|
||||||
|
|
||||||
|
remote_url = "https://git.light7734.com/light7734/light/commit"
|
||||||
|
def format_log(commit_type, message, major, minor, patch, short_sha, hex_sha):
|
||||||
|
href = f"{remote_url}/{hex_sha}"
|
||||||
|
version = f"{major}.{minor}.{patch}-kitten+{short_sha}";
|
||||||
|
link = f"`{version} <{remote_url}/{hex_sha}>`__"
|
||||||
|
return f"| **{message}** ({link})"
|
||||||
|
|
||||||
|
for commit in repo.iter_commits():
|
||||||
|
messages.append(commit.summary)
|
||||||
|
short_shas.append(repo.git.rev_parse(commit.hexsha, short=5))
|
||||||
|
hex_shas.append(commit.hexsha)
|
||||||
|
|
||||||
|
ver_major = 0
|
||||||
|
ver_minor = 0
|
||||||
|
ver_patch = 0
|
||||||
|
|
||||||
|
idx = len(messages)
|
||||||
|
for message in reversed(messages):
|
||||||
|
idx = idx - 1;
|
||||||
|
|
||||||
|
commit_type = re.match("^(feat|fix|refactor|perf|build|asset|test|chore|ci|docs)", message)
|
||||||
|
if not commit_type:
|
||||||
|
continue
|
||||||
|
|
||||||
|
match commit_type.group(0):
|
||||||
|
case "feat":
|
||||||
|
ver_minor = ver_minor + 1
|
||||||
|
ver_patch = 0
|
||||||
|
|
||||||
|
case "fix":
|
||||||
|
ver_patch = ver_patch + 1
|
||||||
|
|
||||||
|
case "refactor":
|
||||||
|
ver_patch = ver_patch + 1
|
||||||
|
|
||||||
|
case "perf":
|
||||||
|
ver_patch = ver_patch + 1
|
||||||
|
|
||||||
|
case "build":
|
||||||
|
ver_patch = ver_patch + 1
|
||||||
|
|
||||||
|
case "asset":
|
||||||
|
ver_patch = ver_patch + 1
|
||||||
|
|
||||||
|
logs.append(format_log(commit_type, message, ver_major, ver_minor, ver_patch, short_shas[idx], hex_shas[idx]))
|
||||||
|
|
||||||
|
with open(file_path, "w") as f:
|
||||||
|
f.write(".. changelogs\n\n\n")
|
||||||
|
f.write("Changelogs\n")
|
||||||
|
f.write("==================================================\n\n")
|
||||||
|
|
||||||
|
f.write("KITTEN\n")
|
||||||
|
f.write("--------------------------------------------------\n\n")
|
||||||
|
for log in reversed(logs):
|
||||||
|
f.write(log + '\n')
|
||||||
|
|
@ -23,10 +23,10 @@
|
||||||
guidelines/conventions.rst
|
guidelines/conventions.rst
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 3
|
:maxdepth: 2
|
||||||
:caption: API
|
:caption: Generated Docs
|
||||||
|
|
||||||
api/app.rst
|
generated/api.rst
|
||||||
api/renderer.rst
|
generated/changelog.rst
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
|
if "%SPHINXBUILD%" == "" (
|
||||||
|
set SPHINXBUILD=sphinx-build
|
||||||
|
)
|
||||||
|
set SOURCEDIR=.
|
||||||
|
set BUILDDIR=_build
|
||||||
|
|
||||||
|
%SPHINXBUILD% >NUL 2>NUL
|
||||||
|
if errorlevel 9009 (
|
||||||
|
echo.
|
||||||
|
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||||
|
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||||
|
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||||
|
echo.may add the Sphinx directory to PATH.
|
||||||
|
echo.
|
||||||
|
echo.If you don't have Sphinx installed, grab it from
|
||||||
|
echo.https://www.sphinx-doc.org/
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1" == "" goto help
|
||||||
|
|
||||||
|
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:help
|
||||||
|
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
|
||||||
|
:end
|
||||||
|
popd
|
||||||
|
|
@ -1,37 +1,26 @@
|
||||||
# engine add_subdirectory(./std)
|
# engine
|
||||||
|
add_subdirectory(./std)
|
||||||
add_subdirectory(test)
|
|
||||||
|
|
||||||
add_subdirectory(./logger)
|
|
||||||
|
|
||||||
add_subdirectory(./bitwise)
|
add_subdirectory(./bitwise)
|
||||||
|
|
||||||
add_subdirectory(./env)
|
add_subdirectory(./env)
|
||||||
|
|
||||||
add_subdirectory(./memory)
|
add_subdirectory(./memory)
|
||||||
|
|
||||||
add_subdirectory(./time)
|
add_subdirectory(./time)
|
||||||
|
add_subdirectory(./logger)
|
||||||
add_subdirectory(./debug)
|
add_subdirectory(./debug)
|
||||||
|
|
||||||
add_subdirectory(./math)
|
add_subdirectory(./math)
|
||||||
|
|
||||||
add_subdirectory(./assets)
|
|
||||||
|
|
||||||
add_subdirectory(./asset_baker)
|
|
||||||
|
|
||||||
add_subdirectory(./camera)
|
|
||||||
|
|
||||||
add_subdirectory(./app)
|
|
||||||
add_subdirectory(./ecs)
|
|
||||||
|
|
||||||
add_subdirectory(./surface)
|
|
||||||
|
|
||||||
add_subdirectory(./input)
|
|
||||||
|
|
||||||
# add_subdirectory(./ui)
|
|
||||||
|
|
||||||
# add_subdirectory(./renderer)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# add_subdirectory(./mirror)
|
add_subdirectory(./asset_baker)
|
||||||
|
add_subdirectory(./assets)
|
||||||
|
#
|
||||||
|
add_subdirectory(./camera)
|
||||||
|
add_subdirectory(./input)
|
||||||
|
# add_subdirectory(./ui)
|
||||||
|
#
|
||||||
|
add_subdirectory(./surface)
|
||||||
|
add_subdirectory(./renderer)
|
||||||
|
add_subdirectory(./ecs)
|
||||||
|
#
|
||||||
|
add_subdirectory(./app)
|
||||||
|
|
||||||
|
# apps
|
||||||
|
add_subdirectory(./mirror)
|
||||||
|
add_subdirectory(test)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,4 @@
|
||||||
add_library_module(
|
add_library_module(app application.cpp)
|
||||||
NAME
|
|
||||||
app
|
|
||||||
INTERFACES
|
|
||||||
application.cppm
|
|
||||||
system.cppm
|
|
||||||
SOURCES
|
|
||||||
entrypoint.cpp)
|
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
app
|
app
|
||||||
PUBLIC memory
|
PUBLIC memory
|
||||||
|
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
export module app;
|
|
||||||
import app.system;
|
|
||||||
import memory.reference;
|
|
||||||
import memory.scope;
|
|
||||||
import std;
|
|
||||||
|
|
||||||
namespace lt::app {
|
|
||||||
|
|
||||||
/** The main application class.
|
|
||||||
* Think of this like an aggregate of systems, you register systems through this interface.
|
|
||||||
* Then they'll tick every "application frame".
|
|
||||||
*/
|
|
||||||
export class Application
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Application(const Application &) = delete;
|
|
||||||
|
|
||||||
Application(Application &&) = delete;
|
|
||||||
|
|
||||||
auto operator=(const Application &) -> Application & = delete;
|
|
||||||
|
|
||||||
auto operator=(Application &&) -> Application & = delete;
|
|
||||||
|
|
||||||
virtual ~Application() = default;
|
|
||||||
|
|
||||||
void game_loop();
|
|
||||||
|
|
||||||
void register_system(memory::Ref<app::ISystem> system);
|
|
||||||
|
|
||||||
void unregister_system(memory::Ref<app::ISystem> system);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Application() = default;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<memory::Ref<app::ISystem>> m_systems;
|
|
||||||
|
|
||||||
std::vector<memory::Ref<app::ISystem>> m_systems_to_be_unregistered;
|
|
||||||
|
|
||||||
std::vector<memory::Ref<app::ISystem>> m_systems_to_be_registered;
|
|
||||||
};
|
|
||||||
|
|
||||||
export extern memory::Scope<class Application> create_application();
|
|
||||||
|
|
||||||
} // namespace lt::app
|
|
||||||
|
|
||||||
module :private;
|
|
||||||
namespace lt::app {
|
|
||||||
|
|
||||||
void Application::game_loop()
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
for (auto &system : m_systems)
|
|
||||||
{
|
|
||||||
const auto &last_tick = system->get_last_tick_result();
|
|
||||||
const auto now = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
system->tick(
|
|
||||||
TickInfo {
|
|
||||||
.delta_time = now - last_tick.end_time,
|
|
||||||
.budget = std::chrono::milliseconds { 10 },
|
|
||||||
.start_time = now,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &system : m_systems_to_be_registered)
|
|
||||||
{
|
|
||||||
m_systems.emplace_back(system)->on_register();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &system : m_systems_to_be_unregistered)
|
|
||||||
{
|
|
||||||
m_systems.erase(
|
|
||||||
std::remove(m_systems.begin(), m_systems.end(), system),
|
|
||||||
m_systems.end()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_systems.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::register_system(memory::Ref<app::ISystem> system)
|
|
||||||
{
|
|
||||||
m_systems.emplace_back(std::move(system));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Application::unregister_system(memory::Ref<app::ISystem> system)
|
|
||||||
{
|
|
||||||
m_systems_to_be_unregistered.emplace_back(std::move(system));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace lt::app
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
import memory.scope;
|
|
||||||
import logger;
|
|
||||||
import app;
|
|
||||||
import std;
|
|
||||||
|
|
||||||
/** The ultimate entrypoint. */
|
|
||||||
auto main(int argc, char *argv[]) -> std::int32_t
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::ignore = argc;
|
|
||||||
std::ignore = argv;
|
|
||||||
|
|
||||||
auto application = lt::memory::Scope<lt::app::Application> {};
|
|
||||||
application = lt::app::create_application();
|
|
||||||
if (!application)
|
|
||||||
{
|
|
||||||
throw std::runtime_error { "Failed to create application\n" };
|
|
||||||
}
|
|
||||||
|
|
||||||
application->game_loop();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
catch (const std::exception &exp)
|
|
||||||
{
|
|
||||||
lt::log::critical("Terminating due to uncaught exception:");
|
|
||||||
lt::log::critical("\texception.what(): {}", exp.what());
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
55
modules/app/private/application.cpp
Normal file
55
modules/app/private/application.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include <app/application.hpp>
|
||||||
|
#include <app/system.hpp>
|
||||||
|
#include <memory/reference.hpp>
|
||||||
|
|
||||||
|
namespace lt::app {
|
||||||
|
|
||||||
|
void Application::game_loop()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
for (auto &system : m_systems)
|
||||||
|
{
|
||||||
|
const auto &last_tick = system->get_last_tick_result();
|
||||||
|
const auto now = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
system->tick(
|
||||||
|
TickInfo {
|
||||||
|
.delta_time = now - last_tick.end_time,
|
||||||
|
.budget = std::chrono::milliseconds { 10 },
|
||||||
|
.start_time = now,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &system : m_systems_to_be_registered)
|
||||||
|
{
|
||||||
|
m_systems.emplace_back(system)->on_register();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &system : m_systems_to_be_unregistered)
|
||||||
|
{
|
||||||
|
m_systems.erase(
|
||||||
|
std::remove(m_systems.begin(), m_systems.end(), system),
|
||||||
|
m_systems.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_systems.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::register_system(memory::Ref<app::ISystem> system)
|
||||||
|
{
|
||||||
|
m_systems.emplace_back(std::move(system));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::unregister_system(memory::Ref<app::ISystem> system)
|
||||||
|
{
|
||||||
|
m_systems_to_be_unregistered.emplace_back(std::move(system));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace lt::app
|
||||||
47
modules/app/public/application.hpp
Normal file
47
modules/app/public/application.hpp
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory/reference.hpp>
|
||||||
|
#include <memory/scope.hpp>
|
||||||
|
|
||||||
|
namespace lt::app {
|
||||||
|
|
||||||
|
class ISystem;
|
||||||
|
|
||||||
|
extern memory::Scope<class Application> create_application();
|
||||||
|
|
||||||
|
/** The main application class.
|
||||||
|
* Think of this like an aggregate of systems, you register systems through this interface.
|
||||||
|
* Then they'll tick every "application frame".
|
||||||
|
*/
|
||||||
|
class Application
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Application(const Application &) = delete;
|
||||||
|
|
||||||
|
Application(Application &&) = delete;
|
||||||
|
|
||||||
|
auto operator=(const Application &) -> Application & = delete;
|
||||||
|
|
||||||
|
auto operator=(Application &&) -> Application & = delete;
|
||||||
|
|
||||||
|
virtual ~Application() = default;
|
||||||
|
|
||||||
|
void game_loop();
|
||||||
|
|
||||||
|
void register_system(memory::Ref<app::ISystem> system);
|
||||||
|
|
||||||
|
void unregister_system(memory::Ref<app::ISystem> system);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Application() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<memory::Ref<app::ISystem>> m_systems;
|
||||||
|
|
||||||
|
std::vector<memory::Ref<app::ISystem>> m_systems_to_be_unregistered;
|
||||||
|
|
||||||
|
std::vector<memory::Ref<app::ISystem>> m_systems_to_be_registered;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace lt::app
|
||||||
27
modules/app/public/entrypoint.hpp
Normal file
27
modules/app/public/entrypoint.hpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <app/application.hpp>
|
||||||
|
#include <memory/scope.hpp>
|
||||||
|
|
||||||
|
auto main(int argc, char *argv[]) -> int32_t
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::ignore = argc;
|
||||||
|
std::ignore = argv;
|
||||||
|
|
||||||
|
auto application = lt::memory::Scope<lt::app::Application> {};
|
||||||
|
application = lt::app::create_application();
|
||||||
|
if (!application)
|
||||||
|
{
|
||||||
|
throw std::runtime_error { "Failed to create application\n" };
|
||||||
|
}
|
||||||
|
|
||||||
|
application->game_loop();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
catch (const std::exception &exp)
|
||||||
|
{
|
||||||
|
log_crt("Terminating due to uncaught exception:");
|
||||||
|
log_crt("\texception.what(): {}", exp.what());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
export module app.system;
|
#pragma once
|
||||||
import logger;
|
|
||||||
import std;
|
#include <chrono>
|
||||||
|
|
||||||
namespace lt::app {
|
namespace lt::app {
|
||||||
|
|
||||||
/** Information required to tick a system.
|
/** Information required to tick a system.
|
||||||
* @note May be used across an entire application-frame (consisting of multiple systems ticking)
|
* @note May be used across an entire application-frame (consisting of multiple systems ticking)
|
||||||
*/
|
*/
|
||||||
export struct TickInfo
|
struct TickInfo
|
||||||
{
|
{
|
||||||
using Timepoint_T = std::chrono::time_point<std::chrono::steady_clock>;
|
using Timepoint_T = std::chrono::time_point<std::chrono::steady_clock>;
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ export struct TickInfo
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Information about how a system's tick performed */
|
/** Information about how a system's tick performed */
|
||||||
export struct TickResult
|
struct TickResult
|
||||||
{
|
{
|
||||||
using Timepoint_T = std::chrono::time_point<std::chrono::steady_clock>;
|
using Timepoint_T = std::chrono::time_point<std::chrono::steady_clock>;
|
||||||
|
|
||||||
|
|
@ -46,9 +46,10 @@ export struct TickResult
|
||||||
Timepoint_T end_time;
|
Timepoint_T end_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
export struct SystemDiagnosis
|
|
||||||
|
struct SystemDiagnosis
|
||||||
{
|
{
|
||||||
enum class Severity : std::uint8_t
|
enum class Severity : uint8_t
|
||||||
{
|
{
|
||||||
verbose,
|
verbose,
|
||||||
info,
|
info,
|
||||||
|
|
@ -64,14 +65,14 @@ export struct SystemDiagnosis
|
||||||
Severity severity;
|
Severity severity;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class SystemStats
|
class SystemStats
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void push_diagnosis(SystemDiagnosis &&diagnosis)
|
void push_diagnosis(SystemDiagnosis &&diagnosis)
|
||||||
{
|
{
|
||||||
auto diag = m_diagnosis.emplace_back(std::move(diagnosis));
|
auto diag = m_diagnosis.emplace_back(std::move(diagnosis));
|
||||||
|
|
||||||
log::debug("message: {}", diag.message);
|
log_dbg("message: {}", diag.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto empty_diagnosis() const -> bool
|
[[nodiscard]] auto empty_diagnosis() const -> bool
|
||||||
|
|
@ -83,7 +84,7 @@ private:
|
||||||
std::vector<SystemDiagnosis> m_diagnosis;
|
std::vector<SystemDiagnosis> m_diagnosis;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ISystem
|
class ISystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ISystem() = default;
|
ISystem() = default;
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
add_library_module(NAME libasset_baker INTERFACES bakers.cppm)
|
add_library_module(libasset_baker bakers.cpp)
|
||||||
target_link_libraries(libasset_baker PUBLIC assets logger lt_debug)
|
target_link_libraries(libasset_baker PUBLIC assets logger lt_debug tbb)
|
||||||
|
add_test_module(libasset_baker bakers.test.cpp)
|
||||||
|
|
||||||
add_executable(asset_baker entrypoint.cpp)
|
add_executable_module(asset_baker entrypoint/baker.cpp)
|
||||||
target_link_libraries(asset_baker PRIVATE libasset_baker)
|
target_link_libraries(asset_baker PRIVATE libasset_baker)
|
||||||
|
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
export module bakers;
|
|
||||||
|
|
||||||
import debug.assertions;
|
|
||||||
import assets.metadata;
|
|
||||||
import assets.shader;
|
|
||||||
import logger;
|
|
||||||
import std;
|
|
||||||
|
|
||||||
export void bake_shader(
|
|
||||||
const std::filesystem::path &in_path,
|
|
||||||
const std::filesystem::path &out_path,
|
|
||||||
lt::assets::ShaderAsset::Type type
|
|
||||||
)
|
|
||||||
{
|
|
||||||
using lt::assets::ShaderAsset;
|
|
||||||
using enum lt::assets::ShaderAsset::Type;
|
|
||||||
|
|
||||||
auto glsl_path = in_path.string();
|
|
||||||
auto spv_path = std::format("{}.spv", glsl_path);
|
|
||||||
lt::log::trace(
|
|
||||||
"Compiling {} shader {} -> {}",
|
|
||||||
type == vertex ? "vertex" : "fragment",
|
|
||||||
glsl_path,
|
|
||||||
spv_path
|
|
||||||
);
|
|
||||||
|
|
||||||
// Don't bother linking to shaderc, just invoke the command with a system call.
|
|
||||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
|
||||||
std::system(
|
|
||||||
std::format(
|
|
||||||
"glslc --target-env=vulkan1.4 -std=450core -fshader-stage={} {} -o {}",
|
|
||||||
type == vertex ? "vert" : "frag",
|
|
||||||
glsl_path,
|
|
||||||
spv_path
|
|
||||||
)
|
|
||||||
.c_str()
|
|
||||||
);
|
|
||||||
|
|
||||||
auto stream = std::ifstream(spv_path, std::ios::binary);
|
|
||||||
lt::debug::ensure(
|
|
||||||
stream.is_open(),
|
|
||||||
"Failed to open compiled {} shader at: {}",
|
|
||||||
type == vertex ? "vert" : "frag",
|
|
||||||
spv_path
|
|
||||||
);
|
|
||||||
|
|
||||||
stream.seekg(0, std::ios::end);
|
|
||||||
const auto size = stream.tellg();
|
|
||||||
|
|
||||||
auto bytes = std::vector<std::byte>(size);
|
|
||||||
stream.seekg(0, std::ios::beg);
|
|
||||||
stream.read((char *)bytes.data(), size); // NOLINT
|
|
||||||
lt::log::debug("BYTES: {}", bytes.size());
|
|
||||||
stream.close();
|
|
||||||
std::filesystem::remove(spv_path);
|
|
||||||
|
|
||||||
ShaderAsset::pack(
|
|
||||||
out_path,
|
|
||||||
lt::assets::AssetMetadata {
|
|
||||||
.version = lt::assets::current_version,
|
|
||||||
.type = ShaderAsset::asset_type_identifier,
|
|
||||||
},
|
|
||||||
ShaderAsset::Metadata {
|
|
||||||
.type = type,
|
|
||||||
},
|
|
||||||
std::move(bytes)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
2
modules/asset_baker/private/bakers.test.cpp
Normal file
2
modules/asset_baker/private/bakers.test.cpp
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include <asset_baker/bakers.hpp>
|
||||||
|
#include <test/test.hpp>
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
import assets.shader;
|
#include <asset_baker/bakers.hpp>
|
||||||
import logger;
|
#include <assets/shader.hpp>
|
||||||
import bakers;
|
|
||||||
import std;
|
|
||||||
|
|
||||||
|
auto main(int argc, char *argv[]) -> int32_t
|
||||||
auto main(int argc, char *argv[]) -> std::int32_t
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
|
|
@ -33,12 +30,12 @@ try
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
catch (const std::exception &exp)
|
catch (const std::exception &exp)
|
||||||
{
|
{
|
||||||
lt::log::critical("Terminating due to uncaught exception:");
|
log_crt("Terminating due to uncaught exception:");
|
||||||
lt::log::critical("\texception.what: {}:", exp.what());
|
log_crt("\texception.what: {}:", exp.what());
|
||||||
|
|
||||||
return 1;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <assets/shader.hpp>
|
||||||
|
|
||||||
inline void bake_shader(
|
inline void bake_shader(
|
||||||
const std::filesystem::path &in_path,
|
const std::filesystem::path &in_path,
|
||||||
|
|
@ -12,7 +13,7 @@ inline void bake_shader(
|
||||||
|
|
||||||
auto glsl_path = in_path.string();
|
auto glsl_path = in_path.string();
|
||||||
auto spv_path = std::format("{}.spv", glsl_path);
|
auto spv_path = std::format("{}.spv", glsl_path);
|
||||||
lt::log::trace(
|
log_trc(
|
||||||
"Compiling {} shader {} -> {}",
|
"Compiling {} shader {} -> {}",
|
||||||
type == vertex ? "vertex" : "fragment",
|
type == vertex ? "vertex" : "fragment",
|
||||||
glsl_path,
|
glsl_path,
|
||||||
|
|
@ -32,7 +33,7 @@ inline void bake_shader(
|
||||||
);
|
);
|
||||||
|
|
||||||
auto stream = std::ifstream(spv_path, std::ios::binary);
|
auto stream = std::ifstream(spv_path, std::ios::binary);
|
||||||
lt::debug::ensure(
|
lt::ensure(
|
||||||
stream.is_open(),
|
stream.is_open(),
|
||||||
"Failed to open compiled {} shader at: {}",
|
"Failed to open compiled {} shader at: {}",
|
||||||
type == vertex ? "vert" : "frag",
|
type == vertex ? "vert" : "frag",
|
||||||
|
|
@ -45,7 +46,7 @@ inline void bake_shader(
|
||||||
auto bytes = std::vector<std::byte>(size);
|
auto bytes = std::vector<std::byte>(size);
|
||||||
stream.seekg(0, std::ios::beg);
|
stream.seekg(0, std::ios::beg);
|
||||||
stream.read((char *)bytes.data(), size); // NOLINT
|
stream.read((char *)bytes.data(), size); // NOLINT
|
||||||
lt::log::debug("BYTES: {}", bytes.size());
|
log_dbg("BYTES: {}", bytes.size());
|
||||||
stream.close();
|
stream.close();
|
||||||
std::filesystem::remove(spv_path);
|
std::filesystem::remove(spv_path);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
add_library_module(NAME assets INTERFACES shader.cppm metadata.cppm)
|
add_library_module(assets shader.cpp)
|
||||||
|
|
||||||
target_link_libraries(assets PUBLIC logger lt_debug)
|
target_link_libraries(assets PUBLIC logger lt_debug)
|
||||||
|
|
||||||
add_test_module(assets shader.test.cpp)
|
add_test_module(assets shader.test.cpp)
|
||||||
|
|
|
||||||
|
|
@ -1,80 +1,4 @@
|
||||||
export module assets.shader;
|
#include <assets/shader.hpp>
|
||||||
import assets.metadata;
|
|
||||||
import debug.assertions;
|
|
||||||
|
|
||||||
import std;
|
|
||||||
|
|
||||||
export namespace lt::assets {
|
|
||||||
|
|
||||||
class ShaderAsset
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static constexpr auto asset_type_identifier = Type_T { "SHADER_________" };
|
|
||||||
|
|
||||||
enum class BlobTag : Tag_T
|
|
||||||
{
|
|
||||||
code,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Type : std::uint8_t
|
|
||||||
{
|
|
||||||
vertex,
|
|
||||||
fragment,
|
|
||||||
geometry,
|
|
||||||
compute,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Metadata
|
|
||||||
{
|
|
||||||
Type type;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void pack(
|
|
||||||
const std::filesystem::path &destination,
|
|
||||||
AssetMetadata asset_metadata,
|
|
||||||
Metadata metadata,
|
|
||||||
Blob code_blob
|
|
||||||
);
|
|
||||||
|
|
||||||
ShaderAsset(const std::filesystem::path &path);
|
|
||||||
|
|
||||||
void unpack_to(BlobTag tag, std::span<std::byte> destination) const;
|
|
||||||
|
|
||||||
[[nodiscard]] auto unpack(BlobTag tag) const -> Blob;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_asset_metadata() const -> const AssetMetadata &
|
|
||||||
{
|
|
||||||
return m_asset_metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_metadata() const -> const Metadata &
|
|
||||||
{
|
|
||||||
return m_metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_blob_metadata(BlobTag tag) const -> const BlobMetadata &
|
|
||||||
{
|
|
||||||
debug::ensure(
|
|
||||||
tag == BlobTag::code,
|
|
||||||
"Invalid blob tag for shader asset: {}",
|
|
||||||
std::to_underlying(tag)
|
|
||||||
);
|
|
||||||
|
|
||||||
return m_code_blob_metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
AssetMetadata m_asset_metadata {};
|
|
||||||
|
|
||||||
Metadata m_metadata {};
|
|
||||||
|
|
||||||
BlobMetadata m_code_blob_metadata {};
|
|
||||||
|
|
||||||
mutable std::ifstream m_stream;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lt::assets
|
|
||||||
|
|
||||||
|
|
||||||
namespace lt::assets {
|
namespace lt::assets {
|
||||||
|
|
||||||
|
|
@ -90,14 +14,14 @@ constexpr auto total_metadata_size = //
|
||||||
|
|
||||||
ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
|
ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
|
||||||
{
|
{
|
||||||
debug::ensure(m_stream.is_open(), "Failed to open shader asset at: {}", path.string());
|
ensure(m_stream.is_open(), "Failed to open shader asset at: {}", path.string());
|
||||||
const auto read = [this](auto &field) {
|
const auto read = [this](auto &field) {
|
||||||
m_stream.read(std::bit_cast<char *>(&field), sizeof(field));
|
m_stream.read(std::bit_cast<char *>(&field), sizeof(field));
|
||||||
};
|
};
|
||||||
|
|
||||||
m_stream.seekg(0, std::ifstream::end);
|
m_stream.seekg(0, std::ifstream::end);
|
||||||
const auto file_size = static_cast<std::size_t>(m_stream.tellg());
|
const auto file_size = static_cast<size_t>(m_stream.tellg());
|
||||||
debug::ensure(
|
ensure(
|
||||||
file_size > total_metadata_size,
|
file_size > total_metadata_size,
|
||||||
"Failed to open shader asset at: {}, file smaller than metadata: {} < {}",
|
"Failed to open shader asset at: {}, file smaller than metadata: {} < {}",
|
||||||
path.string(),
|
path.string(),
|
||||||
|
|
@ -115,7 +39,7 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
|
||||||
read(m_code_blob_metadata.compressed_size);
|
read(m_code_blob_metadata.compressed_size);
|
||||||
read(m_code_blob_metadata.uncompressed_size);
|
read(m_code_blob_metadata.uncompressed_size);
|
||||||
|
|
||||||
debug::ensure(
|
ensure(
|
||||||
m_asset_metadata.type == asset_type_identifier,
|
m_asset_metadata.type == asset_type_identifier,
|
||||||
"Failed to open shader asset at: {}, incorrect asset type: {} != {}",
|
"Failed to open shader asset at: {}, incorrect asset type: {} != {}",
|
||||||
path.string(),
|
path.string(),
|
||||||
|
|
@ -123,7 +47,7 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
|
||||||
asset_type_identifier
|
asset_type_identifier
|
||||||
);
|
);
|
||||||
|
|
||||||
debug::ensure(
|
ensure(
|
||||||
m_asset_metadata.version == current_version,
|
m_asset_metadata.version == current_version,
|
||||||
"Failed to open shader asset at: {}, version mismatch: {} != {}",
|
"Failed to open shader asset at: {}, version mismatch: {} != {}",
|
||||||
path.string(),
|
path.string(),
|
||||||
|
|
@ -131,21 +55,21 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
|
||||||
current_version
|
current_version
|
||||||
);
|
);
|
||||||
|
|
||||||
debug::ensure(
|
ensure(
|
||||||
std::to_underlying(m_metadata.type) <= std::to_underlying(Type::compute),
|
std::to_underlying(m_metadata.type) <= std::to_underlying(Type::compute),
|
||||||
"Failed to open shader asset at: {}, invalid shader type: {}",
|
"Failed to open shader asset at: {}, invalid shader type: {}",
|
||||||
path.string(),
|
path.string(),
|
||||||
std::to_underlying(m_metadata.type)
|
std::to_underlying(m_metadata.type)
|
||||||
);
|
);
|
||||||
|
|
||||||
debug::ensure(
|
ensure(
|
||||||
m_code_blob_metadata.tag == std::to_underlying(BlobTag::code),
|
m_code_blob_metadata.tag == std::to_underlying(BlobTag::code),
|
||||||
"Failed to open shader asset at: {}, invalid blob tag: {}",
|
"Failed to open shader asset at: {}, invalid blob tag: {}",
|
||||||
path.string(),
|
path.string(),
|
||||||
m_code_blob_metadata.tag
|
m_code_blob_metadata.tag
|
||||||
);
|
);
|
||||||
|
|
||||||
debug::ensure(
|
ensure(
|
||||||
m_code_blob_metadata.offset + m_code_blob_metadata.compressed_size <= file_size,
|
m_code_blob_metadata.offset + m_code_blob_metadata.compressed_size <= file_size,
|
||||||
"Failed to open shader asset at: {}, file smaller than blob: {} > {} + {}",
|
"Failed to open shader asset at: {}, file smaller than blob: {} > {} + {}",
|
||||||
path.string(),
|
path.string(),
|
||||||
|
|
@ -175,7 +99,7 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
|
||||||
.uncompressed_size = code_blob.size(),
|
.uncompressed_size = code_blob.size(),
|
||||||
};
|
};
|
||||||
|
|
||||||
debug::ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string());
|
ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string());
|
||||||
const auto write = [&stream](auto &field) {
|
const auto write = [&stream](auto &field) {
|
||||||
stream.write(std::bit_cast<char *>(&field), sizeof(field));
|
stream.write(std::bit_cast<char *>(&field), sizeof(field));
|
||||||
};
|
};
|
||||||
|
|
@ -192,18 +116,14 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
|
||||||
|
|
||||||
void ShaderAsset::unpack_to(BlobTag tag, std::span<std::byte> destination) const
|
void ShaderAsset::unpack_to(BlobTag tag, std::span<std::byte> destination) const
|
||||||
{
|
{
|
||||||
debug::ensure(
|
ensure(tag == BlobTag::code, "Invalid blob tag for shader asset: {}", std::to_underlying(tag));
|
||||||
tag == BlobTag::code,
|
|
||||||
"Invalid blob tag for shader asset: {}",
|
|
||||||
std::to_underlying(tag)
|
|
||||||
);
|
|
||||||
|
|
||||||
debug::ensure(
|
ensure(
|
||||||
destination.size() >= m_code_blob_metadata.uncompressed_size,
|
destination.size() >= m_code_blob_metadata.uncompressed_size,
|
||||||
"Failed to unpack shader blob {} to destination ({}) of size {} since it's smaller "
|
"Failed to unpack shader blob {} to destination ({}) of size {} since it's smaller "
|
||||||
"than the blobl's uncompressed size: {}",
|
"than the blobl's uncompressed size: {}",
|
||||||
std::to_underlying(tag),
|
std::to_underlying(tag),
|
||||||
std::bit_cast<std::size_t>(destination.data()),
|
std::bit_cast<size_t>(destination.data()),
|
||||||
destination.size(),
|
destination.size(),
|
||||||
m_code_blob_metadata.uncompressed_size
|
m_code_blob_metadata.uncompressed_size
|
||||||
);
|
);
|
||||||
|
|
@ -217,11 +137,7 @@ void ShaderAsset::unpack_to(BlobTag tag, std::span<std::byte> destination) const
|
||||||
|
|
||||||
[[nodiscard]] auto ShaderAsset::unpack(BlobTag tag) const -> Blob
|
[[nodiscard]] auto ShaderAsset::unpack(BlobTag tag) const -> Blob
|
||||||
{
|
{
|
||||||
debug::ensure(
|
ensure(tag == BlobTag::code, "Invalid blob tag for shader asset: {}", std::to_underlying(tag));
|
||||||
tag == BlobTag::code,
|
|
||||||
"Invalid blob tag for shader asset: {}",
|
|
||||||
std::to_underlying(tag)
|
|
||||||
);
|
|
||||||
|
|
||||||
auto blob = Blob(m_code_blob_metadata.uncompressed_size);
|
auto blob = Blob(m_code_blob_metadata.uncompressed_size);
|
||||||
unpack_to(tag, blob);
|
unpack_to(tag, blob);
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import assets.metadata;
|
#include <assets/shader.hpp>
|
||||||
import assets.shader;
|
#include <ranges>
|
||||||
import test.test;
|
#include <test/test.hpp>
|
||||||
import test.expects;
|
|
||||||
import std;
|
|
||||||
|
|
||||||
using ::lt::assets::AssetMetadata;
|
using ::lt::assets::AssetMetadata;
|
||||||
using ::lt::assets::BlobMetadata;
|
using ::lt::assets::BlobMetadata;
|
||||||
|
|
@ -12,7 +10,6 @@ using ::lt::test::expect_eq;
|
||||||
using ::lt::test::expect_throw;
|
using ::lt::test::expect_throw;
|
||||||
using ::lt::test::expect_true;
|
using ::lt::test::expect_true;
|
||||||
using ::lt::test::Suite;
|
using ::lt::test::Suite;
|
||||||
using ::lt::test::operator""_suite;
|
|
||||||
|
|
||||||
const auto test_data_path = std::filesystem::path { "./data/test_assets" };
|
const auto test_data_path = std::filesystem::path { "./data/test_assets" };
|
||||||
const auto tmp_path = std::filesystem::path { "/tmp/lt_assets_tests/" };
|
const auto tmp_path = std::filesystem::path { "/tmp/lt_assets_tests/" };
|
||||||
|
|
@ -73,7 +70,7 @@ Suite packing = "shader_pack"_suite = [] {
|
||||||
expect_true(stream.is_open());
|
expect_true(stream.is_open());
|
||||||
|
|
||||||
stream.seekg(0, std::ios::end);
|
stream.seekg(0, std::ios::end);
|
||||||
const auto file_size = static_cast<std::size_t>(stream.tellg());
|
const auto file_size = static_cast<size_t>(stream.tellg());
|
||||||
expect_eq(file_size, expected_size);
|
expect_eq(file_size, expected_size);
|
||||||
stream.close();
|
stream.close();
|
||||||
|
|
||||||
3
modules/assets/public/compressors/lz4.hpp
Normal file
3
modules/assets/public/compressors/lz4.hpp
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// TO BE DOOO
|
||||||
|
|
@ -1,19 +1,18 @@
|
||||||
export module assets.metadata;
|
#pragma once
|
||||||
import std;
|
|
||||||
|
|
||||||
export namespace lt::assets {
|
namespace lt::assets {
|
||||||
|
|
||||||
using Type_T = std::array<const char, 16>;
|
using Type_T = std::array<const char, 16>;
|
||||||
|
|
||||||
using Tag_T = std::uint8_t;
|
using Tag_T = uint8_t;
|
||||||
|
|
||||||
using Version = std::uint8_t;
|
using Version = uint8_t;
|
||||||
|
|
||||||
using Blob = std::vector<std::byte>;
|
using Blob = std::vector<std::byte>;
|
||||||
|
|
||||||
constexpr auto current_version = Version { 1u };
|
constexpr auto current_version = Version { 1u };
|
||||||
|
|
||||||
enum class CompressionType : std::uint8_t
|
enum class CompressionType : uint8_t
|
||||||
{
|
{
|
||||||
none,
|
none,
|
||||||
lz4,
|
lz4,
|
||||||
|
|
@ -31,13 +30,13 @@ struct BlobMetadata
|
||||||
{
|
{
|
||||||
Tag_T tag;
|
Tag_T tag;
|
||||||
|
|
||||||
std::size_t offset;
|
size_t offset;
|
||||||
|
|
||||||
CompressionType compression_type;
|
CompressionType compression_type;
|
||||||
|
|
||||||
std::size_t compressed_size;
|
size_t compressed_size;
|
||||||
|
|
||||||
std::size_t uncompressed_size;
|
size_t uncompressed_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lt::assets
|
} // namespace lt::assets
|
||||||
74
modules/assets/public/shader.hpp
Normal file
74
modules/assets/public/shader.hpp
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assets/metadata.hpp>
|
||||||
|
|
||||||
|
namespace lt::assets {
|
||||||
|
|
||||||
|
class ShaderAsset
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr auto asset_type_identifier = Type_T { "SHADER_________" };
|
||||||
|
|
||||||
|
enum class BlobTag : Tag_T
|
||||||
|
{
|
||||||
|
code,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Type : uint8_t
|
||||||
|
{
|
||||||
|
vertex,
|
||||||
|
fragment,
|
||||||
|
geometry,
|
||||||
|
compute,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Metadata
|
||||||
|
{
|
||||||
|
Type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void pack(
|
||||||
|
const std::filesystem::path &destination,
|
||||||
|
AssetMetadata asset_metadata,
|
||||||
|
Metadata metadata,
|
||||||
|
Blob code_blob
|
||||||
|
);
|
||||||
|
|
||||||
|
ShaderAsset(const std::filesystem::path &path);
|
||||||
|
|
||||||
|
void unpack_to(BlobTag tag, std::span<std::byte> destination) const;
|
||||||
|
|
||||||
|
[[nodiscard]] auto unpack(BlobTag tag) const -> Blob;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_asset_metadata() const -> const AssetMetadata &
|
||||||
|
{
|
||||||
|
return m_asset_metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_metadata() const -> const Metadata &
|
||||||
|
{
|
||||||
|
return m_metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_blob_metadata(BlobTag tag) const -> const BlobMetadata &
|
||||||
|
{
|
||||||
|
ensure(
|
||||||
|
tag == BlobTag::code,
|
||||||
|
"Invalid blob tag for shader asset: {}",
|
||||||
|
std::to_underlying(tag)
|
||||||
|
);
|
||||||
|
|
||||||
|
return m_code_blob_metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
AssetMetadata m_asset_metadata {};
|
||||||
|
|
||||||
|
Metadata m_metadata {};
|
||||||
|
|
||||||
|
BlobMetadata m_code_blob_metadata {};
|
||||||
|
|
||||||
|
mutable std::ifstream m_stream;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt::assets
|
||||||
|
|
@ -1 +1 @@
|
||||||
add_library_module(NAME bitwise INTERFACES operations.cppm)
|
add_library_module(bitwise)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
export module bitwise;
|
#pragma once
|
||||||
import std;
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace lt::bitwise {
|
namespace lt::bitwise {
|
||||||
|
|
||||||
/* bit-wise */
|
/* bit-wise */
|
||||||
constexpr auto bit(std::uint32_t x) -> std::uint32_t
|
constexpr auto bit(uint32_t x) -> uint32_t
|
||||||
{
|
{
|
||||||
return 1u << x;
|
return 1u << x;
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
add_library_module(NAME camera INTERFACES components.cppm)
|
add_library_module(camera camera.cpp scene.cpp)
|
||||||
|
|
||||||
target_link_libraries(camera PUBLIC math)
|
target_link_libraries(camera PUBLIC math)
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
export module camera.components;
|
|
||||||
import math.vec4;
|
|
||||||
|
|
||||||
namespace lt::camera::components {
|
|
||||||
|
|
||||||
export struct PerspectiveCamera
|
|
||||||
{
|
|
||||||
float vertical_fov {};
|
|
||||||
|
|
||||||
float near_plane {};
|
|
||||||
|
|
||||||
float far_plane {};
|
|
||||||
|
|
||||||
float aspect_ratio {};
|
|
||||||
|
|
||||||
math::vec4 background_color;
|
|
||||||
|
|
||||||
bool is_primary {};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lt::camera::components
|
|
||||||
6
modules/camera/private/camera.cpp
Normal file
6
modules/camera/private/camera.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include <camera/camera.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
84
modules/camera/private/scene.cpp
Normal file
84
modules/camera/private/scene.cpp
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include <camera/camera.hpp>
|
||||||
|
#include <camera/component.hpp>
|
||||||
|
#include <math/algebra.hpp>
|
||||||
|
#include <math/trig.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
SceneCamera::SceneCamera()
|
||||||
|
: m_orthographic_specification { .size = 1000.0f, .near_plane = -1.0f, .far_plane = 10000.0f }
|
||||||
|
, m_perspective_specification { .vertical_fov = math::radians(45.0f),
|
||||||
|
.near_plane = 0.01f,
|
||||||
|
.far_plane = 10000.0f }
|
||||||
|
, m_aspect_ratio(16.0f / 9.0f)
|
||||||
|
|
||||||
|
{
|
||||||
|
calculate_projection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneCamera::set_viewport_size(unsigned int width, unsigned int height)
|
||||||
|
{
|
||||||
|
m_aspect_ratio = static_cast<float>(width) / static_cast<float>(height);
|
||||||
|
calculate_projection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneCamera::set_projection_type(ProjectionType projection_type)
|
||||||
|
{
|
||||||
|
m_projection_type = projection_type;
|
||||||
|
calculate_projection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneCamera::set_orthographic_size(float size)
|
||||||
|
{
|
||||||
|
m_orthographic_specification.size = size;
|
||||||
|
calculate_projection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneCamera::set_orthographic_far_plane(float far_plane)
|
||||||
|
{
|
||||||
|
m_orthographic_specification.far_plane = far_plane;
|
||||||
|
calculate_projection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneCamera::set_orthographic_near_plane(float near_plane)
|
||||||
|
{
|
||||||
|
m_orthographic_specification.near_plane = near_plane;
|
||||||
|
calculate_projection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneCamera::set_perspective_vertical_fov(float vertical_fov)
|
||||||
|
{
|
||||||
|
m_perspective_specification.vertical_fov = vertical_fov;
|
||||||
|
calculate_projection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneCamera::set_perspective_far_plane(float far_plane)
|
||||||
|
{
|
||||||
|
m_perspective_specification.far_plane = far_plane;
|
||||||
|
calculate_projection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneCamera::set_perspective_near_plane(float near_plane)
|
||||||
|
{
|
||||||
|
m_perspective_specification.near_plane = near_plane;
|
||||||
|
calculate_projection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneCamera::calculate_projection()
|
||||||
|
{
|
||||||
|
// TODO(Light): implement ortho perspective
|
||||||
|
if (m_projection_type == ProjectionType::Orthographic)
|
||||||
|
{
|
||||||
|
// throw std::runtime_error { "ortho perspective not supported yet" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// defaults to perspective for now...
|
||||||
|
m_projection = math::perspective(
|
||||||
|
m_perspective_specification.vertical_fov,
|
||||||
|
m_aspect_ratio,
|
||||||
|
m_perspective_specification.near_plane,
|
||||||
|
m_perspective_specification.far_plane
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace lt
|
||||||
35
modules/camera/public/camera.hpp
Normal file
35
modules/camera/public/camera.hpp
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <math/mat4.hpp>
|
||||||
|
#include <math/vec4.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
class Camera
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Camera() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_projection() const -> const math::mat4 &
|
||||||
|
{
|
||||||
|
return m_projection;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_background_color() const -> const math::vec4 &
|
||||||
|
{
|
||||||
|
return m_background_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_background_color(const math::vec4 &color)
|
||||||
|
{
|
||||||
|
m_background_color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
math::mat4 m_projection;
|
||||||
|
|
||||||
|
private:
|
||||||
|
math::vec4 m_background_color = math::vec4(1.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
||||||
29
modules/camera/public/component.hpp
Normal file
29
modules/camera/public/component.hpp
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <camera/scene.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
struct CameraComponent
|
||||||
|
{
|
||||||
|
CameraComponent() = default;
|
||||||
|
|
||||||
|
CameraComponent(const CameraComponent &) = default;
|
||||||
|
|
||||||
|
CameraComponent(SceneCamera _camera, bool _isPrimary = false)
|
||||||
|
: camera(_camera)
|
||||||
|
, isPrimary(_isPrimary)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
operator SceneCamera() const
|
||||||
|
{
|
||||||
|
return camera;
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneCamera camera;
|
||||||
|
|
||||||
|
bool isPrimary {};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
||||||
100
modules/camera/public/scene.hpp
Normal file
100
modules/camera/public/scene.hpp
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <camera/camera.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
class SceneCamera: public Camera
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class ProjectionType
|
||||||
|
{
|
||||||
|
Orthographic = 0,
|
||||||
|
Perspetcive = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrthographicSpecification
|
||||||
|
{
|
||||||
|
float size;
|
||||||
|
|
||||||
|
float near_plane;
|
||||||
|
|
||||||
|
float far_plane;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PerspectiveSpecification
|
||||||
|
{
|
||||||
|
float vertical_fov;
|
||||||
|
|
||||||
|
float near_plane;
|
||||||
|
|
||||||
|
float far_plane;
|
||||||
|
};
|
||||||
|
|
||||||
|
SceneCamera();
|
||||||
|
|
||||||
|
void set_viewport_size(unsigned int width, unsigned int height);
|
||||||
|
|
||||||
|
void set_projection_type(ProjectionType projection_type);
|
||||||
|
|
||||||
|
void set_orthographic_size(float size);
|
||||||
|
|
||||||
|
void set_orthographic_far_plane(float far_plane);
|
||||||
|
|
||||||
|
void set_orthographic_near_plane(float near_plane);
|
||||||
|
|
||||||
|
void set_perspective_vertical_fov(float vertical_fov);
|
||||||
|
|
||||||
|
void set_perspective_far_plane(float far_plane);
|
||||||
|
|
||||||
|
void set_perspective_near_plane(float near_plane);
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_orthographic_size() const -> float
|
||||||
|
{
|
||||||
|
return m_orthographic_specification.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_orthographic_far_plane() const -> float
|
||||||
|
{
|
||||||
|
return m_orthographic_specification.far_plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_orthographic_near_plane() const -> float
|
||||||
|
{
|
||||||
|
return m_orthographic_specification.near_plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_perspective_vertical_fov() const -> float
|
||||||
|
{
|
||||||
|
return m_perspective_specification.vertical_fov;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_perspective_far_plane() const -> float
|
||||||
|
{
|
||||||
|
return m_perspective_specification.far_plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_perspective_near_plane() const -> float
|
||||||
|
{
|
||||||
|
return m_perspective_specification.near_plane;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_projection_type() const -> ProjectionType
|
||||||
|
{
|
||||||
|
return m_projection_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
OrthographicSpecification m_orthographic_specification;
|
||||||
|
|
||||||
|
PerspectiveSpecification m_perspective_specification;
|
||||||
|
|
||||||
|
float m_aspect_ratio;
|
||||||
|
|
||||||
|
ProjectionType m_projection_type { ProjectionType::Orthographic };
|
||||||
|
|
||||||
|
void calculate_projection();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
||||||
|
|
@ -1,2 +1,4 @@
|
||||||
add_library_module(NAME lt_debug INTERFACES instrumentor.cppm assertions.cppm)
|
add_library_module(lt_debug instrumentor.cpp)
|
||||||
target_link_libraries(lt_debug PUBLIC logger)
|
target_link_libraries(lt_debug PUBLIC logger)
|
||||||
|
target_precompile_headers(lt_debug PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/private/pch.hpp)
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
export module debug.assertions;
|
|
||||||
|
|
||||||
import std;
|
|
||||||
|
|
||||||
namespace lt::debug {
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
// ----------* INTERFACE *--------- //
|
|
||||||
/////////////////////////////////////
|
|
||||||
export template<typename Expression_T, typename... Args_T>
|
|
||||||
struct ensure
|
|
||||||
{
|
|
||||||
ensure(
|
|
||||||
const Expression_T &expression,
|
|
||||||
std::format_string<Args_T...> fmt,
|
|
||||||
Args_T &&...args,
|
|
||||||
const std::source_location &location = std::source_location::current()
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export template<typename Expression_T, typename... Args_T>
|
|
||||||
ensure(Expression_T, std::format_string<Args_T...>, Args_T &&...)
|
|
||||||
-> ensure<Expression_T, Args_T...>;
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
// * IMPLEMENTATION -- TEMPLATES * //
|
|
||||||
/////////////////////////////////////
|
|
||||||
template<typename Expression_T, typename... Args_T>
|
|
||||||
ensure<Expression_T, Args_T...>::ensure(
|
|
||||||
const Expression_T &expression,
|
|
||||||
std::format_string<Args_T...> fmt,
|
|
||||||
Args_T &&...args,
|
|
||||||
const std::source_location &location
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!static_cast<bool>(expression))
|
|
||||||
{
|
|
||||||
throw std::runtime_error { std::format(
|
|
||||||
"exception: {}\nlocation: {}:{}",
|
|
||||||
std::format(fmt, std::forward<Args_T>(args)...),
|
|
||||||
location.file_name(),
|
|
||||||
location.line()
|
|
||||||
) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace lt::debug
|
|
||||||
|
|
@ -1,145 +0,0 @@
|
||||||
export module debug.instrumentor;
|
|
||||||
|
|
||||||
import std;
|
|
||||||
import logger;
|
|
||||||
|
|
||||||
namespace lt::debug {
|
|
||||||
|
|
||||||
struct ScopeProfileResult
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
long long start, duration;
|
|
||||||
std::uint32_t threadID;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Instrumentor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static auto instance() -> Instrumentor &
|
|
||||||
{
|
|
||||||
static auto instance = Instrumentor {};
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void begin_session(const std::string &outputPath)
|
|
||||||
{
|
|
||||||
instance().begin_session_impl(outputPath);
|
|
||||||
}
|
|
||||||
static void end_session()
|
|
||||||
{
|
|
||||||
instance().end_session_impl();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void submit_scope_profile(const ScopeProfileResult &profileResult)
|
|
||||||
{
|
|
||||||
instance().submit_scope_profile_impl(profileResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::ofstream m_output_file_stream;
|
|
||||||
|
|
||||||
unsigned int m_current_session_count { 0u };
|
|
||||||
|
|
||||||
Instrumentor() = default;
|
|
||||||
|
|
||||||
void begin_session_impl(const std::string &outputPath);
|
|
||||||
|
|
||||||
void end_session_impl();
|
|
||||||
|
|
||||||
void submit_scope_profile_impl(const ScopeProfileResult &profileResult);
|
|
||||||
};
|
|
||||||
|
|
||||||
class InstrumentorTimer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
InstrumentorTimer(const std::string &scopeName);
|
|
||||||
|
|
||||||
~InstrumentorTimer();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ScopeProfileResult m_result;
|
|
||||||
|
|
||||||
std::chrono::time_point<std::chrono::steady_clock> m_start;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lt::debug
|
|
||||||
|
|
||||||
/* scope */
|
|
||||||
#define lt_profile_scope(name) lt_profile_scope_no_redifinition(name, __LINE__)
|
|
||||||
#define lt_profile_scope_no_redifinition(name, line) lt_profile_scope_no_redifinition2(name, line)
|
|
||||||
#define lt_profile_scope_no_redifinition2(name, line) InstrumentorTimer timer##line(name)
|
|
||||||
|
|
||||||
/* function */
|
|
||||||
#define LT_PROFILE_FUNCTION lt_profile_scope(__FUNCSIG__)
|
|
||||||
|
|
||||||
/* session */
|
|
||||||
#define lt_profile_begin_session(outputPath) ::lt::Instrumentor::begin_session(outputPath)
|
|
||||||
#define lt_profile_end_session() ::lt::Instrumentor::end_session()
|
|
||||||
|
|
||||||
module :private;
|
|
||||||
using namespace lt::debug;
|
|
||||||
|
|
||||||
void Instrumentor::begin_session_impl(const std::string &outputPath)
|
|
||||||
{
|
|
||||||
std::filesystem::create_directory(outputPath.substr(0, outputPath.find_last_of('/') + 1));
|
|
||||||
|
|
||||||
m_output_file_stream.open(outputPath);
|
|
||||||
m_output_file_stream << "{\"traceEvents\":[";
|
|
||||||
}
|
|
||||||
|
|
||||||
void Instrumentor::end_session_impl()
|
|
||||||
{
|
|
||||||
if (m_current_session_count == 0u)
|
|
||||||
{
|
|
||||||
log::warn("0 profiling for the ended session");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_current_session_count = 0u;
|
|
||||||
|
|
||||||
m_output_file_stream << "]}";
|
|
||||||
m_output_file_stream.flush();
|
|
||||||
m_output_file_stream.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Instrumentor::submit_scope_profile_impl(const ScopeProfileResult &profileResult)
|
|
||||||
{
|
|
||||||
if (m_current_session_count++ == 0u)
|
|
||||||
{
|
|
||||||
m_output_file_stream << "{";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_output_file_stream << ",{";
|
|
||||||
}
|
|
||||||
|
|
||||||
m_output_file_stream << R"("name":")" << profileResult.name << "\",";
|
|
||||||
m_output_file_stream << R"("cat": "scope",)";
|
|
||||||
m_output_file_stream << R"("ph": "X",)";
|
|
||||||
m_output_file_stream << "\"ts\":" << profileResult.start << ",";
|
|
||||||
m_output_file_stream << "\"dur\":" << profileResult.duration << ",";
|
|
||||||
m_output_file_stream << "\"pid\":0,";
|
|
||||||
m_output_file_stream << "\"tid\":" << profileResult.threadID << "";
|
|
||||||
m_output_file_stream << "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
InstrumentorTimer::InstrumentorTimer(const std::string &scopeName)
|
|
||||||
: m_result({ .name = scopeName, .start = 0, .duration = 0, .threadID = 0 })
|
|
||||||
, m_start(std::chrono::steady_clock::now())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
InstrumentorTimer::~InstrumentorTimer()
|
|
||||||
{
|
|
||||||
auto end = std::chrono::steady_clock::now();
|
|
||||||
|
|
||||||
m_result.start = std::chrono::time_point_cast<std::chrono::microseconds>(m_start)
|
|
||||||
.time_since_epoch()
|
|
||||||
.count();
|
|
||||||
|
|
||||||
m_result.duration = std::chrono::time_point_cast<std::chrono::microseconds>(end)
|
|
||||||
.time_since_epoch()
|
|
||||||
.count()
|
|
||||||
- m_result.start;
|
|
||||||
|
|
||||||
Instrumentor::submit_scope_profile(m_result);
|
|
||||||
}
|
|
||||||
71
modules/debug/private/instrumentor.cpp
Normal file
71
modules/debug/private/instrumentor.cpp
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
#include <logger/logger.hpp>
|
||||||
|
#include <lt_debug/instrumentor.hpp>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
void Instrumentor::begin_session_impl(const std::string &outputPath)
|
||||||
|
{
|
||||||
|
std::filesystem::create_directory(outputPath.substr(0, outputPath.find_last_of('/') + 1));
|
||||||
|
|
||||||
|
m_output_file_stream.open(outputPath);
|
||||||
|
m_output_file_stream << "{\"traceEvents\":[";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Instrumentor::end_session_impl()
|
||||||
|
{
|
||||||
|
if (m_current_session_count == 0u)
|
||||||
|
{
|
||||||
|
log_wrn("0 profiling for the ended session");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_current_session_count = 0u;
|
||||||
|
|
||||||
|
m_output_file_stream << "]}";
|
||||||
|
m_output_file_stream.flush();
|
||||||
|
m_output_file_stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Instrumentor::submit_scope_profile_impl(const ScopeProfileResult &profileResult)
|
||||||
|
{
|
||||||
|
if (m_current_session_count++ == 0u)
|
||||||
|
{
|
||||||
|
m_output_file_stream << "{";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_output_file_stream << ",{";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_output_file_stream << R"("name":")" << profileResult.name << "\",";
|
||||||
|
m_output_file_stream << R"("cat": "scope",)";
|
||||||
|
m_output_file_stream << R"("ph": "X",)";
|
||||||
|
m_output_file_stream << "\"ts\":" << profileResult.start << ",";
|
||||||
|
m_output_file_stream << "\"dur\":" << profileResult.duration << ",";
|
||||||
|
m_output_file_stream << "\"pid\":0,";
|
||||||
|
m_output_file_stream << "\"tid\":" << profileResult.threadID << "";
|
||||||
|
m_output_file_stream << "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrumentorTimer::InstrumentorTimer(const std::string &scopeName)
|
||||||
|
: m_result({ .name = scopeName, .start = 0, .duration = 0, .threadID = 0 })
|
||||||
|
, m_start(std::chrono::steady_clock::now())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrumentorTimer::~InstrumentorTimer()
|
||||||
|
{
|
||||||
|
auto end = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
m_result.start = std::chrono::time_point_cast<std::chrono::microseconds>(m_start)
|
||||||
|
.time_since_epoch()
|
||||||
|
.count();
|
||||||
|
|
||||||
|
m_result.duration = std::chrono::time_point_cast<std::chrono::microseconds>(end)
|
||||||
|
.time_since_epoch()
|
||||||
|
.count()
|
||||||
|
- m_result.start;
|
||||||
|
|
||||||
|
Instrumentor::submit_scope_profile(m_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace lt
|
||||||
3
modules/debug/private/pch.hpp
Normal file
3
modules/debug/private/pch.hpp
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <lt_debug/assertions.hpp>
|
||||||
36
modules/debug/public/assertions.hpp
Normal file
36
modules/debug/public/assertions.hpp
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <format>
|
||||||
|
#include <logger/logger.hpp>
|
||||||
|
#include <source_location>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
template<typename Expression_T, typename... Args_T>
|
||||||
|
struct ensure
|
||||||
|
{
|
||||||
|
ensure(
|
||||||
|
const Expression_T &expression,
|
||||||
|
std::format_string<Args_T...> fmt,
|
||||||
|
Args_T &&...args,
|
||||||
|
const std::source_location &location = std::source_location::current()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!static_cast<bool>(expression))
|
||||||
|
{
|
||||||
|
throw std::runtime_error { std::format(
|
||||||
|
"exception: {}\nlocation: {}:{}",
|
||||||
|
std::format(fmt, std::forward<Args_T>(args)...),
|
||||||
|
location.file_name(),
|
||||||
|
location.line()
|
||||||
|
) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Expression_T, typename... Args_T>
|
||||||
|
ensure(Expression_T, std::format_string<Args_T...>, Args_T &&...)
|
||||||
|
-> ensure<Expression_T, Args_T...>;
|
||||||
|
|
||||||
|
} // namespace lt
|
||||||
77
modules/debug/public/instrumentor.hpp
Normal file
77
modules/debug/public/instrumentor.hpp
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace lt {
|
||||||
|
|
||||||
|
struct ScopeProfileResult
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
long long start, duration;
|
||||||
|
uint32_t threadID;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Instrumentor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static auto instance() -> Instrumentor &
|
||||||
|
{
|
||||||
|
static auto instance = Instrumentor {};
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void begin_session(const std::string &outputPath)
|
||||||
|
{
|
||||||
|
instance().begin_session_impl(outputPath);
|
||||||
|
}
|
||||||
|
static void end_session()
|
||||||
|
{
|
||||||
|
instance().end_session_impl();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void submit_scope_profile(const ScopeProfileResult &profileResult)
|
||||||
|
{
|
||||||
|
instance().submit_scope_profile_impl(profileResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::ofstream m_output_file_stream;
|
||||||
|
|
||||||
|
unsigned int m_current_session_count { 0u };
|
||||||
|
|
||||||
|
Instrumentor() = default;
|
||||||
|
|
||||||
|
void begin_session_impl(const std::string &outputPath);
|
||||||
|
|
||||||
|
void end_session_impl();
|
||||||
|
|
||||||
|
void submit_scope_profile_impl(const ScopeProfileResult &profileResult);
|
||||||
|
};
|
||||||
|
|
||||||
|
class InstrumentorTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InstrumentorTimer(const std::string &scopeName);
|
||||||
|
|
||||||
|
~InstrumentorTimer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ScopeProfileResult m_result;
|
||||||
|
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock> m_start;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace lt
|
||||||
|
|
||||||
|
/* scope */
|
||||||
|
#define lt_profile_scope(name) lt_profile_scope_no_redifinition(name, __LINE__)
|
||||||
|
#define lt_profile_scope_no_redifinition(name, line) lt_profile_scope_no_redifinition2(name, line)
|
||||||
|
#define lt_profile_scope_no_redifinition2(name, line) InstrumentorTimer timer##line(name)
|
||||||
|
|
||||||
|
/* function */
|
||||||
|
#define LT_PROFILE_FUNCTION lt_profile_scope(__FUNCSIG__)
|
||||||
|
|
||||||
|
/* session */
|
||||||
|
#define lt_profile_begin_session(outputPath) ::lt::Instrumentor::begin_session(outputPath)
|
||||||
|
#define lt_profile_end_session() ::lt::Instrumentor::end_session()
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
add_library_module(NAME ecs INTERFACES sparse_set.cppm registry.cppm
|
add_library_module(ecs sparse_set.cpp)
|
||||||
entity.cppm)
|
|
||||||
target_link_libraries(ecs PUBLIC logger lt_debug memory)
|
target_link_libraries(ecs PUBLIC logger lt_debug memory)
|
||||||
|
|
||||||
add_test_module(ecs sparse_set.test.cpp registry.test.cpp)
|
add_test_module(ecs sparse_set.test.cpp registry.test.cpp)
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,19 @@
|
||||||
import ecs.registry;
|
#include <ecs/registry.hpp>
|
||||||
import test.test;
|
#include <ranges>
|
||||||
import test.expects;
|
#include <test/expects.hpp>
|
||||||
import std;
|
#include <test/test.hpp>
|
||||||
|
|
||||||
using ::lt::ecs::EntityId;
|
using lt::test::Case;
|
||||||
using ::lt::ecs::Registry;
|
using lt::test::expect_unreachable;
|
||||||
using ::lt::test::Case;
|
using lt::test::Suite;
|
||||||
using ::lt::test::expect_eq;
|
|
||||||
using ::lt::test::expect_false;
|
using lt::test::expect_eq;
|
||||||
using ::lt::test::expect_true;
|
|
||||||
using ::lt::test::expect_unreachable;
|
using lt::test::expect_false;
|
||||||
using ::lt::test::Suite;
|
using lt::test::expect_true;
|
||||||
using ::lt::test::operator""_suite;
|
|
||||||
|
using lt::ecs::EntityId;
|
||||||
|
using lt::ecs::Registry;
|
||||||
|
|
||||||
struct Component
|
struct Component
|
||||||
{
|
{
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
import ecs.sparse_set;
|
#include <ecs/sparse_set.hpp>
|
||||||
import test.test;
|
#include <ranges>
|
||||||
import test.expects;
|
#include <test/expects.hpp>
|
||||||
import std;
|
#include <test/test.hpp>
|
||||||
|
|
||||||
using ::lt::test::Case;
|
using lt::test::Case;
|
||||||
using ::lt::test::expect_eq;
|
using lt::test::Suite;
|
||||||
using ::lt::test::expect_false;
|
|
||||||
using ::lt::test::expect_ne;
|
using lt::test::expect_eq;
|
||||||
using ::lt::test::expect_throw;
|
using lt::test::expect_false;
|
||||||
using ::lt::test::expect_true;
|
using lt::test::expect_ne;
|
||||||
using ::lt::test::Suite;
|
using lt::test::expect_throw;
|
||||||
using ::lt::test::operator""_suite;
|
using lt::test::expect_true;
|
||||||
|
|
||||||
using Set = lt::ecs::SparseSet<int>;
|
using Set = lt::ecs::SparseSet<int>;
|
||||||
constexpr auto capacity = 100;
|
constexpr auto capacity = 100;
|
||||||
|
|
@ -1,20 +1,19 @@
|
||||||
export module ecs.entity;
|
#pragma once
|
||||||
import debug.assertions;
|
|
||||||
import memory.reference;
|
#include <ecs/registry.hpp>
|
||||||
import ecs.registry;
|
#include <memory/reference.hpp>
|
||||||
import std;
|
|
||||||
|
|
||||||
namespace lt::ecs {
|
namespace lt::ecs {
|
||||||
|
|
||||||
/** High-level entity convenience wrapper */
|
/** High-level entity convenience wrapper */
|
||||||
export class Entity
|
class Entity
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Entity(memory::Ref<Registry> registry, EntityId identifier)
|
Entity(memory::Ref<Registry> registry, EntityId identifier)
|
||||||
: m_registry(std::move(registry))
|
: m_registry(std::move(registry))
|
||||||
, m_identifier(identifier)
|
, m_identifier(identifier)
|
||||||
{
|
{
|
||||||
debug::ensure(m_registry, "Failed to create Entity ({}): null registry", m_identifier);
|
ensure(m_registry, "Failed to create Entity ({}): null registry", m_identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Component_T>
|
template<typename Component_T>
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
export module ecs.registry;
|
#pragma once
|
||||||
import debug.assertions;
|
|
||||||
import ecs.sparse_set;
|
#include <ecs/sparse_set.hpp>
|
||||||
import memory.scope;
|
#include <memory/scope.hpp>
|
||||||
import std;
|
|
||||||
|
|
||||||
namespace lt::ecs {
|
namespace lt::ecs {
|
||||||
|
|
||||||
export using EntityId = std::uint32_t;
|
using EntityId = uint32_t;
|
||||||
|
|
||||||
export constexpr auto null_entity = std::numeric_limits<EntityId>::max();
|
constexpr auto null_entity = std::numeric_limits<EntityId>::max();
|
||||||
|
|
||||||
/** A registry of components, the heart of an ECS architecture.
|
/** A registry of components, the heart of an ECS architecture.
|
||||||
*
|
*
|
||||||
|
|
@ -23,7 +22,7 @@ export constexpr auto null_entity = std::numeric_limits<EntityId>::max();
|
||||||
* @ref https://github.com/skypjack/entt
|
* @ref https://github.com/skypjack/entt
|
||||||
* @ref https://github.com/SanderMertens/flecs
|
* @ref https://github.com/SanderMertens/flecs
|
||||||
*/
|
*/
|
||||||
export class Registry
|
class Registry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using UnderlyingSparseSet_T = TypeErasedSparseSet<EntityId>;
|
using UnderlyingSparseSet_T = TypeErasedSparseSet<EntityId>;
|
||||||
|
|
@ -190,25 +189,25 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] auto get_entity_count() const -> std::size_t
|
[[nodiscard]] auto get_entity_count() const -> size_t
|
||||||
{
|
{
|
||||||
return static_cast<std::size_t>(m_entity_count);
|
return static_cast<size_t>(m_entity_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using TypeId = std::size_t;
|
using TypeId = size_t;
|
||||||
|
|
||||||
static consteval auto hash_cstr(const char *str) -> TypeId
|
static consteval auto hash_cstr(const char *str) -> TypeId
|
||||||
{
|
{
|
||||||
constexpr auto fnv_offset_basis = std::size_t { 14695981039346656037ull };
|
constexpr auto fnv_offset_basis = size_t { 14695981039346656037ull };
|
||||||
constexpr auto fnv_prime = std::size_t { 1099511628211ull };
|
constexpr auto fnv_prime = size_t { 1099511628211ull };
|
||||||
|
|
||||||
auto hash = fnv_offset_basis;
|
auto hash = fnv_offset_basis;
|
||||||
|
|
||||||
for (const auto &ch : std::string_view { str })
|
for (const auto &ch : std::string_view { str })
|
||||||
{
|
{
|
||||||
hash *= fnv_prime;
|
hash *= fnv_prime;
|
||||||
hash ^= static_cast<std::uint8_t>(ch);
|
hash ^= static_cast<uint8_t>(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
|
|
@ -242,7 +241,7 @@ private:
|
||||||
|
|
||||||
auto *base_set = m_sparsed_sets[type_id].get();
|
auto *base_set = m_sparsed_sets[type_id].get();
|
||||||
auto *derived_set = dynamic_cast<SparseSet<T, EntityId> *>(base_set);
|
auto *derived_set = dynamic_cast<SparseSet<T, EntityId> *>(base_set);
|
||||||
debug::ensure(derived_set, "Failed to downcast to derived set");
|
ensure(derived_set, "Failed to downcast to derived set");
|
||||||
|
|
||||||
return *derived_set;
|
return *derived_set;
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
export module ecs.sparse_set;
|
#pragma once
|
||||||
import debug.assertions;
|
|
||||||
import std;
|
|
||||||
|
|
||||||
namespace lt::ecs {
|
namespace lt::ecs {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* @ref https://programmingpraxis.com/2012/03/09/sparse-sets/
|
* @ref https://programmingpraxis.com/2012/03/09/sparse-sets/
|
||||||
*/
|
*/
|
||||||
export template<typename Identifier_T = std::uint32_t>
|
template<typename Identifier_T = uint32_t>
|
||||||
class TypeErasedSparseSet
|
class TypeErasedSparseSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -26,19 +25,19 @@ public:
|
||||||
virtual void remove(Identifier_T identifier) = 0;
|
virtual void remove(Identifier_T identifier) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
export template<typename Value_T, typename Identifier_T = std::uint32_t>
|
template<typename Value_T, typename Identifier_T = uint32_t>
|
||||||
class SparseSet: public TypeErasedSparseSet<Identifier_T>
|
class SparseSet: public TypeErasedSparseSet<Identifier_T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Dense_T = std::pair<Identifier_T, Value_T>;
|
using Dense_T = std::pair<Identifier_T, Value_T>;
|
||||||
|
|
||||||
static constexpr auto max_capacity = std::size_t { 1'000'000 };
|
static constexpr auto max_capacity = size_t { 1'000'000 };
|
||||||
|
|
||||||
static constexpr auto null_identifier = std::numeric_limits<Identifier_T>().max();
|
static constexpr auto null_identifier = std::numeric_limits<Identifier_T>().max();
|
||||||
|
|
||||||
explicit SparseSet(std::size_t initial_capacity = 1)
|
explicit SparseSet(size_t initial_capacity = 1)
|
||||||
{
|
{
|
||||||
debug::ensure(
|
ensure(
|
||||||
initial_capacity <= max_capacity,
|
initial_capacity <= max_capacity,
|
||||||
"Failed to create SparseSet: capacity too large ({} > {})",
|
"Failed to create SparseSet: capacity too large ({} > {})",
|
||||||
initial_capacity,
|
initial_capacity,
|
||||||
|
|
@ -53,16 +52,13 @@ public:
|
||||||
{
|
{
|
||||||
if (m_sparse.size() < identifier + 1)
|
if (m_sparse.size() < identifier + 1)
|
||||||
{
|
{
|
||||||
auto new_capacity = std::max(
|
auto new_capacity = std::max(static_cast<size_t>(identifier + 1), m_sparse.size() * 2);
|
||||||
static_cast<std::size_t>(identifier + 1),
|
|
||||||
m_sparse.size() * 2
|
|
||||||
);
|
|
||||||
new_capacity = std::min(new_capacity, max_capacity);
|
new_capacity = std::min(new_capacity, max_capacity);
|
||||||
|
|
||||||
// log::debug("Increasing sparse vector size:", m_dead_count);
|
// log_dbg("Increasing sparse vector size:", m_dead_count);
|
||||||
// log::debug("\tdead_count: {}", m_dead_count);
|
// log_dbg("\tdead_count: {}", m_dead_count);
|
||||||
// log::debug("\talive_count: {}", m_alive_count);
|
// log_dbg("\talive_count: {}", m_alive_count);
|
||||||
// log::debug("\tsparse.size: {} -> {}", m_sparse.size(), new_capacity);
|
// log_dbg("\tsparse.size: {} -> {}", m_sparse.size(), new_capacity);
|
||||||
|
|
||||||
m_sparse.resize(new_capacity, null_identifier);
|
m_sparse.resize(new_capacity, null_identifier);
|
||||||
}
|
}
|
||||||
|
|
@ -149,12 +145,12 @@ public:
|
||||||
return std::forward<Self_T>(self).m_dense[std::forward<Self_T>(self).m_sparse[identifier]];
|
return std::forward<Self_T>(self).m_dense[std::forward<Self_T>(self).m_sparse[identifier]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto get_size() const noexcept -> std::size_t
|
[[nodiscard]] auto get_size() const noexcept -> size_t
|
||||||
{
|
{
|
||||||
return m_alive_count;
|
return m_alive_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto get_capacity() const noexcept -> std::size_t
|
[[nodiscard]] auto get_capacity() const noexcept -> size_t
|
||||||
{
|
{
|
||||||
return m_sparse.capacity();
|
return m_sparse.capacity();
|
||||||
}
|
}
|
||||||
|
|
@ -169,9 +165,9 @@ private:
|
||||||
|
|
||||||
std::vector<Identifier_T> m_sparse;
|
std::vector<Identifier_T> m_sparse;
|
||||||
|
|
||||||
std::size_t m_alive_count {};
|
size_t m_alive_count {};
|
||||||
|
|
||||||
std::size_t m_dead_count {};
|
size_t m_dead_count {};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lt::ecs
|
} // namespace lt::ecs
|
||||||
2
modules/env/CMakeLists.txt
vendored
2
modules/env/CMakeLists.txt
vendored
|
|
@ -1 +1 @@
|
||||||
add_library_module(NAME env INTERFACES constants.cppm)
|
add_library_module(env)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
export module env;
|
#pragma once
|
||||||
|
|
||||||
import std;
|
|
||||||
|
|
||||||
namespace lt {
|
namespace lt {
|
||||||
|
|
||||||
enum class Platform : std::uint8_t
|
enum class Platform : uint8_t
|
||||||
{
|
{
|
||||||
/** The GNU/Linux platform.
|
/** The GNU/Linux platform.
|
||||||
* Tested on the following distros: arch-x86_64
|
* Tested on the following distros: arch-x86_64
|
||||||
|
|
@ -26,7 +24,7 @@ enum class Platform : std::uint8_t
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The compiler that was used for compiling the project. */
|
/** The compiler that was used for compiling the project. */
|
||||||
enum class Compiler : std::uint8_t
|
enum class Compiler : uint8_t
|
||||||
{
|
{
|
||||||
clang,
|
clang,
|
||||||
gcc,
|
gcc,
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
add_library_module(NAME input INTERFACES system.cpp)
|
add_library_module(input system.cpp)
|
||||||
target_link_libraries(input PUBLIC surface math logger tbb)
|
target_link_libraries(input PUBLIC surface math logger tbb)
|
||||||
|
|
||||||
add_test_module(input system.test.cpp)
|
add_test_module(input system.test.cpp)
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,3 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <app/system.hpp>
|
|
||||||
#include <ecs/registry.hpp>
|
|
||||||
#include <memory/reference.hpp>
|
|
||||||
#include <surface/components.hpp>
|
|
||||||
#include <surface/events/keyboard.hpp>
|
|
||||||
#include <surface/events/mouse.hpp>
|
|
||||||
|
|
||||||
namespace lt::input {
|
|
||||||
|
|
||||||
class System: public app::ISystem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
System(memory::Ref<ecs::Registry> registry);
|
|
||||||
|
|
||||||
void tick(app::TickInfo tick) override;
|
|
||||||
|
|
||||||
void on_register() override;
|
|
||||||
|
|
||||||
void on_unregister() override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override
|
|
||||||
{
|
|
||||||
return m_last_tick_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void handle_event(const surface::SurfaceComponent::Event &event);
|
|
||||||
|
|
||||||
void on_surface_lost_focus();
|
|
||||||
|
|
||||||
void on_key_press(const lt::surface::KeyPressedEvent &event);
|
|
||||||
|
|
||||||
void on_key_release(const lt::surface::KeyReleasedEvent &event);
|
|
||||||
|
|
||||||
void on_pointer_move(const lt::surface::MouseMovedEvent &event);
|
|
||||||
|
|
||||||
void on_button_press(const lt::surface::ButtonPressedEvent &event);
|
|
||||||
|
|
||||||
void on_button_release(const lt::surface::ButtonReleasedEvent &event);
|
|
||||||
|
|
||||||
memory::Ref<ecs::Registry> m_registry;
|
|
||||||
|
|
||||||
std::array<bool, 512> m_keys {};
|
|
||||||
|
|
||||||
std::array<bool, 512> m_buttons {};
|
|
||||||
|
|
||||||
math::vec2 m_pointer_position;
|
|
||||||
|
|
||||||
app::TickResult m_last_tick_result {};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace lt::input
|
|
||||||
|
|
||||||
|
|
||||||
module :private;
|
|
||||||
|
|
||||||
#include <input/components.hpp>
|
#include <input/components.hpp>
|
||||||
#include <input/system.hpp>
|
#include <input/system.hpp>
|
||||||
#include <memory/reference.hpp>
|
#include <memory/reference.hpp>
|
||||||
|
|
@ -160,7 +101,7 @@ void System::on_key_press(const lt::surface::KeyPressedEvent &event)
|
||||||
{
|
{
|
||||||
if (event.get_key() > m_keys.size())
|
if (event.get_key() > m_keys.size())
|
||||||
{
|
{
|
||||||
log::debug(
|
log_dbg(
|
||||||
"Key code larger than key container size, implement platform-dependant "
|
"Key code larger than key container size, implement platform-dependant "
|
||||||
"key-code-mapping!"
|
"key-code-mapping!"
|
||||||
);
|
);
|
||||||
|
|
@ -175,7 +116,7 @@ void System::on_key_release(const lt::surface::KeyReleasedEvent &event)
|
||||||
{
|
{
|
||||||
if (event.get_key() > m_keys.size())
|
if (event.get_key() > m_keys.size())
|
||||||
{
|
{
|
||||||
log::debug(
|
log_dbg(
|
||||||
"Key code larger than key container size, implement platform-dependant "
|
"Key code larger than key container size, implement platform-dependant "
|
||||||
"key-code-mapping!"
|
"key-code-mapping!"
|
||||||
);
|
);
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export module input.components;
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace lt::Key {
|
||||||
|
|
||||||
enum : uint16_t
|
enum : uint16_t
|
||||||
{
|
{
|
||||||
|
|
@ -176,21 +177,4 @@ enum : uint16_t
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
enum : uint8_t
|
|
||||||
{
|
|
||||||
Button1 = 0,
|
|
||||||
Button2 = 1,
|
|
||||||
Button3 = 2,
|
|
||||||
Button4 = 3,
|
|
||||||
Button5 = 4,
|
|
||||||
Button6 = 5,
|
|
||||||
Button7 = 6,
|
|
||||||
Button8 = 7,
|
|
||||||
|
|
||||||
LButton = Button1,
|
|
||||||
RButton = Button2,
|
|
||||||
MButton = Button3,
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lt::Key
|
|
||||||
23
modules/input/public/mouse_codes.hpp
Normal file
23
modules/input/public/mouse_codes.hpp
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace lt::Mouse {
|
||||||
|
|
||||||
|
enum : uint8_t
|
||||||
|
{
|
||||||
|
Button1 = 0,
|
||||||
|
Button2 = 1,
|
||||||
|
Button3 = 2,
|
||||||
|
Button4 = 3,
|
||||||
|
Button5 = 4,
|
||||||
|
Button6 = 5,
|
||||||
|
Button7 = 6,
|
||||||
|
Button8 = 7,
|
||||||
|
|
||||||
|
LButton = Button1,
|
||||||
|
RButton = Button2,
|
||||||
|
MButton = Button3,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
55
modules/input/public/system.hpp
Normal file
55
modules/input/public/system.hpp
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <app/system.hpp>
|
||||||
|
#include <ecs/registry.hpp>
|
||||||
|
#include <memory/reference.hpp>
|
||||||
|
#include <surface/components.hpp>
|
||||||
|
#include <surface/events/keyboard.hpp>
|
||||||
|
#include <surface/events/mouse.hpp>
|
||||||
|
|
||||||
|
namespace lt::input {
|
||||||
|
|
||||||
|
class System: public app::ISystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
System(memory::Ref<ecs::Registry> registry);
|
||||||
|
|
||||||
|
void tick(app::TickInfo tick) override;
|
||||||
|
|
||||||
|
void on_register() override;
|
||||||
|
|
||||||
|
void on_unregister() override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override
|
||||||
|
{
|
||||||
|
return m_last_tick_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handle_event(const surface::SurfaceComponent::Event &event);
|
||||||
|
|
||||||
|
void on_surface_lost_focus();
|
||||||
|
|
||||||
|
void on_key_press(const lt::surface::KeyPressedEvent &event);
|
||||||
|
|
||||||
|
void on_key_release(const lt::surface::KeyReleasedEvent &event);
|
||||||
|
|
||||||
|
void on_pointer_move(const lt::surface::MouseMovedEvent &event);
|
||||||
|
|
||||||
|
void on_button_press(const lt::surface::ButtonPressedEvent &event);
|
||||||
|
|
||||||
|
void on_button_release(const lt::surface::ButtonReleasedEvent &event);
|
||||||
|
|
||||||
|
memory::Ref<ecs::Registry> m_registry;
|
||||||
|
|
||||||
|
std::array<bool, 512> m_keys {};
|
||||||
|
|
||||||
|
std::array<bool, 512> m_buttons {};
|
||||||
|
|
||||||
|
math::vec2 m_pointer_position;
|
||||||
|
|
||||||
|
app::TickResult m_last_tick_result {};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace lt::input
|
||||||
|
|
@ -1,2 +1 @@
|
||||||
add_library_module(NAME logger INTERFACES logger.cppm)
|
add_library_module(logger logger.cpp)
|
||||||
# add_test_module(logger logger.test.cpp)
|
|
||||||
|
|
|
||||||
|
|
@ -1,180 +0,0 @@
|
||||||
export module logger;
|
|
||||||
|
|
||||||
import std;
|
|
||||||
|
|
||||||
namespace lt::log {
|
|
||||||
|
|
||||||
/** Severity of a log message. */
|
|
||||||
enum class Level : std::uint8_t
|
|
||||||
{
|
|
||||||
/** Lowest and most vebose log level, for tracing execution paths and events */
|
|
||||||
trace = 0,
|
|
||||||
|
|
||||||
/** Vebose log level, for enabling temporarily to debug */
|
|
||||||
debug = 1,
|
|
||||||
|
|
||||||
/** General information */
|
|
||||||
info = 2,
|
|
||||||
|
|
||||||
/** Things we should to be aware of and edge cases */
|
|
||||||
warn = 3,
|
|
||||||
|
|
||||||
/** Defects, bugs and undesired behaviour */
|
|
||||||
error = 4,
|
|
||||||
|
|
||||||
/** Unrecoverable errors */
|
|
||||||
critical = 5,
|
|
||||||
|
|
||||||
/** No logging */
|
|
||||||
off = 6,
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace details {
|
|
||||||
|
|
||||||
inline auto thread_hash_id() noexcept -> std::uint64_t
|
|
||||||
{
|
|
||||||
return static_cast<std::uint64_t>(std::hash<std::thread::id> {}(std::this_thread::get_id()));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace details
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
struct [[maybe_unused]] print
|
|
||||||
{
|
|
||||||
[[maybe_unused]] print(
|
|
||||||
Level level,
|
|
||||||
const std::source_location &location,
|
|
||||||
std::format_string<Args...> format,
|
|
||||||
Args &&...arguments
|
|
||||||
) noexcept
|
|
||||||
{
|
|
||||||
constexpr auto to_string = [](Level level, auto location) {
|
|
||||||
// clang-format off
|
|
||||||
switch (level)
|
|
||||||
{
|
|
||||||
using enum Level;
|
|
||||||
case trace : return "\033[1;37m| trc |\033[0m";
|
|
||||||
case debug : return "\033[1;36m| dbg |\033[0m";
|
|
||||||
case info : return "\033[1;32m| inf |\033[0m";
|
|
||||||
case warn : return "\033[1;33m| wrn |\033[0m";
|
|
||||||
case error : return "\033[1;31m| err |\033[0m";
|
|
||||||
case critical: return "\033[1;41m| crt |\033[0m";
|
|
||||||
case off: return "off";
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
std::unreachable();
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto path = std::filesystem::path { location.file_name() };
|
|
||||||
|
|
||||||
std::println(
|
|
||||||
"{} {} ==> {}",
|
|
||||||
to_string(level, location),
|
|
||||||
std::format("{}:{}", path.filename().c_str(), location.line()),
|
|
||||||
std::format(format, std::forward<Args>(arguments)...)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
print(Level, const std::source_location &, std::format_string<Args...>, Args &&...) noexcept
|
|
||||||
-> print<Args...>;
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
struct [[maybe_unused]] trace
|
|
||||||
{
|
|
||||||
[[maybe_unused]] trace(
|
|
||||||
std::format_string<Args...> format,
|
|
||||||
Args &&...arguments,
|
|
||||||
const std::source_location &location = std::source_location::current()
|
|
||||||
) noexcept
|
|
||||||
{
|
|
||||||
print(Level::trace, location, format, std::forward<Args>(arguments)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
trace(std::format_string<Args...>, Args &&...) noexcept -> trace<Args...>;
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
struct [[maybe_unused]] debug
|
|
||||||
{
|
|
||||||
[[maybe_unused]] debug(
|
|
||||||
std::format_string<Args...> format,
|
|
||||||
Args &&...arguments,
|
|
||||||
const std::source_location &location = std::source_location::current()
|
|
||||||
) noexcept
|
|
||||||
{
|
|
||||||
print(Level::debug, location, format, std::forward<Args>(arguments)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
debug(std::format_string<Args...>, Args &&...) noexcept -> debug<Args...>;
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
struct [[maybe_unused]] info
|
|
||||||
{
|
|
||||||
[[maybe_unused]] info(
|
|
||||||
std::format_string<Args...> format,
|
|
||||||
Args &&...arguments,
|
|
||||||
const std::source_location &location = std::source_location::current()
|
|
||||||
) noexcept
|
|
||||||
{
|
|
||||||
print(Level::info, location, format, std::forward<Args>(arguments)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
info(std::format_string<Args...>, Args &&...) noexcept -> info<Args...>;
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
struct [[maybe_unused]] warn
|
|
||||||
{
|
|
||||||
[[maybe_unused]] warn(
|
|
||||||
std::format_string<Args...> format,
|
|
||||||
Args &&...arguments,
|
|
||||||
const std::source_location &location = std::source_location::current()
|
|
||||||
) noexcept
|
|
||||||
{
|
|
||||||
print(Level::warn, location, format, std::forward<Args>(arguments)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
warn(std::format_string<Args...>, Args &&...) noexcept -> warn<Args...>;
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
struct [[maybe_unused]] error
|
|
||||||
{
|
|
||||||
[[maybe_unused]] error(
|
|
||||||
std::format_string<Args...> format,
|
|
||||||
Args &&...arguments,
|
|
||||||
const std::source_location &location = std::source_location::current()
|
|
||||||
) noexcept
|
|
||||||
{
|
|
||||||
print(Level::error, location, format, std::forward<Args>(arguments)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
error(std::format_string<Args...>, Args &&...) noexcept -> error<Args...>;
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
struct [[maybe_unused]] critical
|
|
||||||
{
|
|
||||||
[[maybe_unused]] critical(
|
|
||||||
std::format_string<Args...> format,
|
|
||||||
Args &&...arguments,
|
|
||||||
const std::source_location &location = std::source_location::current()
|
|
||||||
) noexcept
|
|
||||||
{
|
|
||||||
print(Level::critical, location, format, std::forward<Args>(arguments)...);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export template<typename... Args>
|
|
||||||
critical(std::format_string<Args...>, Args &&...) noexcept -> critical<Args...>;
|
|
||||||
|
|
||||||
} // namespace lt::log
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
import logger;
|
|
||||||
import test;
|
|
||||||
|
|
||||||
using ::lt::test::Case;
|
|
||||||
using ::lt::test::Suite;
|
|
||||||
|
|
||||||
Suite suite = [] {
|
|
||||||
Case { "no format" } = [] {
|
|
||||||
lt::log::trace("trace");
|
|
||||||
lt::log::debug("debug");
|
|
||||||
lt::log::info("info");
|
|
||||||
lt::log::warn("warn");
|
|
||||||
lt::log::error("error");
|
|
||||||
lt::log::critical("critical");
|
|
||||||
};
|
|
||||||
|
|
||||||
Case { "formatted" } = [] {
|
|
||||||
lt::log::trace("trace {}", 69);
|
|
||||||
lt::log::debug("debug {}", 69);
|
|
||||||
lt::log::info("info {}", 69);
|
|
||||||
lt::log::warn("warn {}", 69);
|
|
||||||
lt::log::error("error {}", 69);
|
|
||||||
lt::log::critical("critical {}", 69);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
1
modules/logger/private/logger.cpp
Normal file
1
modules/logger/private/logger.cpp
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#include <logger/logger.hpp>
|
||||||
89
modules/logger/public/logger.hpp
Normal file
89
modules/logger/public/logger.hpp
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <format>
|
||||||
|
#include <print>
|
||||||
|
|
||||||
|
/** Severity of a log message. */
|
||||||
|
enum class LogLvl : uint8_t
|
||||||
|
{
|
||||||
|
/** Lowest and most vebose log level, for tracing execution paths and events */
|
||||||
|
trace = 0,
|
||||||
|
|
||||||
|
/** Vebose log level, for enabling temporarily to debug */
|
||||||
|
debug = 1,
|
||||||
|
|
||||||
|
/** General information */
|
||||||
|
info = 2,
|
||||||
|
|
||||||
|
/** Things we should to be aware of and edge cases */
|
||||||
|
warn = 3,
|
||||||
|
|
||||||
|
/** Defects, bugs and undesired behaviour */
|
||||||
|
error = 4,
|
||||||
|
|
||||||
|
/** Unrecoverable errors */
|
||||||
|
critical = 5,
|
||||||
|
|
||||||
|
/** No logging */
|
||||||
|
off = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Simple console logger */
|
||||||
|
class Logger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void static show_imgui_window();
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void static log(LogLvl lvl, std::format_string<Args...> fmt, Args &&...args) noexcept
|
||||||
|
{
|
||||||
|
std::ignore = lvl;
|
||||||
|
std::println(fmt, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
void static log(LogLvl lvl, const char *message) noexcept
|
||||||
|
{
|
||||||
|
std::ignore = lvl;
|
||||||
|
std::println("{}", message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Logger() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void log_trc(std::format_string<Args...> fmt, Args &&...args) noexcept
|
||||||
|
{
|
||||||
|
Logger::log(LogLvl::trace, fmt, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void log_dbg(std::format_string<Args...> fmt, Args &&...args) noexcept
|
||||||
|
{
|
||||||
|
Logger::log(LogLvl::debug, fmt, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void log_inf(std::format_string<Args...> fmt, Args &&...args) noexcept
|
||||||
|
{
|
||||||
|
Logger::log(LogLvl::info, fmt, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void log_wrn(std::format_string<Args...> fmt, Args &&...args) noexcept
|
||||||
|
{
|
||||||
|
Logger::log(LogLvl::warn, fmt, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void log_err(std::format_string<Args...> fmt, Args &&...args) noexcept
|
||||||
|
{
|
||||||
|
Logger::log(LogLvl::error, fmt, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void log_crt(std::format_string<Args...> fmt, Args &&...args) noexcept
|
||||||
|
{
|
||||||
|
Logger::log(LogLvl::critical, fmt, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1 @@
|
||||||
add_library_module(
|
add_library_module(math)
|
||||||
NAME
|
|
||||||
math
|
|
||||||
INTERFACES
|
|
||||||
algebra.cppm
|
|
||||||
mat4.cppm
|
|
||||||
trig.cppm
|
|
||||||
vec2.cppm
|
|
||||||
vec3.cppm
|
|
||||||
vec4.cppm
|
|
||||||
components/transform.cppm)
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
export module math.components;
|
|
||||||
|
|
||||||
import math.vec3;
|
|
||||||
|
|
||||||
namespace lt::math::components {
|
|
||||||
|
|
||||||
export struct Transform
|
|
||||||
{
|
|
||||||
math::vec3 translation;
|
|
||||||
|
|
||||||
math::vec3 scale;
|
|
||||||
|
|
||||||
math::vec3 rotation;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lt::math::components
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
export module math.algebra;
|
#pragma once
|
||||||
import math.mat4;
|
|
||||||
import std;
|
#include <math/mat4.hpp>
|
||||||
|
|
||||||
namespace lt::math {
|
namespace lt::math {
|
||||||
|
|
||||||
|
|
@ -31,29 +31,25 @@ namespace lt::math {
|
||||||
*
|
*
|
||||||
* the 1 at [z][3] is to save the Z axis into the resulting W for perspective division.
|
* the 1 at [z][3] is to save the Z axis into the resulting W for perspective division.
|
||||||
*
|
*
|
||||||
* @ref Thanks to pikuma for explaining the math behind this:
|
* thanks to pikuma: https://www.youtube.com/watch?v=EqNcqBdrNyI
|
||||||
* https://www.youtube.com/watch?v=EqNcqBdrNyI
|
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr auto perspective(T field_of_view, T aspect_ratio, T z_near, T z_far)
|
constexpr auto perspective(T field_of_view, T aspect_ratio, T z_near, T z_far)
|
||||||
{
|
{
|
||||||
const T half_fov_tan = std::tan(field_of_view / static_cast<T>(2));
|
const T half_fov_tan = std::tan(field_of_view / static_cast<T>(2));
|
||||||
|
|
||||||
auto result = mat4_impl<T>::identity();
|
auto result = mat4_impl<T> { T { 0 } };
|
||||||
|
|
||||||
result[0][0] = T { 1 } / (aspect_ratio * half_fov_tan);
|
result[0][0] = T { 1 } / (aspect_ratio * half_fov_tan);
|
||||||
//
|
|
||||||
result[1][1] = T { 1 } / (half_fov_tan);
|
result[1][1] = T { 1 } / (half_fov_tan);
|
||||||
//
|
|
||||||
// result[2][2] = -(z_far + z_near) / (z_far - z_near);
|
result[2][2] = -(z_far + z_near) / (z_far - z_near);
|
||||||
//
|
|
||||||
result[2][2] = z_far / (z_far - z_near);
|
|
||||||
//
|
|
||||||
result[2][3] = -T { 1 };
|
result[2][3] = -T { 1 };
|
||||||
//
|
|
||||||
// result[3][2] = -(T { 2 } * z_far * z_near) / (z_far - z_near);
|
result[3][2] = -(T { 2 } * z_far * z_near) / (z_far - z_near);
|
||||||
result[3][2] = -(z_far * z_near) / (z_far - z_near);
|
|
||||||
//
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
export module math.mat4;
|
#pragma once
|
||||||
import math.vec3;
|
|
||||||
import math.vec4;
|
#include <math/vec3.hpp>
|
||||||
import std;
|
#include <math/vec4.hpp>
|
||||||
|
|
||||||
namespace lt::math {
|
namespace lt::math {
|
||||||
|
|
||||||
export template<typename T = float>
|
template<typename T = float>
|
||||||
struct mat4_impl
|
struct mat4_impl
|
||||||
{
|
{
|
||||||
using Column_T = vec4_impl<T>;
|
using Column_T = vec4_impl<T>;
|
||||||
|
|
||||||
constexpr explicit mat4_impl(T scalar = 0)
|
constexpr explicit mat4_impl(T scalar = 0)
|
||||||
: values(
|
: values(
|
||||||
{
|
{
|
||||||
|
|
@ -44,7 +43,7 @@ struct mat4_impl
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static constexpr auto identity() -> mat4_impl<T>
|
[[nodiscard]] constexpr auto identity() -> mat4_impl<T>
|
||||||
{
|
{
|
||||||
return mat4_impl<T> {
|
return mat4_impl<T> {
|
||||||
{ 1 }, {}, {}, {}, //
|
{ 1 }, {}, {}, {}, //
|
||||||
|
|
@ -54,12 +53,12 @@ struct mat4_impl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto operator[](std::size_t idx) -> Column_T &
|
[[nodiscard]] constexpr auto operator[](size_t idx) -> Column_T &
|
||||||
{
|
{
|
||||||
return values[idx];
|
return values[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto operator[](std::size_t idx) const -> const Column_T &
|
[[nodiscard]] constexpr auto operator[](size_t idx) const -> const Column_T &
|
||||||
{
|
{
|
||||||
return values[idx];
|
return values[idx];
|
||||||
}
|
}
|
||||||
|
|
@ -77,34 +76,34 @@ struct mat4_impl
|
||||||
std::array<Column_T, 4> values; // NOLINT
|
std::array<Column_T, 4> values; // NOLINT
|
||||||
};
|
};
|
||||||
|
|
||||||
export template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] auto translate(const vec3_impl<T> &value) -> mat4_impl<T>
|
[[nodiscard]] inline auto translate(const vec3_impl<T> &value) -> mat4_impl<T>
|
||||||
{
|
{
|
||||||
return mat4_impl<T> {};
|
return mat4_impl<T> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] auto rotate(float value, const vec3_impl<T> &xyz) -> mat4_impl<T>
|
[[nodiscard]] inline auto rotate(float value, const vec3_impl<T> &xyz) -> mat4_impl<T>
|
||||||
{
|
{
|
||||||
return mat4_impl<T> {};
|
return mat4_impl<T> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] auto scale(const vec3_impl<T> &value) -> mat4_impl<T>
|
[[nodiscard]] inline auto scale(const vec3_impl<T> &value) -> mat4_impl<T>
|
||||||
{
|
{
|
||||||
return mat4_impl<T> {};
|
return mat4_impl<T> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] auto inverse(const mat4_impl<T> &value) -> mat4_impl<T>
|
[[nodiscard]] inline auto inverse(const mat4_impl<T> &value) -> mat4_impl<T>
|
||||||
{
|
{
|
||||||
return mat4_impl<T> {};
|
return mat4_impl<T> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export using mat4 = mat4_impl<float>;
|
using mat4 = mat4_impl<float>;
|
||||||
|
|
||||||
export using imat4 = mat4_impl<std::int32_t>;
|
using imat4 = mat4_impl<int32_t>;
|
||||||
|
|
||||||
export using umat4 = mat4_impl<std::uint32_t>;
|
using umat4 = mat4_impl<uint32_t>;
|
||||||
|
|
||||||
} // namespace lt::math
|
} // namespace lt::math
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
export module math.trig;
|
#pragma once
|
||||||
|
|
||||||
namespace lt::math {
|
namespace lt::math {
|
||||||
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
export module math.vec2;
|
#pragma once
|
||||||
|
|
||||||
import std;
|
|
||||||
|
|
||||||
namespace lt::math {
|
namespace lt::math {
|
||||||
|
|
||||||
export template<typename T = float>
|
template<typename T = float>
|
||||||
struct vec2_impl
|
struct vec2_impl
|
||||||
{
|
{
|
||||||
constexpr vec2_impl(): x(), y()
|
constexpr vec2_impl(): x(), y()
|
||||||
|
|
@ -59,15 +57,15 @@ struct vec2_impl
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export using vec2 = vec2_impl<float>;
|
using vec2 = vec2_impl<float>;
|
||||||
|
|
||||||
export using ivec2 = vec2_impl<std::int32_t>;
|
using ivec2 = vec2_impl<int32_t>;
|
||||||
|
|
||||||
export using uvec2 = vec2_impl<std::uint32_t>;
|
using uvec2 = vec2_impl<uint32_t>;
|
||||||
|
|
||||||
} // namespace lt::math
|
} // namespace lt::math
|
||||||
|
|
||||||
export template<typename T>
|
template<typename T>
|
||||||
struct std::formatter<lt::math::vec2_impl<T>>
|
struct std::formatter<lt::math::vec2_impl<T>>
|
||||||
{
|
{
|
||||||
constexpr auto parse(std::format_parse_context &context)
|
constexpr auto parse(std::format_parse_context &context)
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
export module math.vec3;
|
#pragma once
|
||||||
|
|
||||||
import math.vec2;
|
#include <cstdint>
|
||||||
import std;
|
#include <math/vec2.hpp>
|
||||||
|
|
||||||
namespace lt::math {
|
namespace lt::math {
|
||||||
|
|
||||||
export template<typename T = float>
|
template<typename T = float>
|
||||||
struct vec3_impl
|
struct vec3_impl
|
||||||
{
|
{
|
||||||
constexpr vec3_impl(): x(), y(), z()
|
constexpr vec3_impl(): x(), y(), z()
|
||||||
|
|
@ -61,11 +61,11 @@ struct vec3_impl
|
||||||
T z; // NOLINT
|
T z; // NOLINT
|
||||||
};
|
};
|
||||||
|
|
||||||
export using vec3 = vec3_impl<float>;
|
using vec3 = vec3_impl<float>;
|
||||||
|
|
||||||
export using ivec3 = vec3_impl<std::int32_t>;
|
using ivec3 = vec3_impl<int32_t>;
|
||||||
|
|
||||||
export using uvec3 = vec3_impl<std::uint32_t>;
|
using uvec3 = vec3_impl<uint32_t>;
|
||||||
|
|
||||||
} // namespace lt::math
|
} // namespace lt::math
|
||||||
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
export module math.vec4;
|
#pragma once
|
||||||
import math.vec2;
|
|
||||||
import math.vec3;
|
#include <array>
|
||||||
import std;
|
#include <cstdint>
|
||||||
|
|
||||||
namespace lt::math {
|
namespace lt::math {
|
||||||
|
|
||||||
export template<typename T = float>
|
template<typename T = float>
|
||||||
struct vec4_impl
|
struct vec4_impl
|
||||||
{
|
{
|
||||||
constexpr vec4_impl(): x(), y(), z(), w()
|
constexpr vec4_impl(): x(), y(), z(), w()
|
||||||
|
|
@ -40,12 +40,12 @@ struct vec4_impl
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto operator[](std::size_t idx) -> T &
|
[[nodiscard]] constexpr auto operator[](size_t idx) -> T &
|
||||||
{
|
{
|
||||||
return values[idx];
|
return values[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr auto operator[](std::size_t idx) const -> const T &
|
[[nodiscard]] constexpr auto operator[](size_t idx) const -> const T &
|
||||||
{
|
{
|
||||||
return values[idx];
|
return values[idx];
|
||||||
}
|
}
|
||||||
|
|
@ -86,15 +86,15 @@ struct vec4_impl
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export using vec4 = vec4_impl<float>;
|
using vec4 = vec4_impl<float>;
|
||||||
|
|
||||||
export using ivec4 = vec4_impl<std::int32_t>;
|
using ivec4 = vec4_impl<int32_t>;
|
||||||
|
|
||||||
export using uvec4 = vec4_impl<std::uint32_t>;
|
using uvec4 = vec4_impl<uint32_t>;
|
||||||
|
|
||||||
} // namespace lt::math
|
} // namespace lt::math
|
||||||
|
|
||||||
export template<typename T>
|
template<typename T>
|
||||||
struct std::formatter<lt::math::vec4_impl<T>>
|
struct std::formatter<lt::math::vec4_impl<T>>
|
||||||
{
|
{
|
||||||
constexpr auto parse(std::format_parse_context &context)
|
constexpr auto parse(std::format_parse_context &context)
|
||||||
|
|
@ -1,2 +1 @@
|
||||||
add_library_module(NAME memory INTERFACES null_on_move.cppm reference.cppm
|
add_library_module(memory)
|
||||||
scope.cppm)
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
export module memory.null_on_move;
|
#pragma once
|
||||||
|
|
||||||
import std;
|
|
||||||
|
|
||||||
namespace lt::memory {
|
namespace lt::memory {
|
||||||
|
|
||||||
/** Holds an `Underlying_T`, assigns it to `null_value` when this object is moved.
|
/** Holds an `Underlying_T`, assigns it to `null_value` when this object is moved.
|
||||||
*
|
*
|
||||||
* @note For avoiding the need to explicitly implement the move constructor for objects that hold
|
* @note For avoiding the need to explicitly implement the move constructor for objects that hold
|
||||||
* Vulkan objects. But may serve other purposes, hence why I kept the implementation generic.
|
* Vulkan objects. But may server other purposes, hence why I kept the implementation generic.
|
||||||
*/
|
*/
|
||||||
template<typename Underlying_T, Underlying_T null_value = nullptr>
|
template<typename Underlying_T, Underlying_T null_value = nullptr>
|
||||||
class NullOnMove
|
class NullOnMove
|
||||||
|
|
@ -79,9 +77,9 @@ public:
|
||||||
return m_value;
|
return m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator std::uint64_t() const
|
operator uint64_t() const
|
||||||
{
|
{
|
||||||
return (std::uint64_t)m_value;
|
return (uint64_t)m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto get() -> Underlying_T
|
[[nodiscard]] auto get() -> Underlying_T
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
export module memory.reference;
|
#pragma once
|
||||||
|
|
||||||
import std;
|
#include <memory/reference.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace lt::memory {
|
namespace lt::memory {
|
||||||
|
|
||||||
|
|
@ -9,21 +10,21 @@ namespace lt::memory {
|
||||||
* @note Currently just an alias, might turn into an implementation later.
|
* @note Currently just an alias, might turn into an implementation later.
|
||||||
* @ref https://en.cppreference.com/w/cpp/memory/shared_ptr.html
|
* @ref https://en.cppreference.com/w/cpp/memory/shared_ptr.html
|
||||||
*/
|
*/
|
||||||
export template<typename T>
|
template<typename t>
|
||||||
using Ref = std::shared_ptr<T>;
|
using Ref = std::shared_ptr<t>;
|
||||||
|
|
||||||
/** Allocates memory for an `Underlying_T` and directly constructs it there.
|
/** Allocates memory for an `Underlying_T` and directly constructs it there.
|
||||||
*
|
*
|
||||||
* @return A Ref<Underlying_T> to the constructed object.
|
* @return A Ref<Underlying_T> to the constructed object.
|
||||||
*/
|
*/
|
||||||
export template<typename Underlying_T, typename... Args>
|
template<typename Underlying_T, typename... Args>
|
||||||
constexpr Ref<Underlying_T> create_ref(Args &&...args)
|
constexpr Ref<Underlying_T> create_ref(Args &&...args)
|
||||||
{
|
{
|
||||||
return std::make_shared<Underlying_T>(std::forward<Args>(args)...);
|
return std::make_shared<Underlying_T>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converts c-style pointer of type `Underlying_T` to a `Ref<Underlying_T>`. */
|
/** Converts c-style pointer of type `Underlying_T` to a `Ref<Underlying_T>`. */
|
||||||
export template<typename Underlying_T>
|
template<typename Underlying_T>
|
||||||
constexpr Ref<Underlying_T> make_ref(Underlying_T *raw_pointer)
|
constexpr Ref<Underlying_T> make_ref(Underlying_T *raw_pointer)
|
||||||
{
|
{
|
||||||
return Ref<Underlying_T>(raw_pointer);
|
return Ref<Underlying_T>(raw_pointer);
|
||||||
|
|
@ -1,29 +1,30 @@
|
||||||
export module memory.scope;
|
#pragma once
|
||||||
|
|
||||||
import std;
|
#include <memory/scope.hpp>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace lt::memory {
|
namespace lt::memory {
|
||||||
|
|
||||||
/** @brief Wrapper around std::unique_ptr.
|
/** Wrapper around std::unique_ptr.
|
||||||
*
|
*
|
||||||
* @note Currently just an alias, might turn into an implementation later.
|
* @note Currently just an alias, might turn into an implementation later.
|
||||||
* @ref https://en.cppreference.com/w/cpp/memory/unique_ptr.html
|
* @ref https://en.cppreference.com/w/cpp/memory/unique_ptr.html
|
||||||
*/
|
*/
|
||||||
export template<typename t>
|
template<typename t>
|
||||||
using Scope = std::unique_ptr<t>;
|
using Scope = std::unique_ptr<t>;
|
||||||
|
|
||||||
/** Allocates memory for an `Underlying_T` and directly constructs it there.
|
/** Allocates memory for an `Underlying_T` and directly constructs it there.
|
||||||
*
|
*
|
||||||
* @return A Scope<Underlying_T> to the constructed object.
|
* @return A Scope<Underlying_T> to the constructed object.
|
||||||
*/
|
*/
|
||||||
export template<typename Underlying_T, typename... Args>
|
template<typename Underlying_T, typename... Args>
|
||||||
constexpr Scope<Underlying_T> create_scope(Args &&...args)
|
constexpr Scope<Underlying_T> create_scope(Args &&...args)
|
||||||
{
|
{
|
||||||
return std::make_unique<Underlying_T>(std::forward<Args>(args)...);
|
return std::make_unique<Underlying_T>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converts c-style pointer of type `Underlying_T` to a `Scope<Underlying_T>`. */
|
/** Converts c-style pointer of type `Underlying_T` to a `Scope<Underlying_T>`. */
|
||||||
export template<typename Underlying_T>
|
template<typename Underlying_T>
|
||||||
constexpr Scope<Underlying_T> make_scope(Underlying_T *raw_pointer)
|
constexpr Scope<Underlying_T> make_scope(Underlying_T *raw_pointer)
|
||||||
{
|
{
|
||||||
return Scope<Underlying_T>(raw_pointer);
|
return Scope<Underlying_T>(raw_pointer);
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
add_library_module(libmirror)
|
add_library_module(libmirror)
|
||||||
target_link_libraries(libmirror INTERFACE app time input surface renderer
|
target_link_libraries(libmirror INTERFACE app time input surface renderer)
|
||||||
camera)
|
|
||||||
|
|
||||||
add_test_module(
|
add_test_module(
|
||||||
libmirror layers/editor_layer.test.cpp panels/asset_browser.test.cpp
|
libmirror layers/editor_layer.test.cpp panels/asset_browser.test.cpp
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,13 @@
|
||||||
#include <app/application.hpp>
|
#include <app/application.hpp>
|
||||||
#include <app/entrypoint.hpp>
|
#include <app/entrypoint.hpp>
|
||||||
#include <app/system.hpp>
|
#include <app/system.hpp>
|
||||||
#include <camera/components.hpp>
|
|
||||||
#include <ecs/entity.hpp>
|
#include <ecs/entity.hpp>
|
||||||
#include <input/components.hpp>
|
#include <input/components.hpp>
|
||||||
#include <input/system.hpp>
|
#include <input/system.hpp>
|
||||||
#include <math/components/transform.hpp>
|
|
||||||
#include <math/trig.hpp>
|
|
||||||
#include <math/vec2.hpp>
|
#include <math/vec2.hpp>
|
||||||
#include <memory/reference.hpp>
|
#include <memory/reference.hpp>
|
||||||
#include <memory/scope.hpp>
|
#include <memory/scope.hpp>
|
||||||
#include <renderer/components/messenger.hpp>
|
#include <renderer/components/messenger.hpp>
|
||||||
#include <renderer/components/sprite.hpp>
|
|
||||||
#include <renderer/system.hpp>
|
#include <renderer/system.hpp>
|
||||||
#include <surface/events/keyboard.hpp>
|
#include <surface/events/keyboard.hpp>
|
||||||
#include <surface/events/surface.hpp>
|
#include <surface/events/surface.hpp>
|
||||||
|
|
@ -32,7 +28,7 @@ void renderer_callback(
|
||||||
std::ignore = message_type;
|
std::ignore = message_type;
|
||||||
std::ignore = user_data;
|
std::ignore = user_data;
|
||||||
|
|
||||||
log::debug("RENDERER CALLBACK: {}", data.message);
|
log_dbg("RENDERER CALLBACK: {}", data.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MirrorSystem: public lt::app::ISystem
|
class MirrorSystem: public lt::app::ISystem
|
||||||
|
|
@ -70,18 +66,13 @@ public:
|
||||||
const auto &[x, y] = surface.get_position();
|
const auto &[x, y] = surface.get_position();
|
||||||
const auto &[width, height] = surface.get_resolution();
|
const auto &[width, height] = surface.get_resolution();
|
||||||
|
|
||||||
|
|
||||||
if (input.get_action(m_quit_action_key).state == State::active)
|
if (input.get_action(m_quit_action_key).state == State::active)
|
||||||
{
|
{
|
||||||
should_quit = true;
|
should_quit = true;
|
||||||
}
|
}
|
||||||
if (input.get_action(m_debug_action_keys[0]).state == State::active)
|
if (input.get_action(m_debug_action_keys[0]).state == State::active)
|
||||||
{
|
{
|
||||||
for (auto &[id, camera] :
|
surface.push_request(surface::ModifyPositionRequest({ x + 5, y + 5 }));
|
||||||
m_registry->view<lt::camera::components::PerspectiveCamera>())
|
|
||||||
{
|
|
||||||
camera.vertical_fov += (static_cast<float>(tick.delta_time.count()) * 40.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.get_action(m_debug_action_keys[1]).state == State::active)
|
if (input.get_action(m_debug_action_keys[1]).state == State::active)
|
||||||
|
|
@ -147,7 +138,7 @@ public:
|
||||||
|
|
||||||
void on_window_close()
|
void on_window_close()
|
||||||
{
|
{
|
||||||
log::info("Window close requested...");
|
log_inf("Window close requested...");
|
||||||
|
|
||||||
unregister_system(m_input_system);
|
unregister_system(m_input_system);
|
||||||
unregister_system(m_surface_system);
|
unregister_system(m_surface_system);
|
||||||
|
|
@ -228,35 +219,6 @@ public:
|
||||||
.callback = &renderer_callback,
|
.callback = &renderer_callback,
|
||||||
.user_data = this,
|
.user_data = this,
|
||||||
} });
|
} });
|
||||||
|
|
||||||
m_sprite_id = m_editor_registry->create_entity();
|
|
||||||
|
|
||||||
m_editor_registry->add(
|
|
||||||
m_sprite_id,
|
|
||||||
renderer::components::Sprite { .color = lt::math::vec3 { 1.0f, 0.0f, 0.0f } }
|
|
||||||
);
|
|
||||||
m_editor_registry->add(
|
|
||||||
m_sprite_id,
|
|
||||||
math::components::Transform {
|
|
||||||
.translation = { -5.0, -5.0, 0.5 },
|
|
||||||
.scale = { 5.0, 5.0, 1.0 },
|
|
||||||
.rotation = {},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
m_camera_id = m_editor_registry->create_entity();
|
|
||||||
|
|
||||||
m_editor_registry->add(
|
|
||||||
m_camera_id,
|
|
||||||
camera::components::PerspectiveCamera {
|
|
||||||
.vertical_fov = math::radians(90.0f),
|
|
||||||
.near_plane = 0.1f,
|
|
||||||
.far_plane = 30.0,
|
|
||||||
.aspect_ratio = 1.0f,
|
|
||||||
.background_color = math::vec4(1.0, 0.0, 0.0, 1.0),
|
|
||||||
.is_primary = true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_input_system()
|
void setup_input_system()
|
||||||
|
|
@ -283,10 +245,6 @@ private:
|
||||||
memory::Ref<MirrorSystem> m_mirror_system;
|
memory::Ref<MirrorSystem> m_mirror_system;
|
||||||
|
|
||||||
lt::ecs::EntityId m_window = lt::ecs::null_entity;
|
lt::ecs::EntityId m_window = lt::ecs::null_entity;
|
||||||
|
|
||||||
lt::ecs::EntityId m_camera_id = lt::ecs::null_entity;
|
|
||||||
|
|
||||||
lt::ecs::EntityId m_sprite_id = lt::ecs::null_entity;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto app::create_application() -> memory::Scope<app::Application>
|
auto app::create_application() -> memory::Scope<app::Application>
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ void AssetBrowserPanel::on_user_interface_update()
|
||||||
))
|
))
|
||||||
{
|
{
|
||||||
auto serializer = SceneSerializer { m_active_scene };
|
auto serializer = SceneSerializer { m_active_scene };
|
||||||
log::info("Attempting to deserialize: {}", path.string());
|
log_inf("Attempting to deserialize: {}", path.string());
|
||||||
serializer.deserialize(path.string());
|
serializer.deserialize(path.string());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -8,29 +8,21 @@ add_library_module(
|
||||||
backend/vk/context/instance.cpp
|
backend/vk/context/instance.cpp
|
||||||
backend/vk/context/surface.cpp
|
backend/vk/context/surface.cpp
|
||||||
backend/vk/context/swapchain.cpp
|
backend/vk/context/swapchain.cpp
|
||||||
backend/vk/data/buffer.cpp
|
|
||||||
backend/vk/renderer/pass.cpp
|
backend/vk/renderer/pass.cpp
|
||||||
backend/vk/renderer/renderer.cpp
|
backend/vk/renderer/renderer.cpp
|
||||||
# frontend
|
# Vulkan - frontend
|
||||||
frontend/messenger.cpp
|
frontend/messenger.cpp
|
||||||
frontend/context/device.cpp
|
frontend/context/device.cpp
|
||||||
frontend/context/gpu.cpp
|
frontend/context/gpu.cpp
|
||||||
frontend/context/instance.cpp
|
frontend/context/instance.cpp
|
||||||
frontend/context/surface.cpp
|
frontend/context/surface.cpp
|
||||||
frontend/context/swapchain.cpp
|
frontend/context/swapchain.cpp
|
||||||
frontend/data/buffer.cpp
|
|
||||||
frontend/renderer/renderer.cpp
|
frontend/renderer/renderer.cpp
|
||||||
frontend/renderer/pass.cpp)
|
frontend/renderer/pass.cpp)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
renderer
|
renderer
|
||||||
PUBLIC app
|
PUBLIC app ecs memory assets time bitwise
|
||||||
ecs
|
|
||||||
memory
|
|
||||||
assets
|
|
||||||
time
|
|
||||||
bitwise
|
|
||||||
camera
|
|
||||||
PRIVATE surface pthread)
|
PRIVATE surface pthread)
|
||||||
|
|
||||||
add_test_module(
|
add_test_module(
|
||||||
|
|
@ -42,10 +34,11 @@ add_test_module(
|
||||||
frontend/context/surface.test.cpp
|
frontend/context/surface.test.cpp
|
||||||
frontend/context/device.test.cpp
|
frontend/context/device.test.cpp
|
||||||
frontend/context/swapchain.test.cpp
|
frontend/context/swapchain.test.cpp
|
||||||
frontend/data/buffer.test.cpp
|
frontend/renderer/pass.test.cpp
|
||||||
# frontend/renderer/pass.test.cpp
|
|
||||||
frontend/renderer/renderer.test.cpp
|
frontend/renderer/renderer.test.cpp
|
||||||
# backend specific tests -- vk
|
# backend specific tests -- vk
|
||||||
backend/vk/context/instance.test.cpp)
|
backend/vk/context/instance.test.cpp
|
||||||
|
# backend specific tests -- dx backend specific tests -- mt
|
||||||
|
)
|
||||||
|
|
||||||
target_link_libraries(renderer_tests PRIVATE surface pthread)
|
target_link_libraries(renderer_tests PRIVATE surface pthread)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
//
|
//
|
||||||
#include <logger/logger.hpp>
|
|
||||||
#include <renderer/backend/vk/context/device.hpp>
|
#include <renderer/backend/vk/context/device.hpp>
|
||||||
#include <renderer/backend/vk/context/gpu.hpp>
|
#include <renderer/backend/vk/context/gpu.hpp>
|
||||||
#include <renderer/backend/vk/context/surface.hpp>
|
#include <renderer/backend/vk/context/surface.hpp>
|
||||||
|
|
@ -48,8 +47,8 @@ Device::~Device()
|
||||||
}
|
}
|
||||||
catch (const std::exception &exp)
|
catch (const std::exception &exp)
|
||||||
{
|
{
|
||||||
log::error("Failed to destroy vk device:");
|
log_err("Failed to destroy vk device:");
|
||||||
log::error("\twhat: {}", exp.what());
|
log_err("\twhat: {}", exp.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,107 +75,20 @@ void Device::initialize_logical_device()
|
||||||
|
|
||||||
auto extensions = std::vector<const char *> {
|
auto extensions = std::vector<const char *> {
|
||||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||||
VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME,
|
|
||||||
VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
auto descriptor_indexing_features = m_gpu->get_descriptor_indexing_features();
|
auto device_info = VkDeviceCreateInfo {
|
||||||
log::debug("");
|
|
||||||
|
|
||||||
log::debug(
|
|
||||||
"shaderInputAttachmentArrayDynamicIndexing: {}",
|
|
||||||
descriptor_indexing_features.shaderInputAttachmentArrayDynamicIndexing
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" shaderUniformTexelBufferArrayDynamicIndexing: {}",
|
|
||||||
descriptor_indexing_features.shaderUniformTexelBufferArrayDynamicIndexing
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" shaderStorageTexelBufferArrayDynamicIndexing: {}",
|
|
||||||
descriptor_indexing_features.shaderStorageTexelBufferArrayDynamicIndexing
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" shaderUniformBufferArrayNonUniformIndexing: {}",
|
|
||||||
descriptor_indexing_features.shaderUniformBufferArrayNonUniformIndexing
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" shaderSampledImageArrayNonUniformIndexing: {}",
|
|
||||||
descriptor_indexing_features.shaderSampledImageArrayNonUniformIndexing
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" shaderStorageBufferArrayNonUniformIndexing: {}",
|
|
||||||
descriptor_indexing_features.shaderStorageBufferArrayNonUniformIndexing
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" shaderStorageImageArrayNonUniformIndexing: {}",
|
|
||||||
descriptor_indexing_features.shaderStorageImageArrayNonUniformIndexing
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" shaderInputAttachmentArrayNonUniformIndexing: {}",
|
|
||||||
descriptor_indexing_features.shaderInputAttachmentArrayNonUniformIndexing
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" shaderUniformTexelBufferArrayNonUniformIndexing: {}",
|
|
||||||
descriptor_indexing_features.shaderUniformTexelBufferArrayNonUniformIndexing
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" shaderStorageTexelBufferArrayNonUniformIndexing: {}",
|
|
||||||
descriptor_indexing_features.shaderStorageTexelBufferArrayNonUniformIndexing
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" descriptorBindingUniformBufferUpdateAfterBind: {}",
|
|
||||||
descriptor_indexing_features.descriptorBindingUniformBufferUpdateAfterBind
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" descriptorBindingSampledImageUpdateAfterBind: {}",
|
|
||||||
descriptor_indexing_features.descriptorBindingSampledImageUpdateAfterBind
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" descriptorBindingStorageImageUpdateAfterBind: {}",
|
|
||||||
descriptor_indexing_features.descriptorBindingStorageImageUpdateAfterBind
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" descriptorBindingStorageBufferUpdateAfterBind: {}",
|
|
||||||
descriptor_indexing_features.descriptorBindingStorageBufferUpdateAfterBind
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" descriptorBindingUniformTexelBufferUpdateAfterBind: {}",
|
|
||||||
descriptor_indexing_features.descriptorBindingUniformTexelBufferUpdateAfterBind
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" descriptorBindingStorageTexelBufferUpdateAfterBind: {}",
|
|
||||||
descriptor_indexing_features.descriptorBindingStorageTexelBufferUpdateAfterBind
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" descriptorBindingUpdateUnusedWhilePending: {}",
|
|
||||||
descriptor_indexing_features.descriptorBindingUpdateUnusedWhilePending
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" descriptorBindingPartiallyBound: {}",
|
|
||||||
descriptor_indexing_features.descriptorBindingPartiallyBound
|
|
||||||
);
|
|
||||||
log::debug(
|
|
||||||
" descriptorBindingVariableDescriptorCount: {}",
|
|
||||||
descriptor_indexing_features.descriptorBindingVariableDescriptorCount
|
|
||||||
);
|
|
||||||
log::debug(" runtimeDescriptorArray: {}", descriptor_indexing_features.runtimeDescriptorArray);
|
|
||||||
const auto dynamic_rendering_features = VkPhysicalDeviceDynamicRenderingFeatures {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES,
|
|
||||||
.pNext = &descriptor_indexing_features,
|
|
||||||
.dynamicRendering = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
m_device = m_gpu->create_device(
|
|
||||||
VkDeviceCreateInfo {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
.pNext = &dynamic_rendering_features,
|
|
||||||
.queueCreateInfoCount = static_cast<uint32_t>(queue_infos.size()),
|
.queueCreateInfoCount = static_cast<uint32_t>(queue_infos.size()),
|
||||||
.pQueueCreateInfos = queue_infos.data(),
|
.pQueueCreateInfos = queue_infos.data(),
|
||||||
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
|
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
|
||||||
.ppEnabledExtensionNames = extensions.data(),
|
.ppEnabledExtensionNames = extensions.data(),
|
||||||
.pEnabledFeatures = &physical_device_features,
|
.pEnabledFeatures = &physical_device_features,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
ensure(
|
||||||
|
!vk_create_device(m_gpu->vk(), &device_info, nullptr, &m_device),
|
||||||
|
"Failed to create logical vulkan device"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,31 +207,6 @@ void Device::wait_for_fences(std::span<VkFence> fences) const
|
||||||
return images;
|
return images;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto Device::get_memory_requirements(VkBuffer buffer) const -> VkMemoryRequirements
|
|
||||||
{
|
|
||||||
auto requirements = VkMemoryRequirements {};
|
|
||||||
vk_get_buffer_memory_requirements(m_device, buffer, &requirements);
|
|
||||||
return requirements;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::bind_memory(VkBuffer buffer, VkDeviceMemory memory, size_t offset /* = 0u */) const
|
|
||||||
{
|
|
||||||
vkc(vk_bind_buffer_memory(m_device, buffer, memory, offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Device::map_memory(VkDeviceMemory memory, size_t size, size_t offset) const
|
|
||||||
-> std::span<std::byte>
|
|
||||||
{
|
|
||||||
void *data = {};
|
|
||||||
vkc(vk_map_memory(m_device, memory, offset, size, {}, &data));
|
|
||||||
return { std::bit_cast<std::byte *>(data), size };
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::unmap_memory(VkDeviceMemory memory)
|
|
||||||
{
|
|
||||||
vk_unmap_memory(m_device, memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Device::create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR
|
[[nodiscard]] auto Device::create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR
|
||||||
{
|
{
|
||||||
auto *swapchain = VkSwapchainKHR {};
|
auto *swapchain = VkSwapchainKHR {};
|
||||||
|
|
@ -364,19 +251,9 @@ void Device::unmap_memory(VkDeviceMemory memory)
|
||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto Device::create_pipeline_layout(
|
[[nodiscard]] auto Device::create_pipeline_layout(VkPipelineLayoutCreateInfo info) const
|
||||||
std::vector<VkDescriptorSetLayout> descriptor_set_layout,
|
-> VkPipelineLayout
|
||||||
std::vector<VkPushConstantRange> push_constant_ranges
|
|
||||||
) const -> VkPipelineLayout
|
|
||||||
{
|
{
|
||||||
auto info = VkPipelineLayoutCreateInfo {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
||||||
.setLayoutCount = static_cast<uint32_t>(descriptor_set_layout.size()),
|
|
||||||
.pSetLayouts = descriptor_set_layout.data(),
|
|
||||||
.pushConstantRangeCount = static_cast<uint32_t>(push_constant_ranges.size()),
|
|
||||||
.pPushConstantRanges = push_constant_ranges.data(),
|
|
||||||
};
|
|
||||||
|
|
||||||
auto *pipeline_layout = VkPipelineLayout {};
|
auto *pipeline_layout = VkPipelineLayout {};
|
||||||
vkc(vk_create_pipeline_layout(m_device, &info, nullptr, &pipeline_layout));
|
vkc(vk_create_pipeline_layout(m_device, &info, nullptr, &pipeline_layout));
|
||||||
return pipeline_layout;
|
return pipeline_layout;
|
||||||
|
|
@ -422,28 +299,6 @@ void Device::unmap_memory(VkDeviceMemory memory)
|
||||||
return fences;
|
return fences;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto Device::create_buffer(VkBufferCreateInfo info) const -> VkBuffer
|
|
||||||
{
|
|
||||||
auto *buffer = VkBuffer {};
|
|
||||||
vkc(vk_create_buffer(m_device, &info, nullptr, &buffer));
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
[[nodiscard]] auto Device::create_desscriptor_pool(VkDescriptorPoolCreateInfo info) const
|
|
||||||
-> VkDescriptorPool
|
|
||||||
{
|
|
||||||
auto *pool = VkDescriptorPool {};
|
|
||||||
vkc(vk_create_descriptor_pool(m_device, &info, nullptr, &pool));
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Device::create_descriptor_set_layout(VkDescriptorSetLayoutCreateInfo info) const
|
|
||||||
-> VkDescriptorSetLayout
|
|
||||||
{
|
|
||||||
auto *layout = VkDescriptorSetLayout {};
|
|
||||||
vkc(vk_create_descriptor_set_layout(m_device, &info, nullptr, &layout));
|
|
||||||
return layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Device::allocate_command_buffers(VkCommandBufferAllocateInfo info) const
|
[[nodiscard]] auto Device::allocate_command_buffers(VkCommandBufferAllocateInfo info) const
|
||||||
-> std::vector<VkCommandBuffer>
|
-> std::vector<VkCommandBuffer>
|
||||||
{
|
{
|
||||||
|
|
@ -452,34 +307,6 @@ void Device::unmap_memory(VkDeviceMemory memory)
|
||||||
return command_buffers;
|
return command_buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto Device::allocate_memory(VkMemoryAllocateInfo info) const -> VkDeviceMemory
|
|
||||||
{
|
|
||||||
auto *memory = VkDeviceMemory {};
|
|
||||||
vkc(vk_allocate_memory(m_device, &info, nullptr, &memory));
|
|
||||||
return memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Device::allocate_descriptor_set(VkDescriptorSetAllocateInfo info) const
|
|
||||||
-> VkDescriptorSet
|
|
||||||
{
|
|
||||||
auto *descriptor_set = VkDescriptorSet {};
|
|
||||||
vkc(vk_allocate_descriptor_sets(m_device, &info, &descriptor_set));
|
|
||||||
return descriptor_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::free_memory(VkDeviceMemory memory) const
|
|
||||||
{
|
|
||||||
vk_free_memory(m_device, memory, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::free_descriptor_set(
|
|
||||||
VkDescriptorPool descriptor_pool,
|
|
||||||
VkDescriptorSet descriptor_set
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
vkc(vk_free_descriptor_sets(m_device, descriptor_pool, 1, &descriptor_set));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::destroy_swapchain(VkSwapchainKHR swapchain) const
|
void Device::destroy_swapchain(VkSwapchainKHR swapchain) const
|
||||||
{
|
{
|
||||||
vk_destroy_swapchain_khr(m_device, swapchain, m_allocator);
|
vk_destroy_swapchain_khr(m_device, swapchain, m_allocator);
|
||||||
|
|
@ -562,19 +389,4 @@ void Device::destroy_fences(std::span<VkFence> fences) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::destroy_buffer(VkBuffer buffer) const
|
|
||||||
{
|
|
||||||
vk_destroy_buffer(m_device, buffer, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::destroy_descriptor_set_layout(VkDescriptorSetLayout layout) const
|
|
||||||
{
|
|
||||||
vk_destroy_descriptor_set_layout(m_device, layout, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::destroy_descriptor_pool(VkDescriptorPool pool) const
|
|
||||||
{
|
|
||||||
vk_destroy_descriptor_pool(m_device, pool, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace lt::renderer::vk
|
} // namespace lt::renderer::vk
|
||||||
|
|
|
||||||
|
|
@ -96,16 +96,6 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] auto get_swapchain_images(VkSwapchainKHR swapchain) const -> std::vector<VkImage>;
|
[[nodiscard]] auto get_swapchain_images(VkSwapchainKHR swapchain) const -> std::vector<VkImage>;
|
||||||
|
|
||||||
[[nodiscard]] auto get_memory_requirements(VkBuffer buffer) const -> VkMemoryRequirements;
|
|
||||||
|
|
||||||
/** binders / mappers */
|
|
||||||
void bind_memory(VkBuffer buffer, VkDeviceMemory memory, size_t offset = 0u) const;
|
|
||||||
|
|
||||||
[[nodiscard]] auto map_memory(VkDeviceMemory memory, size_t size, size_t offset) const
|
|
||||||
-> std::span<std::byte>;
|
|
||||||
|
|
||||||
void unmap_memory(VkDeviceMemory memory);
|
|
||||||
|
|
||||||
/** create functions */
|
/** create functions */
|
||||||
[[nodiscard]] auto create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR;
|
[[nodiscard]] auto create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR;
|
||||||
|
|
||||||
|
|
@ -118,10 +108,8 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] auto create_pass(VkRenderPassCreateInfo info) const -> VkRenderPass;
|
[[nodiscard]] auto create_pass(VkRenderPassCreateInfo info) const -> VkRenderPass;
|
||||||
|
|
||||||
[[nodiscard]] auto create_pipeline_layout(
|
[[nodiscard]] auto create_pipeline_layout(VkPipelineLayoutCreateInfo info) const
|
||||||
std::vector<VkDescriptorSetLayout> descriptor_set_layout,
|
-> VkPipelineLayout;
|
||||||
std::vector<VkPushConstantRange> push_constant_ranges
|
|
||||||
) const -> VkPipelineLayout;
|
|
||||||
|
|
||||||
[[nodiscard]] auto create_shader_module(VkShaderModuleCreateInfo info) const -> VkShaderModule;
|
[[nodiscard]] auto create_shader_module(VkShaderModuleCreateInfo info) const -> VkShaderModule;
|
||||||
|
|
||||||
|
|
@ -132,31 +120,10 @@ public:
|
||||||
[[nodiscard]] auto create_fences(VkFenceCreateInfo info, uint32_t count) const
|
[[nodiscard]] auto create_fences(VkFenceCreateInfo info, uint32_t count) const
|
||||||
-> std::vector<VkFence>;
|
-> std::vector<VkFence>;
|
||||||
|
|
||||||
[[nodiscard]] auto create_buffer(VkBufferCreateInfo info) const -> VkBuffer;
|
|
||||||
|
|
||||||
[[nodiscard]] auto create_descriptor_set_layout(VkDescriptorSetLayoutCreateInfo info) const
|
|
||||||
-> VkDescriptorSetLayout;
|
|
||||||
|
|
||||||
[[nodiscard]] auto create_desscriptor_pool(VkDescriptorPoolCreateInfo info) const
|
|
||||||
-> VkDescriptorPool;
|
|
||||||
|
|
||||||
/** allocation functions */
|
/** allocation functions */
|
||||||
[[nodiscard]] auto allocate_memory(VkMemoryAllocateInfo info) const -> VkDeviceMemory;
|
|
||||||
|
|
||||||
[[nodiscard]] auto allocate_command_buffers(VkCommandBufferAllocateInfo info) const
|
[[nodiscard]] auto allocate_command_buffers(VkCommandBufferAllocateInfo info) const
|
||||||
-> std::vector<VkCommandBuffer>;
|
-> std::vector<VkCommandBuffer>;
|
||||||
|
|
||||||
[[nodiscard]] auto allocate_descriptor_set(VkDescriptorSetAllocateInfo info) const
|
|
||||||
-> VkDescriptorSet;
|
|
||||||
|
|
||||||
/** de-allocation functions */
|
|
||||||
void free_memory(VkDeviceMemory memory) const;
|
|
||||||
|
|
||||||
void free_descriptor_set(
|
|
||||||
VkDescriptorPool descriptor_pool,
|
|
||||||
VkDescriptorSet descriptor_set
|
|
||||||
) const;
|
|
||||||
|
|
||||||
/** destroy functions */
|
/** destroy functions */
|
||||||
void destroy_swapchain(VkSwapchainKHR swapchain) const;
|
void destroy_swapchain(VkSwapchainKHR swapchain) const;
|
||||||
|
|
||||||
|
|
@ -186,12 +153,6 @@ public:
|
||||||
|
|
||||||
void destroy_fences(std::span<VkFence> fences) const;
|
void destroy_fences(std::span<VkFence> fences) const;
|
||||||
|
|
||||||
void destroy_buffer(VkBuffer buffer) const;
|
|
||||||
|
|
||||||
void destroy_descriptor_set_layout(VkDescriptorSetLayout layout) const;
|
|
||||||
|
|
||||||
void destroy_descriptor_pool(VkDescriptorPool pool) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static auto get_object_type(const T &object) -> VkObjectType
|
static auto get_object_type(const T &object) -> VkObjectType
|
||||||
|
|
|
||||||
|
|
@ -5,38 +5,35 @@
|
||||||
namespace lt::renderer::vk {
|
namespace lt::renderer::vk {
|
||||||
|
|
||||||
Gpu::Gpu(IInstance *instance)
|
Gpu::Gpu(IInstance *instance)
|
||||||
: m_descriptor_indexing_features(
|
|
||||||
{ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES }
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
auto gpus = static_cast<Instance *>(instance)->enumerate_gpus();
|
auto gpus = static_cast<Instance *>(instance)->enumerate_gpus();
|
||||||
|
|
||||||
for (auto &gpu : gpus)
|
for (auto &gpu : gpus)
|
||||||
{
|
{
|
||||||
auto properties = VkPhysicalDeviceProperties {};
|
auto properties = VkPhysicalDeviceProperties {};
|
||||||
auto features = VkPhysicalDeviceFeatures2 {
|
auto features = VkPhysicalDeviceFeatures {};
|
||||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
|
||||||
.pNext = &m_descriptor_indexing_features
|
|
||||||
};
|
|
||||||
|
|
||||||
vk_get_physical_device_properties(gpu, &properties);
|
vk_get_physical_device_properties(gpu, &properties);
|
||||||
vk_get_physical_device_features(gpu, &features);
|
vk_get_physical_device_features(gpu, &features);
|
||||||
|
|
||||||
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|
||||||
&& features.features.geometryShader)
|
&& features.geometryShader)
|
||||||
{
|
{
|
||||||
m_gpu = gpu;
|
m_gpu = gpu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ensure(m_gpu, "Failed to find any suitable Vulkan physical device");
|
ensure(m_gpu, "Failed to find any suitable Vulkan physical device");
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto Gpu::get_queue_family_properties() const -> std::vector<VkQueueFamilyProperties>
|
||||||
vk_get_physical_device_memory_properties(m_gpu, &m_memory_properties);
|
{
|
||||||
|
|
||||||
auto count = uint32_t { 0u };
|
auto count = uint32_t { 0u };
|
||||||
vk_get_physical_device_queue_family_properties(m_gpu, &count, nullptr);
|
vk_get_physical_device_queue_family_properties(m_gpu, &count, nullptr);
|
||||||
m_queue_family_properties.resize(count);
|
|
||||||
vk_get_physical_device_queue_family_properties(m_gpu, &count, m_queue_family_properties.data());
|
auto properties = std::vector<VkQueueFamilyProperties>(count);
|
||||||
|
vk_get_physical_device_queue_family_properties(m_gpu, &count, properties.data());
|
||||||
|
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto Gpu::queue_family_supports_presentation(
|
[[nodiscard]] auto Gpu::queue_family_supports_presentation(
|
||||||
|
|
@ -70,11 +67,5 @@ Gpu::Gpu(IInstance *instance)
|
||||||
return formats;
|
return formats;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto Gpu::create_device(VkDeviceCreateInfo info) const -> VkDevice
|
|
||||||
{
|
|
||||||
auto *device = VkDevice {};
|
|
||||||
vkc(vk_create_device(m_gpu, &info, nullptr, &device));
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace lt::renderer::vk
|
} // namespace lt::renderer::vk
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,13 @@ class Gpu: public IGpu
|
||||||
public:
|
public:
|
||||||
Gpu(IInstance *instance);
|
Gpu(IInstance *instance);
|
||||||
|
|
||||||
|
[[nodiscard]] auto vk() const -> VkPhysicalDevice
|
||||||
|
{
|
||||||
|
return m_gpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_queue_family_properties() const -> std::vector<VkQueueFamilyProperties>;
|
||||||
|
|
||||||
[[nodiscard]] auto queue_family_supports_presentation(
|
[[nodiscard]] auto queue_family_supports_presentation(
|
||||||
VkSurfaceKHR surface,
|
VkSurfaceKHR surface,
|
||||||
uint32_t queue_family_idx
|
uint32_t queue_family_idx
|
||||||
|
|
@ -23,39 +30,8 @@ public:
|
||||||
[[nodiscard]] auto get_surface_formats(VkSurfaceKHR surface) const
|
[[nodiscard]] auto get_surface_formats(VkSurfaceKHR surface) const
|
||||||
-> std::vector<VkSurfaceFormatKHR>;
|
-> std::vector<VkSurfaceFormatKHR>;
|
||||||
|
|
||||||
[[nodiscard]] auto create_device(VkDeviceCreateInfo info) const -> VkDevice;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_properties() const -> VkPhysicalDeviceProperties
|
|
||||||
{
|
|
||||||
return m_properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_descriptor_indexing_features() const
|
|
||||||
-> VkPhysicalDeviceDescriptorIndexingFeatures
|
|
||||||
{
|
|
||||||
return m_descriptor_indexing_features;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_memory_properties() const -> VkPhysicalDeviceMemoryProperties
|
|
||||||
{
|
|
||||||
return m_memory_properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_queue_family_properties() const -> std::vector<VkQueueFamilyProperties>
|
|
||||||
{
|
|
||||||
return m_queue_family_properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
memory::NullOnMove<VkPhysicalDevice> m_gpu = VK_NULL_HANDLE;
|
memory::NullOnMove<VkPhysicalDevice> m_gpu = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkPhysicalDeviceProperties m_properties {};
|
|
||||||
|
|
||||||
VkPhysicalDeviceDescriptorIndexingFeatures m_descriptor_indexing_features;
|
|
||||||
|
|
||||||
VkPhysicalDeviceMemoryProperties m_memory_properties {};
|
|
||||||
|
|
||||||
std::vector<VkQueueFamilyProperties> m_queue_family_properties;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lt::renderer::vk
|
} // namespace lt::renderer::vk
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,8 @@ PFN_vkGetPhysicalDeviceQueueFamilyProperties vk_get_physical_device_queue_family
|
||||||
PFN_vkCreateDevice vk_create_device {};
|
PFN_vkCreateDevice vk_create_device {};
|
||||||
PFN_vkGetDeviceProcAddr vk_get_device_proc_address {};
|
PFN_vkGetDeviceProcAddr vk_get_device_proc_address {};
|
||||||
PFN_vkDestroyDevice vk_destroy_device {};
|
PFN_vkDestroyDevice vk_destroy_device {};
|
||||||
PFN_vkGetPhysicalDeviceFeatures2 vk_get_physical_device_features {};
|
PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features {};
|
||||||
PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties {};
|
PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties {};
|
||||||
PFN_vkGetPhysicalDeviceMemoryProperties vk_get_physical_device_memory_properties {};
|
|
||||||
|
|
||||||
// extension instance functions
|
// extension instance functions
|
||||||
PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label {};
|
PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label {};
|
||||||
|
|
@ -87,37 +86,15 @@ PFN_vkCmdBindPipeline vk_cmd_bind_pipeline {};
|
||||||
PFN_vkCmdDraw vk_cmd_draw {};
|
PFN_vkCmdDraw vk_cmd_draw {};
|
||||||
PFN_vkCmdSetViewport vk_cmd_set_viewport {};
|
PFN_vkCmdSetViewport vk_cmd_set_viewport {};
|
||||||
PFN_vkCmdSetScissor vk_cmd_set_scissors {};
|
PFN_vkCmdSetScissor vk_cmd_set_scissors {};
|
||||||
PFN_vkCmdPushConstants vk_cmd_push_constants {};
|
|
||||||
PFN_vkCmdCopyBuffer vk_cmd_copy_buffer {};
|
|
||||||
|
|
||||||
PFN_vkCreateDescriptorSetLayout vk_create_descriptor_set_layout {};
|
|
||||||
PFN_vkDestroyDescriptorSetLayout vk_destroy_descriptor_set_layout {};
|
|
||||||
PFN_vkCreateDescriptorPool vk_create_descriptor_pool {};
|
|
||||||
PFN_vkDestroyDescriptorPool vk_destroy_descriptor_pool {};
|
|
||||||
PFN_vkAllocateDescriptorSets vk_allocate_descriptor_sets {};
|
|
||||||
PFN_vkFreeDescriptorSets vk_free_descriptor_sets {};
|
|
||||||
|
|
||||||
PFN_vkCreateBuffer vk_create_buffer {};
|
|
||||||
PFN_vkDestroyBuffer vk_destroy_buffer {};
|
|
||||||
PFN_vkGetBufferMemoryRequirements vk_get_buffer_memory_requirements {};
|
|
||||||
PFN_vkAllocateMemory vk_allocate_memory {};
|
|
||||||
PFN_vkBindBufferMemory vk_bind_buffer_memory {};
|
|
||||||
PFN_vkMapMemory vk_map_memory {};
|
|
||||||
PFN_vkUnmapMemory vk_unmap_memory {};
|
|
||||||
PFN_vkFreeMemory vk_free_memory {};
|
|
||||||
|
|
||||||
PFN_vkResetCommandBuffer vk_reset_command_buffer {};
|
PFN_vkResetCommandBuffer vk_reset_command_buffer {};
|
||||||
|
|
||||||
PFN_vkCmdBeginRendering vk_cmd_begin_rendering {};
|
|
||||||
PFN_vkCmdEndRendering vk_cmd_end_rendering {};
|
|
||||||
|
|
||||||
PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {};
|
PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {};
|
||||||
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vk_get_physical_device_surface_capabilities {};
|
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vk_get_physical_device_surface_capabilities {};
|
||||||
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vk_get_physical_device_surface_formats {};
|
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vk_get_physical_device_surface_formats {};
|
||||||
|
|
||||||
auto vk_create_xlib_surface_khr = PFN_vkCreateXlibSurfaceKHR {};
|
auto vk_create_xlib_surface_khr = PFN_vkCreateXlibSurfaceKHR {};
|
||||||
auto vk_destroy_surface_khr = PFN_vkDestroySurfaceKHR {};
|
auto vk_destroy_surface_khr = PFN_vkDestroySurfaceKHR {};
|
||||||
|
|
||||||
// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
|
// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
|
|
||||||
Instance::Instance()
|
Instance::Instance()
|
||||||
|
|
@ -150,7 +127,6 @@ void Instance::initialize_instance()
|
||||||
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
||||||
VK_KHR_SURFACE_EXTENSION_NAME,
|
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||||
VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
|
VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
|
||||||
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *layer_name = "VK_LAYER_KHRONOS_validation";
|
const char *layer_name = "VK_LAYER_KHRONOS_validation";
|
||||||
|
|
@ -244,10 +220,10 @@ void Instance::initialize_instance()
|
||||||
memset(extensions.data(), 0, extensions.size() * sizeof(VkExtensionProperties));
|
memset(extensions.data(), 0, extensions.size() * sizeof(VkExtensionProperties));
|
||||||
vkc(vk_enumerate_instance_extension_properties(nullptr, &count, extensions.data()));
|
vkc(vk_enumerate_instance_extension_properties(nullptr, &count, extensions.data()));
|
||||||
|
|
||||||
// log::info("Available vulkan instance extensions:");
|
// log_inf("Available vulkan instance extensions:");
|
||||||
for (auto &ext : extensions)
|
for (auto &ext : extensions)
|
||||||
{
|
{
|
||||||
// log::info("\t{} @ {}", ext.extensionName, ext.specVersion);
|
// log_inf("\t{} @ {}", ext.extensionName, ext.specVersion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -293,7 +269,7 @@ void Instance::load_global_functions()
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
pfn = reinterpret_cast<T>(vk_get_instance_proc_address(nullptr, fn_name));
|
pfn = reinterpret_cast<T>(vk_get_instance_proc_address(nullptr, fn_name));
|
||||||
ensure(pfn, "Failed to load vulkan global function: {}", fn_name);
|
ensure(pfn, "Failed to load vulkan global function: {}", fn_name);
|
||||||
// log::trace("Loaded global function: {}", fn_name);
|
// log_trc("Loaded global function: {}", fn_name);
|
||||||
};
|
};
|
||||||
|
|
||||||
load_fn(vk_create_instance, "vkCreateInstance");
|
load_fn(vk_create_instance, "vkCreateInstance");
|
||||||
|
|
@ -307,7 +283,7 @@ void Instance::load_instance_functions()
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
pfn = reinterpret_cast<T>(vk_get_instance_proc_address(m_instance, fn_name));
|
pfn = reinterpret_cast<T>(vk_get_instance_proc_address(m_instance, fn_name));
|
||||||
ensure(pfn, "Failed to load vulkan instance function: {}", fn_name);
|
ensure(pfn, "Failed to load vulkan instance function: {}", fn_name);
|
||||||
// log::trace("Loaded instance function: {}", fn_name);
|
// log_trc("Loaded instance function: {}", fn_name);
|
||||||
};
|
};
|
||||||
|
|
||||||
load_fn(vk_destroy_instance, "vkDestroyInstance");
|
load_fn(vk_destroy_instance, "vkDestroyInstance");
|
||||||
|
|
@ -322,7 +298,6 @@ void Instance::load_instance_functions()
|
||||||
load_fn(vk_destroy_device, "vkDestroyDevice");
|
load_fn(vk_destroy_device, "vkDestroyDevice");
|
||||||
load_fn(vk_get_physical_device_features, "vkGetPhysicalDeviceFeatures");
|
load_fn(vk_get_physical_device_features, "vkGetPhysicalDeviceFeatures");
|
||||||
load_fn(vk_enumerate_device_extension_properties, "vkEnumerateDeviceExtensionProperties");
|
load_fn(vk_enumerate_device_extension_properties, "vkEnumerateDeviceExtensionProperties");
|
||||||
load_fn(vk_get_physical_device_memory_properties, "vkGetPhysicalDeviceMemoryProperties");
|
|
||||||
|
|
||||||
load_fn(vk_cmd_begin_debug_label, "vkCmdBeginDebugUtilsLabelEXT");
|
load_fn(vk_cmd_begin_debug_label, "vkCmdBeginDebugUtilsLabelEXT");
|
||||||
load_fn(vk_cmd_end_debug_label, "vkCmdEndDebugUtilsLabelEXT");
|
load_fn(vk_cmd_end_debug_label, "vkCmdEndDebugUtilsLabelEXT");
|
||||||
|
|
@ -352,7 +327,7 @@ void Instance::load_device_functions_impl(VkDevice device)
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||||
pfn = reinterpret_cast<T>(vk_get_device_proc_address(device, fn_name));
|
pfn = reinterpret_cast<T>(vk_get_device_proc_address(device, fn_name));
|
||||||
ensure(pfn, "Failed to load vulkan device function: {}", fn_name);
|
ensure(pfn, "Failed to load vulkan device function: {}", fn_name);
|
||||||
// log::trace("Loaded device function: {}", fn_name);
|
// log_trc("Loaded device function: {}", fn_name);
|
||||||
};
|
};
|
||||||
|
|
||||||
load_fn(vk_get_device_queue, "vkGetDeviceQueue");
|
load_fn(vk_get_device_queue, "vkGetDeviceQueue");
|
||||||
|
|
@ -395,26 +370,7 @@ void Instance::load_device_functions_impl(VkDevice device)
|
||||||
load_fn(vk_cmd_draw, "vkCmdDraw");
|
load_fn(vk_cmd_draw, "vkCmdDraw");
|
||||||
load_fn(vk_cmd_set_viewport, "vkCmdSetViewport");
|
load_fn(vk_cmd_set_viewport, "vkCmdSetViewport");
|
||||||
load_fn(vk_cmd_set_scissors, "vkCmdSetScissor");
|
load_fn(vk_cmd_set_scissors, "vkCmdSetScissor");
|
||||||
load_fn(vk_cmd_push_constants, "vkCmdPushConstants");
|
|
||||||
load_fn(vk_cmd_copy_buffer, "vkCmdCopyBuffer");
|
|
||||||
load_fn(vk_create_descriptor_set_layout, "vkCreateDescriptorSetLayout");
|
|
||||||
load_fn(vk_destroy_descriptor_set_layout, "vkDestroyDescriptorSetLayout");
|
|
||||||
load_fn(vk_create_descriptor_pool, "vkCreateDescriptorPool");
|
|
||||||
load_fn(vk_destroy_descriptor_pool, "vkDestroyDescriptorPool");
|
|
||||||
load_fn(vk_allocate_descriptor_sets, "vkAllocateDescriptorSets");
|
|
||||||
load_fn(vk_free_descriptor_sets, "vkFreeDescriptorSets");
|
|
||||||
load_fn(vk_create_buffer, "vkCreateBuffer");
|
|
||||||
load_fn(vk_destroy_buffer, "vkDestroyBuffer");
|
|
||||||
load_fn(vk_allocate_memory, "vkAllocateMemory");
|
|
||||||
load_fn(vk_bind_buffer_memory, "vkBindBufferMemory");
|
|
||||||
load_fn(vk_map_memory, "vkMapMemory");
|
|
||||||
load_fn(vk_unmap_memory, "vkUnmapMemory");
|
|
||||||
load_fn(vk_free_memory, "vkFreeMemory");
|
|
||||||
load_fn(vk_get_buffer_memory_requirements, "vkGetBufferMemoryRequirements");
|
|
||||||
load_fn(vk_reset_command_buffer, "vkResetCommandBuffer");
|
load_fn(vk_reset_command_buffer, "vkResetCommandBuffer");
|
||||||
|
|
||||||
load_fn(vk_cmd_begin_rendering, "vkCmdBeginRendering");
|
|
||||||
load_fn(vk_cmd_end_rendering, "vkCmdEndRendering");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Instance::enumerate_gpus() const -> std::vector<VkPhysicalDevice>
|
auto Instance::enumerate_gpus() const -> std::vector<VkPhysicalDevice>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#include <logger/logger.hpp>
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <renderer/backend/vk/context/device.hpp>
|
#include <renderer/backend/vk/context/device.hpp>
|
||||||
#include <renderer/backend/vk/context/gpu.hpp>
|
#include <renderer/backend/vk/context/gpu.hpp>
|
||||||
|
|
@ -96,8 +95,8 @@ Swapchain::~Swapchain()
|
||||||
}
|
}
|
||||||
catch (const std::exception &exp)
|
catch (const std::exception &exp)
|
||||||
{
|
{
|
||||||
log::error("Failed to destroy swapchain:");
|
log_err("Failed to destroy swapchain:");
|
||||||
log::error("\twhat: {}", exp.what());
|
log_err("\twhat: {}", exp.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,17 +49,6 @@ public:
|
||||||
return m_images.size();
|
return m_images.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto get_image_view(uint32_t idx) -> VkImageView
|
|
||||||
{
|
|
||||||
return m_image_views[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_image(uint32_t idx) -> VkImage
|
|
||||||
{
|
|
||||||
return m_images[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[[nodiscard]] auto create_framebuffers_for_pass(VkRenderPass pass) const
|
[[nodiscard]] auto create_framebuffers_for_pass(VkRenderPass pass) const
|
||||||
-> std::vector<VkFramebuffer>;
|
-> std::vector<VkFramebuffer>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
#include <renderer/backend/vk/context/device.hpp>
|
|
||||||
#include <renderer/backend/vk/context/gpu.hpp>
|
|
||||||
#include <renderer/backend/vk/data/buffer.hpp>
|
|
||||||
|
|
||||||
namespace lt::renderer::vk {
|
|
||||||
|
|
||||||
Buffer::Buffer(IDevice *device, IGpu *gpu, const CreateInfo &info)
|
|
||||||
: m_device(static_cast<Device *>(device))
|
|
||||||
, m_gpu(static_cast<Gpu *>(gpu))
|
|
||||||
, m_buffer(
|
|
||||||
m_device,
|
|
||||||
VkBufferCreateInfo {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
|
||||||
.size = info.size,
|
|
||||||
.usage = to_native_usage_flags(info.usage),
|
|
||||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
, m_memory(m_device, m_buffer, determine_allocation_info(info.usage))
|
|
||||||
, m_size(info.size)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Buffer::map() -> std::span<std::byte> /* override */
|
|
||||||
{
|
|
||||||
return m_device->map_memory(m_memory, m_size, 0ul);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Buffer::unmap() /* override */
|
|
||||||
{
|
|
||||||
m_device->unmap_memory(m_memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Buffer::determine_allocation_info(Usage usage) const -> VkMemoryAllocateInfo
|
|
||||||
{
|
|
||||||
const auto requirements = m_device->get_memory_requirements(m_buffer);
|
|
||||||
auto memory_properties = m_gpu->get_memory_properties();
|
|
||||||
|
|
||||||
const auto required_properties = to_native_memory_properties(usage);
|
|
||||||
auto type = 0u;
|
|
||||||
for (auto idx = 0; idx < memory_properties.memoryTypeCount; ++idx)
|
|
||||||
{
|
|
||||||
const auto property_flags = memory_properties.memoryTypes[idx].propertyFlags;
|
|
||||||
if (has_correct_memory_type_bit(requirements.memoryTypeBits, idx)
|
|
||||||
&& has_required_memory_properties(required_properties, property_flags))
|
|
||||||
|
|
||||||
{
|
|
||||||
type = idx;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return VkMemoryAllocateInfo {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
||||||
.allocationSize = requirements.size,
|
|
||||||
.memoryTypeIndex = type,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Buffer::to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags
|
|
||||||
{
|
|
||||||
switch (usage)
|
|
||||||
{
|
|
||||||
case Usage::vertex: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
|
||||||
|
|
||||||
case Usage::index: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
|
||||||
|
|
||||||
case Usage::storage:
|
|
||||||
return VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
|
||||||
|
|
||||||
case Usage::staging: return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Buffer::to_native_memory_properties(Usage usage) const -> VkMemoryPropertyFlags
|
|
||||||
{
|
|
||||||
switch (usage)
|
|
||||||
{
|
|
||||||
case Usage::vertex:
|
|
||||||
case Usage::index:
|
|
||||||
case Usage::storage: return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
|
|
||||||
|
|
||||||
case Usage::staging:
|
|
||||||
return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Buffer::has_correct_memory_type_bit(uint32_t type_bits, uint32_t type_idx) const
|
|
||||||
-> bool
|
|
||||||
{
|
|
||||||
return type_bits & (1 << type_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto Buffer::has_required_memory_properties(
|
|
||||||
uint32_t required_properties,
|
|
||||||
uint32_t property_flags
|
|
||||||
) const -> bool
|
|
||||||
{
|
|
||||||
return (property_flags & required_properties) == required_properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace lt::renderer::vk
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <renderer/backend/vk/raii/raii.hpp>
|
|
||||||
#include <renderer/frontend/data/buffer.hpp>
|
|
||||||
|
|
||||||
namespace lt::renderer::vk {
|
|
||||||
|
|
||||||
class Buffer: public IBuffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Buffer(class IDevice *device, class IGpu *gpu, const CreateInfo &info);
|
|
||||||
|
|
||||||
[[nodiscard]] auto map() -> std::span<std::byte> override;
|
|
||||||
|
|
||||||
void unmap() override;
|
|
||||||
|
|
||||||
// TODO(Light): this is to make copying possible.
|
|
||||||
// But it should be removed in the future,
|
|
||||||
// Right now it's not possible because: buffers can't understand CommandBuffers.
|
|
||||||
// And I'm not sure how to properly abstract over command buffers,
|
|
||||||
// before using other APIs...
|
|
||||||
[[nodiscard]] auto vk()
|
|
||||||
{
|
|
||||||
return *m_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_size() const -> size_t override
|
|
||||||
{
|
|
||||||
return m_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
[[nodiscard]] auto determine_allocation_info(Usage usage) const -> VkMemoryAllocateInfo;
|
|
||||||
|
|
||||||
[[nodiscard]] auto to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags;
|
|
||||||
|
|
||||||
[[nodiscard]] auto to_native_memory_properties(Usage usage) const -> VkMemoryPropertyFlags;
|
|
||||||
|
|
||||||
|
|
||||||
[[nodiscard]] auto has_correct_memory_type_bit(uint32_t type_bits, uint32_t type_idx) const
|
|
||||||
-> bool;
|
|
||||||
|
|
||||||
[[nodiscard]] auto has_required_memory_properties(
|
|
||||||
uint32_t required_properties,
|
|
||||||
uint32_t property_flags
|
|
||||||
) const -> bool;
|
|
||||||
|
|
||||||
Device *m_device {};
|
|
||||||
|
|
||||||
Gpu *m_gpu {};
|
|
||||||
|
|
||||||
raii::Buffer m_buffer;
|
|
||||||
|
|
||||||
raii::Memory m_memory;
|
|
||||||
|
|
||||||
// TODO(Light): should this reflect the allocation size instead?
|
|
||||||
size_t m_size {};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lt::renderer::vk
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace lt::renderer::vk {
|
|
||||||
|
|
||||||
class Descriptors
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace lt::renderer::vk
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
#include <logger/logger.hpp>
|
|
||||||
#include <renderer/backend/vk/messenger.hpp>
|
#include <renderer/backend/vk/messenger.hpp>
|
||||||
|
|
||||||
namespace lt::renderer::vk {
|
namespace lt::renderer::vk {
|
||||||
|
|
@ -43,8 +42,8 @@ Messenger::Messenger(IInstance *instance, CreateInfo info)
|
||||||
}
|
}
|
||||||
catch (const std::exception &exp)
|
catch (const std::exception &exp)
|
||||||
{
|
{
|
||||||
log::error("Uncaught exception in messenger callback:");
|
log_err("Uncaught exception in messenger callback:");
|
||||||
log::error("\twhat: {}", exp.what());
|
log_err("\twhat: {}", exp.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
#include <memory/pointer_types/null_on_move.hpp>
|
#include <memory/pointer_types/null_on_move.hpp>
|
||||||
#include <renderer/backend/vk/context/device.hpp>
|
|
||||||
#include <renderer/backend/vk/context/instance.hpp>
|
#include <renderer/backend/vk/context/instance.hpp>
|
||||||
#include <renderer/backend/vk/vulkan.hpp>
|
#include <renderer/backend/vk/vulkan.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace lt::renderer::vk::raii {
|
namespace lt::renderer::vk::raii {
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
|
||||||
class DebugMessenger
|
class DebugMessenger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -17,19 +16,13 @@ public:
|
||||||
|
|
||||||
~DebugMessenger()
|
~DebugMessenger()
|
||||||
{
|
{
|
||||||
if (m_instance)
|
if (!m_instance)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_instance->destroy_messenger(m_object);
|
m_instance->destroy_messenger(m_object);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DebugMessenger(DebugMessenger &&) = default;
|
|
||||||
|
|
||||||
DebugMessenger(const DebugMessenger &) = delete;
|
|
||||||
|
|
||||||
auto operator=(DebugMessenger &&) -> DebugMessenger & = default;
|
|
||||||
|
|
||||||
auto operator=(const DebugMessenger &) -> DebugMessenger & = delete;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
memory::NullOnMove<Instance *> m_instance {};
|
memory::NullOnMove<Instance *> m_instance {};
|
||||||
|
|
@ -37,88 +30,4 @@ private:
|
||||||
VkDebugUtilsMessengerEXT m_object;
|
VkDebugUtilsMessengerEXT m_object;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Buffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Buffer(Device *device, VkBufferCreateInfo info)
|
|
||||||
: m_device(device)
|
|
||||||
, m_object(m_device->create_buffer(info))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~Buffer()
|
|
||||||
{
|
|
||||||
if (m_device)
|
|
||||||
{
|
|
||||||
m_device->destroy_buffer(m_object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Buffer(Buffer &&) = default;
|
|
||||||
|
|
||||||
Buffer(const Buffer &) = delete;
|
|
||||||
|
|
||||||
auto operator=(Buffer &&) -> Buffer & = default;
|
|
||||||
|
|
||||||
auto operator=(const Buffer &) -> Buffer & = delete;
|
|
||||||
|
|
||||||
[[nodiscard]] auto operator*() const -> VkBuffer
|
|
||||||
{
|
|
||||||
return m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] operator VkBuffer() const
|
|
||||||
{
|
|
||||||
return m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
memory::NullOnMove<Device *> m_device {};
|
|
||||||
|
|
||||||
VkBuffer m_object;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Memory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Memory(Device *device, VkBuffer buffer, VkMemoryAllocateInfo info)
|
|
||||||
: m_device(device)
|
|
||||||
, m_object(m_device->allocate_memory(info))
|
|
||||||
{
|
|
||||||
m_device->bind_memory(buffer, m_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Memory()
|
|
||||||
{
|
|
||||||
if (m_device)
|
|
||||||
{
|
|
||||||
m_device->free_memory(m_object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Memory(Memory &&) = default;
|
|
||||||
|
|
||||||
Memory(const Memory &) = delete;
|
|
||||||
|
|
||||||
auto operator=(Memory &&) -> Memory & = default;
|
|
||||||
|
|
||||||
auto operator=(const Memory &) -> Memory & = delete;
|
|
||||||
|
|
||||||
[[nodiscard]] auto operator*() const -> VkDeviceMemory
|
|
||||||
{
|
|
||||||
return m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] operator VkDeviceMemory() const
|
|
||||||
{
|
|
||||||
return m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
memory::NullOnMove<Device *> m_device {};
|
|
||||||
|
|
||||||
VkDeviceMemory m_object = VK_NULL_HANDLE;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace lt::renderer::vk::raii
|
} // namespace lt::renderer::vk::raii
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue