Compare commits
264 commits
Author | SHA1 | Date | |
---|---|---|---|
RenovateBot | 8317fd5d1d | ||
RenovateBot | d7064e37b3 | ||
RenovateBot | 1e617eb7a9 | ||
RenovateBot | fadfacb80a | ||
RenovateBot | b2526bcbfb | ||
RenovateBot | 066ba0cddb | ||
RenovateBot | b6539fc82f | ||
RenovateBot | 40b4e85b8f | ||
RenovateBot | 654511cabf | ||
RenovateBot | f3aa907e45 | ||
RenovateBot | f82c603849 | ||
RenovateBot | da6669042f | ||
RenovateBot | 61c196422f | ||
RenovateBot | d4c8fafeb5 | ||
RenovateBot | e3fa942b40 | ||
RenovateBot | 7af632b4ab | ||
RenovateBot | 75d36c559a | ||
RenovateBot | e07f8e914c | ||
4fb0c1b29c | |||
a255998362 | |||
hodasemi | 7b8df3deb9 | ||
hodasemi | e0bc61def0 | ||
RenovateBot | 5cf5af12cd | ||
hodasemi | bba2da6bbe | ||
hodasemi | 9ae7320d3e | ||
RenovateBot | b12fe7492a | ||
33a894e02f | |||
RenovateBot | 0fa5cb55c8 | ||
hodasemi | 88d2a72dd3 | ||
RenovateBot | 6d00eb3736 | ||
hodasemi | 258eda7ced | ||
RenovateBot | acadb282d3 | ||
hodasemi | 5031b83210 | ||
RenovateBot | 66e87f2531 | ||
hodasemi | 9e7645a9a9 | ||
hodasemi | 72614254b1 | ||
RenovateBot | 01f7ef4f98 | ||
RenovateBot | a7a8f2eae1 | ||
hodasemi | 40000ed6b8 | ||
hodasemi | 032dd8b043 | ||
hodasemi | 171cedf181 | ||
hodasemi | b0b2b3e847 | ||
hodasemi | edc60dd757 | ||
hodasemi | bd8d255492 | ||
RenovateBot | a2ab1291ce | ||
hodasemi | e860b2413a | ||
hodasemi | c297325c37 | ||
hodasemi | 469328b934 | ||
hodasemi | 3fdc3a80eb | ||
RenovateBot | 37a528e8c9 | ||
hodasemi | 19a6158ca8 | ||
RenovateBot | 11590b1600 | ||
hodasemi | 7dde74b2e2 | ||
RenovateBot | 657407a4fe | ||
hodasemi | b2f140812a | ||
RenovateBot | 5691835aec | ||
hodasemi | acd44325f7 | ||
RenovateBot | e16f21ed2d | ||
hodasemi | 44d4794605 | ||
RenovateBot | 1151956f0c | ||
hodasemi | 08b1f168a6 | ||
RenovateBot | 7dfe974a5b | ||
hodasemi | 843cbc6e08 | ||
RenovateBot | 205b68c833 | ||
hodasemi | 188a1ea1b6 | ||
RenovateBot | 02c7555702 | ||
hodasemi | 118d287899 | ||
RenovateBot | 495657d7d7 | ||
hodasemi | 8d03e39bf7 | ||
RenovateBot | aa163bada2 | ||
hodasemi | b02baa6a64 | ||
RenovateBot | f84237eaed | ||
hodasemi | 89d38c1eb2 | ||
hodasemi | f42ba30af8 | ||
hodasemi | 0480fe93f0 | ||
hodasemi | a6ea41ce44 | ||
hodasemi | cf63ff7235 | ||
hodasemi | 18e9b32eff | ||
hodasemi | c4d199ac4b | ||
hodasemi | aa19e7a28d | ||
hodasemi | 3ff553a4de | ||
RenovateBot | e12267db97 | ||
RenovateBot | 36cdd7b4cf | ||
hodasemi | 2f06eac898 | ||
RenovateBot | c1598b5e45 | ||
hodasemi | f4448b0c67 | ||
RenovateBot | 3a996a22b9 | ||
hodasemi | 67de09e80f | ||
RenovateBot | 210f446106 | ||
hodasemi | b0ff05b80c | ||
RenovateBot | 52dc19c1f4 | ||
hodasemi | 7d00606109 | ||
RenovateBot | 87b3429bcc | ||
hodasemi | aee76bf3a2 | ||
RenovateBot | 8e92d101e0 | ||
hodasemi | 1ea08b86bb | ||
RenovateBot | d0e21a161b | ||
hodasemi | 770cbf1e63 | ||
hodasemi | aaf7e2a9ac | ||
RenovateBot | 7e46ec6a10 | ||
RenovateBot | 952c5ef057 | ||
hodasemi | 8c210e4da7 | ||
RenovateBot | 68c3a002dc | ||
hodasemi | 54c5da4d85 | ||
RenovateBot | 0588e04e53 | ||
hodasemi | fcbd315baa | ||
RenovateBot | 199ff59f4c | ||
hodasemi | 2a1ea6d53a | ||
hodasemi | f7dd189018 | ||
RenovateBot | 2107a2db78 | ||
RenovateBot | 56c6f1fbc3 | ||
hodasemi | aa92e65281 | ||
RenovateBot | 9f69bc10a6 | ||
hodasemi | 26b38bda28 | ||
RenovateBot | bfb193155b | ||
hodasemi | 1aec1059d8 | ||
RenovateBot | 2206af4921 | ||
hodasemi | 12eed9d070 | ||
RenovateBot | 8059b0f588 | ||
hodasemi | 5d03af750b | ||
RenovateBot | fc39ca6b21 | ||
hodasemi | a1a2a3de24 | ||
RenovateBot | 2765192e4d | ||
hodasemi | 889b2f212c | ||
hodasemi | d87ed8c0c9 | ||
hodasemi | a5a3702153 | ||
hodasemi | b971e0d2a6 | ||
hodasemi | 93109e4204 | ||
RenovateBot | 60bc8cef4b | ||
hodasemi | c991b578db | ||
RenovateBot | 267e3260cd | ||
hodasemi | 7d3f587269 | ||
RenovateBot | 1ab6df01a0 | ||
hodasemi | 339768f812 | ||
RenovateBot | 7f7a6c92a4 | ||
hodasemi | 06290ebcff | ||
RenovateBot | f43bae56eb | ||
hodasemi | aa0c00bf13 | ||
hodasemi | 50ba0e5e8f | ||
RenovateBot | 3d8f7f6635 | ||
RenovateBot | 12bfe71572 | ||
hodasemi | 84ef422485 | ||
RenovateBot | da37ac99c1 | ||
hodasemi | 52a0743aed | ||
RenovateBot | d02e1f3c27 | ||
hodasemi | ae11e61f44 | ||
RenovateBot | 00b77ba1de | ||
hodasemi | 34a6a33b23 | ||
hodasemi | d8f0451f4e | ||
RenovateBot | 87be24be89 | ||
RenovateBot | d1b89c9f68 | ||
hodasemi | 7905957835 | ||
hodasemi | eaff64a9d6 | ||
hodasemi | 7cc1eb54e2 | ||
hodasemi | 8b3186094d | ||
hodasemi | 8e09841dad | ||
hodasemi | 8626d23f88 | ||
hodasemi | 3d0c520b20 | ||
hodasemi | cc1018b6a4 | ||
RenovateBot | 743a4f4912 | ||
hodasemi | 05fa6bd01b | ||
hodasemi | 1785e9f428 | ||
RenovateBot | 78399646b4 | ||
RenovateBot | 681077b65b | ||
hodasemi | b7557e0616 | ||
hodasemi | 6a1075bf13 | ||
hodasemi | 6f09839b6e | ||
hodasemi | f14737a2bb | ||
hodasemi | b4dc8b4b81 | ||
hodasemi | b0f722b42d | ||
hodasemi | 9e11312d04 | ||
hodasemi | 5d25bad6c6 | ||
hodasemi | 10f75c9537 | ||
hodasemi | 17cd3b2df8 | ||
hodasemi | 67fd07fec9 | ||
hodasemi | e4bb7fc2b6 | ||
hodasemi | 9e8a9d3d64 | ||
hodasemi | 2a14cd60ca | ||
hodasemi | e6e1c29647 | ||
hodasemi | 50629c15cd | ||
hodasemi | 6f49bbe8b5 | ||
hodasemi | 91060664c7 | ||
hodasemi | 90fd8fea7d | ||
hodasemi | da0cd5656a | ||
hodasemi | 1b3c553661 | ||
hodasemi | 73d99df3ab | ||
hodasemi | 18d8d32af6 | ||
hodasemi | 7182d73e60 | ||
hodasemi | 8b355baede | ||
hodasemi | 058cf4c149 | ||
hodasemi | b88909e18c | ||
hodasemi | b16fa030cb | ||
hodasemi | 56a915a863 | ||
hodasemi | 47f5f9ffa8 | ||
hodasemi | f337c3f5fc | ||
hodasemi | f145378d29 | ||
hodasemi | 52ac0952dc | ||
hodasemi | 0ff934217d | ||
hodasemi | 65878f8120 | ||
hodasemi | 544f6d765d | ||
hodasemi | 82b01ff056 | ||
hodasemi | 267c9aecad | ||
hodasemi | 5248070a0f | ||
hodasemi | 49c716e0e4 | ||
hodasemi | 8a0e94b99b | ||
hodasemi | 95e7ec72a1 | ||
hodasemi | bd2470d7c7 | ||
hodasemi | e9377e6985 | ||
hodasemi | a8bf3e85d7 | ||
hodasemi | 790fc00aaa | ||
hodasemi | e49bdd715e | ||
hodasemi | 1b029f4b96 | ||
hodasemi | 62a5364500 | ||
hodasemi | f28acb0174 | ||
hodasemi | 33386a1f17 | ||
hodasemi | 49b450ab4f | ||
hodasemi | 4f1027183d | ||
hodasemi | 3f914ffdeb | ||
hodasemi | eec17e1039 | ||
hodasemi | 5186b96b44 | ||
hodasemi | 64fab8d4e2 | ||
hodasemi | 1d901fdbb8 | ||
hodasemi | 57d795f287 | ||
hodasemi | 1d2120fbd2 | ||
hodasemi | b381d6686d | ||
hodasemi | f11eef57ac | ||
hodasemi | 04bd9374a8 | ||
hodasemi | bc142ba988 | ||
hodasemi | 364b1e5686 | ||
hodasemi | e6ae0e7bee | ||
hodasemi | edd17b3c73 | ||
hodasemi | 2e6072812f | ||
hodasemi | da50c97958 | ||
hodasemi | 2dc925fb16 | ||
hodasemi | b449e74ca0 | ||
hodasemi | dd3d9fd2f2 | ||
hodasemi | 2504d4ee24 | ||
hodasemi | 1df2f4183c | ||
hodasemi | dcf9de54f8 | ||
hodasemi | d7b6cfce5f | ||
hodasemi | 1343311ad1 | ||
hodasemi | cba59392ae | ||
hodasemi | b7547534c1 | ||
hodasemi | 7a8476e7f7 | ||
hodasemi | 0f16adaa2d | ||
hodasemi | 004ec764de | ||
hodasemi | 3e2ab4b42c | ||
hodasemi | 7b1df782da | ||
hodasemi | 52b6e96f83 | ||
hodasemi | 2ea249b948 | ||
hodasemi | 763e3c55e2 | ||
hodasemi | 392c4164d6 | ||
hodasemi | 3478425b71 | ||
hodasemi | ecfaa18614 | ||
hodasemi | b4d53e5ec5 | ||
hodasemi | 793fe755a7 | ||
hodasemi | 1289850e58 | ||
hodasemi | be5a734f4b | ||
hodasemi | 0ce404b926 | ||
hodasemi | 70028eb61a | ||
hodasemi | a7469023f6 | ||
hodasemi | b49c026a05 | ||
hodasemi | aaa0fe80cb | ||
hodasemi | b594bc3762 |
21
.gitea/workflows/pull_request.yaml
Normal file
21
.gitea/workflows/pull_request.yaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
name: Gavania Merge Build
|
||||
run_name: Test successful gavania build on merge request
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, reopened, edited, review_requested, synchronize]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
steps:
|
||||
- uses: https://github.com/actions/checkout@v3
|
||||
|
||||
- uses: https://github.com/dtolnay/rust-toolchain@stable
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y universal-ctags glslang-tools libclang-dev
|
||||
|
||||
- name: Build
|
||||
run: cargo build
|
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.background": "#053607",
|
||||
"titleBar.activeBackground": "#074B0A",
|
||||
"titleBar.activeForeground": "#F2FEF3"
|
||||
"activityBar.background": "#3F0F73",
|
||||
"titleBar.activeBackground": "#5916A1",
|
||||
"titleBar.activeForeground": "#FBF9FE"
|
||||
}
|
||||
}
|
16
Cargo.toml
16
Cargo.toml
|
@ -15,9 +15,13 @@ utilities = { git = "https://gavania.de/hodasemi/utilities.git" }
|
|||
rfactor_sm_reader = { git = "https://gavania.de/hodasemi/rfactor_sm_reader.git" }
|
||||
ui = { git = "https://gavania.de/hodasemi/ui.git" }
|
||||
|
||||
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
||||
cgmath = { version = "0.18.0", features = ["swizzle", "serde"] }
|
||||
paste = "1.0.11"
|
||||
serde = "1.0.152"
|
||||
serde_json = "1.0.91"
|
||||
ringbuf = "0.3.2"
|
||||
anyhow = { version = "1.0.86", features = ["backtrace"] }
|
||||
paste = "1.0.15"
|
||||
serde = "1.0.203"
|
||||
serde_json = "1.0.120"
|
||||
ringbuf = "0.3.3"
|
||||
lazy_static = "1.5.0"
|
||||
|
||||
[profile.release-lto]
|
||||
inherits = "release"
|
||||
lto = true
|
||||
|
|
|
@ -2,5 +2,11 @@
|
|||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"matchUpdateTypes": ["minor", "patch"],
|
||||
"automerge": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ pkgdesc="Vulkan overlay layer for rFactor 2"
|
|||
arch=('x86_64')
|
||||
url="https://gavania.de/hodasemi/${_pkgbase}"
|
||||
license=('GPL-3.0')
|
||||
makedepends=('rust' 'ctags' 'glslang')
|
||||
makedepends=('rust' 'ctags' 'glslang' 'vulkan-headers')
|
||||
depends=()
|
||||
conflicts=("${_pkgbase}")
|
||||
source=("git+${url}")
|
||||
|
@ -17,12 +17,12 @@ build() {
|
|||
cd ${_pkgbase}
|
||||
|
||||
# build binaries
|
||||
cargo build --release
|
||||
cargo build --profile release-lto
|
||||
}
|
||||
|
||||
package() {
|
||||
# copy lib
|
||||
install -Dm755 ${_pkgbase}/target/release/libvk_layer_rs.so "${pkgdir}"/usr/lib/libvk_layer_rs.so
|
||||
install -Dm755 ${_pkgbase}/target/release-lto/libvk_layer_rs.so "${pkgdir}"/usr/lib/libvk_layer_rs.so
|
||||
|
||||
# copy layer discovery info file
|
||||
install -Dm644 ${_pkgbase}/resources/rFactorOverlay.json "${pkgdir}"/usr/share/vulkan/implicit_layer.d/rFactorOverlay.json
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# Build package for arch-based systems
|
||||
* simply build it: `makepkg -fc`
|
||||
* also install it directly afterwards: `makepkg -ifc`
|
||||
* simply build it: `makepkg -sfc`
|
||||
* also install it directly afterwards: `makepkg -isfc`
|
||||
|
|
BIN
resources/rFactor2SharedMemoryMapPlugin64_Wine.dll
Executable file
BIN
resources/rFactor2SharedMemoryMapPlugin64_Wine.dll
Executable file
Binary file not shown.
23
src/lib.rs
23
src/lib.rs
|
@ -5,13 +5,28 @@ use std::{
|
|||
fs::{self, File, OpenOptions},
|
||||
io::Write,
|
||||
path::Path,
|
||||
sync::{Mutex, MutexGuard},
|
||||
};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use overlay::{Overlay, OverlayConfig};
|
||||
|
||||
static mut LOG_ENABLED: bool = true;
|
||||
static mut LOG_FILE: String = String::new();
|
||||
static mut OVERLAY: Overlay = Overlay::new();
|
||||
lazy_static! {
|
||||
static ref OVERLAY: Mutex<Overlay> = Mutex::new(Overlay::new());
|
||||
}
|
||||
|
||||
pub(crate) fn overlay() -> MutexGuard<'static, Overlay> {
|
||||
match OVERLAY.lock() {
|
||||
Ok(overlay) => overlay,
|
||||
Err(_) => {
|
||||
write_log!("failed to lock OVERLAY");
|
||||
write_log!(std::backtrace::Backtrace::force_capture());
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn logging() -> bool {
|
||||
unsafe { LOG_ENABLED }
|
||||
|
@ -96,7 +111,11 @@ pub fn check_logging(home: &str) {
|
|||
LOG_FILE = format!("{}/rf2_vk_hud.log", home);
|
||||
}
|
||||
|
||||
if let Err(_) = File::create(unsafe { &LOG_FILE }) {}
|
||||
if let Err(_) = OpenOptions::new()
|
||||
.append(true)
|
||||
.create(true)
|
||||
.open(unsafe { &LOG_FILE })
|
||||
{}
|
||||
|
||||
write_log!(" ==================================================================");
|
||||
write_log!(" ======================= New Negotiation ==========================");
|
||||
|
|
|
@ -3,12 +3,11 @@ use cgmath::{ortho, vec2, Deg};
|
|||
use vulkan_rs::prelude::*;
|
||||
|
||||
use std::{
|
||||
mem,
|
||||
sync::{Arc, Mutex},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::overlay::elements::PositionOnlyVertex;
|
||||
use crate::overlay::elements::{ColorBuffer, PositionOnlyVertex};
|
||||
|
||||
pub struct BackgroundGenerator;
|
||||
|
||||
|
@ -21,16 +20,10 @@ impl BackgroundGenerator {
|
|||
) -> Result<[Arc<Image>; N]> {
|
||||
let max_supported_sample_count = device.max_supported_sample_count(VK_SAMPLE_COUNT_16_BIT);
|
||||
|
||||
let vertex_shader = ShaderModule::from_slice(
|
||||
device.clone(),
|
||||
include_bytes!("generator.vert.spv"),
|
||||
ShaderType::Vertex,
|
||||
)?;
|
||||
let fragment_shader = ShaderModule::from_slice(
|
||||
device.clone(),
|
||||
include_bytes!("generator.frag.spv"),
|
||||
ShaderType::Fragment,
|
||||
)?;
|
||||
let vertex_shader =
|
||||
ShaderModule::from_slice(device.clone(), include_bytes!("generator.vert.spv"))?;
|
||||
let fragment_shader =
|
||||
ShaderModule::from_slice(device.clone(), include_bytes!("generator.frag.spv"))?;
|
||||
|
||||
Ok(image_infos
|
||||
.iter()
|
||||
|
@ -93,23 +86,7 @@ impl BackgroundGenerator {
|
|||
.build(device.clone())?;
|
||||
|
||||
let pipeline = Pipeline::new_graphics()
|
||||
.set_vertex_shader(
|
||||
vertex_shader.clone(),
|
||||
vec![VkVertexInputBindingDescription {
|
||||
binding: 0,
|
||||
stride: mem::size_of::<PositionOnlyVertex>() as u32,
|
||||
inputRate: VK_VERTEX_INPUT_RATE_VERTEX,
|
||||
}],
|
||||
vec![
|
||||
// position
|
||||
VkVertexInputAttributeDescription {
|
||||
location: 0,
|
||||
binding: 0,
|
||||
format: VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
offset: 0,
|
||||
},
|
||||
],
|
||||
)
|
||||
.set_vertex_shader::<PositionOnlyVertex>(vertex_shader.clone())
|
||||
.set_fragment_shader(fragment_shader.clone())
|
||||
.input_assembly(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false)
|
||||
.default_depth_stencil(false, false)
|
||||
|
@ -130,7 +107,7 @@ impl BackgroundGenerator {
|
|||
let color_buffer = Buffer::builder()
|
||||
.set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
||||
.set_memory_usage(MemoryUsage::CpuOnly)
|
||||
.set_data(&color)
|
||||
.set_data(&ColorBuffer::from_array(color))
|
||||
.build(device.clone())?;
|
||||
|
||||
let desc_pool = DescriptorPool::builder()
|
||||
|
|
|
@ -33,7 +33,7 @@ pub struct LeaderBoardEntry {
|
|||
}
|
||||
|
||||
impl LeaderBoardEntry {
|
||||
const ENTRY: &str = include_str!("leaderboard_entry.xml");
|
||||
const ENTRY: &'static str = include_str!("leaderboard_entry.xml");
|
||||
|
||||
pub fn create_snippet(gui_handler: &Arc<GuiHandler>) -> Result<Arc<GuiSnippet>> {
|
||||
GuiSnippet::from_str(gui_handler, Self::ENTRY)
|
||||
|
@ -218,7 +218,7 @@ impl LeaderBoardEntry {
|
|||
if best_lap > 60.0 {
|
||||
let (full_minutes, remainder) = Self::split_minute(best_lap);
|
||||
|
||||
format!("{:.0}:{:.3}", full_minutes, remainder)
|
||||
format!("{:.0}:{:06.3}", full_minutes, remainder)
|
||||
} else {
|
||||
format!("{:.3}", best_lap)
|
||||
}
|
||||
|
@ -307,5 +307,7 @@ mod test {
|
|||
let behind_leader = LeaderBoardEntry::calculate_behind_leader(BehindLeader::Time(85.42));
|
||||
let behind_next = LeaderBoardEntry::calculate_behind_next(150.213423);
|
||||
let best_lap = LeaderBoardEntry::calculuate_best_lap(97.23436);
|
||||
|
||||
let t = LeaderBoardEntry::calculuate_best_lap(65.23436);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,8 +58,8 @@ pub struct LeaderBoard {
|
|||
}
|
||||
|
||||
impl LeaderBoard {
|
||||
const LEADERBOARD: &str = include_str!("leaderboard_grid.xml");
|
||||
const DELTABOARD: &str = include_str!("deltaboard_grid.xml");
|
||||
const LEADERBOARD: &'static str = include_str!("leaderboard_grid.xml");
|
||||
const DELTABOARD: &'static str = include_str!("deltaboard_grid.xml");
|
||||
|
||||
pub fn new(
|
||||
gui_handler: &Arc<GuiHandler>,
|
||||
|
@ -215,9 +215,8 @@ impl LeaderBoard {
|
|||
.child_at(0, self.leaderboard_entries.len() - 1)?
|
||||
.is_none()
|
||||
{
|
||||
for (i, entry) in self.leaderboard_entries.iter().enumerate() {
|
||||
for i in 0..self.leaderboard_grid.dimensions().1 {
|
||||
self.leaderboard_grid.detach(0, i)?;
|
||||
entry.snippet().set_visibility(false)?;
|
||||
}
|
||||
|
||||
true
|
||||
|
|
|
@ -6,13 +6,36 @@ mod watermark;
|
|||
pub use leaderboard::*;
|
||||
pub use pedals::*;
|
||||
pub use radar::*;
|
||||
use utilities::impl_reprc;
|
||||
pub use watermark::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PositionOnlyVertex {
|
||||
pub position: cgmath::Vector4<f32>,
|
||||
use std::mem;
|
||||
use vulkan_rs::prelude::*;
|
||||
|
||||
impl_reprc!(
|
||||
pub struct ColorBuffer {
|
||||
#[assume_reprc]
|
||||
c: f32,
|
||||
}
|
||||
);
|
||||
|
||||
impl ColorBuffer {
|
||||
pub fn from_array<const N: usize>(a: [f32; N]) -> [Self; N] {
|
||||
a.into_iter()
|
||||
.map(|c| Self { c })
|
||||
.collect::<Vec<Self>>()
|
||||
.try_into()
|
||||
.unwrap_or_else(|_: Vec<Self>| unreachable!("create array from vec from an array"))
|
||||
}
|
||||
}
|
||||
|
||||
impl_reprc!(
|
||||
pub struct PositionOnlyVertex {
|
||||
#[assume_reprc]
|
||||
position: cgmath::Vector4<f32>,
|
||||
}
|
||||
);
|
||||
|
||||
impl PositionOnlyVertex {
|
||||
///
|
||||
/// corners[0] - bottom left
|
||||
|
@ -46,3 +69,25 @@ impl PositionOnlyVertex {
|
|||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl VertexInputDescription for PositionOnlyVertex {
|
||||
fn bindings() -> Vec<vulkan_rs::prelude::VkVertexInputBindingDescription> {
|
||||
vec![VkVertexInputBindingDescription {
|
||||
binding: 0,
|
||||
stride: mem::size_of::<PositionOnlyVertex>() as u32,
|
||||
inputRate: VK_VERTEX_INPUT_RATE_VERTEX,
|
||||
}]
|
||||
}
|
||||
|
||||
fn attributes() -> Vec<vulkan_rs::prelude::VkVertexInputAttributeDescription> {
|
||||
vec![
|
||||
// position
|
||||
VkVertexInputAttributeDescription {
|
||||
location: 0,
|
||||
binding: 0,
|
||||
format: VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
offset: 0,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use ui::prelude::*;
|
|||
use vulkan_rs::prelude::*;
|
||||
|
||||
use crate::overlay::{
|
||||
elements::ColorBuffer,
|
||||
rfactor_data::{DataReceiver, GamePhase},
|
||||
UiOverlay,
|
||||
};
|
||||
|
@ -96,10 +97,10 @@ impl Pedals {
|
|||
.set_descriptor_set_count(2)
|
||||
.build(device.clone())?;
|
||||
|
||||
let brake_color_buffer: Arc<Buffer<f32>> = Buffer::builder()
|
||||
let brake_color_buffer = Buffer::builder()
|
||||
.set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
||||
.set_memory_usage(MemoryUsage::CpuOnly)
|
||||
.set_data(&[0.9, 0.0, 0.0, 1.0])
|
||||
.set_data(&ColorBuffer::from_array([0.9, 0.0, 0.0, 1.0]))
|
||||
.build(device.clone())?;
|
||||
|
||||
write_log!("allocate brake descriptor");
|
||||
|
@ -107,15 +108,24 @@ impl Pedals {
|
|||
let brake_descriptor = descriptor_pool.prepare_set().allocate()?;
|
||||
brake_descriptor.update(&[DescriptorWrite::uniform_buffers(0, &[&brake_color_buffer])])?;
|
||||
|
||||
let throttle_color_buffer: Arc<Buffer<f32>> = Buffer::builder()
|
||||
let throttle_color_buffer = Buffer::builder()
|
||||
.set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
||||
.set_memory_usage(MemoryUsage::CpuOnly)
|
||||
.set_data(&[0.0, 0.9, 0.0, 1.0])
|
||||
.set_data(&ColorBuffer::from_array([0.0, 0.9, 0.0, 1.0]))
|
||||
.build(device.clone())?;
|
||||
|
||||
write_log!("allocate throttle descriptor");
|
||||
|
||||
let throttle_descriptor = descriptor_pool.prepare_set().allocate()?;
|
||||
let throttle_descriptor = match descriptor_pool.prepare_set().allocate() {
|
||||
Ok(d) => d,
|
||||
Err(err) => {
|
||||
write_log!(format!("desc alloc {:?}, {}", err, err.backtrace()));
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
|
||||
write_log!("update throttle descriptor");
|
||||
|
||||
throttle_descriptor.update(&[DescriptorWrite::uniform_buffers(
|
||||
0,
|
||||
&[&throttle_color_buffer],
|
||||
|
@ -129,6 +139,8 @@ impl Pedals {
|
|||
brake_samples.push_overwrite(0.0);
|
||||
}
|
||||
|
||||
write_log!(format!("create vertex buffers ({icon_width})"));
|
||||
|
||||
let brake_vertex_buffer = Self::create_vertex_buffer(&device, icon_width as VkDeviceSize)?;
|
||||
let throttle_vertex_buffer =
|
||||
Self::create_vertex_buffer(&device, icon_width as VkDeviceSize)?;
|
||||
|
@ -159,6 +171,8 @@ impl Pedals {
|
|||
throttle_vertex_buffer,
|
||||
};
|
||||
|
||||
write_log!("update vertex buffers");
|
||||
|
||||
me.update_vertex_buffers()?;
|
||||
|
||||
Ok(me)
|
||||
|
@ -206,26 +220,27 @@ impl Pedals {
|
|||
let command_buffer =
|
||||
CommandBuffer::new_primary().build(self.device.clone(), self.queue.clone())?;
|
||||
|
||||
if self.enable {
|
||||
{
|
||||
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
||||
| VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
|
||||
))?;
|
||||
if self.enable {
|
||||
self.render_target
|
||||
.begin(&mut recorder, VK_SUBPASS_CONTENTS_INLINE, 0);
|
||||
|
||||
self.render_target
|
||||
.begin(&mut recorder, VK_SUBPASS_CONTENTS_INLINE, 0);
|
||||
recorder.bind_pipeline(self.pipeline.pipeline())?;
|
||||
|
||||
recorder.bind_pipeline(self.pipeline.pipeline())?;
|
||||
recorder.bind_descriptor_sets_minimal(&[&self.throttle_descriptor]);
|
||||
recorder.bind_vertex_buffer(&self.throttle_vertex_buffer);
|
||||
recorder.draw_complete_single_instance(self.throttle_vertex_buffer.size() as u32);
|
||||
|
||||
recorder.bind_descriptor_sets_minimal(&[&self.throttle_descriptor]);
|
||||
recorder.bind_vertex_buffer(&self.throttle_vertex_buffer);
|
||||
recorder.draw_complete_single_instance(self.throttle_vertex_buffer.size() as u32);
|
||||
recorder.bind_descriptor_sets_minimal(&[&self.brake_descriptor]);
|
||||
recorder.bind_vertex_buffer(&self.brake_vertex_buffer);
|
||||
recorder.draw_complete_single_instance(self.brake_vertex_buffer.size() as u32);
|
||||
|
||||
recorder.bind_descriptor_sets_minimal(&[&self.brake_descriptor]);
|
||||
recorder.bind_vertex_buffer(&self.brake_vertex_buffer);
|
||||
recorder.draw_complete_single_instance(self.brake_vertex_buffer.size() as u32);
|
||||
|
||||
self.render_target.end(&mut recorder);
|
||||
self.render_target.end(&mut recorder);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(command_buffer)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use vulkan_rs::prelude::*;
|
||||
|
||||
use std::{mem, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::super::PositionOnlyVertex;
|
||||
|
||||
|
@ -17,16 +17,10 @@ impl HistoryPipeline {
|
|||
width: u32,
|
||||
height: u32,
|
||||
) -> Result<Self> {
|
||||
let vertex_shader = ShaderModule::from_slice(
|
||||
device.clone(),
|
||||
include_bytes!("history.vert.spv"),
|
||||
ShaderType::Vertex,
|
||||
)?;
|
||||
let fragment_shader = ShaderModule::from_slice(
|
||||
device.clone(),
|
||||
include_bytes!("history.frag.spv"),
|
||||
ShaderType::Fragment,
|
||||
)?;
|
||||
let vertex_shader =
|
||||
ShaderModule::from_slice(device.clone(), include_bytes!("history.vert.spv"))?;
|
||||
let fragment_shader =
|
||||
ShaderModule::from_slice(device.clone(), include_bytes!("history.frag.spv"))?;
|
||||
|
||||
let descriptor_layout = DescriptorSetLayout::builder()
|
||||
.add_layout_binding(
|
||||
|
@ -59,23 +53,7 @@ impl HistoryPipeline {
|
|||
};
|
||||
|
||||
let pipeline = Pipeline::new_graphics()
|
||||
.set_vertex_shader(
|
||||
vertex_shader.clone(),
|
||||
vec![VkVertexInputBindingDescription {
|
||||
binding: 0,
|
||||
stride: mem::size_of::<PositionOnlyVertex>() as u32,
|
||||
inputRate: VK_VERTEX_INPUT_RATE_VERTEX,
|
||||
}],
|
||||
vec![
|
||||
// position
|
||||
VkVertexInputAttributeDescription {
|
||||
location: 0,
|
||||
binding: 0,
|
||||
format: VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
offset: 0,
|
||||
},
|
||||
],
|
||||
)
|
||||
.set_vertex_shader::<PositionOnlyVertex>(vertex_shader.clone())
|
||||
.set_fragment_shader(fragment_shader.clone())
|
||||
.input_assembly(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, false)
|
||||
.default_depth_stencil(false, false)
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
mod pipeline;
|
||||
|
||||
use anyhow::Result;
|
||||
use cgmath::{ortho, vec2, vec3, vec4, Deg, InnerSpace, Matrix4, Rad, Vector2, Vector3};
|
||||
use rfactor_sm_reader::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vulkan_rs::prelude::cgmath::{
|
||||
ortho, vec2, vec3, vec4, Deg, InnerSpace, Matrix4, Rad, Vector2, Vector3,
|
||||
};
|
||||
use vulkan_rs::prelude::*;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
@ -19,7 +21,7 @@ use crate::{
|
|||
write_log,
|
||||
};
|
||||
|
||||
use super::PositionOnlyVertex;
|
||||
use super::{ColorBuffer, PositionOnlyVertex};
|
||||
|
||||
fn convert_vec(v: rF2Vec3) -> Vector3<f32> {
|
||||
vec3(v.x as f32, v.y as f32, v.z as f32)
|
||||
|
@ -220,29 +222,31 @@ impl Radar {
|
|||
let command_buffer =
|
||||
CommandBuffer::new_primary().build(self.device.clone(), self.queue.clone())?;
|
||||
|
||||
if self.enable {
|
||||
{
|
||||
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
||||
| VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
|
||||
))?;
|
||||
|
||||
self.render_target.begin(
|
||||
&mut recorder,
|
||||
VK_SUBPASS_CONTENTS_INLINE,
|
||||
image_index as usize,
|
||||
);
|
||||
if self.enable {
|
||||
self.render_target.begin(
|
||||
&mut recorder,
|
||||
VK_SUBPASS_CONTENTS_INLINE,
|
||||
image_index as usize,
|
||||
);
|
||||
|
||||
recorder.bind_pipeline(self.pipeline.pipeline())?;
|
||||
recorder.bind_pipeline(self.pipeline.pipeline())?;
|
||||
|
||||
for object in self.objects() {
|
||||
let buffer = &object.position_buffer;
|
||||
for object in self.objects() {
|
||||
let buffer = &object.position_buffer;
|
||||
|
||||
recorder.bind_descriptor_sets_minimal(&[&object.descriptor_set]);
|
||||
recorder.bind_vertex_buffer(buffer);
|
||||
recorder.draw_complete_single_instance(buffer.size() as u32);
|
||||
recorder.bind_descriptor_sets_minimal(&[&object.descriptor_set]);
|
||||
recorder.bind_vertex_buffer(buffer);
|
||||
recorder.draw_complete_single_instance(buffer.size() as u32);
|
||||
}
|
||||
|
||||
self.render_target.end(&mut recorder);
|
||||
}
|
||||
|
||||
self.render_target.end(&mut recorder);
|
||||
}
|
||||
|
||||
Ok(command_buffer)
|
||||
|
@ -383,7 +387,7 @@ struct RadarObject {
|
|||
descriptor_set: Arc<DescriptorSet>,
|
||||
|
||||
// uniform buffer
|
||||
color_buffer: Arc<Buffer<f32>>,
|
||||
color_buffer: Arc<Buffer<ColorBuffer>>,
|
||||
|
||||
// vertex buffer
|
||||
position_buffer: Arc<Buffer<PositionOnlyVertex>>,
|
||||
|
@ -399,7 +403,7 @@ impl RadarObject {
|
|||
let color_buffer = Buffer::builder()
|
||||
.set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
||||
.set_memory_usage(MemoryUsage::CpuOnly)
|
||||
.set_data(&color)
|
||||
.set_data(&ColorBuffer::from_array(color))
|
||||
.build(device.clone())?;
|
||||
|
||||
let position_buffer = Buffer::builder()
|
||||
|
@ -443,7 +447,12 @@ impl RadarObject {
|
|||
car_width,
|
||||
car_height,
|
||||
))?;
|
||||
self.color_buffer.fill(&color)
|
||||
self.color_buffer.fill(
|
||||
&color
|
||||
.iter()
|
||||
.map(|&c| ColorBuffer { c })
|
||||
.collect::<Vec<ColorBuffer>>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use vulkan_rs::prelude::*;
|
||||
|
||||
use std::{mem, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::PositionOnlyVertex;
|
||||
|
||||
|
@ -17,16 +17,10 @@ impl SingleColorPipeline {
|
|||
width: u32,
|
||||
height: u32,
|
||||
) -> Result<Self> {
|
||||
let vertex_shader = ShaderModule::from_slice(
|
||||
device.clone(),
|
||||
include_bytes!("single_color.vert.spv"),
|
||||
ShaderType::Vertex,
|
||||
)?;
|
||||
let fragment_shader = ShaderModule::from_slice(
|
||||
device.clone(),
|
||||
include_bytes!("single_color.frag.spv"),
|
||||
ShaderType::Fragment,
|
||||
)?;
|
||||
let vertex_shader =
|
||||
ShaderModule::from_slice(device.clone(), include_bytes!("single_color.vert.spv"))?;
|
||||
let fragment_shader =
|
||||
ShaderModule::from_slice(device.clone(), include_bytes!("single_color.frag.spv"))?;
|
||||
|
||||
let descriptor_layout = DescriptorSetLayout::builder()
|
||||
.add_layout_binding(
|
||||
|
@ -59,23 +53,7 @@ impl SingleColorPipeline {
|
|||
};
|
||||
|
||||
let pipeline = Pipeline::new_graphics()
|
||||
.set_vertex_shader(
|
||||
vertex_shader.clone(),
|
||||
vec![VkVertexInputBindingDescription {
|
||||
binding: 0,
|
||||
stride: mem::size_of::<PositionOnlyVertex>() as u32,
|
||||
inputRate: VK_VERTEX_INPUT_RATE_VERTEX,
|
||||
}],
|
||||
vec![
|
||||
// position
|
||||
VkVertexInputAttributeDescription {
|
||||
location: 0,
|
||||
binding: 0,
|
||||
format: VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
offset: 0,
|
||||
},
|
||||
],
|
||||
)
|
||||
.set_vertex_shader::<PositionOnlyVertex>(vertex_shader.clone())
|
||||
.set_fragment_shader(fragment_shader.clone())
|
||||
.input_assembly(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, false)
|
||||
.default_depth_stencil(false, false)
|
||||
|
|
|
@ -28,7 +28,7 @@ impl UiOverlay for Watermark {}
|
|||
impl DataReceiver for Watermark {
|
||||
fn game_phase_change(&mut self, phase: GamePhase) -> Result<()> {
|
||||
match phase {
|
||||
GamePhase::None => self.gui.enable()?,
|
||||
GamePhase::None | GamePhase::TestDay => self.gui.enable()?,
|
||||
_ => self.gui.disable()?,
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,10 @@ mod elements;
|
|||
mod rendering;
|
||||
mod rfactor_data;
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{bail, Result};
|
||||
use assetpath::AssetPath;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
rc::Rc,
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use ui::{guihandler::guihandler::Font, prelude::*};
|
||||
|
@ -62,28 +61,38 @@ impl OverlayConfig {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InstanceCollection {
|
||||
pub instance: Arc<Instance>,
|
||||
pub physical_devices: Vec<VkPhysicalDevice>,
|
||||
pub device_collection: HashMap<VkDevice, DeviceCollection>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DeviceCollection {
|
||||
pub device: Arc<Device>,
|
||||
pub queues: HashMap<VkQueue, Arc<Mutex<Queue>>>,
|
||||
pub swapchains: HashMap<VkSwapchainKHR, Arc<Swapchain>>,
|
||||
}
|
||||
|
||||
pub struct Overlay {
|
||||
config: OverlayConfig,
|
||||
|
||||
instance: Option<Arc<Instance>>,
|
||||
device: Option<Arc<Device>>,
|
||||
queue: Option<Arc<Mutex<Queue>>>,
|
||||
pub(crate) instances: HashMap<VkInstance, InstanceCollection>,
|
||||
rendering: Option<Rendering>,
|
||||
gui_handler: Option<Arc<GuiHandler>>,
|
||||
|
||||
ui_elements: Vec<Rc<RefCell<dyn UiOverlay>>>,
|
||||
ui_elements: Vec<Arc<Mutex<dyn UiOverlay>>>,
|
||||
|
||||
rfactor_data: Option<RFactorData>,
|
||||
}
|
||||
|
||||
impl Overlay {
|
||||
pub const fn new() -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
config: OverlayConfig::new(),
|
||||
|
||||
instance: None,
|
||||
device: None,
|
||||
queue: None,
|
||||
instances: HashMap::new(),
|
||||
rendering: None,
|
||||
gui_handler: None,
|
||||
ui_elements: Vec::new(),
|
||||
|
@ -96,28 +105,119 @@ impl Overlay {
|
|||
self.config = config;
|
||||
}
|
||||
|
||||
pub fn set_instance(&mut self, instance: Arc<Instance>) {
|
||||
self.instance = Some(instance);
|
||||
pub fn add_instance(&mut self, instance: Arc<Instance>) {
|
||||
let physical_devices = match instance.enumerate_physical_devices() {
|
||||
Ok(devices) => devices,
|
||||
Err(err) => {
|
||||
write_log!(format!("failed to enumerate physical devices {err:?}"));
|
||||
panic!();
|
||||
}
|
||||
};
|
||||
|
||||
self.instances.insert(
|
||||
instance.vk_handle(),
|
||||
InstanceCollection {
|
||||
instance,
|
||||
physical_devices,
|
||||
device_collection: HashMap::new(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn instance(&self) -> Arc<Instance> {
|
||||
self.instance.as_ref().unwrap().clone()
|
||||
pub fn remove_instance(&mut self, handle: VkInstance) {
|
||||
self.instances.remove(&handle);
|
||||
}
|
||||
|
||||
pub fn remove_device(&mut self, handle: VkDevice) {
|
||||
for instance_collection in self.instances.values_mut() {
|
||||
instance_collection.device_collection.remove(&handle);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn instance_by_physical_device(&self, physical_device: VkPhysicalDevice) -> Arc<Instance> {
|
||||
match self
|
||||
.instances
|
||||
.values()
|
||||
.find(|collection| {
|
||||
collection
|
||||
.physical_devices
|
||||
.iter()
|
||||
.find(|&&phys_dev| phys_dev == physical_device)
|
||||
.is_some()
|
||||
})
|
||||
.map(|collection| &collection.instance)
|
||||
{
|
||||
Some(instance) => instance.clone(),
|
||||
None => {
|
||||
write_log!(format!(
|
||||
"failed to find instance with physical device ({physical_device:?})"
|
||||
));
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_device(&mut self, device: Arc<Device>) {
|
||||
self.device = Some(device);
|
||||
if let Some(instance_collection) = self
|
||||
.instances
|
||||
.get_mut(&device.physical_device().instance().vk_handle())
|
||||
{
|
||||
instance_collection.device_collection.insert(
|
||||
device.vk_handle(),
|
||||
DeviceCollection {
|
||||
device,
|
||||
queues: HashMap::new(),
|
||||
swapchains: HashMap::new(),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn device(&self) -> Arc<Device> {
|
||||
self.device.as_ref().unwrap().clone()
|
||||
fn device_collection(&self, device: VkDevice) -> &DeviceCollection {
|
||||
for instance_collection in self.instances.values() {
|
||||
if let Some(device_collection) = instance_collection.device_collection.get(&device) {
|
||||
return device_collection;
|
||||
}
|
||||
}
|
||||
|
||||
write_log!(format!("device ({device:?}) not found"));
|
||||
panic!();
|
||||
}
|
||||
|
||||
pub fn device_collection_mut(&mut self, device: &Arc<Device>) -> &mut DeviceCollection {
|
||||
if let Some(instance_collection) = self
|
||||
.instances
|
||||
.get_mut(&device.physical_device().instance().vk_handle())
|
||||
{
|
||||
if let Some(device_collection) = instance_collection
|
||||
.device_collection
|
||||
.get_mut(&device.vk_handle())
|
||||
{
|
||||
return device_collection;
|
||||
}
|
||||
}
|
||||
|
||||
write_log!(format!("device ({device:?}) not found"));
|
||||
panic!();
|
||||
}
|
||||
|
||||
pub fn device(&self, handle: VkDevice) -> Arc<Device> {
|
||||
self.device_collection(handle).device.clone()
|
||||
}
|
||||
|
||||
pub fn set_queue(&mut self, queue: Arc<Mutex<Queue>>) {
|
||||
self.queue = Some(queue);
|
||||
let handle = queue.lock().unwrap().vk_handle();
|
||||
let device = queue.lock().unwrap().device().clone();
|
||||
|
||||
self.device_collection_mut(&device)
|
||||
.queues
|
||||
.insert(handle, queue);
|
||||
}
|
||||
|
||||
pub fn queue(&self) -> Arc<Mutex<Queue>> {
|
||||
self.queue.as_ref().unwrap().clone()
|
||||
pub fn insert_swapchain(&mut self, swapchain: Arc<Swapchain>) {
|
||||
self.device_collection_mut(swapchain.device())
|
||||
.swapchains
|
||||
.insert(swapchain.vk_handle(), swapchain);
|
||||
}
|
||||
|
||||
pub fn swapchain(&self, swapchain: VkSwapchainKHR) -> Option<&Arc<Swapchain>> {
|
||||
|
@ -130,14 +230,32 @@ impl Overlay {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn create_rendering(&mut self, swapchain: Arc<Swapchain>) -> Result<()> {
|
||||
pub fn create_rendering(&mut self, device: VkDevice) -> Result<()> {
|
||||
write_log!("-> create rendering: start");
|
||||
|
||||
self.rendering = None;
|
||||
|
||||
write_log!("-> create rendering: old cleared");
|
||||
|
||||
let mut rendering = Rendering::new(self.queue(), swapchain.clone())?;
|
||||
let device_collection = self.device_collection(device);
|
||||
|
||||
let device = &device_collection.device.clone();
|
||||
let queue = match device_collection.queues.values().next() {
|
||||
Some(queue) => queue.clone(),
|
||||
None => {
|
||||
write_log!(format!("failed to find queue"));
|
||||
panic!();
|
||||
}
|
||||
};
|
||||
let swapchain = match device_collection.swapchains.values().next() {
|
||||
Some(swapchain) => swapchain.clone(),
|
||||
None => {
|
||||
write_log!(format!("failed to find swapchain"));
|
||||
panic!();
|
||||
}
|
||||
};
|
||||
|
||||
let mut rendering = Rendering::new(queue.clone(), swapchain.clone())?;
|
||||
|
||||
write_log!("-> create rendering: new created");
|
||||
|
||||
|
@ -152,78 +270,80 @@ impl Overlay {
|
|||
|
||||
// provide trait required by GuiHandler
|
||||
let ctx = Arc::new(ContextImpl::new(
|
||||
self.device(),
|
||||
self.queue(),
|
||||
swapchain,
|
||||
device.clone(),
|
||||
queue.clone(),
|
||||
swapchain.clone(),
|
||||
rendering.images().clone(),
|
||||
));
|
||||
|
||||
write_log!("create rendering: context created");
|
||||
|
||||
// create GuiHandler
|
||||
let gui_handler = GuiHandler::new(create_info, &(ctx as Arc<dyn ContextInterface>))?;
|
||||
write_log!("GuiHandler successfully created");
|
||||
write_log!("create rendering: GuiHandler successfully created");
|
||||
|
||||
// create ui elements
|
||||
|
||||
// create watermark
|
||||
if self.config.ui_config.enable_watermark {
|
||||
let watermark = Rc::new(RefCell::new(Watermark::new(&gui_handler)?));
|
||||
let watermark = Arc::new(Mutex::new(Watermark::new(&gui_handler)?));
|
||||
|
||||
self.ui_elements.push(watermark);
|
||||
|
||||
write_log!("Watermark successfully created");
|
||||
write_log!("create rendering: Watermark successfully created");
|
||||
}
|
||||
|
||||
// create radar
|
||||
if self.config.ui_config.enable_radar {
|
||||
let radar = Rc::new(RefCell::new(Radar::new(
|
||||
let radar = Arc::new(Mutex::new(Radar::new(
|
||||
self.config.radar_config,
|
||||
self.device(),
|
||||
self.queue(),
|
||||
device.clone(),
|
||||
queue.clone(),
|
||||
&rendering,
|
||||
)?));
|
||||
|
||||
rendering.add_render_callback({
|
||||
let radar = radar.clone();
|
||||
|
||||
move |index| radar.borrow().render(index)
|
||||
move |index| radar.lock().unwrap().render(index)
|
||||
});
|
||||
|
||||
self.ui_elements.push(radar);
|
||||
|
||||
write_log!("Radar successfully created");
|
||||
write_log!("create rendering: Radar successfully created");
|
||||
}
|
||||
|
||||
// create pedals
|
||||
if self.config.ui_config.enable_pedals {
|
||||
let pedals = Rc::new(RefCell::new(Pedals::new(
|
||||
let pedals = Arc::new(Mutex::new(Pedals::new(
|
||||
&gui_handler,
|
||||
self.device(),
|
||||
self.queue(),
|
||||
device.clone(),
|
||||
queue.clone(),
|
||||
)?));
|
||||
|
||||
self.ui_elements.push(pedals.clone());
|
||||
|
||||
rendering.add_render_callback(move |_| pedals.borrow().render());
|
||||
rendering.add_render_callback(move |_| pedals.lock().unwrap().render());
|
||||
|
||||
write_log!("Pedals successfully created");
|
||||
write_log!("create rendering: Pedals successfully created");
|
||||
}
|
||||
|
||||
// create leaderboard
|
||||
if self.config.ui_config.enable_leaderboard {
|
||||
let leaderboard = Rc::new(RefCell::new(LeaderBoard::new(
|
||||
let leaderboard = Arc::new(Mutex::new(LeaderBoard::new(
|
||||
&gui_handler,
|
||||
self.config.leader_board_config,
|
||||
)?));
|
||||
self.ui_elements.push(leaderboard);
|
||||
|
||||
write_log!("Leader Board successfully created");
|
||||
write_log!("create rendering: Leader Board successfully created");
|
||||
}
|
||||
|
||||
// add rendering callbacks
|
||||
rendering.add_render_callback({
|
||||
let gui_handler = gui_handler.clone();
|
||||
let device = self.device();
|
||||
let queue = self.queue();
|
||||
let device = device.clone();
|
||||
let queue = queue.clone();
|
||||
|
||||
move |index| {
|
||||
let command_buffer =
|
||||
|
@ -242,17 +362,22 @@ impl Overlay {
|
|||
}
|
||||
});
|
||||
|
||||
write_log!("render callbacks added");
|
||||
write_log!("create rendering: render callbacks added");
|
||||
|
||||
self.rendering = Some(rendering);
|
||||
self.gui_handler = Some(gui_handler);
|
||||
self.rfactor_data = None;
|
||||
|
||||
write_log!("-> create rendering: end");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn render(&mut self) -> Result<()> {
|
||||
pub fn render(
|
||||
&mut self,
|
||||
wait_semaphores: &[VkSemaphore],
|
||||
swapchain: &Arc<Swapchain>,
|
||||
) -> Result<&Arc<Semaphore>> {
|
||||
if self.rfactor_data.is_none() {
|
||||
self.rfactor_data = RFactorData::new().ok();
|
||||
|
||||
|
@ -260,7 +385,7 @@ impl Overlay {
|
|||
write_log!("created RFactorData");
|
||||
|
||||
for receiver in self.ui_elements.iter() {
|
||||
data.add_receiver(receiver.clone());
|
||||
data.add_receiver(receiver.clone())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +394,13 @@ impl Overlay {
|
|||
rfactor.update()?;
|
||||
}
|
||||
|
||||
self.rendering.as_ref().unwrap().render()
|
||||
let rendering = self.rendering.as_ref().unwrap();
|
||||
|
||||
if swapchain.vk_handle() != rendering.swapchain().vk_handle() {
|
||||
bail!("swapchains did not match");
|
||||
} else {
|
||||
rendering.render(wait_semaphores)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use vulkan_rs::prelude::*;
|
||||
|
||||
use std::{
|
||||
sync::{Arc, Mutex},
|
||||
time::Duration,
|
||||
};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::write_log;
|
||||
|
||||
|
@ -14,7 +11,10 @@ pub struct Rendering {
|
|||
|
||||
queue: Arc<Mutex<Queue>>,
|
||||
|
||||
render_callbacks: Vec<Box<dyn Fn(u32) -> Result<Arc<CommandBuffer>>>>,
|
||||
signal_semaphore: Arc<Semaphore>,
|
||||
fence: Arc<Fence>,
|
||||
|
||||
render_callbacks: Vec<Box<dyn Fn(u32) -> Result<Arc<CommandBuffer>> + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl Rendering {
|
||||
|
@ -45,6 +45,9 @@ impl Rendering {
|
|||
));
|
||||
|
||||
Ok(Self {
|
||||
signal_semaphore: Semaphore::new(swapchain.device().clone())?,
|
||||
fence: Fence::builder().build(swapchain.device().clone())?,
|
||||
|
||||
swapchain,
|
||||
images,
|
||||
|
||||
|
@ -60,12 +63,12 @@ impl Rendering {
|
|||
|
||||
pub fn add_render_callback<F>(&mut self, f: F)
|
||||
where
|
||||
F: Fn(u32) -> Result<Arc<CommandBuffer>> + 'static,
|
||||
F: Fn(u32) -> Result<Arc<CommandBuffer>> + Send + Sync + 'static,
|
||||
{
|
||||
self.render_callbacks.push(Box::new(f));
|
||||
}
|
||||
|
||||
pub fn render(&self) -> Result<()> {
|
||||
pub fn render(&self, wait_semaphores: &[VkSemaphore]) -> Result<&Arc<Semaphore>> {
|
||||
let image_index = self.swapchain.current_index();
|
||||
|
||||
let command_buffers: Vec<Arc<CommandBuffer>> = self
|
||||
|
@ -74,15 +77,34 @@ impl Rendering {
|
|||
.map(|c| c(image_index))
|
||||
.collect::<Result<Vec<Arc<CommandBuffer>>>>()?;
|
||||
|
||||
let mut submit = SubmitInfo::default().add_signal_semaphore(&self.signal_semaphore);
|
||||
|
||||
for command_buffer in command_buffers.iter() {
|
||||
submit = submit.add_command_buffer(command_buffer);
|
||||
}
|
||||
|
||||
for wait_semaphore in wait_semaphores {
|
||||
submit = submit
|
||||
.add_wait_semaphore_vk(*wait_semaphore, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
write_log!(format!(
|
||||
"submitting {} commandbuffer(s)",
|
||||
command_buffers.len()
|
||||
));
|
||||
write_log!(format!(
|
||||
"submitting {} wait semaphore(s)",
|
||||
wait_semaphores.len()
|
||||
));
|
||||
|
||||
let queue = self.queue.lock().unwrap();
|
||||
queue.minimal_submit(Duration::from_secs(10), &command_buffers)?;
|
||||
self.queue
|
||||
.lock()
|
||||
.unwrap()
|
||||
.submit(Some(&self.fence), &[submit])?;
|
||||
|
||||
Ok(())
|
||||
write_log!("submitted layer queue");
|
||||
|
||||
Ok(&self.signal_semaphore)
|
||||
}
|
||||
|
||||
pub fn images(&self) -> &Vec<Arc<Image>> {
|
||||
|
|
|
@ -2,8 +2,7 @@ use anyhow::Result;
|
|||
use rfactor_sm_reader::*;
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
rc::Rc,
|
||||
sync::{Arc, Mutex},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
|
@ -11,7 +10,7 @@ use crate::write_log;
|
|||
|
||||
use super::UiOverlay;
|
||||
|
||||
pub trait DataReceiver {
|
||||
pub trait DataReceiver: Send + Sync {
|
||||
fn game_phase_change(&mut self, phase: GamePhase) -> Result<()>;
|
||||
|
||||
fn update_for_phase(&self, phase: GamePhase) -> bool;
|
||||
|
@ -67,7 +66,7 @@ pub struct RFactorData {
|
|||
player_id: Option<i32>,
|
||||
previous_game_phase: GamePhase,
|
||||
|
||||
receivers: Vec<Rc<RefCell<dyn UiOverlay>>>,
|
||||
receivers: Vec<Arc<Mutex<dyn UiOverlay>>>,
|
||||
}
|
||||
|
||||
impl RFactorData {
|
||||
|
@ -89,8 +88,15 @@ impl RFactorData {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn add_receiver(&mut self, receiver: Rc<RefCell<dyn UiOverlay>>) {
|
||||
pub fn add_receiver(&mut self, receiver: Arc<Mutex<dyn UiOverlay>>) -> Result<()> {
|
||||
receiver
|
||||
.lock()
|
||||
.unwrap()
|
||||
.game_phase_change(self.previous_game_phase)?;
|
||||
|
||||
self.receivers.push(receiver);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn now(&self) -> f32 {
|
||||
|
@ -101,65 +107,49 @@ impl RFactorData {
|
|||
write_log!(" =================== update RFactorData ===================");
|
||||
|
||||
// get scoring info
|
||||
match self.scoring_reader.vehicle_scoring(self.now()) {
|
||||
Some((scoring_info, vehicle_scorings)) => {
|
||||
self.last_scoring_read = self.start_time.elapsed();
|
||||
if let Some((scoring_info, vehicle_scorings)) =
|
||||
self.scoring_reader.vehicle_scoring(self.now())
|
||||
{
|
||||
self.last_scoring_read = self.start_time.elapsed();
|
||||
|
||||
write_log!(format!(
|
||||
"new scoring info: vehicles: {}",
|
||||
scoring_info.mNumVehicles
|
||||
));
|
||||
write_log!(format!(
|
||||
"new scoring info: vehicles: {}",
|
||||
scoring_info.mNumVehicles
|
||||
));
|
||||
|
||||
// check for player id
|
||||
if scoring_info.mNumVehicles == 0 {
|
||||
self.player_id = None;
|
||||
} else if self.player_id.is_none() {
|
||||
for vehicle_scoring in vehicle_scorings.iter() {
|
||||
if vehicle_scoring.mIsPlayer != 0 {
|
||||
write_log!(format!("player found: {}", vehicle_scoring.mID));
|
||||
self.player_id = Some(vehicle_scoring.mID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let phase = GamePhase::try_from(scoring_info.mSession)?;
|
||||
|
||||
if self.previous_game_phase != phase {
|
||||
self.previous_game_phase = phase;
|
||||
|
||||
for receiver in self.receivers.iter() {
|
||||
receiver
|
||||
.borrow_mut()
|
||||
.game_phase_change(self.previous_game_phase)?;
|
||||
}
|
||||
}
|
||||
|
||||
write_log!(format!("GamePhase: {:?}", self.previous_game_phase));
|
||||
}
|
||||
|
||||
for receiver in self.receivers.iter() {
|
||||
let mut rec_mut = receiver.borrow_mut();
|
||||
|
||||
if rec_mut.update_for_phase(self.previous_game_phase) {
|
||||
rec_mut.scoring_update(self.previous_game_phase, &vehicle_scorings)?;
|
||||
// check for player id
|
||||
if scoring_info.mNumVehicles == 0 {
|
||||
self.player_id = None;
|
||||
} else if self.player_id.is_none() {
|
||||
for vehicle_scoring in vehicle_scorings.iter() {
|
||||
if vehicle_scoring.mIsPlayer != 0 {
|
||||
write_log!(format!("player found: {}", vehicle_scoring.mID));
|
||||
self.player_id = Some(vehicle_scoring.mID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let now = self.start_time.elapsed();
|
||||
|
||||
if now > (self.last_scoring_read + GAME_PHASE_TIME_OUT) {
|
||||
if self.previous_game_phase != GamePhase::None {
|
||||
self.previous_game_phase = GamePhase::None;
|
||||
let phase = GamePhase::try_from(scoring_info.mSession)?;
|
||||
|
||||
for receiver in self.receivers.iter() {
|
||||
receiver
|
||||
.borrow_mut()
|
||||
.game_phase_change(self.previous_game_phase)?;
|
||||
}
|
||||
}
|
||||
if self.previous_game_phase != phase {
|
||||
self.previous_game_phase = phase;
|
||||
|
||||
for receiver in self.receivers.iter() {
|
||||
receiver
|
||||
.lock()
|
||||
.unwrap()
|
||||
.game_phase_change(self.previous_game_phase)?;
|
||||
}
|
||||
}
|
||||
|
||||
write_log!(format!("GamePhase: {:?}", self.previous_game_phase));
|
||||
|
||||
for receiver in self.receivers.iter() {
|
||||
let mut rec_mut = receiver.lock().unwrap();
|
||||
|
||||
if rec_mut.update_for_phase(self.previous_game_phase) {
|
||||
rec_mut.scoring_update(self.previous_game_phase, &vehicle_scorings)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +160,7 @@ impl RFactorData {
|
|||
write_log!("new telemetry update");
|
||||
|
||||
for receiver in self.receivers.iter() {
|
||||
let mut rec_mut = receiver.borrow_mut();
|
||||
let mut rec_mut = receiver.lock().unwrap();
|
||||
|
||||
if rec_mut.update_for_phase(self.previous_game_phase) {
|
||||
rec_mut.telemetry_update(self.player_id, &telemetries)?;
|
||||
|
|
|
@ -65,6 +65,6 @@ create_functions_enum!(
|
|||
[CreateDevice, create_device],
|
||||
[DestroyDevice, destroy_device],
|
||||
[CreateSwapchainKHR, create_swapchain],
|
||||
[AcquireNextImageKHR, acquire_next_image],
|
||||
[DestroySwapchainKHR, destroy_swapchain],
|
||||
[QueuePresentKHR, present_queue],
|
||||
);
|
||||
|
|
|
@ -8,12 +8,9 @@ use structs::*;
|
|||
use vk_handles::*;
|
||||
use vulkan_rs::prelude::*;
|
||||
|
||||
use std::{ffi::c_void, mem, os::raw::c_char, ptr};
|
||||
use std::{mem, os::raw::c_char, ptr};
|
||||
|
||||
static mut ACQUIRE_NEXT_IMAGE: PFN_vkAcquireNextImageKHR =
|
||||
unsafe { mem::transmute(vkVoidFunction as *const c_void) };
|
||||
|
||||
use crate::{get_config, logging, write_log, OVERLAY};
|
||||
use crate::{get_config, logging, overlay, write_log};
|
||||
|
||||
#[no_mangle]
|
||||
#[allow(non_snake_case)]
|
||||
|
@ -24,9 +21,7 @@ pub(crate) extern "C" fn vkNegotiateLoaderLayerInterfaceVersion(
|
|||
|
||||
check_logging(&home);
|
||||
|
||||
unsafe {
|
||||
OVERLAY.set_config(get_config(&home));
|
||||
}
|
||||
overlay().set_config(get_config(&home));
|
||||
|
||||
unsafe {
|
||||
*pVersionStruct = VkNegotiateLayerInterface {
|
||||
|
@ -55,6 +50,10 @@ extern "system" fn get_device_proc_addr(
|
|||
_device: VkDevice,
|
||||
function_name: *const c_char,
|
||||
) -> PFN_vkVoidFunction {
|
||||
if cfg!(debug_assertions) {
|
||||
write_log!("get_device_proc_addr");
|
||||
}
|
||||
|
||||
let func_string = match VkString::try_from(function_name) {
|
||||
Ok(func) => func,
|
||||
Err(_) => {
|
||||
|
@ -65,6 +64,10 @@ extern "system" fn get_device_proc_addr(
|
|||
|
||||
let s = func_string.as_str();
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
write_log!(format!("\t{}", s));
|
||||
}
|
||||
|
||||
if let Some(func) = Functions::get_vk_func(s) {
|
||||
return func.convert();
|
||||
}
|
||||
|
@ -73,6 +76,10 @@ extern "system" fn get_device_proc_addr(
|
|||
return func;
|
||||
}
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
write_log!("\t-> returning null");
|
||||
}
|
||||
|
||||
Functions::Null.convert()
|
||||
}
|
||||
|
||||
|
@ -81,6 +88,10 @@ extern "system" fn get_instance_proc_addr(
|
|||
_instance: VkInstance,
|
||||
function_name: *const c_char,
|
||||
) -> PFN_vkVoidFunction {
|
||||
if cfg!(debug_assertions) {
|
||||
write_log!("get_instance_proc_addr");
|
||||
}
|
||||
|
||||
let func_string = match VkString::try_from(function_name) {
|
||||
Ok(func) => func,
|
||||
Err(_) => {
|
||||
|
@ -91,6 +102,10 @@ extern "system" fn get_instance_proc_addr(
|
|||
|
||||
let s = func_string.as_str();
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
write_log!(format!("\t{}", s));
|
||||
}
|
||||
|
||||
if let Some(func) = Functions::get_vk_func(s) {
|
||||
return func.convert();
|
||||
}
|
||||
|
@ -99,6 +114,10 @@ extern "system" fn get_instance_proc_addr(
|
|||
return func;
|
||||
}
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
write_log!("\t-> returning null");
|
||||
}
|
||||
|
||||
Functions::Null.convert()
|
||||
}
|
||||
|
||||
|
@ -144,6 +163,8 @@ pub(crate) extern "system" fn create_instance(
|
|||
|
||||
// DXVK workaround, it creates the instance twice with different properties
|
||||
if ext_names.contains(&VkString::new("VK_KHR_surface")) {
|
||||
write_log!("found VK_KHR_surface");
|
||||
|
||||
unsafe {
|
||||
let panic_result =
|
||||
match std::panic::catch_unwind(|| -> anyhow::Result<std::sync::Arc<Instance>> {
|
||||
|
@ -151,7 +172,11 @@ pub(crate) extern "system" fn create_instance(
|
|||
*instance,
|
||||
proc_addr,
|
||||
&ext_names,
|
||||
(*(*create_info).pApplicationInfo).apiVersion,
|
||||
if (*create_info).pApplicationInfo == ptr::null() {
|
||||
None
|
||||
} else {
|
||||
Some((*(*create_info).pApplicationInfo).apiVersion)
|
||||
},
|
||||
)
|
||||
}) {
|
||||
Ok(panic_ok) => panic_ok,
|
||||
|
@ -172,12 +197,14 @@ pub(crate) extern "system" fn create_instance(
|
|||
}
|
||||
};
|
||||
|
||||
OVERLAY.set_instance(ins);
|
||||
overlay().add_instance(ins);
|
||||
}
|
||||
|
||||
write_log!("-> created local instance handle");
|
||||
}
|
||||
|
||||
write_log!("returning from create_instance");
|
||||
|
||||
VK_SUCCESS
|
||||
}
|
||||
|
||||
|
@ -190,6 +217,7 @@ pub(crate) extern "system" fn destroy_instance(
|
|||
unsafe {
|
||||
if let Some(vk_fn) = vk_handles().handle("vkDestroyInstance") {
|
||||
let destroy_instance: PFN_vkDestroyInstance = mem::transmute(vk_fn);
|
||||
overlay().remove_instance(instance);
|
||||
|
||||
destroy_instance(instance, allocator);
|
||||
}
|
||||
|
@ -236,17 +264,12 @@ pub(crate) extern "system" fn create_device(
|
|||
}
|
||||
|
||||
vk_handles_mut().load_device_functions(unsafe { *device }, proc_addr);
|
||||
unsafe {
|
||||
ACQUIRE_NEXT_IMAGE = match vk_handles().handle("vkAcquireNextImageKHR") {
|
||||
Some(acquire_next_image) => mem::transmute(acquire_next_image),
|
||||
None => {
|
||||
write_log!("failed querying vkAcquireNextImageKHR");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let pdev = match PhysicalDevice::from_raw(unsafe { OVERLAY.instance() }, physical_device) {
|
||||
let mut overlay = overlay();
|
||||
|
||||
let instance = overlay.instance_by_physical_device(physical_device);
|
||||
|
||||
let pdev = match PhysicalDevice::from_raw(instance, physical_device) {
|
||||
Ok(pdev) => pdev,
|
||||
Err(err) => {
|
||||
write_log!(format!("failed creating physical device: {:?}", err));
|
||||
|
@ -300,10 +323,8 @@ pub(crate) extern "system" fn create_device(
|
|||
|
||||
write_log!("got queue from device");
|
||||
|
||||
unsafe {
|
||||
OVERLAY.set_device(device);
|
||||
OVERLAY.set_queue(queue);
|
||||
}
|
||||
overlay.set_device(device.clone());
|
||||
overlay.set_queue(queue);
|
||||
|
||||
VK_SUCCESS
|
||||
}
|
||||
|
@ -317,6 +338,7 @@ pub(crate) extern "system" fn destroy_device(
|
|||
unsafe {
|
||||
if let Some(vk_fn) = vk_handles().handle("vkDestroyDevice") {
|
||||
let destroy_device: PFN_vkDestroyDevice = mem::transmute(vk_fn);
|
||||
overlay().remove_device(device);
|
||||
|
||||
destroy_device(device, allocator);
|
||||
}
|
||||
|
@ -346,18 +368,44 @@ pub(crate) extern "system" fn create_swapchain(
|
|||
*p_swapchain
|
||||
}));
|
||||
|
||||
let mut overlay = overlay();
|
||||
|
||||
let swapchain =
|
||||
match unsafe { Swapchain::from_raw(OVERLAY.device(), &*create_info, *p_swapchain) } {
|
||||
Ok(swapchain) => swapchain,
|
||||
Err(err) => {
|
||||
write_log!(format!("create swapchain failed: {:?}", err));
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
unsafe { Swapchain::from_raw(overlay.device(_device), &*create_info, *p_swapchain) };
|
||||
overlay.insert_swapchain(swapchain);
|
||||
|
||||
{
|
||||
let instances = &overlay.instances;
|
||||
|
||||
write_log!(format!("number of instances: {}", instances.len()));
|
||||
|
||||
for instance_collection in instances.values() {
|
||||
write_log!(format!(
|
||||
"\tnumber of physical devices: {}",
|
||||
instance_collection.physical_devices.len()
|
||||
));
|
||||
|
||||
write_log!(format!(
|
||||
"\tnumber of devices: {}",
|
||||
instance_collection.device_collection.len()
|
||||
));
|
||||
|
||||
for device_collection in instance_collection.device_collection.values() {
|
||||
write_log!(format!(
|
||||
"\t\tnumber of queues: {}",
|
||||
device_collection.queues.len()
|
||||
));
|
||||
write_log!(format!(
|
||||
"\t\tnumber of swapchains: {}",
|
||||
device_collection.swapchains.len()
|
||||
));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
write_log!("-> created Arc<Swapchain>");
|
||||
|
||||
if let Err(err) = unsafe { OVERLAY.create_rendering(swapchain) } {
|
||||
if let Err(err) = overlay.create_rendering(_device) {
|
||||
write_log!(format!("create overlay rendering struct failed: {:?}", err));
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
@ -367,52 +415,27 @@ pub(crate) extern "system" fn create_swapchain(
|
|||
VK_SUCCESS
|
||||
}
|
||||
|
||||
pub(crate) extern "system" fn acquire_next_image(
|
||||
pub(crate) extern "system" fn destroy_swapchain(
|
||||
device: VkDevice,
|
||||
swapchain: VkSwapchainKHR,
|
||||
timeout: u64,
|
||||
semaphore: VkSemaphore,
|
||||
fence: VkFence,
|
||||
image_index: *mut u32,
|
||||
) -> VkResult {
|
||||
allocator: *const VkAllocationCallbacks,
|
||||
) -> () {
|
||||
write_log!(" ================== vulkan layer destroy swapchain ==================");
|
||||
|
||||
unsafe {
|
||||
match OVERLAY.swapchain(swapchain) {
|
||||
Some(sc) => {
|
||||
let device = OVERLAY.device();
|
||||
if let Some(vk_fn) = vk_handles().handle("vkDestroySwapchainKHR") {
|
||||
let destroy_swapchain: PFN_vkDestroySwapchainKHR = mem::transmute(vk_fn);
|
||||
|
||||
let res = device.acquire_next_image(
|
||||
sc.vk_handle(),
|
||||
timeout,
|
||||
Some(semaphore),
|
||||
Some(fence),
|
||||
);
|
||||
|
||||
write_log!(format!(
|
||||
"acquire (swapchain: {:?}) res: {:?}",
|
||||
sc.vk_handle(),
|
||||
res
|
||||
));
|
||||
|
||||
match res {
|
||||
Ok(res) => match res {
|
||||
OutOfDate::Ok(index) => {
|
||||
sc.set_image_index(index);
|
||||
VK_SUCCESS
|
||||
}
|
||||
OutOfDate::OutOfDate => VK_ERROR_OUT_OF_DATE_KHR,
|
||||
OutOfDate::TimeOut => VK_TIMEOUT,
|
||||
},
|
||||
Err(err) => {
|
||||
write_log!(format!("failed acquiring next image {:?}", err));
|
||||
VK_ERROR_DEVICE_LOST
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
write_log!("acquired other swapchain image");
|
||||
ACQUIRE_NEXT_IMAGE(device, swapchain, timeout, semaphore, fence, image_index)
|
||||
}
|
||||
destroy_swapchain(device, swapchain, allocator);
|
||||
}
|
||||
|
||||
let mut overlay = overlay();
|
||||
let device = overlay.device(device);
|
||||
|
||||
overlay
|
||||
.device_collection_mut(&device)
|
||||
.swapchains
|
||||
.remove(&swapchain);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,9 +445,6 @@ pub(crate) extern "system" fn present_queue(
|
|||
) -> VkResult {
|
||||
if logging() {
|
||||
write_log!(" ================== vulkan layer queue present ==================");
|
||||
write_log!(format!("iq: {:?}, cq: {:?}", queue, unsafe {
|
||||
OVERLAY.queue().lock().unwrap().vk_handle()
|
||||
}));
|
||||
unsafe {
|
||||
let swapchains = std::slice::from_raw_parts(
|
||||
(*present_info).pSwapchains,
|
||||
|
@ -436,7 +456,7 @@ pub(crate) extern "system" fn present_queue(
|
|||
for swapchain in swapchains {
|
||||
write_log!(format!("present swapchain: {:?}", swapchain));
|
||||
|
||||
if let Some(swch) = OVERLAY.swapchain(*swapchain) {
|
||||
if let Some(swch) = overlay().swapchain(*swapchain) {
|
||||
write_log!(format!(
|
||||
" -> internal swapchain found! ({:?})",
|
||||
swch.vk_handle()
|
||||
|
@ -446,13 +466,8 @@ pub(crate) extern "system" fn present_queue(
|
|||
}
|
||||
}
|
||||
|
||||
match unsafe { OVERLAY.render() } {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
write_log!(format!("overlay rendering failed: {:?}", err));
|
||||
return VK_ERROR_DEVICE_LOST;
|
||||
}
|
||||
};
|
||||
let mut overlay = overlay();
|
||||
let wait_semaphores = unsafe { (*present_info).wait_semaphores() };
|
||||
|
||||
let pfn: PFN_vkQueuePresentKHR = match vk_handles().handle("vkQueuePresentKHR") {
|
||||
Some(pfn) => unsafe { mem::transmute(pfn) },
|
||||
|
@ -462,5 +477,75 @@ pub(crate) extern "system" fn present_queue(
|
|||
}
|
||||
};
|
||||
|
||||
pfn(queue, present_info)
|
||||
for (index, swapchain_info) in unsafe { (*present_info).swapchain_info() }
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
if let Some(swapchain) = overlay.swapchain(swapchain_info.swapchain).cloned() {
|
||||
unsafe { swapchain.set_image_index(swapchain_info.index) };
|
||||
let swapchain_handle = swapchain.vk_handle();
|
||||
|
||||
match overlay.render(wait_semaphores, &swapchain) {
|
||||
Ok(signal_semaphore) => {
|
||||
let wait_semaphores = &[signal_semaphore.vk_handle()];
|
||||
let swapchain_handles = &[swapchain_handle];
|
||||
let indices = &[swapchain_info.index];
|
||||
|
||||
let mut new_present_info =
|
||||
VkPresentInfoKHR::new(wait_semaphores, swapchain_handles, indices, &mut []);
|
||||
new_present_info.pNext = unsafe { (*present_info).pNext };
|
||||
|
||||
if signal_semaphore.vk_handle() != new_present_info.wait_semaphores()[0] {
|
||||
write_log!(format!(
|
||||
"wait_semaphore: expected ({:?}) - found ({:?})",
|
||||
signal_semaphore.vk_handle(),
|
||||
new_present_info.wait_semaphores()[0],
|
||||
));
|
||||
}
|
||||
|
||||
if swapchain_handle != new_present_info.swapchain_info()[0].swapchain {
|
||||
write_log!(format!(
|
||||
"swapchain: expected ({:?}) - found ({:?})",
|
||||
swapchain_handle,
|
||||
new_present_info.swapchain_info()[0].swapchain,
|
||||
));
|
||||
}
|
||||
|
||||
if swapchain_info.index != new_present_info.swapchain_info()[0].index {
|
||||
write_log!(format!(
|
||||
"index: expected ({:?}) - found ({:?})",
|
||||
swapchain_info.index,
|
||||
new_present_info.swapchain_info()[0].index,
|
||||
));
|
||||
}
|
||||
|
||||
let res = pfn(queue, &new_present_info);
|
||||
|
||||
let results = unsafe { (*present_info).results() };
|
||||
|
||||
if results.len() > index {
|
||||
results[index] = res;
|
||||
}
|
||||
|
||||
if res != VK_SUCCESS {
|
||||
write_log!(format!("queue present failed: {:?}", res));
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
write_log!(format!("overlay rendering failed: {:?}", err));
|
||||
return VK_ERROR_DEVICE_LOST;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write_log!("finish present queue");
|
||||
|
||||
match unsafe { (*present_info).results() }
|
||||
.iter()
|
||||
.find(|&&result| result != VK_SUCCESS)
|
||||
{
|
||||
Some(&error) => error,
|
||||
None => VK_SUCCESS,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ use anyhow::Result;
|
|||
use std::{collections::HashMap, ffi::c_void, mem, ptr};
|
||||
use vulkan_rs::prelude::*;
|
||||
|
||||
use crate::write_log;
|
||||
|
||||
static mut FN_HANDLES: Option<VkTypedefHandles> = None;
|
||||
|
||||
pub fn vk_handles() -> &'static VkTypedefHandles {
|
||||
|
@ -43,7 +45,13 @@ impl VkTypedefHandles {
|
|||
let function = proc_addr(instance, name.as_ptr());
|
||||
|
||||
if mem::transmute::<PFN_vkVoidFunction, *const c_void>(function) != ptr::null() {
|
||||
if cfg!(debug_assertions) {
|
||||
write_log!(format!("layer (instance): successfully read: {}", symbol));
|
||||
}
|
||||
|
||||
self.functions.insert(symbol.clone(), function);
|
||||
} else {
|
||||
write_log!(format!("layer (instance): failed reading {}", symbol));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +64,13 @@ impl VkTypedefHandles {
|
|||
let function = proc_addr(device, name.as_ptr());
|
||||
|
||||
if mem::transmute::<PFN_vkVoidFunction, *const c_void>(function) != ptr::null() {
|
||||
if cfg!(debug_assertions) {
|
||||
write_log!(format!("layer (device): successfully read: {}", symbol));
|
||||
}
|
||||
|
||||
self.functions.insert(symbol.clone(), function);
|
||||
} else {
|
||||
write_log!(format!("layer (device): failed reading {}", symbol));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue