wip(0.S3): outside the runtime, its drawable size, scale, screen and tile size are read and set through its functions; a migration reports such a reference instead of threading the runtime's state

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-25 15:47:21 +03:00
parent d70b00f30d
commit 7b17b4a1b9
15 changed files with 46529 additions and 46216 deletions

View file

@ -110,7 +110,7 @@ function dungeon_exit_cell(side: int) -> IVec2 {
}
# where a body of w x h px starts after entering from `side`, `inset` px inside the edge
@Namespace(Dungeon) function dungeon_entry_point(side: int, inset: int, w: int, h: int) -> IVec2 {
let tile = rt_map_tile_px
let tile = rt_map_tile_size()
let across_x = (dungeon_door_column() + 1) * tile - w / 2
let across_y = dungeon_door_row() * tile + (2 * tile - h) / 2
match side {

View file

@ -141,7 +141,7 @@ function ds_report(render3d_st: mut Render3dState) -> void {
pass_inst[render3d_st.ds_row_pass[r]] = pass_inst[render3d_st.ds_row_pass[r]] + render3d_st.ds_row_inst[r]
}
print("")
print(`draw calls per frame ({ds_backend(render3d_st)}, {gl_w}x{gl_h}, mean of {render3d_st.ds_frames} frames from {render3d_st.ds_from}): {ds_per(render3d_st, total)}`)
print(`draw calls per frame ({ds_backend(render3d_st)}, {gl_width()}x{gl_height()}, mean of {render3d_st.ds_frames} frames from {render3d_st.ds_from}): {ds_per(render3d_st, total)}`)
var kinds = ""
for k in 0 .. DS_KINDS { kinds = kinds + ` {ds_kind_name(k)} {ds_per(render3d_st, by_kind[k])}` }
print(` by kind:{kinds}`)
@ -179,7 +179,7 @@ function ds_report(render3d_st: mut Render3dState) -> void {
for i in 0 .. n_rows {
let r = order[i]
let s = render3d_st.ds_row_pass[r]
let line = `{ds_backend(render3d_st)},{gl_w},{gl_h},{render3d_st.ds_frames},"{render3d_st.ds_pass_names[s]}",{ds_kind_name(render3d_st.ds_row_kind[r])},"{gpu_program_key(render3d_st, render3d_st.ds_row_prog[r])}",{ds_per(render3d_st, render3d_st.ds_row_draws[r])},{ds_per(render3d_st, render3d_st.ds_row_inst[r])},{ds_per(render3d_st, render3d_st.ds_row_idx[r])},{ds_per(render3d_st, render3d_st.ds_pass_prog[s])},{ds_per(render3d_st, render3d_st.ds_pass_tex[s])}\n`
let line = `{ds_backend(render3d_st)},{gl_width()},{gl_height()},{render3d_st.ds_frames},"{render3d_st.ds_pass_names[s]}",{ds_kind_name(render3d_st.ds_row_kind[r])},"{gpu_program_key(render3d_st, render3d_st.ds_row_prog[r])}",{ds_per(render3d_st, render3d_st.ds_row_draws[r])},{ds_per(render3d_st, render3d_st.ds_row_inst[r])},{ds_per(render3d_st, render3d_st.ds_row_idx[r])},{ds_per(render3d_st, render3d_st.ds_pass_prog[s])},{ds_per(render3d_st, render3d_st.ds_pass_tex[s])}\n`
file_write(f, line, len(line))
}
file_close(f)

View file

@ -146,9 +146,9 @@ function gpu_depth_bias(render3d_st: mut Render3dState, factor: fixed, units: fi
# A scissor rectangle in top-down pixels (x, y from the top-left of the drawable), or
# off. Every API but OpenGL counts rows from the top; the GL backend flips it.
function gpu_scissor(render3d_st: mut Render3dState, x: int, y_top: int, w: int, h: int) -> void {
if render3d_st.gpu_kind == GPU_VK { render3d_st.gpu_s_scissor = 1; gvk_scissor(render3d_st, x, gl_h - y_top - h, w, h); return }
if render3d_st.gpu_kind == GPU_VK { render3d_st.gpu_s_scissor = 1; gvk_scissor(render3d_st, x, gl_height() - y_top - h, w, h); return }
if render3d_st.gpu_s_scissor != 1 { render3d_st.gpu_s_scissor = 1; gl_enable(GL_SCISSOR_TEST) }
gl_scissor(x, gl_h - y_top - h, w, h)
gl_scissor(x, gl_height() - y_top - h, w, h)
gpu_glcheck_after(render3d_st, "scissor")
}
function gpu_scissor_off(render3d_st: mut Render3dState) -> void {
@ -908,7 +908,7 @@ function gpu_blit(render3d_st: mut Render3dState, w: int, h: int, mask: int) ->
gpu_glcheck_after(render3d_st, "a blit")
}
# the framebuffer the finished frame is presented from (an offscreen one, headless)
function gpu_screen_fb(render3d_st: Render3dState) -> int { if render3d_st.gpu_kind == GPU_VK { return 0 }; return gl_screen }
function gpu_screen_fb(render3d_st: Render3dState) -> int { if render3d_st.gpu_kind == GPU_VK { return 0 }; return gl_screen_fbo() }
function gpu_multisample(render3d_st: mut Render3dState, on: bool) -> void { if render3d_st.gpu_kind == GPU_VK { return }; gpu_gl_cap(render3d_st, GL_MULTISAMPLE, gpu_b(on)); gpu_glcheck_after(render3d_st, "multisample") }
# the most samples the scene may be drawn with: the device's colour-and-depth limit on Vulkan (0 before
# it is open), 4 on OpenGL, which has always asked for up to that
@ -921,7 +921,7 @@ function gpu_wireframe(render3d_st: mut Render3dState, on: bool) -> void {
# the presented frame as RGB8, bottom row first (a photograph)
function gpu_read_screen(render3d_st: mut Render3dState, w: int, h: int, out: pointer) -> void {
if render3d_st.gpu_kind == GPU_VK { gvk_read_screen(render3d_st, w, h, out); return }
gl_bind_framebuffer(GL_READ_FRAMEBUFFER, gl_screen)
gl_bind_framebuffer(GL_READ_FRAMEBUFFER, gl_screen_fbo())
gl_pixel_storei(GL_PACK_ALIGNMENT, 1)
gl_read_pixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, out)
gpu_glcheck_after(render3d_st, `a {w}x{h} read of the screen`)

View file

@ -1328,20 +1328,19 @@ function gvk_manifest(render3d_st: mut Render3dState) -> bool {
# The screen: a colour and a depth image. Headless they are the asked-for size; with a window
# they are its client area in pixels, and the swapchain is made on it.
function gvk_open(render3d_st: mut Render3dState, w: int, h: int, title: string) -> bool {
gl_w = w
gl_h = h
gl_set_drawable(w, h)
if is_windowed() {
win_open(w, h, 1, title) # the window exists before main: this retitles it
win_gl_resize(w, h)
if render3d_st.gvk_size_buf == null { render3d_st.gvk_size_buf = words(4) }
win_gl_drawable(render3d_st.gvk_size_buf)
if render3d_st.gvk_size_buf[0] > 0 and render3d_st.gvk_size_buf[1] > 0 { gl_w = render3d_st.gvk_size_buf[0]; gl_h = render3d_st.gvk_size_buf[1] }
gl_scale = win_gl_scale()
if render3d_st.gvk_size_buf[0] > 0 and render3d_st.gvk_size_buf[1] > 0 { gl_set_drawable(render3d_st.gvk_size_buf[0], render3d_st.gvk_size_buf[1]) }
gl_set_pixel_scale(win_gl_scale())
}
if not gvk_frame_init(render3d_st) { return false }
if not gvk_screen_make(render3d_st, gl_w, gl_h) { return false }
if not gvk_screen_make(render3d_st, gl_width(), gl_height()) { return false }
if r3d_env_has(render3d_st, "R3D_VK_PROBE") { gvk_compute_probe(render3d_st) }
if is_windowed() { return gvk_swap_make(render3d_st, gl_w, gl_h) }
if is_windowed() { return gvk_swap_make(render3d_st, gl_width(), gl_height()) }
return true
}
@ -1695,10 +1694,9 @@ function gvk_resize_check(render3d_st: mut Render3dState) -> bool {
let w = render3d_st.gvk_size_buf[0]
let h = render3d_st.gvk_size_buf[1]
if w <= 0 or h <= 0 { return false }
if w == gl_w and h == gl_h and not render3d_st.gvk_swap_stale { return false }
if w == gl_width() and h == gl_height() and not render3d_st.gvk_swap_stale { return false }
gvk_flush(render3d_st)
gl_w = w
gl_h = h
gl_set_drawable(w, h)
gvk_screen_make(render3d_st, w, h)
gvk_swap_make(render3d_st, w, h)
return true

View file

@ -465,9 +465,9 @@ function gvk_mip_bias(render3d_st: mut Render3dState) -> float {
if r3d_env_has(render3d_st, "R3D_NO_MIPBIAS") { return 0.0 }
if not r3d_dlss_live(render3d_st) { return 0.0 }
let rw = r3d_dlss_render_w(render3d_st)
if rw <= 0 or gl_w <= 0 or rw >= gl_w { return 0.0 }
if rw <= 0 or gl_width() <= 0 or rw >= gl_width() { return 0.0 }
# log2 from the natural log the runtime has: log2(x) = ln(x) * 1/ln(2)
return Math.log(float(rw) / float(gl_w)) * 1.4426950408889634 - 1.0
return Math.log(float(rw) / float(gl_width())) * 1.4426950408889634 - 1.0
}
# the sampler for texture tex's parameters, from the texture's own one-entry cache when they have
# not changed since it last asked - a draw asks for every texture it binds

View file

@ -150,14 +150,14 @@ function ov_glyph(render3d_st: Render3dState, cp: int) -> int {
function ov_begin(render3d_st: mut Render3dState) -> void {
if not render3d_st.ov_ready { return }
gpu_fb_bind(render3d_st, gpu_screen_fb(render3d_st))
gpu_viewport(render3d_st, 0, 0, gl_w, gl_h)
gpu_viewport(render3d_st, 0, 0, gl_width(), gl_height())
gpu_depth_test(render3d_st, false)
gpu_cull(render3d_st, false)
gpu_blend(render3d_st, true)
gpu_blend_func(render3d_st, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
ov_pick_prog(render3d_st)
gpu_use_program(render3d_st, render3d_st.ov_prog)
u_f2(render3d_st, gpu_uniform(render3d_st, render3d_st.ov_prog, "u_screen"), float(gl_w), float(gl_h))
u_f2(render3d_st, gpu_uniform(render3d_st, render3d_st.ov_prog, "u_screen"), float(gl_width()), float(gl_height()))
render3d_st.ov_n = 0; render3d_st.ov_nr = 0; render3d_st.ov_range_start = 0
render3d_st.ov_tex = render3d_st.ov_white
render3d_st.ov_mode = 2; render3d_st.ov_voff = 8.0
@ -191,7 +191,7 @@ function ov_flush(render3d_st: mut Render3dState) -> void {
# (where the screen is an offscreen framebuffer) every overlay draw after it was an invalid
# framebuffer operation. Saying the target at each flush is what a render pass says anyway.
gpu_fb_bind(render3d_st, gpu_screen_fb(render3d_st))
gpu_viewport(render3d_st, 0, 0, gl_w, gl_h)
gpu_viewport(render3d_st, 0, 0, gl_width(), gl_height())
ov_pick_prog(render3d_st)
gpu_use_program(render3d_st, render3d_st.ov_prog)
gpu_mesh_bind(render3d_st, render3d_st.ov_mesh)

View file

@ -382,7 +382,7 @@ function post_tonemap(render3d_st: mut Render3dState, color_tex: int) -> void {
mesh_draw(render3d_st, render3d_st.post_fs)
# sharpen + grain onto the screen
gpu_fb_bind(render3d_st, gpu_screen_fb(render3d_st))
gpu_viewport(render3d_st, 0, 0, gl_w, gl_h)
gpu_viewport(render3d_st, 0, 0, gl_width(), gl_height())
gpu_use_program(render3d_st, render3d_st.post_p_sharp)
r3d_bind_2d(render3d_st, render3d_st.post_p_sharp, "u_src", 0, render3d_st.post_ldr.color)
u_f2(render3d_st, gpu_uniform(render3d_st, render3d_st.post_p_sharp, "u_texel"), 1.0 / float(render3d_st.post_ldr.w), 1.0 / float(render3d_st.post_ldr.h))

View file

@ -97,9 +97,9 @@ function r3d_open(render3d_st: mut Render3dState, w: int, h: int, title: string)
if not gpu_open(render3d_st, w, h, title) { print("r3d: no OpenGL context"); return false }
if r3d_env_has(render3d_st, "R3D_NOVSYNC") { gpu_vsync(render3d_st, 0) }
var renderer: string = gpu_renderer_name(render3d_st)
print(`r3d: {gl_w}x{gl_h} on {renderer}`)
print(`r3d: {gl_width()}x{gl_height()} on {renderer}`)
prof_init(render3d_st)
cam_init(render3d_st, float(gl_w) / float(gl_h))
cam_init(render3d_st, float(gl_width()) / float(gl_height()))
return true
}
@ -124,7 +124,7 @@ function r3d_load_step(render3d_st: mut Render3dState, i: int) -> bool {
terrain_init_step(render3d_st, t)
} else if i == 1 + TERRAIN_INIT_STEPS {
shadow_init(render3d_st)
post_init(render3d_st, gl_w, gl_h)
post_init(render3d_st, gl_width(), gl_height())
} else if i == 2 + TERRAIN_INIT_STEPS {
scatter_init(render3d_st)
actor_init(render3d_st)
@ -169,12 +169,12 @@ function r3d_present(render3d_st: mut Render3dState) -> void { gpu_present(rende
# the drawable changed size: the camera's aspect and every screen-sized target follow
function r3d_resize(render3d_st: mut Render3dState) -> void {
render3d_st.cam_aspect = float(gl_w) / float(gl_h)
render3d_st.cam_aspect = float(gl_width()) / float(gl_height())
cam_update(render3d_st)
post_free(render3d_st)
post_init(render3d_st, gl_w, gl_h)
post_init(render3d_st, gl_width(), gl_height())
if render3d_st.water_refl != null { target_free(render3d_st, render3d_st.water_refl); render3d_st.water_refl = null }
print(`r3d: resized to {gl_w}x{gl_h}`)
print(`r3d: resized to {gl_width()}x{gl_height()}`)
}
function r3d_frame(render3d_st: mut Render3dState, time: float) -> void {
gpu_glcheck_after(render3d_st, "the time between frames")
@ -194,7 +194,7 @@ function r3d_frame(render3d_st: mut Render3dState, time: float) -> void {
if step == 1 { w = 1440; h = 810 }
if step == 2 { w = 2560; h = 1440 }
if step == 3 { w = 1281; h = 721 }
gl_w = w; gl_h = h
gl_set_drawable(w, h)
r3d_resize(render3d_st)
}
render3d_st.r3d_time = time
@ -203,7 +203,7 @@ function r3d_frame(render3d_st: mut Render3dState, time: float) -> void {
# covers is exactly one frame, from this point to the same point next time
prof_gen_frame(render3d_st)
prof_mark_start(render3d_st)
cam_begin_frame(render3d_st, render3d_st.post_frame, gl_w, gl_h)
cam_begin_frame(render3d_st, render3d_st.post_frame, gl_width(), gl_height())
# R3D_CAM_LOG=1: the camera each frame, in millimetres and thousandths of a radian - to tell a
# camera that moves while the hiker stands still from a picture that shakes on its own
if render3d_st.r3d_cam_log < 0 { render3d_st.r3d_cam_log = 0; if r3d_env_has(render3d_st, "R3D_CAM_LOG") { render3d_st.r3d_cam_log = 1 } }

View file

@ -243,12 +243,12 @@ function gsl_fill_options(render3d_st: mut Render3dState, w: int, h: int) -> voi
# the render size for the display's size and the mode, asked once per change
function gsl_optimal(render3d_st: mut Render3dState) -> void {
if render3d_st.gsl_opt_mode == render3d_st.gsl_dlss_mode and render3d_st.gsl_opt_w == gl_w and render3d_st.gsl_opt_h == gl_h { return }
render3d_st.gsl_opt_mode = render3d_st.gsl_dlss_mode; render3d_st.gsl_opt_w = gl_w; render3d_st.gsl_opt_h = gl_h
render3d_st.gsl_rw = gl_w; render3d_st.gsl_rh = gl_h
if render3d_st.gsl_opt_mode == render3d_st.gsl_dlss_mode and render3d_st.gsl_opt_w == gl_width() and render3d_st.gsl_opt_h == gl_height() { return }
render3d_st.gsl_opt_mode = render3d_st.gsl_dlss_mode; render3d_st.gsl_opt_w = gl_width(); render3d_st.gsl_opt_h = gl_height()
render3d_st.gsl_rw = gl_width(); render3d_st.gsl_rh = gl_height()
let f = gsl_fn(GSL_DLSS, "slDLSSGetOptimalSettings")
if f == null { return }
gsl_fill_options(render3d_st, gl_w, gl_h)
gsl_fill_options(render3d_st, gl_width(), gl_height())
let os = gsl_struct(64) # sl::DLSSOptimalSettings
gsl_header(os, 0xef1d, 0x0957, 0xfd58, 0x4df7, 0xb504, 0x8b69, 0xd8aa, 0x6b76, 1)
if Vk.sl_call_pp(f, render3d_st.gsl_opts, os) == 0 {
@ -257,8 +257,8 @@ function gsl_optimal(render3d_st: mut Render3dState) -> void {
if w > 0 and h > 0 { render3d_st.gsl_rw = w; render3d_st.gsl_rh = h }
}
}
function r3d_dlss_render_w(render3d_st: mut Render3dState) -> int { if not r3d_dlss_live(render3d_st) { return gl_w }; gsl_optimal(render3d_st); return render3d_st.gsl_rw }
function r3d_dlss_render_h(render3d_st: mut Render3dState) -> int { if not r3d_dlss_live(render3d_st) { return gl_h }; gsl_optimal(render3d_st); return render3d_st.gsl_rh }
function r3d_dlss_render_w(render3d_st: mut Render3dState) -> int { if not r3d_dlss_live(render3d_st) { return gl_width() }; gsl_optimal(render3d_st); return render3d_st.gsl_rw }
function r3d_dlss_render_h(render3d_st: mut Render3dState) -> int { if not r3d_dlss_live(render3d_st) { return gl_height() }; gsl_optimal(render3d_st); return render3d_st.gsl_rh }
# a radical-inverse sample in [0, 1), float bits
function gsl_halton(i: int, b: int) -> float {
@ -406,15 +406,15 @@ function gsl_targets(render3d_st: mut Render3dState) -> void {
render3d_st.gsl_mv = target_new(render3d_st, render3d_st.post_w, render3d_st.post_h, GL_RG16F, GL_RG, GL_HALF_FLOAT, false, GL_NEAREST)
render3d_st.gsl_reset = true
}
if render3d_st.gsl_out == null or render3d_st.gsl_out.w != gl_w or render3d_st.gsl_out.h != gl_h {
if render3d_st.gsl_out == null or render3d_st.gsl_out.w != gl_width() or render3d_st.gsl_out.h != gl_height() {
if render3d_st.gsl_out != null { target_free(render3d_st, render3d_st.gsl_out) }
render3d_st.gsl_out = target_new(render3d_st, gl_w, gl_h, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, false, GL_LINEAR)
render3d_st.gsl_out = target_new(render3d_st, gl_width(), gl_height(), GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, false, GL_LINEAR)
render3d_st.gsl_reset = true
}
# the LDR image the tonemap writes follows the upscaled size
if render3d_st.post_ldr.w != gl_w or render3d_st.post_ldr.h != gl_h {
if render3d_st.post_ldr.w != gl_width() or render3d_st.post_ldr.h != gl_height() {
target_free(render3d_st, render3d_st.post_ldr)
render3d_st.post_ldr = target_new(render3d_st, gl_w, gl_h, post_ldr_fmt(render3d_st), GL_RGBA, GL_UNSIGNED_BYTE, false, GL_LINEAR)
render3d_st.post_ldr = target_new(render3d_st, gl_width(), gl_height(), post_ldr_fmt(render3d_st), GL_RGBA, GL_UNSIGNED_BYTE, false, GL_LINEAR)
render3d_st.post_ldr_hdr = gpu_hdr_active(render3d_st)
}
if render3d_st.gsl_res == null { render3d_st.gsl_res = gsl_struct(4 * 112); render3d_st.gsl_tags = gsl_struct(4 * 64); render3d_st.gsl_inputs = bytes(8) }
@ -429,17 +429,17 @@ function gsl_dlss_eval(render3d_st: mut Render3dState) -> int {
gpu_clear(render3d_st, GL_COLOR_BUFFER_BIT)
gvk_pass_end(render3d_st)
let cb = gvk_frame_cb(render3d_st)
if render3d_st.gsl_set_mode != render3d_st.gsl_dlss_mode or render3d_st.gsl_set_w != gl_w or render3d_st.gsl_set_h != gl_h {
if render3d_st.gsl_set_mode != render3d_st.gsl_dlss_mode or render3d_st.gsl_set_w != gl_width() or render3d_st.gsl_set_h != gl_height() {
let f = gsl_fn(GSL_DLSS, "slDLSSSetOptions")
gsl_fill_options(render3d_st, gl_w, gl_h)
if f != null and Vk.sl_call_pp(f, render3d_st.gsl_vp, render3d_st.gsl_opts) == 0 { render3d_st.gsl_set_mode = render3d_st.gsl_dlss_mode; render3d_st.gsl_set_w = gl_w; render3d_st.gsl_set_h = gl_h }
gsl_fill_options(render3d_st, gl_width(), gl_height())
if f != null and Vk.sl_call_pp(f, render3d_st.gsl_vp, render3d_st.gsl_opts) == 0 { render3d_st.gsl_set_mode = render3d_st.gsl_dlss_mode; render3d_st.gsl_set_w = gl_width(); render3d_st.gsl_set_h = gl_height() }
}
gsl_constants(render3d_st)
Vk.sl_set_constants(render3d_st.gsl_consts, render3d_st.gsl_token, render3d_st.gsl_vp)
gsl_resource(render3d_st, 0, render3d_st.post_hdr.depth); gsl_tag(render3d_st, 0, 0, render3d_st.post_w, render3d_st.post_h) # kBufferTypeDepth
gsl_resource(render3d_st, 112, render3d_st.gsl_mv.color); gsl_tag(render3d_st, 1, 1, render3d_st.post_w, render3d_st.post_h) # kBufferTypeMotionVectors
gsl_resource(render3d_st, 224, render3d_st.post_hdr.color); gsl_tag(render3d_st, 2, 3, render3d_st.post_w, render3d_st.post_h) # kBufferTypeScalingInputColor
gsl_resource(render3d_st, 336, render3d_st.gsl_out.color); gsl_tag(render3d_st, 3, 4, gl_w, gl_h) # kBufferTypeScalingOutputColor
gsl_resource(render3d_st, 336, render3d_st.gsl_out.color); gsl_tag(render3d_st, 3, 4, gl_width(), gl_height()) # kBufferTypeScalingOutputColor
Vk.sl_set_tag_for_frame(render3d_st.gsl_token, render3d_st.gsl_vp, render3d_st.gsl_tags, 4, cb)
Vk.put_ptr(render3d_st.gsl_inputs, 0, render3d_st.gsl_vp)
let r = Vk.sl_evaluate_feature(GSL_DLSS, render3d_st.gsl_token, render3d_st.gsl_inputs, 1, cb)
@ -453,6 +453,6 @@ function gsl_dlss_eval(render3d_st: mut Render3dState) -> int {
render3d_st.post_color_w = render3d_st.post_w; render3d_st.post_color_h = render3d_st.post_h
return render3d_st.post_hdr.color
}
render3d_st.post_color_w = gl_w; render3d_st.post_color_h = gl_h
render3d_st.post_color_w = gl_width(); render3d_st.post_color_h = gl_height()
return render3d_st.gsl_out.color
}

View file

@ -39,7 +39,7 @@ export function ui_atlas(ui_st: mut UiState, prefix: string, tex: int, cols: int
push(ui_st.r3u_atlas_names, names)
}
function r3u_now() -> float { return float(Time.now_us() / 1000) / 1000.0 }
function r3u_scale(ui_st: UiState) -> float { return float(gl_h) / 1080.0 * ui_st.r3u_user }
function r3u_scale(ui_st: UiState) -> float { return float(gl_height()) / 1080.0 * ui_st.r3u_user }
function r3u_r(c: int) -> float { return float((c / 65536) % 256) / 255.0 }
function r3u_g(c: int) -> float { return float((c / 256) % 256) / 255.0 }
function r3u_b(c: int) -> float { return float(c % 256) / 255.0 }

View file

@ -625,6 +625,7 @@ function rt_map_random_cell_far(glyph: int, from: IVec2, min_tiles: int) -> IVec
var rt_map_solid1: int = 0
var rt_map_solid2: int = 0
var rt_map_tile_px: int = 16
function rt_map_tile_size() -> int { return rt_map_tile_px }
function rt_map_is_solid(x: int, y: int) -> bool {
if rt_map_solid1 == 0 { return false } # no Solids config: nothing is solid
let g = rt_tile(x, y)

View file

@ -161,6 +161,12 @@ function gl_width() -> int { return gl_w }
function gl_height() -> int { return gl_h }
function gl_screen_fbo() -> int { return gl_screen }
function gl_pixel_scale() -> int { return gl_scale }
# a renderer that owns its swapchain (render3d's Vulkan path) says what the drawable is
function gl_set_drawable(w: int, h: int) -> void {
gl_w = w
gl_h = h
}
function gl_set_pixel_scale(s: int) -> void { gl_scale = s }
# Present the frame (vsync'd flushBuffer); headless, just finish the GPU work.
function gl_swap() -> void {

View file

@ -191,8 +191,10 @@ function mg_is_target(v: Node) -> bool {
}
# which vars move, and the state each moves into
function mg_collect() -> void {
var end = g_prog_user_end
if g_mg_runtime { end = len(prog) } # the runtime's declarations come after the program's
var i = 0
while i < g_prog_user_end and i < len(prog) {
while i < end and i < len(prog) {
let d = prog[i]
if d.kind == N_VAR and mg_is_target(d) {
let k = mg_state_of_file(d.file)
@ -269,6 +271,10 @@ function mg_ref(e: Node, g: Node) -> void {
function mg_write(t: Node, g: Node) -> void {
if not g_migrate or g == null or g.kind != N_VAR or g.mg < 0 { return }
g_mg_written[g.mg] = 1
if is_runtime_file(g.file) and t != null and not is_runtime_file(t.file) {
mg_say(t, `{mg_src_name(g.s)} is the runtime's; change it through the runtime's function for it`)
return
}
if g_mg_cur >= 0 { mg_need(g_mg_cur, g_mg_vstate[g.mg], true) }
}
# a var nothing writes, holding a value (not a reference something could change through), and
@ -299,7 +305,11 @@ function mg_read_needs() -> void {
let e = g_mr_node[r]
let u = g_mr_unit[r]
let g = g_mg_vars[v]
if g_mg_let[v] == 0 and u != -3 {
if is_runtime_file(g.file) and not is_runtime_file(e.file) {
# the runtime's state is the runtime's: from outside it is read through its functions
mg_say(e, `{mg_src_name(g.s)} is the runtime's; read it through the runtime's function for it`)
g_mr_var[r] = -1 - v
} else if g_mg_let[v] == 0 and u != -3 {
if u >= 0 { mg_need(u, g_mg_vstate[v], false) }
else { mg_say(e, `{g.s} is read where no function is (a global's initializer); move it by hand`) }
if e.pos < 0 and not mg_bound_var(g.s) { mg_say(e, `a reference to {g.s} in generated code (a component, a view, a registry's lookup)`) }
@ -696,6 +706,10 @@ function mg_refs() -> void {
var r = 0
while r < len(g_mr_node) {
let e = g_mr_node[r]
if g_mr_var[r] < 0 { # the runtime's, read from outside it: by hand
r += 1
continue
}
let v = g_mg_vars[g_mr_var[r]]
if e.pos >= 0 and e.file != null and g_mg_let[g_mr_var[r]] == 0 {
let s = g_mg_vstate[g_mr_var[r]]

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff