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