Compare commits
	
		
			14 commits
		
	
	
		
			ci/msan_fi
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d029c0e473 | |||
| 604ee5e6a1 | |||
| 7ee4381bbf | |||
| 8730d31e2f | |||
| f50208653e | |||
| 5422792705 | |||
| 2ddb90faff | |||
| 736c37d2f1 | |||
| 97ca429d38 | |||
| 5a404d5269 | |||
| a9e27d6935 | |||
| 80662983a3 | |||
| c39ce89a9b | |||
| f1a91c9b81 | 
					 57 changed files with 1631 additions and 734 deletions
				
			
		
							
								
								
									
										5
									
								
								.clangd
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.clangd
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,5 @@ | |||
| CompileFlags: | ||||
|   DriverMode: cl | ||||
|   Add: | ||||
|     - /EHsc | ||||
|     - /std:c++latest | ||||
|  | @ -155,3 +155,4 @@ steps: | |||
| 
 | ||||
|     - rm -rf /light_docs/* | ||||
|     - mv ./html/* /light_docs/ | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,128 +0,0 @@ | |||
| # 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,21 +1,26 @@ | |||
| #version 450 core | ||||
| 
 | ||||
| vec2 positions[3] = vec2[]( | ||||
|     vec2(0.0, -0.5), | ||||
|     vec2(0.5, 0.5), | ||||
|     vec2(-0.5, 0.5) | ||||
| 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) | ||||
| ); | ||||
| 
 | ||||
| vec3 colors[3] = vec3[]( | ||||
|     vec3(1.0, 0.0, 0.0), | ||||
|     vec3(0.0, 1.0, 0.0), | ||||
|     vec3(0.0, 0.0, 1.0) | ||||
|     vec3(0.0, 0.0, 0.0), | ||||
|     vec3(0.0, 0.0, 0.0), | ||||
|     vec3(0.0, 0.0, 0.0) | ||||
| ); | ||||
| 
 | ||||
| layout(location = 0) out vec3 out_frag_color; | ||||
| 
 | ||||
| void main()  | ||||
| { | ||||
|     gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); | ||||
|     gl_Position = view_projection * vec4(positions[gl_VertexIndex], 1.0); | ||||
|     out_frag_color = colors[gl_VertexIndex]; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
										
											Binary file not shown.
										
									
								
							|  | @ -2,18 +2,25 @@ | |||
| 
 | ||||
| namespace lt::assets { | ||||
| 
 | ||||
| constexpr auto total_metadata_size =         //
 | ||||
|     sizeof(AssetMetadata::type)              //
 | ||||
|     + sizeof(AssetMetadata::version)         //
 | ||||
|     + sizeof(ShaderAsset::Metadata::type)    //
 | ||||
|     + sizeof(BlobMetadata::tag)              //
 | ||||
|     + sizeof(BlobMetadata::offset)           //
 | ||||
|     + sizeof(BlobMetadata::compression_type) //
 | ||||
|     + sizeof(BlobMetadata::compressed_size)  //
 | ||||
|     + sizeof(BlobMetadata::uncompressed_size); | ||||
| 
 | ||||
| ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path) | ||||
| { | ||||
| 	constexpr auto total_metadata_size = //
 | ||||
| 	    sizeof(AssetMetadata)            //
 | ||||
| 	    + sizeof(Metadata)               //
 | ||||
| 	    + sizeof(BlobMetadata); | ||||
| 
 | ||||
| 	ensure(m_stream.is_open(), "Failed to open shader asset at: {}", path.string()); | ||||
| 	const auto read = [this](auto &field) { | ||||
| 		m_stream.read(std::bit_cast<char *>(&field), sizeof(field)); | ||||
| 	}; | ||||
| 
 | ||||
| 	m_stream.seekg(0, std::ifstream::end); | ||||
| 	const auto file_size = static_cast<size_t>(m_stream.tellg()); | ||||
| 
 | ||||
| 	ensure( | ||||
| 	    file_size > total_metadata_size, | ||||
| 	    "Failed to open shader asset at: {}, file smaller than metadata: {} < {}", | ||||
|  | @ -22,12 +29,15 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path) | |||
| 	    file_size | ||||
| 	); | ||||
| 
 | ||||
| 	// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||
| 	m_stream.seekg(0, std::ifstream::beg); | ||||
| 	m_stream.read((char *)&m_asset_metadata, sizeof(m_asset_metadata)); | ||||
| 	m_stream.read((char *)&m_metadata, sizeof(m_metadata)); | ||||
| 	m_stream.read((char *)&m_code_blob_metadata, sizeof(m_code_blob_metadata)); | ||||
| 	// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||
| 	read(m_asset_metadata.type); | ||||
| 	read(m_asset_metadata.version); | ||||
| 	read(m_metadata.type); | ||||
| 	read(m_code_blob_metadata.tag); | ||||
| 	read(m_code_blob_metadata.offset); | ||||
| 	read(m_code_blob_metadata.compression_type); | ||||
| 	read(m_code_blob_metadata.compressed_size); | ||||
| 	read(m_code_blob_metadata.uncompressed_size); | ||||
| 
 | ||||
| 	ensure( | ||||
| 	    m_asset_metadata.type == asset_type_identifier, | ||||
|  | @ -69,4 +79,70 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path) | |||
| 	); | ||||
| } | ||||
| 
 | ||||
| /* static */ void ShaderAsset::pack( | ||||
|     const std::filesystem::path &destination, | ||||
|     AssetMetadata asset_metadata, | ||||
|     Metadata metadata, | ||||
|     Blob code_blob | ||||
| ) | ||||
| { | ||||
| 	auto stream = std::ofstream { | ||||
| 		destination, | ||||
| 		std::ios::binary | std::ios::trunc, | ||||
| 	}; | ||||
| 
 | ||||
| 	const auto code_blob_metadata = BlobMetadata { | ||||
| 		.tag = std::to_underlying(BlobTag::code), | ||||
| 		.offset = total_metadata_size, | ||||
| 		.compression_type = CompressionType::none, | ||||
| 		.compressed_size = code_blob.size(), | ||||
| 		.uncompressed_size = code_blob.size(), | ||||
| 	}; | ||||
| 
 | ||||
| 	ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string()); | ||||
| 	const auto write = [&stream](auto &field) { | ||||
| 		stream.write(std::bit_cast<char *>(&field), sizeof(field)); | ||||
| 	}; | ||||
| 	write(asset_metadata.type); | ||||
| 	write(asset_metadata.version); | ||||
| 	write(metadata.type); | ||||
| 	write(code_blob_metadata.tag); | ||||
| 	write(code_blob_metadata.offset); | ||||
| 	write(code_blob_metadata.compression_type); | ||||
| 	write(code_blob_metadata.compressed_size); | ||||
| 	write(code_blob_metadata.uncompressed_size); | ||||
| 	stream.write(std::bit_cast<char *>(code_blob.data()), static_cast<long long>(code_blob.size())); | ||||
| } | ||||
| 
 | ||||
| void ShaderAsset::unpack_to(BlobTag tag, std::span<std::byte> destination) const | ||||
| { | ||||
| 	ensure(tag == BlobTag::code, "Invalid blob tag for shader asset: {}", std::to_underlying(tag)); | ||||
| 
 | ||||
| 	ensure( | ||||
| 	    destination.size() >= m_code_blob_metadata.uncompressed_size, | ||||
| 	    "Failed to unpack shader blob {} to destination ({}) of size {} since it's smaller " | ||||
| 	    "than the blobl's uncompressed size: {}", | ||||
| 	    std::to_underlying(tag), | ||||
| 	    std::bit_cast<size_t>(destination.data()), | ||||
| 	    destination.size(), | ||||
| 	    m_code_blob_metadata.uncompressed_size | ||||
| 	); | ||||
| 
 | ||||
| 	m_stream.seekg(static_cast<long long>(m_code_blob_metadata.offset)); | ||||
| 	m_stream.read( | ||||
| 	    std::bit_cast<char *>(destination.data()), | ||||
| 	    static_cast<long long>(m_code_blob_metadata.uncompressed_size) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| [[nodiscard]] auto ShaderAsset::unpack(BlobTag tag) const -> Blob | ||||
| { | ||||
| 	ensure(tag == BlobTag::code, "Invalid blob tag for shader asset: {}", std::to_underlying(tag)); | ||||
| 
 | ||||
| 	auto blob = Blob(m_code_blob_metadata.uncompressed_size); | ||||
| 	unpack_to(tag, blob); | ||||
| 
 | ||||
| 	return blob; | ||||
| } | ||||
| 
 | ||||
| } // namespace lt::assets
 | ||||
|  |  | |||
|  | @ -41,9 +41,14 @@ Suite packing = "shader_pack"_suite = [] { | |||
| 		} | ||||
| 
 | ||||
| 		const auto expected_size =                    //
 | ||||
| 		    sizeof(AssetMetadata)           //
 | ||||
| 		    + sizeof(ShaderAsset::Metadata) //
 | ||||
| 		    + sizeof(BlobMetadata)          //
 | ||||
| 		    sizeof(AssetMetadata::type)               //
 | ||||
| 		    + sizeof(AssetMetadata::version)          //
 | ||||
| 		    + sizeof(ShaderAsset::Metadata::type)     //
 | ||||
| 		    + sizeof(BlobMetadata::tag)               //
 | ||||
| 		    + sizeof(BlobMetadata::offset)            //
 | ||||
| 		    + sizeof(BlobMetadata::compression_type)  //
 | ||||
| 		    + sizeof(BlobMetadata::compressed_size)   //
 | ||||
| 		    + sizeof(BlobMetadata::uncompressed_size) //
 | ||||
| 		    + dummy_blob.size(); | ||||
| 
 | ||||
| 		ShaderAsset::pack( | ||||
|  |  | |||
|  | @ -32,33 +32,14 @@ public: | |||
| 	    AssetMetadata asset_metadata, | ||||
| 	    Metadata metadata, | ||||
| 	    Blob code_blob | ||||
| 	) | ||||
| 	{ | ||||
| 		auto stream = std::ofstream { | ||||
| 			destination, | ||||
| 			std::ios::binary | std::ios::trunc, | ||||
| 		}; | ||||
| 		ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string()); | ||||
| 
 | ||||
| 		// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||
| 		stream.write((char *)&asset_metadata, sizeof(asset_metadata)); | ||||
| 		stream.write((char *)&metadata, sizeof(metadata)); | ||||
| 
 | ||||
| 		auto code_blob_metadata = BlobMetadata { | ||||
| 			.tag = std::to_underlying(BlobTag::code), | ||||
| 			.offset = static_cast<size_t>(stream.tellp()) + sizeof(BlobMetadata), | ||||
| 			.compression_type = CompressionType::none, | ||||
| 			.compressed_size = code_blob.size(), | ||||
| 			.uncompressed_size = code_blob.size(), | ||||
| 		}; | ||||
| 		stream.write((char *)&code_blob_metadata, sizeof(BlobMetadata)); | ||||
| 
 | ||||
| 		stream.write((char *)code_blob.data(), static_cast<long long>(code_blob.size())); | ||||
| 		// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||
| 	} | ||||
| 	); | ||||
| 
 | ||||
| 	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; | ||||
|  | @ -80,45 +61,6 @@ public: | |||
| 		return m_code_blob_metadata; | ||||
| 	} | ||||
| 
 | ||||
| 	void unpack_to(BlobTag tag, std::span<std::byte> destination) const | ||||
| 	{ | ||||
| 		ensure( | ||||
| 		    tag == BlobTag::code, | ||||
| 		    "Invalid blob tag for shader asset: {}", | ||||
| 		    std::to_underlying(tag) | ||||
| 		); | ||||
| 
 | ||||
| 		ensure( | ||||
| 		    destination.size() >= m_code_blob_metadata.uncompressed_size, | ||||
| 		    "Failed to unpack shader blob {} to destination ({}) of size {} since it's smaller " | ||||
| 		    "than the blobl's uncompressed size: {}", | ||||
| 		    std::to_underlying(tag), | ||||
| 		    (size_t)(destination.data()), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||
| 		    destination.size(), | ||||
| 		    m_code_blob_metadata.uncompressed_size | ||||
| 		); | ||||
| 
 | ||||
| 		m_stream.seekg(static_cast<long long>(m_code_blob_metadata.offset)); | ||||
| 		m_stream.read( | ||||
| 		    (char *)destination.data(), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast)
 | ||||
| 		    static_cast<long long>(m_code_blob_metadata.uncompressed_size) | ||||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 	[[nodiscard]] auto unpack(BlobTag tag) const -> Blob | ||||
| 	{ | ||||
| 		ensure( | ||||
| 		    tag == BlobTag::code, | ||||
| 		    "Invalid blob tag for shader asset: {}", | ||||
| 		    std::to_underlying(tag) | ||||
| 		); | ||||
| 
 | ||||
| 		auto blob = Blob(m_code_blob_metadata.uncompressed_size); | ||||
| 		unpack_to(tag, blob); | ||||
| 
 | ||||
| 		return blob; | ||||
| 	} | ||||
| 
 | ||||
| private: | ||||
| 	AssetMetadata m_asset_metadata {}; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,3 @@ | |||
| add_library_module(camera camera.cpp scene.cpp) | ||||
| add_library_module(camera) | ||||
| 
 | ||||
| target_link_libraries(camera PUBLIC math) | ||||
| target_link_libraries(camera INTERFACE math) | ||||
|  |  | |||
|  | @ -1,6 +0,0 @@ | |||
| #include <camera/camera.hpp> | ||||
| 
 | ||||
| namespace lt { | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | @ -1,84 +0,0 @@ | |||
| #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
 | ||||
|  | @ -1,35 +0,0 @@ | |||
| #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
 | ||||
|  | @ -1,29 +0,0 @@ | |||
| #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
 | ||||
							
								
								
									
										22
									
								
								modules/camera/public/components.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								modules/camera/public/components.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| #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
 | ||||
|  | @ -1,100 +0,0 @@ | |||
| #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,25 +31,29 @@ namespace lt::math { | |||
|  * | ||||
|  * the 1 at [z][3] is to save the Z axis into the resulting W for perspective division. | ||||
|  * | ||||
|  * thanks to pikuma: https://www.youtube.com/watch?v=EqNcqBdrNyI
 | ||||
|  * @ref Thanks to pikuma for explaining the math behind this: | ||||
|  * 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> { T { 0 } }; | ||||
| 	auto result = mat4_impl<T>::identity(); | ||||
| 
 | ||||
| 	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_near) / (z_far - z_near);
 | ||||
| 	//
 | ||||
| 	result[2][2] = z_far / (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] = -(T { 2 } * z_far * z_near) / (z_far - z_near);
 | ||||
| 	result[3][2] = -(z_far * z_near) / (z_far - z_near); | ||||
| 	//
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ template<typename T = float> | |||
| struct mat4_impl | ||||
| { | ||||
| 	using Column_T = vec4_impl<T>; | ||||
| 
 | ||||
| 	constexpr explicit mat4_impl(T scalar = 0) | ||||
| 	    : values( | ||||
| 	          { | ||||
|  | @ -43,7 +44,7 @@ struct mat4_impl | |||
| 	{ | ||||
| 	} | ||||
| 
 | ||||
| 	[[nodiscard]] constexpr auto identity() -> mat4_impl<T> | ||||
| 	[[nodiscard]] static constexpr auto identity() -> mat4_impl<T> | ||||
| 	{ | ||||
| 		return mat4_impl<T> { | ||||
| 			{ 1 }, {},    {},    {},    //
 | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| 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( | ||||
|     libmirror layers/editor_layer.test.cpp panels/asset_browser.test.cpp | ||||
|  |  | |||
|  | @ -2,9 +2,11 @@ | |||
| #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> | ||||
|  | @ -66,13 +68,18 @@ 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) | ||||
| 			{ | ||||
| 				surface.push_request(surface::ModifyPositionRequest({ x + 5, y + 5 })); | ||||
| 				for (auto &[id, camera] : | ||||
| 				     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) | ||||
|  | @ -219,6 +226,20 @@ 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() | ||||
|  | @ -245,6 +266,8 @@ 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,21 +8,29 @@ 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 | ||||
|     # Vulkan - frontend | ||||
|     # 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 | ||||
|     PUBLIC app | ||||
|            ecs | ||||
|            memory | ||||
|            assets | ||||
|            time | ||||
|            bitwise | ||||
|            camera | ||||
|     PRIVATE surface pthread) | ||||
| 
 | ||||
| add_test_module( | ||||
|  | @ -34,11 +42,10 @@ add_test_module( | |||
|     frontend/context/surface.test.cpp | ||||
|     frontend/context/device.test.cpp | ||||
|     frontend/context/swapchain.test.cpp | ||||
|     frontend/renderer/pass.test.cpp | ||||
|     frontend/data/buffer.test.cpp | ||||
|     # frontend/renderer/pass.test.cpp | ||||
|     frontend/renderer/renderer.test.cpp | ||||
|     # backend specific tests -- vk | ||||
|     backend/vk/context/instance.test.cpp | ||||
|     # backend specific tests -- dx backend specific tests -- mt | ||||
| ) | ||||
|     backend/vk/context/instance.test.cpp) | ||||
| 
 | ||||
| target_link_libraries(renderer_tests PRIVATE surface pthread) | ||||
|  |  | |||
|  | @ -75,10 +75,17 @@ 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()), | ||||
|  | @ -207,6 +214,31 @@ 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 {}; | ||||
|  | @ -251,9 +283,18 @@ void Device::wait_for_fences(std::span<VkFence> fences) const | |||
| 	return pass; | ||||
| } | ||||
| 
 | ||||
| [[nodiscard]] auto Device::create_pipeline_layout(VkPipelineLayoutCreateInfo info) const | ||||
|     -> VkPipelineLayout | ||||
| [[nodiscard]] auto Device::create_pipeline_layout( | ||||
|     std::vector<VkPushConstantRange> push_constant_ranges | ||||
| ) 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; | ||||
|  | @ -299,6 +340,13 @@ void Device::wait_for_fences(std::span<VkFence> fences) const | |||
| 	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> | ||||
| { | ||||
|  | @ -307,6 +355,18 @@ void Device::wait_for_fences(std::span<VkFence> fences) const | |||
| 	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); | ||||
|  | @ -389,4 +449,9 @@ 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,6 +96,16 @@ 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; | ||||
| 
 | ||||
|  | @ -108,8 +118,9 @@ public: | |||
| 
 | ||||
| 	[[nodiscard]] auto create_pass(VkRenderPassCreateInfo info) const -> VkRenderPass; | ||||
| 
 | ||||
| 	[[nodiscard]] auto create_pipeline_layout(VkPipelineLayoutCreateInfo info) const | ||||
| 	    -> VkPipelineLayout; | ||||
| 	[[nodiscard]] auto create_pipeline_layout( | ||||
| 	    std::vector<VkPushConstantRange> push_constant_ranges | ||||
| 	) const -> VkPipelineLayout; | ||||
| 
 | ||||
| 	[[nodiscard]] auto create_shader_module(VkShaderModuleCreateInfo info) const -> VkShaderModule; | ||||
| 
 | ||||
|  | @ -120,10 +131,17 @@ 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; | ||||
| 
 | ||||
|  | @ -153,6 +171,8 @@ 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,35 +5,38 @@ | |||
| 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 = VkPhysicalDeviceFeatures {}; | ||||
| 		auto features = VkPhysicalDeviceFeatures2 { | ||||
| 			.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, | ||||
| 			.pNext = &m_descriptor_indexing_features | ||||
| 		}; | ||||
| 
 | ||||
| 		vk_get_physical_device_properties(gpu, &properties); | ||||
| 		vk_get_physical_device_features(gpu, &features); | ||||
| 
 | ||||
| 		if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU | ||||
| 		    && features.geometryShader) | ||||
| 		    && features.features.geometryShader) | ||||
| 		{ | ||||
| 			m_gpu = gpu; | ||||
| 		} | ||||
| 	} | ||||
| 	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 }; | ||||
| 	vk_get_physical_device_queue_family_properties(m_gpu, &count, nullptr); | ||||
| 
 | ||||
| 	auto properties = std::vector<VkQueueFamilyProperties>(count); | ||||
| 	vk_get_physical_device_queue_family_properties(m_gpu, &count, properties.data()); | ||||
| 
 | ||||
| 	return properties; | ||||
| 	m_queue_family_properties.resize(count); | ||||
| 	vk_get_physical_device_queue_family_properties(m_gpu, &count, m_queue_family_properties.data()); | ||||
| } | ||||
| 
 | ||||
| [[nodiscard]] auto Gpu::queue_family_supports_presentation( | ||||
|  | @ -67,5 +70,11 @@ 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,13 +12,6 @@ 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 | ||||
|  | @ -30,8 +23,39 @@ 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,8 +29,9 @@ 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_vkGetPhysicalDeviceFeatures vk_get_physical_device_features {}; | ||||
| PFN_vkGetPhysicalDeviceFeatures2 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 {}; | ||||
|  | @ -86,15 +87,37 @@ 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() | ||||
|  | @ -127,6 +150,7 @@ 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"; | ||||
|  | @ -217,6 +241,7 @@ void Instance::initialize_instance() | |||
| 		vkc(vk_enumerate_instance_extension_properties(nullptr, &count, nullptr)); | ||||
| 
 | ||||
| 		auto extensions = std::vector<VkExtensionProperties>(count); | ||||
| 		memset(extensions.data(), 0, extensions.size() * sizeof(VkExtensionProperties)); | ||||
| 		vkc(vk_enumerate_instance_extension_properties(nullptr, &count, extensions.data())); | ||||
| 
 | ||||
| 		// log_inf("Available vulkan instance extensions:");
 | ||||
|  | @ -232,7 +257,7 @@ void Instance::initialize_instance() | |||
| 
 | ||||
| void Instance::load_library() | ||||
| { | ||||
| 	constexpr auto runtime_loader_flags = RTLD_NOW | RTLD_DEEPBIND | RTLD_LOCAL | RTLD_NODELETE; | ||||
| 	constexpr auto runtime_loader_flags = RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE; | ||||
| 	library = dlopen("libvulkan.so.1", runtime_loader_flags); | ||||
| 	if (!library) | ||||
| 	{ | ||||
|  | @ -297,6 +322,7 @@ 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"); | ||||
|  | @ -369,7 +395,26 @@ 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> | ||||
|  |  | |||
|  | @ -75,7 +75,6 @@ private: | |||
| 	void load_instance_functions(); | ||||
| 
 | ||||
| 	void load_device_functions_impl(VkDevice device); | ||||
| 
 | ||||
| 	VkInstance m_instance = VK_NULL_HANDLE; | ||||
| 
 | ||||
| 	VkAllocationCallbacks *m_allocator = nullptr; | ||||
|  |  | |||
|  | @ -49,6 +49,17 @@ 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>; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										106
									
								
								modules/renderer/private/backend/vk/data/buffer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								modules/renderer/private/backend/vk/data/buffer.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,106 @@ | |||
| #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
 | ||||
							
								
								
									
										60
									
								
								modules/renderer/private/backend/vk/data/buffer.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								modules/renderer/private/backend/vk/data/buffer.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| #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,10 +1,11 @@ | |||
| #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: | ||||
|  | @ -16,13 +17,19 @@ public: | |||
| 
 | ||||
| 	~DebugMessenger() | ||||
| 	{ | ||||
| 		if (!m_instance) | ||||
| 		if (m_instance) | ||||
| 		{ | ||||
| 			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 {}; | ||||
|  | @ -30,4 +37,88 @@ private: | |||
| 	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,6 +1,7 @@ | |||
| #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 { | ||||
| 
 | ||||
|  | @ -12,12 +13,12 @@ Pass::Pass( | |||
| ) | ||||
|     : m_device(static_cast<Device *>(device)) | ||||
|     , m_layout(m_device->create_pipeline_layout( | ||||
|           VkPipelineLayoutCreateInfo { | ||||
|               .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | ||||
|               .setLayoutCount = 0u, | ||||
|               .pSetLayouts = nullptr, | ||||
|               .pushConstantRangeCount = 0u, | ||||
|               .pPushConstantRanges = nullptr, | ||||
|           std::vector<VkPushConstantRange> { | ||||
|               VkPushConstantRange { | ||||
|                   .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, | ||||
|                   .offset = 0u, | ||||
|                   .size = sizeof(FrameConstants), | ||||
|               }, | ||||
|           } | ||||
|       )) | ||||
| { | ||||
|  | @ -112,17 +113,16 @@ Pass::Pass( | |||
| 		.blendConstants = { 0.0f, 0.0, 0.0, 0.0 }, | ||||
| 	}; | ||||
| 
 | ||||
| 
 | ||||
| 	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 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 color_attachment_ref = VkAttachmentReference { | ||||
| 		.attachment = 0, | ||||
|  | @ -144,21 +144,18 @@ Pass::Pass( | |||
| 		.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | ||||
| 	}; | ||||
| 
 | ||||
| 	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, | ||||
| 	    } | ||||
| 	); | ||||
| 	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_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, | ||||
|  | @ -170,15 +167,14 @@ Pass::Pass( | |||
| 	        .pColorBlendState = &color_blend, | ||||
| 	        .pDynamicState = &dynamic_state, | ||||
| 	        .layout = m_layout, | ||||
| 	        .renderPass = m_pass, | ||||
| 	        .renderPass = VK_NULL_HANDLE, | ||||
| 	        .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); | ||||
|  | @ -194,7 +190,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); | ||||
| } | ||||
| 
 | ||||
|  | @ -207,7 +203,8 @@ 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,8 +49,6 @@ 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,6 +100,7 @@ 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( | ||||
|  | @ -142,35 +143,52 @@ void Renderer::replace_swapchain(ISwapchain *swapchain) | |||
| 
 | ||||
| void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx) | ||||
| { | ||||
| 	auto cmd_begin_info = VkCommandBufferBeginInfo { | ||||
| 	const auto cmd_begin_info = VkCommandBufferBeginInfo { | ||||
| 		.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | ||||
| 		.flags = {}, | ||||
| 		.pInheritanceInfo = nullptr, | ||||
| 	}; | ||||
| 
 | ||||
| 	vkc(vk_begin_command_buffer(cmd, &cmd_begin_info)); | ||||
| 	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, | ||||
|         }, | ||||
| 
 | ||||
| 	auto clear_value = VkClearValue { | ||||
| 			.color = {  | ||||
|                 0.93, | ||||
|                 0.93, | ||||
|                 0.93, | ||||
|                1.0, | ||||
| 	}; | ||||
| 
 | ||||
| 	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, | ||||
|         }, | ||||
| 	}; | ||||
| 
 | ||||
| 	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 | ||||
| 	const auto scissor = VkRect2D { | ||||
| 		.offset = { .x = 0u, .y = 0u }, | ||||
| 		.extent = m_resolution, | ||||
| 	}; | ||||
| 	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()); | ||||
| 
 | ||||
| 	auto viewport = VkViewport { | ||||
| 	const auto viewport = VkViewport { | ||||
| 		.x = 0.0f, | ||||
| 		.y = 0.0f, | ||||
| 		.width = static_cast<float>(m_resolution.width), | ||||
|  | @ -178,17 +196,70 @@ void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx) | |||
| 		.minDepth = 0.0f, | ||||
| 		.maxDepth = 1.0f, | ||||
| 	}; | ||||
| 	vk_cmd_set_viewport(cmd, 0, 1, &viewport); | ||||
| 
 | ||||
| 	auto scissor = VkRect2D { | ||||
| 		.offset = { 0u, 0u }, | ||||
| 		.extent = m_resolution, | ||||
| 	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 } }, | ||||
| 	}; | ||||
| 	vk_cmd_set_scissors(cmd, 0, 1, &scissor); | ||||
| 
 | ||||
| 	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); | ||||
| 	vk_cmd_set_scissors(cmd, 0, 1, &scissor); | ||||
| 	vk_cmd_draw(cmd, 3, 1, 0, 0); | ||||
| 	vk_cmd_end_render_pass(cmd); | ||||
| 	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 | ||||
| 	); | ||||
| 	vkc(vk_end_command_buffer(cmd)); | ||||
| } | ||||
| 
 | ||||
| void submit_sprite(const components::Sprite &sprite, const math::components::Transform &transform) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| } // namespace lt::renderer::vk
 | ||||
|  |  | |||
|  | @ -3,8 +3,10 @@ | |||
| #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> | ||||
| 
 | ||||
|  | @ -29,6 +31,18 @@ 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); | ||||
| 
 | ||||
|  | @ -51,6 +65,8 @@ private: | |||
| 	VkExtent2D m_resolution; | ||||
| 
 | ||||
| 	uint32_t m_max_frames_in_flight {}; | ||||
| 
 | ||||
| 	FrameConstants m_frame_constants; | ||||
| }; | ||||
| 
 | ||||
| } // namespace lt::renderer::vk
 | ||||
|  |  | |||
|  | @ -1,18 +0,0 @@ | |||
| // 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,8 +13,9 @@ 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_vkGetPhysicalDeviceFeatures vk_get_physical_device_features; | ||||
| extern PFN_vkGetPhysicalDeviceFeatures2 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; | ||||
|  | @ -75,8 +76,29 @@ 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
 | ||||
|  |  | |||
							
								
								
									
										27
									
								
								modules/renderer/private/frontend/data/buffer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/renderer/private/frontend/data/buffer.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| #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
 | ||||
							
								
								
									
										66
									
								
								modules/renderer/private/frontend/data/buffer.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								modules/renderer/private/frontend/data/buffer.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | |||
| #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
 | ||||
							
								
								
									
										115
									
								
								modules/renderer/private/frontend/data/buffer.test.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								modules/renderer/private/frontend/data/buffer.test.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,115 @@ | |||
| #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" } = [] { | ||||
| 		auto fixture = Fixture_RendererSystem {}; | ||||
| 		Fixture_ auto fixture = Fixture_RendererSystem {}; | ||||
| 		auto &system = fixture.renderer_system(); | ||||
| 
 | ||||
| 		std::ignore = lt::renderer::IPass::create( | ||||
|  |  | |||
|  | @ -1,7 +1,10 @@ | |||
| #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 { | ||||
| 
 | ||||
|  | @ -41,6 +44,13 @@ 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,4 +1,8 @@ | |||
| #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> | ||||
|  | @ -70,6 +74,30 @@ 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(); | ||||
|  |  | |||
|  | @ -1 +0,0 @@ | |||
| 
 | ||||
|  | @ -148,7 +148,6 @@ public: | |||
| 		); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	[[nodiscard]] auto has_any_messages() const -> bool | ||||
| 	{ | ||||
| 		return m_user_data->m_has_any_messages; | ||||
|  |  | |||
							
								
								
									
										77
									
								
								modules/renderer/public/components/sprite.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								modules/renderer/public/components/sprite.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | |||
| #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
 | ||||
							
								
								
									
										12
									
								
								modules/renderer/public/data/frame_constants.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								modules/renderer/public/data/frame_constants.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <math/mat4.hpp> | ||||
| 
 | ||||
| namespace lt::renderer { | ||||
| 
 | ||||
| struct FrameConstants | ||||
| { | ||||
| 	math::mat4 view_projection; | ||||
| }; | ||||
| 
 | ||||
| } // namespace lt::renderer
 | ||||
|  | @ -7,7 +7,6 @@ | |||
| 
 | ||||
| namespace lt::renderer { | ||||
| 
 | ||||
| 
 | ||||
| class IMessenger | ||||
| { | ||||
| public: | ||||
|  |  | |||
|  | @ -55,31 +55,6 @@ 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; | ||||
|  |  | |||
|  | @ -11,14 +11,18 @@ | |||
| #include <X11/keysym.h> | ||||
| #include <X11/keysymdef.h> | ||||
| 
 | ||||
| //
 | ||||
| 
 | ||||
| namespace lt::surface { | ||||
| 
 | ||||
| template<int EventType> | ||||
| int XEventTypeEquals(Display *, XEvent *event, XPointer winptr) | ||||
| auto XEventTypeEquals(Display *display, XEvent *event, char *winptr) -> int | ||||
| { | ||||
| 	std::ignore = display; | ||||
| 	return ( | ||||
| 	    event->type == EventType | ||||
| 	    && *(reinterpret_cast<Window *>(winptr)) == reinterpret_cast<XAnyEvent *>(event)->window | ||||
| 	    && *(std::bit_cast<const Window *>(winptr)) | ||||
| 	           == std::bit_cast<const XAnyEvent *>(event)->window | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
|  | @ -160,7 +164,7 @@ try | |||
| 	XSetWMProtocols(display, main_window, &surface.m_native_data.wm_delete_message, 1); | ||||
| 
 | ||||
| 	// code to remove decoration
 | ||||
| 	auto hints = std::array<unsigned char, 5> { 2, 0, 0, 0, 0 }; | ||||
| 	auto hints = std::array<const unsigned char, 5> { 2, 0, 0, 0, 0 }; | ||||
| 	const auto motif_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False); | ||||
| 
 | ||||
| 	XChangeProperty( | ||||
|  | @ -340,7 +344,7 @@ void System::modify_resolution(SurfaceComponent &surface, const ModifyResolution | |||
| 	// XResizeWindow(display, window, width, height);
 | ||||
| 
 | ||||
| 	// get baseline serial number for X requests generated from XResizeWindow
 | ||||
| 	uint64_t serial = NextRequest(display); | ||||
| 	auto serial = NextRequest(display); | ||||
| 
 | ||||
| 	// request a new window size from the X server
 | ||||
| 	XResizeWindow(display, window, static_cast<uint32_t>(width), static_cast<uint32_t>(height)); | ||||
|  | @ -396,7 +400,7 @@ void System::modify_position(SurfaceComponent &surface, const ModifyPositionRequ | |||
| 	const auto &[x, y] = request.position; | ||||
| 
 | ||||
| 	// get baseline serial number for X requests generated from XResizeWindow
 | ||||
| 	uint64_t serial = NextRequest(display); | ||||
| 	auto serial = NextRequest(display); | ||||
| 	XMoveWindow(display, window, static_cast<int>(x), static_cast<int>(y)); | ||||
| 
 | ||||
| 	// flush output queue and wait for X server to processes the request
 | ||||
|  |  | |||
|  | @ -16,7 +16,6 @@ using test::expect_eq; | |||
| using test::expect_ne; | ||||
| using test::expect_not_nullptr; | ||||
| using test::expect_throw; | ||||
| using test::expect_true; | ||||
| using test::Suite; | ||||
| 
 | ||||
| [[nodiscard]] auto tick_info() -> app::TickInfo | ||||
|  |  | |||
|  | @ -1,44 +1,77 @@ | |||
| FROM archlinux:latest | ||||
| 
 | ||||
| ## Configurations ## | ||||
| RUN \ | ||||
| mkdir /msan \ | ||||
| && echo 'src:*' > /msan/ignorelist_all_sources \ | ||||
| && sed -i 's/^#ParallelDownloads = .*/ParallelDownloads = 8/' /etc/pacman.conf \ | ||||
| && echo 'NoExtract = usr/share/{man,doc,info}/*' >> /etc/pacman.conf | ||||
| 
 | ||||
| ## Packages ## | ||||
| RUN \ | ||||
| sed -i 's/^#ParallelDownloads = .*/ParallelDownloads = 8/' /etc/pacman.conf \ | ||||
| && echo 'NoExtract = usr/share/{man,doc,info}/*' >> /etc/pacman.conf \ | ||||
| && pacman -Syyu --noconfirm --needed --disable-download-timeout \ | ||||
| pacman -Syyu --noconfirm --needed --disable-download-timeout \ | ||||
|     afl++ \ | ||||
|     afl-utils \ | ||||
|     base-devel \ | ||||
|     bash \ | ||||
|     cbindgen \ | ||||
|     clang \ | ||||
|     cmake \ | ||||
|     curl \ | ||||
|     debuginfod \ | ||||
|     directx-headers \ | ||||
|     elfutils \ | ||||
|     expat \ | ||||
|     gcc \ | ||||
|     gcc-libs \ | ||||
|     gdb \ | ||||
|     git \ | ||||
|     glibc \ | ||||
|     glm \ | ||||
|     glslang \ | ||||
|     libc++ \ | ||||
|     libclc \ | ||||
|     libdrm \ | ||||
|     libelf \ | ||||
|     libglvnd \ | ||||
|     libinput \ | ||||
|     libpciaccess \ | ||||
|     libpng \ | ||||
|     libunwind \ | ||||
|     libva \ | ||||
|     libx11 \ | ||||
|     libxcb \ | ||||
| libxcursor \ | ||||
|     libxdamage \ | ||||
|     libxext \ | ||||
|     libxfixes \ | ||||
|     libxi \ | ||||
|     libxinerama \ | ||||
|     libxml2 \ | ||||
|     libxpresent \ | ||||
|     libxrandr \ | ||||
|     libxshmfence \ | ||||
|     libxxf86vm \ | ||||
|     lm_sensors \ | ||||
|     llvm \ | ||||
|     lz4 \ | ||||
| mesa \ | ||||
|     meson \ | ||||
|     mold \ | ||||
|     ninja \ | ||||
|     python \ | ||||
|     python-distlib \ | ||||
|     python-distutils-extra \ | ||||
|     python-jsonschema \ | ||||
|     python-mako \ | ||||
|     python-packaging \ | ||||
|     python-ply \ | ||||
|     python-pyaml \ | ||||
|     qt5-base \ | ||||
|     qt6-base \ | ||||
|     rust \ | ||||
|     rust-bindgen \ | ||||
|     spirv-llvm-translator \ | ||||
|     spirv-tools \ | ||||
|     systemd-libs \ | ||||
|     valgrind \ | ||||
|     vulkan-headers \ | ||||
|     vulkan-icd-loader \ | ||||
|  | @ -47,53 +80,368 @@ vulkan-validation-layers \ | |||
|     wayland \ | ||||
|     wayland-protocols \ | ||||
|     wget \ | ||||
|     xcb-proto \ | ||||
|     xcb-util \ | ||||
|     xcb-util-cursor \ | ||||
|     xcb-util-keysyms \ | ||||
|     xcb-util-wm \ | ||||
|     xorg-server-xvfb \ | ||||
|     xorg-util-macros \ | ||||
|     xorgproto \ | ||||
|     xtrans \ | ||||
|     zlib \ | ||||
|     zstd \ | ||||
| && pacman -Scc --noconfirm | ||||
| 
 | ||||
| ## Sanitizers ## | ||||
| ## Libc++ ## | ||||
| RUN \ | ||||
| git clone --depth=1 https://github.com/llvm/llvm-project.git -b llvmorg-20.1.8 \ | ||||
| && mkdir llvm-project/build-lsan llvm-project/build-msan \ | ||||
| git clone \ | ||||
|     --branch llvmorg-20.1.8 \ | ||||
|     --depth=1 \ | ||||
|     https://github.com/llvm/llvm-project.git | ||||
| 
 | ||||
| RUN git clone \ | ||||
|     --branch='25.2'\ | ||||
|     --depth=1 \ | ||||
|     https://gitlab.freedesktop.org/mesa/mesa.git | ||||
| 
 | ||||
| RUN wget https://x.org/releases/individual/lib/libxcb-1.17.0.tar.xz | ||||
| RUN wget https://x.org/releases/individual/lib/libX11-1.8.12.tar.xz | ||||
| RUN wget 'https://sdk.lunarg.com/sdk/download/1.4.328.1/linux/vulkansdk-linux-x86_64-1.4.328.1.tar.xz' | ||||
| 
 | ||||
| RUN cd llvm-project/ \ | ||||
| \ | ||||
| && cd llvm-project/build-lsan \ | ||||
| && cmake -G Ninja \ | ||||
|   -DCMAKE_BUILD_TYPE=Release \ | ||||
| && cmake \ | ||||
|     -S ./runtimes \ | ||||
|     -B ./build-lsan \ | ||||
|     -G Ninja \ | ||||
|     -D CMAKE_LINKER_TYPE="MOLD" \ | ||||
|     -D CMAKE_BUILD_TYPE=Release \ | ||||
|     -D CMAKE_INSTALL_PREFIX=/libcxx_lsan \ | ||||
|   -DCMAKE_C_COMPILER=clang \ | ||||
|   -DCMAKE_CXX_COMPILER=clang++ \ | ||||
|     -D CMAKE_C_COMPILER=$(which clang) \ | ||||
|     -D CMAKE_CXX_COMPILER=$(which clang++) \ | ||||
|     -D LLVM_ENABLE_PROJECTS="clang;compiler-rt" \ | ||||
|     -D LLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ | ||||
|     -D LLVM_TARGETS_TO_BUILD="X86;SPIRV" \ | ||||
|     -D LLVM_ENABLE_PIC=ON \ | ||||
|     -D LIBCXX_INSTALL_MODULES=ON \ | ||||
|     -D LIBCXXABI_USE_LLVM_UNWINDER=OFF \ | ||||
|     -D LLVM_USE_SANITIZER=Leaks \ | ||||
|   ../runtimes \ | ||||
| && ninja cxx cxxabi \ | ||||
| && ninja install-cxx install-cxxabi \ | ||||
|     -D LLVM_USE_LINKER="MOLD" \ | ||||
| && cd ./build-lsan/ && ninja cxx cxxabi && ninja install-cxx install-cxxabi && cd ../ \ | ||||
| \ | ||||
| && cd ../build-msan \ | ||||
| && cmake -G Ninja \ | ||||
|   -DCMAKE_BUILD_TYPE=Release \ | ||||
| && cmake \ | ||||
|     -S ./runtimes \ | ||||
|     -B ./build-msan \ | ||||
|     -G Ninja \ | ||||
|     -D CMAKE_LINKER_TYPE="MOLD" \ | ||||
|     -D CMAKE_BUILD_TYPE=Release \ | ||||
|     -D CMAKE_INSTALL_PREFIX=/libcxx_msan \ | ||||
|   -DCMAKE_C_COMPILER=clang \ | ||||
|   -DCMAKE_CXX_COMPILER=clang++ \ | ||||
|     -D CMAKE_C_COMPILER=$(which clang) \ | ||||
|     -D CMAKE_CXX_COMPILER=$(which clang++) \ | ||||
|     -D LLVM_ENABLE_PROJECTS="clang;compiler-rt" \ | ||||
|     -D LLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ | ||||
|     -D LLVM_TARGETS_TO_BUILD="X86;SPIRV" \ | ||||
|     -D LLVM_ENABLE_PIC=ON \ | ||||
|     -D LIBCXX_INSTALL_MODULES=ON \ | ||||
|     -D LIBCXXABI_USE_LLVM_UNWINDER=OFF \ | ||||
|     -D LLVM_USE_SANITIZER=MemoryWithOrigins \ | ||||
|   ../runtimes \ | ||||
| && ninja cxx cxxabi \ | ||||
| && ninja install-cxx install-cxxabi \ | ||||
|     -D LLVM_USE_LINKER="MOLD" \ | ||||
| && cd ./build-msan/ && ninja cxx cxxabi && ninja install-cxx install-cxxabi && cd ../ | ||||
| 
 | ||||
| RUN cd llvm-project/ | ||||
| 
 | ||||
| 
 | ||||
| ## libxcb ## | ||||
| RUN \ | ||||
| tar xf libxcb-1.17.0.tar.xz  \ | ||||
| && cd libxcb-1.17.0  \ | ||||
| && export CC=clang \ | ||||
| && export CFLAGS=" \ | ||||
|     -fsanitize=memory \ | ||||
|     -fsanitize-memory-track-origins \ | ||||
|     -fsanitize-ignorelist=/msan/ignorelist_all_sources \ | ||||
|     -fno-omit-frame-pointer \ | ||||
|     -g \ | ||||
|     -fPIC" \ | ||||
| && export LDFLAGS=" \ | ||||
|     -fsanitize=memory \ | ||||
|     -fsanitize-memory-track-origins \ | ||||
|     -fsanitize-ignorelist=/msan/ignorelist_all_sources \ | ||||
|     -fno-omit-frame-pointer \ | ||||
|     -g \ | ||||
|     -fPIC" \ | ||||
| && ./configure \ | ||||
|     --prefix=/msan \ | ||||
|     --disable-static \ | ||||
|     --without-doxygen \ | ||||
| && make && make install \ | ||||
| && cd .. && rm -rf libxcb-1.17.0 libxcb-1.17.0.tar.xz | ||||
| 
 | ||||
| ## libx11 ## | ||||
| RUN \ | ||||
| tar xf libX11-1.8.12.tar.xz  \ | ||||
| && cd libX11-1.8.12  \ | ||||
| && export CC=clang \ | ||||
| && export CFLAGS=" \ | ||||
| -fsanitize=memory \ | ||||
| -fsanitize-memory-track-origins \ | ||||
| -fsanitize-ignorelist=/msan/ignorelist_all_sources \ | ||||
| -fno-omit-frame-pointer \ | ||||
| -g \ | ||||
| -fPIC" \ | ||||
| && export LDFLAGS=" \ | ||||
| -fsanitize=memory \ | ||||
| -fsanitize-memory-track-origins \ | ||||
| -fsanitize-ignorelist=/msan/ignorelist_all_sources \ | ||||
| -fno-omit-frame-pointer \ | ||||
| -g \ | ||||
| -fPIC" \ | ||||
| && export PKG_CONFIG_PATH=/msan/lib/pkgconfig:$PKG_CONFIG_PATH \ | ||||
| && ./configure \ | ||||
|     --prefix=/msan \ | ||||
|     --disable-static \ | ||||
| && make && make install \ | ||||
| && cd .. && rm -rf libX11-1.8.12 libX11-1.8.12.tar.xz | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ## Vulkan SDK ## | ||||
| RUN \ | ||||
| tar xf 'vulkansdk-linux-x86_64-1.4.328.1.tar.xz' \ | ||||
| && cd /1.4.328.1 \ | ||||
| && chmod +x ./vulkansdk \ | ||||
| && chmod +x ./setup-env.sh \ | ||||
| && export CC="$(which clang)" \ | ||||
| && export CXX="$(which clang++)" \ | ||||
| && export CXXFLAGS="\ | ||||
|         -fsanitize=memory \ | ||||
|         -fsanitize-memory-track-origins \ | ||||
|         -fsanitize-ignorelist=/msan/ignorelist_all_sources \ | ||||
|         -fno-omit-frame-pointer \ | ||||
|         -g \ | ||||
|         -std=c++26 \ | ||||
|         -nostdinc++ \ | ||||
|         -isystem /libcxx_msan/include/c++/v1/"\ | ||||
| && export CFLAGS="\ | ||||
|         -fsanitize=memory \ | ||||
|         -fsanitize-memory-track-origins \ | ||||
|         -fno-omit-frame-pointer \ | ||||
|         -g" \ | ||||
| && export LDFLAGS="\ | ||||
|     -fsanitize=memory \ | ||||
|     -fsanitize-memory-track-origins \ | ||||
|     -fsanitize-ignorelist=/msan/ignorelist_all_sources \ | ||||
|     -g \ | ||||
|     -std=c++26 \ | ||||
|     -L/msan/lib -Wl,-rpath,/msan/lib \ | ||||
|     -L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib \ | ||||
|     -lc++ \ | ||||
|     -lc++abi" \ | ||||
| && ./vulkansdk \ | ||||
|     --debug \ | ||||
|     --skip-installing-deps \ | ||||
|     --numjobs `nproc` \ | ||||
|     vulkan-loader \ | ||||
|     spirv-tools | ||||
| 
 | ||||
| ## Mesa ## | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| RUN \ | ||||
| export build_llvm=/build-llvm \ | ||||
| && export build_path=/b_llvm_normal \ | ||||
| && export repo=/llvm-project \ | ||||
| \ | ||||
| && cd ../.. \ | ||||
| && rm -rf llvm-project | ||||
| && cmake \ | ||||
|     -S $repo/llvm \ | ||||
|     -G Ninja \ | ||||
|     -B $build_path \ | ||||
|     -D CMAKE_BUILD_TYPE=Release \ | ||||
|     -D LLVM_ENABLE_PROJECTS="clang;lld;compiler-rt" \ | ||||
|     -D CMAKE_C_COMPILER=$(which clang) \ | ||||
|     -D CMAKE_CXX_COMPILER=$(which clang++) \ | ||||
|     -D CMAKE_INSTALL_PREFIX=/opt/llvm-normal \ | ||||
| && ninja -C $build_path install | ||||
| 
 | ||||
| RUN \ | ||||
| export CXXFLAGS="\ | ||||
|         -fsanitize=memory \ | ||||
|         -fsanitize-memory-track-origins \ | ||||
|         -fsanitize-ignorelist=/msan/ignorelist_all_sources \ | ||||
|         -fno-omit-frame-pointer \ | ||||
|         -g \ | ||||
|         -std=c++26 \ | ||||
|         -nostdinc++ \ | ||||
|         -isystem /libcxx_msan/include/c++/v1/"\ | ||||
| && export CFLAGS="\ | ||||
|         -fsanitize=memory \ | ||||
|         -fsanitize-memory-track-origins \ | ||||
|         -fno-omit-frame-pointer \ | ||||
|         -g" \ | ||||
| && export LDFLAGS="\ | ||||
|     -fsanitize=memory \ | ||||
|     -fsanitize-memory-track-origins \ | ||||
|     -fsanitize-ignorelist=/msan/ignorelist_all_sources \ | ||||
|     -g \ | ||||
|     -std=c++26 \ | ||||
|     -L/msan/lib -Wl,-rpath,/msan/lib \ | ||||
|     -L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib \ | ||||
|     -lc++ \ | ||||
|     -lc++abi" \ | ||||
| && export build_path=/b_llvm_msan \ | ||||
| && export repo=/llvm-project \ | ||||
| \ | ||||
| && cmake \ | ||||
|     -S $repo/llvm \ | ||||
|     -G Ninja \ | ||||
|     -B $build_path \ | ||||
|     -D CMAKE_BUILD_TYPE=Release \ | ||||
|     -D LLVM_ENABLE_PROJECTS="clang;lld" \ | ||||
|     -D LLVM_TARGETS_TO_BUILD="X86;SPIRV" \ | ||||
|     -D LLVM_ENABLE_PIC=ON \ | ||||
|     -D LLVM_NATIVE_TOOL_DIR=/opt/llvm-normal/bin/ \ | ||||
|     -D LLVM_USE_SANITIZER=MemoryWithOrigins \ | ||||
|     -D LLVM_TABLEGEN=/opt/llvm-normal/bin/llvm-tblgen \ | ||||
|     -D LLVM_CONFIG_PATH=/opt/llvm-normal/bin/llvm-config \ | ||||
|     -D CMAKE_C_COMPILER=/opt/llvm-normal/bin/clang \ | ||||
|     -D CMAKE_CXX_COMPILER=/opt/llvm-normal/bin/clang++ \ | ||||
|     -D CMAKE_INSTALL_PREFIX=/opt/llvm-msan \ | ||||
| && ninja -C $build_path install | ||||
| 
 | ||||
| # && cmake \ | ||||
| #     -G Ninja \ | ||||
| #     -S $llvm/llvm \ | ||||
| #     -B $build_llvm \ | ||||
| #     -D LLVM_INSTALL_UTILS=ON \ | ||||
| #     -D CMAKE_INSTALL_PREFIX=$installprefix \ | ||||
| #     -D CMAKE_BUILD_TYPE=Release \ | ||||
| #     -D LLVM_TARGETS_TO_BUILD="X86;SPIRV" \ | ||||
| #     -D CMAKE_C_COMPILER=$(which clang) \ | ||||
| #     -D CMAKE_CXX_COMPILER=$(which clang++) \ | ||||
| # \ | ||||
| #     -D LLVM_USE_SANITIZER=MemoryWithOrigins \ | ||||
| #     -D LIBCXXABI_USE_LLVM_UNWINDER=OFF \ | ||||
| # \ | ||||
| # && ninja -C $build_llvm install | ||||
| # | ||||
| # && cmake  \ | ||||
| #     -G Ninja  \ | ||||
| #     -S $llvm/clang  \ | ||||
| #     -B $build_clang \ | ||||
| #     -D LLVM_EXTERNAL_LIT=$build_llvm/utils/lit \ | ||||
| #     -D LLVM_ROOT=$installprefix \ | ||||
| # \ | ||||
| # && ninja -C $build_clang | ||||
| 
 | ||||
| RUN \ | ||||
| cd /mesa \ | ||||
| && export CXX='clang++' \ | ||||
| && export CC='clang' \ | ||||
| && export CFLAGS="-fsanitize=memory  -fsanitize-memory-track-origins  -fno-omit-frame-pointer  -g" \ | ||||
| && export CXXFLAGS="-fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -g -nostdinc++ -isystem /libcxx_msan/include/c++/v1/" \ | ||||
| && export LDFLAGS="-fsanitize=memory -fsanitize-memory-track-origins -g -L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib -L/msan/lib -Wl,-rpath,/msan/lib -lc++ -lc++abi"  \ | ||||
| && export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH" \ | ||||
| && meson setup ./ _build \ | ||||
|     -D build-tests=false  \ | ||||
|     -D enable-glcpp-tests=false  \ | ||||
|     -D build-radv-tests=false  \ | ||||
|     -D build-aco-tests=false  \ | ||||
|     -D install-intel-gpu-tests=false  \ | ||||
|     -D gallium-mediafoundation-test=false  \ | ||||
|     -D android-libbacktrace=disabled  \ | ||||
|     -D split-debug=disabled  \ | ||||
|     -D b_ndebug=true  \ | ||||
|     -D b_lto=false  \ | ||||
|     -D egl=enabled  \ | ||||
|     -D gallium-drivers=r300,r600,radeonsi,nouveau,virgl,svga,softpipe,llvmpipe,i915,iris,crocus,zink  \ | ||||
|     -D gallium-extra-hud=true  \ | ||||
|     -D gallium-rusticl=true  \ | ||||
|     -D gallium-va=enabled  \ | ||||
|     -D gbm=enabled  \ | ||||
|     -D gles1=disabled  \ | ||||
|     -D gles2=enabled  \ | ||||
|     -D glvnd=enabled  \ | ||||
|     -D glx=dri  \ | ||||
|     -D libunwind=enabled  \ | ||||
|     -D llvm=enabled  \ | ||||
|     -D lmsensors=disabled  \ | ||||
|     -D microsoft-clc=disabled  \ | ||||
|     -D platforms=x11,wayland  \ | ||||
|     -D valgrind=disabled  \ | ||||
|     -D video-codecs=all  \ | ||||
|     -D vulkan-drivers=amd,intel,intel_hasvk,swrast,virtio,nouveau  \ | ||||
|     -D vulkan-layers=device-select,intel-nullhw,overlay  \ | ||||
|     -D tools=''  \ | ||||
|     -D zstd=enabled  \ | ||||
|     -D buildtype=plain  \ | ||||
|     -D prefix=/usr  \ | ||||
|     -D sysconfdir=/etc  \ | ||||
|     --wrap-mode=nofallback  \ | ||||
|     --force-fallback-for=syn,paste,rustc-hash  \ | ||||
| && ninja -C _build | ||||
| 
 | ||||
| # RUN cd mesa/ \ | ||||
| # && source '/1.4.328.1/setup-env.sh' \ | ||||
| # && export CXX='clang++' \ | ||||
| # && export CC='clang' \ | ||||
| # && export CFLAGS="\ | ||||
| #         -fsanitize=memory \ | ||||
| #         -fsanitize-memory-track-origins \ | ||||
| #         -fno-omit-frame-pointer \ | ||||
| #         -g" \ | ||||
| # && export CXXFLAGS="\ | ||||
| #         -fsanitize=memory \ | ||||
| #         -fsanitize-memory-track-origins \ | ||||
| #         -fno-omit-frame-pointer \ | ||||
| #         -g \ | ||||
| #         -nostdinc++ \ | ||||
| #         -isystem /libcxx_msan/include/c++/v1/"\ | ||||
| # && export LDFLAGS="\ | ||||
| #     -fsanitize=memory \ | ||||
| #     -fsanitize-memory-track-origins \ | ||||
| #     -g \ | ||||
| #     -L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib \ | ||||
| #     -L/msan/lib -Wl,-rpath,/msan/lib \ | ||||
| #     -lc++ \ | ||||
| #     -lc++abi" \ | ||||
| # && meson setup ./ _build  \ | ||||
| #     -D build-tests=false \ | ||||
| #     -D enable-glcpp-tests=false \ | ||||
| #     -D build-radv-tests=false \ | ||||
| #     -D build-aco-tests=false \ | ||||
| #     -D install-intel-gpu-tests=false \ | ||||
| #     -D gallium-mediafoundation-test=false \ | ||||
| #     -D android-libbacktrace=disabled \ | ||||
| #     -D split-debug=disabled \ | ||||
| #     -D b_ndebug=true \ | ||||
| #     -D b_lto=false \ | ||||
| #     -D egl=enabled \ | ||||
| #     -D gallium-drivers=r300,r600,radeonsi,nouveau,virgl,svga,softpipe,llvmpipe,i915,iris,crocus,zink \ | ||||
| #     -D gallium-extra-hud=true \ | ||||
| #     -D gallium-rusticl=true \ | ||||
| #     -D gallium-va=enabled \ | ||||
| #     -D gbm=enabled \ | ||||
| #     -D gles1=disabled \ | ||||
| #     -D gles2=enabled \ | ||||
| #     -D glvnd=enabled \ | ||||
| #     -D glx=dri \ | ||||
| #     -D libunwind=enabled \ | ||||
| #     -D llvm=enabled \ | ||||
| #     -D lmsensors=disabled \ | ||||
| #     -D microsoft-clc=disabled \ | ||||
| #     -D platforms=x11,wayland \ | ||||
| #     -D valgrind=disabled \ | ||||
| #     -D video-codecs=all \ | ||||
| #     -D vulkan-drivers=amd,intel,intel_hasvk,swrast,virtio,nouveau \ | ||||
| #     -D vulkan-layers=device-select,intel-nullhw,overlay \ | ||||
| #     -D tools='' \ | ||||
| #     -D zstd=enabled \ | ||||
| #     -D buildtype=plain \ | ||||
| #     -D prefix=/usr \ | ||||
| #     -D sysconfdir=/etc \ | ||||
| #     --wrap-mode=nofallback \ | ||||
| #     --force-fallback-for=syn,paste,rustc-hash \ | ||||
| # && ninja -C _build | ||||
| # | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ | |||
| set -euo pipefail | ||||
| cd "$(git rev-parse --show-toplevel)/" | ||||
| 
 | ||||
| source '/1.4.328.1/setup-env.sh' | ||||
| 
 | ||||
| CC=$(which clang) | ||||
| export CC | ||||
| 
 | ||||
|  | @ -12,6 +14,12 @@ export CXX | |||
| DISPLAY=:99 | ||||
| export DISPLAY | ||||
| 
 | ||||
| PKG_CONFIG_PATH="/msan/lib/pkgconfig:${PKG_CONFIG_PATH}" | ||||
| export PKG_CONFIG_PATH | ||||
| 
 | ||||
| VK_ICD_FILENAMES='/usr/share/vulkan/icd.d/lvp_icd.x86_64.json' | ||||
| export VK_ICD_FILENAMES | ||||
| 
 | ||||
| Xvfb :99 -screen 0 1024x768x16 & | ||||
| 
 | ||||
| cmake \ | ||||
|  | @ -26,16 +34,18 @@ cmake \ | |||
| -fsanitize-memory-track-origins \ | ||||
| -g \ | ||||
| -fno-omit-frame-pointer \ | ||||
| -std=c++23 \ | ||||
| -std=c++26 \ | ||||
| -nostdinc++ \ | ||||
| -isystem /libcxx_msan/include/c++/v1/" \ | ||||
|     -D CMAKE_EXE_LINKER_FLAGS=" \ | ||||
| -fsanitize=memory \ | ||||
| -fsanitize-memory-track-origins \ | ||||
| -L/libcxx_msan/lib \ | ||||
| -g \ | ||||
| -std=c++26 \ | ||||
| -L/msan/lib -Wl,-rpath,/msan/lib \ | ||||
| -L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib \ | ||||
| -lc++ \ | ||||
| -lc++abi \ | ||||
| -Wl,-rpath,/libcxx_msan/lib" | ||||
| -lc++abi" | ||||
| 
 | ||||
| cmake --build ./build -j"$(nproc)" | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										3
									
								
								tools/ci/amd64/clang/msan.supp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tools/ci/amd64/clang/msan.supp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| src:* | ||||
| obj:* | ||||
| fun:* | ||||
|  | @ -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++23 -g -fno-omit-frame-pointer" | ||||
|     -D CMAKE_CXX_FLAGS="-std=c++26 -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++23 -fno-omit-frame-pointer -fno-common -g" | ||||
|     -D CMAKE_CXX_FLAGS="-std=c++26 -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++23 -stdlib=libc++" | ||||
|     -D CMAKE_CXX_FLAGS="-std=c++26 -stdlib=libc++" | ||||
| 
 | ||||
| cmake --build . -j"$(nproc)" | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue