some work on camera (wip)
This commit is contained in:
parent
fd03759f57
commit
e429cee207
Binary file not shown.
170
src/gears/game.d
Normal file
170
src/gears/game.d
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
import aliases;
|
||||||
|
import includes;
|
||||||
|
import renderer : Destroy;
|
||||||
|
import renderer;
|
||||||
|
import util;
|
||||||
|
import platform;
|
||||||
|
import dplug.math;
|
||||||
|
|
||||||
|
struct Camera
|
||||||
|
{
|
||||||
|
f32 speed = 3.0;
|
||||||
|
Vec3 pos = Vec3(0.0, 0.0, 3.0);
|
||||||
|
Vec3 front = Vec3(0.0, 0.0, -1.0);
|
||||||
|
Vec3 up = Vec3(0.0, 1.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Game
|
||||||
|
{
|
||||||
|
Renderer rd;
|
||||||
|
|
||||||
|
PlatformWindow* window;
|
||||||
|
|
||||||
|
Pipeline pbr_pipeline;
|
||||||
|
Pipeline triangle_pipeline;
|
||||||
|
Pipeline compute_pipeline;
|
||||||
|
Pipeline ui_pipeline;
|
||||||
|
|
||||||
|
GlobalUniforms globals;
|
||||||
|
|
||||||
|
f32 delta;
|
||||||
|
Timer timer;
|
||||||
|
|
||||||
|
Camera camera;
|
||||||
|
|
||||||
|
Model model;
|
||||||
|
}
|
||||||
|
|
||||||
|
Game
|
||||||
|
InitGame(PlatformWindow* window)
|
||||||
|
{
|
||||||
|
Game g = {
|
||||||
|
rd: InitRenderer(window),
|
||||||
|
window: window,
|
||||||
|
timer: CreateTimer(),
|
||||||
|
};
|
||||||
|
|
||||||
|
GfxPipelineInfo triangle_info = {
|
||||||
|
vertex_shader: "shaders/triangle.vert.spv",
|
||||||
|
frag_shader: "shaders/triangle.frag.spv",
|
||||||
|
};
|
||||||
|
|
||||||
|
GfxPipelineInfo ui_info = {
|
||||||
|
vertex_shader: "shaders/gui.vert.spv",
|
||||||
|
frag_shader: "shaders/gui.frag.spv",
|
||||||
|
input_rate: IR.Instance,
|
||||||
|
input_rate_stride: UIVertex.sizeof,
|
||||||
|
vertex_attributes: [
|
||||||
|
{ binding: 0, location: 0, format: FMT.RG_F32, offset: 0 },
|
||||||
|
{ binding: 0, location: 1, format: FMT.RG_F32, offset: UIVertex.p1.offsetof },
|
||||||
|
{ binding: 0, location: 2, format: FMT.RGBA_F32, offset: UIVertex.col.offsetof },
|
||||||
|
{ binding: 0, location: 3, format: FMT.UINT, offset: UIVertex.texture.offsetof },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
GfxPipelineInfo pbr_info = {
|
||||||
|
vertex_shader: "shaders/pbr.vert.spv",
|
||||||
|
frag_shader: "shaders/pbr.frag.spv",
|
||||||
|
input_rate_stride: Vertex.sizeof,
|
||||||
|
vertex_attributes: [
|
||||||
|
{ binding: 0, location: 0, format: FMT.RGBA_F32, offset: 0 },
|
||||||
|
{ binding: 0, location: 1, format: FMT.RGBA_F32, offset: Vertex.n.offsetof },
|
||||||
|
{ binding: 0, location: 2, format: FMT.RG_F32, offset: Vertex.uv.offsetof },
|
||||||
|
{ binding: 0, location: 3, format: FMT.RGBA_UNORM, offset: Vertex.col.offsetof },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
CompPipelineInfo gradient_info = {
|
||||||
|
shader: "shaders/gradient.comp.spv",
|
||||||
|
};
|
||||||
|
|
||||||
|
g.pbr_pipeline = BuildGfxPipeline(&g.rd, &pbr_info);
|
||||||
|
g.triangle_pipeline = BuildGfxPipeline(&g.rd, &triangle_info);
|
||||||
|
g.ui_pipeline = BuildGfxPipeline(&g.rd, &ui_info);
|
||||||
|
g.compute_pipeline = BuildCompPipeline(&g.rd, &gradient_info);
|
||||||
|
|
||||||
|
g.model = LoadModel(&g.rd, "models/yoda.m3d");
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Update(Game* g, Camera* cam)
|
||||||
|
{
|
||||||
|
f32 speed = cam.speed * g.delta;
|
||||||
|
|
||||||
|
foreach(i; 0 .. g.window.input_count)
|
||||||
|
{
|
||||||
|
switch(g.window.inputs[i].key)
|
||||||
|
{
|
||||||
|
case KBI.W:
|
||||||
|
{
|
||||||
|
cam.pos += speed * cam.front;
|
||||||
|
} break;
|
||||||
|
case KBI.A:
|
||||||
|
{
|
||||||
|
cam.pos -= speed * cam.front;
|
||||||
|
} break;
|
||||||
|
case KBI.S:
|
||||||
|
{
|
||||||
|
cam.pos -= cross(cam.front, cam.up).normalized() * speed;
|
||||||
|
} break;
|
||||||
|
case KBI.D:
|
||||||
|
{
|
||||||
|
cam.pos += cross(cam.front, cam.up).normalized() * speed;
|
||||||
|
} break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Cycle(Game* g)
|
||||||
|
{
|
||||||
|
g.delta = DeltaTime(&g.timer);
|
||||||
|
|
||||||
|
Update(g, &g.camera);
|
||||||
|
|
||||||
|
g.globals.projection_matrix = Mat4.identity;
|
||||||
|
g.globals.view_matrix = Mat4.lookAt(g.camera.pos, g.camera.pos + g.camera.front, g.camera.up);
|
||||||
|
|
||||||
|
BeginFrame(&g.rd);
|
||||||
|
|
||||||
|
Bind(&g.rd, &g.compute_pipeline);
|
||||||
|
|
||||||
|
SetUniform(&g.rd, &g.globals);
|
||||||
|
|
||||||
|
DrawRect(&g.rd, 150.0, 300.0, 500.0, 700.0, Vec4(0.0, 0.0, 1.0, 1.0));
|
||||||
|
|
||||||
|
PrepComputeDrawImage(&g.rd);
|
||||||
|
|
||||||
|
Dispatch(&g.rd);
|
||||||
|
|
||||||
|
BeginRender(&g.rd);
|
||||||
|
|
||||||
|
Bind(&g.rd, &g.ui_pipeline);
|
||||||
|
|
||||||
|
BindUIBuffers(&g.rd);
|
||||||
|
|
||||||
|
DrawUI(&g.rd);
|
||||||
|
|
||||||
|
Bind(&g.rd, &g.triangle_pipeline);
|
||||||
|
|
||||||
|
Draw(&g.rd, 3, 1);
|
||||||
|
|
||||||
|
Bind(&g.rd, &g.pbr_pipeline);
|
||||||
|
|
||||||
|
DrawModel(&g.rd, &g.model);
|
||||||
|
|
||||||
|
FinishFrame(&g.rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Destroy(Game* g)
|
||||||
|
{
|
||||||
|
Destroy(&g.rd, &g.pbr_pipeline);
|
||||||
|
Destroy(&g.rd, &g.triangle_pipeline);
|
||||||
|
Destroy(&g.rd, &g.ui_pipeline);
|
||||||
|
Destroy(&g.rd, &g.compute_pipeline);
|
||||||
|
Destroy(&g.rd);
|
||||||
|
}
|
||||||
@ -2,43 +2,24 @@ public import includes;
|
|||||||
import std.stdio;
|
import std.stdio;
|
||||||
import aliases;
|
import aliases;
|
||||||
import core.memory;
|
import core.memory;
|
||||||
import p = platform;
|
import platform;
|
||||||
import r = renderer;
|
import game;
|
||||||
import util;
|
import util;
|
||||||
import core.simd;
|
import core.simd;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
p.Window window = p.CreateWindow("Video Game", 1920, 1080);
|
PlatformWindow window = CreateWindow("Video Game", 1920, 1080);
|
||||||
|
|
||||||
r.Renderer rd = r.Init(&window);
|
Game g = InitGame(&window);
|
||||||
scope(exit) r.Destroy(&rd);
|
scope(exit) Destroy(&g);
|
||||||
|
|
||||||
u64 os_freq = OSTimeFreq();
|
|
||||||
u64 cpu_start = RDTSC();
|
|
||||||
u64 os_start = OSTime();
|
|
||||||
u64 os_end = 0;
|
|
||||||
u64 os_elapsed = 0;
|
|
||||||
|
|
||||||
while (os_elapsed < os_freq)
|
|
||||||
{
|
|
||||||
os_end = OSTime();
|
|
||||||
os_elapsed = os_end - os_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 cpu_end = RDTSC();
|
|
||||||
u64 cpu_elapsed = cpu_end - cpu_start;
|
|
||||||
|
|
||||||
writefln(" OS Timer: %s -> %s = %s elapsed", os_start, os_end, os_elapsed);
|
|
||||||
writefln("OS Seconds: %.4f", cast(f64)(os_elapsed)/cast(f64)(os_freq));
|
|
||||||
writefln(" CPU Timer: %s -> %s = %s elapsed", cpu_start, cpu_end, cpu_elapsed);
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
p.HandleEvents(&window);
|
HandleEvents(&window);
|
||||||
if (window.close) break;
|
if (window.close) break;
|
||||||
|
|
||||||
r.Cycle(&rd);
|
Cycle(&g);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,11 +3,40 @@ import includes;
|
|||||||
import std.stdio;
|
import std.stdio;
|
||||||
import core.memory;
|
import core.memory;
|
||||||
|
|
||||||
|
enum KeyboardInput
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
A, B, C, D, E, F, G, H, I, J, K, L, M,
|
||||||
|
N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||||
|
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine,
|
||||||
|
Num0, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9,
|
||||||
|
NumLock, NumSlash, NumStar, NumMinus, NumPlus, NumEnter, NumPeriod,
|
||||||
|
Insert, Delete, Home, End, PageUp, PageDown,
|
||||||
|
PrintScreen, ScrollLock, Pause,
|
||||||
|
Comma, Period, BackSlash, Backspace, ForwardSlash, Minus, Plus,
|
||||||
|
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||||
|
Up, Down, Left, Right,
|
||||||
|
LeftCtrl, LeftAlt, LeftShift, LeftSuper,
|
||||||
|
Tab, CapsLock,
|
||||||
|
RightCtrl, RightAlt, RightSuper, RightShift,
|
||||||
|
Enter, Space,
|
||||||
|
Tilde, Esc,
|
||||||
|
Semicolon, Quote, LeftBrace, RightBrace,
|
||||||
|
};
|
||||||
|
|
||||||
|
alias KBI = KeyboardInput;
|
||||||
|
|
||||||
version(linux)
|
version(linux)
|
||||||
{
|
{
|
||||||
import core.sys.posix.dlfcn;
|
import core.sys.posix.dlfcn;
|
||||||
|
|
||||||
struct Window
|
struct InputEvent
|
||||||
|
{
|
||||||
|
KeyboardInput key;
|
||||||
|
bool pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PlatformWindow
|
||||||
{
|
{
|
||||||
Display *display;
|
Display *display;
|
||||||
xcb_connection_t *conn;
|
xcb_connection_t *conn;
|
||||||
@ -17,6 +46,8 @@ struct Window
|
|||||||
u16 w;
|
u16 w;
|
||||||
u16 h;
|
u16 h;
|
||||||
bool close;
|
bool close;
|
||||||
|
InputEvent[10] inputs;
|
||||||
|
u32 input_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Library
|
struct Library
|
||||||
@ -29,15 +60,15 @@ struct Function
|
|||||||
void* ptr;
|
void* ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
void CheckErr(Window *window, xcb_void_cookie_t *cookie, xcb_generic_error_t *err, string msg)
|
void CheckErr(PlatformWindow *window, xcb_void_cookie_t *cookie, xcb_generic_error_t *err, string msg)
|
||||||
{
|
{
|
||||||
assert(err == null, msg);
|
assert(err == null, msg);
|
||||||
pureFree(err);
|
pureFree(err);
|
||||||
};
|
};
|
||||||
|
|
||||||
Window CreateWindow(string name, u16 width, u16 height)
|
PlatformWindow CreateWindow(string name, u16 width, u16 height)
|
||||||
{
|
{
|
||||||
Window window = {
|
PlatformWindow window = {
|
||||||
w: width,
|
w: width,
|
||||||
h: height,
|
h: height,
|
||||||
};
|
};
|
||||||
@ -147,7 +178,7 @@ Window CreateWindow(string name, u16 width, u16 height)
|
|||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
HandleEvents(Window* window)
|
HandleEvents(PlatformWindow* window)
|
||||||
{
|
{
|
||||||
xcb_generic_event_t* e;
|
xcb_generic_event_t* e;
|
||||||
|
|
||||||
@ -172,6 +203,29 @@ HandleEvents(Window* window)
|
|||||||
window.close = true;
|
window.close = true;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case XCB_KEY_RELEASE:
|
||||||
|
case XCB_KEY_PRESS:
|
||||||
|
{
|
||||||
|
// TODO: definitely definitely need to rework this whole thing
|
||||||
|
if (window.input_count == window.inputs.length)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_key_press_event_t* keyboard_event = cast(xcb_key_press_event_t*)e;
|
||||||
|
|
||||||
|
bool pressed = e.response_type == XCB_KEY_PRESS;
|
||||||
|
xcb_keycode_t code = keyboard_event.detail;
|
||||||
|
KeySym key_sym = XkbKeycodeToKeysym(window.display, cast(KeyCode)code, 0, 0);
|
||||||
|
KBI input = ConvertInput(key_sym);
|
||||||
|
|
||||||
|
if (input != KBI.None)
|
||||||
|
{
|
||||||
|
window.inputs[window.input_count].key = input;
|
||||||
|
window.inputs[window.input_count].pressed = pressed;
|
||||||
|
window.input_count += 1;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -202,6 +256,143 @@ Function LoadFunction(Library lib, string name)
|
|||||||
return fn;
|
return fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
KeyboardInput
|
||||||
|
ConvertInput(u64 x_key)
|
||||||
|
{
|
||||||
|
switch (x_key)
|
||||||
|
{
|
||||||
|
case XK_BackSpace: return KBI.Backspace;
|
||||||
|
case XK_Return: return KBI.Enter;
|
||||||
|
case XK_Tab: return KBI.Tab;
|
||||||
|
case XK_Pause: return KBI.Pause;
|
||||||
|
case XK_Caps_Lock: return KBI.CapsLock;
|
||||||
|
case XK_Escape: return KBI.Esc;
|
||||||
|
case XK_space: return KBI.Space;
|
||||||
|
case XK_Prior: return KBI.PageUp;
|
||||||
|
case XK_Next: return KBI.PageDown;
|
||||||
|
case XK_End: return KBI.End;
|
||||||
|
case XK_Home: return KBI.Home;
|
||||||
|
case XK_Left: return KBI.Left;
|
||||||
|
case XK_Up: return KBI.Up;
|
||||||
|
case XK_Right: return KBI.Right;
|
||||||
|
case XK_Down: return KBI.Down;
|
||||||
|
case XK_Print: return KBI.PrintScreen;
|
||||||
|
case XK_Insert: return KBI.Insert;
|
||||||
|
case XK_Delete: return KBI.Delete;
|
||||||
|
case XK_Meta_L:
|
||||||
|
case XK_Super_L: return KBI.LeftSuper;
|
||||||
|
case XK_Meta_R:
|
||||||
|
case XK_Super_R: return KBI.RightSuper;
|
||||||
|
case XK_KP_0: return KBI.Num0;
|
||||||
|
case XK_KP_1: return KBI.Num1;
|
||||||
|
case XK_KP_2: return KBI.Num2;
|
||||||
|
case XK_KP_3: return KBI.Num3;
|
||||||
|
case XK_KP_4: return KBI.Num4;
|
||||||
|
case XK_KP_5: return KBI.Num5;
|
||||||
|
case XK_KP_6: return KBI.Num6;
|
||||||
|
case XK_KP_7: return KBI.Num7;
|
||||||
|
case XK_KP_8: return KBI.Num8;
|
||||||
|
case XK_KP_9: return KBI.Num9;
|
||||||
|
case XK_multiply: return KBI.NumStar;
|
||||||
|
case XK_KP_Subtract: return KBI.NumMinus;
|
||||||
|
case XK_KP_Decimal: return KBI.NumPeriod;
|
||||||
|
case XK_KP_Divide: return KBI.NumSlash;
|
||||||
|
case XK_KP_Add: return KBI.NumPlus;
|
||||||
|
case XK_F1: return KBI.F1;
|
||||||
|
case XK_F2: return KBI.F2;
|
||||||
|
case XK_F3: return KBI.F3;
|
||||||
|
case XK_F4: return KBI.F4;
|
||||||
|
case XK_F5: return KBI.F5;
|
||||||
|
case XK_F6: return KBI.F6;
|
||||||
|
case XK_F7: return KBI.F7;
|
||||||
|
case XK_F8: return KBI.F8;
|
||||||
|
case XK_F9: return KBI.F9;
|
||||||
|
case XK_F10: return KBI.F10;
|
||||||
|
case XK_F11: return KBI.F11;
|
||||||
|
case XK_F12: return KBI.F12;
|
||||||
|
case XK_Num_Lock: return KBI.NumLock;
|
||||||
|
case XK_Scroll_Lock: return KBI.ScrollLock;
|
||||||
|
case XK_Shift_L: return KBI.LeftShift;
|
||||||
|
case XK_Shift_R: return KBI.RightShift;
|
||||||
|
case XK_Control_L: return KBI.LeftCtrl;
|
||||||
|
case XK_Control_R: return KBI.RightCtrl;
|
||||||
|
case XK_Alt_L: return KBI.LeftAlt;
|
||||||
|
case XK_Alt_R: return KBI.RightAlt;
|
||||||
|
case XK_semicolon: return KBI.Semicolon;
|
||||||
|
case XK_bracketleft: return KBI.LeftBrace;
|
||||||
|
case XK_bracketright: return KBI.RightBrace;
|
||||||
|
case XK_plus: return KBI.Plus;
|
||||||
|
case XK_comma: return KBI.Comma;
|
||||||
|
case XK_minus: return KBI.Minus;
|
||||||
|
case XK_backslash: return KBI.BackSlash;
|
||||||
|
case XK_slash: return KBI.ForwardSlash;
|
||||||
|
case XK_grave: return KBI.Tilde;
|
||||||
|
case XK_0: return KBI.Zero;
|
||||||
|
case XK_1: return KBI.One;
|
||||||
|
case XK_2: return KBI.Two;
|
||||||
|
case XK_3: return KBI.Three;
|
||||||
|
case XK_4: return KBI.Four;
|
||||||
|
case XK_5: return KBI.Five;
|
||||||
|
case XK_6: return KBI.Six;
|
||||||
|
case XK_7: return KBI.Seven;
|
||||||
|
case XK_8: return KBI.Eight;
|
||||||
|
case XK_9: return KBI.Nine;
|
||||||
|
case XK_a:
|
||||||
|
case XK_A: return KBI.A;
|
||||||
|
case XK_b:
|
||||||
|
case XK_B: return KBI.B;
|
||||||
|
case XK_c:
|
||||||
|
case XK_C: return KBI.C;
|
||||||
|
case XK_d:
|
||||||
|
case XK_D: return KBI.D;
|
||||||
|
case XK_e:
|
||||||
|
case XK_E: return KBI.E;
|
||||||
|
case XK_f:
|
||||||
|
case XK_F: return KBI.F;
|
||||||
|
case XK_g:
|
||||||
|
case XK_G: return KBI.G;
|
||||||
|
case XK_h:
|
||||||
|
case XK_H: return KBI.H;
|
||||||
|
case XK_i:
|
||||||
|
case XK_I: return KBI.I;
|
||||||
|
case XK_j:
|
||||||
|
case XK_J: return KBI.J;
|
||||||
|
case XK_k:
|
||||||
|
case XK_K: return KBI.K;
|
||||||
|
case XK_l:
|
||||||
|
case XK_L: return KBI.L;
|
||||||
|
case XK_m:
|
||||||
|
case XK_M: return KBI.M;
|
||||||
|
case XK_n:
|
||||||
|
case XK_N: return KBI.N;
|
||||||
|
case XK_o:
|
||||||
|
case XK_O: return KBI.O;
|
||||||
|
case XK_p:
|
||||||
|
case XK_P: return KBI.P;
|
||||||
|
case XK_q:
|
||||||
|
case XK_Q: return KBI.Q;
|
||||||
|
case XK_r:
|
||||||
|
case XK_R: return KBI.R;
|
||||||
|
case XK_s:
|
||||||
|
case XK_S: return KBI.S;
|
||||||
|
case XK_t:
|
||||||
|
case XK_T: return KBI.T;
|
||||||
|
case XK_u:
|
||||||
|
case XK_U: return KBI.U;
|
||||||
|
case XK_v:
|
||||||
|
case XK_V: return KBI.V;
|
||||||
|
case XK_w:
|
||||||
|
case XK_W: return KBI.W;
|
||||||
|
case XK_x:
|
||||||
|
case XK_X: return KBI.X;
|
||||||
|
case XK_y:
|
||||||
|
case XK_Y: return KBI.Y;
|
||||||
|
case XK_z:
|
||||||
|
case XK_Z: return KBI.Z;
|
||||||
|
default: return KBI.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
version(Windows)
|
version(Windows)
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRend
|
|||||||
import assets;
|
import assets;
|
||||||
import std.math.traits : isNaN;
|
import std.math.traits : isNaN;
|
||||||
import u = util : Logf;
|
import u = util : Logf;
|
||||||
import p = platform;
|
import platform;
|
||||||
|
|
||||||
alias Shader = VkShaderModule;
|
alias Shader = VkShaderModule;
|
||||||
alias Pipeline = PipelineHandle;
|
alias Pipeline = PipelineHandle;
|
||||||
@ -51,8 +51,8 @@ alias BT = BufferType;
|
|||||||
|
|
||||||
struct GlobalUniforms
|
struct GlobalUniforms
|
||||||
{
|
{
|
||||||
Mat4 view_matrix;
|
Mat4 view_matrix = Mat4.identity;
|
||||||
Mat4 projection_matrix;
|
Mat4 projection_matrix = Mat4.identity;
|
||||||
Vec2 res;
|
Vec2 res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,30 +106,13 @@ struct Renderer
|
|||||||
Arena temp_arena;
|
Arena temp_arena;
|
||||||
|
|
||||||
Vulkan vk;
|
Vulkan vk;
|
||||||
p.Window* window;
|
PlatformWindow* window;
|
||||||
|
|
||||||
GlobalUniforms globals;
|
|
||||||
UIVertex[] ui_vertex_buf;
|
UIVertex[] ui_vertex_buf;
|
||||||
u32[] ui_index_buf;
|
u32[] ui_index_buf;
|
||||||
u32 ui_count;
|
u32 ui_count;
|
||||||
|
|
||||||
Pipeline pbr_pipeline;
|
|
||||||
Pipeline triangle_pipeline;
|
|
||||||
Pipeline compute_pipeline;
|
|
||||||
Pipeline ui_pipeline;
|
|
||||||
|
|
||||||
PushConst push_const;
|
PushConst push_const;
|
||||||
|
|
||||||
Vec3 camera_pos = Vec3(0.0);
|
|
||||||
|
|
||||||
Model model;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Camera
|
|
||||||
{
|
|
||||||
Vec3 pos = Vec3(0.0, 0.0, 3.0);
|
|
||||||
Vec3 front = Vec3(0.0, 0.0, -1.0);
|
|
||||||
Vec3 up = Vec3(0.0, 1.0, 0.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern(C) struct Material
|
extern(C) struct Material
|
||||||
@ -182,7 +165,7 @@ struct Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
Renderer
|
Renderer
|
||||||
Init(p.Window* window)
|
InitRenderer(PlatformWindow* window)
|
||||||
{
|
{
|
||||||
u.Result!(Vulkan) vk_result = Init(window, u.MB(24), u.MB(32));
|
u.Result!(Vulkan) vk_result = Init(window, u.MB(24), u.MB(32));
|
||||||
assert(vk_result.ok, "Init failure: Unable to initialize Vulkan");
|
assert(vk_result.ok, "Init failure: Unable to initialize Vulkan");
|
||||||
@ -196,95 +179,15 @@ Init(p.Window* window)
|
|||||||
ui_index_buf: GetUIIndexBuffer(&vk_result.value),
|
ui_index_buf: GetUIIndexBuffer(&vk_result.value),
|
||||||
};
|
};
|
||||||
|
|
||||||
GfxPipelineInfo triangle_info = {
|
|
||||||
vertex_shader: "shaders/triangle.vert.spv",
|
|
||||||
frag_shader: "shaders/triangle.frag.spv",
|
|
||||||
};
|
|
||||||
|
|
||||||
GfxPipelineInfo ui_info = {
|
|
||||||
vertex_shader: "shaders/gui.vert.spv",
|
|
||||||
frag_shader: "shaders/gui.frag.spv",
|
|
||||||
input_rate: IR.Instance,
|
|
||||||
input_rate_stride: UIVertex.sizeof,
|
|
||||||
vertex_attributes: [
|
|
||||||
{ binding: 0, location: 0, format: FMT.RG_F32, offset: 0 },
|
|
||||||
{ binding: 0, location: 1, format: FMT.RG_F32, offset: UIVertex.p1.offsetof },
|
|
||||||
{ binding: 0, location: 2, format: FMT.RGBA_F32, offset: UIVertex.col.offsetof },
|
|
||||||
{ binding: 0, location: 3, format: FMT.UINT, offset: UIVertex.texture.offsetof },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
GfxPipelineInfo pbr_info = {
|
|
||||||
vertex_shader: "shaders/pbr.vert.spv",
|
|
||||||
frag_shader: "shaders/pbr.frag.spv",
|
|
||||||
input_rate_stride: Vertex.sizeof,
|
|
||||||
vertex_attributes: [
|
|
||||||
{ binding: 0, location: 0, format: FMT.RGBA_F32, offset: 0 },
|
|
||||||
{ binding: 0, location: 1, format: FMT.RGBA_F32, offset: Vertex.n.offsetof },
|
|
||||||
{ binding: 0, location: 2, format: FMT.RG_F32, offset: Vertex.uv.offsetof },
|
|
||||||
{ binding: 0, location: 3, format: FMT.RGBA_UNORM, offset: Vertex.col.offsetof },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
CompPipelineInfo gradient_info = {
|
|
||||||
shader: "shaders/gradient.comp.spv",
|
|
||||||
};
|
|
||||||
|
|
||||||
rd.pbr_pipeline = BuildGfxPipeline(&rd, &pbr_info);
|
|
||||||
rd.triangle_pipeline = BuildGfxPipeline(&rd, &triangle_info);
|
|
||||||
rd.ui_pipeline = BuildGfxPipeline(&rd, &ui_info);
|
|
||||||
rd.compute_pipeline = BuildCompPipeline(&rd, &gradient_info);
|
|
||||||
|
|
||||||
rd.model = LoadModel(&rd, "models/yoda.m3d");
|
|
||||||
|
|
||||||
ReadModel(&rd, "models/yoda.m3d");
|
|
||||||
|
|
||||||
return rd;
|
return rd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
Cycle(Renderer* rd)
|
|
||||||
{
|
|
||||||
rd.ui_count = 0;
|
|
||||||
|
|
||||||
rd.globals.view_matrix = Mat4(1.0);
|
|
||||||
|
|
||||||
BeginFrame(rd);
|
|
||||||
|
|
||||||
Bind(rd, &rd.compute_pipeline);
|
|
||||||
|
|
||||||
SetUniform(rd, &rd.globals);
|
|
||||||
|
|
||||||
//DrawRect(rd, 150.0, 300.0, 500.0, 700.0, Vec4(0.0, 0.0, 1.0, 1.0));
|
|
||||||
|
|
||||||
PrepComputeDrawImage(rd);
|
|
||||||
|
|
||||||
Dispatch(rd);
|
|
||||||
|
|
||||||
BeginRender(rd);
|
|
||||||
|
|
||||||
Bind(rd, &rd.ui_pipeline);
|
|
||||||
|
|
||||||
BindUIBuffers(rd);
|
|
||||||
|
|
||||||
DrawIndexed(rd, 6, rd.ui_count, 0);
|
|
||||||
|
|
||||||
Bind(rd, &rd.triangle_pipeline);
|
|
||||||
|
|
||||||
//Draw(rd, 3, 1);
|
|
||||||
|
|
||||||
Bind(rd, &rd.pbr_pipeline);
|
|
||||||
|
|
||||||
DrawModel(rd, &rd.model);
|
|
||||||
|
|
||||||
FinishFrame(rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
DrawModel(Renderer* rd, Model* model)
|
DrawModel(Renderer* rd, Model* model)
|
||||||
{
|
{
|
||||||
BindBuffers(&rd.vk, &model.index_buffer, &model.vertex_buffer);
|
BindBuffers(&rd.vk, &model.index_buffer, &model.vertex_buffer);
|
||||||
|
|
||||||
|
rd.push_const.model_matrix = Mat4.identity;
|
||||||
foreach(i, part; model.parts)
|
foreach(i, part; model.parts)
|
||||||
{
|
{
|
||||||
rd.push_const.mat_id = part.mat;
|
rd.push_const.mat_id = part.mat;
|
||||||
@ -308,9 +211,16 @@ CopyVertex(Vec4* dst, m3dv_t* src)
|
|||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
BeginFrame(Renderer* rd)
|
BeginFrame(Renderer* rd)
|
||||||
{
|
{
|
||||||
|
rd.ui_count = 0;
|
||||||
BeginFrame(&rd.vk);
|
BeginFrame(&rd.vk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pragma(inline): void
|
||||||
|
DrawUI(Renderer* rd)
|
||||||
|
{
|
||||||
|
DrawIndexed(rd, 6, rd.ui_count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
pragma(inline): void
|
pragma(inline): void
|
||||||
FinishFrame(Renderer* rd)
|
FinishFrame(Renderer* rd)
|
||||||
{
|
{
|
||||||
@ -410,7 +320,6 @@ ReadModel(Renderer* rd, string name)
|
|||||||
foreach(i; 0 .. m3d.numtexture)
|
foreach(i; 0 .. m3d.numtexture)
|
||||||
{
|
{
|
||||||
const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)];
|
const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)];
|
||||||
Logf("texture name: %r", tex_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m3d.numtexture == 0)
|
if (m3d.numtexture == 0)
|
||||||
@ -421,7 +330,6 @@ ReadModel(Renderer* rd, string name)
|
|||||||
foreach(i; 0 .. m3d.nummaterial)
|
foreach(i; 0 .. m3d.nummaterial)
|
||||||
{
|
{
|
||||||
const(char)[] mat_name = m3d.material[i].name[0 .. strlen(m3d.material[i].name)];
|
const(char)[] mat_name = m3d.material[i].name[0 .. strlen(m3d.material[i].name)];
|
||||||
Logf("material name: %r", mat_name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,8 +353,6 @@ LoadModel(Renderer* rd, string name)
|
|||||||
u32 w = m3d.texture[i].w; u32 h = m3d.texture[i].h; u32 ch = m3d.texture[i].f;
|
u32 w = m3d.texture[i].w; u32 h = m3d.texture[i].h; u32 ch = m3d.texture[i].f;
|
||||||
u8[] tex_data = m3d.texture[i].d[0 .. w * h * ch];
|
u8[] tex_data = m3d.texture[i].d[0 .. w * h * ch];
|
||||||
|
|
||||||
Logf("w: %s h: %s ch: %s", w, h, ch);
|
|
||||||
|
|
||||||
const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)];
|
const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)];
|
||||||
CreateImageView(&rd.vk, &model.textures[i], w, h, ch, tex_data);
|
CreateImageView(&rd.vk, &model.textures[i], w, h, ch, tex_data);
|
||||||
|
|
||||||
@ -483,7 +389,7 @@ LoadModel(Renderer* rd, string name)
|
|||||||
mats[i].specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
mats[i].specular_texture = tex_lookup[m3d.material[i].prop[j].value.textureid];
|
||||||
mats[i].specular_has_texture = true;
|
mats[i].specular_has_texture = true;
|
||||||
} break;
|
} break;
|
||||||
default: Logf("Unimplemented: %s", m3d.material[i].prop[j].type); break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,9 +494,11 @@ LoadModel(Renderer* rd, string name)
|
|||||||
void
|
void
|
||||||
Destroy(Renderer* rd)
|
Destroy(Renderer* rd)
|
||||||
{
|
{
|
||||||
Destroy(&rd.vk, rd.triangle_pipeline);
|
|
||||||
Destroy(&rd.vk, rd.compute_pipeline);
|
|
||||||
Destroy(&rd.vk);
|
Destroy(&rd.vk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Destroy(Renderer* rd, Pipeline* pipeline)
|
||||||
|
{
|
||||||
|
Destroy(&rd.vk, pipeline);
|
||||||
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import core.stdc.string : strcmp, memcpy;
|
|||||||
import std.format : sformat;
|
import std.format : sformat;
|
||||||
import u = util : HashTable, Result, Logf, Log, MB, Delete;
|
import u = util : HashTable, Result, Logf, Log, MB, Delete;
|
||||||
import alloc;
|
import alloc;
|
||||||
import p = platform;
|
import platform;
|
||||||
import ap = assets;
|
import ap = assets;
|
||||||
import renderer;
|
import renderer;
|
||||||
import std.math.rounding : Ceil = ceil;
|
import std.math.rounding : Ceil = ceil;
|
||||||
@ -140,7 +140,7 @@ struct Vulkan
|
|||||||
|
|
||||||
u.SLList!(SI) cleanup_list;
|
u.SLList!(SI) cleanup_list;
|
||||||
|
|
||||||
p.Window* window;
|
PlatformWindow* window;
|
||||||
|
|
||||||
VkDebugUtilsMessengerEXT dbg_msg;
|
VkDebugUtilsMessengerEXT dbg_msg;
|
||||||
VkInstance instance;
|
VkInstance instance;
|
||||||
@ -226,7 +226,7 @@ struct QueueInfo
|
|||||||
};
|
};
|
||||||
|
|
||||||
u.Result!(Vulkan)
|
u.Result!(Vulkan)
|
||||||
Init(p.Window* window, u64 permanent_mem, u64 frame_mem)
|
Init(PlatformWindow* window, u64 permanent_mem, u64 frame_mem)
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
@ -716,8 +716,6 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
|
|||||||
{
|
{
|
||||||
CreateImageView(vk, view, w, h);
|
CreateImageView(vk, view, w, h);
|
||||||
|
|
||||||
Logf("w: %s h: %s ch: %s", w, h, ch);
|
|
||||||
|
|
||||||
if (ch == 4)
|
if (ch == 4)
|
||||||
{
|
{
|
||||||
assert(Transfer(vk, view, data, w, h), "CreateImageView failure: Image Transfer error");
|
assert(Transfer(vk, view, data, w, h), "CreateImageView failure: Image Transfer error");
|
||||||
@ -1457,6 +1455,7 @@ SetUniform(Vulkan* vk, GlobalUniforms* globals)
|
|||||||
{
|
{
|
||||||
globals.res.x = vk.swapchain_extent.width;
|
globals.res.x = vk.swapchain_extent.width;
|
||||||
globals.res.y = vk.swapchain_extent.height;
|
globals.res.y = vk.swapchain_extent.height;
|
||||||
|
globals.projection_matrix = Mat4.perspective(1.57, cast(f32)(globals.res.y) / cast(f32)(globals.res.y), 0.1, 100.0);
|
||||||
|
|
||||||
vk.global_buf.data[0] = *globals;
|
vk.global_buf.data[0] = *globals;
|
||||||
|
|
||||||
@ -1484,7 +1483,7 @@ Destroy(Vulkan* vk, Shader shader)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Destroy(Vulkan* vk, Pipeline pipeline)
|
Destroy(Vulkan* vk, Pipeline* pipeline)
|
||||||
{
|
{
|
||||||
vkDestroyPipeline(vk.device, pipeline.handle, null);
|
vkDestroyPipeline(vk.device, pipeline.handle, null);
|
||||||
}
|
}
|
||||||
@ -1731,34 +1730,41 @@ InitDescriptors(Vulkan* vk)
|
|||||||
sampler: vk.nearest_sampler,
|
sampler: vk.nearest_sampler,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkDescriptorImageInfo draw_image_info = {
|
VkWriteDescriptorSet write = {
|
||||||
imageView: vk.draw_image.view,
|
|
||||||
imageLayout: VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
};
|
|
||||||
|
|
||||||
VkWriteDescriptorSet[] writes = [
|
|
||||||
{
|
|
||||||
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
dstSet: vk.desc_sets[DT.Shared],
|
dstSet: vk.desc_sets[DT.Shared],
|
||||||
dstBinding: 3,
|
dstBinding: 3,
|
||||||
descriptorCount: 1,
|
descriptorCount: 1,
|
||||||
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
|
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||||
pImageInfo: &sampler_info,
|
pImageInfo: &sampler_info,
|
||||||
},
|
};
|
||||||
|
|
||||||
|
vkUpdateDescriptorSets(vk.device, 1, &write, 0, null);
|
||||||
|
|
||||||
|
WriteDrawImageDesc(vk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WriteDrawImageDesc(Vulkan* vk)
|
||||||
{
|
{
|
||||||
|
VkDescriptorImageInfo draw_image_info = {
|
||||||
|
imageView: vk.draw_image.view,
|
||||||
|
imageLayout: VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkWriteDescriptorSet write = {
|
||||||
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
dstSet: vk.desc_sets[DT.Shared],
|
dstSet: vk.desc_sets[DT.Shared],
|
||||||
dstBinding: 2,
|
dstBinding: 2,
|
||||||
descriptorCount: 1,
|
descriptorCount: 1,
|
||||||
descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||||
pImageInfo: &draw_image_info,
|
pImageInfo: &draw_image_info,
|
||||||
},
|
};
|
||||||
];
|
|
||||||
|
|
||||||
vkUpdateDescriptorSets(vk.device, cast(u32)writes.length, writes.ptr, 0, null);
|
vkUpdateDescriptorSets(vk.device, 1, &write, 0, null);
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2258,8 +2264,11 @@ RecreateSwapchain(Vulkan* vk)
|
|||||||
vkDeviceWaitIdle(vk.device);
|
vkDeviceWaitIdle(vk.device);
|
||||||
|
|
||||||
Destroy(vk.swapchain, vk.present_images, vk.device);
|
Destroy(vk.swapchain, vk.present_images, vk.device);
|
||||||
|
Destroy(&vk.draw_image, &vk.depth_image, vk.device, vk.vma);
|
||||||
|
|
||||||
CreateSwapchain(vk);
|
CreateSwapchain(vk);
|
||||||
|
CreateDrawImages(vk);
|
||||||
|
WriteDrawImageDesc(vk);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
@ -22,7 +22,7 @@ mat4 y_matrix = mat4(
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_Position = in_pos * y_matrix;
|
gl_Position = G.projection_matrix * G.view_matrix * PC.model_matrix * in_pos;
|
||||||
|
|
||||||
vec4 col = Materials[nonuniformEXT(PC.mat_id)].diffuse;
|
vec4 col = Materials[nonuniformEXT(PC.mat_id)].diffuse;
|
||||||
|
|
||||||
|
|||||||
@ -411,3 +411,111 @@ OSTime()
|
|||||||
|
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: probably needs improvement/testing
|
||||||
|
struct IntervalTimer
|
||||||
|
{
|
||||||
|
u64 cpu_freq;
|
||||||
|
u64 interval;
|
||||||
|
u64 prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntervalTimer
|
||||||
|
CreateTimer(u64 fps)
|
||||||
|
{
|
||||||
|
IntervalTimer timer;
|
||||||
|
|
||||||
|
u64 ms_to_wait = 50;
|
||||||
|
|
||||||
|
u64 os_freq = OSTimeFreq();
|
||||||
|
u64 cpu_start = RDTSC();
|
||||||
|
u64 os_start = OSTime();
|
||||||
|
u64 os_end = 0;
|
||||||
|
u64 os_elapsed = 0;
|
||||||
|
|
||||||
|
u64 os_wait_time = os_freq * ms_to_wait / 1000;
|
||||||
|
|
||||||
|
while (os_elapsed < os_wait_time)
|
||||||
|
{
|
||||||
|
os_end = OSTime();
|
||||||
|
os_elapsed = os_end - os_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cpu_end = RDTSC();
|
||||||
|
u64 cpu_elapsed = cpu_end - cpu_start;
|
||||||
|
u64 cpu_freq = 0;
|
||||||
|
if (os_elapsed)
|
||||||
|
{
|
||||||
|
cpu_freq = os_freq * cpu_elapsed / os_elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
timer.cpu_freq = cpu_freq;
|
||||||
|
timer.interval = cpu_freq/(fps+1);
|
||||||
|
timer.prev = RDTSC();
|
||||||
|
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): bool
|
||||||
|
CheckTimer(IntervalTimer* t)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
u64 time = RDTSC();
|
||||||
|
if (time - t.prev > t.interval)
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
t.prev = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Timer
|
||||||
|
{
|
||||||
|
u64 cpu_freq;
|
||||||
|
u64 prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer
|
||||||
|
CreateTimer()
|
||||||
|
{
|
||||||
|
u64 ms_to_wait = 50;
|
||||||
|
|
||||||
|
u64 os_freq = OSTimeFreq();
|
||||||
|
u64 cpu_start = RDTSC();
|
||||||
|
u64 os_start = OSTime();
|
||||||
|
u64 os_end = 0;
|
||||||
|
u64 os_elapsed = 0;
|
||||||
|
|
||||||
|
u64 os_wait_time = os_freq * ms_to_wait / 1000;
|
||||||
|
|
||||||
|
while (os_elapsed < os_wait_time)
|
||||||
|
{
|
||||||
|
os_end = OSTime();
|
||||||
|
os_elapsed = os_end - os_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 cpu_end = RDTSC();
|
||||||
|
u64 cpu_elapsed = cpu_end - cpu_start;
|
||||||
|
u64 cpu_freq = 0;
|
||||||
|
if (os_elapsed)
|
||||||
|
{
|
||||||
|
cpu_freq = os_freq * cpu_elapsed / os_elapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer timer = {
|
||||||
|
cpu_freq: cpu_freq,
|
||||||
|
prev: RDTSC(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma(inline): f32
|
||||||
|
DeltaTime(Timer* t)
|
||||||
|
{
|
||||||
|
u64 time = RDTSC();
|
||||||
|
u64 step = time - t.prev;
|
||||||
|
t.prev = time;
|
||||||
|
return cast(f32)(step) / cast(f32)(t.cpu_freq);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user