mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-31 18:32:12 +00:00
2
.gitignore
vendored
2
.gitignore
vendored
@@ -303,7 +303,7 @@ bin/
|
||||
# - Linux/MacOS
|
||||
odin
|
||||
!odin/
|
||||
odin.dSYM
|
||||
**/*.dSYM
|
||||
*.bin
|
||||
demo.bin
|
||||
libLLVM*.so*
|
||||
|
||||
@@ -712,3 +712,7 @@ Window_setDelegate :: proc "c" (self: ^Window, delegate: ^WindowDelegate) {
|
||||
Window_backingScaleFactor :: proc "c" (self: ^Window) -> Float {
|
||||
return msgSend(Float, self, "backingScaleFactor")
|
||||
}
|
||||
@(objc_type=Window, objc_name="setWantsLayer")
|
||||
Window_setWantsLayer :: proc "c" (self: ^Window, ok: BOOL) {
|
||||
msgSend(nil, self, "setWantsLayer:", ok)
|
||||
}
|
||||
|
||||
24
vendor/glfw/native_linux.odin
vendored
24
vendor/glfw/native_linux.odin
vendored
@@ -2,14 +2,18 @@
|
||||
|
||||
package glfw
|
||||
|
||||
// TODO: Native Linux
|
||||
// Display* glfwGetX11Display(void);
|
||||
// RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor);
|
||||
// RROutput glfwGetX11Monitor(GLFWmonitor* monitor);
|
||||
// Window glfwGetX11Window(GLFWwindow* window);
|
||||
// void glfwSetX11SelectionString(const char* string);
|
||||
// const char* glfwGetX11SelectionString(void);
|
||||
import "vendor:x11/xlib"
|
||||
|
||||
// struct wl_display* glfwGetWaylandDisplay(void);
|
||||
// struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);
|
||||
// struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);
|
||||
@(default_calling_convention="c", link_prefix="glfw")
|
||||
foreign {
|
||||
GetX11Display :: proc() -> ^xlib.Display ---
|
||||
GetX11Window :: proc(window: WindowHandle) -> xlib.Window ---
|
||||
GetX11Adapter :: proc(monitor: MonitorHandle) -> xlib.RRCrtc ---
|
||||
GetX11Monitor :: proc(monitor: MonitorHandle) -> xlib.RROutput ---
|
||||
SetX11SelectionString :: proc(string: cstring) ---
|
||||
GetX11SelectionString :: proc() -> cstring ---
|
||||
|
||||
GetWaylandDisplay :: proc() -> rawptr /* struct wl_display* */ ---
|
||||
GetWaylandWindow :: proc(window: WindowHandle) -> rawptr /* struct wl_surface* */ ---
|
||||
GetWaylandMonitor :: proc(monitor: MonitorHandle) -> rawptr /* struct wl_output* */ ---
|
||||
}
|
||||
|
||||
44
vendor/wasm/js/runtime.js
vendored
44
vendor/wasm/js/runtime.js
vendored
@@ -96,6 +96,10 @@ class WasmMemoryInterface {
|
||||
};
|
||||
loadPtr(addr) { return this.loadU32(addr); }
|
||||
|
||||
loadB32(addr) {
|
||||
return this.loadU32(addr) != 0;
|
||||
}
|
||||
|
||||
loadBytes(ptr, len) {
|
||||
return new Uint8Array(this.memory.buffer, ptr, Number(len));
|
||||
}
|
||||
@@ -104,6 +108,16 @@ class WasmMemoryInterface {
|
||||
const bytes = this.loadBytes(ptr, Number(len));
|
||||
return new TextDecoder().decode(bytes);
|
||||
}
|
||||
|
||||
loadCstring(ptr) {
|
||||
const start = this.loadPtr(ptr);
|
||||
if (start == 0) {
|
||||
return null;
|
||||
}
|
||||
let len = 0;
|
||||
for (; this.mem.getUint8(start+len) != 0; len += 1) {}
|
||||
return this.loadString(start, len);
|
||||
}
|
||||
|
||||
storeU8(addr, value) { this.mem.setUint8 (addr, value); }
|
||||
storeI8(addr, value) { this.mem.setInt8 (addr, value); }
|
||||
@@ -1245,7 +1259,7 @@ class WebGLInterface {
|
||||
};
|
||||
|
||||
|
||||
function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
||||
function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) {
|
||||
const MAX_INFO_CONSOLE_LINES = 512;
|
||||
let infoConsoleLines = new Array();
|
||||
let currentLine = {};
|
||||
@@ -1366,8 +1380,15 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
||||
let event_temp_data = {};
|
||||
|
||||
let webglContext = new WebGLInterface(wasmMemoryInterface);
|
||||
|
||||
const env = {};
|
||||
|
||||
if (memory) {
|
||||
env.memory = memory;
|
||||
}
|
||||
|
||||
return {
|
||||
"env": {},
|
||||
env,
|
||||
"odin_env": {
|
||||
write: (fd, ptr, len) => {
|
||||
const str = wasmMemoryInterface.loadString(ptr, len);
|
||||
@@ -1720,13 +1741,16 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
||||
* @param {string} wasmPath - Path to the WASM module to run
|
||||
* @param {?HTMLPreElement} consoleElement - Optional console/pre element to append output to, in addition to the console
|
||||
* @param {any} extraForeignImports - Imports, in addition to the default runtime to provide the module
|
||||
* @param {?WasmMemoryInterface} wasmMemoryInterface - Optional memory to use instead of the defaults
|
||||
* @param {?int} intSize - Size (in bytes) of the integer type, should be 4 on `js_wasm32` and 8 on `js_wasm64p32`
|
||||
*/
|
||||
async function runWasm(wasmPath, consoleElement, extraForeignImports, intSize = 4) {
|
||||
const wasmMemoryInterface = new WasmMemoryInterface();
|
||||
async function runWasm(wasmPath, consoleElement, extraForeignImports, wasmMemoryInterface, intSize = 4) {
|
||||
if (!wasmMemoryInterface) {
|
||||
wasmMemoryInterface = new WasmMemoryInterface();
|
||||
}
|
||||
wasmMemoryInterface.setIntSize(intSize);
|
||||
|
||||
let imports = odinSetupDefaultImports(wasmMemoryInterface, consoleElement);
|
||||
let imports = odinSetupDefaultImports(wasmMemoryInterface, consoleElement, wasmMemoryInterface.memory);
|
||||
let exports = {};
|
||||
|
||||
if (extraForeignImports !== undefined) {
|
||||
@@ -1741,11 +1765,17 @@ async function runWasm(wasmPath, consoleElement, extraForeignImports, intSize =
|
||||
const wasm = await WebAssembly.instantiate(file, imports);
|
||||
exports = wasm.instance.exports;
|
||||
wasmMemoryInterface.setExports(exports);
|
||||
wasmMemoryInterface.setMemory(exports.memory);
|
||||
|
||||
if (exports.memory) {
|
||||
if (wasmMemoryInterface.memory) {
|
||||
console.warn("WASM module exports memory, but `runWasm` was given an interface with existing memory too");
|
||||
}
|
||||
wasmMemoryInterface.setMemory(exports.memory);
|
||||
}
|
||||
|
||||
exports._start();
|
||||
|
||||
// Define a `@export step :: proc(dt: f32) -> (continue: bool) {`
|
||||
// Define a `@export step :: proc(dt: f32) -> (keep_going: bool) {`
|
||||
// in your app and it will get called every frame.
|
||||
// return `false` to stop the execution of the module.
|
||||
if (exports.step) {
|
||||
|
||||
9
vendor/wgpu/.gitignore
vendored
Normal file
9
vendor/wgpu/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
lib/*
|
||||
!lib/.gitkeep
|
||||
example/web/triangle.wasm
|
||||
example/web/wgpu.js
|
||||
example/web/runtime.js
|
||||
example/example
|
||||
example/example.exe
|
||||
example/triangle
|
||||
example/triangle.exe
|
||||
48
vendor/wgpu/README.md
vendored
Normal file
48
vendor/wgpu/README.md
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# WGPU
|
||||
|
||||
A cross-platform (and WASM) GPU API.
|
||||
|
||||
WASM support is achieved by providing wrappers around the browser native WebGPU API
|
||||
that are called instead of the [wgpu-native](https://github.com/gfx-rs/wgpu-native) library,
|
||||
the wgpu-native library provides support for all other targets.
|
||||
|
||||
Have a look at the `example/` directory for the rendering of a basic triangle.
|
||||
|
||||
## Getting the wgpu-native libraries
|
||||
|
||||
For native support (not the browser), some libraries are required. Fortunately this is
|
||||
extremely easy, just download them from the [releases on GitHub](https://github.com/gfx-rs/wgpu-native/releases/tag/v0.19.4.1),
|
||||
the bindings are for v0.19.4.1 at the moment.
|
||||
|
||||
These are expected in the `lib` folder under the same name as they are released (just unzipped).
|
||||
By default it will look for a static release version (`wgpu-OS-ARCH-release.a|lib`),
|
||||
you can set `-define:WGPU_DEBUG=true` for it to look for a debug version,
|
||||
and use `-define:WGPU_SHARED=true` to look for the shared libraries.
|
||||
|
||||
## WASM
|
||||
|
||||
For WASM, the module has to be built with a function table to enable callbacks.
|
||||
You can do so using `-extra-linker-flags:"--export-table"`.
|
||||
|
||||
Being able to allocate is also required (for some auxiliary APIs but also for mapping/unmapping buffers).
|
||||
|
||||
You can set the context that is used for allocations by setting the global variable `wpgu.g_context`.
|
||||
It will default to the `runtime.default_context`.
|
||||
|
||||
Again, have a look at the `example/` and how it is set up, doing the `--import-memory` and the likes
|
||||
is not strictly necessary but allows your app more memory than the minimal default.
|
||||
|
||||
The bindings work on both `-target:js_wasm32` and `-target:js_wasm64p32`.
|
||||
|
||||
## GLFW Glue
|
||||
|
||||
There is an inner package `glfwglue` that can be used to glue together WGPU and GLFW.
|
||||
It exports one procedure `GetSurface(wgpu.Instance, glfw.WindowHandle) -> glfw.Surface`.
|
||||
The procedure will call the needed target specific procedures and return a surface configured
|
||||
for the given window.
|
||||
|
||||
To support Wayland on Linux, you need to have GLFW compiled to support it, and use
|
||||
`-define:WGPU_GFLW_GLUE_SUPPORT_WAYLAND=true` to enable the package to check for Wayland.
|
||||
|
||||
Do note that wgpu does not require GLFW, you can use native windows or another windowing library too.
|
||||
For that you can take inspiration from `glfwglue` on glueing them together.
|
||||
17
vendor/wgpu/example/Makefile
vendored
Normal file
17
vendor/wgpu/example/Makefile
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
FILES := $(wildcard *)
|
||||
|
||||
# NOTE: changing this requires changing the same values in the `web/index.html`.
|
||||
INITIAL_MEMORY_PAGES := 2000
|
||||
MAX_MEMORY_PAGES := 65536
|
||||
|
||||
PAGE_SIZE := 65536
|
||||
INITIAL_MEMORY_BYTES := $(shell expr $(INITIAL_MEMORY_PAGES) \* $(PAGE_SIZE))
|
||||
MAX_MEMORY_BYTES := $(shell expr $(MAX_MEMORY_PAGES) \* $(PAGE_SIZE))
|
||||
|
||||
web/triangle.wasm: $(FILES) ../wgpu.js ../../wasm/js/runtime.js
|
||||
odin build . \
|
||||
-target:js_wasm32 -out:web/triangle.wasm -o:size \
|
||||
-extra-linker-flags:"--export-table --import-memory --initial-memory=$(INITIAL_MEMORY_BYTES) --max-memory=$(MAX_MEMORY_BYTES)"
|
||||
|
||||
cp ../wgpu.js web/wgpu.js
|
||||
cp ../../wasm/js/runtime.js web/runtime.js
|
||||
12
vendor/wgpu/example/build.bat
vendored
Normal file
12
vendor/wgpu/example/build.bat
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
REM NOTE: changing this requires changing the same values in the `web/index.html`.
|
||||
set INITIAL_MEMORY_PAGES=2000
|
||||
set MAX_MEMORY_PAGES=65536
|
||||
|
||||
set PAGE_SIZE=65536
|
||||
set /a INITIAL_MEMORY_BYTES=%INITIAL_MEMORY_PAGES% * %PAGE_SIZE%
|
||||
set /a MAX_MEMORY_BYTES=%MAX_MEMORY_PAGES% * %PAGE_SIZE%
|
||||
|
||||
call odin.exe build . -target:js_wasm32 -out:web/triangle.wasm -o:size -extra-linker-flags:"--export-table --import-memory --initial-memory=%INITIAL_MEMORY_BYTES% --max-memory=%MAX_MEMORY_BYTES%"
|
||||
|
||||
copy "..\wgpu.js" "web\wgpu.js"
|
||||
copy "..\..\wasm\js\runtime.js" "web\runtime.js"
|
||||
187
vendor/wgpu/example/main.odin
vendored
Normal file
187
vendor/wgpu/example/main.odin
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
package vendor_wgpu_example_triangle
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
import "core:fmt"
|
||||
|
||||
import "vendor:wgpu"
|
||||
|
||||
State :: struct {
|
||||
ctx: runtime.Context,
|
||||
os: OS,
|
||||
|
||||
instance: wgpu.Instance,
|
||||
surface: wgpu.Surface,
|
||||
adapter: wgpu.Adapter,
|
||||
device: wgpu.Device,
|
||||
config: wgpu.SurfaceConfiguration,
|
||||
queue: wgpu.Queue,
|
||||
module: wgpu.ShaderModule,
|
||||
pipeline_layout: wgpu.PipelineLayout,
|
||||
pipeline: wgpu.RenderPipeline,
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
state: State
|
||||
|
||||
main :: proc() {
|
||||
state.ctx = context
|
||||
|
||||
os_init(&state.os)
|
||||
|
||||
state.instance = wgpu.CreateInstance(nil)
|
||||
if state.instance == nil {
|
||||
panic("WebGPU is not supported")
|
||||
}
|
||||
state.surface = os_get_surface(&state.os, state.instance)
|
||||
|
||||
wgpu.InstanceRequestAdapter(state.instance, &{ compatibleSurface = state.surface }, on_adapter, nil)
|
||||
|
||||
on_adapter :: proc "c" (status: wgpu.RequestAdapterStatus, adapter: wgpu.Adapter, message: cstring, userdata: rawptr) {
|
||||
context = state.ctx
|
||||
if status != .Success || adapter == nil {
|
||||
fmt.panicf("request adapter failure: [%v] %s", status, message)
|
||||
}
|
||||
state.adapter = adapter
|
||||
wgpu.AdapterRequestDevice(adapter, nil, on_device)
|
||||
}
|
||||
|
||||
on_device :: proc "c" (status: wgpu.RequestDeviceStatus, device: wgpu.Device, message: cstring, userdata: rawptr) {
|
||||
context = state.ctx
|
||||
if status != .Success || device == nil {
|
||||
fmt.panicf("request device failure: [%v] %s", status, message)
|
||||
}
|
||||
state.device = device
|
||||
|
||||
width, height := os_get_render_bounds(&state.os)
|
||||
|
||||
state.config = wgpu.SurfaceConfiguration {
|
||||
device = state.device,
|
||||
usage = { .RenderAttachment },
|
||||
format = .BGRA8Unorm,
|
||||
width = width,
|
||||
height = height,
|
||||
presentMode = .Fifo,
|
||||
alphaMode = .Opaque,
|
||||
}
|
||||
wgpu.SurfaceConfigure(state.surface, &state.config)
|
||||
|
||||
state.queue = wgpu.DeviceGetQueue(state.device)
|
||||
|
||||
shader :: `
|
||||
@vertex
|
||||
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
|
||||
let x = f32(i32(in_vertex_index) - 1);
|
||||
let y = f32(i32(in_vertex_index & 1u) * 2 - 1);
|
||||
return vec4<f32>(x, y, 0.0, 1.0);
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main() -> @location(0) vec4<f32> {
|
||||
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
|
||||
}`
|
||||
|
||||
state.module = wgpu.DeviceCreateShaderModule(state.device, &{
|
||||
nextInChain = &wgpu.ShaderModuleWGSLDescriptor{
|
||||
sType = .ShaderModuleWGSLDescriptor,
|
||||
code = shader,
|
||||
},
|
||||
})
|
||||
|
||||
state.pipeline_layout = wgpu.DeviceCreatePipelineLayout(state.device, &{})
|
||||
state.pipeline = wgpu.DeviceCreateRenderPipeline(state.device, &{
|
||||
layout = state.pipeline_layout,
|
||||
vertex = {
|
||||
module = state.module,
|
||||
entryPoint = "vs_main",
|
||||
},
|
||||
fragment = &{
|
||||
module = state.module,
|
||||
entryPoint = "fs_main",
|
||||
targetCount = 1,
|
||||
targets = &wgpu.ColorTargetState{
|
||||
format = .BGRA8Unorm,
|
||||
writeMask = wgpu.ColorWriteMaskFlags_All,
|
||||
},
|
||||
},
|
||||
primitive = {
|
||||
topology = .TriangleList,
|
||||
|
||||
},
|
||||
multisample = {
|
||||
count = 1,
|
||||
mask = 0xFFFFFFFF,
|
||||
},
|
||||
})
|
||||
|
||||
os_run(&state.os)
|
||||
}
|
||||
}
|
||||
|
||||
resize :: proc "c" () {
|
||||
context = state.ctx
|
||||
|
||||
state.config.width, state.config.height = os_get_render_bounds(&state.os)
|
||||
wgpu.SurfaceConfigure(state.surface, &state.config)
|
||||
}
|
||||
|
||||
frame :: proc "c" (dt: f32) {
|
||||
context = state.ctx
|
||||
|
||||
surface_texture := wgpu.SurfaceGetCurrentTexture(state.surface)
|
||||
switch surface_texture.status {
|
||||
case .Success:
|
||||
// All good, could check for `surface_texture.suboptimal` here.
|
||||
case .Timeout, .Outdated, .Lost:
|
||||
// Skip this frame, and re-configure surface.
|
||||
if surface_texture.texture != nil {
|
||||
wgpu.TextureRelease(surface_texture.texture)
|
||||
}
|
||||
resize()
|
||||
return
|
||||
case .OutOfMemory, .DeviceLost:
|
||||
// Fatal error
|
||||
fmt.panicf("[triangle] get_current_texture status=%v", surface_texture.status)
|
||||
}
|
||||
defer wgpu.TextureRelease(surface_texture.texture)
|
||||
|
||||
frame := wgpu.TextureCreateView(surface_texture.texture, nil)
|
||||
defer wgpu.TextureViewRelease(frame)
|
||||
|
||||
command_encoder := wgpu.DeviceCreateCommandEncoder(state.device, nil)
|
||||
defer wgpu.CommandEncoderRelease(command_encoder)
|
||||
|
||||
render_pass_encoder := wgpu.CommandEncoderBeginRenderPass(
|
||||
command_encoder, &{
|
||||
colorAttachmentCount = 1,
|
||||
colorAttachments = &wgpu.RenderPassColorAttachment{
|
||||
view = frame,
|
||||
loadOp = .Clear,
|
||||
storeOp = .Store,
|
||||
clearValue = { r = 0, g = 1, b = 0, a = 1 },
|
||||
},
|
||||
},
|
||||
)
|
||||
defer wgpu.RenderPassEncoderRelease(render_pass_encoder)
|
||||
|
||||
wgpu.RenderPassEncoderSetPipeline(render_pass_encoder, state.pipeline)
|
||||
wgpu.RenderPassEncoderDraw(render_pass_encoder, vertexCount=3, instanceCount=1, firstVertex=0, firstInstance=0)
|
||||
wgpu.RenderPassEncoderEnd(render_pass_encoder)
|
||||
|
||||
command_buffer := wgpu.CommandEncoderFinish(command_encoder, nil)
|
||||
defer wgpu.CommandBufferRelease(command_buffer)
|
||||
|
||||
wgpu.QueueSubmit(state.queue, { command_buffer })
|
||||
wgpu.SurfacePresent(state.surface)
|
||||
}
|
||||
|
||||
finish :: proc() {
|
||||
wgpu.RenderPipelineRelease(state.pipeline)
|
||||
wgpu.PipelineLayoutRelease(state.pipeline_layout)
|
||||
wgpu.ShaderModuleRelease(state.module)
|
||||
wgpu.QueueRelease(state.queue)
|
||||
wgpu.DeviceRelease(state.device)
|
||||
wgpu.AdapterRelease(state.adapter)
|
||||
wgpu.SurfaceRelease(state.surface)
|
||||
wgpu.InstanceRelease(state.instance)
|
||||
}
|
||||
55
vendor/wgpu/example/os_glfw.odin
vendored
Normal file
55
vendor/wgpu/example/os_glfw.odin
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
//+build !js
|
||||
package vendor_wgpu_example_triangle
|
||||
|
||||
import "core:time"
|
||||
|
||||
import "vendor:glfw"
|
||||
import "vendor:wgpu"
|
||||
import "vendor:wgpu/glfwglue"
|
||||
|
||||
OS :: struct {
|
||||
window: glfw.WindowHandle,
|
||||
}
|
||||
|
||||
os_init :: proc(os: ^OS) {
|
||||
if !glfw.Init() {
|
||||
panic("[glfw] init failure")
|
||||
}
|
||||
|
||||
glfw.WindowHint(glfw.CLIENT_API, glfw.NO_API)
|
||||
os.window = glfw.CreateWindow(960, 540, "WGPU Native Triangle", nil, nil)
|
||||
|
||||
glfw.SetFramebufferSizeCallback(os.window, size_callback)
|
||||
}
|
||||
|
||||
os_run :: proc(os: ^OS) {
|
||||
dt: f32
|
||||
|
||||
for !glfw.WindowShouldClose(os.window) {
|
||||
start := time.tick_now()
|
||||
|
||||
glfw.PollEvents()
|
||||
frame(dt)
|
||||
|
||||
dt = f32(time.duration_seconds(time.tick_since(start)))
|
||||
}
|
||||
|
||||
finish()
|
||||
|
||||
glfw.DestroyWindow(os.window)
|
||||
glfw.Terminate()
|
||||
}
|
||||
|
||||
os_get_render_bounds :: proc(os: ^OS) -> (width, height: u32) {
|
||||
iw, ih := glfw.GetWindowSize(os.window)
|
||||
return u32(iw), u32(ih)
|
||||
}
|
||||
|
||||
os_get_surface :: proc(os: ^OS, instance: wgpu.Instance) -> wgpu.Surface {
|
||||
return glfwglue.GetSurface(instance, os.window)
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
size_callback :: proc "c" (window: glfw.WindowHandle, width, height: i32) {
|
||||
resize()
|
||||
}
|
||||
60
vendor/wgpu/example/os_js.odin
vendored
Normal file
60
vendor/wgpu/example/os_js.odin
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
package vendor_wgpu_example_triangle
|
||||
|
||||
import "vendor:wgpu"
|
||||
import "vendor:wasm/js"
|
||||
|
||||
OS :: struct {
|
||||
initialized: bool,
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
g_os: ^OS
|
||||
|
||||
os_init :: proc(os: ^OS) {
|
||||
g_os = os
|
||||
assert(js.add_window_event_listener(.Resize, nil, size_callback))
|
||||
}
|
||||
|
||||
// NOTE: frame loop is done by the runtime.js repeatedly calling `step`.
|
||||
os_run :: proc(os: ^OS) {
|
||||
os.initialized = true
|
||||
}
|
||||
|
||||
os_get_render_bounds :: proc(os: ^OS) -> (width, height: u32) {
|
||||
rect := js.get_bounding_client_rect("body")
|
||||
return u32(rect.width), u32(rect.height)
|
||||
}
|
||||
|
||||
os_get_surface :: proc(os: ^OS, instance: wgpu.Instance) -> wgpu.Surface {
|
||||
return wgpu.InstanceCreateSurface(
|
||||
instance,
|
||||
&wgpu.SurfaceDescriptor{
|
||||
nextInChain = &wgpu.SurfaceDescriptorFromCanvasHTMLSelector{
|
||||
sType = .SurfaceDescriptorFromCanvasHTMLSelector,
|
||||
selector = "#wgpu-canvas",
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@(private="file", export)
|
||||
step :: proc(dt: f32) -> bool {
|
||||
if !g_os.initialized {
|
||||
return true
|
||||
}
|
||||
|
||||
frame(dt)
|
||||
return true
|
||||
}
|
||||
|
||||
@(private="file", fini)
|
||||
os_fini :: proc() {
|
||||
js.remove_window_event_listener(.Resize, nil, size_callback)
|
||||
|
||||
finish()
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
size_callback :: proc(e: js.Event) {
|
||||
resize()
|
||||
}
|
||||
23
vendor/wgpu/example/web/index.html
vendored
Normal file
23
vendor/wgpu/example/web/index.html
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" style="height: 100%;">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>WGPU WASM Triangle</title>
|
||||
</head>
|
||||
<body id="body" style="height: 100%; padding: 0; margin: 0; overflow: hidden;">
|
||||
<canvas id="wgpu-canvas"></canvas>
|
||||
|
||||
<script type="text/javascript" src="runtime.js"></script>
|
||||
<script type="text/javascript" src="wgpu.js"></script>
|
||||
<script type="text/javascript">
|
||||
const mem = new WebAssembly.Memory({ initial: 2000, maximum: 65536, shared: false });
|
||||
const memInterface = new odin.WasmMemoryInterface();
|
||||
memInterface.setMemory(mem);
|
||||
|
||||
const wgpuInterface = new odin.WebGPUInterface(memInterface);
|
||||
|
||||
odin.runWasm("triangle.wasm", null, { wgpu: wgpuInterface.getInterface() }, memInterface, /*intSize=8*/);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
6
vendor/wgpu/glfwglue/glue.odin
vendored
Normal file
6
vendor/wgpu/glfwglue/glue.odin
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
//+build !linux
|
||||
//+build !windows
|
||||
//+build !darwin
|
||||
package wgpu_glfw_glue
|
||||
|
||||
#panic("package wgpu/glfwglue is not supported on the current target")
|
||||
23
vendor/wgpu/glfwglue/glue_darwin.odin
vendored
Normal file
23
vendor/wgpu/glfwglue/glue_darwin.odin
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package wgpu_glfw_glue
|
||||
|
||||
import "vendor:glfw"
|
||||
import "vendor:wgpu"
|
||||
import CA "vendor:darwin/QuartzCore"
|
||||
|
||||
GetSurface :: proc(instance: wgpu.Instance, window: glfw.WindowHandle) -> wgpu.Surface {
|
||||
ns_window := glfw.GetCocoaWindow(window)
|
||||
ns_window->contentView()->setWantsLayer(true)
|
||||
metal_layer := CA.MetalLayer_layer()
|
||||
ns_window->contentView()->setLayer(metal_layer)
|
||||
return wgpu.InstanceCreateSurface(
|
||||
instance,
|
||||
&wgpu.SurfaceDescriptor{
|
||||
nextInChain = &wgpu.SurfaceDescriptorFromMetalLayer{
|
||||
chain = wgpu.ChainedStruct{
|
||||
sType = .SurfaceDescriptorFromMetalLayer,
|
||||
},
|
||||
layer = rawptr(metal_layer),
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
43
vendor/wgpu/glfwglue/glue_linux.odin
vendored
Normal file
43
vendor/wgpu/glfwglue/glue_linux.odin
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package wgpu_glfw_glue
|
||||
|
||||
import "vendor:glfw"
|
||||
import "vendor:wgpu"
|
||||
|
||||
// GLFW needs to be compiled with wayland support for this to work.
|
||||
SUPPORT_WAYLAND :: #config(WGPU_GFLW_GLUE_SUPPORT_WAYLAND, false)
|
||||
|
||||
GetSurface :: proc(instance: wgpu.Instance, window: glfw.WindowHandle) -> wgpu.Surface {
|
||||
when SUPPORT_WAYLAND {
|
||||
if glfw.GetPlatform() == glfw.PLATFORM_WAYLAND {
|
||||
display := glfw.GetWaylandDisplay()
|
||||
surface := glfw.GetWaylandWindow(window)
|
||||
return wgpu.InstanceCreateSurface(
|
||||
instance,
|
||||
&wgpu.SurfaceDescriptor{
|
||||
nextInChain = &wgpu.SurfaceDescriptorFromWaylandSurface{
|
||||
chain = {
|
||||
sType = .SurfaceDescriptorFromWaylandSurface,
|
||||
},
|
||||
display = display,
|
||||
surface = surface,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
display := glfw.GetX11Display()
|
||||
window := glfw.GetX11Window(window)
|
||||
return wgpu.InstanceCreateSurface(
|
||||
instance,
|
||||
&wgpu.SurfaceDescriptor{
|
||||
nextInChain = &wgpu.SurfaceDescriptorFromXlibWindow{
|
||||
chain = {
|
||||
sType = .SurfaceDescriptorFromXlibWindow,
|
||||
},
|
||||
display = display,
|
||||
window = u64(window),
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
23
vendor/wgpu/glfwglue/glue_windows.odin
vendored
Normal file
23
vendor/wgpu/glfwglue/glue_windows.odin
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package wgpu_glfw_glue
|
||||
|
||||
import win "core:sys/windows"
|
||||
|
||||
import "vendor:glfw"
|
||||
import "vendor:wgpu"
|
||||
|
||||
GetSurface :: proc(instance: wgpu.Instance, window: glfw.WindowHandle) -> wgpu.Surface {
|
||||
hwnd := glfw.GetWin32Window(window)
|
||||
hinstance := win.GetModuleHandleW(nil)
|
||||
return wgpu.InstanceCreateSurface(
|
||||
instance,
|
||||
&wgpu.SurfaceDescriptor{
|
||||
nextInChain = &wgpu.SurfaceDescriptorFromWindowsHWND{
|
||||
chain = wgpu.ChainedStruct{
|
||||
sType = .SurfaceDescriptorFromWindowsHWND,
|
||||
},
|
||||
hinstance = rawptr(hinstance),
|
||||
hwnd = rawptr(hwnd),
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
0
vendor/wgpu/lib/.gitkeep
vendored
Normal file
0
vendor/wgpu/lib/.gitkeep
vendored
Normal file
2916
vendor/wgpu/wgpu.js
vendored
Normal file
2916
vendor/wgpu/wgpu.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1636
vendor/wgpu/wgpu.odin
vendored
Normal file
1636
vendor/wgpu/wgpu.odin
vendored
Normal file
File diff suppressed because it is too large
Load Diff
26
vendor/wgpu/wgpu_js.odin
vendored
Normal file
26
vendor/wgpu/wgpu_js.odin
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
package wgpu
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
g_context: runtime.Context
|
||||
|
||||
@(private="file", init)
|
||||
wgpu_init_allocator :: proc() {
|
||||
if g_context.allocator.procedure == nil {
|
||||
g_context = runtime.default_context()
|
||||
}
|
||||
}
|
||||
|
||||
@(private="file", export)
|
||||
wgpu_alloc :: proc "contextless" (size: i32) -> [^]byte {
|
||||
context = g_context
|
||||
bytes, err := runtime.mem_alloc(int(size), 16)
|
||||
assert(err == nil, "wgpu_alloc failed")
|
||||
return raw_data(bytes)
|
||||
}
|
||||
|
||||
@(private="file", export)
|
||||
wgpu_free :: proc "contextless" (ptr: rawptr) {
|
||||
context = g_context
|
||||
assert(free(ptr) == nil, "wgpu_free failed")
|
||||
}
|
||||
75
vendor/wgpu/wgpu_native.odin
vendored
Normal file
75
vendor/wgpu/wgpu_native.odin
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
//+build !js
|
||||
package wgpu
|
||||
|
||||
BINDINGS_VERSION :: [4]u8{0, 19, 4, 1}
|
||||
BINDINGS_VERSION_STRING :: "0.19.4.1"
|
||||
|
||||
@(private="file", init)
|
||||
wgpu_native_version_check :: proc() {
|
||||
v := (transmute([4]u8)GetVersion()).wzyx
|
||||
|
||||
if v != BINDINGS_VERSION {
|
||||
buf: [1024]byte
|
||||
n := copy(buf[:], "wgpu-native version mismatch: ")
|
||||
n += copy(buf[n:], "bindings are for version ")
|
||||
n += copy(buf[n:], BINDINGS_VERSION_STRING)
|
||||
n += copy(buf[n:], ", but a different version is linked")
|
||||
panic(string(buf[:n]))
|
||||
}
|
||||
}
|
||||
|
||||
@(link_prefix="wgpu")
|
||||
foreign {
|
||||
@(link_name="wgpuGenerateReport")
|
||||
RawGenerateReport :: proc(instance: Instance, report: ^GlobalReport) ---
|
||||
@(link_name="wgpuInstanceEnumerateAdapters")
|
||||
RawInstanceEnumerateAdapters :: proc(instance: Instance, /* NULLABLE */ options: /* const */ ^InstanceEnumerateAdapterOptions, adapters: [^]Adapter) -> uint ---
|
||||
|
||||
@(link_name="wgpuQueueSubmitForIndex")
|
||||
RawQueueSubmitForIndex :: proc(queue: Queue, commandCount: uint, commands: [^]CommandBuffer) -> SubmissionIndex ---
|
||||
|
||||
// Returns true if the queue is empty, or false if there are more queue submissions still in flight.
|
||||
@(link_name="wgpuDevicePoll")
|
||||
RawDevicePoll :: proc(device: Device, wait: b32, /* NULLABLE */ wrappedSubmissionIndex: /* const */ ^WrappedSubmissionIndex) -> b32 ---
|
||||
|
||||
SetLogCallback :: proc "odin" (callback: LogCallback) ---
|
||||
|
||||
SetLogLevel :: proc(level: LogLevel) ---
|
||||
|
||||
GetVersion :: proc() -> u32 ---
|
||||
|
||||
RenderPassEncoderSetPushConstants :: proc(encoder: RenderPassEncoder, stages: ShaderStageFlags, offset: u32, sizeBytes: u32, data: cstring) ---
|
||||
|
||||
RenderPassEncoderMultiDrawIndirect :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count: u32) ---
|
||||
RenderPassEncoderMultiDrawIndexedIndirect :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count: u32) ---
|
||||
|
||||
RenderPassEncoderMultiDrawIndirectCount :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count_buffer: Buffer, count_buffer_offset: u64, max_count: u32) ---
|
||||
RenderPassEncoderMultiDrawIndexedIndirectCount :: proc(encoder: RenderPassEncoder, buffer: Buffer, offset: u64, count_buffer: Buffer, count_buffer_offset: u64, max_count: u32) ---
|
||||
|
||||
ComputePassEncoderBeginPipelineStatisticsQuery :: proc(computePassEncoder: ComputePassEncoder, querySet: QuerySet, queryIndex: u32) ---
|
||||
ComputePassEncoderEndPipelineStatisticsQuery :: proc(computePassEncoder: ComputePassEncoder) ---
|
||||
RenderPassEncoderBeginPipelineStatisticsQuery :: proc(renderPassEncoder: RenderPassEncoder, querySet: QuerySet, queryIndex: u32) ---
|
||||
RenderPassEncoderEndPipelineStatisticsQuery :: proc(renderPassEncoder: RenderPassEncoder) ---
|
||||
}
|
||||
|
||||
GenerateReport :: proc(instance: Instance) -> (report: GlobalReport) {
|
||||
RawGenerateReport(instance, &report)
|
||||
return
|
||||
}
|
||||
|
||||
InstanceEnumerateAdapters :: proc(instance: Instance, options: ^InstanceEnumerateAdapterOptions = nil, allocator := context.allocator) -> (adapters: []Adapter) {
|
||||
count := RawInstanceEnumerateAdapters(instance, options, nil)
|
||||
adapters = make([]Adapter, count, allocator)
|
||||
RawInstanceEnumerateAdapters(instance, options, raw_data(adapters))
|
||||
return
|
||||
}
|
||||
|
||||
QueueSubmitForIndex :: proc(queue: Queue, commands: []CommandBuffer) -> SubmissionIndex {
|
||||
return RawQueueSubmitForIndex(queue, len(commands), raw_data(commands))
|
||||
}
|
||||
|
||||
DevicePoll :: proc(device: Device, wait: b32) -> (wrappedSubmissionIndex: WrappedSubmissionIndex, ok: bool) {
|
||||
ok = bool(RawDevicePoll(device, wait, &wrappedSubmissionIndex))
|
||||
return
|
||||
}
|
||||
|
||||
212
vendor/wgpu/wgpu_native_types.odin
vendored
Normal file
212
vendor/wgpu/wgpu_native_types.odin
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
package wgpu
|
||||
|
||||
import "base:runtime"
|
||||
|
||||
LogLevel :: enum i32 {
|
||||
Off,
|
||||
Error,
|
||||
Warn,
|
||||
Info,
|
||||
Debug,
|
||||
Trace,
|
||||
}
|
||||
|
||||
InstanceBackend :: enum i32 {
|
||||
Vulkan,
|
||||
GL,
|
||||
Metal,
|
||||
DX12,
|
||||
DX11,
|
||||
BrowserWebGPU,
|
||||
}
|
||||
InstanceBackendFlags :: bit_set[InstanceBackend; Flags]
|
||||
InstanceBackendFlags_All :: InstanceBackendFlags{}
|
||||
InstanceBackendFlags_Primary :: InstanceBackendFlags{ .Vulkan, .Metal, .DX12, .BrowserWebGPU }
|
||||
InstanceBackendFlags_Secondary :: InstanceBackendFlags{ .GL, .DX11 }
|
||||
|
||||
InstanceFlag :: enum i32 {
|
||||
Debug,
|
||||
Validation,
|
||||
DiscardHalLabels,
|
||||
}
|
||||
InstanceFlags :: bit_set[InstanceFlag; Flags]
|
||||
InstanceFlags_Default :: InstanceFlags{}
|
||||
|
||||
Dx12Compiler :: enum i32 {
|
||||
Undefined,
|
||||
Fxc,
|
||||
Dxc,
|
||||
}
|
||||
|
||||
Gles3MinorVersion :: enum i32 {
|
||||
Automatic,
|
||||
Version0,
|
||||
Version1,
|
||||
Version2,
|
||||
}
|
||||
|
||||
PipelineStatisticName :: enum i32 {
|
||||
VertexShaderInvocations,
|
||||
ClipperInvocations,
|
||||
ClipperPrimitivesOut,
|
||||
FragmentShaderInvocations,
|
||||
ComputeShaderInvocations,
|
||||
}
|
||||
|
||||
InstanceExtras :: struct {
|
||||
using chain: ChainedStruct,
|
||||
backends: InstanceBackendFlags,
|
||||
flags: InstanceFlags,
|
||||
dx12ShaderCompiler: Dx12Compiler,
|
||||
gles3MinorVersion: Gles3MinorVersion,
|
||||
dxilPath: cstring,
|
||||
dxcPath: cstring,
|
||||
}
|
||||
|
||||
DeviceExtras :: struct {
|
||||
using chain: ChainedStruct,
|
||||
tracePath: cstring,
|
||||
}
|
||||
|
||||
NativeLimits :: struct {
|
||||
maxPushConstantSize: u32,
|
||||
maxNonSamplerBindings: u32,
|
||||
}
|
||||
|
||||
RequiredLimitsExtras :: struct {
|
||||
using chain: ChainedStruct,
|
||||
limits: NativeLimits,
|
||||
}
|
||||
|
||||
SupportedLimitsExtras :: struct {
|
||||
using chain: ChainedStruct,
|
||||
limits: NativeLimits,
|
||||
}
|
||||
|
||||
PushConstantRange :: struct {
|
||||
stages: ShaderStageFlags,
|
||||
start: u32,
|
||||
end: u32,
|
||||
}
|
||||
|
||||
PipelineLayoutExtras :: struct {
|
||||
using chain: ChainedStruct,
|
||||
pushConstantRangeCount: uint,
|
||||
pushConstantRanges: [^]PushConstantRange `fmt:"v,pushConstantRangeCount"`,
|
||||
}
|
||||
|
||||
SubmissionIndex :: distinct u64
|
||||
|
||||
WrappedSubmissionIndex :: struct {
|
||||
queue: Queue,
|
||||
submissionIndex: SubmissionIndex,
|
||||
}
|
||||
|
||||
ShaderDefine :: struct {
|
||||
name: cstring,
|
||||
value: cstring,
|
||||
}
|
||||
|
||||
ShaderModuleGLSLDescriptor :: struct {
|
||||
using chain: ChainedStruct,
|
||||
stage: ShaderStage,
|
||||
code: cstring,
|
||||
defineCount: uint,
|
||||
defines: [^]ShaderDefine `fmt:"v,defineCount"`,
|
||||
}
|
||||
|
||||
RegistryReport :: struct {
|
||||
numAllocated: uint,
|
||||
numKeptFromUser: uint,
|
||||
numReleasedFromUser: uint,
|
||||
numErrors: uint,
|
||||
elementSize: uint,
|
||||
}
|
||||
|
||||
HubReport :: struct {
|
||||
adapters: RegistryReport,
|
||||
devices: RegistryReport,
|
||||
queues: RegistryReport,
|
||||
pipelineLayouts: RegistryReport,
|
||||
shaderModules: RegistryReport,
|
||||
bindGroupLayouts: RegistryReport,
|
||||
bindGroups: RegistryReport,
|
||||
commandBuffers: RegistryReport,
|
||||
renderBundles: RegistryReport,
|
||||
renderPipelines: RegistryReport,
|
||||
computePipelines: RegistryReport,
|
||||
querySets: RegistryReport,
|
||||
buffers: RegistryReport,
|
||||
textures: RegistryReport,
|
||||
textureViews: RegistryReport,
|
||||
samplers: RegistryReport,
|
||||
}
|
||||
|
||||
GlobalReport :: struct {
|
||||
surfaces: RegistryReport,
|
||||
backendType: BackendType,
|
||||
vulkan: HubReport,
|
||||
metal: HubReport,
|
||||
dx12: HubReport,
|
||||
gl: HubReport,
|
||||
}
|
||||
|
||||
InstanceEnumerateAdapterOptions :: struct {
|
||||
nextInChain: ^ChainedStruct,
|
||||
backends: InstanceBackendFlags,
|
||||
}
|
||||
|
||||
BindGroupEntryExtras :: struct {
|
||||
using chain: ChainedStruct,
|
||||
buffers: [^]Buffer `fmt:"v,bufferCount"`,
|
||||
bufferCount: uint,
|
||||
samplers: [^]Sampler `fmt:"v,samplerCount"`,
|
||||
samplerCount: uint,
|
||||
textureViews: [^]TextureView `fmt:"v,textureViewCount"`,
|
||||
textureViewCount: uint,
|
||||
}
|
||||
|
||||
BindGroupLayoutEntryExtras :: struct {
|
||||
using chain: ChainedStruct,
|
||||
count: u32,
|
||||
}
|
||||
|
||||
QuerySetDescriptorExtras :: struct {
|
||||
using chain: ChainedStruct,
|
||||
pipelineStatistics: [^]PipelineStatisticName `fmt:"v,pipelineStatisticCount"`,
|
||||
pipelineStatisticCount: uint,
|
||||
}
|
||||
|
||||
SurfaceConfigurationExtras :: struct {
|
||||
using chain: ChainedStruct,
|
||||
desiredMaximumFrameLatency: i32,
|
||||
}
|
||||
|
||||
LogCallback :: #type proc "odin" (level: LogLevel, message: cstring)
|
||||
|
||||
// Wrappers
|
||||
|
||||
ConvertOdinToWGPULogLevel :: proc(level: runtime.Logger_Level) -> LogLevel {
|
||||
switch {
|
||||
case level < .Debug: return .Trace
|
||||
case level < .Info: return .Debug
|
||||
case level < .Warning: return .Info
|
||||
case level < .Error: return .Warn
|
||||
case: return .Error
|
||||
}
|
||||
}
|
||||
|
||||
ConvertWGPUToOdinLogLevel :: proc(level: LogLevel) -> runtime.Logger_Level {
|
||||
switch level {
|
||||
case .Off, .Trace, .Debug: return .Debug
|
||||
case .Info: return .Info
|
||||
case .Warn: return .Warning
|
||||
case .Error: return .Error
|
||||
case: return .Error
|
||||
}
|
||||
}
|
||||
|
||||
ConvertLogLevel :: proc {
|
||||
ConvertOdinToWGPULogLevel,
|
||||
ConvertWGPUToOdinLogLevel,
|
||||
}
|
||||
3
vendor/x11/xlib/xlib_types.odin
vendored
3
vendor/x11/xlib/xlib_types.odin
vendored
@@ -24,6 +24,9 @@ Cursor :: XID
|
||||
Colormap :: XID
|
||||
GContext :: XID
|
||||
|
||||
RRCrtc :: XID
|
||||
RROutput :: XID
|
||||
|
||||
KeyCode :: u8
|
||||
|
||||
/* ---- X11/Xlib.h ---------------------------------------------------------*/
|
||||
|
||||
Reference in New Issue
Block a user