Boring Friday night in? Looking for some hot, esoteric programming challenges? Give my "Low-Rez Shadertoy: The Game" a go!

Write shaders in some made up assembly language, match your target, win prizes*

This is an alpha version and I'm looking for feedback. Please boost/share, thanks!

http://lrst-alpha.s3-website.eu-north-1.amazonaws.com/

LRST

@evilpaul_atebit It'd be cool if it showed you which level you're on while you're in the level? Unless that is somewhere and I'm missing it.

I only did the first 8 levels but doing World 2 level 4 in three instructions was very satisfying.

@evilpaul_atebit This gives me 100% but is still showing a handful of red pixels...?

sub #31,r0,r0
sub.mi #-1,r0,r0
mulu r0,r0,r0
sub #31,r1,r1
sub.mi #-1,r1,r1
mulu r1,r1,r1
add r0,r1,r0
sub r0,#981,r0
mov.lt #6,r0
mov.ge #3,r0

@evilpaul_atebit Oh wait, I guess to get 100% you just have to get it to the point where the error rounds down to zero? 64 squared is 4096, half a percent is 20.48 pixels. And I got it down to 16. Ha, nice.
@evilpaul_atebit I have no idea how you're supposed to get the circles pixel-correct, but otherwise... fun.
@JoshGrams @evilpaul_atebit aha, pixel-perfect!
@jcreed @JoshGrams Interesting. Someone else had solved it also in 10 instructions, but differently. Oh.. and SIMD would shave more instructions here so I'm getting more and more keen to add that ;)

@evilpaul_atebit @JoshGrams haha me too...

it suddenly occurred to me that mixing "SIMD register specs" and ordinary registers could be confusing or erroneous.
mov rH, r0
add rH, #1, r0
seem of dubious meaning (unless the last is interpreted as r0 := r4+r5+r6+r7+#1?? 😨 )

not sure what to do about it. maybe just require that all registers have to be of the same type for an instruction? does that mean the concrete syntax for them should be different?? guess it's up to you to make these calls :)

@jcreed @JoshGrams I was thinking of just saying that all regs have to be of the same type. Feels a little awkward and unsatisfying..
@evilpaul_atebit @JoshGrams yeah, dunno. brainstorming some alternatives (for something that's meant to be equivalent to
mov r0, r4
mov r1, r5
mov r2, r6
mov r3, r7)
I can think of
mov.4 R0, R1 ; R0 = r0,r1,r2,r3, and R1 = r4,r5,r6,r7
mov.4 R0, R4 ; but maybe you'd have to forbid overlapping register groups?
mov r0:4 r1:4
mov r0-3, r4-7
mov r0123, r4567
@evilpaul_atebit @JoshGrams (& I want to triple down on the sentiment that --- it's your game, and please feel very free to ignore any of my suggestions, they're offered in the spirit of hoping they help but no big deal if not :)

@evilpaul_atebit I've been mostly ignoring this part of the conversation, but... idk. Multi-register operations feel like something that is moving away from the spirit of assembly language.

Deciding how to handle "I need to do the same thing multiple times" is very much a part of all the asm writing that I've done: do you cut-and-paste? Just re-type it? Write a preprocessor macro? Make it a subroutine? Are you optimizing for overall code size, or for execution speed? etc.

So I think if it were me I'd be leaning toward adding a macro facility or a call stack. But I've always felt that code re-use and editing/re-factoring/tinkering with existing code is a major part of my coding time but is unfortunately left out of coding games, so I'm biased.

And as @jcreed says, I don't want to tell you what's best for your game.

@JoshGrams @evilpaul_atebit huh! tbh I'm stoked that you have different aesthetic feelings on this issue..., it means we're in an interesting space. for me, having played a bunch of "assembly programming games", SIMD is something I haven't seen explored, and it seems like a sweet spot of "kind of awkward but potentially powerful" to me that might lead to fun surprises while optimizing.

@JoshGrams @evilpaul_atebit but if these kinds of instructions are "not in the spirit of [the kind of asm you want to program in]", that's totally legit!

dunno, I think macros could be an interesting feature in general, but my gut sense is they would be Very Big Change relative to this particular game

@jcreed @JoshGrams Well.. yes.. this is a super interesting discussion and it's great to see different views!

The "hardware model" that I have for this thing is super limited "no branches" and "no local memory", so that rules out functions and loops. I did this partly to make it close to modern shader arch (where branches and loops hurt performance so you try to avoid them), partly to make the compile/execution code faster/easier and partly because it feels closer to the hardware that was available in the 70s/80s timeline that it I'm targeting.

@jcreed @JoshGrams I'm leaning heavily towards the SIMD thing because it's something I've not really played with, and it seems like an interesting area to get really clever with size optimizations and that's what some of the games goals are geared towards. I do worry that it might be too complex/scary though.. so I might introduce it later in the game.

I also have to admit that macros are interesting too..

@jcreed @JoshGrams I took a quick hack at implementing SIMD last night. It sort of worked.. but I went for rH/rL type pairings and didn't like it.

I think I'll go for something like:

mov r01,r10 ; swap r0 and r1

add r01,#1,r01; add 1 to r0 and r1

mov r000,r123 ; copy r0 to r1,r2 and r3

etc...

@jcreed @JoshGrams Overlapping ranges are fine here. Flags.. hmm.. I guess I'll use a combination of all operations: zero flag is set if any of the values are zero.
@jcreed @JoshGrams But anyway... after my quick hack I realised that I need to go back and refactor some compiler stuff to make it more robust to the types of modifications that I'm going to need to make. I'll mull on my decisions while I do that..
@evilpaul_atebit @jcreed yeah, the SIMD stuff I've tried is all a separate register file, so it has a multiple flags register too.

@evilpaul_atebit @jcreed "went for rH/rL type pairings and didn't like it" Ha, yeah. Thinking about it more, a lot of my bias against SIMD is that the little real-world stuff always seemed super clunky and not something you'd want to do by hand, and probably only really saved time/space if you were doing linear algebra or data processing at scale.

Load exactly 4 values from an aligned memory address, do the same thing to all 4 of them: a speed optimization that wasted space and processing units if your use-case didn't line up perfectly exactly with the capabilities.

@evilpaul_atebit @jcreed But yeah, moving in the more flexible direction that you two are talking about (even if I highly doubt it's something you could do with real hardware?) seems like a fun idea for the game
@evilpaul_atebit @jcreed this is making me really want to go build a programming game, heh
@JoshGrams @jcreed Haha.. the more the merrier :)

@jcreed @evilpaul_atebit Re: overlapping register groups: I think depending on how you implemented it in hardware, overlapping groups would work fine, you'd capture all the outputs before the new values propagated?

In a software emulation of it you'd have to be careful.