Compare commits
1 commit
main
...
feat/test_
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ce413a1d7 |
53 changed files with 854 additions and 1217 deletions
5
.clangd
5
.clangd
|
|
@ -1,5 +0,0 @@
|
|||
CompileFlags:
|
||||
DriverMode: cl
|
||||
Add:
|
||||
- /EHsc
|
||||
- /std:c++latest
|
||||
290
.drone.yml
290
.drone.yml
|
|
@ -1,42 +1,42 @@
|
|||
---
|
||||
kind: pipeline
|
||||
type: exec
|
||||
name: amd64 — msvc
|
||||
trigger:
|
||||
branch:
|
||||
- main
|
||||
platform:
|
||||
os: windows
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: unit tests
|
||||
shell: powershell
|
||||
commands:
|
||||
- ./tools/ci/amd64/msvc/unit_tests.ps1
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: amd64 — gcc
|
||||
trigger:
|
||||
branch:
|
||||
- main
|
||||
|
||||
steps:
|
||||
- name: unit tests
|
||||
image: ci:latest
|
||||
pull: if-not-exists
|
||||
commands:
|
||||
- ./tools/ci/amd64/gcc/unit_tests.sh
|
||||
|
||||
- name: valgrind
|
||||
image: ci:latest
|
||||
pull: if-not-exists
|
||||
commands:
|
||||
- ./tools/ci/amd64/gcc/valgrind.sh
|
||||
|
||||
---
|
||||
# ---
|
||||
# kind: pipeline
|
||||
# type: exec
|
||||
# name: amd64 — msvc
|
||||
# trigger:
|
||||
# branch:
|
||||
# - main
|
||||
# platform:
|
||||
# os: windows
|
||||
# arch: amd64
|
||||
#
|
||||
# steps:
|
||||
# - name: unit tests
|
||||
# shell: powershell
|
||||
# commands:
|
||||
# - ./tools/ci/amd64/msvc/unit_tests.ps1
|
||||
#
|
||||
# ---
|
||||
# kind: pipeline
|
||||
# type: docker
|
||||
# name: amd64 — gcc
|
||||
# trigger:
|
||||
# branch:
|
||||
# - main
|
||||
#
|
||||
# steps:
|
||||
# - name: unit tests
|
||||
# image: ci:latest
|
||||
# pull: if-not-exists
|
||||
# commands:
|
||||
# - ./tools/ci/amd64/gcc/unit_tests.sh
|
||||
#
|
||||
# - name: valgrind
|
||||
# image: ci:latest
|
||||
# pull: if-not-exists
|
||||
# commands:
|
||||
# - ./tools/ci/amd64/gcc/valgrind.sh
|
||||
#
|
||||
# ---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: amd64 — clang
|
||||
|
|
@ -45,114 +45,114 @@ trigger:
|
|||
- main
|
||||
|
||||
steps:
|
||||
- name: code coverage
|
||||
image: ci:latest
|
||||
pull: if-not-exists
|
||||
environment:
|
||||
CODECOV_TOKEN:
|
||||
from_secret: CODECOV_TOKEN
|
||||
commands:
|
||||
- ./tools/ci/amd64/clang/coverage.sh
|
||||
|
||||
- name: leak sanitizer
|
||||
image: ci:latest
|
||||
pull: if-not-exists
|
||||
commands:
|
||||
- ./tools/ci/amd64/clang/lsan.sh
|
||||
|
||||
# - name: code coverage
|
||||
# image: ci:latest
|
||||
# pull: if-not-exists
|
||||
# environment:
|
||||
# CODECOV_TOKEN:
|
||||
# from_secret: CODECOV_TOKEN
|
||||
# commands:
|
||||
# - ./tools/ci/amd64/clang/coverage.sh
|
||||
#
|
||||
# - name: leak sanitizer
|
||||
# image: ci:latest
|
||||
# pull: if-not-exists
|
||||
# commands:
|
||||
# - ./tools/ci/amd64/clang/lsan.sh
|
||||
#
|
||||
- name: memory sanitizer
|
||||
image: ci:latest
|
||||
pull: if-not-exists
|
||||
commands:
|
||||
- ./tools/ci/amd64/clang/msan.sh
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: static analysis
|
||||
trigger:
|
||||
branch:
|
||||
- main
|
||||
|
||||
steps:
|
||||
- name: clang tidy
|
||||
image: ci:latest
|
||||
pull: if-not-exists
|
||||
privileged: true
|
||||
commands:
|
||||
- ./tools/ci/static_analysis/clang_tidy.sh
|
||||
|
||||
- name: shell check
|
||||
image: ci:latest
|
||||
pull: if-not-exists
|
||||
commands:
|
||||
- ./tools/ci/static_analysis/shell_check.sh
|
||||
|
||||
- name: clang format
|
||||
image: ci:latest
|
||||
pull: if-not-exists
|
||||
commands:
|
||||
- ./tools/ci/static_analysis/clang_format.sh
|
||||
|
||||
- name: cmake format
|
||||
image: ci:latest
|
||||
pull: if-not-exists
|
||||
commands:
|
||||
- ./tools/ci/static_analysis/cmake_format.sh
|
||||
|
||||
- name: shell format
|
||||
image: ci:latest
|
||||
pull: if-not-exists
|
||||
commands:
|
||||
- ./tools/ci/static_analysis/shell_format.sh
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: documentation — development
|
||||
node:
|
||||
environment: ryali
|
||||
trigger:
|
||||
branch:
|
||||
- main
|
||||
|
||||
steps:
|
||||
- name: build and deploy
|
||||
image: documentation:latest
|
||||
pull: if-not-exists
|
||||
commands:
|
||||
- pwd
|
||||
- cd docs
|
||||
- mkdir generated
|
||||
- touch generated/changelogs.rst
|
||||
- touch generated/api.rst
|
||||
- sphinx-build -M html . .
|
||||
|
||||
- rm -rf /light_docs_dev/*
|
||||
- mv ./html/* /light_docs_dev/
|
||||
|
||||
---
|
||||
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: documentation — production
|
||||
node:
|
||||
environment: ryali
|
||||
trigger:
|
||||
event:
|
||||
- tag
|
||||
|
||||
steps:
|
||||
- name: build and deploy
|
||||
image: documentation:latest
|
||||
pull: if-not-exists
|
||||
commands:
|
||||
- cd docs
|
||||
- mkdir generated
|
||||
- touch generated/changelogs.rst
|
||||
- touch generated/api.rst
|
||||
- sphinx-build -M html . .
|
||||
|
||||
- rm -rf /light_docs/*
|
||||
- mv ./html/* /light_docs/
|
||||
|
||||
#
|
||||
# ---
|
||||
# kind: pipeline
|
||||
# type: docker
|
||||
# name: static analysis
|
||||
# trigger:
|
||||
# branch:
|
||||
# - main
|
||||
#
|
||||
# steps:
|
||||
# - name: clang tidy
|
||||
# image: ci:latest
|
||||
# pull: if-not-exists
|
||||
# privileged: true
|
||||
# commands:
|
||||
# - ./tools/ci/static_analysis/clang_tidy.sh
|
||||
#
|
||||
# - name: shell check
|
||||
# image: ci:latest
|
||||
# pull: if-not-exists
|
||||
# commands:
|
||||
# - ./tools/ci/static_analysis/shell_check.sh
|
||||
#
|
||||
# - name: clang format
|
||||
# image: ci:latest
|
||||
# pull: if-not-exists
|
||||
# commands:
|
||||
# - ./tools/ci/static_analysis/clang_format.sh
|
||||
#
|
||||
# - name: cmake format
|
||||
# image: ci:latest
|
||||
# pull: if-not-exists
|
||||
# commands:
|
||||
# - ./tools/ci/static_analysis/cmake_format.sh
|
||||
#
|
||||
# - name: shell format
|
||||
# image: ci:latest
|
||||
# pull: if-not-exists
|
||||
# commands:
|
||||
# - ./tools/ci/static_analysis/shell_format.sh
|
||||
#
|
||||
# ---
|
||||
# kind: pipeline
|
||||
# type: docker
|
||||
# name: documentation — development
|
||||
# node:
|
||||
# environment: ryali
|
||||
# trigger:
|
||||
# branch:
|
||||
# - main
|
||||
#
|
||||
# steps:
|
||||
# - name: build and deploy
|
||||
# image: documentation:latest
|
||||
# pull: if-not-exists
|
||||
# commands:
|
||||
# - pwd
|
||||
# - cd docs
|
||||
# - mkdir generated
|
||||
# - touch generated/changelogs.rst
|
||||
# - touch generated/api.rst
|
||||
# - sphinx-build -M html . .
|
||||
#
|
||||
# - rm -rf /light_docs_dev/*
|
||||
# - mv ./html/* /light_docs_dev/
|
||||
#
|
||||
# ---
|
||||
#
|
||||
# kind: pipeline
|
||||
# type: docker
|
||||
# name: documentation — production
|
||||
# node:
|
||||
# environment: ryali
|
||||
# trigger:
|
||||
# event:
|
||||
# - tag
|
||||
#
|
||||
# steps:
|
||||
# - name: build and deploy
|
||||
# image: documentation:latest
|
||||
# pull: if-not-exists
|
||||
# commands:
|
||||
# - cd docs
|
||||
# - mkdir generated
|
||||
# - touch generated/changelogs.rst
|
||||
# - 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
|
||||
|
||||
layout(push_constant ) uniform pc {
|
||||
mat4 view_projection;
|
||||
};
|
||||
|
||||
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)
|
||||
vec2 positions[3] = vec2[](
|
||||
vec2(0.0, -0.5),
|
||||
vec2(0.5, 0.5),
|
||||
vec2(-0.5, 0.5)
|
||||
);
|
||||
|
||||
vec3 colors[3] = vec3[](
|
||||
vec3(0.0, 0.0, 0.0),
|
||||
vec3(0.0, 0.0, 0.0),
|
||||
vec3(0.0, 0.0, 0.0)
|
||||
vec3(1.0, 0.0, 0.0),
|
||||
vec3(0.0, 1.0, 0.0),
|
||||
vec3(0.0, 0.0, 1.0)
|
||||
);
|
||||
|
||||
layout(location = 0) out vec3 out_frag_color;
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,3 +1,3 @@
|
|||
add_library_module(camera)
|
||||
add_library_module(camera camera.cpp scene.cpp)
|
||||
|
||||
target_link_libraries(camera INTERFACE math)
|
||||
target_link_libraries(camera PUBLIC math)
|
||||
|
|
|
|||
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
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <math/mat4.hpp>
|
||||
|
||||
namespace lt::camera::components {
|
||||
|
||||
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
|
||||
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
|
||||
|
|
@ -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.
|
||||
*
|
||||
* @ref Thanks to pikuma for explaining the math behind this:
|
||||
* https://www.youtube.com/watch?v=EqNcqBdrNyI
|
||||
* thanks to pikuma: https://www.youtube.com/watch?v=EqNcqBdrNyI
|
||||
*/
|
||||
template<typename T>
|
||||
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));
|
||||
|
||||
auto result = mat4_impl<T>::identity();
|
||||
auto result = mat4_impl<T> { T { 0 } };
|
||||
|
||||
result[0][0] = T { 1 } / (aspect_ratio * 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_far - z_near);
|
||||
//
|
||||
|
||||
result[2][2] = -(z_far + z_near) / (z_far - z_near);
|
||||
|
||||
result[2][3] = -T { 1 };
|
||||
//
|
||||
// result[3][2] = -(T { 2 } * z_far * z_near) / (z_far - z_near);
|
||||
result[3][2] = -(z_far * z_near) / (z_far - z_near);
|
||||
//
|
||||
|
||||
result[3][2] = -(T { 2 } * z_far * z_near) / (z_far - z_near);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ template<typename T = float>
|
|||
struct mat4_impl
|
||||
{
|
||||
using Column_T = vec4_impl<T>;
|
||||
|
||||
constexpr explicit mat4_impl(T scalar = 0)
|
||||
: 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> {
|
||||
{ 1 }, {}, {}, {}, //
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
add_library_module(libmirror)
|
||||
target_link_libraries(libmirror INTERFACE app time input surface renderer
|
||||
camera)
|
||||
target_link_libraries(libmirror INTERFACE app time input surface renderer)
|
||||
|
||||
add_test_module(
|
||||
libmirror layers/editor_layer.test.cpp panels/asset_browser.test.cpp
|
||||
|
|
|
|||
|
|
@ -2,11 +2,9 @@
|
|||
#include <app/application.hpp>
|
||||
#include <app/entrypoint.hpp>
|
||||
#include <app/system.hpp>
|
||||
#include <camera/components.hpp>
|
||||
#include <ecs/entity.hpp>
|
||||
#include <input/components.hpp>
|
||||
#include <input/system.hpp>
|
||||
#include <math/trig.hpp>
|
||||
#include <math/vec2.hpp>
|
||||
#include <memory/reference.hpp>
|
||||
#include <memory/scope.hpp>
|
||||
|
|
@ -68,18 +66,13 @@ public:
|
|||
const auto &[x, y] = surface.get_position();
|
||||
const auto &[width, height] = surface.get_resolution();
|
||||
|
||||
|
||||
if (input.get_action(m_quit_action_key).state == State::active)
|
||||
{
|
||||
should_quit = true;
|
||||
}
|
||||
if (input.get_action(m_debug_action_keys[0]).state == State::active)
|
||||
{
|
||||
for (auto &[id, camera] :
|
||||
m_registry->view<lt::camera::components::PerspectiveCamera>())
|
||||
{
|
||||
camera.vertical_fov += (static_cast<float>(tick.delta_time.count()) * 40.0f);
|
||||
}
|
||||
surface.push_request(surface::ModifyPositionRequest({ x + 5, y + 5 }));
|
||||
}
|
||||
|
||||
if (input.get_action(m_debug_action_keys[1]).state == State::active)
|
||||
|
|
@ -226,20 +219,6 @@ public:
|
|||
.callback = &renderer_callback,
|
||||
.user_data = this,
|
||||
} });
|
||||
|
||||
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()
|
||||
|
|
@ -266,8 +245,6 @@ private:
|
|||
memory::Ref<MirrorSystem> m_mirror_system;
|
||||
|
||||
lt::ecs::EntityId m_window = lt::ecs::null_entity;
|
||||
|
||||
lt::ecs::EntityId m_camera_id = lt::ecs::null_entity;
|
||||
};
|
||||
|
||||
auto app::create_application() -> memory::Scope<app::Application>
|
||||
|
|
|
|||
|
|
@ -8,29 +8,21 @@ add_library_module(
|
|||
backend/vk/context/instance.cpp
|
||||
backend/vk/context/surface.cpp
|
||||
backend/vk/context/swapchain.cpp
|
||||
backend/vk/data/buffer.cpp
|
||||
backend/vk/renderer/pass.cpp
|
||||
backend/vk/renderer/renderer.cpp
|
||||
# frontend
|
||||
# Vulkan - frontend
|
||||
frontend/messenger.cpp
|
||||
frontend/context/device.cpp
|
||||
frontend/context/gpu.cpp
|
||||
frontend/context/instance.cpp
|
||||
frontend/context/surface.cpp
|
||||
frontend/context/swapchain.cpp
|
||||
frontend/data/buffer.cpp
|
||||
frontend/renderer/renderer.cpp
|
||||
frontend/renderer/pass.cpp)
|
||||
|
||||
target_link_libraries(
|
||||
renderer
|
||||
PUBLIC app
|
||||
ecs
|
||||
memory
|
||||
assets
|
||||
time
|
||||
bitwise
|
||||
camera
|
||||
PUBLIC app ecs memory assets time bitwise
|
||||
PRIVATE surface pthread)
|
||||
|
||||
add_test_module(
|
||||
|
|
@ -42,10 +34,11 @@ add_test_module(
|
|||
frontend/context/surface.test.cpp
|
||||
frontend/context/device.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
|
||||
# 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)
|
||||
|
|
|
|||
|
|
@ -75,17 +75,10 @@ void Device::initialize_logical_device()
|
|||
|
||||
auto extensions = std::vector<const char *> {
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||
VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME,
|
||||
};
|
||||
|
||||
const auto dynamic_rendering_features = VkPhysicalDeviceDynamicRenderingFeatures {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES,
|
||||
.dynamicRendering = true,
|
||||
};
|
||||
|
||||
auto device_info = VkDeviceCreateInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||
.pNext = &dynamic_rendering_features,
|
||||
.queueCreateInfoCount = static_cast<uint32_t>(queue_infos.size()),
|
||||
.pQueueCreateInfos = queue_infos.data(),
|
||||
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
|
||||
|
|
@ -214,31 +207,6 @@ void Device::wait_for_fences(std::span<VkFence> fences) const
|
|||
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
|
||||
{
|
||||
auto *swapchain = VkSwapchainKHR {};
|
||||
|
|
@ -283,18 +251,9 @@ void Device::unmap_memory(VkDeviceMemory memory)
|
|||
return pass;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto Device::create_pipeline_layout(
|
||||
std::vector<VkPushConstantRange> push_constant_ranges
|
||||
) const -> VkPipelineLayout
|
||||
[[nodiscard]] auto Device::create_pipeline_layout(VkPipelineLayoutCreateInfo info) const
|
||||
-> VkPipelineLayout
|
||||
{
|
||||
auto info = VkPipelineLayoutCreateInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = 0u,
|
||||
.pSetLayouts = nullptr,
|
||||
.pushConstantRangeCount = static_cast<uint32_t>(push_constant_ranges.size()),
|
||||
.pPushConstantRanges = push_constant_ranges.data(),
|
||||
};
|
||||
|
||||
auto *pipeline_layout = VkPipelineLayout {};
|
||||
vkc(vk_create_pipeline_layout(m_device, &info, nullptr, &pipeline_layout));
|
||||
return pipeline_layout;
|
||||
|
|
@ -340,13 +299,6 @@ void Device::unmap_memory(VkDeviceMemory memory)
|
|||
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::allocate_command_buffers(VkCommandBufferAllocateInfo info) const
|
||||
-> std::vector<VkCommandBuffer>
|
||||
{
|
||||
|
|
@ -355,18 +307,6 @@ void Device::unmap_memory(VkDeviceMemory memory)
|
|||
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;
|
||||
}
|
||||
|
||||
void Device::free_memory(VkDeviceMemory memory) const
|
||||
{
|
||||
vk_free_memory(m_device, memory, nullptr);
|
||||
}
|
||||
|
||||
void Device::destroy_swapchain(VkSwapchainKHR swapchain) const
|
||||
{
|
||||
vk_destroy_swapchain_khr(m_device, swapchain, m_allocator);
|
||||
|
|
@ -449,9 +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);
|
||||
}
|
||||
|
||||
} // namespace lt::renderer::vk
|
||||
|
|
|
|||
|
|
@ -96,16 +96,6 @@ public:
|
|||
|
||||
[[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 */
|
||||
[[nodiscard]] auto create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR;
|
||||
|
||||
|
|
@ -118,9 +108,8 @@ public:
|
|||
|
||||
[[nodiscard]] auto create_pass(VkRenderPassCreateInfo info) const -> VkRenderPass;
|
||||
|
||||
[[nodiscard]] auto create_pipeline_layout(
|
||||
std::vector<VkPushConstantRange> push_constant_ranges
|
||||
) const -> VkPipelineLayout;
|
||||
[[nodiscard]] auto create_pipeline_layout(VkPipelineLayoutCreateInfo info) const
|
||||
-> VkPipelineLayout;
|
||||
|
||||
[[nodiscard]] auto create_shader_module(VkShaderModuleCreateInfo info) const -> VkShaderModule;
|
||||
|
||||
|
|
@ -131,17 +120,10 @@ public:
|
|||
[[nodiscard]] auto create_fences(VkFenceCreateInfo info, uint32_t count) const
|
||||
-> std::vector<VkFence>;
|
||||
|
||||
[[nodiscard]] auto create_buffer(VkBufferCreateInfo info) const -> VkBuffer;
|
||||
|
||||
/** allocation functions */
|
||||
[[nodiscard]] auto allocate_memory(VkMemoryAllocateInfo info) const -> VkDeviceMemory;
|
||||
|
||||
[[nodiscard]] auto allocate_command_buffers(VkCommandBufferAllocateInfo info) const
|
||||
-> std::vector<VkCommandBuffer>;
|
||||
|
||||
/** de-allocation functions */
|
||||
void free_memory(VkDeviceMemory memory) const;
|
||||
|
||||
/** destroy functions */
|
||||
void destroy_swapchain(VkSwapchainKHR swapchain) const;
|
||||
|
||||
|
|
@ -171,8 +153,6 @@ public:
|
|||
|
||||
void destroy_fences(std::span<VkFence> fences) const;
|
||||
|
||||
void destroy_buffer(VkBuffer buffer) const;
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static auto get_object_type(const T &object) -> VkObjectType
|
||||
|
|
|
|||
|
|
@ -5,38 +5,35 @@
|
|||
namespace lt::renderer::vk {
|
||||
|
||||
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();
|
||||
|
||||
for (auto &gpu : gpus)
|
||||
{
|
||||
auto properties = VkPhysicalDeviceProperties {};
|
||||
auto features = VkPhysicalDeviceFeatures2 {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
|
||||
.pNext = &m_descriptor_indexing_features
|
||||
};
|
||||
auto features = VkPhysicalDeviceFeatures {};
|
||||
|
||||
vk_get_physical_device_properties(gpu, &properties);
|
||||
vk_get_physical_device_features(gpu, &features);
|
||||
|
||||
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|
||||
&& features.features.geometryShader)
|
||||
&& features.geometryShader)
|
||||
{
|
||||
m_gpu = gpu;
|
||||
}
|
||||
}
|
||||
ensure(m_gpu, "Failed to find any suitable Vulkan physical device");
|
||||
}
|
||||
|
||||
|
||||
vk_get_physical_device_memory_properties(m_gpu, &m_memory_properties);
|
||||
|
||||
[[nodiscard]] auto Gpu::get_queue_family_properties() const -> std::vector<VkQueueFamilyProperties>
|
||||
{
|
||||
auto count = uint32_t { 0u };
|
||||
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(
|
||||
|
|
@ -70,11 +67,5 @@ Gpu::Gpu(IInstance *instance)
|
|||
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
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@ class Gpu: public IGpu
|
|||
public:
|
||||
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(
|
||||
VkSurfaceKHR surface,
|
||||
uint32_t queue_family_idx
|
||||
|
|
@ -23,39 +30,8 @@ public:
|
|||
[[nodiscard]] auto get_surface_formats(VkSurfaceKHR surface) const
|
||||
-> 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:
|
||||
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
|
||||
|
|
|
|||
|
|
@ -29,9 +29,8 @@ PFN_vkGetPhysicalDeviceQueueFamilyProperties vk_get_physical_device_queue_family
|
|||
PFN_vkCreateDevice vk_create_device {};
|
||||
PFN_vkGetDeviceProcAddr vk_get_device_proc_address {};
|
||||
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_vkGetPhysicalDeviceMemoryProperties vk_get_physical_device_memory_properties {};
|
||||
|
||||
// extension instance functions
|
||||
PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label {};
|
||||
|
|
@ -87,37 +86,15 @@ PFN_vkCmdBindPipeline vk_cmd_bind_pipeline {};
|
|||
PFN_vkCmdDraw vk_cmd_draw {};
|
||||
PFN_vkCmdSetViewport vk_cmd_set_viewport {};
|
||||
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_vkCmdBeginRendering vk_cmd_begin_rendering {};
|
||||
PFN_vkCmdEndRendering vk_cmd_end_rendering {};
|
||||
|
||||
PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {};
|
||||
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vk_get_physical_device_surface_capabilities {};
|
||||
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vk_get_physical_device_surface_formats {};
|
||||
|
||||
auto vk_create_xlib_surface_khr = PFN_vkCreateXlibSurfaceKHR {};
|
||||
auto vk_destroy_surface_khr = PFN_vkDestroySurfaceKHR {};
|
||||
|
||||
// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
Instance::Instance()
|
||||
|
|
@ -150,7 +127,6 @@ void Instance::initialize_instance()
|
|||
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
||||
VK_KHR_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";
|
||||
|
|
@ -322,7 +298,6 @@ void Instance::load_instance_functions()
|
|||
load_fn(vk_destroy_device, "vkDestroyDevice");
|
||||
load_fn(vk_get_physical_device_features, "vkGetPhysicalDeviceFeatures");
|
||||
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_end_debug_label, "vkCmdEndDebugUtilsLabelEXT");
|
||||
|
|
@ -395,26 +370,7 @@ void Instance::load_device_functions_impl(VkDevice device)
|
|||
load_fn(vk_cmd_draw, "vkCmdDraw");
|
||||
load_fn(vk_cmd_set_viewport, "vkCmdSetViewport");
|
||||
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_cmd_begin_rendering, "vkCmdBeginRendering");
|
||||
load_fn(vk_cmd_end_rendering, "vkCmdEndRendering");
|
||||
}
|
||||
|
||||
auto Instance::enumerate_gpus() const -> std::vector<VkPhysicalDevice>
|
||||
|
|
|
|||
|
|
@ -49,17 +49,6 @@ public:
|
|||
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
|
||||
-> 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,11 +1,10 @@
|
|||
#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/vulkan.hpp>
|
||||
|
||||
|
||||
namespace lt::renderer::vk::raii {
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
|
||||
class DebugMessenger
|
||||
{
|
||||
public:
|
||||
|
|
@ -17,108 +16,18 @@ public:
|
|||
|
||||
~DebugMessenger()
|
||||
{
|
||||
if (m_instance)
|
||||
if (!m_instance)
|
||||
{
|
||||
m_instance->destroy_messenger(m_object);
|
||||
return;
|
||||
}
|
||||
|
||||
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:
|
||||
memory::NullOnMove<Instance *> m_instance {};
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#include <renderer/backend/vk/context/device.hpp>
|
||||
#include <renderer/backend/vk/context/swapchain.hpp>
|
||||
#include <renderer/backend/vk/renderer/pass.hpp>
|
||||
#include <renderer/data/frame_constants.hpp>
|
||||
|
||||
namespace lt::renderer::vk {
|
||||
|
||||
|
|
@ -13,12 +12,12 @@ Pass::Pass(
|
|||
)
|
||||
: m_device(static_cast<Device *>(device))
|
||||
, m_layout(m_device->create_pipeline_layout(
|
||||
std::vector<VkPushConstantRange> {
|
||||
VkPushConstantRange {
|
||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
||||
.offset = 0u,
|
||||
.size = sizeof(FrameConstants),
|
||||
},
|
||||
VkPipelineLayoutCreateInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = 0u,
|
||||
.pSetLayouts = nullptr,
|
||||
.pushConstantRangeCount = 0u,
|
||||
.pPushConstantRanges = nullptr,
|
||||
}
|
||||
))
|
||||
{
|
||||
|
|
@ -113,16 +112,17 @@ Pass::Pass(
|
|||
.blendConstants = { 0.0f, 0.0, 0.0, 0.0 },
|
||||
};
|
||||
|
||||
// auto attachment_description = VkAttachmentDescription {
|
||||
// .format =,
|
||||
// .samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
// .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
// .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
// .stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
// .stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
// .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
// .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
// };
|
||||
|
||||
auto attachment_description = VkAttachmentDescription {
|
||||
.format = static_cast<Swapchain *>(swapchain)->get_format(),
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
};
|
||||
|
||||
auto color_attachment_ref = VkAttachmentReference {
|
||||
.attachment = 0,
|
||||
|
|
@ -144,18 +144,21 @@ Pass::Pass(
|
|||
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
};
|
||||
|
||||
auto color_format = static_cast<Swapchain *>(swapchain)->get_format();
|
||||
auto rendering_info = VkPipelineRenderingCreateInfoKHR {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
|
||||
.colorAttachmentCount = 1u,
|
||||
.pColorAttachmentFormats = &color_format,
|
||||
|
||||
};
|
||||
m_pass = m_device->create_pass(
|
||||
VkRenderPassCreateInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||
.attachmentCount = 1u,
|
||||
.pAttachments = &attachment_description,
|
||||
.subpassCount = 1u,
|
||||
.pSubpasses = &subpass_description,
|
||||
.dependencyCount = 1u,
|
||||
.pDependencies = &pass_dependency,
|
||||
}
|
||||
);
|
||||
|
||||
m_pipeline = m_device->create_graphics_pipeline(
|
||||
VkGraphicsPipelineCreateInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.pNext = &rendering_info,
|
||||
.stageCount = static_cast<uint32_t>(shader_stages.size()),
|
||||
.pStages = shader_stages.data(),
|
||||
.pVertexInputState = &vertex_input,
|
||||
|
|
@ -167,14 +170,15 @@ Pass::Pass(
|
|||
.pColorBlendState = &color_blend,
|
||||
.pDynamicState = &dynamic_state,
|
||||
.layout = m_layout,
|
||||
.renderPass = VK_NULL_HANDLE,
|
||||
.renderPass = m_pass,
|
||||
.subpass = 0u,
|
||||
.basePipelineHandle = VK_NULL_HANDLE,
|
||||
.basePipelineIndex = -1,
|
||||
}
|
||||
);
|
||||
|
||||
// m_framebuffers = static_cast<Swapchain *>(swapchain)->create_framebuffers_for_pass(m_pass);
|
||||
m_framebuffers = static_cast<Swapchain *>(swapchain)->create_framebuffers_for_pass(m_pass);
|
||||
|
||||
|
||||
m_device->destroy_shader_module(vertex_module);
|
||||
m_device->destroy_shader_module(fragment_module);
|
||||
|
|
@ -190,7 +194,7 @@ Pass::~Pass()
|
|||
m_device->wait_idle();
|
||||
m_device->destroy_framebuffers(m_framebuffers);
|
||||
m_device->destroy_pipeline(m_pipeline);
|
||||
// m_device->destroy_pass(m_pass);
|
||||
m_device->destroy_pass(m_pass);
|
||||
m_device->destroy_pipeline_layout(m_layout);
|
||||
}
|
||||
|
||||
|
|
@ -203,8 +207,7 @@ void Pass::replace_swapchain(const ISwapchain &swapchain)
|
|||
|
||||
m_device->wait_idle();
|
||||
m_device->destroy_framebuffers(m_framebuffers);
|
||||
// m_framebuffers = static_cast<const Swapchain
|
||||
// &>(swapchain).create_framebuffers_for_pass(m_pass);
|
||||
m_framebuffers = static_cast<const Swapchain &>(swapchain).create_framebuffers_for_pass(m_pass);
|
||||
}
|
||||
|
||||
auto Pass::create_module(lt::assets::Blob blob) -> VkShaderModule
|
||||
|
|
|
|||
|
|
@ -29,16 +29,16 @@ public:
|
|||
|
||||
void replace_swapchain(const ISwapchain &swapchain);
|
||||
|
||||
[[nodiscard]] auto get_pass() -> VkRenderPass
|
||||
{
|
||||
return m_pass;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_pipeline() -> VkPipeline
|
||||
{
|
||||
return m_pipeline;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_layout() -> VkPipelineLayout
|
||||
{
|
||||
return m_layout;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_framebuffers() -> std::vector<VkFramebuffer> &
|
||||
{
|
||||
return m_framebuffers;
|
||||
|
|
@ -49,6 +49,8 @@ private:
|
|||
|
||||
memory::NullOnMove<class Device *> m_device {};
|
||||
|
||||
VkRenderPass m_pass = VK_NULL_HANDLE;
|
||||
|
||||
VkPipeline m_pipeline = VK_NULL_HANDLE;
|
||||
|
||||
VkPipelineLayout m_layout = VK_NULL_HANDLE;
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ Renderer::~Renderer()
|
|||
vk_reset_command_buffer(cmd, {});
|
||||
record_cmd(cmd, *image_idx);
|
||||
|
||||
|
||||
auto wait_stage = VkPipelineStageFlags { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
|
||||
auto &submit_semaphore = m_submit_semaphores[*image_idx];
|
||||
m_device->submit(
|
||||
|
|
@ -143,52 +142,35 @@ void Renderer::replace_swapchain(ISwapchain *swapchain)
|
|||
|
||||
void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx)
|
||||
{
|
||||
const auto cmd_begin_info = VkCommandBufferBeginInfo {
|
||||
auto cmd_begin_info = VkCommandBufferBeginInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
.flags = {},
|
||||
.pInheritanceInfo = nullptr,
|
||||
};
|
||||
|
||||
const auto begin_frame_barrier = VkImageMemoryBarrier {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = {},
|
||||
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.image = m_swapchain->get_image(image_idx),
|
||||
.subresourceRange = VkImageSubresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0u,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0u,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
vkc(vk_begin_command_buffer(cmd, &cmd_begin_info));
|
||||
|
||||
auto clear_value = VkClearValue {
|
||||
.color = {
|
||||
0.93,
|
||||
0.93,
|
||||
0.93,
|
||||
1.0,
|
||||
},
|
||||
};
|
||||
|
||||
auto pass_begin_info = VkRenderPassBeginInfo {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.renderPass = m_pass->get_pass(),
|
||||
.framebuffer = m_pass->get_framebuffers()[image_idx],
|
||||
.renderArea = { .offset = {}, .extent = m_resolution },
|
||||
.clearValueCount = 1u,
|
||||
.pClearValues = &clear_value
|
||||
};
|
||||
vk_cmd_begin_render_pass(cmd, &pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
vk_cmd_bind_pipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pass->get_pipeline());
|
||||
|
||||
const auto end_frame_barrier = VkImageMemoryBarrier {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||
.dstAccessMask = {},
|
||||
.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||
.image = m_swapchain->get_image(image_idx),
|
||||
|
||||
.subresourceRange = VkImageSubresourceRange{
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0u,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0u,
|
||||
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||
},
|
||||
};
|
||||
|
||||
const auto scissor = VkRect2D {
|
||||
.offset = { .x = 0u, .y = 0u },
|
||||
.extent = m_resolution,
|
||||
};
|
||||
|
||||
const auto viewport = VkViewport {
|
||||
auto viewport = VkViewport {
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = static_cast<float>(m_resolution.width),
|
||||
|
|
@ -196,70 +178,17 @@ void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx)
|
|||
.minDepth = 0.0f,
|
||||
.maxDepth = 1.0f,
|
||||
};
|
||||
|
||||
const auto color_attachment_info = VkRenderingAttachmentInfoKHR {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
|
||||
.imageView = m_swapchain->get_image_view(image_idx),
|
||||
.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.resolveMode = VK_RESOLVE_MODE_NONE,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
.clearValue = VkClearValue { .color = { 0.93, 0.93, 0.93, 1.0 } },
|
||||
};
|
||||
|
||||
const auto rendering_info = VkRenderingInfoKHR {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
|
||||
.renderArea = scissor,
|
||||
.layerCount = 1,
|
||||
.colorAttachmentCount = 1,
|
||||
.pColorAttachments = &color_attachment_info,
|
||||
|
||||
};
|
||||
|
||||
vkc(vk_begin_command_buffer(cmd, &cmd_begin_info));
|
||||
vk_cmd_push_constants(
|
||||
cmd,
|
||||
m_pass->get_layout(),
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0u,
|
||||
sizeof(FrameConstants),
|
||||
&m_frame_constants
|
||||
);
|
||||
vk_cmd_pipeline_barrier(
|
||||
cmd,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
1,
|
||||
&begin_frame_barrier
|
||||
);
|
||||
vk_cmd_begin_rendering(cmd, &rendering_info);
|
||||
vk_cmd_bind_pipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pass->get_pipeline());
|
||||
vk_cmd_set_viewport(cmd, 0, 1, &viewport);
|
||||
|
||||
auto scissor = VkRect2D {
|
||||
.offset = { 0u, 0u },
|
||||
.extent = m_resolution,
|
||||
};
|
||||
vk_cmd_set_scissors(cmd, 0, 1, &scissor);
|
||||
|
||||
vk_cmd_draw(cmd, 3, 1, 0, 0);
|
||||
vk_cmd_end_rendering(cmd);
|
||||
vk_cmd_pipeline_barrier(
|
||||
cmd,
|
||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
1,
|
||||
&end_frame_barrier
|
||||
);
|
||||
vk_cmd_end_render_pass(cmd);
|
||||
vkc(vk_end_command_buffer(cmd));
|
||||
}
|
||||
|
||||
void submit_sprite(const components::Sprite &sprite, const math::components::Transform &transform)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace lt::renderer::vk
|
||||
|
|
|
|||
|
|
@ -3,10 +3,8 @@
|
|||
#include <memory/reference.hpp>
|
||||
#include <ranges>
|
||||
#include <renderer/backend/vk/context/device.hpp>
|
||||
#include <renderer/backend/vk/data/buffer.hpp>
|
||||
#include <renderer/backend/vk/renderer/pass.hpp>
|
||||
#include <renderer/backend/vk/utils.hpp>
|
||||
#include <renderer/frontend/data/buffer.hpp>
|
||||
#include <renderer/frontend/renderer/pass.hpp>
|
||||
#include <renderer/frontend/renderer/renderer.hpp>
|
||||
|
||||
|
|
@ -31,18 +29,6 @@ public:
|
|||
|
||||
void replace_swapchain(ISwapchain *swapchain) override;
|
||||
|
||||
void set_frame_constants(FrameConstants constants) override
|
||||
{
|
||||
m_frame_constants = constants;
|
||||
}
|
||||
|
||||
void submit_sprite(
|
||||
const components::Sprite &sprite,
|
||||
const math::components::Transform &transform
|
||||
) override
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
void record_cmd(VkCommandBuffer cmd, uint32_t image_idx);
|
||||
|
||||
|
|
@ -65,8 +51,6 @@ private:
|
|||
VkExtent2D m_resolution;
|
||||
|
||||
uint32_t m_max_frames_in_flight {};
|
||||
|
||||
FrameConstants m_frame_constants;
|
||||
};
|
||||
|
||||
} // namespace lt::renderer::vk
|
||||
|
|
|
|||
18
modules/renderer/private/backend/vk/test_utils.hpp
Normal file
18
modules/renderer/private/backend/vk/test_utils.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// template<>
|
||||
// struct std::formatter<VkExtent2D>
|
||||
// {
|
||||
// constexpr auto parse(std::format_parse_context &context)
|
||||
// {
|
||||
// return context.begin();
|
||||
// }
|
||||
//
|
||||
// auto format(const VkExtent2D &val, std::format_context &context) const
|
||||
// {
|
||||
// return std::format_to(context.out(), "{}, {}", val.width, val.height);
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// inline auto operator==(VkExtent2D lhs, VkExtent2D rhs) -> bool
|
||||
// {
|
||||
// return lhs.width == rhs.width && lhs.height == rhs.height;
|
||||
// }
|
||||
|
|
@ -13,9 +13,8 @@ extern PFN_vkGetPhysicalDeviceQueueFamilyProperties vk_get_physical_device_queue
|
|||
extern PFN_vkCreateDevice vk_create_device;
|
||||
extern PFN_vkGetDeviceProcAddr vk_get_device_proc_address;
|
||||
extern PFN_vkDestroyDevice vk_destroy_device;
|
||||
extern PFN_vkGetPhysicalDeviceFeatures2 vk_get_physical_device_features;
|
||||
extern PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features;
|
||||
extern PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties;
|
||||
extern PFN_vkGetPhysicalDeviceMemoryProperties vk_get_physical_device_memory_properties;
|
||||
|
||||
// extension instance functions
|
||||
extern PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label;
|
||||
|
|
@ -76,29 +75,8 @@ extern PFN_vkCmdBindPipeline vk_cmd_bind_pipeline;
|
|||
extern PFN_vkCmdDraw vk_cmd_draw;
|
||||
extern PFN_vkCmdSetViewport vk_cmd_set_viewport;
|
||||
extern PFN_vkCmdSetScissor vk_cmd_set_scissors;
|
||||
extern PFN_vkCmdPushConstants vk_cmd_push_constants;
|
||||
extern PFN_vkCmdCopyBuffer vk_cmd_copy_buffer;
|
||||
|
||||
extern PFN_vkCreateDescriptorSetLayout vk_create_descriptor_set_layout;
|
||||
extern PFN_vkDestroyDescriptorSetLayout vk_destroy_descriptor_set_layout;
|
||||
extern PFN_vkCreateDescriptorPool vk_create_descriptor_pool;
|
||||
extern PFN_vkDestroyDescriptorPool vk_destroy_descriptor_pool;
|
||||
extern PFN_vkAllocateDescriptorSets vk_allocate_descriptor_sets;
|
||||
extern PFN_vkFreeDescriptorSets vk_free_descriptor_sets;
|
||||
|
||||
extern PFN_vkCreateBuffer vk_create_buffer;
|
||||
extern PFN_vkDestroyBuffer vk_destroy_buffer;
|
||||
extern PFN_vkGetBufferMemoryRequirements vk_get_buffer_memory_requirements;
|
||||
extern PFN_vkAllocateMemory vk_allocate_memory;
|
||||
extern PFN_vkBindBufferMemory vk_bind_buffer_memory;
|
||||
extern PFN_vkMapMemory vk_map_memory;
|
||||
extern PFN_vkUnmapMemory vk_unmap_memory;
|
||||
extern PFN_vkFreeMemory vk_free_memory;
|
||||
|
||||
extern PFN_vkResetCommandBuffer vk_reset_command_buffer;
|
||||
|
||||
extern PFN_vkCmdBeginRendering vk_cmd_begin_rendering;
|
||||
extern PFN_vkCmdEndRendering vk_cmd_end_rendering;
|
||||
// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace lt::renderer::vk
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
#include <renderer/backend/vk/data/buffer.hpp>
|
||||
#include <renderer/frontend/data/buffer.hpp>
|
||||
|
||||
namespace lt::renderer {
|
||||
|
||||
|
||||
[[nodiscard]] /* static */ auto IBuffer::create(
|
||||
Api target_api,
|
||||
class IDevice *device,
|
||||
class IGpu *gpu,
|
||||
const CreateInfo &info
|
||||
) -> memory::Scope<IBuffer>
|
||||
{
|
||||
ensure(device, "Failed to create renderer::IBuffer: null device");
|
||||
ensure(gpu, "Failed to create renderer::IBuffer: null gpu");
|
||||
ensure(info.size > 0, "Failed to create renderer::IBuffer: null size");
|
||||
|
||||
switch (target_api)
|
||||
{
|
||||
case Api::vulkan: return memory::create_scope<vk::Buffer>(device, gpu, info);
|
||||
case Api::none:
|
||||
case Api::metal:
|
||||
case Api::direct_x: throw std::runtime_error { "Invalid API" };
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace lt::renderer
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory/scope.hpp>
|
||||
#include <renderer/api.hpp>
|
||||
|
||||
namespace lt::renderer {
|
||||
|
||||
class IBuffer
|
||||
{
|
||||
public:
|
||||
enum class Usage : uint8_t
|
||||
{
|
||||
vertex,
|
||||
|
||||
index,
|
||||
|
||||
storage,
|
||||
|
||||
staging,
|
||||
};
|
||||
|
||||
struct CreateInfo
|
||||
{
|
||||
Usage usage;
|
||||
|
||||
size_t size;
|
||||
|
||||
std::string debug_name;
|
||||
};
|
||||
|
||||
struct CopyInfo
|
||||
{
|
||||
size_t offset;
|
||||
|
||||
size_t size;
|
||||
};
|
||||
|
||||
[[nodiscard]] static auto create(
|
||||
Api target_api,
|
||||
class IDevice *device,
|
||||
class IGpu *gpu,
|
||||
const CreateInfo &info
|
||||
) -> memory::Scope<IBuffer>;
|
||||
|
||||
IBuffer() = default;
|
||||
|
||||
virtual ~IBuffer() = default;
|
||||
|
||||
IBuffer(IBuffer &&) = default;
|
||||
|
||||
IBuffer(const IBuffer &) = delete;
|
||||
|
||||
auto operator=(IBuffer &&) -> IBuffer & = default;
|
||||
|
||||
auto operator=(const IBuffer &) -> IBuffer & = delete;
|
||||
|
||||
[[nodiscard]] virtual auto map() -> std::span<std::byte> = 0;
|
||||
|
||||
virtual void unmap() = 0;
|
||||
|
||||
[[nodiscard]] virtual auto get_size() const -> size_t = 0;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace lt::renderer
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
#include <renderer/frontend/data/buffer.hpp>
|
||||
#include <renderer/test/utils.hpp>
|
||||
|
||||
using ::lt::renderer::IBuffer;
|
||||
using enum ::lt::renderer::IMessenger::MessageSeverity;
|
||||
|
||||
Suite raii = "buffer_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
|
||||
for (auto idx = 0; idx <= std::to_underlying(IBuffer::Usage::staging); ++idx)
|
||||
{
|
||||
ignore = IBuffer::create(
|
||||
lt::renderer::Api::vulkan,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
IBuffer::CreateInfo {
|
||||
.usage = static_cast<IBuffer::Usage>(idx),
|
||||
.size = 1000u,
|
||||
.debug_name = "",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
expect_false(fixture.has_any_messages_of(error));
|
||||
expect_false(fixture.has_any_messages_of(warning));
|
||||
};
|
||||
|
||||
Case { "unhappy path throws" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
|
||||
auto info = IBuffer::CreateInfo {
|
||||
.usage = IBuffer::Usage::vertex,
|
||||
.size = 10000u,
|
||||
.debug_name = "",
|
||||
};
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = IBuffer::create(lt::renderer::Api::vulkan, nullptr, fixture.gpu(), info);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = IBuffer::create(lt::renderer::Api::vulkan, fixture.device(), nullptr, info);
|
||||
});
|
||||
|
||||
expect_throw([&, info] mutable {
|
||||
info.size = 0;
|
||||
ignore = IBuffer::create(
|
||||
lt::renderer::Api::vulkan,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = IBuffer::create(
|
||||
lt::renderer::Api::direct_x,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = IBuffer::create(
|
||||
lt::renderer::Api::metal,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
expect_throw([&] {
|
||||
ignore = IBuffer::create(
|
||||
lt::renderer::Api::none,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
info
|
||||
);
|
||||
});
|
||||
|
||||
/** Make sure the default-case was OK */
|
||||
ignore = IBuffer::create(lt::renderer::Api::vulkan, fixture.device(), fixture.gpu(), info);
|
||||
|
||||
expect_false(fixture.has_any_messages_of(error));
|
||||
expect_false(fixture.has_any_messages_of(warning));
|
||||
};
|
||||
};
|
||||
|
||||
Suite mapping = "buffer_mapping"_suite = [] {
|
||||
Case { "mapping" } = [] {
|
||||
auto fixture = FixtureDeviceSwapchain {};
|
||||
|
||||
constexpr auto size = 1000u;
|
||||
|
||||
auto buffer = IBuffer::create(
|
||||
lt::renderer::Api::vulkan,
|
||||
fixture.device(),
|
||||
fixture.gpu(),
|
||||
IBuffer::CreateInfo {
|
||||
.usage = IBuffer::Usage::staging,
|
||||
.size = size,
|
||||
.debug_name = "",
|
||||
}
|
||||
);
|
||||
|
||||
auto map = buffer->map();
|
||||
expect_eq(map.size(), size);
|
||||
expect_not_nullptr(map.data());
|
||||
|
||||
expect_false(fixture.has_any_messages_of(error));
|
||||
expect_false(fixture.has_any_messages_of(warning));
|
||||
};
|
||||
};
|
||||
|
|
@ -7,7 +7,7 @@ using ::lt::renderer::IMessenger;
|
|||
|
||||
Suite raii = "pass_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
Fixture_ auto fixture = Fixture_RendererSystem {};
|
||||
auto fixture = Fixture_RendererSystem {};
|
||||
auto &system = fixture.renderer_system();
|
||||
|
||||
std::ignore = lt::renderer::IPass::create(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <math/components/transform.hpp>
|
||||
#include <memory/scope.hpp>
|
||||
#include <renderer/api.hpp>
|
||||
#include <renderer/components/sprite.hpp>
|
||||
#include <renderer/data/frame_constants.hpp>
|
||||
|
||||
namespace lt::renderer {
|
||||
|
||||
|
|
@ -44,13 +41,6 @@ public:
|
|||
[[nodiscard]] virtual auto draw(uint32_t frame_idx) -> DrawResult = 0;
|
||||
|
||||
virtual void replace_swapchain(class ISwapchain *swapchain) = 0;
|
||||
|
||||
virtual void set_frame_constants(FrameConstants constants) = 0;
|
||||
|
||||
virtual void submit_sprite(
|
||||
const components::Sprite &sprite,
|
||||
const math::components::Transform &transform
|
||||
) = 0;
|
||||
};
|
||||
|
||||
} // namespace lt::renderer
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
#include <camera/components.hpp>
|
||||
#include <math/algebra.hpp>
|
||||
#include <math/components/transform.hpp>
|
||||
#include <renderer/components/messenger.hpp>
|
||||
#include <renderer/components/sprite.hpp>
|
||||
#include <renderer/frontend/context/device.hpp>
|
||||
#include <renderer/frontend/context/gpu.hpp>
|
||||
#include <renderer/frontend/context/instance.hpp>
|
||||
|
|
@ -74,30 +70,6 @@ void System::tick(app::TickInfo tick)
|
|||
}
|
||||
}
|
||||
|
||||
auto perspective = math::mat4::identity();
|
||||
for (auto [id, camera] : m_registry->view<lt::camera::components::PerspectiveCamera>())
|
||||
{
|
||||
if (camera.is_primary)
|
||||
{
|
||||
perspective = math::perspective(
|
||||
camera.vertical_fov,
|
||||
camera.aspect_ratio,
|
||||
camera.near_plane,
|
||||
camera.far_plane
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// for each sprite, submit a new "model matrix" + "color" to go into the scene's SSBO
|
||||
for (auto &[id, sprite, transform] :
|
||||
m_registry->view<components::Sprite, math::components::Transform>())
|
||||
{
|
||||
m_renderer->submit_sprite(sprite, transform);
|
||||
}
|
||||
|
||||
m_renderer->set_frame_constants({ .view_projection = perspective });
|
||||
if (m_renderer->draw(m_frame_idx) != IRenderer::DrawResult::success)
|
||||
{
|
||||
m_swapchain.reset();
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
|
||||
|
|
@ -148,6 +148,7 @@ public:
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] auto has_any_messages() const -> bool
|
||||
{
|
||||
return m_user_data->m_has_any_messages;
|
||||
|
|
|
|||
|
|
@ -1,77 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <assets/shader.hpp>
|
||||
#include <math/vec3.hpp>
|
||||
#include <memory/reference.hpp>
|
||||
|
||||
namespace lt::renderer::components {
|
||||
|
||||
enum class VertexFormat : uint8_t
|
||||
{
|
||||
r32_g32_b32_sfloat,
|
||||
|
||||
r32_g32_sfloat,
|
||||
};
|
||||
|
||||
enum class VertexInputRate : uint8_t
|
||||
{
|
||||
per_vertex,
|
||||
|
||||
per_instance,
|
||||
};
|
||||
|
||||
struct VertexInputAttributeDescriptipn
|
||||
{
|
||||
uint32_t location;
|
||||
|
||||
uint32_t binding;
|
||||
|
||||
uint32_t offset;
|
||||
|
||||
VertexFormat format;
|
||||
};
|
||||
|
||||
struct VertexInputBindingDescription
|
||||
{
|
||||
uint32_t binding;
|
||||
|
||||
uint32_t stride;
|
||||
};
|
||||
|
||||
/** Requires a math::components::Transform component on the same entity to be functional. */
|
||||
struct Sprite
|
||||
{
|
||||
struct Vertex
|
||||
{
|
||||
math::vec3 position;
|
||||
|
||||
math::vec3 color;
|
||||
|
||||
[[nodiscard]] constexpr static auto get_attributes()
|
||||
-> std::array<VertexInputAttributeDescriptipn, 2>
|
||||
{
|
||||
return {
|
||||
VertexInputAttributeDescriptipn {
|
||||
.location = 0u,
|
||||
.binding = 0u,
|
||||
.offset = offsetof(Sprite::Vertex, position),
|
||||
.format = VertexFormat::r32_g32_b32_sfloat,
|
||||
|
||||
},
|
||||
|
||||
VertexInputAttributeDescriptipn {
|
||||
.location = 1u,
|
||||
.binding = 0u,
|
||||
.offset = offsetof(Sprite::Vertex, color),
|
||||
.format = VertexFormat::r32_g32_b32_sfloat,
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
memory::Ref<assets::ShaderAsset> vertex_shader;
|
||||
|
||||
memory::Ref<assets::ShaderAsset> fragment_shader;
|
||||
};
|
||||
|
||||
} // namespace lt::renderer::components
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <math/mat4.hpp>
|
||||
|
||||
namespace lt::renderer {
|
||||
|
||||
struct FrameConstants
|
||||
{
|
||||
math::mat4 view_projection;
|
||||
};
|
||||
|
||||
} // namespace lt::renderer
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace lt::renderer {
|
||||
|
||||
|
||||
class IMessenger
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -55,6 +55,31 @@ public:
|
|||
|
||||
void tick(app::TickInfo tick) override;
|
||||
|
||||
[[nodiscard]] auto get_surface() -> class ISurface *
|
||||
{
|
||||
return m_surface.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_gpu() -> class IGpu *
|
||||
{
|
||||
return m_gpu.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_device() -> class IDevice *
|
||||
{
|
||||
return m_device.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_swapchain() -> class ISwapchain *
|
||||
{
|
||||
return m_swapchain.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_renderer() -> class IRenderer *
|
||||
{
|
||||
return m_renderer.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override
|
||||
{
|
||||
return m_last_tick_result;
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ add_library_module(fuzz_test test.cpp fuzz.cpp)
|
|||
target_link_libraries(test PUBLIC tbb logger)
|
||||
target_link_libraries(fuzz_test PUBLIC tbb logger)
|
||||
|
||||
add_test_module(test test.test.cpp)
|
||||
add_test_module(test test.test.cpp mock.test.cpp)
|
||||
|
|
|
|||
52
modules/test/private/mock.test.cpp
Normal file
52
modules/test/private/mock.test.cpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include <test/mock.hpp>
|
||||
#include <test/test.hpp>
|
||||
|
||||
using namespace lt::test;
|
||||
using namespace lt::test::mock;
|
||||
|
||||
class ExpensiveClass
|
||||
{
|
||||
private:
|
||||
public:
|
||||
virtual int expensive(std::string str, std::optional<int> opt)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
class MockClass: public ExpensiveClass
|
||||
{
|
||||
public:
|
||||
int expensive(std::string str, std::optional<int> opt) override
|
||||
{
|
||||
return expensive_mock(str, opt);
|
||||
};
|
||||
|
||||
Mock<int(std::string, std::optional<int>)> expensive_mock {};
|
||||
};
|
||||
|
||||
class ExpensiveUser
|
||||
{
|
||||
public:
|
||||
ExpensiveUser(ExpensiveClass &dependency)
|
||||
{
|
||||
dependency.expensive("", 10);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// problem #1: matcher functions should construct an invokable object to test against the indexed
|
||||
// argument.
|
||||
|
||||
Suite raii = "mock_raii"_suite = [] {
|
||||
Case { "happy path won't throw" } = [] {
|
||||
auto a = std::function<int(int)> {};
|
||||
auto expensive = MockClass {};
|
||||
auto side_effect = false;
|
||||
expensive.expensive_mock.expect("test", std::nullopt)
|
||||
.apply([&](auto str, auto opt) { side_effect = true; })
|
||||
.returns(69);
|
||||
|
||||
auto user = ExpensiveUser { expensive };
|
||||
};
|
||||
};
|
||||
94
modules/test/public/mock.hpp
Normal file
94
modules/test/public/mock.hpp
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#pragma once
|
||||
|
||||
namespace lt::test {
|
||||
|
||||
template<typename _Signature>
|
||||
class Mock;
|
||||
|
||||
template<typename Return_Type, typename... Arg_Types>
|
||||
class Mock<Return_Type(Arg_Types...)>
|
||||
{
|
||||
public:
|
||||
auto at_least() -> Mock &
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator&&(Mock &mock) -> Mock &
|
||||
{
|
||||
return mock;
|
||||
}
|
||||
|
||||
auto operator()(Arg_Types... arguments) -> Return_Type
|
||||
{
|
||||
++m_call_index;
|
||||
|
||||
for (auto &side_effect : m_side_effects)
|
||||
{
|
||||
side_effect(std::forward<Arg_Types>(arguments)...);
|
||||
}
|
||||
|
||||
if (m_return_func)
|
||||
{
|
||||
return m_return_func(std::forward<Arg_Types>(arguments)...);
|
||||
}
|
||||
return m_return_value;
|
||||
}
|
||||
|
||||
/** With any arguments. */
|
||||
template<uint32_t counter = 1>
|
||||
auto expect() -> Mock &
|
||||
{
|
||||
m_expected_counter = counter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto apply(std::function<void(Arg_Types...)> side_effect) -> Mock &
|
||||
{
|
||||
m_side_effects.emplace_back(std::move(side_effect));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Returns a fixed value. */
|
||||
auto returns(Return_Type value) -> Mock &
|
||||
{
|
||||
m_return_value = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Returns a value based on input. */
|
||||
auto returns(std::function<Return_Type(Arg_Types...)> func) -> Mock &
|
||||
{
|
||||
m_return_func = std::move(func);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
Return_Type m_return_value {};
|
||||
|
||||
std::function<Return_Type(Arg_Types...)> m_return_func {};
|
||||
|
||||
std::vector<std::function<void(Arg_Types...)>> m_side_effects {};
|
||||
|
||||
uint32_t m_call_index = 0;
|
||||
|
||||
std::vector<std::pair<std::tuple<Arg_Types...>, uint32_t>> m_expected_args;
|
||||
|
||||
uint32_t m_expected_counter {};
|
||||
};
|
||||
|
||||
namespace mock::range {
|
||||
|
||||
[[nodiscard]] auto is_empty() -> bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}; // namespace mock::range
|
||||
|
||||
[[nodiscard]] auto eq(auto rhs) -> bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace lt::test
|
||||
|
|
@ -220,7 +220,7 @@ tar xf 'vulkansdk-linux-x86_64-1.4.328.1.tar.xz' \
|
|||
-fsanitize-ignorelist=/msan/ignorelist_all_sources \
|
||||
-fno-omit-frame-pointer \
|
||||
-g \
|
||||
-std=c++26 \
|
||||
-std=c++23 \
|
||||
-nostdinc++ \
|
||||
-isystem /libcxx_msan/include/c++/v1/"\
|
||||
&& export CFLAGS="\
|
||||
|
|
@ -233,7 +233,7 @@ tar xf 'vulkansdk-linux-x86_64-1.4.328.1.tar.xz' \
|
|||
-fsanitize-memory-track-origins \
|
||||
-fsanitize-ignorelist=/msan/ignorelist_all_sources \
|
||||
-g \
|
||||
-std=c++26 \
|
||||
-std=c++23 \
|
||||
-L/msan/lib -Wl,-rpath,/msan/lib \
|
||||
-L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib \
|
||||
-lc++ \
|
||||
|
|
@ -272,7 +272,7 @@ export CXXFLAGS="\
|
|||
-fsanitize-ignorelist=/msan/ignorelist_all_sources \
|
||||
-fno-omit-frame-pointer \
|
||||
-g \
|
||||
-std=c++26 \
|
||||
-std=c++23 \
|
||||
-nostdinc++ \
|
||||
-isystem /libcxx_msan/include/c++/v1/"\
|
||||
&& export CFLAGS="\
|
||||
|
|
@ -285,7 +285,7 @@ export CXXFLAGS="\
|
|||
-fsanitize-memory-track-origins \
|
||||
-fsanitize-ignorelist=/msan/ignorelist_all_sources \
|
||||
-g \
|
||||
-std=c++26 \
|
||||
-std=c++23 \
|
||||
-L/msan/lib -Wl,-rpath,/msan/lib \
|
||||
-L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib \
|
||||
-lc++ \
|
||||
|
|
|
|||
|
|
@ -34,14 +34,14 @@ cmake \
|
|||
-fsanitize-memory-track-origins \
|
||||
-g \
|
||||
-fno-omit-frame-pointer \
|
||||
-std=c++26 \
|
||||
-std=c++23 \
|
||||
-nostdinc++ \
|
||||
-isystem /libcxx_msan/include/c++/v1/" \
|
||||
-D CMAKE_EXE_LINKER_FLAGS=" \
|
||||
-fsanitize=memory \
|
||||
-fsanitize-memory-track-origins \
|
||||
-g \
|
||||
-std=c++26 \
|
||||
-std=c++23 \
|
||||
-L/msan/lib -Wl,-rpath,/msan/lib \
|
||||
-L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib \
|
||||
-lc++ \
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ cmake \
|
|||
-D CMAKE_LINKER_TYPE=MOLD \
|
||||
-D ENABLE_UNIT_TESTS=ON \
|
||||
-D CMAKE_BUILD_TYPE=Release \
|
||||
-D CMAKE_CXX_FLAGS="-std=c++26 -g -fno-omit-frame-pointer"
|
||||
-D CMAKE_CXX_FLAGS="-std=c++23 -g -fno-omit-frame-pointer"
|
||||
|
||||
cmake --build ./build -j"$(nproc)"
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ cmake \
|
|||
-D CMAKE_LINKER_TYPE=MOLD \
|
||||
-D ENABLE_UNIT_TESTS=ON \
|
||||
-D CMAKE_BUILD_TYPE=Release \
|
||||
-D CMAKE_CXX_FLAGS="-std=c++26 -fno-omit-frame-pointer -fno-common -g"
|
||||
-D CMAKE_CXX_FLAGS="-std=c++23 -fno-omit-frame-pointer -fno-common -g"
|
||||
|
||||
cmake --build ./build -j"$(nproc)"
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,6 @@ cmake \
|
|||
-D ENABLE_UNIT_TESTS=ON \
|
||||
-D ENABLE_STATIC_ANALYSIS=ON \
|
||||
-D CMAKE_BUILD_TYPE=Release \
|
||||
-D CMAKE_CXX_FLAGS="-std=c++26 -stdlib=libc++"
|
||||
-D CMAKE_CXX_FLAGS="-std=c++23 -stdlib=libc++"
|
||||
|
||||
cmake --build . -j"$(nproc)"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue