use cbindgen for FFI #3

Open
noteuclid wants to merge 5 commits from cbindgen into master
14 changed files with 95 additions and 79 deletions

9
.clang-format Normal file
View File

@ -0,0 +1,9 @@
BasedOnStyle: LLVM
UseTab: Always
TabWidth: 4
IndentWidth: 4
AccessModifierOffset: -4
IndentCaseLabels: false
ColumnLimit: 0
PointerAlignment: Left
PackConstructorInitializers: Never

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.18) cmake_minimum_required(VERSION 4.2)
project(PROJECT-NAME VERSION 1.0.0 LANGUAGES CXX) project(PROJECT-NAME VERSION 1.0.0 LANGUAGES CXX)
@ -9,10 +9,7 @@ find_package(Qt6 REQUIRED COMPONENTS Gui Widgets)
find_program(CARGO cargo REQUIRED) find_program(CARGO cargo REQUIRED)
set(CARGO_TARGET_DIR "${CMAKE_BINARY_DIR}/cargo") set(CARGO_TARGET_DIR "${CMAKE_BINARY_DIR}/cargo")
# KDE-specific include(cbindgen.cmake)
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
find_package(KF6 REQUIRED COMPONENTS WidgetsAddons)
qt_standard_project_setup() qt_standard_project_setup()

13
cbindgen.cmake Normal file
View File

@ -0,0 +1,13 @@
option(LOCAL_CBINDGEN "Download and build `cbindgen` even if one can be found on the system")
if(NOT LOCAL_CBINDGEN)
find_program(CBINDGEN cbindgen)
endif()
if(NOT CBINDGEN)
message(CONFIGURE_LOG "cbindgen not found, downloading...")
set(crates "${CMAKE_BINARY_DIR}/crates")
file(MAKE_DIRECTORY ${crates})
execute_process(COMMAND ${CARGO} install --root ${crates} cbindgen@0.29.4)
set(CACHE{CBINDGEN} TYPE FILEPATH FORCE VALUE "${crates}/bin/cbindgen")
endif()

11
format.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
find src/ ui/ \
\( \
-name '*.cxx' -o \
-name '*.hxx' -o \
-name '*.c' -o \
-name '*.h' \
\) \
-print \
-exec 'clang-format' '-i' '{}' \;

View File

@ -9,11 +9,11 @@ pub(crate) fn rotation(yaw: f32, pitch: f32) -> Mat3 {
} }
pub(crate) fn view(yaw: f32, pitch: f32, distance: f32) -> Affine3A { pub(crate) fn view(yaw: f32, pitch: f32, distance: f32) -> Affine3A {
Affine3A::from_mat3_translation(rotation(yaw, pitch), vec3(0., 0., distance)) Affine3A::from_mat3_translation(rotation(-yaw, -pitch), vec3(0., 0., -distance))
} }
pub(crate) fn projection(fovy: f32, aspect: f32) -> Mat4 { pub(crate) fn projection(fovy: f32, aspect: f32) -> Mat4 {
Mat4::perspective_lh(fovy, aspect, 0.1, 10.0) Mat4::perspective_rh(fovy, aspect, 0.1, 10.0)
} }
#[cfg(test)] #[cfg(test)]

View File

@ -5,10 +5,11 @@ use glam::{Mat4, UVec2, Vec3, Vec4, vec3, vec4};
mod camera; mod camera;
mod render; mod render;
const BACKGROUND: Vec4 = vec4(0.00, 0.39, 0.52, 1.00);
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(C)] #[repr(C)]
pub struct RedrawArgs { pub struct RedrawArgs {
pub background: Vec4,
pub cam_yaw: f32, pub cam_yaw: f32,
pub cam_pitch: f32, pub cam_pitch: f32,
pub cam_distance: f32, pub cam_distance: f32,
@ -18,8 +19,7 @@ pub struct RedrawArgs {
impl Default for RedrawArgs { impl Default for RedrawArgs {
fn default() -> Self { fn default() -> Self {
Self { Self {
background: vec4(0.25, 0.49, 0.93, 1.00), cam_yaw: 3. * std::f32::consts::FRAC_PI_4,
cam_yaw: std::f32::consts::FRAC_PI_4,
cam_pitch: std::f32::consts::FRAC_PI_6, cam_pitch: std::f32::consts::FRAC_PI_6,
cam_distance: 3., cam_distance: 3.,
cam_fovy: std::f32::consts::FRAC_PI_2, cam_fovy: std::f32::consts::FRAC_PI_2,
@ -56,7 +56,7 @@ fn cube(a: f32, b: f32) -> render::mesh::CpuMeshIndexed {
] { ] {
for m in [1., -1.] { for m in [1., -1.] {
let base = mesh.vertices.len() as u16; let base = mesh.vertices.len() as u16;
for offset in [m * v + u, -m * v + u, -m * v - u, m * v - u] { for offset in [m * v + u, m * v - u, -m * v - u, -m * v + u] {
let vertex = render::mesh::Vertex { let vertex = render::mesh::Vertex {
position: (m * w + offset), position: (m * w + offset),
color: gray + color_level * m * w, color: gray + color_level * m * w,
@ -158,7 +158,7 @@ impl Core {
depth_slice: None, depth_slice: None,
resolve_target: None, resolve_target: None,
ops: wgpu::Operations { ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(color_to_wgpu(srgba_to_linear(args.background))), load: wgpu::LoadOp::Clear(color_to_wgpu(srgba_to_linear(BACKGROUND))),
store: wgpu::StoreOp::Store, store: wgpu::StoreOp::Store,
}, },
})], })],

View File

@ -9,6 +9,5 @@ qt_add_executable(PROJECT-NAME
) )
target_link_libraries(PROJECT-NAME PRIVATE Qt6::Gui Qt6::Widgets) target_link_libraries(PROJECT-NAME PRIVATE Qt6::Gui Qt6::Widgets)
target_link_libraries(PROJECT-NAME PRIVATE KF6::WidgetsAddons)
target_link_libraries(PROJECT-NAME PRIVATE PROJECT_NAME_impl) target_link_libraries(PROJECT-NAME PRIVATE PROJECT_NAME_impl)
target_include_directories(PROJECT-NAME PRIVATE src) target_include_directories(PROJECT-NAME PRIVATE src)

14
ui/cbindgen.toml Normal file
View File

@ -0,0 +1,14 @@
includes = ["types.hxx"]
sys_includes = ["cstdint"]
pragma_once = true
no_includes = true
namespace = "ffi"
tab_width = 4
language = "C++"
[parse]
parse_deps = true
include = ["PROJECT-NAME"]
[export]
exclude = ["Box"]

View File

@ -1,3 +1,4 @@
# build the Rust side as a static library
set(impl_basename "${CARGO_TARGET_DIR}/release/libPROJECT_NAME_impl") set(impl_basename "${CARGO_TARGET_DIR}/release/libPROJECT_NAME_impl")
add_custom_command( add_custom_command(
@ -6,7 +7,8 @@ add_custom_command(
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPFILE ${impl_basename}.d DEPFILE ${impl_basename}.d
USES_TERMINAL USES_TERMINAL
JOB_SERVER_AWARE JOB_SERVER_AWARE TRUE
VERBATIM
DEPENDS_EXPLICIT_ONLY DEPENDS_EXPLICIT_ONLY
) )
@ -20,3 +22,24 @@ add_library(PROJECT_NAME_impl STATIC IMPORTED)
set_target_properties(PROJECT_NAME_impl PROPERTIES set_target_properties(PROJECT_NAME_impl PROPERTIES
IMPORTED_LOCATION ${impl_basename}.a IMPORTED_LOCATION ${impl_basename}.a
) )
# generate the bindings
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include")
set(bindings_basename "${CMAKE_CURRENT_BINARY_DIR}/include/bindings")
add_custom_command(
OUTPUT ${bindings_basename}.hxx
COMMAND ${CBINDGEN} --only-target-dependencies --output "${bindings_basename}.hxx" --depfile "${bindings_basename}.d"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPFILE ${bindings_basename}.d
VERBATIM
CODEGEN
DEPENDS_EXPLICIT_ONLY
)
target_sources(PROJECT_NAME_impl INTERFACE
${bindings_basename}.hxx
)
target_include_directories(PROJECT_NAME_impl INTERFACE
"${CMAKE_CURRENT_BINARY_DIR}/include"
)

View File

@ -3,13 +3,6 @@
#include <stdexcept> #include <stdexcept>
#include <utility> #include <utility>
namespace ffi {
extern "C" Core* rt4_viewport_create(xcb_connection_t* connection, std::uint32_t window, std::uint32_t width, std::uint32_t height);
extern "C" void rt4_viewport_destroy(Core* viewport);
extern "C" void rt4_viewport_configure(Core* viewport, std::uint32_t width, std::uint32_t height);
extern "C" void rt4_viewport_redraw(Core* viewport, const RedrawArgs* args);
} // namespace ffi
BoxCore::BoxCore(BoxCore&& b) BoxCore::BoxCore(BoxCore&& b)
: ptr(std::exchange(b.ptr, {})) { : ptr(std::exchange(b.ptr, {})) {
} }

View File

@ -2,24 +2,10 @@
#include <cstdint> #include <cstdint>
#include "bindings.hxx"
struct xcb_connection_t; struct xcb_connection_t;
struct alignas(16) Vec4 {
float x, y, z, w;
};
namespace ffi {
struct Core;
struct RedrawArgs {
Vec4 background;
float cam_yaw;
float cam_pitch;
float cam_distance;
float cam_fovy;
};
} // namespace ffi
using ffi::RedrawArgs; using ffi::RedrawArgs;
class MutCore { class MutCore {

View File

@ -12,9 +12,7 @@ PROJECTNAME::PROJECTNAME(QWidget* parent)
PROJECTNAME::~PROJECTNAME() = default; PROJECTNAME::~PROJECTNAME() = default;
void PROJECTNAME::updateView() { void PROJECTNAME::updateView() {
const auto color = m_ui->inBackground->color();
RedrawArgs args{ RedrawArgs args{
.background = { color.redF(), color.greenF(), color.blueF(), 1.00 },
.cam_yaw = qDegreesToRadians((float)m_ui->camYaw->value()), .cam_yaw = qDegreesToRadians((float)m_ui->camYaw->value()),
.cam_pitch = qDegreesToRadians((float)m_ui->camPitch->value()), .cam_pitch = qDegreesToRadians((float)m_ui->camPitch->value()),
.cam_distance = (float)m_ui->camDistance->value(), .cam_distance = (float)m_ui->camDistance->value(),

View File

@ -71,7 +71,7 @@
<double>5.000000000000000</double> <double>5.000000000000000</double>
</property> </property>
<property name="value"> <property name="value">
<double>45.000000000000000</double> <double>135.000000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
@ -156,24 +156,6 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Background color</string>
</property>
</widget>
</item>
<item>
<widget class="KColorCombo" name="inBackground">
<property name="color">
<color>
<red>0</red>
<green>99</green>
<blue>133</blue>
</color>
</property>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
@ -192,11 +174,6 @@
</widget> </widget>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>KColorCombo</class>
<extends>QComboBox</extends>
<header>kcolorcombo.h</header>
</customwidget>
<customwidget> <customwidget>
<class>Viewport</class> <class>Viewport</class>
<extends>QWidget</extends> <extends>QWidget</extends>
@ -206,22 +183,6 @@
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections> <connections>
<connection>
<sender>inBackground</sender>
<signal>highlighted(QColor)</signal>
<receiver>MainWindow</receiver>
<slot>updateView()</slot>
<hints>
<hint type="sourcelabel">
<x>1531</x>
<y>115</y>
</hint>
<hint type="destinationlabel">
<x>799</x>
<y>599</y>
</hint>
</hints>
</connection>
<connection> <connection>
<sender>camYaw</sender> <sender>camYaw</sender>
<signal>valueChanged(double)</signal> <signal>valueChanged(double)</signal>

12
ui/src/types.hxx Normal file
View File

@ -0,0 +1,12 @@
#pragma once
struct alignas(16) Vec4 {
float x, y, z, w;
};
namespace ffi {
template <typename T>
using Box = T*;
} // namespace ffi