315 lines
8.9 KiB
Rust
315 lines
8.9 KiB
Rust
mod pipeline;
|
|
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
use anyhow::Result;
|
|
use cgmath::{ortho, vec4, Matrix4};
|
|
use rfactor_sm_reader::{rF2VehicleTelemetry, VehicleScoringInfoV01};
|
|
use ringbuf::{HeapRb, Rb};
|
|
use ui::prelude::*;
|
|
use vulkan_rs::prelude::*;
|
|
|
|
use crate::overlay::{
|
|
rfactor_data::{DataReceiver, GamePhase},
|
|
UiOverlay,
|
|
};
|
|
use crate::write_log;
|
|
|
|
use self::pipeline::HistoryPipeline;
|
|
|
|
use super::PositionOnlyVertex;
|
|
|
|
pub struct Pedals {
|
|
gui: Arc<GuiBuilder>,
|
|
|
|
brake: Arc<ProgressBar>,
|
|
throttle: Arc<ProgressBar>,
|
|
_history: Arc<Icon>,
|
|
|
|
enable: bool,
|
|
|
|
throttle_samples: HeapRb<f32>,
|
|
brake_samples: HeapRb<f32>,
|
|
|
|
ortho: Matrix4<f32>,
|
|
|
|
device: Arc<Device>,
|
|
queue: Arc<Mutex<Queue>>,
|
|
|
|
render_target: RenderTarget,
|
|
pipeline: HistoryPipeline,
|
|
|
|
brake_descriptor: Arc<DescriptorSet>,
|
|
brake_vertex_buffer: Arc<Buffer<PositionOnlyVertex>>,
|
|
throttle_descriptor: Arc<DescriptorSet>,
|
|
throttle_vertex_buffer: Arc<Buffer<PositionOnlyVertex>>,
|
|
}
|
|
|
|
impl Pedals {
|
|
pub fn new(
|
|
gui_handler: &Arc<GuiHandler>,
|
|
device: Arc<Device>,
|
|
queue: Arc<Mutex<Queue>>,
|
|
) -> Result<Self> {
|
|
const DESC: &str = include_str!("pedals.xml");
|
|
|
|
let gui = GuiBuilder::from_str(gui_handler, DESC)?;
|
|
|
|
let brake = gui.element("brake")?;
|
|
let throttle = gui.element("throttle")?;
|
|
let history: Arc<Icon> = gui.element("history")?;
|
|
|
|
let (icon_width, icon_height) = history.extent();
|
|
let history_image = Image::empty(
|
|
icon_width as u32,
|
|
icon_height as u32,
|
|
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
|
VK_SAMPLE_COUNT_1_BIT,
|
|
)
|
|
.format(VK_FORMAT_R8G8B8A8_UNORM)
|
|
.attach_sampler(Sampler::nearest_sampler().build(&device)?)
|
|
.build(&device, &queue)?;
|
|
|
|
history_image.convert_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)?;
|
|
|
|
history.set_icon(&history_image)?;
|
|
|
|
let render_target = RenderTarget::builder()
|
|
.add_sub_pass(
|
|
SubPass::builder(history_image.width(), history_image.height())
|
|
.set_prepared_targets(&[history_image.clone()], 0, [0.3, 0.3, 0.3, 1.0], true)
|
|
.build(&device)?,
|
|
)
|
|
.build(&device)?;
|
|
|
|
let pipeline = HistoryPipeline::new(
|
|
device.clone(),
|
|
render_target.render_pass(),
|
|
history_image.width(),
|
|
history_image.height(),
|
|
)?;
|
|
|
|
let ortho = ortho(0.0, history_image.width() as f32, -0.01, 1.01, -1.0, 1.0);
|
|
|
|
let descriptor_pool = DescriptorPool::builder()
|
|
.set_layout(pipeline.descriptor_layout().clone())
|
|
.set_descriptor_set_count(2)
|
|
.build(device.clone())?;
|
|
|
|
let brake_color_buffer: Arc<Buffer<f32>> = 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])
|
|
.build(device.clone())?;
|
|
|
|
write_log!("allocate brake descriptor");
|
|
|
|
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()
|
|
.set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
|
.set_memory_usage(MemoryUsage::CpuOnly)
|
|
.set_data(&[0.0, 0.9, 0.0, 1.0])
|
|
.build(device.clone())?;
|
|
|
|
write_log!("allocate throttle descriptor");
|
|
|
|
let throttle_descriptor = descriptor_pool.prepare_set().allocate()?;
|
|
throttle_descriptor.update(&[DescriptorWrite::uniform_buffers(
|
|
0,
|
|
&[&throttle_color_buffer],
|
|
)])?;
|
|
|
|
let mut throttle_samples = HeapRb::new(icon_width as usize);
|
|
let mut brake_samples = HeapRb::new(icon_width as usize);
|
|
|
|
for _ in 0..icon_width {
|
|
throttle_samples.push_overwrite(0.0);
|
|
brake_samples.push_overwrite(0.0);
|
|
}
|
|
|
|
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)?;
|
|
|
|
let me = Self {
|
|
gui,
|
|
|
|
brake,
|
|
throttle,
|
|
_history: history,
|
|
|
|
enable: false,
|
|
|
|
throttle_samples,
|
|
brake_samples,
|
|
|
|
ortho,
|
|
|
|
device,
|
|
queue,
|
|
|
|
render_target,
|
|
pipeline,
|
|
|
|
brake_descriptor,
|
|
brake_vertex_buffer,
|
|
throttle_descriptor,
|
|
throttle_vertex_buffer,
|
|
};
|
|
|
|
me.update_vertex_buffers()?;
|
|
|
|
Ok(me)
|
|
}
|
|
|
|
fn create_vertex_buffer(
|
|
device: &Arc<Device>,
|
|
size: VkDeviceSize,
|
|
) -> Result<Arc<Buffer<PositionOnlyVertex>>> {
|
|
Buffer::builder()
|
|
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
|
.set_memory_usage(MemoryUsage::CpuOnly)
|
|
.set_size(size)
|
|
.build(device.clone())
|
|
}
|
|
|
|
fn update_vertex_buffers(&self) -> Result<()> {
|
|
self.update_vertex_buffer(
|
|
&self.throttle_vertex_buffer,
|
|
self.throttle_samples.as_slices(),
|
|
)?;
|
|
self.update_vertex_buffer(&self.brake_vertex_buffer, self.brake_samples.as_slices())?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn update_vertex_buffer(
|
|
&self,
|
|
buffer: &Arc<Buffer<PositionOnlyVertex>>,
|
|
(data1, data2): (&[f32], &[f32]),
|
|
) -> Result<()> {
|
|
let points = data1
|
|
.iter()
|
|
.chain(data2.iter())
|
|
.enumerate()
|
|
.map(|(x, &date)| PositionOnlyVertex {
|
|
position: self.ortho * vec4(x as f32, date, 0.0, 1.0),
|
|
})
|
|
.collect::<Vec<PositionOnlyVertex>>();
|
|
|
|
buffer.fill(&points)
|
|
}
|
|
|
|
pub fn render(&self) -> Result<Arc<CommandBuffer>> {
|
|
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, 0);
|
|
|
|
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.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);
|
|
}
|
|
|
|
Ok(command_buffer)
|
|
}
|
|
}
|
|
|
|
impl UiOverlay for Pedals {}
|
|
|
|
impl DataReceiver for Pedals {
|
|
fn game_phase_change(&mut self, phase: GamePhase) -> Result<()> {
|
|
match phase {
|
|
GamePhase::None => {
|
|
self.enable = false;
|
|
self.gui.disable()?;
|
|
}
|
|
_ => {
|
|
self.enable = true;
|
|
self.gui.enable()?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn update_for_phase(&self, phase: GamePhase) -> bool {
|
|
match phase {
|
|
GamePhase::None => false,
|
|
_ => true,
|
|
}
|
|
}
|
|
|
|
fn scoring_update(
|
|
&mut self,
|
|
_phase: GamePhase,
|
|
_vehicle_scoring: &[VehicleScoringInfoV01],
|
|
) -> Result<()> {
|
|
Ok(())
|
|
}
|
|
|
|
fn telemetry_update(
|
|
&mut self,
|
|
player_id: Option<i32>,
|
|
telemetries: &[rF2VehicleTelemetry],
|
|
) -> Result<()> {
|
|
if let Some(id) = player_id {
|
|
if let Some(telemetry) = telemetries.iter().find(|telemetry| telemetry.id == id) {
|
|
let brake = 1.0 - telemetry.unfiltered_brake as f32;
|
|
let throttle = 1.0 - telemetry.unfiltered_throttle as f32;
|
|
|
|
self.throttle.set_progress(throttle)?;
|
|
self.brake.set_progress(brake)?;
|
|
|
|
self.throttle_samples.push_overwrite(throttle);
|
|
self.brake_samples.push_overwrite(brake);
|
|
|
|
self.update_vertex_buffers()?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use ringbuf::{HeapRb, Rb};
|
|
|
|
#[test]
|
|
fn rb_test() {
|
|
const CAP: usize = 10;
|
|
|
|
let mut buf = HeapRb::new(CAP);
|
|
|
|
for _ in 0..CAP {
|
|
buf.push_overwrite(20);
|
|
}
|
|
|
|
println!("{:?}", buf.as_slices());
|
|
|
|
buf.push_overwrite(40);
|
|
buf.push_overwrite(40);
|
|
buf.push_overwrite(40);
|
|
buf.push_overwrite(40);
|
|
|
|
println!("{:?}", buf.as_slices());
|
|
}
|
|
}
|