Compare commits

...

59 commits

Author SHA1 Message Date
ccf503f44b
wip
Some checks reported errors
continuous-integration/drone/pr Build was killed
2025-10-16 11:48:17 +03:30
3a7b42445e
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-11 05:38:10 +03:30
742dcd044d
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-11 05:34:59 +03:30
5fc73f60ab
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 16:58:22 +03:30
2fd02ce929
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 16:49:09 +03:30
4475375e28
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 16:44:25 +03:30
fcbf6a277c
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 16:41:13 +03:30
d7c1567d3e
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 16:37:58 +03:30
326f7bf833
wip
Some checks reported errors
continuous-integration/drone/pr Build was killed
2025-10-10 16:37:40 +03:30
514a27a789
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 16:31:46 +03:30
46cdcb6874
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 16:21:54 +03:30
9762138730
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 15:20:13 +03:30
25bdfac834
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 15:17:55 +03:30
fa87648986
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 15:14:53 +03:30
4eecb0bef2
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 15:11:53 +03:30
a599e65bae
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 14:55:10 +03:30
6065ab1636
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 14:48:19 +03:30
baff796eb8
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 14:07:50 +03:30
ba6a4a0342
wip
Some checks reported errors
continuous-integration/drone/pr Build was killed
2025-10-10 14:07:39 +03:30
b6acc19ac8
wip
All checks were successful
continuous-integration/drone/pr Build is passing
2025-10-10 14:06:29 +03:30
197e10c0cf
wip
All checks were successful
continuous-integration/drone/pr Build is passing
2025-10-10 13:58:32 +03:30
1ab514be71
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 13:35:31 +03:30
26727a63e0
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 13:20:49 +03:30
2ffecd9aae
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 13:19:29 +03:30
79e22cec0e
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 13:18:14 +03:30
cf6eea6638
wip
All checks were successful
continuous-integration/drone/pr Build is passing
2025-10-10 13:15:23 +03:30
93eb4eb61a
wip
Some checks reported errors
continuous-integration/drone/pr Build was killed
2025-10-10 13:01:51 +03:30
7cc8bbd3e5
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 12:14:37 +03:30
c80419e2ba
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 12:10:44 +03:30
5020941711
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 12:08:51 +03:30
775211e9f3
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 11:58:26 +03:30
ddc44735d8
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 11:57:34 +03:30
897acfe149
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 11:54:18 +03:30
9597e33f3c
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 11:50:25 +03:30
6be011f75f
wip
All checks were successful
continuous-integration/drone/pr Build is passing
2025-10-10 11:48:27 +03:30
05c4757338
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 11:43:11 +03:30
39b68e7654
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 11:39:41 +03:30
2fdaabdb07
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 11:33:50 +03:30
e4dd1711b2
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 11:32:58 +03:30
6171c7ddb4
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-10 11:31:26 +03:30
ef10b77b1a
wip
All checks were successful
continuous-integration/drone/pr Build is passing
2025-10-10 11:30:47 +03:30
ec032439e1
wip
All checks were successful
continuous-integration/drone/pr Build is passing
2025-10-10 11:29:43 +03:30
4cf28095db
wip
All checks were successful
continuous-integration/drone/pr Build is passing
2025-10-10 11:27:28 +03:30
b1b9d6ce85
wip
All checks were successful
continuous-integration/drone/pr Build is passing
2025-10-10 11:25:28 +03:30
f312f68b9e
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 21:06:47 +03:30
4fea22239c
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 21:03:11 +03:30
f7c7e75185
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 21:00:41 +03:30
073c3bb60f
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 20:55:35 +03:30
136b26e918
wip
All checks were successful
continuous-integration/drone/pr Build is passing
2025-10-09 20:53:33 +03:30
b0a31d9633
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 20:47:11 +03:30
6675e4c3cb
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 20:31:13 +03:30
b17e165fd6
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 20:29:59 +03:30
b2609e4808
wip
All checks were successful
continuous-integration/drone/pr Build is passing
2025-10-09 20:25:57 +03:30
513acf0d30
wpi
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 20:23:59 +03:30
24d772c2d8
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 20:22:27 +03:30
f7f6aa20ab
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 20:18:20 +03:30
4ef760baa0
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 20:07:57 +03:30
48cb615051
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 20:05:00 +03:30
3fed6aa4f2
wip
Some checks failed
continuous-integration/drone/pr Build is failing
2025-10-09 19:53:18 +03:30
16 changed files with 607 additions and 341 deletions

View file

@ -1,42 +1,42 @@
---
kind: pipeline
type: exec
name: amd64 — msvc
trigger:
branch:
- main
platform:
os: windows
arch: amd64
steps:
- name: unit tests
shell: powershell
commands:
- ./tools/ci/amd64/msvc/unit_tests.ps1
---
kind: pipeline
type: docker
name: amd64 — gcc
trigger:
branch:
- main
steps:
- name: unit tests
image: ci:latest
pull: if-not-exists
commands:
- ./tools/ci/amd64/gcc/unit_tests.sh
- name: valgrind
image: ci:latest
pull: if-not-exists
commands:
- ./tools/ci/amd64/gcc/valgrind.sh
---
# ---
# kind: pipeline
# type: exec
# name: amd64 — msvc
# trigger:
# branch:
# - main
# platform:
# os: windows
# arch: amd64
#
# steps:
# - name: unit tests
# shell: powershell
# commands:
# - ./tools/ci/amd64/msvc/unit_tests.ps1
#
# ---
# kind: pipeline
# type: docker
# name: amd64 — gcc
# trigger:
# branch:
# - main
#
# steps:
# - name: unit tests
# image: ci:latest
# pull: if-not-exists
# commands:
# - ./tools/ci/amd64/gcc/unit_tests.sh
#
# - name: valgrind
# image: ci:latest
# pull: if-not-exists
# commands:
# - ./tools/ci/amd64/gcc/valgrind.sh
#
# ---
kind: pipeline
type: docker
name: amd64 — clang
@ -45,95 +45,95 @@ trigger:
- main
steps:
- name: code coverage
image: ci:latest
pull: if-not-exists
environment:
CODECOV_TOKEN:
from_secret: CODECOV_TOKEN
commands:
- ./tools/ci/amd64/clang/coverage.sh
- name: leak sanitizer
image: ci:latest
pull: if-not-exists
commands:
- ./tools/ci/amd64/clang/lsan.sh
# - name: code coverage
# image: ci:latest
# pull: if-not-exists
# environment:
# CODECOV_TOKEN:
# from_secret: CODECOV_TOKEN
# commands:
# - ./tools/ci/amd64/clang/coverage.sh
#
# - name: leak sanitizer
# image: ci:latest
# pull: if-not-exists
# commands:
# - ./tools/ci/amd64/clang/lsan.sh
#
- name: memory sanitizer
image: ci:latest
pull: if-not-exists
commands:
- ./tools/ci/amd64/clang/msan.sh
---
kind: pipeline
type: docker
name: static analysis
trigger:
branch:
- main
steps:
- name: clang tidy
image: ci:latest
pull: if-not-exists
privileged: true
commands:
- ./tools/ci/static_analysis/clang_tidy.sh
- name: clang format
image: ci:latest
pull: if-not-exists
commands:
- ./tools/ci/static_analysis/clang_format.sh
---
kind: pipeline
type: docker
name: documentation — development
node:
environment: ryali
trigger:
branch:
- main
steps:
- name: build and deploy
image: documentation:latest
pull: if-not-exists
commands:
- pwd
- cd docs
- mkdir generated
- touch generated/changelogs.rst
- touch generated/api.rst
- sphinx-build -M html . .
- rm -rf /light_docs_dev/*
- mv ./html/* /light_docs_dev/
---
kind: pipeline
type: docker
name: documentation — production
node:
environment: ryali
trigger:
event:
- tag
steps:
- name: build and deploy
image: documentation:latest
pull: if-not-exists
commands:
- cd docs
- mkdir generated
- touch generated/changelogs.rst
- touch generated/api.rst
- sphinx-build -M html . .
- rm -rf /light_docs/*
- mv ./html/* /light_docs/
#
# ---
# kind: pipeline
# type: docker
# name: static analysis
# trigger:
# branch:
# - main
#
# steps:
# - name: clang tidy
# image: ci:latest
# pull: if-not-exists
# privileged: true
# commands:
# - ./tools/ci/static_analysis/clang_tidy.sh
#
# - name: clang format
# image: ci:latest
# pull: if-not-exists
# commands:
# - ./tools/ci/static_analysis/clang_format.sh
#
# ---
# kind: pipeline
# type: docker
# name: documentation — development
# node:
# environment: ryali
# trigger:
# branch:
# - main
#
# steps:
# - name: build and deploy
# image: documentation:latest
# pull: if-not-exists
# commands:
# - pwd
# - cd docs
# - mkdir generated
# - touch generated/changelogs.rst
# - touch generated/api.rst
# - sphinx-build -M html . .
#
# - rm -rf /light_docs_dev/*
# - mv ./html/* /light_docs_dev/
#
# ---
#
# kind: pipeline
# type: docker
# name: documentation — production
# node:
# environment: ryali
# trigger:
# event:
# - tag
#
# steps:
# - name: build and deploy
# image: documentation:latest
# pull: if-not-exists
# commands:
# - cd docs
# - mkdir generated
# - touch generated/changelogs.rst
# - touch generated/api.rst
# - sphinx-build -M html . .
#
# - rm -rf /light_docs/*
# - mv ./html/* /light_docs/

View file

@ -2,18 +2,25 @@
namespace lt::assets {
constexpr auto total_metadata_size = //
sizeof(AssetMetadata::type) //
+ sizeof(AssetMetadata::version) //
+ sizeof(ShaderAsset::Metadata::type) //
+ sizeof(BlobMetadata::tag) //
+ sizeof(BlobMetadata::offset) //
+ sizeof(BlobMetadata::compression_type) //
+ sizeof(BlobMetadata::compressed_size) //
+ sizeof(BlobMetadata::uncompressed_size);
ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
{
constexpr auto total_metadata_size = //
sizeof(AssetMetadata) //
+ sizeof(Metadata) //
+ sizeof(BlobMetadata);
ensure(m_stream.is_open(), "Failed to open shader asset at: {}", path.string());
const auto read = [this](auto &field) {
m_stream.read(std::bit_cast<char *>(&field), sizeof(field));
};
m_stream.seekg(0, std::ifstream::end);
const auto file_size = static_cast<size_t>(m_stream.tellg());
ensure(
file_size > total_metadata_size,
"Failed to open shader asset at: {}, file smaller than metadata: {} < {}",
@ -22,12 +29,15 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
file_size
);
// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
m_stream.seekg(0, std::ifstream::beg);
m_stream.read((char *)&m_asset_metadata, sizeof(m_asset_metadata));
m_stream.read((char *)&m_metadata, sizeof(m_metadata));
m_stream.read((char *)&m_code_blob_metadata, sizeof(m_code_blob_metadata));
// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
read(m_asset_metadata.type);
read(m_asset_metadata.version);
read(m_metadata.type);
read(m_code_blob_metadata.tag);
read(m_code_blob_metadata.offset);
read(m_code_blob_metadata.compression_type);
read(m_code_blob_metadata.compressed_size);
read(m_code_blob_metadata.uncompressed_size);
ensure(
m_asset_metadata.type == asset_type_identifier,
@ -69,4 +79,70 @@ ShaderAsset::ShaderAsset(const std::filesystem::path &path): m_stream(path)
);
}
/* static */ void ShaderAsset::pack(
const std::filesystem::path &destination,
AssetMetadata asset_metadata,
Metadata metadata,
Blob code_blob
)
{
auto stream = std::ofstream {
destination,
std::ios::binary | std::ios::trunc,
};
const auto code_blob_metadata = BlobMetadata {
.tag = std::to_underlying(BlobTag::code),
.offset = total_metadata_size,
.compression_type = CompressionType::none,
.compressed_size = code_blob.size(),
.uncompressed_size = code_blob.size(),
};
ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string());
const auto write = [&stream](auto &field) {
stream.write(std::bit_cast<char *>(&field), sizeof(field));
};
write(asset_metadata.type);
write(asset_metadata.version);
write(metadata.type);
write(code_blob_metadata.tag);
write(code_blob_metadata.offset);
write(code_blob_metadata.compression_type);
write(code_blob_metadata.compressed_size);
write(code_blob_metadata.uncompressed_size);
stream.write(std::bit_cast<char *>(code_blob.data()), static_cast<long long>(code_blob.size()));
}
void ShaderAsset::unpack_to(BlobTag tag, std::span<std::byte> destination) const
{
ensure(tag == BlobTag::code, "Invalid blob tag for shader asset: {}", std::to_underlying(tag));
ensure(
destination.size() >= m_code_blob_metadata.uncompressed_size,
"Failed to unpack shader blob {} to destination ({}) of size {} since it's smaller "
"than the blobl's uncompressed size: {}",
std::to_underlying(tag),
std::bit_cast<size_t>(destination.data()),
destination.size(),
m_code_blob_metadata.uncompressed_size
);
m_stream.seekg(static_cast<long long>(m_code_blob_metadata.offset));
m_stream.read(
std::bit_cast<char *>(destination.data()),
static_cast<long long>(m_code_blob_metadata.uncompressed_size)
);
}
[[nodiscard]] auto ShaderAsset::unpack(BlobTag tag) const -> Blob
{
ensure(tag == BlobTag::code, "Invalid blob tag for shader asset: {}", std::to_underlying(tag));
auto blob = Blob(m_code_blob_metadata.uncompressed_size);
unpack_to(tag, blob);
return blob;
}
} // namespace lt::assets

View file

@ -40,10 +40,15 @@ Suite packing = "shader_pack"_suite = [] {
dummy_blob.emplace_back(static_cast<std::byte>(idx));
}
const auto expected_size = //
sizeof(AssetMetadata) //
+ sizeof(ShaderAsset::Metadata) //
+ sizeof(BlobMetadata) //
const auto expected_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) //
+ dummy_blob.size();
ShaderAsset::pack(

View file

@ -32,33 +32,14 @@ public:
AssetMetadata asset_metadata,
Metadata metadata,
Blob code_blob
)
{
auto stream = std::ofstream {
destination,
std::ios::binary | std::ios::trunc,
};
ensure(stream.is_open(), "Failed to pack shader asset to {}", destination.string());
// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
stream.write((char *)&asset_metadata, sizeof(asset_metadata));
stream.write((char *)&metadata, sizeof(metadata));
auto code_blob_metadata = BlobMetadata {
.tag = std::to_underlying(BlobTag::code),
.offset = static_cast<size_t>(stream.tellp()) + sizeof(BlobMetadata),
.compression_type = CompressionType::none,
.compressed_size = code_blob.size(),
.uncompressed_size = code_blob.size(),
};
stream.write((char *)&code_blob_metadata, sizeof(BlobMetadata));
stream.write((char *)code_blob.data(), static_cast<long long>(code_blob.size()));
// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast)
}
);
ShaderAsset(const std::filesystem::path &path);
void unpack_to(BlobTag tag, std::span<std::byte> destination) const;
[[nodiscard]] auto unpack(BlobTag tag) const -> Blob;
[[nodiscard]] auto get_asset_metadata() const -> const AssetMetadata &
{
return m_asset_metadata;
@ -80,45 +61,6 @@ public:
return m_code_blob_metadata;
}
void unpack_to(BlobTag tag, std::span<std::byte> destination) const
{
ensure(
tag == BlobTag::code,
"Invalid blob tag for shader asset: {}",
std::to_underlying(tag)
);
ensure(
destination.size() >= m_code_blob_metadata.uncompressed_size,
"Failed to unpack shader blob {} to destination ({}) of size {} since it's smaller "
"than the blobl's uncompressed size: {}",
std::to_underlying(tag),
(size_t)(destination.data()), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast)
destination.size(),
m_code_blob_metadata.uncompressed_size
);
m_stream.seekg(static_cast<long long>(m_code_blob_metadata.offset));
m_stream.read(
(char *)destination.data(), // NOLINT(cppcoreguidelines-pro-type-cstyle-cast)
static_cast<long long>(m_code_blob_metadata.uncompressed_size)
);
}
[[nodiscard]] auto unpack(BlobTag tag) const -> Blob
{
ensure(
tag == BlobTag::code,
"Invalid blob tag for shader asset: {}",
std::to_underlying(tag)
);
auto blob = Blob(m_code_blob_metadata.uncompressed_size);
unpack_to(tag, blob);
return blob;
}
private:
AssetMetadata m_asset_metadata {};

View file

@ -112,7 +112,7 @@ Instance::~Instance()
unload_library();
}
void Instance::initialize_instance()
__attribute__((no_sanitize("memory"))) void Instance::initialize_instance()
{
auto app_info = VkApplicationInfo {
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
@ -217,6 +217,7 @@ void Instance::initialize_instance()
vkc(vk_enumerate_instance_extension_properties(nullptr, &count, nullptr));
auto extensions = std::vector<VkExtensionProperties>(count);
memset(extensions.data(), 0, extensions.size() * sizeof(VkExtensionProperties));
vkc(vk_enumerate_instance_extension_properties(nullptr, &count, extensions.data()));
// log_inf("Available vulkan instance extensions:");
@ -230,9 +231,9 @@ void Instance::initialize_instance()
ensure(m_instance, "Failed to create vulkan instance");
}
void Instance::load_library()
__attribute__((no_sanitize("memory"))) void Instance::load_library()
{
constexpr auto runtime_loader_flags = RTLD_NOW | RTLD_DEEPBIND | RTLD_LOCAL | RTLD_NODELETE;
constexpr auto runtime_loader_flags = RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE;
library = dlopen("libvulkan.so.1", runtime_loader_flags);
if (!library)
{
@ -247,7 +248,7 @@ void Instance::load_library()
ensure(vk_get_instance_proc_address, "Failed to load vulkan function: vkGetInstanceProcAddr");
}
void Instance::unload_library()
__attribute__((no_sanitize("memory"))) void Instance::unload_library()
{
if (!library)
{
@ -262,7 +263,7 @@ void Instance::unload_library()
// library = nullptr;
}
void Instance::load_global_functions()
__attribute__((no_sanitize("memory"))) void Instance::load_global_functions()
{
constexpr auto load_fn = []<typename T>(T &pfn, const char *fn_name) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
@ -276,7 +277,7 @@ void Instance::load_global_functions()
load_fn(vk_enumerate_instance_layer_properties, "vkEnumerateInstanceLayerProperties");
}
void Instance::load_instance_functions()
__attribute__((no_sanitize("memory"))) void Instance::load_instance_functions()
{
const auto load_fn = [&]<typename T>(T &pfn, const char *fn_name) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
@ -320,7 +321,7 @@ void Instance::load_instance_functions()
load_fn(vk_destroy_surface_khr, "vkDestroySurfaceKHR");
}
void Instance::load_device_functions_impl(VkDevice device)
__attribute__((no_sanitize("memory"))) void Instance::load_device_functions_impl(VkDevice device)
{
const auto load_fn = [&]<typename T>(T &pfn, const char *fn_name) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)

View file

@ -64,17 +64,17 @@ private:
Instance();
void initialize_instance();
__attribute__((no_sanitize("memory"))) void initialize_instance();
void load_library();
__attribute__((no_sanitize("memory"))) void load_library();
void unload_library();
__attribute__((no_sanitize("memory"))) void unload_library();
void load_global_functions();
__attribute__((no_sanitize("memory"))) void load_global_functions();
void load_instance_functions();
__attribute__((no_sanitize("memory"))) void load_instance_functions();
void load_device_functions_impl(VkDevice device);
__attribute__((no_sanitize("memory"))) void load_device_functions_impl(VkDevice device);
VkInstance m_instance = VK_NULL_HANDLE;

View file

@ -10,15 +10,16 @@ Pass::Pass(
const lt::assets::ShaderAsset &vertex_shader,
const lt::assets::ShaderAsset &fragment_shader
)
: m_device(static_cast<Device *>(device)), m_layout(m_device->create_pipeline_layout(
VkPipelineLayoutCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 0u,
.pSetLayouts = nullptr,
.pushConstantRangeCount = 0u,
.pPushConstantRanges = nullptr,
}
))
: m_device(static_cast<Device *>(device))
, m_layout(m_device->create_pipeline_layout(
VkPipelineLayoutCreateInfo {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 0u,
.pSetLayouts = nullptr,
.pushConstantRangeCount = 0u,
.pPushConstantRanges = nullptr,
}
))
{
auto *vertex_module = create_module(
vertex_shader.unpack(lt::assets::ShaderAsset::BlobTag::code)
@ -112,7 +113,6 @@ Pass::Pass(
};
auto attachment_description = VkAttachmentDescription {
.format = static_cast<Swapchain *>(swapchain)->get_format(),
.samples = VK_SAMPLE_COUNT_1_BIT,

View file

@ -46,8 +46,7 @@ System::System(CreateInfo info)
) };
}
System::~System()
= default;
System::~System() = default;
void System::on_register()
{

View file

@ -11,14 +11,19 @@
#include <X11/keysym.h>
#include <X11/keysymdef.h>
//
#include <sanitizer/msan_interface.h>
namespace lt::surface {
template<int EventType>
int XEventTypeEquals(Display *, XEvent *event, XPointer winptr)
auto XEventTypeEquals(Display *display, XEvent *event, char *winptr) -> int
{
std::ignore = display;
return (
event->type == EventType
&& *(reinterpret_cast<Window *>(winptr)) == reinterpret_cast<XAnyEvent *>(event)->window
&& *(std::bit_cast<const Window *>(winptr))
== std::bit_cast<const XAnyEvent *>(event)->window
);
}
@ -100,7 +105,10 @@ void System::on_unregister()
{
}
void System::create_surface_component(ecs::EntityId entity, SurfaceComponent::CreateInfo info)
__attribute__((no_sanitize_memory)) void System::create_surface_component(
ecs::EntityId entity,
SurfaceComponent::CreateInfo info
)
try
{
auto &component = m_registry->add<SurfaceComponent>(entity, info);
@ -160,9 +168,14 @@ try
XSetWMProtocols(display, main_window, &surface.m_native_data.wm_delete_message, 1);
// code to remove decoration
auto hints = std::array<unsigned char, 5> { 2, 0, 0, 0, 0 };
auto hints = std::array<const unsigned char, 5> { 2, 0, 0, 0, 0 };
const auto motif_hints = XInternAtom(display, "_MOTIF_WM_HINTS", False);
#if defined(__clang__) && __has_feature(memory_sanitizer)
auto bytes = (size_t)(1u) * (size_t)hints.size();
__msan_unpoison((void *)hints.data(), bytes);
#endif
XChangeProperty(
display,
surface.m_native_data.window,
@ -331,7 +344,10 @@ void System::modify_title(SurfaceComponent &surface, const ModifyTitleRequest &r
XStoreName(display, window, request.title.c_str());
}
void System::modify_resolution(SurfaceComponent &surface, const ModifyResolutionRequest &request)
__attribute__((no_sanitize("memory"))) void System::modify_resolution(
SurfaceComponent &surface,
const ModifyResolutionRequest &request
)
{
// surface.m_resolution = request.resolution;
@ -340,7 +356,7 @@ void System::modify_resolution(SurfaceComponent &surface, const ModifyResolution
// XResizeWindow(display, window, width, height);
// get baseline serial number for X requests generated from XResizeWindow
uint64_t serial = NextRequest(display);
auto serial = NextRequest(display);
// request a new window size from the X server
XResizeWindow(display, window, static_cast<uint32_t>(width), static_cast<uint32_t>(height));
@ -396,7 +412,7 @@ void System::modify_position(SurfaceComponent &surface, const ModifyPositionRequ
const auto &[x, y] = request.position;
// get baseline serial number for X requests generated from XResizeWindow
uint64_t serial = NextRequest(display);
auto serial = NextRequest(display);
XMoveWindow(display, window, static_cast<int>(x), static_cast<int>(y));
// flush output queue and wait for X server to processes the request

View file

@ -16,7 +16,6 @@ using test::expect_eq;
using test::expect_ne;
using test::expect_not_nullptr;
using test::expect_throw;
using test::expect_true;
using test::Suite;
[[nodiscard]] auto tick_info() -> app::TickInfo

View file

@ -4,10 +4,7 @@
namespace lt::surface {
System::System(
memory::Ref<ecs::Registry> registry,
memory::Ref<app::EventMediator> event_mediator
)
System::System(memory::Ref<ecs::Registry> registry, memory::Ref<app::EventMediator> event_mediator)
: m_registry(std::move(registry))
, m_event_mediator(std::move(event_mediator))
{

View file

@ -27,7 +27,10 @@ public:
void on_unregister() override;
void create_surface_component(ecs::EntityId entity, SurfaceComponent::CreateInfo info);
__attribute__((no_sanitize("memory"))) void create_surface_component(
ecs::EntityId entity,
SurfaceComponent::CreateInfo info
);
void tick(app::TickInfo tick) override;
@ -45,12 +48,12 @@ private:
void modify_title(struct SurfaceComponent &surface, const struct ModifyTitleRequest &request);
void modify_resolution(
__attribute__((no_sanitize("memory"))) void modify_resolution(
struct SurfaceComponent &surface,
const struct ModifyResolutionRequest &request
);
void modify_position(
__attribute__((no_sanitize("memory"))) void modify_position(
struct SurfaceComponent &surface,
const struct ModifyPositionRequest &request
);

View file

@ -1,99 +1,301 @@
FROM archlinux:latest
## Configurations ##
RUN \
mkdir /msan \
&& echo 'src:*' > /msan/ignorelist_all_sources \
&& sed -i 's/^#ParallelDownloads = .*/ParallelDownloads = 8/' /etc/pacman.conf \
&& echo 'NoExtract = usr/share/{man,doc,info}/*' >> /etc/pacman.conf
## Packages ##
RUN \
sed -i 's/^#ParallelDownloads = .*/ParallelDownloads = 8/' /etc/pacman.conf \
&& echo 'NoExtract = usr/share/{man,doc,info}/*' >> /etc/pacman.conf \
&& pacman -Syyu --noconfirm --needed --disable-download-timeout \
afl++ \
afl-utils \
base-devel \
bash \
clang \
cmake \
curl \
expat \
gcc \
gdb \
git \
glm \
libc++ \
libinput \
libpciaccess \
libpng \
libunwind \
libx11 \
libxcb \
libxcursor \
libxi \
libxinerama \
libxpresent \
libxrandr \
lz4 \
mesa \
mold \
ninja \
python \
python-distlib \
python-distutils-extra \
python-jsonschema \
qt5-base \
qt6-base \
valgrind \
vulkan-headers \
vulkan-icd-loader \
vulkan-tools \
vulkan-validation-layers \
wayland \
wayland-protocols \
wget \
xcb-util \
xcb-util-cursor \
xcb-util-keysyms \
xcb-util-wm \
xorg-server-xvfb \
xorg-util-macros \
xtrans \
zlib \
zstd \
pacman -Syyu --noconfirm --needed --disable-download-timeout \
afl++ \
afl-utils \
base-devel \
bash \
cbindgen \
clang \
cmake \
curl \
debuginfod \
directx-headers \
elfutils \
expat \
gcc \
gcc-libs \
gdb \
git \
glibc \
glm \
glslang \
libc++ \
libclc \
libdrm \
libelf \
libglvnd \
libinput \
libpciaccess \
libpng \
libunwind \
libva \
libx11 \
libxcb \
libxdamage \
libxext \
libxfixes \
libxi \
libxinerama \
libxml2 \
libxpresent \
libxrandr \
libxshmfence \
libxxf86vm \
lm_sensors \
llvm \
lz4 \
meson \
mold \
ninja \
python \
python-distlib \
python-distutils-extra \
python-jsonschema \
python-mako \
python-packaging \
python-ply \
python-pyaml \
qt5-base \
qt6-base \
rust \
rust-bindgen \
spirv-llvm-translator \
spirv-tools \
systemd-libs \
valgrind \
vulkan-headers \
vulkan-icd-loader \
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
## Sanitizers ##
## Libc++ ##
RUN \
git clone --depth=1 https://github.com/llvm/llvm-project.git -b llvmorg-20.1.8 \
&& mkdir llvm-project/build-lsan llvm-project/build-msan \
git clone \
--branch llvmorg-20.1.8 \
--depth=1 \
https://github.com/llvm/llvm-project.git
RUN cd llvm-project/ \
\
&& cd llvm-project/build-lsan \
&& cmake -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_LINKER_TYPE="MOLD" \
-DCMAKE_INSTALL_PREFIX=/libcxx_lsan \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \
-DLLVM_ENABLE_PIC=ON \
-DLIBCXX_INSTALL_MODULES=ON \
-DLIBCXXABI_USE_LLVM_UNWINDER=OFF \
-DLLVM_USE_SANITIZER=Leaks \
../runtimes \
&& ninja cxx cxxabi \
&& ninja install-cxx install-cxxabi \
&& cmake \
-S ./runtimes \
-B ./build-lsan \
-G Ninja \
-D CMAKE_LINKER_TYPE="MOLD" \
-D CMAKE_BUILD_TYPE=Release \
-D CMAKE_INSTALL_PREFIX=/libcxx_lsan \
-D CMAKE_C_COMPILER=$(which clang) \
-D CMAKE_CXX_COMPILER=$(which clang++) \
-D LLVM_ENABLE_PROJECTS="clang;compiler-rt" \
-D LLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \
-D LLVM_TARGETS_TO_BUILD="X86;SPIRV" \
-D LLVM_ENABLE_PIC=ON \
-D LIBCXX_INSTALL_MODULES=ON \
-D LIBCXXABI_USE_LLVM_UNWINDER=OFF \
-D LLVM_USE_SANITIZER=Leaks \
&& cd ./build-lsan/ && ninja cxx cxxabi && ninja install-cxx install-cxxabi && cd ../ \
\
&& cd ../build-msan \
&& cmake -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_LINKER_TYPE="MOLD" \
-DCMAKE_INSTALL_PREFIX=/libcxx_msan \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \
-DLLVM_ENABLE_PIC=ON \
-DLIBCXX_INSTALL_MODULES=ON \
-DLIBCXXABI_USE_LLVM_UNWINDER=OFF \
-DLLVM_USE_SANITIZER=MemoryWithOrigins \
../runtimes \
&& ninja cxx cxxabi \
&& ninja install-cxx install-cxxabi \
\
&& cd ../.. \
&& rm -rf llvm-project
&& cmake \
-S ./runtimes \
-B ./build-msan \
-G Ninja \
-D CMAKE_LINKER_TYPE="MOLD" \
-D CMAKE_BUILD_TYPE=Release \
-D CMAKE_INSTALL_PREFIX=/libcxx_msan \
-D CMAKE_C_COMPILER=$(which clang) \
-D CMAKE_CXX_COMPILER=$(which clang++) \
-D LLVM_ENABLE_PROJECTS="clang;compiler-rt" \
-D LLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \
-D LLVM_TARGETS_TO_BUILD="X86;SPIRV" \
-D LLVM_ENABLE_PIC=ON \
-D LIBCXX_INSTALL_MODULES=ON \
-D LIBCXXABI_USE_LLVM_UNWINDER=OFF \
-D LLVM_USE_SANITIZER=MemoryWithOrigins \
&& cd ./build-msan/ && ninja cxx cxxabi && ninja install-cxx install-cxxabi && cd ../
## libxcb ##
RUN \
wget https://x.org/releases/individual/lib/libxcb-1.17.0.tar.xz \
&& 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 \
wget https://x.org/releases/individual/lib/libX11-1.8.12.tar.xz \
&& 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
RUN wget 'https://sdk.lunarg.com/sdk/download/1.4.328.1/linux/vulkansdk-linux-x86_64-1.4.328.1.tar.xz'
RUN tar xf vulkansdk-linux-x86_64-1.4.328.1.tar.xz
## Vulkan SDK ##
RUN \
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++23 \
-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++23 \
-L/msan/lib -Wl,-rpath,/msan/lib \
-L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib \
-lc++ \
-lc++abi" \
&& ./vulkansdk \
--debug \
--numjobs `nproc` \
vulkan-loader
## Mesa ##
RUN git clone \
--branch='25.2'\
--depth=1 \
https://gitlab.freedesktop.org/mesa/mesa.git
RUN \
export CXX=$(which clang++) \
&& export CC=$(which clang) \
&& export CXXFLAGS="\
-fsanitize=memory \
-fsanitize-memory-track-origins \
-fno-omit-frame-pointer \
-g \
-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 \
-g \
-L/msan/lib -Wl,-rpath,/msan/lib \
-L/libcxx_msan/lib -Wl,-rpath,/libcxx_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

View file

@ -17,9 +17,9 @@ cmake . \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS=" \
-fsanitize=leak \
-fno-omit-frame-pointer \
-fno-common \
-g \
-fno-omit-frame-pointer \
-std=c++23 \
-nostdinc++ \
-isystem /libcxx_lsan/include/c++/v1/" \
@ -29,7 +29,7 @@ cmake . \
-lc++ \
-lc++abi \
-Wl,-rpath,/libcxx_lsan/lib" \
&& cmake --build ./build --target='renderer_tests' -j`nproc`
&& cmake --build ./build -j`nproc`
export LSAN_OPTIONS="suppressions=$(git rev-parse --show-toplevel)/tools/ci/amd64/clang/lsan.supp:fast_unwind_on_malloc=0:verbosity=1:report_objects=1"
export LSAN_SYMBOLIZER_PATH="$(which llvm-symbolizer)"

View file

@ -9,29 +9,52 @@ export CXX=$(which clang++)
export CC=$(which clang)
export DISPLAY=:99
export PKG_CONFIG_PATH=/msan/lib/pkgconfig:${PKG_CONFIG_PATH}
source '/1.4.328.1/setup-env.sh'
echo "REVPARSE: $(git rev-parse --show-toplevel)"
cat "$(git rev-parse --show-toplevel)/tools/ci/amd64/clang/msan.supp"
cmake . \
-Bbuild \
-GNinja \
-DCMAKE_INCLUDE_PATH=/msan/include \
-DCMAKE_LIBRARY_PATH=/msan/lib \
-DCMAKE_PREFIX_PATH=/msan \
-DCMAKE_LINKER_TYPE=MOLD \
-DENABLE_UNIT_TESTS=ON \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_FLAGS=" \
-fsanitize=memory \
-fsanitize-memory-track-origins \
-fsanitize-ignorelist=$(git rev-parse --show-toplevel)/tools/ci/amd64/clang/msan.supp \
-fno-omit-frame-pointer \
-g" \
-DCMAKE_CXX_FLAGS=" \
-fsanitize=memory \
-fsanitize-memory-track-origins \
-g \
-fsanitize-ignorelist=$(git rev-parse --show-toplevel)/tools/ci/amd64/clang/msan.supp \
-fno-omit-frame-pointer \
-g \
-std=c++23 \
-nostdinc++ \
-isystem /libcxx_msan/include/c++/v1/" \
-DCMAKE_EXE_LINKER_FLAGS=" \
-fsanitize=memory \
-fsanitize-memory-track-origins \
-L/libcxx_msan/lib \
-fsanitize-ignorelist=$(git rev-parse --show-toplevel)/tools/ci/amd64/clang/msan.supp \
-g \
-std=c++23 \
-L/msan/lib -Wl,-rpath,/msan/lib \
-L/libcxx_msan/lib -Wl,-rpath,/libcxx_msan/lib \
-lc++ \
-lc++abi \
-Wl,-rpath,/libcxx_msan/lib" \
&& cmake --build ./build -j`nproc`
-lc++abi" \
&& cmake --build ./build --target='renderer_tests' -j`nproc`
export MSAN_SYMBOLIZER_PATH="$(which llvm-symbolizer)"
export MSAN_OPTIONS="suppressions=$(git rev-parse --show-toplevel)/tools/ci/amd64/clang/msan.supp:fast_unwind_on_malloc=0:verbosity=1:report_umrs=1"
for test in $(find ./build -type f -name '*_tests' -executable); do
echo "Running $test"
"$test"

View file

@ -0,0 +1,3 @@
src:*
obj:*
fun:*