@lritter@mastodon.gamedev.place avatar lritter , to random

Slang 🤝 C++
..........cpp

lritter OP ,
@lritter@mastodon.gamedev.place avatar

today i'll start in earnest to prepare GPU compute support for LRDL:

  • the C++ generating backend will be generalized to use macro indirections for C++ idoms slang doesn't support

  • each case tagged for gpu is translated to a slang file, the slang file then translated to SPIR-V binary, the binary code embedded in the generated host code.

  • host code uses SDL_gpu (through macros as well) to load GPU kernels and execute them.

(cont)

lritter OP ,
@lritter@mastodon.gamedev.place avatar
  • host table impls need to implement SDL_gpu upload/download locally; no global system.

  • tables accessed from gpu cases need a parallel implementation in slang; slang has limited support for generics - what i can't get to work there, i'll do with macros.

i hope that's all.

lritter OP ,
@lritter@mastodon.gamedev.place avatar

set up a test case. parses, but we're not generating slang code yet.

ALT
  • Reply
  • Loading...
  • @lritter@mastodon.gamedev.place avatar lritter , to random

    fixed a bunch of compiler bugs today, and developed some flow to modularize e.g. mouse click handling.

    the abstraction below makes it possible to "listen" to mouse click events. it's just a test, i'm still figuring out how to treat system events in data flow; not happy yet.

    ALT
    @lritter@mastodon.gamedev.place avatar lritter , to random

    struct got a small upgrade this morning to support two kinds of extensions to field declarators

    ALT
    @periaptgames@dice.camp avatar periaptgames , to random

    Dropping a little about the actual gameplay of , my new solo of cartoonish cult devilry. This is a tactical game that revolves around five ever-changing stats.

    As an outer god, you'll need enough CULTISTS and IMMINENCE to become manifest.

    Your cultists generate imminence with their worship, but also

    • spread heretical ideas (adding DIVERGENCE)
    • get overexcited about bloodshed (increasing FERVOUR)
    • draw ancient horrors to the well of power (adding MONSTROSITY)

    1/3

    ALT
    @bluattire@mastodon.gamedev.place avatar bluattire , to random

    In ByteBlaster there are all sorts of strange and unexplained sights and locales to explore. It’s not just random stuff around though. We believe in the power of environmental storytelling.

    Follow for more on ByteBlaster!

    ALT
    @lritter@mastodon.gamedev.place avatar lritter , to random

    doing a thing for

    @dunkingdoggames@mastodon.gamedev.place avatar dunkingdoggames , to random

    Big thanks to everybody who encouraged me on this whacky gamedev journey! Today I replaced the complex cloud system with a simple shader and tuned some of the sound effects

    video/mp4

    @lisyarus@mastodon.gamedev.place avatar lisyarus , to random

    A new devlog about my village building game! 📺

    Learn about how and why I transformed my game's world from a tiny 200m patch to a mighty 100km island! 🔥

    https://youtu.be/00f5GLnVtok

    @stegodon@stegodon.social avatar stegodon , to random

    🔧 Devlog: FediBuzz relay returned 400 errors. Root cause: nginx 1.18 + HTTP/2 + hyper/reqwest sent duplicate Host/:authority headers. Fixed by upgrading to nginx 1.29.4 which handles HTTP/2 headers correctly (fix from Aug 2025).

    @lritter@mastodon.gamedev.place avatar lritter , to random

    (continued from https://mastodon.gamedev.place/@lritter/115927292419525735)

    i'm now making some changes to the code generator to conform to NOIR semantics. rules targeting a relator will only be run when any of the inputs have been updated.

    this way we can put the entire program in a single top level loop, and leave it to the low-level compiler to optimize branches.

    lritter OP ,
    @lritter@mastodon.gamedev.place avatar

    another terminology change. renamed "relators" to "tables". has precedent, sounds familiar, describes the shape precisely - they're in fact more table-y than lua's tables.

    also, if you like, you can pronounce LRDL as "lurdle".

    lritter OP ,
    @lritter@mastodon.gamedev.place avatar

    slowly getting back into it.

    codegen now generates code that for each case ensures that it only runs when any of its source tables bool ::changed() method returns true.

    next step is to de-complexify the scheduling algo and enforce DAGness (complain about hard cycles in the hypergraph). that means i can remove SCC analysis.

    lritter OP ,
    @lritter@mastodon.gamedev.place avatar

    i'm rewriting the execution planner, and that requires topologically sorting the program's hypergraph - so, a bipartite graph.

    the problem is we have two types of vertices. how i solved it is that i number both tables and cases in the same vertex array; the reverse map (object -> vertex index) works with std::variant to resolve.

    and so, for topological analysis, the graph appears no longer bipartite, and many headaches are avoided.

    lritter OP ,
    @lritter@mastodon.gamedev.place avatar

    yesterday i only managed to do translation to a sortable graph, today i'm going to add kahn's toposort. part of it is reporting errors on hard cycles. i could auto-convert hard to soft edges, but this can still be added later.

    ironically i procrastinate here not because it is hard but because it is easy and i've done this part already three times. will have to put on some music and grind through it.

    lritter OP , (edited )
    @lritter@mastodon.gamedev.place avatar

    fixed all tests.

    continuing on the SDL3 framework.

    tracking mouse state is presently done with a table abstraction; first pic is how it's set up; the case is triggered every time there were state changes.

    unfortunately this means clicks received in the same frame get lost. so instead i'll expose mouse state updates directly as a delta table.

    update: and it's done. on the user side, i only needed to swap two fields to respect field order convention.

    @lritter@mastodon.gamedev.place avatar lritter , (edited ) to random

    got an idea for how to control loops better that might finally break this stalemate between me and the language.

    in a nutshell: user being able to mark cases as backedges allows to organize the entire thing as nested DAGs. i really hope this is the only thing i need.

    [update: no it isn't.]

    lritter OP ,
    @lritter@mastodon.gamedev.place avatar

    made my test case worse to break Natural Loop finding. i added edges A->C with which B no longer is a suitable loop header, and D->F so flipping all edges does not make the problem any simpler.

    note that this is a dependency graph not a CFG. each edge is a task, each vertex is (accumulating) data.

    lritter OP ,
    @lritter@mastodon.gamedev.place avatar

    i can easily build an optimal schedule for this graph, but i can not turn it into an algorithm yet.

    if i use kahn's DFS with cycle-breaking, then D->F will be executed piece-by-piece in the loop, rather than once after.

    with flipped edges, A->C will land in the loop, performing redundant work.

    lritter OP ,
    @lritter@mastodon.gamedev.place avatar

    but i think there's still semantic clarity
    missing.

    even in datalog, stratification is completely implicit. it's also very limiting - there is no support for nested strat, where a result can be considered "temporarily stratified", and then we make a change afterwards that invalidates this result so its inputs have to be recomputed again.

    so for this we'd need ways to define

    1. when the container should be reset.

    2. when the container is considered "sufficiently complete".

    lritter OP ,
    @lritter@mastodon.gamedev.place avatar

    these two points do look suspiciously like header and break condition for loops.

    in NOIR (https://git.sr.ht/~duangle/texts/tree/master/item/NOIR.md), which has similar, more minimal semantics, (1) is decided by whether we're updating from a back- (update) or from a front-edge (init), where the front-edge has precedence, and both edges are explicitly defined as such.

    (2) would apply when no back-edge sourcing our container has made updates. this means active back-edges always preempt further processing.

    lritter OP ,
    @lritter@mastodon.gamedev.place avatar

    but handling (2) like this is not enough; say you do a 2d loop. the outer variable Y will not receive updates for a while while the inner variable X updates - but Y is not complete yet.

    in NOIR, (2) is implemented through definedness; a "breaking flow" was caused when an output was defined, by making the breaking flow depend on it being defined.

    here the user would need to define a "gate" that indicates whether the container is considered complete. a bit cumbersome but precise.

    lritter OP ,
    @lritter@mastodon.gamedev.place avatar

    the gate would be an option that we need to be able to set or unset, and "unsetting things" is also not in the repertoire of datalog.

    so for this, we finally need deletion support for rules. i have already thought of this, and it will be analog to insertion:

    insert single-item row {x} into A

    then A x

    remove x from A, if any

    then not A x

    declare that A doesn't contain anything, thus emptying/undefining it

    then not A _

    lritter OP , (edited )
    @lritter@mastodon.gamedev.place avatar

    for (1) i would need to add the restriction that back-rules (that is, rules that modify a container after it has been sourced) need to mark their insertion as an update:

    cue A x

    this is also beneficial for the reason that front-rules can now safely mutate a container directly since it has not been sourced yet; while only back-rules need to mutate a temporary delta state that gets applied on the next iteration so we do not change the present container state.