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/* |     - rm -rf /light_docs/* | ||||||
|     - mv ./html/* /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 | #version 450 core | ||||||
| 
 | 
 | ||||||
| vec2 positions[3] = vec2[]( | layout(push_constant ) uniform pc { | ||||||
|     vec2(0.0, -0.5), |  mat4 view_projection; | ||||||
|     vec2(0.5, 0.5), | }; | ||||||
|     vec2(-0.5, 0.5) | 
 | ||||||
|  | vec3 positions[3] = vec3[]( | ||||||
|  |     vec3(0.0, -0.5, 0.5), | ||||||
|  |     vec3(0.5, 0.5, 0.5), | ||||||
|  |     vec3(-0.5, 0.5, 0.5) | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| vec3 colors[3] = vec3[]( | vec3 colors[3] = vec3[]( | ||||||
|     vec3(1.0, 0.0, 0.0), |     vec3(0.0, 0.0, 0.0), | ||||||
|     vec3(0.0, 1.0, 0.0), |     vec3(0.0, 0.0, 0.0), | ||||||
|     vec3(0.0, 0.0, 1.0) |     vec3(0.0, 0.0, 0.0) | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| layout(location = 0) out vec3 out_frag_color; | layout(location = 0) out vec3 out_frag_color; | ||||||
| 
 | 
 | ||||||
| void main()  | 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]; |     out_frag_color = colors[gl_VertexIndex]; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  |  | ||||||
										
											Binary file not shown.
										
									
								
							|  | @ -2,18 +2,25 @@ | ||||||
| 
 | 
 | ||||||
| namespace lt::assets { | 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) | 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()); | 	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); | 	m_stream.seekg(0, std::ifstream::end); | ||||||
| 	const auto file_size = static_cast<size_t>(m_stream.tellg()); | 	const auto file_size = static_cast<size_t>(m_stream.tellg()); | ||||||
| 
 |  | ||||||
| 	ensure( | 	ensure( | ||||||
| 	    file_size > total_metadata_size, | 	    file_size > total_metadata_size, | ||||||
| 	    "Failed to open shader asset at: {}, file smaller than metadata: {} < {}", | 	    "Failed to open shader asset at: {}, file smaller than metadata: {} < {}", | ||||||
|  | @ -22,12 +29,15 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path) | ||||||
| 	    file_size | 	    file_size | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
 |  | ||||||
| 	m_stream.seekg(0, std::ifstream::beg); | 	m_stream.seekg(0, std::ifstream::beg); | ||||||
| 	m_stream.read((char *)&m_asset_metadata, sizeof(m_asset_metadata)); | 	read(m_asset_metadata.type); | ||||||
| 	m_stream.read((char *)&m_metadata, sizeof(m_metadata)); | 	read(m_asset_metadata.version); | ||||||
| 	m_stream.read((char *)&m_code_blob_metadata, sizeof(m_code_blob_metadata)); | 	read(m_metadata.type); | ||||||
| 	// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
 | 	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( | 	ensure( | ||||||
| 	    m_asset_metadata.type == asset_type_identifier, | 	    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
 | } // namespace lt::assets
 | ||||||
|  |  | ||||||
|  | @ -40,10 +40,15 @@ Suite packing = "shader_pack"_suite = [] { | ||||||
| 			dummy_blob.emplace_back(static_cast<std::byte>(idx)); | 			dummy_blob.emplace_back(static_cast<std::byte>(idx)); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		const auto expected_size =          //
 | 		const auto expected_size =                    //
 | ||||||
| 		    sizeof(AssetMetadata)           //
 | 		    sizeof(AssetMetadata::type)               //
 | ||||||
| 		    + sizeof(ShaderAsset::Metadata) //
 | 		    + sizeof(AssetMetadata::version)          //
 | ||||||
| 		    + sizeof(BlobMetadata)          //
 | 		    + 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(); | 		    + dummy_blob.size(); | ||||||
| 
 | 
 | ||||||
| 		ShaderAsset::pack( | 		ShaderAsset::pack( | ||||||
|  |  | ||||||
|  | @ -32,33 +32,14 @@ public: | ||||||
| 	    AssetMetadata asset_metadata, | 	    AssetMetadata asset_metadata, | ||||||
| 	    Metadata metadata, | 	    Metadata metadata, | ||||||
| 	    Blob code_blob | 	    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); | 	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 & | 	[[nodiscard]] auto get_asset_metadata() const -> const AssetMetadata & | ||||||
| 	{ | 	{ | ||||||
| 		return m_asset_metadata; | 		return m_asset_metadata; | ||||||
|  | @ -80,45 +61,6 @@ public: | ||||||
| 		return m_code_blob_metadata; | 		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: | private: | ||||||
| 	AssetMetadata m_asset_metadata {}; | 	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. |  * 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> | template<typename T> | ||||||
| constexpr auto perspective(T field_of_view, T aspect_ratio, T z_near, T z_far) | constexpr auto perspective(T field_of_view, T aspect_ratio, T z_near, T z_far) | ||||||
| { | { | ||||||
| 	const T half_fov_tan = std::tan(field_of_view / static_cast<T>(2)); | 	const T half_fov_tan = std::tan(field_of_view / static_cast<T>(2)); | ||||||
| 
 | 
 | ||||||
| 	auto result = mat4_impl<T> { T { 0 } }; | 	auto result = mat4_impl<T>::identity(); | ||||||
| 
 | 
 | ||||||
| 	result[0][0] = T { 1 } / (aspect_ratio * half_fov_tan); | 	result[0][0] = T { 1 } / (aspect_ratio * half_fov_tan); | ||||||
| 
 | 	//
 | ||||||
| 	result[1][1] = T { 1 } / (half_fov_tan); | 	result[1][1] = T { 1 } / (half_fov_tan); | ||||||
| 
 | 	//
 | ||||||
| 	result[2][2] = -(z_far + z_near) / (z_far - z_near); | 	//	result[2][2] = -(z_far + z_near) / (z_far - z_near);
 | ||||||
| 
 | 	//
 | ||||||
|  | 	result[2][2] = z_far / (z_far - z_near); | ||||||
|  | 	//
 | ||||||
| 	result[2][3] = -T { 1 }; | 	result[2][3] = -T { 1 }; | ||||||
| 
 | 	//
 | ||||||
| 	result[3][2] = -(T { 2 } * z_far * z_near) / (z_far - z_near); | 	// result[3][2] = -(T { 2 } * z_far * z_near) / (z_far - z_near);
 | ||||||
| 
 | 	result[3][2] = -(z_far * z_near) / (z_far - z_near); | ||||||
|  | 	//
 | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ template<typename T = float> | ||||||
| struct mat4_impl | struct mat4_impl | ||||||
| { | { | ||||||
| 	using Column_T = vec4_impl<T>; | 	using Column_T = vec4_impl<T>; | ||||||
|  | 
 | ||||||
| 	constexpr explicit mat4_impl(T scalar = 0) | 	constexpr explicit mat4_impl(T scalar = 0) | ||||||
| 	    : values( | 	    : values( | ||||||
| 	          { | 	          { | ||||||
|  | @ -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> { | 		return mat4_impl<T> { | ||||||
| 			{ 1 }, {},    {},    {},    //
 | 			{ 1 }, {},    {},    {},    //
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| add_library_module(libmirror) | add_library_module(libmirror) | ||||||
| target_link_libraries(libmirror INTERFACE app time input surface renderer) | target_link_libraries(libmirror INTERFACE app time input surface renderer | ||||||
|  |                                           camera) | ||||||
| 
 | 
 | ||||||
| add_test_module( | add_test_module( | ||||||
|     libmirror layers/editor_layer.test.cpp panels/asset_browser.test.cpp |     libmirror layers/editor_layer.test.cpp panels/asset_browser.test.cpp | ||||||
|  |  | ||||||
|  | @ -2,9 +2,11 @@ | ||||||
| #include <app/application.hpp> | #include <app/application.hpp> | ||||||
| #include <app/entrypoint.hpp> | #include <app/entrypoint.hpp> | ||||||
| #include <app/system.hpp> | #include <app/system.hpp> | ||||||
|  | #include <camera/components.hpp> | ||||||
| #include <ecs/entity.hpp> | #include <ecs/entity.hpp> | ||||||
| #include <input/components.hpp> | #include <input/components.hpp> | ||||||
| #include <input/system.hpp> | #include <input/system.hpp> | ||||||
|  | #include <math/trig.hpp> | ||||||
| #include <math/vec2.hpp> | #include <math/vec2.hpp> | ||||||
| #include <memory/reference.hpp> | #include <memory/reference.hpp> | ||||||
| #include <memory/scope.hpp> | #include <memory/scope.hpp> | ||||||
|  | @ -66,13 +68,18 @@ public: | ||||||
| 			const auto &[x, y] = surface.get_position(); | 			const auto &[x, y] = surface.get_position(); | ||||||
| 			const auto &[width, height] = surface.get_resolution(); | 			const auto &[width, height] = surface.get_resolution(); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 			if (input.get_action(m_quit_action_key).state == State::active) | 			if (input.get_action(m_quit_action_key).state == State::active) | ||||||
| 			{ | 			{ | ||||||
| 				should_quit = true; | 				should_quit = true; | ||||||
| 			} | 			} | ||||||
| 			if (input.get_action(m_debug_action_keys[0]).state == State::active) | 			if (input.get_action(m_debug_action_keys[0]).state == State::active) | ||||||
| 			{ | 			{ | ||||||
| 				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) | 			if (input.get_action(m_debug_action_keys[1]).state == State::active) | ||||||
|  | @ -219,6 +226,20 @@ public: | ||||||
| 		        .callback = &renderer_callback, | 		        .callback = &renderer_callback, | ||||||
| 		        .user_data = this, | 		        .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() | 	void setup_input_system() | ||||||
|  | @ -245,6 +266,8 @@ private: | ||||||
| 	memory::Ref<MirrorSystem> m_mirror_system; | 	memory::Ref<MirrorSystem> m_mirror_system; | ||||||
| 
 | 
 | ||||||
| 	lt::ecs::EntityId m_window = lt::ecs::null_entity; | 	lt::ecs::EntityId m_window = lt::ecs::null_entity; | ||||||
|  | 
 | ||||||
|  | 	lt::ecs::EntityId m_camera_id = lt::ecs::null_entity; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| auto app::create_application() -> memory::Scope<app::Application> | auto app::create_application() -> memory::Scope<app::Application> | ||||||
|  |  | ||||||
|  | @ -8,21 +8,29 @@ add_library_module( | ||||||
|     backend/vk/context/instance.cpp |     backend/vk/context/instance.cpp | ||||||
|     backend/vk/context/surface.cpp |     backend/vk/context/surface.cpp | ||||||
|     backend/vk/context/swapchain.cpp |     backend/vk/context/swapchain.cpp | ||||||
|  |     backend/vk/data/buffer.cpp | ||||||
|     backend/vk/renderer/pass.cpp |     backend/vk/renderer/pass.cpp | ||||||
|     backend/vk/renderer/renderer.cpp |     backend/vk/renderer/renderer.cpp | ||||||
|     # Vulkan - frontend |     # frontend | ||||||
|     frontend/messenger.cpp |     frontend/messenger.cpp | ||||||
|     frontend/context/device.cpp |     frontend/context/device.cpp | ||||||
|     frontend/context/gpu.cpp |     frontend/context/gpu.cpp | ||||||
|     frontend/context/instance.cpp |     frontend/context/instance.cpp | ||||||
|     frontend/context/surface.cpp |     frontend/context/surface.cpp | ||||||
|     frontend/context/swapchain.cpp |     frontend/context/swapchain.cpp | ||||||
|  |     frontend/data/buffer.cpp | ||||||
|     frontend/renderer/renderer.cpp |     frontend/renderer/renderer.cpp | ||||||
|     frontend/renderer/pass.cpp) |     frontend/renderer/pass.cpp) | ||||||
| 
 | 
 | ||||||
| target_link_libraries( | target_link_libraries( | ||||||
|     renderer |     renderer | ||||||
|     PUBLIC app ecs memory assets time bitwise |     PUBLIC app | ||||||
|  |            ecs | ||||||
|  |            memory | ||||||
|  |            assets | ||||||
|  |            time | ||||||
|  |            bitwise | ||||||
|  |            camera | ||||||
|     PRIVATE surface pthread) |     PRIVATE surface pthread) | ||||||
| 
 | 
 | ||||||
| add_test_module( | add_test_module( | ||||||
|  | @ -34,11 +42,10 @@ add_test_module( | ||||||
|     frontend/context/surface.test.cpp |     frontend/context/surface.test.cpp | ||||||
|     frontend/context/device.test.cpp |     frontend/context/device.test.cpp | ||||||
|     frontend/context/swapchain.test.cpp |     frontend/context/swapchain.test.cpp | ||||||
|     frontend/renderer/pass.test.cpp |     frontend/data/buffer.test.cpp | ||||||
|  |     # frontend/renderer/pass.test.cpp | ||||||
|     frontend/renderer/renderer.test.cpp |     frontend/renderer/renderer.test.cpp | ||||||
|     # backend specific tests -- vk |     # backend specific tests -- vk | ||||||
|     backend/vk/context/instance.test.cpp |     backend/vk/context/instance.test.cpp) | ||||||
|     # backend specific tests -- dx backend specific tests -- mt |  | ||||||
| ) |  | ||||||
| 
 | 
 | ||||||
| target_link_libraries(renderer_tests PRIVATE surface pthread) | target_link_libraries(renderer_tests PRIVATE surface pthread) | ||||||
|  |  | ||||||
|  | @ -75,10 +75,17 @@ void Device::initialize_logical_device() | ||||||
| 
 | 
 | ||||||
| 	auto extensions = std::vector<const char *> { | 	auto extensions = std::vector<const char *> { | ||||||
| 		VK_KHR_SWAPCHAIN_EXTENSION_NAME, | 		VK_KHR_SWAPCHAIN_EXTENSION_NAME, | ||||||
|  | 		VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	const auto dynamic_rendering_features = VkPhysicalDeviceDynamicRenderingFeatures { | ||||||
|  | 		.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES, | ||||||
|  | 		.dynamicRendering = true, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	auto device_info = VkDeviceCreateInfo { | 	auto device_info = VkDeviceCreateInfo { | ||||||
| 		.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, | 		.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, | ||||||
|  | 		.pNext = &dynamic_rendering_features, | ||||||
| 		.queueCreateInfoCount = static_cast<uint32_t>(queue_infos.size()), | 		.queueCreateInfoCount = static_cast<uint32_t>(queue_infos.size()), | ||||||
| 		.pQueueCreateInfos = queue_infos.data(), | 		.pQueueCreateInfos = queue_infos.data(), | ||||||
| 		.enabledExtensionCount = static_cast<uint32_t>(extensions.size()), | 		.enabledExtensionCount = static_cast<uint32_t>(extensions.size()), | ||||||
|  | @ -207,6 +214,31 @@ void Device::wait_for_fences(std::span<VkFence> fences) const | ||||||
| 	return images; | 	return images; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | [[nodiscard]] auto Device::get_memory_requirements(VkBuffer buffer) const -> VkMemoryRequirements | ||||||
|  | { | ||||||
|  | 	auto requirements = VkMemoryRequirements {}; | ||||||
|  | 	vk_get_buffer_memory_requirements(m_device, buffer, &requirements); | ||||||
|  | 	return requirements; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Device::bind_memory(VkBuffer buffer, VkDeviceMemory memory, size_t offset /* = 0u */) const | ||||||
|  | { | ||||||
|  | 	vkc(vk_bind_buffer_memory(m_device, buffer, memory, offset)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | [[nodiscard]] auto Device::map_memory(VkDeviceMemory memory, size_t size, size_t offset) const | ||||||
|  |     -> std::span<std::byte> | ||||||
|  | { | ||||||
|  | 	void *data = {}; | ||||||
|  | 	vkc(vk_map_memory(m_device, memory, offset, size, {}, &data)); | ||||||
|  | 	return { std::bit_cast<std::byte *>(data), size }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Device::unmap_memory(VkDeviceMemory memory) | ||||||
|  | { | ||||||
|  | 	vk_unmap_memory(m_device, memory); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| [[nodiscard]] auto Device::create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR | [[nodiscard]] auto Device::create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR | ||||||
| { | { | ||||||
| 	auto *swapchain = VkSwapchainKHR {}; | 	auto *swapchain = VkSwapchainKHR {}; | ||||||
|  | @ -251,9 +283,18 @@ void Device::wait_for_fences(std::span<VkFence> fences) const | ||||||
| 	return pass; | 	return pass; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [[nodiscard]] auto Device::create_pipeline_layout(VkPipelineLayoutCreateInfo info) const | [[nodiscard]] auto Device::create_pipeline_layout( | ||||||
|     -> VkPipelineLayout |     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 {}; | 	auto *pipeline_layout = VkPipelineLayout {}; | ||||||
| 	vkc(vk_create_pipeline_layout(m_device, &info, nullptr, &pipeline_layout)); | 	vkc(vk_create_pipeline_layout(m_device, &info, nullptr, &pipeline_layout)); | ||||||
| 	return pipeline_layout; | 	return pipeline_layout; | ||||||
|  | @ -299,6 +340,13 @@ void Device::wait_for_fences(std::span<VkFence> fences) const | ||||||
| 	return fences; | 	return fences; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | [[nodiscard]] auto Device::create_buffer(VkBufferCreateInfo info) const -> VkBuffer | ||||||
|  | { | ||||||
|  | 	auto *buffer = VkBuffer {}; | ||||||
|  | 	vkc(vk_create_buffer(m_device, &info, nullptr, &buffer)); | ||||||
|  | 	return buffer; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| [[nodiscard]] auto Device::allocate_command_buffers(VkCommandBufferAllocateInfo info) const | [[nodiscard]] auto Device::allocate_command_buffers(VkCommandBufferAllocateInfo info) const | ||||||
|     -> std::vector<VkCommandBuffer> |     -> std::vector<VkCommandBuffer> | ||||||
| { | { | ||||||
|  | @ -307,6 +355,18 @@ void Device::wait_for_fences(std::span<VkFence> fences) const | ||||||
| 	return command_buffers; | 	return command_buffers; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | [[nodiscard]] auto Device::allocate_memory(VkMemoryAllocateInfo info) const -> VkDeviceMemory | ||||||
|  | { | ||||||
|  | 	auto *memory = VkDeviceMemory {}; | ||||||
|  | 	vkc(vk_allocate_memory(m_device, &info, nullptr, &memory)); | ||||||
|  | 	return memory; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Device::free_memory(VkDeviceMemory memory) const | ||||||
|  | { | ||||||
|  | 	vk_free_memory(m_device, memory, nullptr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Device::destroy_swapchain(VkSwapchainKHR swapchain) const | void Device::destroy_swapchain(VkSwapchainKHR swapchain) const | ||||||
| { | { | ||||||
| 	vk_destroy_swapchain_khr(m_device, swapchain, m_allocator); | 	vk_destroy_swapchain_khr(m_device, swapchain, m_allocator); | ||||||
|  | @ -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
 | } // namespace lt::renderer::vk
 | ||||||
|  |  | ||||||
|  | @ -96,6 +96,16 @@ public: | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto get_swapchain_images(VkSwapchainKHR swapchain) const -> std::vector<VkImage>; | 	[[nodiscard]] auto get_swapchain_images(VkSwapchainKHR swapchain) const -> std::vector<VkImage>; | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] auto get_memory_requirements(VkBuffer buffer) const -> VkMemoryRequirements; | ||||||
|  | 
 | ||||||
|  | 	/** binders / mappers  */ | ||||||
|  | 	void bind_memory(VkBuffer buffer, VkDeviceMemory memory, size_t offset = 0u) const; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto map_memory(VkDeviceMemory memory, size_t size, size_t offset) const | ||||||
|  | 	    -> std::span<std::byte>; | ||||||
|  | 
 | ||||||
|  | 	void unmap_memory(VkDeviceMemory memory); | ||||||
|  | 
 | ||||||
| 	/** create functions */ | 	/** create functions */ | ||||||
| 	[[nodiscard]] auto create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR; | 	[[nodiscard]] auto create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR; | ||||||
| 
 | 
 | ||||||
|  | @ -108,8 +118,9 @@ public: | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto create_pass(VkRenderPassCreateInfo info) const -> VkRenderPass; | 	[[nodiscard]] auto create_pass(VkRenderPassCreateInfo info) const -> VkRenderPass; | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto create_pipeline_layout(VkPipelineLayoutCreateInfo info) const | 	[[nodiscard]] auto create_pipeline_layout( | ||||||
| 	    -> VkPipelineLayout; | 	    std::vector<VkPushConstantRange> push_constant_ranges | ||||||
|  | 	) const -> VkPipelineLayout; | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto create_shader_module(VkShaderModuleCreateInfo info) const -> VkShaderModule; | 	[[nodiscard]] auto create_shader_module(VkShaderModuleCreateInfo info) const -> VkShaderModule; | ||||||
| 
 | 
 | ||||||
|  | @ -120,10 +131,17 @@ public: | ||||||
| 	[[nodiscard]] auto create_fences(VkFenceCreateInfo info, uint32_t count) const | 	[[nodiscard]] auto create_fences(VkFenceCreateInfo info, uint32_t count) const | ||||||
| 	    -> std::vector<VkFence>; | 	    -> std::vector<VkFence>; | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] auto create_buffer(VkBufferCreateInfo info) const -> VkBuffer; | ||||||
|  | 
 | ||||||
| 	/** allocation functions */ | 	/** allocation functions */ | ||||||
|  | 	[[nodiscard]] auto allocate_memory(VkMemoryAllocateInfo info) const -> VkDeviceMemory; | ||||||
|  | 
 | ||||||
| 	[[nodiscard]] auto allocate_command_buffers(VkCommandBufferAllocateInfo info) const | 	[[nodiscard]] auto allocate_command_buffers(VkCommandBufferAllocateInfo info) const | ||||||
| 	    -> std::vector<VkCommandBuffer>; | 	    -> std::vector<VkCommandBuffer>; | ||||||
| 
 | 
 | ||||||
|  | 	/** de-allocation functions */ | ||||||
|  | 	void free_memory(VkDeviceMemory memory) const; | ||||||
|  | 
 | ||||||
| 	/** destroy functions */ | 	/** destroy functions */ | ||||||
| 	void destroy_swapchain(VkSwapchainKHR swapchain) const; | 	void destroy_swapchain(VkSwapchainKHR swapchain) const; | ||||||
| 
 | 
 | ||||||
|  | @ -153,6 +171,8 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void destroy_fences(std::span<VkFence> fences) const; | 	void destroy_fences(std::span<VkFence> fences) const; | ||||||
| 
 | 
 | ||||||
|  | 	void destroy_buffer(VkBuffer buffer) const; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
| 	template<typename T> | 	template<typename T> | ||||||
| 	static auto get_object_type(const T &object) -> VkObjectType | 	static auto get_object_type(const T &object) -> VkObjectType | ||||||
|  |  | ||||||
|  | @ -5,35 +5,38 @@ | ||||||
| namespace lt::renderer::vk { | namespace lt::renderer::vk { | ||||||
| 
 | 
 | ||||||
| Gpu::Gpu(IInstance *instance) | Gpu::Gpu(IInstance *instance) | ||||||
|  |     : m_descriptor_indexing_features( | ||||||
|  |           { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES } | ||||||
|  |       ) | ||||||
| { | { | ||||||
| 	auto gpus = static_cast<Instance *>(instance)->enumerate_gpus(); | 	auto gpus = static_cast<Instance *>(instance)->enumerate_gpus(); | ||||||
| 
 | 
 | ||||||
| 	for (auto &gpu : gpus) | 	for (auto &gpu : gpus) | ||||||
| 	{ | 	{ | ||||||
| 		auto properties = VkPhysicalDeviceProperties {}; | 		auto properties = VkPhysicalDeviceProperties {}; | ||||||
| 		auto features = 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_properties(gpu, &properties); | ||||||
| 		vk_get_physical_device_features(gpu, &features); | 		vk_get_physical_device_features(gpu, &features); | ||||||
| 
 | 
 | ||||||
| 		if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU | 		if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU | ||||||
| 		    && features.geometryShader) | 		    && features.features.geometryShader) | ||||||
| 		{ | 		{ | ||||||
| 			m_gpu = gpu; | 			m_gpu = gpu; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	ensure(m_gpu, "Failed to find any suitable Vulkan physical device"); | 	ensure(m_gpu, "Failed to find any suitable Vulkan physical device"); | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| [[nodiscard]] auto Gpu::get_queue_family_properties() const -> std::vector<VkQueueFamilyProperties> | 
 | ||||||
| { | 	vk_get_physical_device_memory_properties(m_gpu, &m_memory_properties); | ||||||
|  | 
 | ||||||
| 	auto count = uint32_t { 0u }; | 	auto count = uint32_t { 0u }; | ||||||
| 	vk_get_physical_device_queue_family_properties(m_gpu, &count, nullptr); | 	vk_get_physical_device_queue_family_properties(m_gpu, &count, nullptr); | ||||||
| 
 | 	m_queue_family_properties.resize(count); | ||||||
| 	auto properties = std::vector<VkQueueFamilyProperties>(count); | 	vk_get_physical_device_queue_family_properties(m_gpu, &count, m_queue_family_properties.data()); | ||||||
| 	vk_get_physical_device_queue_family_properties(m_gpu, &count, properties.data()); |  | ||||||
| 
 |  | ||||||
| 	return properties; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [[nodiscard]] auto Gpu::queue_family_supports_presentation( | [[nodiscard]] auto Gpu::queue_family_supports_presentation( | ||||||
|  | @ -67,5 +70,11 @@ Gpu::Gpu(IInstance *instance) | ||||||
| 	return formats; | 	return formats; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | [[nodiscard]] auto Gpu::create_device(VkDeviceCreateInfo info) const -> VkDevice | ||||||
|  | { | ||||||
|  | 	auto *device = VkDevice {}; | ||||||
|  | 	vkc(vk_create_device(m_gpu, &info, nullptr, &device)); | ||||||
|  | 	return device; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| } // namespace lt::renderer::vk
 | } // namespace lt::renderer::vk
 | ||||||
|  |  | ||||||
|  | @ -12,13 +12,6 @@ class Gpu: public IGpu | ||||||
| public: | public: | ||||||
| 	Gpu(IInstance *instance); | 	Gpu(IInstance *instance); | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto vk() const -> VkPhysicalDevice |  | ||||||
| 	{ |  | ||||||
| 		return m_gpu; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_queue_family_properties() const -> std::vector<VkQueueFamilyProperties>; |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto queue_family_supports_presentation( | 	[[nodiscard]] auto queue_family_supports_presentation( | ||||||
| 	    VkSurfaceKHR surface, | 	    VkSurfaceKHR surface, | ||||||
| 	    uint32_t queue_family_idx | 	    uint32_t queue_family_idx | ||||||
|  | @ -30,8 +23,39 @@ public: | ||||||
| 	[[nodiscard]] auto get_surface_formats(VkSurfaceKHR surface) const | 	[[nodiscard]] auto get_surface_formats(VkSurfaceKHR surface) const | ||||||
| 	    -> std::vector<VkSurfaceFormatKHR>; | 	    -> std::vector<VkSurfaceFormatKHR>; | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] auto create_device(VkDeviceCreateInfo info) const -> VkDevice; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_properties() const -> VkPhysicalDeviceProperties | ||||||
|  | 	{ | ||||||
|  | 		return m_properties; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_descriptor_indexing_features() const | ||||||
|  | 	    -> VkPhysicalDeviceDescriptorIndexingFeatures | ||||||
|  | 	{ | ||||||
|  | 		return m_descriptor_indexing_features; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_memory_properties() const -> VkPhysicalDeviceMemoryProperties | ||||||
|  | 	{ | ||||||
|  | 		return m_memory_properties; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_queue_family_properties() const -> std::vector<VkQueueFamilyProperties> | ||||||
|  | 	{ | ||||||
|  | 		return m_queue_family_properties; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
| 	memory::NullOnMove<VkPhysicalDevice> m_gpu = VK_NULL_HANDLE; | 	memory::NullOnMove<VkPhysicalDevice> m_gpu = VK_NULL_HANDLE; | ||||||
|  | 
 | ||||||
|  | 	VkPhysicalDeviceProperties m_properties {}; | ||||||
|  | 
 | ||||||
|  | 	VkPhysicalDeviceDescriptorIndexingFeatures m_descriptor_indexing_features; | ||||||
|  | 
 | ||||||
|  | 	VkPhysicalDeviceMemoryProperties m_memory_properties {}; | ||||||
|  | 
 | ||||||
|  | 	std::vector<VkQueueFamilyProperties> m_queue_family_properties; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace lt::renderer::vk
 | } // namespace lt::renderer::vk
 | ||||||
|  |  | ||||||
|  | @ -29,8 +29,9 @@ PFN_vkGetPhysicalDeviceQueueFamilyProperties vk_get_physical_device_queue_family | ||||||
| PFN_vkCreateDevice vk_create_device {}; | PFN_vkCreateDevice vk_create_device {}; | ||||||
| PFN_vkGetDeviceProcAddr vk_get_device_proc_address {}; | PFN_vkGetDeviceProcAddr vk_get_device_proc_address {}; | ||||||
| PFN_vkDestroyDevice vk_destroy_device {}; | PFN_vkDestroyDevice vk_destroy_device {}; | ||||||
| PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features {}; | PFN_vkGetPhysicalDeviceFeatures2 vk_get_physical_device_features {}; | ||||||
| PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties {}; | PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties {}; | ||||||
|  | PFN_vkGetPhysicalDeviceMemoryProperties vk_get_physical_device_memory_properties {}; | ||||||
| 
 | 
 | ||||||
| // extension instance functions
 | // extension instance functions
 | ||||||
| PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label {}; | PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label {}; | ||||||
|  | @ -86,15 +87,37 @@ PFN_vkCmdBindPipeline vk_cmd_bind_pipeline {}; | ||||||
| PFN_vkCmdDraw vk_cmd_draw {}; | PFN_vkCmdDraw vk_cmd_draw {}; | ||||||
| PFN_vkCmdSetViewport vk_cmd_set_viewport {}; | PFN_vkCmdSetViewport vk_cmd_set_viewport {}; | ||||||
| PFN_vkCmdSetScissor vk_cmd_set_scissors {}; | PFN_vkCmdSetScissor vk_cmd_set_scissors {}; | ||||||
|  | PFN_vkCmdPushConstants vk_cmd_push_constants {}; | ||||||
|  | PFN_vkCmdCopyBuffer vk_cmd_copy_buffer {}; | ||||||
|  | 
 | ||||||
|  | PFN_vkCreateDescriptorSetLayout vk_create_descriptor_set_layout {}; | ||||||
|  | PFN_vkDestroyDescriptorSetLayout vk_destroy_descriptor_set_layout {}; | ||||||
|  | PFN_vkCreateDescriptorPool vk_create_descriptor_pool {}; | ||||||
|  | PFN_vkDestroyDescriptorPool vk_destroy_descriptor_pool {}; | ||||||
|  | PFN_vkAllocateDescriptorSets vk_allocate_descriptor_sets {}; | ||||||
|  | PFN_vkFreeDescriptorSets vk_free_descriptor_sets {}; | ||||||
|  | 
 | ||||||
|  | PFN_vkCreateBuffer vk_create_buffer {}; | ||||||
|  | PFN_vkDestroyBuffer vk_destroy_buffer {}; | ||||||
|  | PFN_vkGetBufferMemoryRequirements vk_get_buffer_memory_requirements {}; | ||||||
|  | PFN_vkAllocateMemory vk_allocate_memory {}; | ||||||
|  | PFN_vkBindBufferMemory vk_bind_buffer_memory {}; | ||||||
|  | PFN_vkMapMemory vk_map_memory {}; | ||||||
|  | PFN_vkUnmapMemory vk_unmap_memory {}; | ||||||
|  | PFN_vkFreeMemory vk_free_memory {}; | ||||||
| 
 | 
 | ||||||
| PFN_vkResetCommandBuffer vk_reset_command_buffer {}; | PFN_vkResetCommandBuffer vk_reset_command_buffer {}; | ||||||
| 
 | 
 | ||||||
|  | PFN_vkCmdBeginRendering vk_cmd_begin_rendering {}; | ||||||
|  | PFN_vkCmdEndRendering vk_cmd_end_rendering {}; | ||||||
|  | 
 | ||||||
| PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {}; | PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {}; | ||||||
| PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vk_get_physical_device_surface_capabilities {}; | PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vk_get_physical_device_surface_capabilities {}; | ||||||
| PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vk_get_physical_device_surface_formats {}; | PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vk_get_physical_device_surface_formats {}; | ||||||
| 
 | 
 | ||||||
| auto vk_create_xlib_surface_khr = PFN_vkCreateXlibSurfaceKHR {}; | auto vk_create_xlib_surface_khr = PFN_vkCreateXlibSurfaceKHR {}; | ||||||
| auto vk_destroy_surface_khr = PFN_vkDestroySurfaceKHR {}; | auto vk_destroy_surface_khr = PFN_vkDestroySurfaceKHR {}; | ||||||
|  | 
 | ||||||
| // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
 | // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
 | ||||||
| 
 | 
 | ||||||
| Instance::Instance() | Instance::Instance() | ||||||
|  | @ -127,6 +150,7 @@ void Instance::initialize_instance() | ||||||
| 		VK_EXT_DEBUG_UTILS_EXTENSION_NAME, | 		VK_EXT_DEBUG_UTILS_EXTENSION_NAME, | ||||||
| 		VK_KHR_SURFACE_EXTENSION_NAME, | 		VK_KHR_SURFACE_EXTENSION_NAME, | ||||||
| 		VK_KHR_XLIB_SURFACE_EXTENSION_NAME, | 		VK_KHR_XLIB_SURFACE_EXTENSION_NAME, | ||||||
|  | 		VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	const char *layer_name = "VK_LAYER_KHRONOS_validation"; | 	const char *layer_name = "VK_LAYER_KHRONOS_validation"; | ||||||
|  | @ -217,6 +241,7 @@ void Instance::initialize_instance() | ||||||
| 		vkc(vk_enumerate_instance_extension_properties(nullptr, &count, nullptr)); | 		vkc(vk_enumerate_instance_extension_properties(nullptr, &count, nullptr)); | ||||||
| 
 | 
 | ||||||
| 		auto extensions = std::vector<VkExtensionProperties>(count); | 		auto extensions = std::vector<VkExtensionProperties>(count); | ||||||
|  | 		memset(extensions.data(), 0, extensions.size() * sizeof(VkExtensionProperties)); | ||||||
| 		vkc(vk_enumerate_instance_extension_properties(nullptr, &count, extensions.data())); | 		vkc(vk_enumerate_instance_extension_properties(nullptr, &count, extensions.data())); | ||||||
| 
 | 
 | ||||||
| 		// log_inf("Available vulkan instance extensions:");
 | 		// log_inf("Available vulkan instance extensions:");
 | ||||||
|  | @ -232,7 +257,7 @@ void Instance::initialize_instance() | ||||||
| 
 | 
 | ||||||
| void Instance::load_library() | 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); | 	library = dlopen("libvulkan.so.1", runtime_loader_flags); | ||||||
| 	if (!library) | 	if (!library) | ||||||
| 	{ | 	{ | ||||||
|  | @ -297,6 +322,7 @@ void Instance::load_instance_functions() | ||||||
| 	load_fn(vk_destroy_device, "vkDestroyDevice"); | 	load_fn(vk_destroy_device, "vkDestroyDevice"); | ||||||
| 	load_fn(vk_get_physical_device_features, "vkGetPhysicalDeviceFeatures"); | 	load_fn(vk_get_physical_device_features, "vkGetPhysicalDeviceFeatures"); | ||||||
| 	load_fn(vk_enumerate_device_extension_properties, "vkEnumerateDeviceExtensionProperties"); | 	load_fn(vk_enumerate_device_extension_properties, "vkEnumerateDeviceExtensionProperties"); | ||||||
|  | 	load_fn(vk_get_physical_device_memory_properties, "vkGetPhysicalDeviceMemoryProperties"); | ||||||
| 
 | 
 | ||||||
| 	load_fn(vk_cmd_begin_debug_label, "vkCmdBeginDebugUtilsLabelEXT"); | 	load_fn(vk_cmd_begin_debug_label, "vkCmdBeginDebugUtilsLabelEXT"); | ||||||
| 	load_fn(vk_cmd_end_debug_label, "vkCmdEndDebugUtilsLabelEXT"); | 	load_fn(vk_cmd_end_debug_label, "vkCmdEndDebugUtilsLabelEXT"); | ||||||
|  | @ -369,7 +395,26 @@ void Instance::load_device_functions_impl(VkDevice device) | ||||||
| 	load_fn(vk_cmd_draw, "vkCmdDraw"); | 	load_fn(vk_cmd_draw, "vkCmdDraw"); | ||||||
| 	load_fn(vk_cmd_set_viewport, "vkCmdSetViewport"); | 	load_fn(vk_cmd_set_viewport, "vkCmdSetViewport"); | ||||||
| 	load_fn(vk_cmd_set_scissors, "vkCmdSetScissor"); | 	load_fn(vk_cmd_set_scissors, "vkCmdSetScissor"); | ||||||
|  | 	load_fn(vk_cmd_push_constants, "vkCmdPushConstants"); | ||||||
|  | 	load_fn(vk_cmd_copy_buffer, "vkCmdCopyBuffer"); | ||||||
|  | 	load_fn(vk_create_descriptor_set_layout, "vkCreateDescriptorSetLayout"); | ||||||
|  | 	load_fn(vk_destroy_descriptor_set_layout, "vkDestroyDescriptorSetLayout"); | ||||||
|  | 	load_fn(vk_create_descriptor_pool, "vkCreateDescriptorPool"); | ||||||
|  | 	load_fn(vk_destroy_descriptor_pool, "vkDestroyDescriptorPool"); | ||||||
|  | 	load_fn(vk_allocate_descriptor_sets, "vkAllocateDescriptorSets"); | ||||||
|  | 	load_fn(vk_free_descriptor_sets, "vkFreeDescriptorSets"); | ||||||
|  | 	load_fn(vk_create_buffer, "vkCreateBuffer"); | ||||||
|  | 	load_fn(vk_destroy_buffer, "vkDestroyBuffer"); | ||||||
|  | 	load_fn(vk_allocate_memory, "vkAllocateMemory"); | ||||||
|  | 	load_fn(vk_bind_buffer_memory, "vkBindBufferMemory"); | ||||||
|  | 	load_fn(vk_map_memory, "vkMapMemory"); | ||||||
|  | 	load_fn(vk_unmap_memory, "vkUnmapMemory"); | ||||||
|  | 	load_fn(vk_free_memory, "vkFreeMemory"); | ||||||
|  | 	load_fn(vk_get_buffer_memory_requirements, "vkGetBufferMemoryRequirements"); | ||||||
| 	load_fn(vk_reset_command_buffer, "vkResetCommandBuffer"); | 	load_fn(vk_reset_command_buffer, "vkResetCommandBuffer"); | ||||||
|  | 
 | ||||||
|  | 	load_fn(vk_cmd_begin_rendering, "vkCmdBeginRendering"); | ||||||
|  | 	load_fn(vk_cmd_end_rendering, "vkCmdEndRendering"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| auto Instance::enumerate_gpus() const -> std::vector<VkPhysicalDevice> | auto Instance::enumerate_gpus() const -> std::vector<VkPhysicalDevice> | ||||||
|  |  | ||||||
|  | @ -75,7 +75,6 @@ private: | ||||||
| 	void load_instance_functions(); | 	void load_instance_functions(); | ||||||
| 
 | 
 | ||||||
| 	void load_device_functions_impl(VkDevice device); | 	void load_device_functions_impl(VkDevice device); | ||||||
| 
 |  | ||||||
| 	VkInstance m_instance = VK_NULL_HANDLE; | 	VkInstance m_instance = VK_NULL_HANDLE; | ||||||
| 
 | 
 | ||||||
| 	VkAllocationCallbacks *m_allocator = nullptr; | 	VkAllocationCallbacks *m_allocator = nullptr; | ||||||
|  |  | ||||||
|  | @ -49,6 +49,17 @@ public: | ||||||
| 		return m_images.size(); | 		return m_images.size(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] auto get_image_view(uint32_t idx) -> VkImageView | ||||||
|  | 	{ | ||||||
|  | 		return m_image_views[idx]; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_image(uint32_t idx) -> VkImage | ||||||
|  | 	{ | ||||||
|  | 		return m_images[idx]; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 	[[nodiscard]] auto create_framebuffers_for_pass(VkRenderPass pass) const | 	[[nodiscard]] auto create_framebuffers_for_pass(VkRenderPass pass) const | ||||||
| 	    -> std::vector<VkFramebuffer>; | 	    -> std::vector<VkFramebuffer>; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										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 <memory/pointer_types/null_on_move.hpp> | ||||||
|  | #include <renderer/backend/vk/context/device.hpp> | ||||||
| #include <renderer/backend/vk/context/instance.hpp> | #include <renderer/backend/vk/context/instance.hpp> | ||||||
| #include <renderer/backend/vk/vulkan.hpp> | #include <renderer/backend/vk/vulkan.hpp> | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| namespace lt::renderer::vk::raii { | namespace lt::renderer::vk::raii { | ||||||
| 
 | 
 | ||||||
| // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
 |  | ||||||
| class DebugMessenger | class DebugMessenger | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  | @ -16,18 +17,108 @@ public: | ||||||
| 
 | 
 | ||||||
| 	~DebugMessenger() | 	~DebugMessenger() | ||||||
| 	{ | 	{ | ||||||
| 		if (!m_instance) | 		if (m_instance) | ||||||
| 		{ | 		{ | ||||||
| 			return; | 			m_instance->destroy_messenger(m_object); | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		m_instance->destroy_messenger(m_object); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	DebugMessenger(DebugMessenger &&) = default; | ||||||
|  | 
 | ||||||
|  | 	DebugMessenger(const DebugMessenger &) = delete; | ||||||
|  | 
 | ||||||
|  | 	auto operator=(DebugMessenger &&) -> DebugMessenger & = default; | ||||||
|  | 
 | ||||||
|  | 	auto operator=(const DebugMessenger &) -> DebugMessenger & = delete; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
| 	memory::NullOnMove<Instance *> m_instance {}; | 	memory::NullOnMove<Instance *> m_instance {}; | ||||||
| 
 | 
 | ||||||
| 	VkDebugUtilsMessengerEXT m_object; | 	VkDebugUtilsMessengerEXT m_object; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | class Buffer | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	Buffer(Device *device, VkBufferCreateInfo info) | ||||||
|  | 	    : m_device(device) | ||||||
|  | 	    , m_object(m_device->create_buffer(info)) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	~Buffer() | ||||||
|  | 	{ | ||||||
|  | 		if (m_device) | ||||||
|  | 		{ | ||||||
|  | 			m_device->destroy_buffer(m_object); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Buffer(Buffer &&) = default; | ||||||
|  | 
 | ||||||
|  | 	Buffer(const Buffer &) = delete; | ||||||
|  | 
 | ||||||
|  | 	auto operator=(Buffer &&) -> Buffer & = default; | ||||||
|  | 
 | ||||||
|  | 	auto operator=(const Buffer &) -> Buffer & = delete; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto operator*() const -> VkBuffer | ||||||
|  | 	{ | ||||||
|  | 		return m_object; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] operator VkBuffer() const | ||||||
|  | 	{ | ||||||
|  | 		return m_object; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	memory::NullOnMove<Device *> m_device {}; | ||||||
|  | 
 | ||||||
|  | 	VkBuffer m_object; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class Memory | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	Memory(Device *device, VkBuffer buffer, VkMemoryAllocateInfo info) | ||||||
|  | 	    : m_device(device) | ||||||
|  | 	    , m_object(m_device->allocate_memory(info)) | ||||||
|  | 	{ | ||||||
|  | 		m_device->bind_memory(buffer, m_object); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	~Memory() | ||||||
|  | 	{ | ||||||
|  | 		if (m_device) | ||||||
|  | 		{ | ||||||
|  | 			m_device->free_memory(m_object); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Memory(Memory &&) = default; | ||||||
|  | 
 | ||||||
|  | 	Memory(const Memory &) = delete; | ||||||
|  | 
 | ||||||
|  | 	auto operator=(Memory &&) -> Memory & = default; | ||||||
|  | 
 | ||||||
|  | 	auto operator=(const Memory &) -> Memory & = delete; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto operator*() const -> VkDeviceMemory | ||||||
|  | 	{ | ||||||
|  | 		return m_object; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] operator VkDeviceMemory() const | ||||||
|  | 	{ | ||||||
|  | 		return m_object; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	memory::NullOnMove<Device *> m_device {}; | ||||||
|  | 
 | ||||||
|  | 	VkDeviceMemory m_object = VK_NULL_HANDLE; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } // namespace lt::renderer::vk::raii
 | } // namespace lt::renderer::vk::raii
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include <renderer/backend/vk/context/device.hpp> | #include <renderer/backend/vk/context/device.hpp> | ||||||
| #include <renderer/backend/vk/context/swapchain.hpp> | #include <renderer/backend/vk/context/swapchain.hpp> | ||||||
| #include <renderer/backend/vk/renderer/pass.hpp> | #include <renderer/backend/vk/renderer/pass.hpp> | ||||||
|  | #include <renderer/data/frame_constants.hpp> | ||||||
| 
 | 
 | ||||||
| namespace lt::renderer::vk { | namespace lt::renderer::vk { | ||||||
| 
 | 
 | ||||||
|  | @ -12,12 +13,12 @@ Pass::Pass( | ||||||
| ) | ) | ||||||
|     : m_device(static_cast<Device *>(device)) |     : m_device(static_cast<Device *>(device)) | ||||||
|     , m_layout(m_device->create_pipeline_layout( |     , m_layout(m_device->create_pipeline_layout( | ||||||
|           VkPipelineLayoutCreateInfo { |           std::vector<VkPushConstantRange> { | ||||||
|               .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |               VkPushConstantRange { | ||||||
|               .setLayoutCount = 0u, |                   .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, | ||||||
|               .pSetLayouts = nullptr, |                   .offset = 0u, | ||||||
|               .pushConstantRangeCount = 0u, |                   .size = sizeof(FrameConstants), | ||||||
|               .pPushConstantRanges = nullptr, |               }, | ||||||
|           } |           } | ||||||
|       )) |       )) | ||||||
| { | { | ||||||
|  | @ -112,17 +113,16 @@ Pass::Pass( | ||||||
| 		.blendConstants = { 0.0f, 0.0, 0.0, 0.0 }, | 		.blendConstants = { 0.0f, 0.0, 0.0, 0.0 }, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 
 | 	// auto attachment_description = VkAttachmentDescription {
 | ||||||
| 	auto attachment_description = VkAttachmentDescription { | 	// 	.format =,
 | ||||||
| 		.format = static_cast<Swapchain *>(swapchain)->get_format(), | 	// 	.samples = VK_SAMPLE_COUNT_1_BIT,
 | ||||||
| 		.samples = VK_SAMPLE_COUNT_1_BIT, | 	// 	.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
 | ||||||
| 		.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, | 	// 	.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
 | ||||||
| 		.storeOp = VK_ATTACHMENT_STORE_OP_STORE, | 	// 	.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
 | ||||||
| 		.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, | 	// 	.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
 | ||||||
| 		.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, | 	// 	.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
 | ||||||
| 		.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, | 	// 	.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
 | ||||||
| 		.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, | 	// };
 | ||||||
| 	}; |  | ||||||
| 
 | 
 | ||||||
| 	auto color_attachment_ref = VkAttachmentReference { | 	auto color_attachment_ref = VkAttachmentReference { | ||||||
| 		.attachment = 0, | 		.attachment = 0, | ||||||
|  | @ -144,21 +144,18 @@ Pass::Pass( | ||||||
| 		.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | 		.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	m_pass = m_device->create_pass( | 	auto color_format = static_cast<Swapchain *>(swapchain)->get_format(); | ||||||
| 	    VkRenderPassCreateInfo { | 	auto rendering_info = VkPipelineRenderingCreateInfoKHR { | ||||||
| 	        .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, | 		.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO, | ||||||
| 	        .attachmentCount = 1u, | 		.colorAttachmentCount = 1u, | ||||||
| 	        .pAttachments = &attachment_description, | 		.pColorAttachmentFormats = &color_format, | ||||||
| 	        .subpassCount = 1u, | 
 | ||||||
| 	        .pSubpasses = &subpass_description, | 	}; | ||||||
| 	        .dependencyCount = 1u, |  | ||||||
| 	        .pDependencies = &pass_dependency, |  | ||||||
| 	    } |  | ||||||
| 	); |  | ||||||
| 
 | 
 | ||||||
| 	m_pipeline = m_device->create_graphics_pipeline( | 	m_pipeline = m_device->create_graphics_pipeline( | ||||||
| 	    VkGraphicsPipelineCreateInfo { | 	    VkGraphicsPipelineCreateInfo { | ||||||
| 	        .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | 	        .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, | ||||||
|  | 	        .pNext = &rendering_info, | ||||||
| 	        .stageCount = static_cast<uint32_t>(shader_stages.size()), | 	        .stageCount = static_cast<uint32_t>(shader_stages.size()), | ||||||
| 	        .pStages = shader_stages.data(), | 	        .pStages = shader_stages.data(), | ||||||
| 	        .pVertexInputState = &vertex_input, | 	        .pVertexInputState = &vertex_input, | ||||||
|  | @ -170,15 +167,14 @@ Pass::Pass( | ||||||
| 	        .pColorBlendState = &color_blend, | 	        .pColorBlendState = &color_blend, | ||||||
| 	        .pDynamicState = &dynamic_state, | 	        .pDynamicState = &dynamic_state, | ||||||
| 	        .layout = m_layout, | 	        .layout = m_layout, | ||||||
| 	        .renderPass = m_pass, | 	        .renderPass = VK_NULL_HANDLE, | ||||||
| 	        .subpass = 0u, | 	        .subpass = 0u, | ||||||
| 	        .basePipelineHandle = VK_NULL_HANDLE, | 	        .basePipelineHandle = VK_NULL_HANDLE, | ||||||
| 	        .basePipelineIndex = -1, | 	        .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(vertex_module); | ||||||
| 	m_device->destroy_shader_module(fragment_module); | 	m_device->destroy_shader_module(fragment_module); | ||||||
|  | @ -194,7 +190,7 @@ Pass::~Pass() | ||||||
| 	m_device->wait_idle(); | 	m_device->wait_idle(); | ||||||
| 	m_device->destroy_framebuffers(m_framebuffers); | 	m_device->destroy_framebuffers(m_framebuffers); | ||||||
| 	m_device->destroy_pipeline(m_pipeline); | 	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); | 	m_device->destroy_pipeline_layout(m_layout); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -207,7 +203,8 @@ void Pass::replace_swapchain(const ISwapchain &swapchain) | ||||||
| 
 | 
 | ||||||
| 	m_device->wait_idle(); | 	m_device->wait_idle(); | ||||||
| 	m_device->destroy_framebuffers(m_framebuffers); | 	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 | auto Pass::create_module(lt::assets::Blob blob) -> VkShaderModule | ||||||
|  |  | ||||||
|  | @ -29,16 +29,16 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void replace_swapchain(const ISwapchain &swapchain); | 	void replace_swapchain(const ISwapchain &swapchain); | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto get_pass() -> VkRenderPass |  | ||||||
| 	{ |  | ||||||
| 		return m_pass; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto get_pipeline() -> VkPipeline | 	[[nodiscard]] auto get_pipeline() -> VkPipeline | ||||||
| 	{ | 	{ | ||||||
| 		return m_pipeline; | 		return m_pipeline; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] auto get_layout() -> VkPipelineLayout | ||||||
|  | 	{ | ||||||
|  | 		return m_layout; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	[[nodiscard]] auto get_framebuffers() -> std::vector<VkFramebuffer> & | 	[[nodiscard]] auto get_framebuffers() -> std::vector<VkFramebuffer> & | ||||||
| 	{ | 	{ | ||||||
| 		return m_framebuffers; | 		return m_framebuffers; | ||||||
|  | @ -49,8 +49,6 @@ private: | ||||||
| 
 | 
 | ||||||
| 	memory::NullOnMove<class Device *> m_device {}; | 	memory::NullOnMove<class Device *> m_device {}; | ||||||
| 
 | 
 | ||||||
| 	VkRenderPass m_pass = VK_NULL_HANDLE; |  | ||||||
| 
 |  | ||||||
| 	VkPipeline m_pipeline = VK_NULL_HANDLE; | 	VkPipeline m_pipeline = VK_NULL_HANDLE; | ||||||
| 
 | 
 | ||||||
| 	VkPipelineLayout m_layout = VK_NULL_HANDLE; | 	VkPipelineLayout m_layout = VK_NULL_HANDLE; | ||||||
|  |  | ||||||
|  | @ -100,6 +100,7 @@ Renderer::~Renderer() | ||||||
| 	vk_reset_command_buffer(cmd, {}); | 	vk_reset_command_buffer(cmd, {}); | ||||||
| 	record_cmd(cmd, *image_idx); | 	record_cmd(cmd, *image_idx); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 	auto wait_stage = VkPipelineStageFlags { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; | 	auto wait_stage = VkPipelineStageFlags { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; | ||||||
| 	auto &submit_semaphore = m_submit_semaphores[*image_idx]; | 	auto &submit_semaphore = m_submit_semaphores[*image_idx]; | ||||||
| 	m_device->submit( | 	m_device->submit( | ||||||
|  | @ -142,35 +143,52 @@ void Renderer::replace_swapchain(ISwapchain *swapchain) | ||||||
| 
 | 
 | ||||||
| void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx) | 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, | 		.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, | ||||||
| 		.flags = {}, | 		.flags = {}, | ||||||
| 		.pInheritanceInfo = nullptr, | 		.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, |  | ||||||
|             }, |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 	auto pass_begin_info = VkRenderPassBeginInfo { |  | ||||||
| 		.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, |  | ||||||
| 		.renderPass = m_pass->get_pass(), |  | ||||||
| 		.framebuffer = m_pass->get_framebuffers()[image_idx], |  | ||||||
| 		.renderArea = { .offset = {}, .extent = m_resolution }, |  | ||||||
| 		.clearValueCount = 1u, |  | ||||||
| 		.pClearValues = &clear_value |  | ||||||
| 	}; | 	}; | ||||||
| 	vk_cmd_begin_render_pass(cmd, &pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); |  | ||||||
| 	vk_cmd_bind_pipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pass->get_pipeline()); |  | ||||||
| 
 | 
 | ||||||
| 	auto viewport = VkViewport { | 	const auto end_frame_barrier = VkImageMemoryBarrier { | ||||||
|  | 		.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||||||
|  | 		.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, | ||||||
|  | 		.dstAccessMask = {}, | ||||||
|  | 		.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, | ||||||
|  | 		.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, | ||||||
|  |         .image = m_swapchain->get_image(image_idx), | ||||||
|  | 
 | ||||||
|  |         .subresourceRange = VkImageSubresourceRange{ | ||||||
|  |             .aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT, | ||||||
|  |             .baseMipLevel   = 0u, | ||||||
|  |             .levelCount     = VK_REMAINING_MIP_LEVELS, | ||||||
|  |             .baseArrayLayer = 0u, | ||||||
|  |             .layerCount     = VK_REMAINING_ARRAY_LAYERS, | ||||||
|  |         }, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	const auto scissor = VkRect2D { | ||||||
|  | 		.offset = { .x = 0u, .y = 0u }, | ||||||
|  | 		.extent = m_resolution, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	const auto viewport = VkViewport { | ||||||
| 		.x = 0.0f, | 		.x = 0.0f, | ||||||
| 		.y = 0.0f, | 		.y = 0.0f, | ||||||
| 		.width = static_cast<float>(m_resolution.width), | 		.width = static_cast<float>(m_resolution.width), | ||||||
|  | @ -178,17 +196,70 @@ void Renderer::record_cmd(VkCommandBuffer cmd, uint32_t image_idx) | ||||||
| 		.minDepth = 0.0f, | 		.minDepth = 0.0f, | ||||||
| 		.maxDepth = 1.0f, | 		.maxDepth = 1.0f, | ||||||
| 	}; | 	}; | ||||||
| 	vk_cmd_set_viewport(cmd, 0, 1, &viewport); |  | ||||||
| 
 | 
 | ||||||
| 	auto scissor = VkRect2D { | 	const auto color_attachment_info = VkRenderingAttachmentInfoKHR { | ||||||
| 		.offset = { 0u, 0u }, | 		.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, | ||||||
| 		.extent = m_resolution, | 		.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_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)); | 	vkc(vk_end_command_buffer(cmd)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void submit_sprite(const components::Sprite &sprite, const math::components::Transform &transform) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace lt::renderer::vk
 | } // namespace lt::renderer::vk
 | ||||||
|  |  | ||||||
|  | @ -3,8 +3,10 @@ | ||||||
| #include <memory/reference.hpp> | #include <memory/reference.hpp> | ||||||
| #include <ranges> | #include <ranges> | ||||||
| #include <renderer/backend/vk/context/device.hpp> | #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/renderer/pass.hpp> | ||||||
| #include <renderer/backend/vk/utils.hpp> | #include <renderer/backend/vk/utils.hpp> | ||||||
|  | #include <renderer/frontend/data/buffer.hpp> | ||||||
| #include <renderer/frontend/renderer/pass.hpp> | #include <renderer/frontend/renderer/pass.hpp> | ||||||
| #include <renderer/frontend/renderer/renderer.hpp> | #include <renderer/frontend/renderer/renderer.hpp> | ||||||
| 
 | 
 | ||||||
|  | @ -29,6 +31,18 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void replace_swapchain(ISwapchain *swapchain) override; | 	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: | private: | ||||||
| 	void record_cmd(VkCommandBuffer cmd, uint32_t image_idx); | 	void record_cmd(VkCommandBuffer cmd, uint32_t image_idx); | ||||||
| 
 | 
 | ||||||
|  | @ -51,6 +65,8 @@ private: | ||||||
| 	VkExtent2D m_resolution; | 	VkExtent2D m_resolution; | ||||||
| 
 | 
 | ||||||
| 	uint32_t m_max_frames_in_flight {}; | 	uint32_t m_max_frames_in_flight {}; | ||||||
|  | 
 | ||||||
|  | 	FrameConstants m_frame_constants; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace lt::renderer::vk
 | } // 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_vkCreateDevice vk_create_device; | ||||||
| extern PFN_vkGetDeviceProcAddr vk_get_device_proc_address; | extern PFN_vkGetDeviceProcAddr vk_get_device_proc_address; | ||||||
| extern PFN_vkDestroyDevice vk_destroy_device; | 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_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties; | ||||||
|  | extern PFN_vkGetPhysicalDeviceMemoryProperties vk_get_physical_device_memory_properties; | ||||||
| 
 | 
 | ||||||
| // extension instance functions
 | // extension instance functions
 | ||||||
| extern PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label; | 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_vkCmdDraw vk_cmd_draw; | ||||||
| extern PFN_vkCmdSetViewport vk_cmd_set_viewport; | extern PFN_vkCmdSetViewport vk_cmd_set_viewport; | ||||||
| extern PFN_vkCmdSetScissor vk_cmd_set_scissors; | 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_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)
 | // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
 | ||||||
| 
 | 
 | ||||||
| } // namespace lt::renderer::vk
 | } // 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 = [] { | Suite raii = "pass_raii"_suite = [] { | ||||||
| 	Case { "happy path won't throw" } = [] { | 	Case { "happy path won't throw" } = [] { | ||||||
| 		auto fixture = Fixture_RendererSystem {}; | 		Fixture_ auto fixture = Fixture_RendererSystem {}; | ||||||
| 		auto &system = fixture.renderer_system(); | 		auto &system = fixture.renderer_system(); | ||||||
| 
 | 
 | ||||||
| 		std::ignore = lt::renderer::IPass::create( | 		std::ignore = lt::renderer::IPass::create( | ||||||
|  |  | ||||||
|  | @ -1,7 +1,10 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <math/components/transform.hpp> | ||||||
| #include <memory/scope.hpp> | #include <memory/scope.hpp> | ||||||
| #include <renderer/api.hpp> | #include <renderer/api.hpp> | ||||||
|  | #include <renderer/components/sprite.hpp> | ||||||
|  | #include <renderer/data/frame_constants.hpp> | ||||||
| 
 | 
 | ||||||
| namespace lt::renderer { | namespace lt::renderer { | ||||||
| 
 | 
 | ||||||
|  | @ -41,6 +44,13 @@ public: | ||||||
| 	[[nodiscard]] virtual auto draw(uint32_t frame_idx) -> DrawResult = 0; | 	[[nodiscard]] virtual auto draw(uint32_t frame_idx) -> DrawResult = 0; | ||||||
| 
 | 
 | ||||||
| 	virtual void replace_swapchain(class ISwapchain *swapchain) = 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
 | } // 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/messenger.hpp> | ||||||
|  | #include <renderer/components/sprite.hpp> | ||||||
| #include <renderer/frontend/context/device.hpp> | #include <renderer/frontend/context/device.hpp> | ||||||
| #include <renderer/frontend/context/gpu.hpp> | #include <renderer/frontend/context/gpu.hpp> | ||||||
| #include <renderer/frontend/context/instance.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) | 	if (m_renderer->draw(m_frame_idx) != IRenderer::DrawResult::success) | ||||||
| 	{ | 	{ | ||||||
| 		m_swapchain.reset(); | 		m_swapchain.reset(); | ||||||
|  |  | ||||||
|  | @ -1 +0,0 @@ | ||||||
| 
 |  | ||||||
|  | @ -148,7 +148,6 @@ public: | ||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto has_any_messages() const -> bool | 	[[nodiscard]] auto has_any_messages() const -> bool | ||||||
| 	{ | 	{ | ||||||
| 		return m_user_data->m_has_any_messages; | 		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 { | namespace lt::renderer { | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| class IMessenger | class IMessenger | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  |  | ||||||
|  | @ -55,31 +55,6 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void tick(app::TickInfo tick) override; | 	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 | 	[[nodiscard]] auto get_last_tick_result() const -> const app::TickResult & override | ||||||
| 	{ | 	{ | ||||||
| 		return m_last_tick_result; | 		return m_last_tick_result; | ||||||
|  |  | ||||||
|  | @ -11,14 +11,18 @@ | ||||||
| #include <X11/keysym.h> | #include <X11/keysym.h> | ||||||
| #include <X11/keysymdef.h> | #include <X11/keysymdef.h> | ||||||
| 
 | 
 | ||||||
|  | //
 | ||||||
|  | 
 | ||||||
| namespace lt::surface { | namespace lt::surface { | ||||||
| 
 | 
 | ||||||
| template<int EventType> | template<int EventType> | ||||||
| int XEventTypeEquals(Display *, XEvent *event, XPointer winptr) | auto XEventTypeEquals(Display *display, XEvent *event, char *winptr) -> int | ||||||
| { | { | ||||||
|  | 	std::ignore = display; | ||||||
| 	return ( | 	return ( | ||||||
| 	    event->type == EventType | 	    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); | 	XSetWMProtocols(display, main_window, &surface.m_native_data.wm_delete_message, 1); | ||||||
| 
 | 
 | ||||||
| 	// code to remove decoration
 | 	// 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); | 	const auto motif_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False); | ||||||
| 
 | 
 | ||||||
| 	XChangeProperty( | 	XChangeProperty( | ||||||
|  | @ -340,7 +344,7 @@ void System::modify_resolution(SurfaceComponent &surface, const ModifyResolution | ||||||
| 	// XResizeWindow(display, window, width, height);
 | 	// XResizeWindow(display, window, width, height);
 | ||||||
| 
 | 
 | ||||||
| 	// get baseline serial number for X requests generated from XResizeWindow
 | 	// 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
 | 	// request a new window size from the X server
 | ||||||
| 	XResizeWindow(display, window, static_cast<uint32_t>(width), static_cast<uint32_t>(height)); | 	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; | 	const auto &[x, y] = request.position; | ||||||
| 
 | 
 | ||||||
| 	// get baseline serial number for X requests generated from XResizeWindow
 | 	// 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)); | 	XMoveWindow(display, window, static_cast<int>(x), static_cast<int>(y)); | ||||||
| 
 | 
 | ||||||
| 	// flush output queue and wait for X server to processes the request
 | 	// 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_ne; | ||||||
| using test::expect_not_nullptr; | using test::expect_not_nullptr; | ||||||
| using test::expect_throw; | using test::expect_throw; | ||||||
| using test::expect_true; |  | ||||||
| using test::Suite; | using test::Suite; | ||||||
| 
 | 
 | ||||||
| [[nodiscard]] auto tick_info() -> app::TickInfo | [[nodiscard]] auto tick_info() -> app::TickInfo | ||||||
|  |  | ||||||
|  | @ -1,99 +1,447 @@ | ||||||
| FROM archlinux:latest | 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 ## | ## Packages ## | ||||||
| RUN \ | RUN \ | ||||||
| sed -i 's/^#ParallelDownloads = .*/ParallelDownloads = 8/' /etc/pacman.conf \ | pacman -Syyu --noconfirm --needed --disable-download-timeout \ | ||||||
| && echo 'NoExtract = usr/share/{man,doc,info}/*' >> /etc/pacman.conf \ |     afl++ \ | ||||||
| && pacman -Syyu --noconfirm --needed --disable-download-timeout \ |     afl-utils \ | ||||||
| afl++ \ |     base-devel \ | ||||||
| afl-utils \ |     bash \ | ||||||
| base-devel \ |     cbindgen \ | ||||||
| bash \ |     clang \ | ||||||
| clang \ |     cmake \ | ||||||
| cmake \ |     curl \ | ||||||
| curl \ |     debuginfod \ | ||||||
| expat \ |     directx-headers \ | ||||||
| gcc \ |     elfutils \ | ||||||
| gdb \ |     expat \ | ||||||
| git \ |     gcc \ | ||||||
| glm \ |     gcc-libs \ | ||||||
| libc++ \ |     gdb \ | ||||||
| libinput \ |     git \ | ||||||
| libpciaccess \ |     glibc \ | ||||||
| libpng \ |     glm \ | ||||||
| libunwind \ |     glslang \ | ||||||
| libx11 \ |     libc++ \ | ||||||
| libxcb \ |     libclc \ | ||||||
| libxcursor \ |     libdrm \ | ||||||
| libxi \ |     libelf \ | ||||||
| libxinerama \ |     libglvnd \ | ||||||
| libxpresent \ |     libinput \ | ||||||
| libxrandr \ |     libpciaccess \ | ||||||
| lz4 \ |     libpng \ | ||||||
| mesa \ |     libunwind \ | ||||||
| mold \ |     libva \ | ||||||
| ninja \ |     libx11 \ | ||||||
| python \ |     libxcb \ | ||||||
| python-distlib \ |     libxdamage \ | ||||||
| python-distutils-extra \ |     libxext \ | ||||||
| python-jsonschema \ |     libxfixes \ | ||||||
| qt5-base \ |     libxi \ | ||||||
| qt6-base \ |     libxinerama \ | ||||||
| valgrind \ |     libxml2 \ | ||||||
| vulkan-headers \ |     libxpresent \ | ||||||
| vulkan-icd-loader \ |     libxrandr \ | ||||||
| vulkan-tools \ |     libxshmfence \ | ||||||
| vulkan-validation-layers \ |     libxxf86vm \ | ||||||
| wayland \ |     lm_sensors \ | ||||||
| wayland-protocols \ |     llvm \ | ||||||
| wget \ |     lz4 \ | ||||||
| xcb-util \ |     meson \ | ||||||
| xcb-util-cursor \ |     mold \ | ||||||
| xcb-util-keysyms \ |     ninja \ | ||||||
| xcb-util-wm \ |     python \ | ||||||
| xorg-server-xvfb \ |     python-distlib \ | ||||||
| xorg-util-macros \ |     python-distutils-extra \ | ||||||
| xtrans \ |     python-jsonschema \ | ||||||
| zlib \ |     python-mako \ | ||||||
| zstd \ |     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 \ | ||||||
|  |     vulkan-tools \ | ||||||
|  |     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 | && pacman -Scc --noconfirm | ||||||
| 
 | 
 | ||||||
| ## Sanitizers ## | ## Libc++ ## | ||||||
| RUN \ | RUN \ | ||||||
| git clone --depth=1 https://github.com/llvm/llvm-project.git -b llvmorg-20.1.8 \ | git clone \ | ||||||
| && mkdir llvm-project/build-lsan llvm-project/build-msan \ |     --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 \ | ||||||
| && cmake -G Ninja \ |     -S ./runtimes \ | ||||||
|   -DCMAKE_BUILD_TYPE=Release \ |     -B ./build-lsan \ | ||||||
|   -DCMAKE_LINKER_TYPE="MOLD" \ |     -G Ninja \ | ||||||
|   -DCMAKE_INSTALL_PREFIX=/libcxx_lsan \ |     -D CMAKE_LINKER_TYPE="MOLD" \ | ||||||
|   -DCMAKE_C_COMPILER=clang \ |     -D CMAKE_BUILD_TYPE=Release \ | ||||||
|   -DCMAKE_CXX_COMPILER=clang++ \ |     -D CMAKE_INSTALL_PREFIX=/libcxx_lsan \ | ||||||
|   -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ |     -D CMAKE_C_COMPILER=$(which clang) \ | ||||||
|   -DLLVM_ENABLE_PIC=ON \ |     -D CMAKE_CXX_COMPILER=$(which clang++) \ | ||||||
|   -DLIBCXX_INSTALL_MODULES=ON \ |     -D LLVM_ENABLE_PROJECTS="clang;compiler-rt" \ | ||||||
|   -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ |     -D LLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ | ||||||
|   -DLLVM_USE_SANITIZER=Leaks \ |     -D LLVM_TARGETS_TO_BUILD="X86;SPIRV" \ | ||||||
|   ../runtimes \ |     -D LLVM_ENABLE_PIC=ON \ | ||||||
| && ninja cxx cxxabi \ |     -D LIBCXX_INSTALL_MODULES=ON \ | ||||||
| && ninja install-cxx install-cxxabi \ |     -D LIBCXXABI_USE_LLVM_UNWINDER=OFF \ | ||||||
|  |     -D LLVM_USE_SANITIZER=Leaks \ | ||||||
|  |     -D LLVM_USE_LINKER="MOLD" \ | ||||||
|  | && cd ./build-lsan/ && ninja cxx cxxabi && ninja install-cxx install-cxxabi && cd ../ \ | ||||||
| \ | \ | ||||||
| && cd ../build-msan \ | && cmake \ | ||||||
| && cmake -G Ninja \ |     -S ./runtimes \ | ||||||
|   -DCMAKE_BUILD_TYPE=Release \ |     -B ./build-msan \ | ||||||
|   -DCMAKE_LINKER_TYPE="MOLD" \ |     -G Ninja \ | ||||||
|   -DCMAKE_INSTALL_PREFIX=/libcxx_msan \ |     -D CMAKE_LINKER_TYPE="MOLD" \ | ||||||
|   -DCMAKE_C_COMPILER=clang \ |     -D CMAKE_BUILD_TYPE=Release \ | ||||||
|   -DCMAKE_CXX_COMPILER=clang++ \ |     -D CMAKE_INSTALL_PREFIX=/libcxx_msan \ | ||||||
|   -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ |     -D CMAKE_C_COMPILER=$(which clang) \ | ||||||
|   -DLLVM_ENABLE_PIC=ON \ |     -D CMAKE_CXX_COMPILER=$(which clang++) \ | ||||||
|   -DLIBCXX_INSTALL_MODULES=ON \ |     -D LLVM_ENABLE_PROJECTS="clang;compiler-rt" \ | ||||||
|   -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \ |     -D LLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ | ||||||
|   -DLLVM_USE_SANITIZER=MemoryWithOrigins \ |     -D LLVM_TARGETS_TO_BUILD="X86;SPIRV" \ | ||||||
|   ../runtimes \ |     -D LLVM_ENABLE_PIC=ON \ | ||||||
| && ninja cxx cxxabi \ |     -D LIBCXX_INSTALL_MODULES=ON \ | ||||||
| && ninja install-cxx install-cxxabi \ |     -D LIBCXXABI_USE_LLVM_UNWINDER=OFF \ | ||||||
|  |     -D LLVM_USE_SANITIZER=MemoryWithOrigins \ | ||||||
|  |     -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 ../.. \ | && cmake \ | ||||||
| && rm -rf llvm-project |     -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 | set -euo pipefail | ||||||
| cd "$(git rev-parse --show-toplevel)/" | cd "$(git rev-parse --show-toplevel)/" | ||||||
| 
 | 
 | ||||||
|  | source '/1.4.328.1/setup-env.sh' | ||||||
|  | 
 | ||||||
| CC=$(which clang) | CC=$(which clang) | ||||||
| export CC | export CC | ||||||
| 
 | 
 | ||||||
|  | @ -12,6 +14,12 @@ export CXX | ||||||
| DISPLAY=:99 | DISPLAY=:99 | ||||||
| export DISPLAY | 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 & | Xvfb :99 -screen 0 1024x768x16 & | ||||||
| 
 | 
 | ||||||
| cmake \ | cmake \ | ||||||
|  | @ -26,16 +34,18 @@ cmake \ | ||||||
| -fsanitize-memory-track-origins \ | -fsanitize-memory-track-origins \ | ||||||
| -g \ | -g \ | ||||||
| -fno-omit-frame-pointer \ | -fno-omit-frame-pointer \ | ||||||
| -std=c++23 \ | -std=c++26 \ | ||||||
| -nostdinc++ \ | -nostdinc++ \ | ||||||
| -isystem /libcxx_msan/include/c++/v1/" \ | -isystem /libcxx_msan/include/c++/v1/" \ | ||||||
|     -D CMAKE_EXE_LINKER_FLAGS=" \ |     -D CMAKE_EXE_LINKER_FLAGS=" \ | ||||||
| -fsanitize=memory \ | -fsanitize=memory \ | ||||||
| -fsanitize-memory-track-origins \ | -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++ \ | ||||||
| -lc++abi \ | -lc++abi" | ||||||
| -Wl,-rpath,/libcxx_msan/lib" |  | ||||||
| 
 | 
 | ||||||
| cmake --build ./build -j"$(nproc)" | 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 CMAKE_LINKER_TYPE=MOLD \ | ||||||
|     -D ENABLE_UNIT_TESTS=ON \ |     -D ENABLE_UNIT_TESTS=ON \ | ||||||
|     -D CMAKE_BUILD_TYPE=Release \ |     -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)" | cmake --build ./build -j"$(nproc)" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ cmake \ | ||||||
|     -D CMAKE_LINKER_TYPE=MOLD \ |     -D CMAKE_LINKER_TYPE=MOLD \ | ||||||
|     -D ENABLE_UNIT_TESTS=ON \ |     -D ENABLE_UNIT_TESTS=ON \ | ||||||
|     -D CMAKE_BUILD_TYPE=Release \ |     -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)" | cmake --build ./build -j"$(nproc)" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -17,6 +17,6 @@ cmake \ | ||||||
|     -D ENABLE_UNIT_TESTS=ON \ |     -D ENABLE_UNIT_TESTS=ON \ | ||||||
|     -D ENABLE_STATIC_ANALYSIS=ON \ |     -D ENABLE_STATIC_ANALYSIS=ON \ | ||||||
|     -D CMAKE_BUILD_TYPE=Release \ |     -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)" | cmake --build . -j"$(nproc)" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue