forked from nonsensical-dev/zenyx-engine
feat: basic triangle rendering
This commit is contained in:
parent
f215c10d0e
commit
43f8f46021
11 changed files with 1828 additions and 67 deletions
1487
Cargo.lock
generated
1487
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -12,7 +12,7 @@ repository = "https://codeberg.org/Caznix/Zenyx"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = ["subcrates/zlog"]
|
members = [ "subcrates/renderer","subcrates/zlog"]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
zlog = { path = "subcrates/zlog" }
|
zlog = { path = "subcrates/zlog" }
|
||||||
|
@ -37,10 +37,14 @@ incremental = false
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
glm = "0.2.3"
|
||||||
|
smol = "2.0.2"
|
||||||
|
|
||||||
terminator = "0.3.2"
|
terminator = "0.3.2"
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
tracing = "0.1.41"
|
tracing = "0.1.41"
|
||||||
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||||
|
vulkano = "0.35.1"
|
||||||
|
wgpu = { version = "25.0.0", features = ["spirv"] }
|
||||||
winit = "0.30.9"
|
winit = "0.30.9"
|
||||||
zlog.workspace = true
|
zlog.workspace = true
|
||||||
|
|
26
build.rs
Normal file
26
build.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
use std::{env, process::Command};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("cargo::rerun-if-changed=shaders");
|
||||||
|
let outdir = env::var("OUT_DIR").unwrap();
|
||||||
|
let vert = Command::new("glslc")
|
||||||
|
.args(["shaders/shader.vert", "-o", &format!("{outdir}/vert.spv")])
|
||||||
|
.output()
|
||||||
|
.expect("Failed to execute 'glslc'");
|
||||||
|
let frag = Command::new("glslc")
|
||||||
|
.args(["shaders/shader.frag", "-o", &format!("{outdir}/frag.spv")])
|
||||||
|
.output()
|
||||||
|
.expect("Failed to execute 'glslc'");
|
||||||
|
if !vert.status.success() {
|
||||||
|
panic!(
|
||||||
|
"Failed to compile vertex shader: {}",
|
||||||
|
String::from_utf8(vert.stderr).unwrap()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if !frag.status.success() {
|
||||||
|
panic!(
|
||||||
|
"Failed to compile fragment shader: {}",
|
||||||
|
String::from_utf8(frag.stderr).unwrap()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
8
shaders/shader.frag
Normal file
8
shaders/shader.frag
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 color;
|
||||||
|
layout(location = 0) out vec4 out_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
out_color = vec4(color, 1.0);
|
||||||
|
}
|
10
shaders/shader.vert
Normal file
10
shaders/shader.vert
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 position;
|
||||||
|
layout(location = 1) in vec3 color;
|
||||||
|
layout(location = 0) out vec3 out_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(position, 1.0);
|
||||||
|
out_color = color;
|
||||||
|
}
|
332
src/main.rs
332
src/main.rs
|
@ -1,7 +1,327 @@
|
||||||
use tracing::info;
|
use std::collections::BTreeMap;
|
||||||
use zlog::config::LoggerConfig;
|
use std::sync::LazyLock;
|
||||||
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
fn main() {
|
use terminator::Terminator;
|
||||||
|
use vulkano::buffer::BufferUsage;
|
||||||
|
use wgpu::util::{DeviceExt, RenderEncoder};
|
||||||
|
use wgpu::{
|
||||||
|
Backends, BufferSlice, BufferUsages, FragmentState, IndexFormat, Instance, InstanceDescriptor,
|
||||||
|
PipelineCompilationOptions, Surface,
|
||||||
|
};
|
||||||
|
use winit::application::ApplicationHandler;
|
||||||
|
use winit::event_loop::EventLoop;
|
||||||
|
use winit::window::{Window, WindowAttributes, WindowId};
|
||||||
|
use zlog::{config::LoggerConfig, query::LogQuery};
|
||||||
|
struct WindowContext<'window> {
|
||||||
|
window: Arc<Window>,
|
||||||
|
renderer: WgpuRenderer<'window>,
|
||||||
|
}
|
||||||
|
impl std::ops::Deref for WindowContext<'_> {
|
||||||
|
type Target = winit::window::Window;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.window.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WgpuRenderer<'surface> {
|
||||||
|
device: wgpu::Device,
|
||||||
|
queue: wgpu::Queue,
|
||||||
|
surface: wgpu::Surface<'surface>,
|
||||||
|
surface_config: wgpu::SurfaceConfiguration,
|
||||||
|
render_pipeline: wgpu::RenderPipeline,
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl WgpuRenderer {
|
||||||
|
// pub fn new(window: Arc<Window>) {}
|
||||||
|
struct App<'window> {
|
||||||
|
state: WgpuState,
|
||||||
|
windows: BTreeMap<WindowId, WindowContext<'window>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl App<'_> {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
state: WgpuState::new(),
|
||||||
|
windows: BTreeMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WgpuState {
|
||||||
|
instance: wgpu::Instance,
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
struct Vertex {
|
||||||
|
position: glm::Vec3,
|
||||||
|
color: glm::Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vertex {
|
||||||
|
const ATTRIBS: [wgpu::VertexAttribute; 2] = [
|
||||||
|
wgpu::VertexAttribute {
|
||||||
|
offset: 0,
|
||||||
|
shader_location: 0,
|
||||||
|
format: wgpu::VertexFormat::Float32x3,
|
||||||
|
},
|
||||||
|
wgpu::VertexAttribute {
|
||||||
|
offset: std::mem::offset_of!(Vertex, color) as u64,
|
||||||
|
shader_location: 1,
|
||||||
|
format: wgpu::VertexFormat::Float32x3,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
|
||||||
|
wgpu::VertexBufferLayout {
|
||||||
|
array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
|
||||||
|
step_mode: wgpu::VertexStepMode::Vertex,
|
||||||
|
attributes: &Self::ATTRIBS,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WgpuState {
|
||||||
|
fn new() -> Self {
|
||||||
|
let backends = Backends::PRIMARY;
|
||||||
|
let instance_descriptor = InstanceDescriptor {
|
||||||
|
backends,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let instance = Instance::new(&instance_descriptor);
|
||||||
|
Self { instance }
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_renderer<'surface>(&self, window: Arc<Window>) -> WgpuRenderer<'surface> {
|
||||||
|
let surface = self.instance.create_surface(window.clone()).unwrap();
|
||||||
|
let adapter = self
|
||||||
|
.instance
|
||||||
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||||
|
power_preference: wgpu::PowerPreference::default(),
|
||||||
|
compatible_surface: Some(&surface),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let device_descriptor = wgpu::DeviceDescriptor::default();
|
||||||
|
let (device, queue) = adapter.request_device(&device_descriptor).await.unwrap();
|
||||||
|
|
||||||
|
let size = window.inner_size();
|
||||||
|
let width = size.width.max(1);
|
||||||
|
let height = size.height.max(1);
|
||||||
|
#[repr(align(4))]
|
||||||
|
struct ShaderCode<const N: usize>([u8; N]);
|
||||||
|
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
|
label: Some("Pipeline Layout"),
|
||||||
|
bind_group_layouts: &[],
|
||||||
|
push_constant_ranges: &[],
|
||||||
|
});
|
||||||
|
|
||||||
|
let vert_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
|
label: Some("Vertex Shader"),
|
||||||
|
source: unsafe {
|
||||||
|
static shader_code: &[u8] =
|
||||||
|
&ShaderCode(*include_bytes!(concat!(env!("OUT_DIR"), "/vert.spv"))).0;
|
||||||
|
// assert!(bytes.len() % 4 == 0);
|
||||||
|
let shader = shader_code.align_to::<u32>().1;
|
||||||
|
wgpu::ShaderSource::SpirV(std::borrow::Cow::Borrowed(shader))
|
||||||
|
},
|
||||||
|
});
|
||||||
|
let frag_shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||||
|
label: Some("Fragment Shader"),
|
||||||
|
source: unsafe {
|
||||||
|
static shader_code: &[u8] =
|
||||||
|
&ShaderCode(*include_bytes!(concat!(env!("OUT_DIR"), "/frag.spv"))).0;
|
||||||
|
// assert!(bytes.len() % 4 == 0);
|
||||||
|
let shader = shader_code.align_to::<u32>().1;
|
||||||
|
wgpu::ShaderSource::SpirV(std::borrow::Cow::Borrowed(shader))
|
||||||
|
},
|
||||||
|
});
|
||||||
|
let var_name = [Some(wgpu::ColorTargetState {
|
||||||
|
format: surface.get_capabilities(&adapter).formats[0],
|
||||||
|
blend: Some(wgpu::BlendState::REPLACE),
|
||||||
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
|
})];
|
||||||
|
let pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
||||||
|
label: Some("Main pipeline"),
|
||||||
|
layout: Some(&pipeline_layout),
|
||||||
|
vertex: wgpu::VertexState {
|
||||||
|
module: &vert_shader,
|
||||||
|
entry_point: Some("main"),
|
||||||
|
buffers: &[Vertex::desc()],
|
||||||
|
compilation_options: Default::default(),
|
||||||
|
},
|
||||||
|
primitive: wgpu::PrimitiveState {
|
||||||
|
topology: wgpu::PrimitiveTopology::TriangleList,
|
||||||
|
strip_index_format: None,
|
||||||
|
front_face: wgpu::FrontFace::Ccw,
|
||||||
|
cull_mode: Some(wgpu::Face::Back),
|
||||||
|
polygon_mode: wgpu::PolygonMode::Fill,
|
||||||
|
unclipped_depth: false,
|
||||||
|
conservative: false,
|
||||||
|
},
|
||||||
|
depth_stencil: None,
|
||||||
|
multisample: wgpu::MultisampleState {
|
||||||
|
count: 1,
|
||||||
|
mask: !0,
|
||||||
|
alpha_to_coverage_enabled: false,
|
||||||
|
},
|
||||||
|
fragment: Some(FragmentState {
|
||||||
|
module: &frag_shader,
|
||||||
|
entry_point: Some("main"),
|
||||||
|
compilation_options: PipelineCompilationOptions::default(),
|
||||||
|
targets: &var_name,
|
||||||
|
}),
|
||||||
|
multiview: None,
|
||||||
|
cache: None,
|
||||||
|
};
|
||||||
|
// todo!();
|
||||||
|
let surface_caps = surface.get_capabilities(&adapter);
|
||||||
|
let present_mode = if surface_caps
|
||||||
|
.present_modes
|
||||||
|
.contains(&wgpu::PresentMode::Mailbox)
|
||||||
|
{
|
||||||
|
wgpu::PresentMode::Mailbox
|
||||||
|
} else {
|
||||||
|
wgpu::PresentMode::Fifo
|
||||||
|
};
|
||||||
|
|
||||||
|
let surface_config = wgpu::SurfaceConfiguration {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
format: surface_caps.formats[0],
|
||||||
|
present_mode,
|
||||||
|
alpha_mode: wgpu::CompositeAlphaMode::Auto,
|
||||||
|
view_formats: vec![],
|
||||||
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||||
|
desired_maximum_frame_latency: 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
surface.configure(&device, &surface_config);
|
||||||
|
let render_pipeline = device.create_render_pipeline(&pipeline_descriptor);
|
||||||
|
WgpuRenderer {
|
||||||
|
surface,
|
||||||
|
surface_config,
|
||||||
|
render_pipeline,
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static VERTICES: LazyLock<[Vertex; 3]> = std::sync::LazyLock::new(|| {
|
||||||
|
[
|
||||||
|
Vertex {
|
||||||
|
position: glm::vec3(-0.6, -0.5, 0.0),
|
||||||
|
color: glm::vec3(1.0, 0.0, 0.0),
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: glm::vec3(0.6, -0.5, 0.0),
|
||||||
|
color: glm::vec3(0.0, 1.0, 0.0),
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: glm::vec3(0.0, 0.5, 0.0),
|
||||||
|
color: glm::vec3(0.0, 0.0, 1.0),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
static INDICIES: [u32; 3] = [0, 1, 2];
|
||||||
|
|
||||||
|
impl<'window> ApplicationHandler for App<'window> {
|
||||||
|
fn window_event(
|
||||||
|
&mut self,
|
||||||
|
event_loop: &winit::event_loop::ActiveEventLoop,
|
||||||
|
window_id: WindowId,
|
||||||
|
event: winit::event::WindowEvent,
|
||||||
|
) {
|
||||||
|
match event {
|
||||||
|
winit::event::WindowEvent::RedrawRequested => {
|
||||||
|
let window_ctx = self.windows.get(&window_id).unwrap();
|
||||||
|
let surface_texture = window_ctx.renderer.surface.get_current_texture().unwrap();
|
||||||
|
let view = surface_texture.texture.create_view(&Default::default());
|
||||||
|
let mut encoder = window_ctx.renderer.device.create_command_encoder(
|
||||||
|
&wgpu::wgt::CommandEncoderDescriptor {
|
||||||
|
label: Some("Render encoder"),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
{
|
||||||
|
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
label: Some("Render"),
|
||||||
|
color_attachments: &[Some(wgpu::RenderPassColorAttachment {
|
||||||
|
view: &view,
|
||||||
|
resolve_target: None,
|
||||||
|
ops: wgpu::Operations {
|
||||||
|
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
|
||||||
|
store: wgpu::StoreOp::Store,
|
||||||
|
},
|
||||||
|
})],
|
||||||
|
depth_stencil_attachment: None,
|
||||||
|
timestamp_writes: None,
|
||||||
|
occlusion_query_set: None,
|
||||||
|
});
|
||||||
|
rpass.set_pipeline(&window_ctx.renderer.render_pipeline);
|
||||||
|
let vertex_buffer = window_ctx.renderer.device.create_buffer_init(
|
||||||
|
&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("Vertex buffer"),
|
||||||
|
contents: unsafe { VERTICES.align_to::<u8>().1 },
|
||||||
|
usage: BufferUsages::VERTEX,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let index_buffer = window_ctx.renderer.device.create_buffer_init(
|
||||||
|
&wgpu::util::BufferInitDescriptor {
|
||||||
|
label: Some("Index buffer"),
|
||||||
|
contents: unsafe { INDICIES.align_to::<u8>().1 },
|
||||||
|
usage: BufferUsages::INDEX,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
rpass.set_vertex_buffer(0, vertex_buffer.slice(..));
|
||||||
|
rpass.set_index_buffer(index_buffer.slice(..), IndexFormat::Uint32);
|
||||||
|
rpass.draw_indexed(0..INDICIES.len() as u32, 0, 0..1);
|
||||||
|
}
|
||||||
|
window_ctx.renderer.queue.submit(Some(encoder.finish()));
|
||||||
|
surface_texture.present()
|
||||||
|
}
|
||||||
|
winit::event::WindowEvent::CloseRequested => {
|
||||||
|
event_loop.exit();
|
||||||
|
}
|
||||||
|
winit::event::WindowEvent::Resized(size) => {
|
||||||
|
if let Some(window_ctx) = self.windows.get(&window_id) {
|
||||||
|
if size.width == 0 || size.height == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut new_config = window_ctx.renderer.surface_config.clone();
|
||||||
|
new_config.width = size.width;
|
||||||
|
new_config.height = size.height;
|
||||||
|
window_ctx
|
||||||
|
.renderer
|
||||||
|
.surface
|
||||||
|
.configure(&window_ctx.renderer.device, &new_config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||||
|
let attr = WindowAttributes::default()
|
||||||
|
.with_title("Zenyx")
|
||||||
|
.with_min_inner_size(winit::dpi::LogicalSize::new(1, 1));
|
||||||
|
|
||||||
|
if self.windows.is_empty() {
|
||||||
|
let window = event_loop.create_window(attr).unwrap();
|
||||||
|
let window = Arc::new(window);
|
||||||
|
let renderer = self.state.create_renderer(window.clone());
|
||||||
|
let window_ctx = WindowContext {
|
||||||
|
renderer: smol::block_on(renderer),
|
||||||
|
window: window.clone(),
|
||||||
|
};
|
||||||
|
let window_id = window.id();
|
||||||
|
self.windows.insert(window_id, window_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), terminator::Terminator> {
|
||||||
let config = LoggerConfig::default()
|
let config = LoggerConfig::default()
|
||||||
.colored_stdout(true)
|
.colored_stdout(true)
|
||||||
.log_to_stdout(true)
|
.log_to_stdout(true)
|
||||||
|
@ -9,6 +329,10 @@ fn main() {
|
||||||
.log_to_file(true)
|
.log_to_file(true)
|
||||||
.log_path("zenyx.log");
|
.log_path("zenyx.log");
|
||||||
let _logger = zlog::Logger::new(config);
|
let _logger = zlog::Logger::new(config);
|
||||||
|
let event_loop = EventLoop::new()?;
|
||||||
|
event_loop.set_control_flow(winit::event_loop::ControlFlow::Poll);
|
||||||
|
|
||||||
info!("This workss")
|
let mut app = App::new();
|
||||||
|
event_loop.run_app(&mut app)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
6
subcrates/renderer/Cargo.toml
Normal file
6
subcrates/renderer/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "renderer"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
1
subcrates/renderer/src/lib.rs
Normal file
1
subcrates/renderer/src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::LogLevel;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use crate::LogLevel;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct LoggerConfig {
|
pub struct LoggerConfig {
|
||||||
pub(crate) log_level: LogLevel,
|
pub(crate) log_level: LogLevel,
|
||||||
|
@ -17,26 +18,32 @@ impl LoggerConfig {
|
||||||
self.log_level = level;
|
self.log_level = level;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_to_file(mut self, f: bool) -> Self {
|
pub fn log_to_file(mut self, f: bool) -> Self {
|
||||||
self.log_to_file = f;
|
self.log_to_file = f;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn colored_stdout(mut self, c: bool) -> Self {
|
pub fn colored_stdout(mut self, c: bool) -> Self {
|
||||||
self.stdout_color = c;
|
self.stdout_color = c;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_to_stdout(mut self, s: bool) -> Self {
|
pub fn log_to_stdout(mut self, s: bool) -> Self {
|
||||||
self.log_to_stdout = s;
|
self.log_to_stdout = s;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log_path<P: AsRef<Path>>(mut self, p: P) -> Self {
|
pub fn log_path<P: AsRef<Path>>(mut self, p: P) -> Self {
|
||||||
self.log_file_path = p.as_ref().to_path_buf();
|
self.log_file_path = p.as_ref().to_path_buf();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stdout_include_time(mut self, i: bool) -> Self {
|
pub fn stdout_include_time(mut self, i: bool) -> Self {
|
||||||
self.stdout_include_time = i;
|
self.stdout_include_time = i;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_include_time(mut self, i: bool) -> Self {
|
pub fn file_include_time(mut self, i: bool) -> Self {
|
||||||
self.file_include_time = i;
|
self.file_include_time = i;
|
||||||
self
|
self
|
||||||
|
|
|
@ -3,8 +3,6 @@ pub mod query;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use config::LoggerConfig;
|
|
||||||
use query::LogQuery;
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt,
|
fmt,
|
||||||
fs::OpenOptions,
|
fs::OpenOptions,
|
||||||
|
@ -17,6 +15,9 @@ use std::{
|
||||||
thread,
|
thread,
|
||||||
time::SystemTime,
|
time::SystemTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use config::LoggerConfig;
|
||||||
|
use query::LogQuery;
|
||||||
use tracing::{Event, Level, Subscriber};
|
use tracing::{Event, Level, Subscriber};
|
||||||
use tracing_subscriber::{
|
use tracing_subscriber::{
|
||||||
layer::{Context, Layer, SubscriberExt},
|
layer::{Context, Layer, SubscriberExt},
|
||||||
|
@ -161,6 +162,7 @@ impl fmt::Display for LogLevel {
|
||||||
|
|
||||||
impl FromStr for LogLevel {
|
impl FromStr for LogLevel {
|
||||||
type Err = ();
|
type Err = ();
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
match s {
|
match s {
|
||||||
"trace" => Ok(Self::Trace),
|
"trace" => Ok(Self::Trace),
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use super::*;
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use tracing::Level;
|
use tracing::Level;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_logger_sequential_consistency() {
|
fn test_logger_sequential_consistency() {
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
let config = LoggerConfig::default()
|
let config = LoggerConfig::default()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue