init
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
Vendored
+45
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug executable 'toil_and_hardship'",
|
||||||
|
"cargo": {
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"--bin=toil_and_hardship",
|
||||||
|
"--package=toil_and_hardship"
|
||||||
|
],
|
||||||
|
"filter": {
|
||||||
|
"name": "toil_and_hardship",
|
||||||
|
"kind": "bin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug unit tests in executable 'toil_and_hardship'",
|
||||||
|
"cargo": {
|
||||||
|
"args": [
|
||||||
|
"test",
|
||||||
|
"--no-run",
|
||||||
|
"--bin=toil_and_hardship",
|
||||||
|
"--package=toil_and_hardship"
|
||||||
|
],
|
||||||
|
"filter": {
|
||||||
|
"name": "toil_and_hardship",
|
||||||
|
"kind": "bin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Generated
+39
@@ -0,0 +1,39 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cty"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7313c0d620d0cb4dbd9d019e461a4beb501071ff46ec0ab933efb4daa76d73e3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toil_and_hardship"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cty",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
[package]
|
||||||
|
name = "toil_and_hardship"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[features]
|
||||||
|
logger = []
|
||||||
|
fullscreen = []
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
lto = true
|
||||||
|
codegen-units = 1 # should be 1, test diff
|
||||||
|
opt-level = "z" # is this highest
|
||||||
|
panic = 'abort'
|
||||||
|
# rustflags = ["-C", "target-cpu=native", "--emit=obj"] #??? to emit the obj files not sure about first two
|
||||||
|
# rustflags = ["--emit=obj"] #??? to emit the obj files not sure about first two
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
lto = true
|
||||||
|
opt-level = 0
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cty = "*"
|
||||||
|
winapi = { version = "0.3.9", features = ["windef", "wingdi", "winuser", "libloaderapi", "fileapi", "handleapi", "processthreadsapi"] }
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=shaders/shader.vert");
|
||||||
|
println!("cargo:rerun-if-changed=shaders/shader.frag");
|
||||||
|
let out = Command::new("glslc.exe")
|
||||||
|
.args(&["shaders/shader.vert", "-Os", "-o", "shaders/vert.spv"])
|
||||||
|
.output()
|
||||||
|
.expect("failed to execute vert process");
|
||||||
|
println!("{}", String::from_utf8(out.stderr).unwrap());
|
||||||
|
println!("{}", String::from_utf8(out.stdout).unwrap());
|
||||||
|
let out = Command::new("glslc.exe")
|
||||||
|
.args(&["shaders/shader.frag", "-Os", "-o", "shaders/frag.spv"])
|
||||||
|
.output()
|
||||||
|
.expect("failed to execute frag process");
|
||||||
|
println!("{}", String::from_utf8(out.stderr).unwrap());
|
||||||
|
println!("{}", String::from_utf8(out.stdout).unwrap());
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -0,0 +1,72 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
layout(location=0)out vec4 fragColor;
|
||||||
|
|
||||||
|
vec3 logo(vec2 u,float time){
|
||||||
|
mat2 x=mat2(cos(time),sin(time),-sin(time),cos(time));
|
||||||
|
mat2 y=mat2(sin(time),cos(time),-cos(time),sin(time));
|
||||||
|
float l=length(u);
|
||||||
|
|
||||||
|
if(l<.17){
|
||||||
|
return vec3(1.);
|
||||||
|
}else if(l<.22){
|
||||||
|
u=x*u;
|
||||||
|
if(abs(u.y)<.02){
|
||||||
|
return vec3(1.);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
return vec3(.82,.0,.1);
|
||||||
|
}
|
||||||
|
}else if(l<.25){
|
||||||
|
return vec3(1.);
|
||||||
|
}else if(l<.4){
|
||||||
|
u=y*u;
|
||||||
|
if(l>.32){
|
||||||
|
float a=fract((atan(u.y,u.x)/(atan(-1.)*4.)+.5)*3.);
|
||||||
|
if((l>.37)&&(a>.85-(l*2.)&&a<.15+(l*2.))){
|
||||||
|
return vec3(1.);
|
||||||
|
}else if(a>.275-l/2.&&a<.725+l/2.){
|
||||||
|
return vec3(1.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(abs(u.y)<.02){
|
||||||
|
return vec3(1.);
|
||||||
|
}else if(u.y<0.){
|
||||||
|
return vec3(.35,.32,.32);
|
||||||
|
}else{
|
||||||
|
return vec3(.12);
|
||||||
|
}
|
||||||
|
}else if(l<.44){
|
||||||
|
return vec3(1.);
|
||||||
|
}else if(l<.5){
|
||||||
|
return vec3(.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
//flashy colours
|
||||||
|
return vec3((sin(u.y+time*2.)+1.)/2.,(sin(u.x+time*3.)+1.)/2.,(sin(u.y+time*5.)+1.)/2.);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
vec2 iResolution=vec2(1920.,1080.);
|
||||||
|
float iTime=0;
|
||||||
|
// Normalized pixel coordinates (from -0.5 to 0.5 vertically, -AR to AR horizontally)
|
||||||
|
vec2 uv=gl_FragCoord.xy/iResolution.y;
|
||||||
|
uv.x-=iResolution.x/iResolution.y/2.;
|
||||||
|
uv.y-=.5;
|
||||||
|
|
||||||
|
// Antialias
|
||||||
|
float low=1./iResolution.y/2.;;
|
||||||
|
vec3 o=vec3(low,-low,0.);
|
||||||
|
vec3 col=(logo(uv+o.xx,iTime)
|
||||||
|
+logo(uv+o.xy,iTime)
|
||||||
|
+logo(uv+o.yx,iTime)
|
||||||
|
+logo(uv+o.yy,iTime)
|
||||||
|
+logo(uv+o.yz,iTime)
|
||||||
|
+logo(uv+o.zy,iTime)
|
||||||
|
+logo(uv+o.zz,iTime)
|
||||||
|
+logo(uv+o.zx,iTime)
|
||||||
|
+logo(uv+o.xz,iTime))/9.;
|
||||||
|
|
||||||
|
// Output to screen
|
||||||
|
fragColor=vec4(col,1.);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#version 450
|
||||||
|
|
||||||
|
vec2 positions[3]=vec2[](
|
||||||
|
vec2(-1.,-1.),
|
||||||
|
vec2(3.,-1.),
|
||||||
|
vec2(-1.,3.)
|
||||||
|
);
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
gl_Position=vec4(positions[gl_VertexIndex],0.,1.);
|
||||||
|
}
|
||||||
Binary file not shown.
+798
@@ -0,0 +1,798 @@
|
|||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
#![windows_subsystem = "windows"]
|
||||||
|
#![feature(maybe_uninit_uninit_array)]
|
||||||
|
#![feature(maybe_uninit_slice)]
|
||||||
|
|
||||||
|
mod miniwin;
|
||||||
|
mod util;
|
||||||
|
mod vk;
|
||||||
|
use miniwin::handle_message;
|
||||||
|
use vk::*;
|
||||||
|
use winapi::shared::windef::HWND;
|
||||||
|
use winapi::um::libloaderapi::GetModuleHandleA;
|
||||||
|
|
||||||
|
use core::{ffi::c_void, mem::MaybeUninit, panic::PanicInfo, ptr};
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn panic(_info: &PanicInfo) -> ! {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEVICE_FEATURES: PhysicalDeviceFeatures = PhysicalDeviceFeatures {
|
||||||
|
robustBufferAccess: FALSE,
|
||||||
|
fullDrawIndexUint32: FALSE,
|
||||||
|
imageCubeArray: FALSE,
|
||||||
|
independentBlend: FALSE,
|
||||||
|
geometryShader: FALSE,
|
||||||
|
tessellationShader: FALSE,
|
||||||
|
sampleRateShading: FALSE,
|
||||||
|
dualSrcBlend: FALSE,
|
||||||
|
logicOp: FALSE,
|
||||||
|
multiDrawIndirect: FALSE,
|
||||||
|
drawIndirectFirstInstance: FALSE,
|
||||||
|
depthClamp: FALSE,
|
||||||
|
depthBiasClamp: FALSE,
|
||||||
|
fillModeNonSolid: FALSE,
|
||||||
|
depthBounds: FALSE,
|
||||||
|
wideLines: FALSE,
|
||||||
|
largePoints: FALSE,
|
||||||
|
alphaToOne: FALSE,
|
||||||
|
multiViewport: FALSE,
|
||||||
|
samplerAnisotropy: FALSE,
|
||||||
|
textureCompressionETC2: FALSE,
|
||||||
|
textureCompressionASTC_LDR: FALSE,
|
||||||
|
textureCompressionBC: FALSE,
|
||||||
|
occlusionQueryPrecise: FALSE,
|
||||||
|
pipelineStatisticsQuery: FALSE,
|
||||||
|
vertexPipelineStoresAndAtomics: FALSE,
|
||||||
|
fragmentStoresAndAtomics: FALSE,
|
||||||
|
shaderTessellationAndGeometryPointSize: FALSE,
|
||||||
|
shaderImageGatherExtended: FALSE,
|
||||||
|
shaderStorageImageExtendedFormats: FALSE,
|
||||||
|
shaderStorageImageMultisample: FALSE,
|
||||||
|
shaderStorageImageReadWithoutFormat: FALSE,
|
||||||
|
shaderStorageImageWriteWithoutFormat: FALSE,
|
||||||
|
shaderUniformBufferArrayDynamicIndexing: FALSE,
|
||||||
|
shaderSampledImageArrayDynamicIndexing: FALSE,
|
||||||
|
shaderStorageBufferArrayDynamicIndexing: FALSE,
|
||||||
|
shaderStorageImageArrayDynamicIndexing: FALSE,
|
||||||
|
shaderClipDistance: FALSE,
|
||||||
|
shaderCullDistance: FALSE,
|
||||||
|
shaderFloat64: FALSE,
|
||||||
|
shaderInt64: FALSE,
|
||||||
|
shaderInt16: FALSE,
|
||||||
|
shaderResourceResidency: FALSE,
|
||||||
|
shaderResourceMinLod: FALSE,
|
||||||
|
sparseBinding: FALSE,
|
||||||
|
sparseResidencyBuffer: FALSE,
|
||||||
|
sparseResidencyImage2D: FALSE,
|
||||||
|
sparseResidencyImage3D: FALSE,
|
||||||
|
sparseResidency2Samples: FALSE,
|
||||||
|
sparseResidency4Samples: FALSE,
|
||||||
|
sparseResidency8Samples: FALSE,
|
||||||
|
sparseResidency16Samples: FALSE,
|
||||||
|
sparseResidencyAliased: FALSE,
|
||||||
|
variableMultisampleRate: FALSE,
|
||||||
|
inheritedQueries: FALSE,
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! create_shader_module {
|
||||||
|
($s:expr, $ps:ident, $device:ident) => {{
|
||||||
|
let shader = include_bytes!($s);
|
||||||
|
let create_info = ShaderModuleCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
||||||
|
codeSize: shader.len(),
|
||||||
|
pCode: shader.as_ptr() as *const u32,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
let mut shader = MaybeUninit::uninit();
|
||||||
|
$ps.CreateShaderModule($device, &create_info, ptr::null(), shader.as_mut_ptr());
|
||||||
|
shader.assume_init()
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_vulkan(window: HWND, ps: &Static) {
|
||||||
|
let instance = create_instance(ps);
|
||||||
|
let surface = create_surface(ps, window, instance);
|
||||||
|
let physical_device = pick_physical_device(ps, instance);
|
||||||
|
let (device, queue) = create_logical_device(ps, physical_device);
|
||||||
|
let (swapchain, image) = create_swapchain(ps, device, surface);
|
||||||
|
let image_view = create_image_view(ps, device, image);
|
||||||
|
let render_pass = create_render_pass(ps, device);
|
||||||
|
let pipeline = create_graphics_pipeline(ps, device, render_pass);
|
||||||
|
let framebuffer = create_framebuffers(ps, device, image_view, render_pass);
|
||||||
|
let command_pool = create_command_pool(ps, device);
|
||||||
|
let command_buffer =
|
||||||
|
create_command_buffers(ps, device, command_pool, pipeline, render_pass, framebuffer);
|
||||||
|
let (available, rendered, fence) = create_sync_objects(ps, device);
|
||||||
|
draw_frame(
|
||||||
|
ps,
|
||||||
|
device,
|
||||||
|
swapchain,
|
||||||
|
command_buffer,
|
||||||
|
queue,
|
||||||
|
fence,
|
||||||
|
available,
|
||||||
|
rendered,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_instance(ps: &Static) -> Instance {
|
||||||
|
const APP_INFO: ApplicationInfo = ApplicationInfo {
|
||||||
|
sType: STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
|
pApplicationName: "\0".as_ptr() as *const i8,
|
||||||
|
applicationVersion: 0,
|
||||||
|
pEngineName: "\0".as_ptr() as *const i8,
|
||||||
|
engineVersion: 0,
|
||||||
|
apiVersion: 0b_000_0000001_0000000010_000000000000,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const EXTENSIONS: [*const i8; 2] = [
|
||||||
|
"VK_KHR_surface\0".as_ptr() as *const i8,
|
||||||
|
"VK_KHR_win32_surface\0".as_ptr() as *const i8,
|
||||||
|
];
|
||||||
|
|
||||||
|
const CREATE_INFO: InstanceCreateInfo = InstanceCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
|
pApplicationInfo: &APP_INFO,
|
||||||
|
enabledExtensionCount: EXTENSIONS.len() as u32,
|
||||||
|
ppEnabledExtensionNames: EXTENSIONS.as_ptr(),
|
||||||
|
enabledLayerCount: 0,
|
||||||
|
ppEnabledLayerNames: ptr::null(),
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut instance = MaybeUninit::uninit();
|
||||||
|
unsafe {
|
||||||
|
ps.CreateInstance(&CREATE_INFO, ptr::null(), instance.as_mut_ptr());
|
||||||
|
instance.assume_init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_surface(ps: &Static, hwnd: HWND, instance: Instance) -> SurfaceKHR {
|
||||||
|
let create_info = Win32SurfaceCreateInfoKHR {
|
||||||
|
sType: STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
|
||||||
|
hwnd: (hwnd as *mut _ as *mut c_void),
|
||||||
|
hinstance: unsafe { GetModuleHandleA(ptr::null()) as *mut _ as *mut c_void },
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut surface = MaybeUninit::uninit();
|
||||||
|
unsafe {
|
||||||
|
ps.CreateWin32SurfaceKHR(instance, &create_info, ptr::null(), surface.as_mut_ptr());
|
||||||
|
surface.assume_init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pick_physical_device(ps: &Static, instance: Instance) -> PhysicalDevice {
|
||||||
|
//bounds checks are for losers, just don't plug in more than 8 gpus ok
|
||||||
|
let mut devices: [MaybeUninit<PhysicalDevice>; 8] = MaybeUninit::uninit_array();
|
||||||
|
let mut _count = MaybeUninit::uninit();
|
||||||
|
unsafe {
|
||||||
|
ps.EnumeratePhysicalDevices(
|
||||||
|
instance,
|
||||||
|
_count.as_mut_ptr(),
|
||||||
|
devices.as_mut_ptr() as *mut PhysicalDevice,
|
||||||
|
);
|
||||||
|
devices[0].assume_init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_logical_device(ps: &Static, physical_device: PhysicalDevice) -> (Device, Queue) {
|
||||||
|
// Here we take all infos to be const values. We can do this because most
|
||||||
|
// vendor cards will provide family 0 as graphics and present, and so
|
||||||
|
// this code assumes as such.
|
||||||
|
const QUEUE_CREATE_INFO: DeviceQueueCreateInfo = DeviceQueueCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||||
|
queueFamilyIndex: 0,
|
||||||
|
queueCount: 1,
|
||||||
|
pQueuePriorities: &1.0,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
const DEVICE_EXTENSIONS: [*const i8; 1] = ["VK_KHR_swapchain\0".as_ptr() as *const i8];
|
||||||
|
const CREATE_INFO: DeviceCreateInfo = DeviceCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
|
pQueueCreateInfos: &QUEUE_CREATE_INFO,
|
||||||
|
queueCreateInfoCount: 1,
|
||||||
|
enabledLayerCount: 0,
|
||||||
|
ppEnabledLayerNames: ptr::null(),
|
||||||
|
ppEnabledExtensionNames: DEVICE_EXTENSIONS.as_ptr(),
|
||||||
|
enabledExtensionCount: DEVICE_EXTENSIONS.len() as u32,
|
||||||
|
pEnabledFeatures: &DEVICE_FEATURES,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
let mut device = MaybeUninit::uninit();
|
||||||
|
let mut queue = MaybeUninit::uninit();
|
||||||
|
let device = unsafe {
|
||||||
|
ps.CreateDevice(
|
||||||
|
physical_device,
|
||||||
|
&CREATE_INFO,
|
||||||
|
ptr::null(),
|
||||||
|
device.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
device.assume_init()
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
ps.GetDeviceQueue(device, 0, 0, queue.as_mut_ptr());
|
||||||
|
}
|
||||||
|
unsafe { (device, queue.assume_init()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_swapchain(ps: &Static, device: Device, surface: SurfaceKHR) -> (SwapchainKHR, Image) {
|
||||||
|
let create_info;
|
||||||
|
const CREATE_INFO: SwapchainCreateInfoKHR = SwapchainCreateInfoKHR {
|
||||||
|
sType: STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||||
|
surface: 0,
|
||||||
|
minImageCount: 1,
|
||||||
|
imageFormat: FORMAT_R8G8B8A8_SRGB,
|
||||||
|
imageColorSpace: COLOR_SPACE_SRGB_NONLINEAR_KHR,
|
||||||
|
imageExtent: Extent2D {
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
},
|
||||||
|
presentMode: PRESENT_MODE_IMMEDIATE_KHR,
|
||||||
|
imageArrayLayers: 1,
|
||||||
|
imageUsage: IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||||
|
imageSharingMode: SHARING_MODE_EXCLUSIVE,
|
||||||
|
queueFamilyIndexCount: 1,
|
||||||
|
pQueueFamilyIndices: &0,
|
||||||
|
preTransform: SURFACE_TRANSFORM_IDENTITY_BIT_KHR,
|
||||||
|
compositeAlpha: COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
||||||
|
clipped: TRUE,
|
||||||
|
oldSwapchain: NULL_HANDLE,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
let mut create_info_i = CREATE_INFO;
|
||||||
|
create_info_i.surface = surface;
|
||||||
|
create_info = create_info_i;
|
||||||
|
let swapchain: SwapchainKHR = unsafe {
|
||||||
|
let mut swapchain = MaybeUninit::uninit();
|
||||||
|
ps.CreateSwapchainKHR(device, &create_info, ptr::null(), swapchain.as_mut_ptr());
|
||||||
|
swapchain.assume_init()
|
||||||
|
};
|
||||||
|
let image: Image = unsafe {
|
||||||
|
let mut image = MaybeUninit::uninit();
|
||||||
|
let mut count = MaybeUninit::uninit();
|
||||||
|
ps.GetSwapchainImagesKHR(device, swapchain, count.as_mut_ptr(), image.as_mut_ptr());
|
||||||
|
//let count = count.assume_init();
|
||||||
|
//if count > 1 {
|
||||||
|
// show_error("Count is greater than one\0".as_ptr() as *const i8);
|
||||||
|
//}
|
||||||
|
image.assume_init()
|
||||||
|
};
|
||||||
|
(swapchain, image)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_image_view(ps: &Static, device: Device, image: Image) -> ImageView {
|
||||||
|
let create_info;
|
||||||
|
{
|
||||||
|
const CREATE_INFO: ImageViewCreateInfo = ImageViewCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||||
|
image: 0,
|
||||||
|
viewType: IMAGE_VIEW_TYPE_2D,
|
||||||
|
format: FORMAT_R8G8B8A8_SRGB,
|
||||||
|
components: ComponentMapping {
|
||||||
|
r: COMPONENT_SWIZZLE_IDENTITY,
|
||||||
|
g: COMPONENT_SWIZZLE_IDENTITY,
|
||||||
|
b: COMPONENT_SWIZZLE_IDENTITY,
|
||||||
|
a: COMPONENT_SWIZZLE_IDENTITY,
|
||||||
|
},
|
||||||
|
subresourceRange: ImageSubresourceRange {
|
||||||
|
aspectMask: IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
baseMipLevel: 0,
|
||||||
|
levelCount: 1,
|
||||||
|
baseArrayLayer: 0,
|
||||||
|
layerCount: 1,
|
||||||
|
},
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
let mut create_info_i = CREATE_INFO;
|
||||||
|
create_info_i.image = image;
|
||||||
|
create_info = create_info_i;
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
let mut image_view = MaybeUninit::uninit();
|
||||||
|
ps.CreateImageView(device, &create_info, ptr::null(), image_view.as_mut_ptr());
|
||||||
|
image_view.assume_init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_render_pass(ps: &Static, device: Device) -> RenderPass {
|
||||||
|
const COLOR_ATTACHMENT: AttachmentDescription = AttachmentDescription {
|
||||||
|
format: FORMAT_R8G8B8A8_SRGB,
|
||||||
|
samples: SAMPLE_COUNT_1_BIT,
|
||||||
|
loadOp: ATTACHMENT_LOAD_OP_CLEAR,
|
||||||
|
storeOp: ATTACHMENT_STORE_OP_STORE,
|
||||||
|
stencilLoadOp: ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||||
|
stencilStoreOp: ATTACHMENT_STORE_OP_DONT_CARE,
|
||||||
|
initialLayout: IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
finalLayout: IMAGE_LAYOUT_PRESENT_SRC_KHR,
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
const COLOR_ATTACHMENT_REF: AttachmentReference = AttachmentReference {
|
||||||
|
attachment: 0,
|
||||||
|
layout: IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
};
|
||||||
|
const SUBPASS: SubpassDescription = SubpassDescription {
|
||||||
|
pipelineBindPoint: PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
colorAttachmentCount: 1,
|
||||||
|
pColorAttachments: &COLOR_ATTACHMENT_REF,
|
||||||
|
inputAttachmentCount: 0,
|
||||||
|
pInputAttachments: ptr::null(),
|
||||||
|
preserveAttachmentCount: 0,
|
||||||
|
pPreserveAttachments: ptr::null(),
|
||||||
|
pResolveAttachments: ptr::null(),
|
||||||
|
pDepthStencilAttachment: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
const DEPENDENCY: SubpassDependency = SubpassDependency {
|
||||||
|
srcSubpass: SUBPASS_EXTERNAL,
|
||||||
|
dstSubpass: 0,
|
||||||
|
srcStageMask: PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
srcAccessMask: 0,
|
||||||
|
dstStageMask: PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
dstAccessMask: ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
|
dependencyFlags: 0,
|
||||||
|
};
|
||||||
|
const RENDER_PASS_INFO: RenderPassCreateInfo = RenderPassCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
||||||
|
attachmentCount: 1,
|
||||||
|
pAttachments: &COLOR_ATTACHMENT,
|
||||||
|
subpassCount: 1,
|
||||||
|
pSubpasses: &SUBPASS,
|
||||||
|
dependencyCount: 1,
|
||||||
|
pDependencies: &DEPENDENCY,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
let mut render_pass = MaybeUninit::uninit();
|
||||||
|
ps.CreateRenderPass(
|
||||||
|
device,
|
||||||
|
&RENDER_PASS_INFO,
|
||||||
|
ptr::null(),
|
||||||
|
render_pass.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
render_pass.assume_init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_graphics_pipeline(ps: &Static, device: Device, render_pass: RenderPass) -> Pipeline {
|
||||||
|
let vert_shader_module = create_shader_module!("../shaders/vert.spv", ps, device);
|
||||||
|
let frag_shader_module = create_shader_module!("../shaders/frag.spv", ps, device);
|
||||||
|
|
||||||
|
const STAGE_INFO: PipelineShaderStageCreateInfo = PipelineShaderStageCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
||||||
|
stage: SHADER_STAGE_VERTEX_BIT,
|
||||||
|
module: 0,
|
||||||
|
pName: "main\0".as_ptr() as *const i8,
|
||||||
|
pSpecializationInfo: ptr::null(),
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut vert_shader_stage_info = STAGE_INFO;
|
||||||
|
vert_shader_stage_info.module = vert_shader_module;
|
||||||
|
let vert_shader_stage_info = vert_shader_stage_info;
|
||||||
|
|
||||||
|
let mut frag_shader_stage_info = STAGE_INFO;
|
||||||
|
frag_shader_stage_info.module = frag_shader_module;
|
||||||
|
frag_shader_stage_info.stage = SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
let frag_shader_stage_info = frag_shader_stage_info;
|
||||||
|
|
||||||
|
let shader_stages = [vert_shader_stage_info, frag_shader_stage_info];
|
||||||
|
|
||||||
|
const VERTEX_INPUT_INFO: PipelineVertexInputStateCreateInfo =
|
||||||
|
PipelineVertexInputStateCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
|
vertexBindingDescriptionCount: 0,
|
||||||
|
vertexAttributeDescriptionCount: 0,
|
||||||
|
pVertexBindingDescriptions: ptr::null(),
|
||||||
|
pVertexAttributeDescriptions: ptr::null(),
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
const INPUT_ASSEMBLY: PipelineInputAssemblyStateCreateInfo =
|
||||||
|
PipelineInputAssemblyStateCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||||
|
topology: PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||||
|
primitiveRestartEnable: FALSE,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
const VIEWPORT: Viewport = Viewport {
|
||||||
|
x: 0f32,
|
||||||
|
y: 0f32,
|
||||||
|
width: 1920f32,
|
||||||
|
height: 1080f32,
|
||||||
|
minDepth: 0f32,
|
||||||
|
maxDepth: 1f32,
|
||||||
|
};
|
||||||
|
const SCISSOR: Rect2D = Rect2D {
|
||||||
|
offset: Offset2D { x: 0, y: 0 },
|
||||||
|
extent: Extent2D {
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const VIEWPORT_STATE: PipelineViewportStateCreateInfo = PipelineViewportStateCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
|
viewportCount: 1,
|
||||||
|
pViewports: &VIEWPORT,
|
||||||
|
scissorCount: 1,
|
||||||
|
pScissors: &SCISSOR,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
const RASTERISER: PipelineRasterizationStateCreateInfo = PipelineRasterizationStateCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
depthClampEnable: FALSE,
|
||||||
|
depthBiasEnable: FALSE,
|
||||||
|
depthBiasClamp: unsafe { core::mem::transmute(0u32) },
|
||||||
|
depthBiasConstantFactor: unsafe { core::mem::transmute(0u32) },
|
||||||
|
depthBiasSlopeFactor: unsafe { core::mem::transmute(0u32) },
|
||||||
|
rasterizerDiscardEnable: FALSE,
|
||||||
|
polygonMode: POLYGON_MODE_FILL,
|
||||||
|
lineWidth: 1f32,
|
||||||
|
cullMode: CULL_MODE_BACK_BIT,
|
||||||
|
frontFace: FRONT_FACE_CLOCKWISE,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
const MULTISAMPLING: PipelineMultisampleStateCreateInfo = PipelineMultisampleStateCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
||||||
|
sampleShadingEnable: FALSE,
|
||||||
|
rasterizationSamples: SAMPLE_COUNT_1_BIT,
|
||||||
|
minSampleShading: unsafe { core::mem::transmute(0u32) },
|
||||||
|
alphaToCoverageEnable: FALSE,
|
||||||
|
alphaToOneEnable: FALSE,
|
||||||
|
pSampleMask: ptr::null(),
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
const COLOR_BLEND_ATTACHMENT: PipelineColorBlendAttachmentState =
|
||||||
|
PipelineColorBlendAttachmentState {
|
||||||
|
colorWriteMask: COLOR_COMPONENT_R_BIT
|
||||||
|
| COLOR_COMPONENT_G_BIT
|
||||||
|
| COLOR_COMPONENT_B_BIT
|
||||||
|
| COLOR_COMPONENT_A_BIT,
|
||||||
|
blendEnable: FALSE,
|
||||||
|
colorBlendOp: FALSE,
|
||||||
|
dstColorBlendFactor: FALSE,
|
||||||
|
srcColorBlendFactor: FALSE,
|
||||||
|
alphaBlendOp: FALSE,
|
||||||
|
dstAlphaBlendFactor: FALSE,
|
||||||
|
srcAlphaBlendFactor: FALSE,
|
||||||
|
};
|
||||||
|
const COLOR_BLENDING: PipelineColorBlendStateCreateInfo = PipelineColorBlendStateCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
||||||
|
logicOpEnable: FALSE,
|
||||||
|
logicOp: LOGIC_OP_COPY,
|
||||||
|
attachmentCount: 1,
|
||||||
|
pAttachments: &COLOR_BLEND_ATTACHMENT,
|
||||||
|
blendConstants: [0f32, 0f32, 0f32, 0f32],
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
const PIPELINE_LAYOUT_INFO: PipelineLayoutCreateInfo = PipelineLayoutCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||||
|
setLayoutCount: 0,
|
||||||
|
pushConstantRangeCount: 0,
|
||||||
|
pPushConstantRanges: ptr::null(),
|
||||||
|
pSetLayouts: ptr::null(),
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
let pipeline_layout = unsafe {
|
||||||
|
let mut pipeline_layout = MaybeUninit::uninit();
|
||||||
|
ps.CreatePipelineLayout(
|
||||||
|
device,
|
||||||
|
&PIPELINE_LAYOUT_INFO,
|
||||||
|
ptr::null(),
|
||||||
|
pipeline_layout.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
pipeline_layout.assume_init()
|
||||||
|
};
|
||||||
|
const PIPELINE_INFO: GraphicsPipelineCreateInfo = GraphicsPipelineCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
|
stageCount: 2,
|
||||||
|
pStages: ptr::null(),
|
||||||
|
pVertexInputState: &VERTEX_INPUT_INFO,
|
||||||
|
pInputAssemblyState: &INPUT_ASSEMBLY,
|
||||||
|
pViewportState: &VIEWPORT_STATE,
|
||||||
|
pRasterizationState: &RASTERISER,
|
||||||
|
pMultisampleState: &MULTISAMPLING,
|
||||||
|
pColorBlendState: &COLOR_BLENDING,
|
||||||
|
layout: 0,
|
||||||
|
renderPass: 0,
|
||||||
|
subpass: 0,
|
||||||
|
basePipelineHandle: NULL_HANDLE,
|
||||||
|
basePipelineIndex: 0,
|
||||||
|
pDepthStencilState: ptr::null(),
|
||||||
|
pDynamicState: ptr::null(),
|
||||||
|
pTessellationState: ptr::null(),
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
let mut pipeline_info = PIPELINE_INFO;
|
||||||
|
pipeline_info.pStages = shader_stages.as_ptr();
|
||||||
|
pipeline_info.layout = pipeline_layout;
|
||||||
|
pipeline_info.renderPass = render_pass;
|
||||||
|
let pipeline_info = pipeline_info;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mut pipeline = MaybeUninit::uninit();
|
||||||
|
ps.CreateGraphicsPipelines(
|
||||||
|
device,
|
||||||
|
NULL_HANDLE,
|
||||||
|
1,
|
||||||
|
&pipeline_info,
|
||||||
|
ptr::null(),
|
||||||
|
pipeline.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
pipeline.assume_init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_framebuffers(
|
||||||
|
ps: &Static,
|
||||||
|
device: Device,
|
||||||
|
image_view: ImageView,
|
||||||
|
render_pass: RenderPass,
|
||||||
|
) -> Framebuffer {
|
||||||
|
const FRAMEBUFFER_INFO: FramebufferCreateInfo = FramebufferCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||||
|
renderPass: NULL_HANDLE,
|
||||||
|
attachmentCount: 1,
|
||||||
|
pAttachments: ptr::null(),
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
layers: 1,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
let mut framebuffer_info = FRAMEBUFFER_INFO;
|
||||||
|
framebuffer_info.pAttachments = &image_view;
|
||||||
|
framebuffer_info.renderPass = render_pass;
|
||||||
|
let framebuffer_info = framebuffer_info;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mut framebuffer = MaybeUninit::uninit();
|
||||||
|
ps.CreateFramebuffer(
|
||||||
|
device,
|
||||||
|
&framebuffer_info,
|
||||||
|
ptr::null(),
|
||||||
|
framebuffer.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
framebuffer.assume_init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_command_pool(ps: &Static, device: Device) -> CommandPool {
|
||||||
|
const POOL_INFO: CommandPoolCreateInfo = CommandPoolCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
|
queueFamilyIndex: 0,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
let mut command_pool = MaybeUninit::uninit();
|
||||||
|
ps.CreateCommandPool(device, &POOL_INFO, ptr::null(), command_pool.as_mut_ptr());
|
||||||
|
command_pool.assume_init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_command_buffers(
|
||||||
|
ps: &Static,
|
||||||
|
device: Device,
|
||||||
|
command_pool: CommandPool,
|
||||||
|
graphics_pipeline: Pipeline,
|
||||||
|
render_pass: RenderPass,
|
||||||
|
framebuffer: Framebuffer,
|
||||||
|
) -> CommandBuffer {
|
||||||
|
const ALLOC_INFO: CommandBufferAllocateInfo = CommandBufferAllocateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
|
commandPool: NULL_HANDLE,
|
||||||
|
level: COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||||
|
commandBufferCount: 1,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
};
|
||||||
|
let mut alloc_info = ALLOC_INFO;
|
||||||
|
alloc_info.commandPool = command_pool;
|
||||||
|
let alloc_info = alloc_info;
|
||||||
|
|
||||||
|
let command_buffer = unsafe {
|
||||||
|
let mut command_buffer = MaybeUninit::uninit();
|
||||||
|
ps.AllocateCommandBuffers(device, &alloc_info, command_buffer.as_mut_ptr());
|
||||||
|
command_buffer.assume_init()
|
||||||
|
};
|
||||||
|
|
||||||
|
const BEGIN_INFO: CommandBufferBeginInfo = CommandBufferBeginInfo {
|
||||||
|
sType: STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
pInheritanceInfo: ptr::null(),
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ps.BeginCommandBuffer(command_buffer, &BEGIN_INFO);
|
||||||
|
}
|
||||||
|
const RENDER_PASS_INFO: RenderPassBeginInfo = RenderPassBeginInfo {
|
||||||
|
sType: STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
|
renderPass: NULL_HANDLE,
|
||||||
|
framebuffer: NULL_HANDLE,
|
||||||
|
renderArea: Rect2D {
|
||||||
|
offset: Offset2D { x: 0, y: 0 },
|
||||||
|
extent: Extent2D {
|
||||||
|
width: 1920,
|
||||||
|
height: 1080,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pClearValues: &ClearValue {
|
||||||
|
color: ClearColorValue {
|
||||||
|
float32: [0f32, 0f32, 0f32, 1f32],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
clearValueCount: 1,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
};
|
||||||
|
let mut render_pass_info = RENDER_PASS_INFO;
|
||||||
|
render_pass_info.renderPass = render_pass;
|
||||||
|
render_pass_info.framebuffer = framebuffer;
|
||||||
|
let render_pass_info = render_pass_info;
|
||||||
|
unsafe {
|
||||||
|
ps.CmdBeginRenderPass(command_buffer, &render_pass_info, SUBPASS_CONTENTS_INLINE);
|
||||||
|
ps.CmdBindPipeline(
|
||||||
|
command_buffer,
|
||||||
|
PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
graphics_pipeline,
|
||||||
|
);
|
||||||
|
ps.CmdDraw(command_buffer, 3, 1, 0, 0);
|
||||||
|
ps.CmdEndRenderPass(command_buffer);
|
||||||
|
ps.EndCommandBuffer(command_buffer);
|
||||||
|
}
|
||||||
|
command_buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_sync_objects(ps: &Static, device: Device) -> (Semaphore, Semaphore, Fence) {
|
||||||
|
const SEMAPHORE_INFO: SemaphoreCreateInfo = SemaphoreCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
const FENCE_INFO: FenceCreateInfo = FenceCreateInfo {
|
||||||
|
sType: STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
flags: FENCE_CREATE_SIGNALED_BIT,
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
let mut available_semaphore = MaybeUninit::uninit();
|
||||||
|
let mut rendered_semaphore = MaybeUninit::uninit();
|
||||||
|
let mut in_flight_fence = MaybeUninit::uninit();
|
||||||
|
ps.CreateSemaphore(
|
||||||
|
device,
|
||||||
|
&SEMAPHORE_INFO,
|
||||||
|
ptr::null(),
|
||||||
|
available_semaphore.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
ps.CreateSemaphore(
|
||||||
|
device,
|
||||||
|
&SEMAPHORE_INFO,
|
||||||
|
ptr::null(),
|
||||||
|
rendered_semaphore.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
ps.CreateFence(
|
||||||
|
device,
|
||||||
|
&FENCE_INFO,
|
||||||
|
ptr::null(),
|
||||||
|
in_flight_fence.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
(
|
||||||
|
available_semaphore.assume_init(),
|
||||||
|
rendered_semaphore.assume_init(),
|
||||||
|
in_flight_fence.assume_init(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_frame(
|
||||||
|
ps: &Static,
|
||||||
|
device: Device,
|
||||||
|
swapchain: SwapchainKHR,
|
||||||
|
command_buffer: CommandBuffer,
|
||||||
|
queue: Queue,
|
||||||
|
fence: Fence,
|
||||||
|
available_semaphore: Semaphore,
|
||||||
|
rendered_semaphore: Semaphore,
|
||||||
|
) -> () {
|
||||||
|
unsafe {
|
||||||
|
ps.WaitForFences(device, 1, &fence, TRUE, u64::MAX);
|
||||||
|
}
|
||||||
|
let image_index = unsafe {
|
||||||
|
let mut image_index = MaybeUninit::uninit();
|
||||||
|
ps.AcquireNextImageKHR(
|
||||||
|
device,
|
||||||
|
swapchain,
|
||||||
|
u64::MAX,
|
||||||
|
available_semaphore,
|
||||||
|
NULL_HANDLE,
|
||||||
|
image_index.as_mut_ptr(),
|
||||||
|
);
|
||||||
|
image_index.assume_init()
|
||||||
|
};
|
||||||
|
const SUBMIT_INFO: SubmitInfo = SubmitInfo {
|
||||||
|
sType: STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
|
waitSemaphoreCount: 1,
|
||||||
|
pWaitSemaphores: ptr::null(),
|
||||||
|
pWaitDstStageMask: &PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
|
commandBufferCount: 1,
|
||||||
|
pCommandBuffers: ptr::null(),
|
||||||
|
signalSemaphoreCount: 1,
|
||||||
|
pSignalSemaphores: ptr::null(),
|
||||||
|
pNext: ptr::null(),
|
||||||
|
};
|
||||||
|
let mut submit_info = SUBMIT_INFO;
|
||||||
|
submit_info.pWaitSemaphores = &available_semaphore;
|
||||||
|
submit_info.pSignalSemaphores = &rendered_semaphore;
|
||||||
|
submit_info.pCommandBuffers = &command_buffer;
|
||||||
|
let submit_info = submit_info;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ps.QueueSubmit(queue, 1, &submit_info, fence);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result = MaybeUninit::uninit();
|
||||||
|
let present_info: PresentInfoKHR = PresentInfoKHR {
|
||||||
|
sType: STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
|
waitSemaphoreCount: 1,
|
||||||
|
pWaitSemaphores: &rendered_semaphore,
|
||||||
|
swapchainCount: 1,
|
||||||
|
pSwapchains: &swapchain,
|
||||||
|
pImageIndices: &image_index,
|
||||||
|
pNext: ptr::null(),
|
||||||
|
pResults: result.as_mut_ptr(),
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
ps.QueuePresentKHR(queue, &present_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "system" fn mainCRTStartup() {
|
||||||
|
let pointers = init();
|
||||||
|
let (window, _hdc) = miniwin::create_window();
|
||||||
|
init_vulkan(window, &pointers);
|
||||||
|
loop {
|
||||||
|
{
|
||||||
|
if !handle_message(window) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if winapi::um::winuser::GetAsyncKeyState(winapi::um::winuser::VK_ESCAPE) != 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// Tying to exit normally seems to crash after certain APIs functions have been called. ( Like ChoosePixelFormat )
|
||||||
|
winapi::um::processthreadsapi::ExitProcess(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub static _fltused: i32 = 1;
|
||||||
+237
@@ -0,0 +1,237 @@
|
|||||||
|
#[cfg(windows)]
|
||||||
|
extern crate winapi;
|
||||||
|
|
||||||
|
use core::cmp::Ordering;
|
||||||
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
use winapi::um::wingdi::{
|
||||||
|
wglCreateContext, wglMakeCurrent, ChoosePixelFormat, SetPixelFormat, SwapBuffers, DEVMODEA,
|
||||||
|
PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
use winapi::shared::minwindef::{HINSTANCE, LPARAM, LPVOID, LRESULT, UINT, WPARAM};
|
||||||
|
|
||||||
|
use winapi::shared::windef::{HBRUSH, HDC, HGLRC, HICON, HMENU, HWND};
|
||||||
|
|
||||||
|
use winapi::um::libloaderapi::GetModuleHandleA;
|
||||||
|
|
||||||
|
use winapi::um::winuser::{
|
||||||
|
CreateWindowExA, DefWindowProcA, DispatchMessageA, GetDC, MessageBoxA, PeekMessageA,
|
||||||
|
PostQuitMessage, RegisterClassA, TranslateMessage, CS_HREDRAW, CS_OWNDC, CS_VREDRAW,
|
||||||
|
CW_USEDEFAULT, MB_ICONERROR, MSG, PM_REMOVE, WNDCLASSA, WS_MAXIMIZE, WS_OVERLAPPEDWINDOW,
|
||||||
|
WS_POPUP, WS_VISIBLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub unsafe extern "system" fn window_proc(
|
||||||
|
hwnd: HWND,
|
||||||
|
msg: UINT,
|
||||||
|
w_param: WPARAM,
|
||||||
|
l_param: LPARAM,
|
||||||
|
) -> LRESULT {
|
||||||
|
match msg {
|
||||||
|
winapi::um::winuser::WM_DESTROY => {
|
||||||
|
PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return DefWindowProcA(hwnd, msg, w_param, l_param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
pub fn show_error(message: *const i8) {
|
||||||
|
unsafe {
|
||||||
|
MessageBoxA(
|
||||||
|
0 as HWND,
|
||||||
|
message,
|
||||||
|
"Window::create\0".as_ptr() as *const i8,
|
||||||
|
MB_ICONERROR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_window() -> (HWND, HDC) {
|
||||||
|
unsafe {
|
||||||
|
let h_wnd: HWND;
|
||||||
|
|
||||||
|
#[cfg(feature = "fullscreen")]
|
||||||
|
{
|
||||||
|
let mut dev_mode: DEVMODEA = core::mem::zeroed();
|
||||||
|
dev_mode.dmSize = core::mem::size_of::<DEVMODEA>() as u16;
|
||||||
|
dev_mode.dmFields = winapi::um::wingdi::DM_BITSPERPEL
|
||||||
|
| winapi::um::wingdi::DM_PELSWIDTH
|
||||||
|
| winapi::um::wingdi::DM_PELSHEIGHT;
|
||||||
|
dev_mode.dmBitsPerPel = 32;
|
||||||
|
dev_mode.dmPelsWidth = 1920;
|
||||||
|
dev_mode.dmPelsHeight = 1080;
|
||||||
|
if winapi::um::winuser::ChangeDisplaySettingsA(
|
||||||
|
&mut dev_mode,
|
||||||
|
winapi::um::winuser::CDS_FULLSCREEN,
|
||||||
|
) != winapi::um::winuser::DISP_CHANGE_SUCCESSFUL
|
||||||
|
{
|
||||||
|
return (0 as HWND, 0 as HDC);
|
||||||
|
}
|
||||||
|
winapi::um::winuser::ShowCursor(0);
|
||||||
|
|
||||||
|
h_wnd = CreateWindowExA(
|
||||||
|
0,
|
||||||
|
"static\0".as_ptr() as *const i8, // class we registered.
|
||||||
|
"GLWIN\0".as_ptr() as *const i8, // title
|
||||||
|
WS_POPUP | WS_VISIBLE | WS_MAXIMIZE,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0, // size and position
|
||||||
|
0 as HWND, // hWndParent
|
||||||
|
0 as HMENU, // hMenu
|
||||||
|
0 as HINSTANCE, // hInstance
|
||||||
|
0 as LPVOID,
|
||||||
|
); // lpParam
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "fullscreen"))]
|
||||||
|
{
|
||||||
|
let hinstance = GetModuleHandleA(0 as *const i8);
|
||||||
|
let mut wnd_class: WNDCLASSA = core::mem::zeroed();
|
||||||
|
wnd_class.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
|
||||||
|
wnd_class.lpfnWndProc = Some(window_proc);
|
||||||
|
wnd_class.hInstance = hinstance; // The instance handle for our application which we can retrieve by calling GetModuleHandleW.
|
||||||
|
wnd_class.lpszClassName = "MyClass\0".as_ptr() as *const i8;
|
||||||
|
RegisterClassA(&wnd_class);
|
||||||
|
|
||||||
|
h_wnd = CreateWindowExA(
|
||||||
|
0,
|
||||||
|
//WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, // dwExStyle
|
||||||
|
"MyClass\0".as_ptr() as *const i8, // class we registered.
|
||||||
|
"GLWIN\0".as_ptr() as *const i8, // title
|
||||||
|
WS_OVERLAPPEDWINDOW | WS_VISIBLE, // dwStyle
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
1920,
|
||||||
|
1080, // size and position
|
||||||
|
0 as HWND, // hWndParent
|
||||||
|
0 as HMENU, // hMenu
|
||||||
|
hinstance, // hInstance
|
||||||
|
0 as LPVOID,
|
||||||
|
); // lpParam
|
||||||
|
}
|
||||||
|
let h_dc: HDC = GetDC(h_wnd); // Device Context
|
||||||
|
|
||||||
|
let mut pfd: PIXELFORMATDESCRIPTOR = core::mem::zeroed();
|
||||||
|
pfd.nSize = core::mem::size_of::<PIXELFORMATDESCRIPTOR>() as u16;
|
||||||
|
pfd.nVersion = 1;
|
||||||
|
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||||
|
pfd.iPixelType = PFD_TYPE_RGBA;
|
||||||
|
pfd.cColorBits = 32;
|
||||||
|
pfd.cAlphaBits = 8;
|
||||||
|
pfd.cDepthBits = 32;
|
||||||
|
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
{
|
||||||
|
let pf_id: i32 = ChoosePixelFormat(h_dc, &pfd);
|
||||||
|
if pf_id == 0 {
|
||||||
|
show_error("ChoosePixelFormat() failed.\0".as_ptr() as *const i8);
|
||||||
|
return (0 as HWND, h_dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if SetPixelFormat(h_dc, pf_id, &pfd) == 0 {
|
||||||
|
show_error("SetPixelFormat() failed.\0".as_ptr() as *const i8);
|
||||||
|
return (0 as HWND, h_dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
let gl_context: HGLRC = wglCreateContext(h_dc); // Rendering Contex
|
||||||
|
if gl_context == 0 as HGLRC {
|
||||||
|
show_error("wglCreateContext() failed.\0".as_ptr() as *const i8);
|
||||||
|
return (0 as HWND, h_dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if wglMakeCurrent(h_dc, gl_context) == 0 {
|
||||||
|
show_error("wglMakeCurrent() failed.\0".as_ptr() as *const i8);
|
||||||
|
return (0 as HWND, h_dc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*#[cfg(not(feature = "logger"))]
|
||||||
|
{
|
||||||
|
let pf_id: i32 = ChoosePixelFormat(h_dc, &pfd);
|
||||||
|
SetPixelFormat(h_dc, pf_id, &pfd);
|
||||||
|
let gl_context: HGLRC = wglCreateContext(h_dc); // Rendering Context
|
||||||
|
wglMakeCurrent(h_dc, gl_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the system font the device context's selected font
|
||||||
|
winapi::um::wingdi::SelectObject(
|
||||||
|
h_dc,
|
||||||
|
winapi::um::wingdi::GetStockObject(winapi::um::wingdi::SYSTEM_FONT as i32),
|
||||||
|
);
|
||||||
|
|
||||||
|
// create the bitmap display lists
|
||||||
|
winapi::um::wingdi::wglUseFontBitmapsA(h_dc, 0, 255, 1000);*/
|
||||||
|
|
||||||
|
//gl::init();
|
||||||
|
//gl::wglSwapIntervalEXT(1);
|
||||||
|
(h_wnd, h_dc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create message handling function with which to link to hook window to Windows messaging system
|
||||||
|
// More info: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644927(v=vs.85).aspx
|
||||||
|
pub fn handle_message(_window: HWND) -> bool {
|
||||||
|
unsafe {
|
||||||
|
let mut msg: MSG = MaybeUninit::uninit().assume_init();
|
||||||
|
loop {
|
||||||
|
if PeekMessageA(&mut msg, 0 as HWND, 0, 0, PM_REMOVE) == 0 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if msg.message == winapi::um::winuser::WM_QUIT {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessageA(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn memset(dest: *mut u8, c: i32, n: usize) -> *mut u8 {
|
||||||
|
let mut i = 0;
|
||||||
|
while i < n {
|
||||||
|
*((dest as usize + i) as *mut u8) = c as u8;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
dest
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
|
||||||
|
let mut i = 0;
|
||||||
|
while i < n {
|
||||||
|
*((dest as usize + i) as *mut u8) = *((src as usize + i) as *const u8);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
dest
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
|
||||||
|
let mut i = 0;
|
||||||
|
|
||||||
|
while i < n {
|
||||||
|
let a = *((s1 as usize + i) as *const u8);
|
||||||
|
let b = *((s2 as usize + i) as *const u8);
|
||||||
|
if a != b {
|
||||||
|
return a as i32 - b as i32;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
//this is fine
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
#[no_mangle]
|
||||||
|
extern "C" fn __chkstk() {}
|
||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
#[cfg(feature = "logger")]
|
||||||
|
use winapi::um::fileapi::{CreateFileA, ReadFile, WriteFile, OPEN_ALWAYS, OPEN_EXISTING};
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
use winapi::um::handleapi::CloseHandle;
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
use winapi::um::winnt::{FILE_APPEND_DATA, FILE_ATTRIBUTE_NORMAL, GENERIC_READ};
|
||||||
|
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log {
|
||||||
|
($text:expr) => {
|
||||||
|
crate::util::log0($text);
|
||||||
|
};
|
||||||
|
($text:expr, $val:expr) => {
|
||||||
|
crate::util::log1($text, $val);
|
||||||
|
};
|
||||||
|
($text:expr, $val1:expr, $val2:expr) => {
|
||||||
|
crate::util::log2($text, $val1, $val2);
|
||||||
|
};
|
||||||
|
($text:expr, $val1:expr, $val2:expr, $val3:expr) => {
|
||||||
|
crate::util::log3($text, $val1, $val2, $val3);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "logger"))]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log {
|
||||||
|
($text:expr) => {};
|
||||||
|
($text:expr, $val:expr) => {};
|
||||||
|
($text:expr, $val1:expr, $val2:expr) => {};
|
||||||
|
($text:expr, $val1:expr, $val2:expr, $val3:expr) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
pub unsafe fn log0(message: &str) {
|
||||||
|
let name = "dbg_out.txt\0";
|
||||||
|
let mut out = 0;
|
||||||
|
|
||||||
|
let h_file = CreateFileA(
|
||||||
|
name.as_ptr() as *const i8,
|
||||||
|
FILE_APPEND_DATA,
|
||||||
|
0,
|
||||||
|
0 as *mut winapi::um::minwinbase::SECURITY_ATTRIBUTES,
|
||||||
|
OPEN_ALWAYS,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
0 as *mut winapi::ctypes::c_void,
|
||||||
|
);
|
||||||
|
WriteFile(
|
||||||
|
h_file,
|
||||||
|
message.as_ptr() as *const winapi::ctypes::c_void,
|
||||||
|
message.len() as u32,
|
||||||
|
&mut out,
|
||||||
|
0 as *mut winapi::um::minwinbase::OVERLAPPED,
|
||||||
|
);
|
||||||
|
CloseHandle(h_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
pub fn get_c_string_length(buffer: &[u8]) -> usize {
|
||||||
|
let mut buffer_text_len = 0;
|
||||||
|
while buffer_text_len < buffer.len() {
|
||||||
|
if buffer[buffer_text_len] == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buffer_text_len += 1
|
||||||
|
}
|
||||||
|
return buffer_text_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
pub fn f32_to_text(dest: &mut [u8], value: f32, comma: bool) -> usize {
|
||||||
|
let int_part = value as u32;
|
||||||
|
let frac_part = ((value - int_part as f32) * 10000f32) as u32;
|
||||||
|
unsafe {
|
||||||
|
winapi::um::winuser::wsprintfA(
|
||||||
|
dest.as_mut_ptr() as *mut i8,
|
||||||
|
"%d.%.4d\0".as_ptr() as *const i8,
|
||||||
|
int_part,
|
||||||
|
frac_part,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if comma {
|
||||||
|
let length = get_c_string_length(dest);
|
||||||
|
dest[length] = ',' as u8;
|
||||||
|
dest[length + 1] = ' ' as u8;
|
||||||
|
return length + 2;
|
||||||
|
}
|
||||||
|
return get_c_string_length(&dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
pub unsafe fn log1(message: &str, value: f32) {
|
||||||
|
let mut buffer: [u8; 256] = [0; 256];
|
||||||
|
let mut length: usize = 0;
|
||||||
|
length += f32_to_text(&mut buffer, value, false);
|
||||||
|
buffer[length] = '\n' as u8;
|
||||||
|
let buffer_text_len = get_c_string_length(&buffer);
|
||||||
|
log0(core::str::from_utf8_unchecked(&buffer[0..buffer_text_len]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
pub unsafe fn log2(message: &str, value1: f32, value2: f32) {
|
||||||
|
let mut buffer: [u8; 256] = [0; 256];
|
||||||
|
let mut length: usize = 0;
|
||||||
|
length += f32_to_text(&mut buffer, value1, true);
|
||||||
|
length += f32_to_text(&mut buffer[length..], value2, false);
|
||||||
|
buffer[length] = '\n' as u8;
|
||||||
|
let buffer_text_len = get_c_string_length(&buffer);
|
||||||
|
log0(core::str::from_utf8_unchecked(&buffer[0..buffer_text_len]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
pub unsafe fn log3(message: &str, value1: f32, value2: f32, value3: f32) {
|
||||||
|
let mut buffer: [u8; 256] = [0; 256];
|
||||||
|
let mut length: usize = 0;
|
||||||
|
length += f32_to_text(&mut buffer, value1, true);
|
||||||
|
length += f32_to_text(&mut buffer[length..], value2, true);
|
||||||
|
length += f32_to_text(&mut buffer[length..], value3, false);
|
||||||
|
buffer[length] = '\n' as u8;
|
||||||
|
let buffer_text_len = get_c_string_length(&buffer);
|
||||||
|
log0(core::str::from_utf8_unchecked(&buffer[0..buffer_text_len]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "logger")]
|
||||||
|
pub unsafe fn read_file(file_name: &str, dst: &mut [u8]) {
|
||||||
|
//let name = "dbg_out.txt\0";
|
||||||
|
let mut out = 0;
|
||||||
|
|
||||||
|
log!("Creating file for reading\n");
|
||||||
|
let h_file = CreateFileA(
|
||||||
|
file_name.as_ptr() as *const i8,
|
||||||
|
GENERIC_READ,
|
||||||
|
0,
|
||||||
|
0 as *mut winapi::um::minwinbase::SECURITY_ATTRIBUTES,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
0 as *mut winapi::ctypes::c_void,
|
||||||
|
);
|
||||||
|
log!("Reading...\n");
|
||||||
|
ReadFile(
|
||||||
|
h_file,
|
||||||
|
dst.as_mut_ptr() as *mut winapi::ctypes::c_void,
|
||||||
|
dst.len() as u32,
|
||||||
|
&mut out,
|
||||||
|
0 as *mut winapi::um::minwinbase::OVERLAPPED,
|
||||||
|
);
|
||||||
|
log!("Close handle...\n");
|
||||||
|
CloseHandle(h_file);
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# [dependencies]
|
||||||
|
# std = {default-features=false,features=["panic_immediate_abort"]}
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
std = {features=["panic_immediate_abort"]}
|
||||||
Reference in New Issue
Block a user