Push break job work [not work]
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 7m55s
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 7m55s
This commit is contained in:
parent
e58c22b531
commit
5b74eef561
13 changed files with 118 additions and 18 deletions
75
src/core/input.rs
Normal file
75
src/core/input.rs
Normal file
|
@ -0,0 +1,75 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use winit::{
|
||||
dpi::PhysicalPosition,
|
||||
event::{ElementState, KeyEvent, WindowEvent},
|
||||
keyboard::PhysicalKey,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MouseState {
|
||||
old_position: glam::Vec2,
|
||||
pub position: glam::Vec2,
|
||||
pub delta: glam::Vec2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct InputState {
|
||||
pub key_states: HashMap<PhysicalKey, ElementState>,
|
||||
pub mouse_state: MouseState,
|
||||
}
|
||||
|
||||
impl InputState {
|
||||
pub fn process_event(&mut self, event: &WindowEvent) {
|
||||
match event {
|
||||
WindowEvent::KeyboardInput { event, .. } => {
|
||||
self.update_key_state(event.physical_key, event);
|
||||
}
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
self.update_mouse_position(position);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates deltas before running update
|
||||
pub fn update(&mut self) {
|
||||
self.mouse_state.delta = self.mouse_state.position - self.mouse_state.old_position;
|
||||
self.mouse_state.old_position = self.mouse_state.position;
|
||||
}
|
||||
|
||||
pub fn get_key_state(&self, key: PhysicalKey) -> &ElementState {
|
||||
self.key_states.get(&key).unwrap_or(&ElementState::Released)
|
||||
}
|
||||
|
||||
pub fn get_mouse_state(&self) -> &MouseState {
|
||||
&self.mouse_state
|
||||
}
|
||||
|
||||
fn update_key_state(&mut self, key: PhysicalKey, event: &KeyEvent) {
|
||||
let key_state = self.key_states.get(&event.physical_key);
|
||||
let new_key_state = match key_state {
|
||||
Some(key_state) => match event.state {
|
||||
ElementState::Pressed => match key_state {
|
||||
ElementState::Released => Some(ElementState::Pressed),
|
||||
ElementState::Pressed => None,
|
||||
},
|
||||
ElementState::Released => match key_state {
|
||||
ElementState::Released => None,
|
||||
ElementState::Pressed => Some(ElementState::Released),
|
||||
},
|
||||
},
|
||||
None => match event.state {
|
||||
ElementState::Pressed => Some(ElementState::Pressed),
|
||||
ElementState::Released => Some(ElementState::Released),
|
||||
},
|
||||
};
|
||||
if let Some(new_key_state) = new_key_state {
|
||||
self.key_states.insert(key, new_key_state);
|
||||
}
|
||||
}
|
||||
|
||||
fn update_mouse_position(&mut self, position: &PhysicalPosition<f64>) {
|
||||
self.mouse_state.position = glam::Vec2::new(position.x as f32, position.y as f32);
|
||||
}
|
||||
}
|
4
src/core/mod.rs
Normal file
4
src/core/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
pub mod input;
|
||||
pub mod render;
|
||||
pub mod scene;
|
||||
pub mod timer;
|
201
src/core/render/app.rs
Normal file
201
src/core/render/app.rs
Normal file
|
@ -0,0 +1,201 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::core::input::InputState;
|
||||
use crate::core::scene::SceneManager;
|
||||
use crate::core::timer::Timer;
|
||||
use crate::game::main_scene::MainScene;
|
||||
use egui_winit_vulkano::{Gui, GuiConfig, egui};
|
||||
use vulkano::command_buffer::{
|
||||
AutoCommandBufferBuilder, CommandBufferUsage, RenderingAttachmentInfo, RenderingInfo,
|
||||
};
|
||||
use vulkano::pipeline::graphics::viewport::Viewport;
|
||||
use vulkano::render_pass::{AttachmentLoadOp, AttachmentStoreOp};
|
||||
use vulkano::swapchain::PresentMode;
|
||||
use vulkano::sync::GpuFuture;
|
||||
use vulkano_util::context::VulkanoContext;
|
||||
use vulkano_util::window::{VulkanoWindows, WindowDescriptor};
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::{ElementState, WindowEvent};
|
||||
use winit::event_loop::ActiveEventLoop;
|
||||
use winit::window::WindowId;
|
||||
|
||||
use super::vulkan_context::VulkanContext;
|
||||
|
||||
pub struct App {
|
||||
vulkan_context: VulkanContext,
|
||||
vulkano_windows: VulkanoWindows,
|
||||
gui: HashMap<WindowId, Gui>,
|
||||
clear_color: [f32; 3],
|
||||
input_state: InputState,
|
||||
scene_manager: SceneManager,
|
||||
timer: Timer,
|
||||
}
|
||||
|
||||
impl From<VulkanoContext> for App {
|
||||
fn from(vulkano_context: VulkanoContext) -> Self {
|
||||
Self {
|
||||
vulkan_context: VulkanContext::new(vulkano_context),
|
||||
vulkano_windows: VulkanoWindows::default(),
|
||||
gui: HashMap::new(),
|
||||
clear_color: [0.0, 0.0, 0.0],
|
||||
input_state: InputState::default(),
|
||||
scene_manager: SceneManager::new(),
|
||||
timer: Timer::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplicationHandler for App {
|
||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
let window_id = self.vulkano_windows.create_window(
|
||||
event_loop,
|
||||
self.vulkan_context.vulkano_context(),
|
||||
&WindowDescriptor {
|
||||
title: "Rust ASH Test".to_string(),
|
||||
width: 800.0,
|
||||
height: 600.0,
|
||||
present_mode: PresentMode::Fifo,
|
||||
..Default::default()
|
||||
},
|
||||
|_| {},
|
||||
);
|
||||
|
||||
let gui = {
|
||||
let renderer = self.vulkano_windows.get_renderer_mut(window_id).unwrap();
|
||||
Gui::new(
|
||||
event_loop,
|
||||
renderer.surface(),
|
||||
renderer.graphics_queue(),
|
||||
renderer.swapchain_format(),
|
||||
GuiConfig {
|
||||
is_overlay: true,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
};
|
||||
self.gui.insert(window_id, gui);
|
||||
|
||||
self.scene_manager
|
||||
.load_scene(Box::new(MainScene::default()));
|
||||
}
|
||||
|
||||
fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) {
|
||||
let renderer = self.vulkano_windows.get_renderer_mut(id).unwrap();
|
||||
let gui = self.gui.get_mut(&id).unwrap();
|
||||
|
||||
if !gui.update(&event) {
|
||||
self.input_state.process_event(&event);
|
||||
}
|
||||
|
||||
match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
log::debug!("The close button was pressed; stopping");
|
||||
event_loop.exit();
|
||||
}
|
||||
WindowEvent::Resized(_) => {
|
||||
renderer.resize();
|
||||
}
|
||||
WindowEvent::ScaleFactorChanged { .. } => {
|
||||
renderer.resize();
|
||||
}
|
||||
WindowEvent::RedrawRequested => {
|
||||
self.input_state.update();
|
||||
|
||||
let acquire_future = renderer.acquire(None, |_| {}).unwrap();
|
||||
|
||||
let mut builder = AutoCommandBufferBuilder::primary(
|
||||
self.vulkan_context.command_buffer_allocator().clone(),
|
||||
self.vulkan_context
|
||||
.vulkano_context()
|
||||
.graphics_queue()
|
||||
.queue_family_index(),
|
||||
CommandBufferUsage::OneTimeSubmit,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let viewport = Viewport {
|
||||
offset: [0.0, 0.0],
|
||||
extent: renderer.resolution(),
|
||||
depth_range: 0.0..=1.0,
|
||||
};
|
||||
|
||||
builder
|
||||
.begin_rendering(RenderingInfo {
|
||||
color_attachments: vec![Some(RenderingAttachmentInfo {
|
||||
load_op: AttachmentLoadOp::Clear,
|
||||
store_op: AttachmentStoreOp::Store,
|
||||
clear_value: Some(self.clear_color.into()),
|
||||
..RenderingAttachmentInfo::image_view(
|
||||
renderer.swapchain_image_view().clone(),
|
||||
)
|
||||
})],
|
||||
..Default::default()
|
||||
})
|
||||
.unwrap()
|
||||
.set_viewport(0, [viewport].into_iter().collect())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if let Some(scene) = self.scene.as_ref() {
|
||||
scene
|
||||
.render(&self.vulkan_context, renderer, &mut builder)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
builder.end_rendering().unwrap();
|
||||
|
||||
let command_buffer = builder.build().unwrap();
|
||||
|
||||
let render_future = acquire_future
|
||||
.then_execute(
|
||||
self.vulkan_context
|
||||
.vulkano_context()
|
||||
.graphics_queue()
|
||||
.clone(),
|
||||
command_buffer,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
gui.immediate_ui(|gui| {
|
||||
let ctx = gui.context();
|
||||
|
||||
egui::Window::new("Informations")
|
||||
.vscroll(true)
|
||||
.show(&ctx, |ui| {
|
||||
ui.label(format!("Resolution: {:?}", renderer.resolution()));
|
||||
ui.color_edit_button_rgb(&mut self.clear_color);
|
||||
ui.label(format!(
|
||||
"Mouse position: {:?}",
|
||||
self.input_state.get_mouse_state().position
|
||||
));
|
||||
ui.label(format!(
|
||||
"Mouse delta: {:?}",
|
||||
self.input_state.get_mouse_state().delta
|
||||
));
|
||||
|
||||
for (key, state) in self
|
||||
.input_state
|
||||
.key_states
|
||||
.iter()
|
||||
.filter(|(_, state)| *state == &ElementState::Pressed)
|
||||
{
|
||||
ui.label(format!("{:?} State: {:?}", key, state));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let render_future =
|
||||
gui.draw_on_image(render_future, renderer.swapchain_image_view());
|
||||
|
||||
renderer.present(render_future.boxed(), true);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
|
||||
let window = self.vulkano_windows.get_primary_window().unwrap();
|
||||
window.request_redraw();
|
||||
}
|
||||
}
|
4
src/core/render/mod.rs
Normal file
4
src/core/render/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
pub mod app;
|
||||
pub mod pipelines;
|
||||
pub mod vertex;
|
||||
pub mod vulkan_context;
|
1
src/core/render/pipelines/mod.rs
Normal file
1
src/core/render/pipelines/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod triangle_pipeline;
|
111
src/core/render/pipelines/triangle_pipeline.rs
Normal file
111
src/core/render/pipelines/triangle_pipeline.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::error::Error;
|
||||
use std::sync::Arc;
|
||||
use vulkano::descriptor_set::layout::{
|
||||
DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorType,
|
||||
};
|
||||
use vulkano::device::Device;
|
||||
use vulkano::format::Format;
|
||||
use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo;
|
||||
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState};
|
||||
use vulkano::pipeline::graphics::input_assembly::InputAssemblyState;
|
||||
use vulkano::pipeline::graphics::multisample::MultisampleState;
|
||||
use vulkano::pipeline::graphics::rasterization::RasterizationState;
|
||||
use vulkano::pipeline::graphics::subpass::PipelineRenderingCreateInfo;
|
||||
use vulkano::pipeline::graphics::vertex_input::{Vertex, VertexDefinition};
|
||||
use vulkano::pipeline::graphics::viewport::ViewportState;
|
||||
use vulkano::pipeline::layout::{PipelineDescriptorSetLayoutCreateInfo, PipelineLayoutCreateFlags};
|
||||
use vulkano::pipeline::{
|
||||
DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo,
|
||||
};
|
||||
use vulkano::shader::{EntryPoint, ShaderStages};
|
||||
|
||||
use crate::core::render::vertex::Vertex2D;
|
||||
|
||||
pub mod shaders {
|
||||
pub mod vs {
|
||||
vulkano_shaders::shader! {
|
||||
ty: "vertex",
|
||||
path: r"res/shaders/vertex.vert",
|
||||
}
|
||||
}
|
||||
|
||||
pub mod fs {
|
||||
vulkano_shaders::shader! {
|
||||
ty: "fragment",
|
||||
path: r"res/shaders/vertex.frag",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_triangle_pipeline(
|
||||
device: &Arc<Device>,
|
||||
swapchain_format: Format,
|
||||
) -> Result<Arc<GraphicsPipeline>, Box<dyn Error>> {
|
||||
let (vs, fs) = load_shaders(device)?;
|
||||
let vertex_input_state = Vertex2D::per_vertex().definition(&vs)?;
|
||||
|
||||
let stages = [
|
||||
PipelineShaderStageCreateInfo::new(vs),
|
||||
PipelineShaderStageCreateInfo::new(fs),
|
||||
];
|
||||
|
||||
let mut bindings = BTreeMap::<u32, DescriptorSetLayoutBinding>::new();
|
||||
let mut descriptor_set_layout_binding =
|
||||
DescriptorSetLayoutBinding::descriptor_type(DescriptorType::UniformBuffer);
|
||||
descriptor_set_layout_binding.stages = ShaderStages::VERTEX;
|
||||
bindings.insert(0, descriptor_set_layout_binding);
|
||||
|
||||
let descriptor_set_layout = DescriptorSetLayoutCreateInfo {
|
||||
bindings,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let create_info = PipelineDescriptorSetLayoutCreateInfo {
|
||||
set_layouts: vec![descriptor_set_layout],
|
||||
flags: PipelineLayoutCreateFlags::default(),
|
||||
push_constant_ranges: vec![],
|
||||
}
|
||||
.into_pipeline_layout_create_info(device.clone())?;
|
||||
|
||||
let layout = PipelineLayout::new(device.clone(), create_info)?;
|
||||
|
||||
let subpass = PipelineRenderingCreateInfo {
|
||||
color_attachment_formats: vec![Some(swapchain_format)],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let pipeline = GraphicsPipeline::new(
|
||||
device.clone(),
|
||||
None,
|
||||
GraphicsPipelineCreateInfo {
|
||||
stages: stages.into_iter().collect(),
|
||||
vertex_input_state: Some(vertex_input_state),
|
||||
input_assembly_state: Some(InputAssemblyState::default()),
|
||||
viewport_state: Some(ViewportState::default()),
|
||||
rasterization_state: Some(RasterizationState::default()),
|
||||
multisample_state: Some(MultisampleState::default()),
|
||||
color_blend_state: Some(ColorBlendState::with_attachment_states(
|
||||
subpass.color_attachment_formats.len() as u32,
|
||||
ColorBlendAttachmentState::default(),
|
||||
)),
|
||||
dynamic_state: [DynamicState::Viewport].into_iter().collect(),
|
||||
subpass: Some(subpass.into()),
|
||||
..GraphicsPipelineCreateInfo::layout(layout)
|
||||
},
|
||||
)?;
|
||||
|
||||
Ok(pipeline)
|
||||
}
|
||||
|
||||
fn load_shaders(device: &Arc<Device>) -> Result<(EntryPoint, EntryPoint), Box<dyn Error>> {
|
||||
let vs = shaders::vs::load(device.clone())?
|
||||
.entry_point("main")
|
||||
.ok_or("Failed find main entry point of vertex shader".to_string())?;
|
||||
|
||||
let fs = shaders::fs::load(device.clone())?
|
||||
.entry_point("main")
|
||||
.ok_or("Failed find main entry point of fragment shader".to_string())?;
|
||||
|
||||
Ok((vs, fs))
|
||||
}
|
38
src/core/render/vertex.rs
Normal file
38
src/core/render/vertex.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
use std::sync::Arc;
|
||||
use vulkano::Validated;
|
||||
use vulkano::buffer::{
|
||||
AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
|
||||
};
|
||||
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator};
|
||||
use vulkano::pipeline::graphics::vertex_input::Vertex;
|
||||
|
||||
#[derive(BufferContents, Vertex)]
|
||||
#[repr(C)]
|
||||
pub struct Vertex2D {
|
||||
#[format(R32G32_SFLOAT)]
|
||||
pub position: [f32; 2],
|
||||
|
||||
#[format(R32G32B32_SFLOAT)]
|
||||
pub color: [f32; 3],
|
||||
}
|
||||
|
||||
impl Vertex2D {
|
||||
pub fn create_buffer(
|
||||
vertices: Vec<Vertex2D>,
|
||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
) -> Result<Subbuffer<[Vertex2D]>, Validated<AllocateBufferError>> {
|
||||
Buffer::from_iter(
|
||||
memory_allocator.clone(),
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::VERTEX_BUFFER,
|
||||
..Default::default()
|
||||
},
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
},
|
||||
vertices,
|
||||
)
|
||||
}
|
||||
}
|
45
src/core/render/vulkan_context.rs
Normal file
45
src/core/render/vulkan_context.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use vulkano::{
|
||||
command_buffer::allocator::StandardCommandBufferAllocator,
|
||||
descriptor_set::allocator::StandardDescriptorSetAllocator,
|
||||
};
|
||||
use vulkano_util::context::VulkanoContext;
|
||||
|
||||
pub struct VulkanContext {
|
||||
vulkano_context: VulkanoContext,
|
||||
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
|
||||
descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
|
||||
}
|
||||
|
||||
impl VulkanContext {
|
||||
pub fn new(vulkano_context: VulkanoContext) -> Self {
|
||||
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
|
||||
vulkano_context.device().clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
|
||||
vulkano_context.device().clone(),
|
||||
Default::default(),
|
||||
));
|
||||
|
||||
Self {
|
||||
vulkano_context,
|
||||
command_buffer_allocator,
|
||||
descriptor_set_allocator,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vulkano_context(&self) -> &VulkanoContext {
|
||||
&self.vulkano_context
|
||||
}
|
||||
|
||||
pub fn command_buffer_allocator(&self) -> &Arc<StandardCommandBufferAllocator> {
|
||||
&self.command_buffer_allocator
|
||||
}
|
||||
|
||||
pub fn descriptor_set_allocator(&self) -> &Arc<StandardDescriptorSetAllocator> {
|
||||
&self.descriptor_set_allocator
|
||||
}
|
||||
}
|
29
src/core/scene.rs
Normal file
29
src/core/scene.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
use vulkano_util::renderer::VulkanoWindowRenderer;
|
||||
|
||||
use super::{input::InputState, render::vulkan_context::VulkanContext, timer::Timer};
|
||||
|
||||
pub trait Scene {
|
||||
fn load(&mut self, app: &mut App);
|
||||
fn update(&mut self, app: &mut App);
|
||||
fn render(&self);
|
||||
fn unload(&mut self);
|
||||
}
|
||||
|
||||
pub struct SceneManager {
|
||||
current_scene: Option<Box<dyn Scene>>,
|
||||
}
|
||||
|
||||
impl SceneManager {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
current_scene: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_scene(&mut self, scene: Box<dyn Scene>) {
|
||||
if let Some(current_scene) = self.current_scene.as_mut() {
|
||||
current_scene.unload();
|
||||
}
|
||||
self.current_scene = Some(scene);
|
||||
}
|
||||
}
|
30
src/core/timer.rs
Normal file
30
src/core/timer.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
pub struct Timer {
|
||||
start_time: std::time::Instant,
|
||||
last_time: std::time::Instant,
|
||||
current_time: std::time::Instant,
|
||||
delta_time: f32,
|
||||
}
|
||||
|
||||
impl Timer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
start_time: std::time::Instant::now(),
|
||||
last_time: std::time::Instant::now(),
|
||||
current_time: std::time::Instant::now(),
|
||||
delta_time: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self) {
|
||||
self.current_time = std::time::Instant::now();
|
||||
self.delta_time = self
|
||||
.current_time
|
||||
.duration_since(self.last_time)
|
||||
.as_secs_f32();
|
||||
self.last_time = self.current_time;
|
||||
}
|
||||
|
||||
pub fn get_delta_time(&self) -> f32 {
|
||||
self.delta_time
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue