add new win32 platform implementation (#1224)
* Buffer resources from swap chain were not being released. * sysgpu Texture.getWidth() should return width not height. * d3d12: Fixing issues with d3d12 on sysgpu. * Initial win32 platform
This commit is contained in:
parent
3fa889b136
commit
c32e763e11
12 changed files with 3329 additions and 18 deletions
|
|
@ -16,6 +16,7 @@ const Platform = switch (build_options.core_platform) {
|
|||
.x11 => @import("core/X11.zig"),
|
||||
.wayland => @import("core/Wayland.zig"),
|
||||
.web => @panic("TODO: revive wasm backend"),
|
||||
.win32 => @import("core/win32.zig"),
|
||||
};
|
||||
|
||||
// TODO(important): mach.core has a lot of standard Zig APIs, and some global variables, which are
|
||||
|
|
@ -242,8 +243,10 @@ pub inline fn deinit(entities: *mach.Entities.Mod, core: *Mod) !void {
|
|||
if (builtin.os.tag == .linux and
|
||||
state.linux_gamemode != null and
|
||||
state.linux_gamemode.?)
|
||||
{
|
||||
deinitLinuxGamemode();
|
||||
|
||||
}
|
||||
|
||||
state.platform.deinit();
|
||||
state.swap_chain.release();
|
||||
state.queue.release();
|
||||
|
|
|
|||
618
src/core/win32.zig
Normal file
618
src/core/win32.zig
Normal file
|
|
@ -0,0 +1,618 @@
|
|||
const std = @import("std");
|
||||
const w = @import("win32/win32.zig");
|
||||
const mach = @import("../main.zig");
|
||||
const Core = @import("../Core.zig");
|
||||
const InputState = @import("InputState.zig");
|
||||
const Frequency = @import("Frequency.zig");
|
||||
const unicode = @import("unicode.zig");
|
||||
|
||||
const gpu = mach.gpu;
|
||||
const InitOptions = Core.InitOptions;
|
||||
const Event = Core.Event;
|
||||
const KeyEvent = Core.KeyEvent;
|
||||
const MouseButtonEvent = Core.MouseButtonEvent;
|
||||
const MouseButton = Core.MouseButton;
|
||||
const Size = Core.Size;
|
||||
const DisplayMode = Core.DisplayMode;
|
||||
const CursorShape = Core.CursorShape;
|
||||
const VSyncMode = Core.VSyncMode;
|
||||
const CursorMode = Core.CursorMode;
|
||||
const Position = Core.Position;
|
||||
const Key = Core.Key;
|
||||
const KeyMods = Core.KeyMods;
|
||||
const Joystick = Core.Joystick;
|
||||
|
||||
const log = std.log.scoped(.mach);
|
||||
|
||||
const EventQueue = std.fifo.LinearFifo(Event, .Dynamic);
|
||||
const Win32 = @This();
|
||||
|
||||
/////////////////////////
|
||||
// Module state
|
||||
////////////////////////
|
||||
allocator: std.mem.Allocator,
|
||||
core: *Core,
|
||||
|
||||
// Core platform interface
|
||||
title: [:0]u8,
|
||||
display_mode: DisplayMode,
|
||||
vsync_mode: VSyncMode,
|
||||
cursor_mode: CursorMode,
|
||||
cursor_shape: CursorShape,
|
||||
border: bool,
|
||||
headless: bool,
|
||||
refresh_rate: u32,
|
||||
size: Size,
|
||||
surface_descriptor: gpu.Surface.Descriptor,
|
||||
surface_descriptor_from_hwnd: gpu.Surface.DescriptorFromWindowsHWND,
|
||||
|
||||
// Internals
|
||||
window: w.HWND,
|
||||
surrogate: u16 = 0,
|
||||
dinput: *w.IDirectInput8W,
|
||||
|
||||
events: EventQueue,
|
||||
oom: std.Thread.ResetEvent = .{},
|
||||
|
||||
////////////////////////////
|
||||
/// Internals
|
||||
////////////////////////////
|
||||
|
||||
const RequestAdapterResponse = struct {
|
||||
status: gpu.RequestAdapterStatus,
|
||||
adapter: ?*gpu.Adapter,
|
||||
message: ?[*:0]const u8,
|
||||
};
|
||||
|
||||
inline fn requestAdapterCallback(
|
||||
context: *RequestAdapterResponse,
|
||||
status: gpu.RequestAdapterStatus,
|
||||
adapter: ?*gpu.Adapter,
|
||||
message: ?[*:0]const u8,
|
||||
) void {
|
||||
context.* = RequestAdapterResponse{
|
||||
.status = status,
|
||||
.adapter = adapter,
|
||||
.message = message,
|
||||
};
|
||||
}
|
||||
|
||||
inline fn printUnhandledErrorCallback(_: void, ty: gpu.ErrorType, message: [*:0]const u8) void {
|
||||
switch (ty) {
|
||||
.validation => std.log.err("gpu: validation error: {s}\n", .{message}),
|
||||
.out_of_memory => std.log.err("gpu: out of memory: {s}\n", .{message}),
|
||||
.unknown => std.log.err("gpu: unknown error: {s}\n", .{message}),
|
||||
else => unreachable,
|
||||
}
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
/// Platform interface
|
||||
////////////////////////////
|
||||
pub fn init(
|
||||
self: *Win32,
|
||||
options: InitOptions,
|
||||
) !void {
|
||||
self.allocator = options.allocator;
|
||||
self.core = @fieldParentPtr("platform", self);
|
||||
self.events = EventQueue.init(self.allocator);
|
||||
self.size = options.size;
|
||||
|
||||
const hInstance = w.GetModuleHandleW(null);
|
||||
const class_name = w.L("mach");
|
||||
const class = std.mem.zeroInit(w.WNDCLASSW, .{
|
||||
.style = w.CS_OWNDC,
|
||||
.lpfnWndProc = wndProc,
|
||||
.hInstance = hInstance,
|
||||
.hIcon = w.LoadIconW(null, @as([*:0]align(1) const u16, @ptrFromInt(@as(u32, w.IDI_APPLICATION)))),
|
||||
.hCursor = w.LoadCursorW(null, @as([*:0]align(1) const u16, @ptrFromInt(@as(u32, w.IDC_ARROW)))),
|
||||
.lpszClassName = class_name,
|
||||
});
|
||||
if (w.RegisterClassW(&class) == 0) return error.Unexpected;
|
||||
|
||||
const title = try std.unicode.utf8ToUtf16LeAllocZ(self.allocator, options.title);
|
||||
defer self.allocator.free(title);
|
||||
// TODO set title , copy to self.title
|
||||
|
||||
const window = w.CreateWindowExW(
|
||||
.{.APPWINDOW = 1, .WINDOWEDGE = 1, .CLIENTEDGE = 1},
|
||||
class_name,
|
||||
title,
|
||||
if (options.border) w.WS_OVERLAPPEDWINDOW else w.WS_POPUPWINDOW,
|
||||
w.CW_USEDEFAULT,
|
||||
w.CW_USEDEFAULT,
|
||||
@bitCast(self.size.width),
|
||||
@bitCast(self.size.height),
|
||||
null,
|
||||
null,
|
||||
hInstance,
|
||||
null,
|
||||
) orelse return error.Unexpected;
|
||||
self.window = window;
|
||||
|
||||
var dinput: ?*w.IDirectInput8W = undefined;
|
||||
//@ptrCast(*anyopaque
|
||||
|
||||
const ptr: ?*?*anyopaque = @ptrCast(&dinput);
|
||||
|
||||
// if (w.DirectInput8Create(instance, w.DIRECTINPUT_VERSION, &w.IID_IDirectInput8W, &dinput, null) != w.DI_OK) return error.Unexpected;
|
||||
if (w.DirectInput8Create(hInstance, w.DIRECTINPUT_VERSION, w.IID_IDirectInput8W, ptr, null) != w.DI_OK) {
|
||||
return error.Unexpected;
|
||||
}
|
||||
self.dinput = dinput.?;
|
||||
|
||||
self.surface_descriptor_from_hwnd = .{
|
||||
.hinstance = std.os.windows.kernel32.GetModuleHandleW(null).?,
|
||||
.hwnd = window,
|
||||
};
|
||||
|
||||
self.surface_descriptor = .{
|
||||
.next_in_chain = .{
|
||||
.from_windows_hwnd = &self.surface_descriptor_from_hwnd,
|
||||
}
|
||||
};
|
||||
|
||||
_ = w.SetWindowLongPtrW(window, w.GWLP_USERDATA, @bitCast(@intFromPtr(self)));
|
||||
if (!options.headless) {
|
||||
setDisplayMode(self, options.display_mode);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Win32) void {
|
||||
self.events.deinit();
|
||||
_ = self.dinput.IUnknown_Release();
|
||||
}
|
||||
|
||||
pub fn update(self: *Win32) !void {
|
||||
_ = self;
|
||||
var msg: w.MSG = undefined;
|
||||
while (w.PeekMessageW(&msg, null, 0, 0, w.PM_REMOVE) != 0) {
|
||||
_ = w.TranslateMessage(&msg);
|
||||
_ = w.DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
pub const EventIterator = struct {
|
||||
queue: *EventQueue,
|
||||
|
||||
pub fn next(self: *EventIterator) ?Event {
|
||||
return self.queue.readItem();
|
||||
}
|
||||
};
|
||||
|
||||
pub fn pollEvents(self: *Win32) EventIterator {
|
||||
return .{ .queue = &self.events };
|
||||
}
|
||||
|
||||
pub fn setTitle(self: *Win32, title: [:0]const u8) void {
|
||||
const wtitle = std.unicode.utf8ToUtf16LeAllocZ(self.allocator, title) catch {
|
||||
self.oom.set();
|
||||
return;
|
||||
};
|
||||
// TODO update self.title
|
||||
defer self.allocator.free(wtitle);
|
||||
_ = w.SetWindowTextW(self.window, wtitle);
|
||||
}
|
||||
|
||||
pub fn setDisplayMode(self: *Win32, mode: DisplayMode) void {
|
||||
// TODO update self.displayMode
|
||||
switch (mode) {
|
||||
.windowed => _ = w.ShowWindow(self.window, w.SW_RESTORE),
|
||||
// .maximized => _ = w.ShowWindow(self.window, w.SW_MAXIMIZE),
|
||||
.fullscreen => {},
|
||||
.borderless => {},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setBorder(self: *Win32, value: bool) void {
|
||||
_ = w.SetWindowLongW(self.window, w.GWL_STYLE, if (value) w.WS_OVERLAPPEDWINDOW else w.WS_POPUPWINDOW);
|
||||
self.border = value;
|
||||
}
|
||||
|
||||
pub fn setHeadless(self: *Win32, value: bool) void {
|
||||
_ = w.ShowWindow(self.window, if (value) w.SW_HIDE else w.SW_SHOW);
|
||||
self.headless = value;
|
||||
}
|
||||
|
||||
pub fn setVSync(self: *Win32, mode: VSyncMode) void {
|
||||
self.vsync_mode = mode;
|
||||
}
|
||||
|
||||
pub fn setSize(self: *Win32, value: Size) void {
|
||||
_ = w.SetWindowPos(self.window, 0, 0, 0, value.width, value.height, w.SWP_NOMOVE | w.SWP_NOZORDER | w.SWP_NOACTIVATE);
|
||||
self.size = value;
|
||||
}
|
||||
// pub fn size(self: *Core) core.Size {
|
||||
// var rect: w.RECT = undefined;
|
||||
// _ = w.GetClientRect(self.window, &rect);
|
||||
|
||||
// const width:u32 = @intCast(rect.right - rect.left);
|
||||
// const height:u32 = @intCast(rect.bottom - rect.top);
|
||||
|
||||
// return .{ .width = width, .height = height };
|
||||
// }
|
||||
|
||||
// pub fn setSizeLimit(self: *Core, value: core.SizeLimit) void {
|
||||
// self.mutex.lock();
|
||||
// defer self.mutex.unlock();
|
||||
// self.limits = value;
|
||||
// // trigger WM_GETMINMAXINFO
|
||||
// _ = w.SetWindowPos(self.window, 0, 0, 0, 0, 0, w.SWP_NOMOVE | w.SWP_NOSIZE | w.SWP_NOZORDER | w.SWP_NOACTIVATE);
|
||||
// }
|
||||
|
||||
// pub fn sizeLimit(self: *Core) core.SizeLimit {
|
||||
// self.mutex.lock();
|
||||
// defer self.mutex.unlock();
|
||||
// return self.limits;
|
||||
// }
|
||||
|
||||
pub fn setCursorMode(self: *Win32, mode: CursorMode) void {
|
||||
switch (mode) {
|
||||
.normal => while (w.ShowCursor(true) < 0) {},
|
||||
.hidden => while (w.ShowCursor(false) >= 0) {},
|
||||
.disabled => {},
|
||||
}
|
||||
self.cursor_mode = mode;
|
||||
}
|
||||
|
||||
pub fn setCursorShape(self: *Win32, shape: CursorShape) void {
|
||||
const name = switch (shape) {
|
||||
.arrow => w.IDC_ARROW,
|
||||
.ibeam => w.IDC_IBEAM,
|
||||
.crosshair => w.IDC_CROSS,
|
||||
.pointing_hand => w.IDC_HAND,
|
||||
.resize_ew => w.IDC_SIZEWE,
|
||||
.resize_ns => w.IDC_SIZENS,
|
||||
.resize_nwse => w.IDC_SIZENWSE,
|
||||
.resize_nesw => w.IDC_SIZENESW,
|
||||
.resize_all => w.IDC_SIZEALL,
|
||||
.not_allowed => w.IDC_NO,
|
||||
};
|
||||
_ = w.SetCursor(w.LoadCursorW(null, @ptrFromInt(name)));
|
||||
self.cursor_shape = shape;
|
||||
}
|
||||
|
||||
pub fn keyPressed(self: *Win32, key: Key) bool {
|
||||
_ = self;
|
||||
_ = key;
|
||||
// self.input_mutex.lockShared();
|
||||
// defer self.input_mutex.unlockShared();
|
||||
// return self.input_state.isKeyPressed(key);
|
||||
}
|
||||
|
||||
pub fn keyReleased(self: *Win32, key: Key) bool {
|
||||
_ = self;
|
||||
_ = key;
|
||||
// self.input_mutex.lockShared();
|
||||
// defer self.input_mutex.unlockShared();
|
||||
// return self.input_state.isKeyReleased(key);
|
||||
}
|
||||
|
||||
pub fn mousePressed(self: *Win32, button: MouseButton) bool {
|
||||
_ = self;
|
||||
_ = button;
|
||||
// self.input_mutex.lockShared();
|
||||
// defer self.input_mutex.unlockShared();
|
||||
// return self.input_state.isMouseButtonPressed(button);
|
||||
}
|
||||
|
||||
pub fn mouseReleased(self: *Win32, button: MouseButton) bool {
|
||||
_ = self;
|
||||
_ = button;
|
||||
// self.input_mutex.lockShared();
|
||||
// defer self.input_mutex.unlockShared();
|
||||
// return self.input_state.isMouseButtonReleased(button);
|
||||
}
|
||||
|
||||
pub fn mousePosition(self: *Win32) Position {
|
||||
_ = self;
|
||||
// self.input_mutex.lockShared();
|
||||
// defer self.input_mutex.unlockShared();
|
||||
// return self.input_state.mouse_position;
|
||||
}
|
||||
|
||||
pub fn outOfMemory(self: *Win32) bool {
|
||||
if (self.oom.isSet()) {
|
||||
self.oom.reset();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn pushEvent(self: *Win32, event: Event) void {
|
||||
//self.event_mutex.lock();
|
||||
//defer self.event_mutex.unlock();
|
||||
self.events.writeItem(event) catch self.oom.set();
|
||||
}
|
||||
|
||||
fn wndProc(wnd: w.HWND, msg: u32, wParam: w.WPARAM, lParam: w.LPARAM) callconv(w.WINAPI) w.LRESULT {
|
||||
const self = blk: {
|
||||
const userdata: usize = @bitCast(w.GetWindowLongPtrW(wnd, w.GWLP_USERDATA));
|
||||
const ptr: ?*Win32 = @ptrFromInt(userdata);
|
||||
break :blk ptr orelse return w.DefWindowProcW(wnd, msg, wParam, lParam);
|
||||
};
|
||||
|
||||
switch (msg) {
|
||||
w.WM_CLOSE => {
|
||||
self.pushEvent(.close);
|
||||
return 0;
|
||||
},
|
||||
w.WM_GETMINMAXINFO => {
|
||||
//self.mutex.lock();
|
||||
//defer self.mutex.unlock();
|
||||
|
||||
// TODO: SizeLimit is no longer in mach core or has changed
|
||||
// const info: *w.MINMAXINFO = blk: {
|
||||
// const int: usize = @bitCast(lParam);
|
||||
// break :blk @ptrFromInt(int);
|
||||
// };
|
||||
// if (self.limits.min.width) |width| info.ptMinTrackSize.x = @bitCast(width);
|
||||
// if (self.limits.min.height) |height| info.ptMinTrackSize.y = @bitCast(height);
|
||||
// if (self.limits.max.width) |width| info.ptMaxTrackSize.x = @bitCast(width);
|
||||
// if (self.limits.max.height) |height| info.ptMaxTrackSize.y = @bitCast(height);
|
||||
return 0;
|
||||
},
|
||||
w.WM_KEYDOWN, w.WM_KEYUP => {
|
||||
const vkey: w.VIRTUAL_KEY = @enumFromInt(wParam);
|
||||
if (vkey == w.VK_PROCESSKEY) return 0;
|
||||
|
||||
if (msg == w.WM_SYSKEYDOWN and vkey == w.VK_F4) {
|
||||
self.pushEvent(.close);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const flags = lParam >> 16;
|
||||
const scancode: u9 = @intCast(flags & 0x1FF);
|
||||
|
||||
if (scancode == 0x1D) {
|
||||
// right alt sends left control first
|
||||
var next: w.MSG = undefined;
|
||||
const time = w.GetMessageTime();
|
||||
if (w.PeekMessageW(&next, self.window, 0, 0, w.PM_NOREMOVE) != 0 and
|
||||
next.time == time and
|
||||
(next.message == msg or (msg == w.WM_SYSKEYDOWN and next.message == w.WM_KEYUP)) and
|
||||
((next.lParam >> 16) & 0x1FF) == 0x138)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const key = keyFromScancode(scancode);
|
||||
if (msg == w.WM_KEYDOWN) {
|
||||
if (flags & w.KF_REPEAT == 0) {
|
||||
self.pushEvent(.{ .key_press = .{ .key = key, .mods = undefined } });
|
||||
} else {
|
||||
self.pushEvent(.{ .key_repeat = .{ .key = key, .mods = undefined } });
|
||||
}
|
||||
} else {
|
||||
self.pushEvent(.{ .key_release = .{ .key = key, .mods = undefined } });
|
||||
}
|
||||
|
||||
return 0;
|
||||
},
|
||||
w.WM_CHAR => {
|
||||
const char: u16 = @truncate(wParam);
|
||||
var chars: []const u16 = undefined;
|
||||
if (self.surrogate != 0) {
|
||||
chars = &.{ self.surrogate, char };
|
||||
self.surrogate = 0;
|
||||
} else if (std.unicode.utf16IsHighSurrogate(char)) {
|
||||
self.surrogate = char;
|
||||
return 0;
|
||||
} else {
|
||||
chars = &.{char};
|
||||
}
|
||||
var iter = std.unicode.Utf16LeIterator.init(chars);
|
||||
if (iter.nextCodepoint()) |codepoint| {
|
||||
self.pushEvent(.{ .char_input = .{ .codepoint = codepoint.? } });
|
||||
} else |err| {
|
||||
err catch {};
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
w.WM_LBUTTONDOWN,
|
||||
w.WM_LBUTTONUP,
|
||||
w.WM_RBUTTONDOWN,
|
||||
w.WM_RBUTTONUP,
|
||||
w.WM_MBUTTONDOWN,
|
||||
w.WM_MBUTTONUP,
|
||||
w.WM_XBUTTONDOWN,
|
||||
w.WM_XBUTTONUP,
|
||||
=> {
|
||||
const x:f64 = @floatFromInt(@as(i16, @truncate(lParam & 0xFFFF)));
|
||||
const y:f64 = @floatFromInt(@as(i16, @truncate((lParam >> 16) & 0xFFFF)));
|
||||
const xbutton: u32 = @truncate(wParam >> 16);
|
||||
const button: MouseButton = switch (msg) {
|
||||
w.WM_LBUTTONDOWN, w.WM_LBUTTONUP => .left,
|
||||
w.WM_RBUTTONDOWN, w.WM_RBUTTONUP => .right,
|
||||
w.WM_MBUTTONDOWN, w.WM_MBUTTONUP => .middle,
|
||||
else => if (xbutton == @as(u32, @bitCast(w.XBUTTON1))) .four else .five,
|
||||
};
|
||||
|
||||
switch (msg) {
|
||||
w.WM_LBUTTONDOWN,
|
||||
w.WM_MBUTTONDOWN,
|
||||
w.WM_RBUTTONDOWN,
|
||||
w.WM_XBUTTONDOWN,
|
||||
=> self.pushEvent(.{ .mouse_press = .{ .button = button, .mods = undefined, .pos = .{.x = x, .y = y }}}),
|
||||
else => self.pushEvent(.{ .mouse_release = .{ .button = button, .mods = undefined, .pos = .{.x = x, .y = y}}}),
|
||||
}
|
||||
|
||||
return if (msg == w.WM_XBUTTONDOWN or msg == w.WM_XBUTTONUP) w.TRUE else 0;
|
||||
},
|
||||
w.WM_MOUSEMOVE => {
|
||||
self.pushEvent(.{
|
||||
.mouse_motion = .{
|
||||
.pos = .{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
return 0;
|
||||
},
|
||||
w.WM_MOUSEWHEEL => {
|
||||
self.pushEvent(.{
|
||||
.mouse_scroll = .{
|
||||
.xoffset = 0,
|
||||
.yoffset = 0,
|
||||
},
|
||||
});
|
||||
return 0;
|
||||
},
|
||||
else => return w.DefWindowProcW(wnd, msg, wParam, lParam),
|
||||
}
|
||||
}
|
||||
|
||||
fn keyFromScancode(scancode: u9) Key {
|
||||
comptime var table: [0x15D]Key = undefined;
|
||||
comptime for (&table, 1..) |*ptr, i| {
|
||||
ptr.* = switch (i) {
|
||||
0x1 => .escape,
|
||||
0x2 => .one,
|
||||
0x3 => .two,
|
||||
0x4 => .three,
|
||||
0x5 => .four,
|
||||
0x6 => .five,
|
||||
0x7 => .six,
|
||||
0x8 => .seven,
|
||||
0x9 => .eight,
|
||||
0xA => .nine,
|
||||
0xB => .zero,
|
||||
0xC => .minus,
|
||||
0xD => .equal,
|
||||
0xE => .backspace,
|
||||
0xF => .tab,
|
||||
0x10 => .q,
|
||||
0x11 => .w,
|
||||
0x12 => .e,
|
||||
0x13 => .r,
|
||||
0x14 => .t,
|
||||
0x15 => .y,
|
||||
0x16 => .u,
|
||||
0x17 => .i,
|
||||
0x18 => .o,
|
||||
0x19 => .p,
|
||||
0x1A => .left_bracket,
|
||||
0x1B => .right_bracket,
|
||||
0x1C => .enter,
|
||||
0x1D => .left_control,
|
||||
0x1E => .a,
|
||||
0x1F => .s,
|
||||
0x20 => .d,
|
||||
0x21 => .f,
|
||||
0x22 => .g,
|
||||
0x23 => .h,
|
||||
0x24 => .j,
|
||||
0x25 => .k,
|
||||
0x26 => .l,
|
||||
0x27 => .semicolon,
|
||||
0x28 => .apostrophe,
|
||||
0x29 => .grave,
|
||||
0x2A => .left_shift,
|
||||
0x2B => .backslash,
|
||||
0x2C => .z,
|
||||
0x2D => .x,
|
||||
0x2E => .c,
|
||||
0x2F => .v,
|
||||
0x30 => .b,
|
||||
0x31 => .n,
|
||||
0x32 => .m,
|
||||
0x33 => .comma,
|
||||
0x34 => .period,
|
||||
0x35 => .slash,
|
||||
0x36 => .right_shift,
|
||||
0x37 => .kp_multiply,
|
||||
0x38 => .left_alt,
|
||||
0x39 => .space,
|
||||
0x3A => .caps_lock,
|
||||
0x3B => .f1,
|
||||
0x3C => .f2,
|
||||
0x3D => .f3,
|
||||
0x3E => .f4,
|
||||
0x3F => .f5,
|
||||
0x40 => .f6,
|
||||
0x41 => .f7,
|
||||
0x42 => .f8,
|
||||
0x43 => .f9,
|
||||
0x44 => .f10,
|
||||
0x45 => .pause,
|
||||
0x46 => .scroll_lock,
|
||||
0x47 => .kp_7,
|
||||
0x48 => .kp_8,
|
||||
0x49 => .kp_9,
|
||||
0x4A => .kp_subtract,
|
||||
0x4B => .kp_4,
|
||||
0x4C => .kp_5,
|
||||
0x4D => .kp_6,
|
||||
0x4E => .kp_add,
|
||||
0x4F => .kp_1,
|
||||
0x50 => .kp_2,
|
||||
0x51 => .kp_3,
|
||||
0x52 => .kp_0,
|
||||
0x53 => .kp_decimal,
|
||||
//0x56 => .europe2,
|
||||
0x57 => .f11,
|
||||
0x58 => .f12,
|
||||
//0x5C => .international6,
|
||||
0x64 => .f13,
|
||||
0x65 => .f14,
|
||||
0x66 => .f15,
|
||||
0x67 => .f16,
|
||||
0x68 => .f17,
|
||||
0x69 => .f18,
|
||||
0x6A => .f19,
|
||||
0x6B => .f20,
|
||||
0x6C => .f21,
|
||||
0x6D => .f22,
|
||||
0x6E => .f23,
|
||||
//0x70 => .international2,
|
||||
//0x73 => .international1,
|
||||
//0x76 => .lang5,
|
||||
//0x77 => .lang4,
|
||||
//0x78 => .lang3,
|
||||
//0x79 => .international4,
|
||||
//0x7B => .international5,
|
||||
//0x7D => .international3,
|
||||
//0x7E => .kp_comma,
|
||||
//0xF1 => .lang2,
|
||||
//0xF2 => .lang1,
|
||||
//0x11C => .kp_enter,
|
||||
0x11D => .right_control,
|
||||
//0x135 => .kp_divide,
|
||||
0x138 => .right_alt,
|
||||
0x145 => .num_lock,
|
||||
0x146 => .pause,
|
||||
0x147 => .home,
|
||||
0x148 => .up,
|
||||
0x149 => .page_up,
|
||||
0x14B => .left,
|
||||
0x14D => .right,
|
||||
0x14F => .end,
|
||||
0x150 => .down,
|
||||
0x151 => .page_down,
|
||||
0x152 => .insert,
|
||||
0x153 => .delete,
|
||||
0x15B => .left_super,
|
||||
0x15C => .right_super,
|
||||
0x15D => .menu,
|
||||
else => .unknown,
|
||||
};
|
||||
};
|
||||
return if (scancode > 0 and scancode <= table.len) table[scancode - 1] else .unknown;
|
||||
}
|
||||
|
||||
pub fn joystickPresent(_: *Win32, _: Joystick) bool {
|
||||
@panic("NOT IMPLEMENTED");
|
||||
}
|
||||
pub fn joystickName(_: *Win32, _: Joystick) ?[:0]const u8 {
|
||||
@panic("NOT IMPLEMENTED");
|
||||
}
|
||||
pub fn joystickButtons(_: *Win32, _: Joystick) ?[]const bool {
|
||||
@panic("NOT IMPLEMENTED");
|
||||
}
|
||||
// May be called from any thread.
|
||||
pub fn joystickAxes(_: *Win32, _: Joystick) ?[]const f32 {
|
||||
@panic("NOT IMPLEMENTED");
|
||||
}
|
||||
2664
src/core/win32/win32.zig
Normal file
2664
src/core/win32/win32.zig
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -5,6 +5,9 @@ const gfx = mach.gfx;
|
|||
|
||||
const math = mach.math;
|
||||
const vec2 = math.vec2;
|
||||
const vec3 = math.vec3;
|
||||
const vec4 = math.vec4;
|
||||
const mat4x4 = math.mat4x4;
|
||||
const Vec2 = math.Vec2;
|
||||
const Vec3 = math.Vec3;
|
||||
const Mat3x3 = math.Mat3x3;
|
||||
|
|
@ -87,8 +90,14 @@ fn updatePipeline(
|
|||
// that all entities with the same pipeline value are stored in contiguous memory, and
|
||||
// skip this copy.
|
||||
if (sprite_pipeline_id == pipeline_id) {
|
||||
const uv = uv_transform;
|
||||
gfx.SpritePipeline.cp_transforms[i] = transform;
|
||||
gfx.SpritePipeline.cp_uv_transforms[i] = uv_transform;
|
||||
// TODO(d3d12): #1217
|
||||
// changed the uv_transform to 4x4. The 3x3 causes issues with d3d12/hlsl
|
||||
gfx.SpritePipeline.cp_uv_transforms[i].v[0] = vec4(uv.v[0].x(), uv.v[0].y(), uv.v[0].z(), 0.0);
|
||||
gfx.SpritePipeline.cp_uv_transforms[i].v[1] = vec4(uv.v[1].x(), uv.v[1].y(), uv.v[1].z(), 0.0);
|
||||
gfx.SpritePipeline.cp_uv_transforms[i].v[2] = vec4(uv.v[2].x(), uv.v[2].y(), uv.v[2].z(), 0.0);
|
||||
gfx.SpritePipeline.cp_uv_transforms[i].v[3] = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
gfx.SpritePipeline.cp_sizes[i] = size;
|
||||
i += 1;
|
||||
num_sprites += 1;
|
||||
|
|
@ -98,8 +107,10 @@ fn updatePipeline(
|
|||
|
||||
// Sort sprites back-to-front for draw order, alpha blending
|
||||
const Context = struct {
|
||||
// TODO(d3d12): #1217
|
||||
// changed the uv_transform to 4x4. The 3x3 causes issues with d3d12/hlsl
|
||||
transforms: []Mat4x4,
|
||||
uv_transforms: []Mat3x3,
|
||||
uv_transforms: []Mat4x4,
|
||||
sizes: []Vec2,
|
||||
|
||||
pub fn lessThan(ctx: @This(), a: usize, b: usize) bool {
|
||||
|
|
@ -111,7 +122,9 @@ fn updatePipeline(
|
|||
|
||||
pub fn swap(ctx: @This(), a: usize, b: usize) void {
|
||||
std.mem.swap(Mat4x4, &ctx.transforms[a], &ctx.transforms[b]);
|
||||
std.mem.swap(Mat3x3, &ctx.uv_transforms[a], &ctx.uv_transforms[b]);
|
||||
// TODO(d3d12): #1217
|
||||
// changed the uv_transform to 4x4. The 3x3 causes issues with d3d12/hlsl
|
||||
std.mem.swap(Mat4x4, &ctx.uv_transforms[a], &ctx.uv_transforms[b]);
|
||||
std.mem.swap(Vec2, &ctx.sizes[a], &ctx.sizes[b]);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -110,7 +110,9 @@ const sprite_buffer_cap = 1024 * 512; // TODO(sprite): allow user to specify pre
|
|||
// TODO(sprite): eliminate these, see Sprite.updatePipeline for details on why these exist
|
||||
// currently.
|
||||
pub var cp_transforms: [sprite_buffer_cap]math.Mat4x4 = undefined;
|
||||
pub var cp_uv_transforms: [sprite_buffer_cap]math.Mat3x3 = undefined;
|
||||
// TODO(d3d12): #1217
|
||||
// changed the uv_transform to 4x4. The 3x3 causes issues with d3d12/hlsl
|
||||
pub var cp_uv_transforms: [sprite_buffer_cap]math.Mat4x4 = undefined;
|
||||
pub var cp_sizes: [sprite_buffer_cap]math.Vec2 = undefined;
|
||||
|
||||
/// Which render pass should be used during .render
|
||||
|
|
@ -209,7 +211,9 @@ fn buildPipeline(
|
|||
const uv_transforms = device.createBuffer(&.{
|
||||
.label = label ++ " uv_transforms",
|
||||
.usage = .{ .storage = true, .copy_dst = true },
|
||||
.size = @sizeOf(math.Mat3x3) * sprite_buffer_cap,
|
||||
// TODO(d3d12): #1217
|
||||
// changed the uv_transform to 4x4. The 3x3 causes issues with d3d12/hlsl
|
||||
.size = @sizeOf(math.Mat4x4) * sprite_buffer_cap,
|
||||
.mapped_at_creation = .false,
|
||||
});
|
||||
const sizes = device.createBuffer(&.{
|
||||
|
|
|
|||
|
|
@ -273,6 +273,9 @@ fn updatePipeline(
|
|||
).divScalar(px_density),
|
||||
.size = size.divScalar(px_density),
|
||||
.text_index = num_texts,
|
||||
// TODO(d3d12): #1217
|
||||
// Added padding for d3d12/hlsl. Having 7 floats before the color vec caused and error.
|
||||
.text_padding = 0,
|
||||
.uv_pos = vec2(@floatFromInt(r.x), @floatFromInt(r.y)),
|
||||
.color = font_color,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -134,6 +134,9 @@ pub const Glyph = extern struct {
|
|||
|
||||
/// Which text this glyph belongs to; this is the index for transforms[i], colors[i].
|
||||
text_index: u32,
|
||||
// TODO(d3d12): #1217
|
||||
// Added padding for d3d12/hlsl. Having 7 floats before the color vec caused and error.
|
||||
text_padding: u32,
|
||||
|
||||
/// Color of the glyph
|
||||
color: math.Vec4,
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ struct Uniforms {
|
|||
|
||||
// Sprite UV coordinate transformation matrices. Sprite UV coordinates are (0, 0) at the top-left
|
||||
// corner, and in pixels.
|
||||
@group(0) @binding(2) var<storage, read> sprite_uv_transforms: array<mat3x3<f32>>;
|
||||
// TODO(d3d12): #1217
|
||||
// changed the uv_transform to 4x4. The 3x3 ca@group(0) @binding(2) var<storage, read> sprite_uv_transforms: array<mat4x4<f32>>;
|
||||
@group(0) @binding(2) var<storage, read> sprite_uv_transforms: array<mat4x4<f32>>;
|
||||
|
||||
// Sprite sizes, in pixels.
|
||||
@group(0) @binding(3) var<storage, read> sprite_sizes: array<vec2<f32>>;
|
||||
|
|
@ -70,12 +72,12 @@ fn vertMain(
|
|||
// Currently, our pos_2d and uv coordinates describe a card that covers 1px by 1px; and the UV
|
||||
// coordinates describe using the entire texture. We alter the coordinates to describe the
|
||||
// desired sprite location, size, and apply a subset of the texture instead of the entire texture.
|
||||
var pos = vec4<f32>(pos_2d * sprite_size, 0, 1); // normalized -> pixels
|
||||
var pos = vec4<f32>(pos_2d * sprite_size, 0, 1); // normalized -> pixels
|
||||
pos = sprite_transform * pos; // apply sprite transform (pixels)
|
||||
pos = uniforms.view_projection * pos; // pixels -> normalized
|
||||
|
||||
uv *= sprite_size; // normalized -> pixels
|
||||
uv = (sprite_uv_transform * vec3<f32>(uv, 1)).xy; // apply sprite UV transform (pixels)
|
||||
uv = (sprite_uv_transform * vec4<f32>(uv, 1, 0)).xy; // apply sprite UV transform (pixels)
|
||||
uv /= uniforms.texture_size; // pixels -> normalized
|
||||
|
||||
var output : VertexOutput;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ struct Glyph {
|
|||
// Which text this glyph belongs to; this is the index for transforms[i], colors[i]
|
||||
text_index: u32,
|
||||
|
||||
// TODO(d3d12): #1217
|
||||
// Added padding for d3d12/hlsl. Having 7 floats before the color vec caused and error.
|
||||
text_index2: u32, // Padding for struct alignment
|
||||
|
||||
// Color of the glyph
|
||||
color: vec4<f32>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -413,10 +413,6 @@ pub const Device = struct {
|
|||
}
|
||||
|
||||
pub fn deinit(device: *Device) void {
|
||||
if (device.lost_cb) |lost_cb| {
|
||||
lost_cb(.destroyed, "Device was destroyed.", device.lost_cb_userdata);
|
||||
}
|
||||
|
||||
device.queue.waitUntil(device.queue.fence_value);
|
||||
device.processQueuedOperations();
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ pub fn gen(allocator: std.mem.Allocator, air: *const Air, debug_info: DebugInfo)
|
|||
hlsl.arena.deinit();
|
||||
}
|
||||
|
||||
try hlsl.output.appendSlice(allocator, "#pragma pack_matrix( row_major )\n");
|
||||
|
||||
for (air.refToList(air.globals_index)) |inst_idx| {
|
||||
switch (air.getInst(inst_idx)) {
|
||||
.@"var" => try hlsl.emitGlobalVar(inst_idx),
|
||||
|
|
@ -938,12 +936,14 @@ fn emitBinary(hlsl: *Hlsl, inst: Inst.Binary) !void {
|
|||
const rhs_type = hlsl.air.getInst(inst.rhs_type);
|
||||
|
||||
if (lhs_type == .matrix or rhs_type == .matrix) {
|
||||
// matrices are transposed
|
||||
// TODO(d3d12):
|
||||
// Changed to column major storage because dxc does not apply same ordering to Storage Buffers.
|
||||
// matrices are in column major storage
|
||||
try hlsl.writeAll("mul");
|
||||
try hlsl.writeAll("(");
|
||||
try hlsl.emitExpr(inst.rhs);
|
||||
try hlsl.writeAll(", ");
|
||||
try hlsl.emitExpr(inst.lhs);
|
||||
try hlsl.writeAll(", ");
|
||||
try hlsl.emitExpr(inst.rhs);
|
||||
try hlsl.writeAll(")");
|
||||
} else {
|
||||
try hlsl.emitBinaryOp(inst);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue