Start implement data reader from rfactor
This commit is contained in:
parent
793fe755a7
commit
b4d53e5ec5
7 changed files with 235 additions and 37 deletions
|
@ -13,3 +13,4 @@ crate-type = ["cdylib"]
|
||||||
vulkan-rs = { path = "/home/michael/Dokumente/Workspace/Gavania/vulkan-rs" }
|
vulkan-rs = { path = "/home/michael/Dokumente/Workspace/Gavania/vulkan-rs" }
|
||||||
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
anyhow = { version = "1.0.68", features = ["backtrace"] }
|
||||||
rfactor_sm_reader = { path = "../rfactor_sm_reader" }
|
rfactor_sm_reader = { path = "../rfactor_sm_reader" }
|
||||||
|
cgmath = "0.18.0"
|
||||||
|
|
29
build.rs
29
build.rs
|
@ -9,6 +9,11 @@ const VK_HEADER: &[&str] = &[
|
||||||
];
|
];
|
||||||
const FN_PREFIX: &str = "PFN_";
|
const FN_PREFIX: &str = "PFN_";
|
||||||
|
|
||||||
|
const SHADER: &[&str] = &[
|
||||||
|
"src/overlay/shader/single_color.vert",
|
||||||
|
"src/overlay/shader/single_color.frag",
|
||||||
|
];
|
||||||
|
|
||||||
fn query_vulkan_function_typedefs() {
|
fn query_vulkan_function_typedefs() {
|
||||||
let mut fns = Vec::new();
|
let mut fns = Vec::new();
|
||||||
|
|
||||||
|
@ -48,21 +53,15 @@ fn compile_shader() {
|
||||||
.output()
|
.output()
|
||||||
.expect("Failed to execute glslangValidator. Maybe you need to install it first?");
|
.expect("Failed to execute glslangValidator. Maybe you need to install it first?");
|
||||||
|
|
||||||
Command::new("glslangValidator")
|
for shader in SHADER {
|
||||||
.arg("-V")
|
Command::new("glslangValidator")
|
||||||
.arg("src/overlay/shader/single_color.vert")
|
.arg("-V")
|
||||||
.arg("-o")
|
.arg(shader)
|
||||||
.arg("src/overlay/shader/single_color.vert.spv")
|
.arg("-o")
|
||||||
.output()
|
.arg(&format!("{}.spv", shader))
|
||||||
.expect("Failed to compile single_color.vert");
|
.output()
|
||||||
|
.expect(&format!("Failed to compile {}", shader));
|
||||||
Command::new("glslangValidator")
|
}
|
||||||
.arg("-V")
|
|
||||||
.arg("src/overlay/shader/single_color.frag")
|
|
||||||
.arg("-o")
|
|
||||||
.arg("src/overlay/shader/single_color.frag.spv")
|
|
||||||
.output()
|
|
||||||
.expect("Failed to compile single_color.frag");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -325,8 +325,6 @@ extern "system" fn submit_queue(
|
||||||
submits: *const VkSubmitInfo,
|
submits: *const VkSubmitInfo,
|
||||||
fence: VkFence,
|
fence: VkFence,
|
||||||
) -> VkResult {
|
) -> VkResult {
|
||||||
write_log(" ================== vulkan layer submit queue ==================");
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let input_submit_info = slice::from_raw_parts(submits, submit_count as usize);
|
let input_submit_info = slice::from_raw_parts(submits, submit_count as usize);
|
||||||
let overlay_submit = match OVERLAY.render() {
|
let overlay_submit = match OVERLAY.render() {
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub struct Overlay {
|
||||||
queue: Option<Arc<Mutex<Queue>>>,
|
queue: Option<Arc<Mutex<Queue>>>,
|
||||||
rendering: Option<Rendering>,
|
rendering: Option<Rendering>,
|
||||||
|
|
||||||
rfactor_data: RFactorData,
|
rfactor_data: Option<RFactorData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Overlay {
|
impl Overlay {
|
||||||
|
@ -27,7 +27,7 @@ impl Overlay {
|
||||||
queue: None,
|
queue: None,
|
||||||
rendering: None,
|
rendering: None,
|
||||||
|
|
||||||
rfactor_data: RFactorData::default(),
|
rfactor_data: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,27 @@ impl Overlay {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self) -> Result<VkSubmitInfo> {
|
pub fn render(&mut self) -> Result<VkSubmitInfo> {
|
||||||
self.rfactor_data.update()?;
|
if self.rfactor_data.is_none() {
|
||||||
|
self.rfactor_data = RFactorData::new(
|
||||||
|
self.device(),
|
||||||
|
self.rendering
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.single_color_pipeline()
|
||||||
|
.descriptor_layout(),
|
||||||
|
)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check twice for rfactor data, because of borrowing rules
|
||||||
|
if let Some(rfactor) = &mut self.rfactor_data {
|
||||||
|
rfactor.update()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let objects = match &self.rfactor_data {
|
||||||
|
Some(rfactor) => rfactor.objects(),
|
||||||
|
None => Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
let device = self.device();
|
let device = self.device();
|
||||||
let queue = self.queue();
|
let queue = self.queue();
|
||||||
|
@ -89,6 +109,6 @@ impl Overlay {
|
||||||
self.rendering
|
self.rendering
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.render(device, queue, swapchain, &self.rfactor_data)
|
.render(device, queue, swapchain, &objects)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,12 @@ use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
use std::{mem, sync::Arc};
|
use std::{mem, sync::Arc};
|
||||||
|
|
||||||
|
use super::rendering::PositionOnlyVertex;
|
||||||
|
|
||||||
pub struct SingleColorPipeline {
|
pub struct SingleColorPipeline {
|
||||||
pipeline: Arc<Pipeline>,
|
pipeline: Arc<Pipeline>,
|
||||||
pipeline_layout: Arc<PipelineLayout>,
|
pipeline_layout: Arc<PipelineLayout>,
|
||||||
|
descriptor_layout: Arc<DescriptorSetLayout>,
|
||||||
|
|
||||||
vertex_shader: Arc<ShaderModule>,
|
vertex_shader: Arc<ShaderModule>,
|
||||||
fragment_shader: Arc<ShaderModule>,
|
fragment_shader: Arc<ShaderModule>,
|
||||||
|
@ -24,14 +27,25 @@ impl SingleColorPipeline {
|
||||||
ShaderType::Fragment,
|
ShaderType::Fragment,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let pipeline_layout = PipelineLayout::builder().build(device.clone())?;
|
let descriptor_layout = DescriptorSetLayout::builder()
|
||||||
|
.add_layout_binding(
|
||||||
|
0,
|
||||||
|
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.build(device.clone())?;
|
||||||
|
|
||||||
|
let pipeline_layout = PipelineLayout::builder()
|
||||||
|
.add_descriptor_set_layout(&descriptor_layout)
|
||||||
|
.build(device.clone())?;
|
||||||
|
|
||||||
let pipeline = Pipeline::new_graphics()
|
let pipeline = Pipeline::new_graphics()
|
||||||
.set_vertex_shader(
|
.set_vertex_shader(
|
||||||
vertex_shader.clone(),
|
vertex_shader.clone(),
|
||||||
vec![VkVertexInputBindingDescription {
|
vec![VkVertexInputBindingDescription {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
stride: mem::size_of::<[f32; 4]>() as u32,
|
stride: mem::size_of::<PositionOnlyVertex>() as u32,
|
||||||
inputRate: VK_VERTEX_INPUT_RATE_VERTEX,
|
inputRate: VK_VERTEX_INPUT_RATE_VERTEX,
|
||||||
}],
|
}],
|
||||||
vec![
|
vec![
|
||||||
|
@ -55,6 +69,7 @@ impl SingleColorPipeline {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
vertex_shader,
|
vertex_shader,
|
||||||
fragment_shader,
|
fragment_shader,
|
||||||
|
descriptor_layout,
|
||||||
pipeline,
|
pipeline,
|
||||||
pipeline_layout,
|
pipeline_layout,
|
||||||
})
|
})
|
||||||
|
@ -63,4 +78,8 @@ impl SingleColorPipeline {
|
||||||
pub fn pipeline(&self) -> &Arc<Pipeline> {
|
pub fn pipeline(&self) -> &Arc<Pipeline> {
|
||||||
&self.pipeline
|
&self.pipeline
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn descriptor_layout(&self) -> &Arc<DescriptorSetLayout> {
|
||||||
|
&self.descriptor_layout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,52 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use cgmath::{Vector2, Vector4};
|
||||||
use vulkan_rs::prelude::*;
|
use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use super::{pipeline::SingleColorPipeline, rfactor_data::RFactorData};
|
use super::{pipeline::SingleColorPipeline, rfactor_data::RenderObject};
|
||||||
use crate::write_log;
|
use crate::write_log;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PositionOnlyVertex {
|
||||||
|
pub position: Vector4<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PositionOnlyVertex {
|
||||||
|
///
|
||||||
|
/// corners[0] - bottom left
|
||||||
|
/// corners[1] - top left
|
||||||
|
/// corners[2] - top right
|
||||||
|
/// corners[3] - bottom right
|
||||||
|
///
|
||||||
|
pub fn from_2d_corners(corners: [Vector2<f32>; 4]) -> [Self; 6] {
|
||||||
|
[
|
||||||
|
Self {
|
||||||
|
position: corners[0].extend(0.0).extend(1.0),
|
||||||
|
},
|
||||||
|
Self {
|
||||||
|
position: corners[1].extend(0.0).extend(1.0),
|
||||||
|
},
|
||||||
|
Self {
|
||||||
|
position: corners[2].extend(0.0).extend(1.0),
|
||||||
|
},
|
||||||
|
Self {
|
||||||
|
position: corners[2].extend(0.0).extend(1.0),
|
||||||
|
},
|
||||||
|
Self {
|
||||||
|
position: corners[3].extend(0.0).extend(1.0),
|
||||||
|
},
|
||||||
|
Self {
|
||||||
|
position: corners[0].extend(0.0).extend(1.0),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Rendering {
|
pub struct Rendering {
|
||||||
swapchain: Arc<Swapchain>,
|
swapchain: Arc<Swapchain>,
|
||||||
pipeline: SingleColorPipeline,
|
pipeline: SingleColorPipeline,
|
||||||
render_target: RenderTarget,
|
render_target: RenderTarget,
|
||||||
images: Vec<Arc<Image>>,
|
|
||||||
submit_info: SubmitInfo,
|
submit_info: SubmitInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +85,6 @@ impl Rendering {
|
||||||
swapchain,
|
swapchain,
|
||||||
pipeline: SingleColorPipeline::new(device, render_target.render_pass())?,
|
pipeline: SingleColorPipeline::new(device, render_target.render_pass())?,
|
||||||
render_target,
|
render_target,
|
||||||
images,
|
|
||||||
submit_info: SubmitInfo::default(),
|
submit_info: SubmitInfo::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -58,15 +93,17 @@ impl Rendering {
|
||||||
&self.swapchain
|
&self.swapchain
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn single_color_pipeline(&self) -> &SingleColorPipeline {
|
||||||
|
&self.pipeline
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render(
|
pub fn render(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: Arc<Device>,
|
device: Arc<Device>,
|
||||||
queue: Arc<Mutex<Queue>>,
|
queue: Arc<Mutex<Queue>>,
|
||||||
swapchain: Arc<Swapchain>,
|
swapchain: Arc<Swapchain>,
|
||||||
rfactor_data: &RFactorData,
|
objects: &[&dyn RenderObject],
|
||||||
) -> Result<VkSubmitInfo> {
|
) -> Result<VkSubmitInfo> {
|
||||||
write_log(" ================== vulkan layer enter rendering ==================");
|
|
||||||
|
|
||||||
let image_index = self.swapchain.current_index();
|
let image_index = self.swapchain.current_index();
|
||||||
|
|
||||||
let viewport = [VkViewport {
|
let viewport = [VkViewport {
|
||||||
|
@ -88,15 +125,11 @@ impl Rendering {
|
||||||
|
|
||||||
let command_buffer = CommandBuffer::new_primary().build(device, queue)?;
|
let command_buffer = CommandBuffer::new_primary().build(device, queue)?;
|
||||||
|
|
||||||
write_log(" ================== vulkan layer created command buffer ==================");
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
|
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
|
||||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
write_log(" ================== vulkan layer begin command buffer ==================");
|
|
||||||
|
|
||||||
self.render_target
|
self.render_target
|
||||||
.begin(&recorder, VK_SUBPASS_CONTENTS_INLINE, image_index as usize);
|
.begin(&recorder, VK_SUBPASS_CONTENTS_INLINE, image_index as usize);
|
||||||
|
|
||||||
|
@ -104,7 +137,13 @@ impl Rendering {
|
||||||
recorder.set_scissor(&scissor);
|
recorder.set_scissor(&scissor);
|
||||||
recorder.set_viewport(&viewport);
|
recorder.set_viewport(&viewport);
|
||||||
|
|
||||||
// // recorder.bind_vertex_buffer();
|
for object in objects {
|
||||||
|
let buffer = object.buffer();
|
||||||
|
|
||||||
|
recorder.bind_descriptor_sets_minimal(&[object.descriptor()]);
|
||||||
|
recorder.bind_vertex_buffer(buffer);
|
||||||
|
recorder.draw_complete_single_instance(buffer.size() as u32);
|
||||||
|
}
|
||||||
|
|
||||||
self.render_target.end(&recorder);
|
self.render_target.end(&recorder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,137 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use cgmath::vec2;
|
||||||
|
use rfactor_sm_reader::*;
|
||||||
|
use vulkan_rs::prelude::*;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use super::rendering::PositionOnlyVertex;
|
||||||
|
|
||||||
|
pub trait RenderObject {
|
||||||
|
fn descriptor(&self) -> &Arc<DescriptorSet>;
|
||||||
|
fn buffer(&self) -> &Arc<Buffer<PositionOnlyVertex>>;
|
||||||
|
}
|
||||||
|
|
||||||
pub struct RFactorData {
|
pub struct RFactorData {
|
||||||
// TODO
|
// rf2 memory mapped data
|
||||||
|
telemetry_reader: TelemetryReader,
|
||||||
|
scoring_reader: ScoringReader,
|
||||||
|
|
||||||
|
// radar objects
|
||||||
|
background: RadarObject,
|
||||||
|
player_car: RadarObject,
|
||||||
|
cars: Vec<RadarObject>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RFactorData {
|
impl RFactorData {
|
||||||
pub const fn default() -> Self {
|
pub fn new(device: Arc<Device>, descriptor_layout: &Arc<DescriptorSetLayout>) -> Result<Self> {
|
||||||
Self {}
|
let radar_extent = 0.2;
|
||||||
|
let car_height = 0.05;
|
||||||
|
let car_width = 0.025;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
telemetry_reader: TelemetryReader::new()?,
|
||||||
|
scoring_reader: ScoringReader::new()?,
|
||||||
|
|
||||||
|
background: RadarObject::new(
|
||||||
|
device.clone(),
|
||||||
|
descriptor_layout,
|
||||||
|
PositionOnlyVertex::from_2d_corners([
|
||||||
|
vec2(-radar_extent, -radar_extent),
|
||||||
|
vec2(-radar_extent, radar_extent),
|
||||||
|
vec2(radar_extent, radar_extent),
|
||||||
|
vec2(radar_extent, -radar_extent),
|
||||||
|
]),
|
||||||
|
[0.5, 0.5, 0.5, 0.5],
|
||||||
|
)?,
|
||||||
|
player_car: RadarObject::new(
|
||||||
|
device.clone(),
|
||||||
|
descriptor_layout,
|
||||||
|
PositionOnlyVertex::from_2d_corners([
|
||||||
|
vec2(-car_width, -car_height),
|
||||||
|
vec2(-car_width, car_height),
|
||||||
|
vec2(car_width, car_height),
|
||||||
|
vec2(car_width, -car_height),
|
||||||
|
]),
|
||||||
|
[0.9, 0.9, 0.0, 0.9],
|
||||||
|
)?,
|
||||||
|
cars: Vec::new(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self) -> Result<()> {
|
pub fn update(&mut self) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn objects(&self) -> Vec<&dyn RenderObject> {
|
||||||
|
let mut objects: Vec<&dyn RenderObject> = Vec::new();
|
||||||
|
|
||||||
|
objects.push(&self.background);
|
||||||
|
|
||||||
|
for other_player_cars in &self.cars {
|
||||||
|
objects.push(other_player_cars);
|
||||||
|
}
|
||||||
|
|
||||||
|
objects.push(&self.player_car);
|
||||||
|
|
||||||
|
objects
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RadarObject {
|
||||||
|
descriptor_set: Arc<DescriptorSet>,
|
||||||
|
|
||||||
|
// uniform buffer
|
||||||
|
color_buffer: Arc<Buffer<f32>>,
|
||||||
|
|
||||||
|
// vertex buffer
|
||||||
|
position_buffer: Arc<Buffer<PositionOnlyVertex>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RadarObject {
|
||||||
|
fn new(
|
||||||
|
device: Arc<Device>,
|
||||||
|
descriptor_layout: &Arc<DescriptorSetLayout>,
|
||||||
|
positions: [PositionOnlyVertex; 6],
|
||||||
|
color: [f32; 4],
|
||||||
|
) -> Result<Self> {
|
||||||
|
let color_buffer = Buffer::builder()
|
||||||
|
.set_usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
|
||||||
|
.set_memory_usage(MemoryUsage::CpuOnly)
|
||||||
|
.set_data(&color)
|
||||||
|
.build(device.clone())?;
|
||||||
|
|
||||||
|
let position_buffer = Buffer::builder()
|
||||||
|
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||||||
|
.set_memory_usage(MemoryUsage::CpuOnly)
|
||||||
|
.set_data(&positions)
|
||||||
|
.build(device.clone())?;
|
||||||
|
|
||||||
|
let descriptor_pool = DescriptorPool::builder()
|
||||||
|
.set_layout(descriptor_layout.clone())
|
||||||
|
.build(device.clone())?;
|
||||||
|
|
||||||
|
let descriptor_set = descriptor_pool.prepare_set().allocate()?;
|
||||||
|
descriptor_set.update(&[DescriptorWrite::uniform_buffers(0, &[&color_buffer])])?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
descriptor_set,
|
||||||
|
color_buffer,
|
||||||
|
position_buffer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_color(&self, color: [f32; 4]) -> Result<()> {
|
||||||
|
self.color_buffer.fill(&color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderObject for RadarObject {
|
||||||
|
fn descriptor(&self) -> &Arc<DescriptorSet> {
|
||||||
|
&self.descriptor_set
|
||||||
|
}
|
||||||
|
|
||||||
|
fn buffer(&self) -> &Arc<Buffer<PositionOnlyVertex>> {
|
||||||
|
&self.position_buffer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue