some work on camera (wip)

This commit is contained in:
matthew 2025-07-24 07:58:12 +10:00
parent fd03759f57
commit e429cee207
8 changed files with 538 additions and 171 deletions

Binary file not shown.

170
src/gears/game.d Normal file
View 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);
}

View File

@ -2,43 +2,24 @@ public import includes;
import std.stdio;
import aliases;
import core.memory;
import p = platform;
import r = renderer;
import platform;
import game;
import util;
import core.simd;
void main()
{
p.Window window = p.CreateWindow("Video Game", 1920, 1080);
PlatformWindow window = CreateWindow("Video Game", 1920, 1080);
r.Renderer rd = r.Init(&window);
scope(exit) r.Destroy(&rd);
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);
Game g = InitGame(&window);
scope(exit) Destroy(&g);
while (true)
{
p.HandleEvents(&window);
HandleEvents(&window);
if (window.close) break;
r.Cycle(&rd);
Cycle(&g);
}
}

View File

@ -3,11 +3,40 @@ import includes;
import std.stdio;
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)
{
import core.sys.posix.dlfcn;
struct Window
struct InputEvent
{
KeyboardInput key;
bool pressed;
}
struct PlatformWindow
{
Display *display;
xcb_connection_t *conn;
@ -17,6 +46,8 @@ struct Window
u16 w;
u16 h;
bool close;
InputEvent[10] inputs;
u32 input_count;
};
struct Library
@ -29,15 +60,15 @@ struct Function
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);
pureFree(err);
};
Window CreateWindow(string name, u16 width, u16 height)
PlatformWindow CreateWindow(string name, u16 width, u16 height)
{
Window window = {
PlatformWindow window = {
w: width,
h: height,
};
@ -147,7 +178,7 @@ Window CreateWindow(string name, u16 width, u16 height)
};
void
HandleEvents(Window* window)
HandleEvents(PlatformWindow* window)
{
xcb_generic_event_t* e;
@ -172,6 +203,29 @@ HandleEvents(Window* window)
window.close = true;
}
} 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:
break;
}
@ -202,6 +256,143 @@ Function LoadFunction(Library lib, string name)
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)

View File

@ -8,7 +8,7 @@ import vulkan : Destroy, Init, Draw, DrawIndexed, Bind, BindUIBuffers, BeginRend
import assets;
import std.math.traits : isNaN;
import u = util : Logf;
import p = platform;
import platform;
alias Shader = VkShaderModule;
alias Pipeline = PipelineHandle;
@ -51,8 +51,8 @@ alias BT = BufferType;
struct GlobalUniforms
{
Mat4 view_matrix;
Mat4 projection_matrix;
Mat4 view_matrix = Mat4.identity;
Mat4 projection_matrix = Mat4.identity;
Vec2 res;
}
@ -106,30 +106,13 @@ struct Renderer
Arena temp_arena;
Vulkan vk;
p.Window* window;
PlatformWindow* window;
GlobalUniforms globals;
UIVertex[] ui_vertex_buf;
u32[] ui_index_buf;
u32 ui_count;
Pipeline pbr_pipeline;
Pipeline triangle_pipeline;
Pipeline compute_pipeline;
Pipeline ui_pipeline;
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
@ -182,7 +165,7 @@ struct Model
}
Renderer
Init(p.Window* window)
InitRenderer(PlatformWindow* window)
{
u.Result!(Vulkan) vk_result = Init(window, u.MB(24), u.MB(32));
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),
};
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;
}
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
DrawModel(Renderer* rd, Model* model)
{
BindBuffers(&rd.vk, &model.index_buffer, &model.vertex_buffer);
rd.push_const.model_matrix = Mat4.identity;
foreach(i, part; model.parts)
{
rd.push_const.mat_id = part.mat;
@ -308,9 +211,16 @@ CopyVertex(Vec4* dst, m3dv_t* src)
pragma(inline): void
BeginFrame(Renderer* rd)
{
rd.ui_count = 0;
BeginFrame(&rd.vk);
}
pragma(inline): void
DrawUI(Renderer* rd)
{
DrawIndexed(rd, 6, rd.ui_count, 0);
}
pragma(inline): void
FinishFrame(Renderer* rd)
{
@ -410,7 +320,6 @@ ReadModel(Renderer* rd, string name)
foreach(i; 0 .. m3d.numtexture)
{
const(char)[] tex_name = m3d.texture[i].name[0 .. strlen(m3d.texture[i].name)];
Logf("texture name: %r", tex_name);
}
if (m3d.numtexture == 0)
@ -421,7 +330,6 @@ ReadModel(Renderer* rd, string name)
foreach(i; 0 .. m3d.nummaterial)
{
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;
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)];
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_has_texture = true;
} break;
default: Logf("Unimplemented: %s", m3d.material[i].prop[j].type); break;
default: break;
}
}
@ -588,9 +494,11 @@ LoadModel(Renderer* rd, string name)
void
Destroy(Renderer* rd)
{
Destroy(&rd.vk, rd.triangle_pipeline);
Destroy(&rd.vk, rd.compute_pipeline);
Destroy(&rd.vk);
}
void
Destroy(Renderer* rd, Pipeline* pipeline)
{
Destroy(&rd.vk, pipeline);
}

View File

@ -7,7 +7,7 @@ import core.stdc.string : strcmp, memcpy;
import std.format : sformat;
import u = util : HashTable, Result, Logf, Log, MB, Delete;
import alloc;
import p = platform;
import platform;
import ap = assets;
import renderer;
import std.math.rounding : Ceil = ceil;
@ -140,7 +140,7 @@ struct Vulkan
u.SLList!(SI) cleanup_list;
p.Window* window;
PlatformWindow* window;
VkDebugUtilsMessengerEXT dbg_msg;
VkInstance instance;
@ -226,7 +226,7 @@ struct QueueInfo
};
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;
@ -716,8 +716,6 @@ CreateImageView(Vulkan* vk, ImageView* view, u32 w, u32 h, u32 ch, u8[] data)
{
CreateImageView(vk, view, w, h);
Logf("w: %s h: %s ch: %s", w, h, ch);
if (ch == 4)
{
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.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;
@ -1484,7 +1483,7 @@ Destroy(Vulkan* vk, Shader shader)
}
void
Destroy(Vulkan* vk, Pipeline pipeline)
Destroy(Vulkan* vk, Pipeline* pipeline)
{
vkDestroyPipeline(vk.device, pipeline.handle, null);
}
@ -1731,34 +1730,41 @@ InitDescriptors(Vulkan* vk)
sampler: vk.nearest_sampler,
};
VkDescriptorImageInfo draw_image_info = {
imageView: vk.draw_image.view,
imageLayout: VK_IMAGE_LAYOUT_GENERAL,
};
VkWriteDescriptorSet[] writes = [
{
VkWriteDescriptorSet write = {
sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
dstSet: vk.desc_sets[DT.Shared],
dstBinding: 3,
descriptorCount: 1,
descriptorType: VK_DESCRIPTOR_TYPE_SAMPLER,
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,
dstSet: vk.desc_sets[DT.Shared],
dstBinding: 2,
descriptorCount: 1,
descriptorType: VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
pImageInfo: &draw_image_info,
},
];
};
vkUpdateDescriptorSets(vk.device, cast(u32)writes.length, writes.ptr, 0, null);
}
return success;
vkUpdateDescriptorSets(vk.device, 1, &write, 0, null);
}
void
@ -2258,8 +2264,11 @@ RecreateSwapchain(Vulkan* vk)
vkDeviceWaitIdle(vk.device);
Destroy(vk.swapchain, vk.present_images, vk.device);
Destroy(&vk.draw_image, &vk.depth_image, vk.device, vk.vma);
CreateSwapchain(vk);
CreateDrawImages(vk);
WriteDrawImageDesc(vk);
}
bool

View File

@ -22,7 +22,7 @@ mat4 y_matrix = mat4(
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;

View File

@ -411,3 +411,111 @@ OSTime()
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);
}