[HN Gopher] Low-latency scripting for game engines
___________________________________________________________________
Low-latency scripting for game engines
Author : fwsgonzo
Score : 93 points
Date : 2024-05-26 05:42 UTC (1 days ago)
(HTM) web link (fwsgonzo.medium.com)
(TXT) w3m dump (fwsgonzo.medium.com)
| shmerl wrote:
| I must be missing some idea used there. Why does scripting need
| emulation of hardware?
| fp64 wrote:
| I don't have an answer either, but I've seen people who want to
| use bytecode/a VM using RISC-V just because it's well defined
| and tooling is already there. This has less to do with RISC-V
| hardware, or even really the fact that it's RISC-V, and more
| with using a simple bytecode and VM - e.g. JVM could also work
| there, but the Java ecosystem comes with what some people
| consider considerable pain.
| neonsunset wrote:
| Many game developers have been successfully using XNA/FNA
| with C# on all kinds of platforms (and, of course, Unity
| existed for a long time, and now we have Godot and Stride
| too). You get to access all the low-level bits when you need
| to, and you don't have to sacrifice productivity or
| performance for scripting otherwise.
| boffinAudio wrote:
| It doesn't need emulation of _hardware_ per se, but most
| scripting environments are already _virtual machines_ of some
| variety or another - and RISC-V just happens to be the latest
| in a long line of virtual machine architectures available for
| the purpose.
|
| The author is cleverly using libriscv for this purpose - and it
| is indeed a neat use of the library - but I fail to see the
| 'scripting' part, personally - isn't it scripting when you can
| just load a text file off the disk, containing program
| instructions, have it interpreted into some (hopefully
| optimized) interim representation, and then pushed through a
| virtual machine? I don't see the "text files" part here - but
| perhaps it gets more relevant in parts 2/3/4, which I haven't
| read yet, either...
|
| EDIT: I heard you like ABI, so I put a foreign ABI within your
| ABI so you can ABI with your ABI .. actually, this started off
| as a joke but its kind of painful to think about. This isn't
| really "scripting" .. its more "embed a foreign ABI into your
| application so you can throw a foreign binary at it, any time,
| and modify program behaviour extensively "without needing to
| recompile" .. maybe the author should rename the article "how
| to embed a virtual machine into your app so you never have to
| write (your app code) again .."
|
| I can see why they call it "scripting" since, this is what you
| usually do when embedding the Lua VM into an app - but the fact
| that I have to use a compiler disqualifies the term 'scripting'
| from being applicable here, imho ..
| exDM69 wrote:
| > but the fact that I have to use a compiler disqualifies the
| term 'scripting' from being applicable here, imho ..
|
| I'm not sure if this is a useful distinction to make.
|
| Lua, perhaps the most used scripting language out there, runs
| through a compiler too and then runs a bytecode interpreter
| on the resulting code. Most scripting languages work this
| way. The compiler is still there even if it gets invoked at
| runtime. Most games ship the compiled bytecode files, not the
| script source.
|
| The key part here is loading the "script" bytecode at runtime
| and then executing it in the host, allowing reloading and
| restarting the script without restarting the "host" process
| (often a game engine with long load times and lots of
| resident assets like textures, shaders, models etc that don't
| need reloading).
|
| The host process _could_ also include a mechanism to invoke
| the compiler at runtime, pass in the script as text, grab the
| output and then run it as it does currently. This would be
| identical to how Lua et al work, but quite a bit of work to
| set up for limited benefit.
| boffinAudio wrote:
| Hey - the distinction _is important_ but I don 't think
| you've got it right.
|
| Out-of-the-box, Lua runs through an _interpreter_ - not a
| _compiler_.
|
| A compiler produces native machine code from a human-
| readable programming language for the target platform -
| whereas an interpreter (in some cases) produces an interim
| representation (bytecode) for a virtual machine, not
| necessarily native - and in other cases, simply executes
| script code line-by-line, without the interim step.
|
| In the case of Lua, this interim representation is in the
| form of bytecode which is then further interpreted by a
| virtual machine, pretending that it is a register-based
| machine vastly different to the actual hardware it is
| running on. This particular aspect is the _only_ feature
| that the authors ' libriscv usage and the Lua VM have in
| common - but that doesn't make it _scripting_.
|
| And scripting means (to my jaded 40-years of development
| brain) to load text files from a resource (disk or
| otherwise), interpret it in some interim form, and then
| push through a secondary mechanism for final execution in
| the native environment.
|
| >The key part here is loading the "script" bytecode at
| runtime and then executing it in the host, allowing
| reloading and restarting the script without restarting the
| "host" process (often a game engine with long load times
| and lots of resident assets like textures, shaders, models
| etc that don't need reloading).
|
| So this is where our definitions conflict and go awry,
| because to me all you've described is runtime loading of a
| binary resource. Is loading and parsing a .PNG resource
| that appears in your executive bundle somewhere, also
| considered "Scripting" in your opinion? Because I don't
| think that is an accurate use of the term, personally. It
| would be scripting if the file (or memory blob) was somehow
| modifiable by the user, and then interpreted without
| further interaction required on the part of the developer -
| but in this case (the article) the developer (not the end
| user) still has to compile a binary blob, integrate it into
| their application, and then 'run it'.
|
| This is more appropriately referred to as runtime resource
| modification and execution - for which the action of
| "scripting" is a superset - but the fact that there are
| _two compilers_ involved in this project (native to build
| the .exe, and risc-v cross-compiling to build the binary
| blob resource for integration) means that we are far, far
| away from the typical scripting mechanic.
|
| Its important to make this distinction. This isn't about
| scripting. It is about runtime resource modification and
| processing - but the different paths taken to the same fork
| in the road between scripting and compiling are vastly
| different and should not be conflated.
|
| This isn't to say that integrating libriscv as a virtual
| machine in ones application execution environment is not a
| brilliant idea with a great deal of merit - just that the
| author is incorrectly using terms, and this must simply not
| be allowed. There is no interpreting happening here until
| runtime - when the binary risc-v blob is loaded and parsed
| by a virtual machine. If there were some mechanism to load
| code intended for the risc-v component _at runtime_ ,
| compile it, and load it for execution/report errors in the
| script/etc. - then I would say that the scripting workflow
| has been completed for this project - and it would be
| appropriate to use the term - but that has not happened
| here. It still requires a separate compilation (risc-v
| machine code) step, and there are still many, many aspects
| of the scripting workflow that are not implemented in this
| project ..
| fwsgonzo wrote:
| You're right! I actually did try to integrate a compiler,
| but I quickly realized that it wasn't worth it for me,
| personally. Iterating on the script is very quick right
| now. It's mostly a matter of compiler flags and ccache,
| believe it or not. And I can use mold for linking RISC-V!
| boffinAudio wrote:
| Its great work, and you've inspired me to put libriscv in
| places where I usually put the LuaVM, but I wish you'd
| update your article to s/Scripting/Dynamic modification
| of resources at runtime/ .. or something.
|
| We can see, already here in this thread, the dangers of
| people mis-interpreting your technology.
|
| Now, if you get the riscv compiler integrated into your
| projects such that we can indeed just load a text file
| containing C code, dynamically at runtime, (a la
| shaders), I'll revisit all of this and go along with your
| program. ;)
|
| Anyway, thanks for the great series of articles - really
| gave me an interesting read on the way to work this
| morning, and I've put libriscv (as well as your sample
| projects) in my stack of Lab Todo's for the week .. now
| if someone produces LuaRISCV that targets the riscv VM
| instead of Lua Bytecode, that's gonna break a few molds,
| in and of itself .. ;) (In the context of your work so
| far, this seems like a low-hanging fruit, actually..)
| exDM69 wrote:
| > Out-of-the-box, Lua runs through an interpreter - not a
| compiler.
|
| The first thing the "interpreter" does is run the Lua
| code through `luac`, the Lua _compiler_ and then feed the
| bytecode to the Lua VM. This may be transparent to the
| user, but it 's still there.
|
| Almost all interpreted languages have a compiler and a
| bytecode interpreter as distinct steps.
|
| > Is loading and parsing a .PNG resource that appears in
| your executive bundle somewhere, also considered
| "Scripting" in your opinion?
|
| Of course it's not, an image file does not contain any
| code that could be interpreted or executed in a host
| environment.
|
| There is a distinction here on how code is executed,
| whether by compiling, interpreting, JITting or a
| combination of the above. But if you draw the line for
| "scripting" at consuming textual source code, that would
| exclude most use of Lua in gaming engines, as it is
| typically distributed as bytecode and may not even link
| luac compiler to the host executable. Yet it's commonly
| called "scripting" in the industry.
|
| And conversely, if the code in this article included a
| mechanism to compile the source to risc-v would it meet
| your definition of "scripting"?
|
| There isn't a clear definition of what's scripting and
| what's not, but drawing the line at consuming textual
| source code is not, in my opinion, a _useful_ distinction
| (it 's certainly a distinction) because it hardly matches
| what's the state of the art out there.
| boffinAudio wrote:
| For _decades_ , compiling has referred to the process of
| turning human-readable language into native machine code.
| _That is what is happening here._
|
| Interpreting has, also for decades, referred to the run-
| time interpretation of human-readable language into some
| mechanism which either a) immediately results in native
| execution at runtime, or b) produces errors reported to
| the developer for fixing, _precluding_ the generation of
| immutable machine code being executed natively by the CPU
| (except of course with JIT, which _is a form of
| compilation at runtime_ , since the interim bytecode is
| translated into real machine code instructions...)
|
| Scripting has, for decades - not just in the gaming
| industry, which is a subset of computing enterprises -
| meant "loading a human readable text file containing a
| programming language and directly executing it if it
| passes validation - reporting errors, otherwise,
| preventing further execution. This is why we have BASH
| scripts and Python scripts and Lua scripts - they are not
| machine code, they are interpreted and either eventually
| produce machine code, or run through a state device
| pretending to be a non-native machine.
|
| _fwsgonzo is literally compiling C code into machine
| code to be executed on a pretend CPU (in the form of an
| embedded libriscv)._
|
| The code is not interpreted (from one language to
| another) - it is executed in a virtual machine
| environment. Bytecode _is_ , on the other hand, always
| interpreted from one form to another prior to execution
| (except JIT, it is only interpreted once, compiled, and
| then exists as machine code always)
|
| fwsgonzo's binary blob is executed by a 'fake' CPU, it is
| not interpreted.
|
| If he had the execution environment set up, he could
| literally run that very same machine code on real RISCV
| hardware, unchanged, without translation or
| interpretation.
|
| It is not, therefore, interpreted in any sense other than
| by his embedded RISCV emulator - and thus it is not
| scripting!
|
| This is the point where the distinction is important.
|
| >The first thing the "interpreter" does is run the Lua
| code through `luac`,
|
| The first thing the Lua interpreter does is validate the
| inbound, human-readable script to make sure the program
| is correct, syntactically and otherwise - giving errors
| to the developer if errors are encountered. Meaning, at
| runtime, errors can be caught and fixed by the human
| developer.
|
| Only then, once it has been validated, is it processed
| into an interim representation as bytecode. Sure, Lua can
| be told to produce bytecode in order to speed up runtime
| loading and execution, but its still an _interpreted
| bytecode_. It hasn 't been compiled into a native form
| for direct execution - it still requires a secondary
| _native program_ (a VM host) in order to provide any
| functionality.
|
| From the Lua 5.1 manual, Section 2.4.1:
| ... Chunks can also be pre-compiled into binary
| form; see program luac for details. Programs in source
| and compiled forms are interchangeable; Lua automatically
| detects the file type and acts accordingly.
|
| Lua _does have a compiler_ for the case where you want to
| create Lua bytecode (.luac), as a loadable-at-runtime
| resource to be further interpreted and also, the
| _bytecode is subsequently interpreted according to the
| needs of the target (native) environment on which it is
| being executed, whether through a JIT or otherwise_. That
| same bytecode can be executed on vastly different native
| CPU architectures - _through interpretation_.
|
| The difference is, prior to Lua's internal compilation of
| the script into bytecode, _validation of the programs
| correctness is performed, preventing the developer from
| producing incorrect bytecode if there are errors_ , and
| this is the process of scripting - distinct from
| compilation - because it is a more direct human/computer
| interaction regarding the correctness of the script
| language as it is being used by the developer.
|
| >There isn't a clear definition of what's scripting and
| what's not, but drawing the line at consuming textual
| source code is not, in my opinion, a useful distinction
| (it's certainly a distinction) because it hardly matches
| what's the state of the art out there.
|
| I disagree with you, there very definitely _IS_ a clear
| definition of what is scripting and what is not - one
| must not call it 'scripting' unless runtime loading,
| validation (or not), interpreting, and subsequent
| execution (whether on an interim bytecode or otherwise)
| is happening - and that is not what is happening here in
| fwsgonzo's project. He is compiling binary blobs, and his
| eventual execution environment has _nothing to do with
| the validation of the scripted code_. The C compiler he
| uses in a prior step does, however.
|
| Scripting is a development workflow where
| compilation/linking/building is not required - results
| are immediate, the program reports validity of the loaded
| script, or otherwise, and executes directly upon command
| by the developer.
|
| Additionally, fwsgonzo has also, already confirmed that
| this distinction is correct (see elsewhere in the thread)
| - that in fact interpreting of a script is _NOT_
| happening in any sense other than the RISCV VM is
| interpreting pre-validated machine code (not bytecode!)
| in the form of RISCV instructions.
|
| _That machine code is not a human-readable script, and
| it is not bytecode! It is machine code, produced by a
| compiler._
|
| This distinction is important because that same machine
| code could, theoretically, be executed directly,
| unmodified, on a RISCV machine - _that is not the case
| with Lua bytecode, ever, which always requires
| interpretation by a VM._
|
| fwsgonzo's project is _entirely based around pre-
| compilation of native binary resources_ , not
| interpretation. A human-readable language is not being
| interpreted by his runtime.
|
| There is no opportunity (at runtime) with his project to
| have the runtime report on errors in the human-readable
| script - this has all been done with a prior
| _compilation_ step.
|
| >but drawing the line at consuming textual source code is
| not, in my opinion, a useful distinction (it's certainly
| a distinction) because it hardly matches what's the state
| of the art out there.
|
| I disagree with you. I think you are taking an aberration
| of the gaming industry, which is rife with such things,
| and applying it to computing as a whole - and this is
| where the protest over your position lays.
|
| It is absolutely important to make this useful
| distinction, because in case a) INTERPRETATION: an
| interim representation is being generated after
| validating program correctness/conformity to a language
| spec, and in case b) COMPILATION: no such validation is
| occurring once the compiler produces runnable machine
| code.
|
| > Yet it's commonly called "scripting" in the industry.
|
| I have 40 years of experience with this subject,
| including working on game engines and realtime
| (scientific) use of Lua in high-performance environments,
| and the phrase "scripting" has _always_ referred to the
| process of writing code that is immediately interpreted
| by some program before resulting in actual runtime
| execution if it is found to be valid code.
|
| The interpretation may not even work as desired, but the
| host environment/program will still continue to be
| executed in a runtime context.
|
| The fact that compilers "interpret" code before producing
| an interim representation that is then used to produce
| static machine code, is entirely why the distinction must
| be made: _because there is a point where code can be
| incorrect and thus not runnable!_
|
| In the game world, "scripting" means 'writing some human-
| readable script and having it interpreted at runtime,
| without involving a native
| compilation/linking/building/packaging step" - and as
| this is not what is happening (key word: without) in
| fwsgonzos' project, it is incorrect use of the phrase.
|
| He is compiling resources which can be loaded at runtime,
| bypassing the native loading/linking phase, and it is
| therefore more appropriate to refer to what he is doing
| as "runtime resource management" which, incidentally,
| feeds into a VM. This is not scripting, although
| scripting often necessitates the same activity - errors
| in the code are not reported at runtime, by the process
| doing something with the resource.
|
| Please just use the right term and stop trying to justify
| an incorrect usage - don't re-define these terms based on
| a misunderstanding of the mechanics involved. There are
| literally _decades_ of examples which are entirely
| counter to your misunderstanding out there, in the state
| of the art.
|
| (tl;dr - Is /bin/bash a compiler? Is /bin/python a
| compiler? Why isn't gcc exclusively referred to as an
| interpreter? Is clang an interpreter? Is ld a scripting
| environment?)
| indigoabstract wrote:
| > This particular aspect is the only feature that the
| authors' libriscv usage and the Lua VM have in common -
| but that doesn't make it scripting.
|
| Maybe I'm nitpicking, but to me scripting is just
| programming/extending a certain fixed piece of software
| to execute instructions not already programmed into it
| without having to modify that software itself. Usually
| using an API. Not unlike computer programming, which aims
| to make a piece of hardware execute some instructions
| without needing to alter the said hardware. The main
| difference is conceptual (the platform targeted: hardware
| or software). If the script happens to be run by a VM
| emulating a real processor because your software includes
| such a thing, I think the distinction becomes purely
| conceptual.
|
| Now, the technology is obviously super cool, but what I
| don't quite understand yet is what is the best use case
| for this? Is it really game scripting? Or compiling C++
| on the fly?
|
| It's not exactly a simple drop in replacement for a Lua
| interpreter.
| mistercow wrote:
| I would argue that "scripting" has to do with what you, as
| the programmer, do to deploy your code, and not what
| happens under the hood. If you can deploy by shipping a
| single source code file, that's a script. If there's a
| build step, that's not a script. Whether the underlying
| system compiles it, interprets it, sends it to MTurk for a
| human to evaluate by hand, or whatever doesn't matter.
| fsniper wrote:
| Isn't it mentioned as "sandboxing"? If the script runs in a
| controlled vm, it can not reach the game's internal state
| unless it is exposed to the vm.
| bawolff wrote:
| I was kind of wondering that too. Perhaps for sandboxing, but
| then i wonder why not something like webassembly or even eBPF.
| I kind of wish the author went more into the why of it.
| fwsgonzo wrote:
| Nothing wrong with using WebAssembly, if you wish to. eBPF
| I'm not so sure is a good fit. Most people are just fine with
| Lua, LuaJIT or Luau though. This is really just for
| especially interested, or if you really need low latency.
| gudzpoz wrote:
| > ... but Lua still creates issues now and then. Like if you
| forget return, the return value is that of the last expression.
|
| Is this true? Or was it true for some Lua 2.X versions? Because
| it does not seem to be the case for Lua 3.0 and on: [1]
|
| > If control reaches the end of a function without a return
| instruction, then the function returns with no results.
|
| As to the idea of using an emulator for scripting, it seems a bit
| similar to approaches using WebAssembly. But looking into the
| benchmarks [2] provided by libriscv, it is quite interesting to
| see it outperforms luajit and wasm3 (in its "hand-picked" tests,
| at the very least).
|
| [1] https://www.lua.org/manual/3.0/manual.html [2]
| https://github.com/fwsGonzo/libriscv?tab=readme-ov-file#benc...
| sebstefan wrote:
| I've forgotten `return` plenty of times and to the best of my
| recollection it's always returned `nil` to the caller.
|
| Maybe he's talking about something else than pure lua?
| Something with the game's bindings?
| fwsgonzo wrote:
| Maybe I'm old now. I'll remove it from the article! Reading
| back on it, it seems like I'm writing negatively about Lua,
| despite using it for many years. I think highly of Lua, and
| especially think it has made so many things easier for people
| over the years. I actually chose Nelua as one of the examples
| (Part 3) because of it!
| fwsgonzo wrote:
| I spent a lot of time on those benchmarks. I think my
| conclusion is just that because WASM isn't a register-machine
| architecture, you basically have to implement a register
| allocator to be really fast. wasmtime uses a complex allocator
| to great success. wasm3 has done it too, but it's just a basic
| one and it won't be able to compete with GCC or Clang. I could
| be wrong here, but what else is there? During my testing, it
| was never in question if libriscv was faster.
|
| I used my usual benchmarks: STREAM (memory) and CoreMark (CPU).
| dazzawazza wrote:
| This is seriously cool but I really think we are losing our way
| in game development.
|
| We used to create DSLs to make scripting of games simpler and
| less error prone... so that coders/designers could write
| Scripts/AI in a language better suited to the problems they face.
| It was sort of a side issue that is was a sandbox although that
| was really useful for lots of reasons.
|
| Now we seem to be creating more and more complex toolchains while
| complaining that game development is getting more and more
| expensive. We're not solving the correct problems at all.
|
| Oh well.
| johnnyanmac wrote:
| Even if it's c++ to c++, the goal of scripting at the end of
| the day is quick iteration. What is "quick iteration" for
| scripting will depend on the scriptor.
|
| This article is clearly targeted at engineers rolling their own
| engine, so that audience may find it beneficial keep everything
| in one language if they are already comfortable with it. As
| long as the core engine doesn't need to re-compile every little
| change, it's a win.
| fwsgonzo wrote:
| Yeah, I can confirm that the iteration speed is fast. I
| consider the scripting portion a solved problem right now,
| having used it so long. Gamedev is so many other things
| though, and practically every corner of the engine has to
| have convenience functionality in order to reduce the overall
| workload. It's rough for gamedevs right now, I feel like.
| johnnyanmac wrote:
| IMO the big tools are convinent enough to use. But the
| rampup time to really understand how the engine ticks is
| dreadful, because documentation drops off a cliff once you
| want to do more than animate a few dozen actors in a level
| (and tbf, sometimes that is indeed enough to ship).
|
| The other half of the problem is asset production time. But
| no game engine is really solving that problem. As you'll
| discover in that domain, the art community is a lot more
| protective of their techniques and pipelines than
| programming. Even more so if looking for game ready asset
| production. Same issue, different cause.
| nxobject wrote:
| There is one benefit to jumping through these hoops to use C++
| as a scripting language (how much of a benefit it is, well,
| that's your judgment): you get to reuse libraries, as the
| author notes.
| pjc50 wrote:
| Modern AAA game development is suffering a chronic
| mismanagement problem. Like fimmaking. Poor creative vision,
| not communicated clearly to those executing it; endless
| rewrites and rework; lack of originality; poor treatment of
| staff leading to poor morale; and churning away in the
| background, the culture war.
|
| Technically the only interesting challenge is "how do we get
| off Unity?"
| chii wrote:
| > a chronic mismanagement problem. Like fimmaking.
|
| the mismanagement stems from the fact that it is costing too
| much from the onset, and "management" wants to ensure that
| the investment makes a good enough return to justify the high
| cost.
|
| Therefore, they dictate all of the risks have to be removed -
| such as not going for a risky new brand, but make a sequel.
| They want realistic graphics because it's more commercially
| viable - going for a different or uncommon aesthetic means
| taking risks.
|
| I would argue all of the problems in AAA development stems
| from this fact.
|
| it is also why indie games can be so cheap yet so successful.
| Not because indies are better (tho they are- at least more
| passionate if nothing else), but because indies are capable
| of taking risks to push the edge and make something new and
| untested.
|
| It's the same as films - creative endeavours cannot have
| their risks managed away. It is inherent, and there's a large
| chance of failure even if the team has done their best.
| kevindamm wrote:
| The risk aversion in product is not a new phenomenon,
| though. Bigger producers have been following that track
| since at least the 90s. Adherence to brand, and even more
| so to basic game genres and mechanics, has been an issue
| complained about by devs at any big enough studio for
| decades.
|
| What changed, I think, is all of the development studios
| being bought up by large producers. But, then again, I see
| steam as being a great counterforce on this, and the ease
| of releasing on web or mobile has been a boon for indie
| devs too. So maybe that hasn't changed that much.
|
| The technology has advanced to where you can spend
| blockbuster budgets and get nearly film-quality results
| (not nearly possible in the cartridge and CD days).
| Meanwhile the price per AAA title has stayed relatively
| fixed at 50-60 USD for that same range of time, so
| production houses have had to try being appealing to ever-
| larger audiences. Fortunately, many people continue playing
| these games into their 30s and 40s so the market grows on
| its own too.
|
| I'm trying to say you're right about the risk aversion
| being a big part of the industry's problems but that's been
| an issue for a while, it has gotten terribly enhanced with
| the growth of the industry.
|
| Now I wonder which is worse.. extracting money one quarter
| a time with punishingly difficult timing tests, or
| extracting money via cosmetics that have no actual game
| impact but are marketed very compellingly.
| the_snooze wrote:
| >it is also why indie games can be so cheap yet so
| successful. Not because indies are better (tho they are- at
| least more passionate if nothing else), but because indies
| are capable of taking risks to push the edge and make
| something new and untested.
|
| The cheapness also means indies simply get more "shots on
| goal." The barrier to entry is relatively low, so failing
| is lower-stakes. You have way more indies trying (and
| mostly failing), which means you have a greater raw number
| of hits. That's compared to a big company only having a
| handful of big-budget games in development.
| 587846 wrote:
| This certainly seems to be true, at least for one modern
| example, according to a recent post that linked to a YouTube
| video whose creator evidently has insider information about
| the 'failure' of Kerbal Space Program 2
| (https://news.ycombinator.com/item?id=40485788).
| chris37879 wrote:
| As someone in an otherwise healthy position at my job, fuck
| yes, I want to get away from Unity, but there's just no
| better option for the platforms we're targeting and how
| quickly we want to ship things. Something about the devil you
| know, ya know?
| kgabis wrote:
| Shameless plug, but some time ago I've created a language where
| the main design goal was for it to be easy to use and embed:
| https://github.com/kgabis/ape.
| nox101 wrote:
| Something I want is a sandboxed place to run USER scripts in
| game. I trust the game's creators to not hack my machine with
| their DSL (else I wouldn't be running their game). I don't
| trust random drive by game mod to the same level. I'd love not
| to have to trust user additions, but currently I do have to
| trust them or go without.
|
| I run a few games that takes C# plugins. The games have a big
| warning that they aren't doing anything to prevent my machine
| getting hacked, personal files uploaded to random servers,
| etc....
| maccard wrote:
| You want luau - https://luau-lang.org/
|
| It's what Roblox uses
| JonChesterfield wrote:
| Or lua itself
| sebstefan wrote:
| > 2. Install a RISC-V compiler
|
| > On Linux this is fairly straight-forward.
|
| Well... Of course on Linux it would be straight forward
|
| I'd love for games to start having any/all system languages as
| the embedded scripting language.
|
| But with Linux being around ~2% of the market share (with "~" in
| a hand-wavey way), I was kinda looking for the Windows steps to
| see if how much of a pain this would actually be if somebody
| wanted to set it up.
| fwsgonzo wrote:
| Ah yeah, I have installed RISC-V with a oneliner in WSL. So
| it's not too far off on Windows, but I mostly program on Linux
| these days. You can also build on a Linux VM and share it to
| Windows, but what kind of iteration loop is that?
|
| I don't know. Perhaps clang-cl could be used on Windows? It
| depends on how much of a run-time environment one wants.
| nxobject wrote:
| I just think it's neat that the canonical script package is an
| Linux ELF binary.
| pdpi wrote:
| Is there anything Linux-specific about ELF? I was under the
| impression it's a pretty common format for executables, used by
| a whole bunch of systems. It certainly predates Linux, as it
| was (according to Wikipedia) introduced in 1988 with SVR4.
| gmueckl wrote:
| The ELF format is shared between different platforms. There
| are identifiers for the target OS and CPU in the ELF header.
| lenkite wrote:
| This is wonderful! No need for a second language for
| plugins/extensions if your software is written in C++. Hell, it
| is mind-blowing - using a RISC-V emulator to run _C++_ scripts.
| Lol - this is not something that immediately strikes one 's
| brain. Looking forward to fully digging into this next weekend.
| highsea wrote:
| Reminds me how Quake3 shipped with a VM to compile/run the C game
| code.
| ceronman wrote:
| If I understand correctly, the idea here is to provide safe
| scripting by running a RISC V emulator. The "scripts" would be
| written in C/C++ compiled to RISC V. And then these compiled
| scripts would be run inside the game engine's emulator. The
| emulator's library then will allow to share some memory between
| the emulated program and the host game engine by sharing some
| memory.
|
| All this sounds like a poor re-invention of Web Assembly 1.0.
|
| I think Wasm is a better option for most cases because:
|
| - There are more advanced Wasm runtimes that can do JIT
| compilation and be very fast.
|
| - There are probably more languages compiled to Wasm than to RISC
| V. Especially for higher level languages, which is attractive for
| scripting.
|
| - There is better tooling for debugging Wasm.
|
| - Interoperability is better specified in Wasm, it was designed
| from the ground up for that. And with Wasm components it's even
| better. This is specially important for different host
| architectures.
| fwsgonzo wrote:
| This whole comment sounds dismissive towards both me and RISC-V
| as an architecture people actually run their computers on.
|
| I have a lot of blog posts that you can read to get up to
| speed. Or maybe you already made up your mind.
| JonChesterfield wrote:
| Risc-v is a hardware ISA optimised for education. Wasm is a
| sandboxed IR optimised for compilers. It would be
| phenomenally unlikely for risc-v to be better than wasm in
| the exact domain wasm was built to excel at.
| thefaux wrote:
| Both are targets for a general purpose programming
| language. As OP commented below, wasm is a stack machine
| while riscv is a register machine. It would surprise me if
| there is any wasm program for which there is not a
| semantically equivalent and faster riscv implementation.
| JonChesterfield wrote:
| Wasm has locals and block arguments, it's no more a stack
| machine than risc-v is a stack machine.
| ceronman wrote:
| In no way I intended to be dismissive of you work or the
| RISC-V architecture. I apologize if my words could be
| interpreted in that way. I actually think that RISCV is a
| really cool architecture, mostly because it is open. I would
| love to see it getting more traction in the hardware world. I
| also think that your work on libriscv is impressive!
|
| My criticism was at the idea of using a RISC-V emulator as a
| scripting platform. And I'm not saying that it doesn't work,
| only that I personally think that Web assembly seems a better
| option for that particular use case.
| fwsgonzo wrote:
| I've been at it for a few years now and my experience with
| game engine scripting is that the functions are small, and
| that it's helpful or pleasant to have the ability to make
| many calls back into the game engine to ask for things,
| even simple things. My measurements have shown time and
| again that libriscv spends 3ns entering and leaving the
| emulator dispatch, and 2ns to execute a system call or even
| a more complex host function scheme (using custom
| instructions).
|
| So now it's a race. For example, wasmtime needs 48ns just
| to enter and leave, and 24ns to make a call into the host.
| That's around 100-150 instructions libriscv can execute
| before wasmtime has even overcome the fixed call latencies.
| And then add 50 each time we make a call back into the
| engine.
|
| Now combine this with my ~200 host functions in my game,
| and I don't know how many in-game events. Which function
| would wasmtime be faster at? I don't know, probably not a
| single one. And that's really it. There's no fibonacci
| computations in game engine scripting. It's just logic.
|
| As far as using complex run-times for scripting: I've
| already been doing this dance for years now. For example,
| TinyKVM is a native performance KVM userspace emulator that
| I among other things ran v8 inside. You can find my
| research paper about it. So it's not like I couldn't throw
| v8 in there and slideware some JS solution. But, I really
| do prefer writing C++.
|
| Also related is attack surface. libriscv is 10k LOC.
| wasmtime is what, 350k LOC?
|
| Here is a random function I benchmarked:
| https://fwsgonzo.medium.com/a-sandboxed-rainbow-
| function-b42...
|
| wasmtime spent 107ns and libriscv 57ns. Those kinds of
| functions is your average script function. And, even if we
| were exactly matching in latency, I would still call that a
| win!
|
| EDIT: To add, you did make a good point about tooling,
| components etc.
| neonsunset wrote:
| It's a classic fallacy of thinking "interpreter would be fast
| enough". Except here it's worse by not even getting the
| productivity advantage of automatic memory management!
|
| No, use something actually good for gamescript, like C#, which
| is industry proven and has no issues interpreted languages
| suffer from.
|
| I'm always baffled this even has to be said, yet enthusiast
| circles keep sabotaging themselves in assuming they can do
| better with techniques known to do worse.
| bitwize wrote:
| Or QuakeC. That's pretty much what QuakeC was like.
| Narishma wrote:
| I don't think so. QuakeC was its own language.
|
| This is more like Quake 3 which used a general purpose VM
| that you could compile regular C to.
| senkora wrote:
| > There are probably more languages compiled to Wasm than to
| RISC V. Especially for higher level languages, which is
| attractive for scripting.
|
| To expand on this, this is especially useful for modding. The
| original developers should probably standardize on a single
| scripting language for practical reasons, but individual
| modders or groups or modders may benefit from being able to
| choose their scripting language independent of the original
| developers'.
___________________________________________________________________
(page generated 2024-05-27 23:01 UTC)