Skip to content

Commit 6da7d8e

Browse files
committed
sync on 2026/05/30, rev 6069dec2fc94ad2fe48465cbe051c3c8b95fdffc
1 parent 0223d11 commit 6da7d8e

759 files changed

Lines changed: 17530 additions & 8270 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

DagorEngine.rev.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6552bf3b2222466802e0ac7b4a550752cfbac036
1+
6069dec2fc94ad2fe48465cbe051c3c8b95fdffc

outerSpace/prog/gameBase/gamedata/scenes/_common_render_scene.blk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@ entity{
1313
entity{
1414
_template:t="ui_nodes"
1515
}
16+
17+
entity{
18+
_template:t="film_grain_lut"
19+
}

outerSpace/prog/gameBase/gamedata/templates/outer_space.entities.blk

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,3 +813,18 @@ capsules_ao{
813813
_tags:t="render"
814814
}
815815
}
816+
817+
film_grain_lut{
818+
_singleton:b=yes
819+
film_grain_lut__wh:i=256
820+
film_grain_lut__d:i=64
821+
film_grain_lut__gen_params:p4=2.5,0.5,1.0,64
822+
823+
_tracked:t="film_grain_lut__wh"
824+
_tracked:t="film_grain_lut__d"
825+
_tracked:t="film_grain_lut__gen_params"
826+
827+
film_grain_lut{
828+
_tags:t="render"
829+
}
830+
}

prog/1stPartyLibs/daScript/daslib/rst.das

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,25 @@ def document_class_method(doc_file : file; mod : Module?; value; var fld) {
11551155
document_function_topic(doc_file, func.result, topic("function", mod, "{value.name}-{function_label_file(fld.name, fld.init._type, 1)}"), "def {fld.name} : {describe(fld._type)}", args)
11561156
}
11571157

1158+
def document_deprecated_unsafe(doc_file : file; func) {
1159+
if (func.flags.unsafeOperation) {
1160+
document_warning(doc_file, "This is unsafe operation.")
1161+
}
1162+
if (func.moreFlags.deprecated) {
1163+
for (ann in func.annotations) {
1164+
if (ann.annotation.name == "deprecated") {
1165+
for (arg in ann.arguments) {
1166+
if (arg.name == "message") {
1167+
document_warning(doc_file, "{arg.sValue}")
1168+
return
1169+
}
1170+
}
1171+
}
1172+
}
1173+
document_warning(doc_file, "This function is deprecated.")
1174+
}
1175+
}
1176+
11581177
def document_struct_method(doc_file : file; mod : Module?; value; var func) {
11591178
// For structs (not classes), methods become module-level functions with isClassMethod flag.
11601179
// Static methods get names like "BoolArray`clear"; non-static keep names like "[]", "finalize".
@@ -1173,12 +1192,7 @@ def document_struct_method(doc_file : file; mod : Module?; value; var func) {
11731192
(document_function_declaration(doc_file, "das:function", "{value.name}.{fname}",
11741193
argNames, argTypes, argInits, func.result, /*drop args*/1))
11751194

1176-
if (func.flags.unsafeOperation) {
1177-
document_warning(doc_file, "This is unsafe operation.")
1178-
}
1179-
if (func.moreFlags.deprecated) {
1180-
document_warning(doc_file, "This function is deprecated.")
1181-
}
1195+
document_deprecated_unsafe(doc_file, func)
11821196

11831197
var args <- document_function_arguments(doc_file, argNames, argTypes, /*skip args*/1)
11841198

@@ -1795,7 +1809,10 @@ def function_needs_documenting(func : FunctionPtr) {
17951809

17961810
def document_warning(doc_file : file; issue : string) {
17971811
fwrite(doc_file, ".. warning::")
1798-
fwrite(doc_file, "\n {issue}\n\n")
1812+
for (str in issue |> split("\n")) {
1813+
fwrite(doc_file, "\n {str}\n")
1814+
}
1815+
fwrite(doc_file, "\n")
17991816
}
18001817

18011818
def function_name(func : FunctionPtr) {
@@ -1854,12 +1871,7 @@ def document_function(doc_file : file; mod : Module?; var func : FunctionPtr; dr
18541871
if (skip_body) return
18551872
// if func.result != null && !func.result.isVoid
18561873
// fwrite(doc_file,"``{funcSafeName}`` returns {describe_type(func.result)}\n\n")
1857-
if (func.flags.unsafeOperation) {
1858-
document_warning(doc_file, "This is unsafe operation.")
1859-
}
1860-
if (func.moreFlags.deprecated) {
1861-
document_warning(doc_file, "This function is deprecated.")
1862-
}
1874+
document_deprecated_unsafe(doc_file, func)
18631875

18641876
var args <- document_function_arguments(doc_file, argNames, argTypes, drop_args)
18651877
document_function_topic(doc_file, func.result, topic("function", mod, "{prefix}{function_label_file(func,drop_args)}"), "def {rst_describe_function_short(func)}", args)
@@ -1879,7 +1891,7 @@ def document_functions(doc_file : file; mods : array<Module?>; var groups : arra
18791891
if (grp.hidden) {
18801892
document_warning(doc_file, "This group of functions is hidden. It will not be in the final documentation.")
18811893
}
1882-
grp.func |> sort($(a, b) => function_name(a.fn) < function_name(b.fn))
1894+
grp.func |> sort($(a, b) => rst_describe_function_short(a.fn) < rst_describe_function_short(b.fn))
18831895
for (func in grp.func) {
18841896
if (!key_exists(tab, func.fn)) {
18851897
let descr = rst_describe_function_short(func.fn)

prog/1stPartyLibs/daScript/include/daScript/simulate/aot.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,10 +769,19 @@ namespace das {
769769
static __forceinline VecT & at ( MatT & value, int32_t index, Context * __context__ ) {
770770
uint32_t idx = uint32_t(index);
771771
if ( idx>=uint32_t(size) ) __context__->throw_error_ex("matrix index out of range, %u of %u", idx, size);
772+
#if defined(__clang__) && defined(DAS_STRICT_ALIASING)
773+
// Compiler barrier: prevents ThinLTO SROA from substituting a stale virtual-register
774+
// value for value.m[idx] after a write through an aliased pointer of a different type
775+
// (e.g. TMatrix & aliasing float3x4). No machine instruction is emitted.
776+
std::atomic_signal_fence(std::memory_order_seq_cst);
777+
#endif
772778
return value.m[idx];
773779
}
774780
static __forceinline VecT & at ( MatT & value, uint32_t idx, Context * __context__ ) {
775781
if ( idx>=uint32_t(size) ) __context__->throw_error_ex("matrix index out of range, %u of %u", idx, size);
782+
#if defined(__clang__) && defined(DAS_STRICT_ALIASING)
783+
std::atomic_signal_fence(std::memory_order_seq_cst);
784+
#endif
776785
return value.m[idx];
777786
}
778787
};

prog/1stPartyLibs/daScript/src/builtin/module_builtin_ast_serialize.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2491,7 +2491,7 @@ namespace das {
24912491
}
24922492

24932493
uint32_t AstSerializer::getVersion () {
2494-
static constexpr uint32_t currentVersion = 188;
2494+
static constexpr uint32_t currentVersion = 189;
24952495
return currentVersion;
24962496
}
24972497

prog/1stPartyLibs/quirrel/quirrel/doc/source/reference/embedding/async_runtime.rst

Lines changed: 85 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ cooperative scheduler with C-level entry points declared in
1515

1616
1. Calling :cpp:func:`sqasync::bind` once per shared state, before any
1717
``async`` function in script can run.
18-
2. Publishing the ``Promise`` class to script (typically through
18+
2. Publishing the ``Future`` class to script (typically through
1919
``SqModules::registerAsyncLib`` or by calling
2020
:cpp:func:`sqasync::sqasync_register` directly).
2121
3. Calling :cpp:func:`sqasync::pump` periodically - once per host frame,
@@ -50,7 +50,7 @@ Lifecycle API
5050
.. cpp:function:: SQRESULT sqasync::bind(HSQUIRRELVM v)
5151

5252
Install the async runtime into ``v``'s shared state and build the
53-
``Promise`` class. Cache the class internally so further publishing
53+
``Future`` class. Cache the class internally so further publishing
5454
paths see the same object.
5555

5656
Call it once per shared state, before any ``async`` function runs.
@@ -71,16 +71,16 @@ Lifecycle API
7171
.. cpp:function:: SQBool sqasync::has_pending(HSQUIRRELVM v)
7272

7373
``SQTrue`` iff the runtime has work it can drive forward on its own
74-
(step queue or inbox non-empty). Returns ``SQFalse`` when the
75-
runtime is not bound.
74+
(step queue or inbox non-empty, or a deferred unhandled-fault sweep
75+
pending). Returns ``SQFalse`` when the runtime is not bound.
7676

77-
A task parked on an unsettled Promise does not count here: the
77+
A task parked on an unsettled Future does not count here: the
7878
runtime cannot wake it on its own, only the producer that started
7979
the work (timer, in-flight HTTP, eventbus, ...) can, by calling
80-
``resolve_promise`` / ``reject_promise``. A drain loop that only
81-
checks ``has_pending`` will therefore exit too soon while such
82-
producers still have work to deliver - OR the check with whatever
83-
in-flight signals you already track for them::
80+
``future_resolve`` (or ``future_throw`` for a worker-thread bug).
81+
A drain loop that only checks ``has_pending`` will therefore exit
82+
too soon while such producers still have work to deliver - OR the
83+
check with whatever in-flight signals you already track for them::
8484

8585
while (sqasync::has_pending(v) || timers.has_due() || http_in_flight)
8686
sqasync::pump(v);
@@ -123,65 +123,73 @@ callback's responsibility to free or reinterpret ``user`` as
123123
appropriate.
124124

125125
---------------------
126-
Promise class & C API
126+
Future class & C API
127127
---------------------
128128

129-
.. cpp:function:: SQRESULT sqasync::push_promise_class(HSQUIRRELVM v)
129+
.. cpp:function:: SQRESULT sqasync::future_push_class(HSQUIRRELVM v)
130130

131-
Push the cached ``Promise`` class onto the stack. Useful for
132-
embedders that want to instantiate a Promise from C (for example,
131+
Push the cached ``Future`` class onto the stack. Useful for
132+
embedders that want to instantiate a Future from C (for example,
133133
an ``async.delay`` native that returns one). Returns ``SQ_ERROR``
134134
(and raises an error) if :cpp:func:`sqasync::bind` has not been
135135
called.
136136

137-
.. cpp:function:: SQRESULT sqasync::create_promise(HSQUIRRELVM v, HSQOBJECT *out)
137+
.. cpp:function:: SQRESULT sqasync::future_create(HSQUIRRELVM v, HSQOBJECT *out)
138138

139-
Create a fresh ``Promise`` instance and write an addref'd handle
139+
Create a fresh ``Future`` instance and write an addref'd handle
140140
into ``*out``. Nothing is left on the stack. Caller owns one
141141
strong ref and must either:
142142

143-
* settle the promise via ``resolve_promise`` / ``reject_promise``
144-
and then ``sq_release(v, out)``, or
145-
* ``sq_release(v, out)`` directly to discard the promise.
143+
* settle the future via ``future_resolve`` (or ``future_throw``
144+
for a worker-thread bug) and then ``sq_release(v, out)``, or
145+
* ``sq_release(v, out)`` directly to discard the future.
146146

147147
Returns ``SQ_ERROR`` (raised) if the runtime is not bound or
148148
instance creation fails; ``*out`` is reset to null on error.
149149

150-
.. cpp:function:: SQRESULT sqasync::resolve_promise(HSQUIRRELVM v, HSQOBJECT promise, HSQOBJECT value)
151-
.. cpp:function:: SQRESULT sqasync::reject_promise(HSQUIRRELVM v, HSQOBJECT promise, HSQOBJECT reason)
150+
.. cpp:function:: SQRESULT sqasync::future_resolve(HSQUIRRELVM v, HSQOBJECT future, HSQOBJECT value)
151+
.. cpp:function:: SQRESULT sqasync::future_throw(HSQUIRRELVM v, HSQOBJECT future, HSQOBJECT value)
152152

153-
Settle a manually-created Promise from C. The payload is kept
153+
Settle a manually-created Future from C. The payload is kept
154154
alive by an internal ``sq_addref``. Settling an already-settled
155-
or already-adopted promise is a silent no-op.
156-
157-
``resolve_promise`` applies the JS Promise Resolution Procedure:
158-
a Promise ``value`` is adopted (``promise`` mirrors its eventual
159-
settlement); a non-Promise ``value`` fulfills immediately.
160-
``reject_promise`` stores ``reason`` verbatim regardless of type.
161-
162-
Both return ``SQ_ERROR`` and throw if ``promise`` is not a
163-
Promise instance, is a task-promise (returned by an ``async``
164-
function), or the payload is ``promise`` itself.
165-
``resolve_promise`` additionally throws on a cycle that lies
155+
or already-adopted future is a silent no-op.
156+
157+
``future_resolve`` applies the JS Promise Resolution Procedure:
158+
a Future ``value`` is adopted (``future`` mirrors its eventual
159+
settlement); a non-Future ``value`` fulfills immediately.
160+
161+
``future_throw`` is reserved for surfacing bugs from native code
162+
when a Quirrel call stack is not available - typically a
163+
worker-thread I/O completion that discovers an internal invariant
164+
violation. Documented failures should travel as values through
165+
``future_resolve``. A native binding that detects a bug and is
166+
itself running inside a Quirrel call should use
167+
``sq_throwerror``, which the runtime routes into the surrounding
168+
async body's task-Future via the throw-escape path. ``value`` is
169+
stored verbatim regardless of type.
170+
171+
Both return ``SQ_ERROR`` and throw if ``future`` is not a
172+
Future instance, is a task-future (returned by an ``async``
173+
function), or the payload is ``future`` itself.
174+
``future_resolve`` additionally throws on a cycle that lies
166175
entirely within the adoption chain
167176
(``a.resolve(b); b.resolve(a)``). Cycles that pass through a
168-
rejection (``a.resolve(b); b.reject(a)`` or
169-
``b.reject(a); a.resolve(b)``) are detected during settlement
170-
and produce a diagnostic reason rather than throwing.
177+
fault are detected during settlement and produce a diagnostic
178+
value rather than throwing.
171179

172180
Typical worker -> VM result delivery looks like::
173181

174182
struct OpCtx {
175-
HSQOBJECT promise; // addref'd via create_promise
183+
HSQOBJECT future; // addref'd via future_create
176184
HSQOBJECT result; // built on the VM thread
177185
};
178186

179-
// VM thread: kick off the op and hand the promise to script
180-
HSQOBJECT prom;
181-
sqasync::create_promise(v, &prom);
182-
OpCtx *ctx = new OpCtx { prom, /*result=*/{} };
187+
// VM thread: kick off the op and hand the future to script
188+
HSQOBJECT fut;
189+
sqasync::future_create(v, &fut);
190+
OpCtx *ctx = new OpCtx { fut, /*result=*/{} };
183191
start_worker(ctx);
184-
// push the promise back to script as the call result, etc.
192+
// push the future back to script as the call result, etc.
185193

186194
// Worker thread: do the work, then post the completion
187195
sqasync::post_from_any_thread(v, &on_complete, ctx);
@@ -190,8 +198,8 @@ Typical worker -> VM result delivery looks like::
190198
static void on_complete(void *user) {
191199
OpCtx *ctx = static_cast<OpCtx *>(user);
192200
// build ctx->result here (we are on the VM thread)
193-
sqasync::resolve_promise(v, ctx->promise, ctx->result);
194-
sq_release(v, &ctx->promise);
201+
sqasync::future_resolve(v, ctx->future, ctx->result);
202+
sq_release(v, &ctx->future);
195203
delete ctx;
196204
}
197205

@@ -203,21 +211,21 @@ Publishing the ``async`` module
203211

204212
SqModules-shaped registration entry point. On entry the new module
205213
table is expected on top of the stack; the function adds
206-
``"Promise"`` -> class into it and leaves the table on top.
214+
``"Future"`` -> class into it and leaves the table on top.
207215

208216
Suitable for ``SqModules::registerStdLibNativeModule`` and
209217
``SqModules::registerAsyncLib``.
210218

211219
The simplest wiring for an embedder using ``SqModules`` is::
212220

213221
sqasync::bind(v);
214-
module_mgr->registerAsyncLib(); // adds "async" -> { Promise }
222+
module_mgr->registerAsyncLib(); // adds "async" -> { Future }
215223

216-
After that, script code can write ``from "async" import Promise``.
224+
After that, script code can write ``from "async" import Future``.
217225

218226
Embedders that do not use ``SqModules`` can publish the class manually
219-
by pushing it via :cpp:func:`sqasync::push_promise_class` and storing it
220-
wherever they want script to see it.
227+
by pushing it via :cpp:func:`sqasync::future_push_class` and storing
228+
it wherever they want script to see it.
221229

222230
--------------------------------
223231
Async function call integration
@@ -227,14 +235,40 @@ When the engine encounters a call to a script-side ``async`` function
227235
in ``SQVM::StartCall``, it does not run the body. Instead it builds a
228236
generator from the function's bytecode and hands it to the runtime
229237
through a hidden entry point (``sqasync::wrap_generator``). The
230-
runtime builds a task-promise around the generator, schedules the
231-
first step, and returns the task-promise as the call result. Subsequent
238+
runtime builds a task-future around the generator, schedules the
239+
first step, and returns the task-future as the call result. Subsequent
232240
``pump()`` calls drive the generator one ``await`` at a time.
233241

234242
This means an embedder does not need a per-async-function binding:
235243
any Quirrel function declared ``async`` is wired automatically once
236244
:cpp:func:`sqasync::bind` has installed the runtime.
237245

246+
-------------------------
247+
Unhandled fault reporting
248+
-------------------------
249+
250+
When a task-future faults and no awaiter is there to receive the thrown
251+
value, the pump-tick sweep routes the fault to the VM's installed error
252+
handler (``sq_seterrorhandler``), passing the thrown value. If no handler
253+
is installed, the runtime emits a one-line console diagnostic instead.
254+
255+
By the time an async fault surfaces, the throwing generator's call stack
256+
has already unwound, so the handler's live call stack
257+
(:cpp:func:`sqstd_printcallstack`) is empty. The origin is recovered from
258+
the thrown value instead: when an :ref:`Error <builtin_error_class>`
259+
instance is thrown, the runtime captures its throw-site stack into
260+
``e.trace`` at the throw point, and as the fault propagates the settle-time
261+
ancestry walk appends one ``awaited at`` frame per uncaught async ancestor
262+
that was parked awaiting the faulting step, so ``e.trace`` carries the path
263+
from throw site out through those ``await`` hops.
264+
An embedder error handler can read ``e.trace`` directly; the standard
265+
handler installed by ``sqstd_seterrorhandlers`` prints it under an
266+
``ERROR TRACE`` heading.
267+
268+
Non-``Error`` thrown values (strings, tables) carry no trace - the
269+
single-channel convention is to throw ``Error`` (or a subclass) across
270+
async boundaries precisely so the fault carries this context.
271+
238272
--------
239273
Shutdown
240274
--------
@@ -243,7 +277,7 @@ The runtime is owned by the shared state and freed automatically
243277
during ``sq_close``. Once shutdown begins, ``post_from_any_thread``
244278
returns ``SQ_ERROR`` and the caller retains ownership of ``user``;
245279
any queued callbacks are still dispatched so they can release their
246-
refs, and tasks still parked on unsettled promises are reclaimed
280+
refs, and tasks still parked on unsettled futures are reclaimed
247281
without completing their bodies.
248282

249283
To drain pending work cleanly before ``sq_close``, loop on

0 commit comments

Comments
 (0)