Added the SUBDIV (subtract and divide) instruction to Qupls4, used
mainly with pointer arithmetic. The integer divider shortcuts divisions
by powers of two. This was previously called PTRDIF which only did a
right shift instead of a divide.
SUBDIV Rd, Rs1, Rs2, Rs3 ; Rd = (Rs1-Rs2)/Rs3
At work again on Qupls4. Certain aspects seem to be stabilizing, like
the use of 48-bit instructions. The CPU currently has 64 GPRs. 8 GPRs
may be selected as carry registers and are selected by three-bit code in some instructions.
Added the SUBDIV (subtract and divide) instruction to Qupls4, used
mainly with pointer arithmetic. The integer divider shortcuts divisions
by powers of two. This was previously called PTRDIF which only did a
right shift instead of a divide.
SUBDIV Rd, Rs1, Rs2, Rs3 ; Rd = (Rs1-Rs2)/Rs3
At work again on Qupls4. Certain aspects seem to be stabilizing, like
the use of 48-bit instructions. The CPU currently has 64 GPRs. 8 GPRs
may be selected as carry registers and are selected by three-bit code in some instructions.
Robert Finch <[email protected]> posted:Maybe, it showed up less than 1% but more than 0.1% IIRC. It does not
Added the SUBDIV (subtract and divide) instruction to Qupls4, used
mainly with pointer arithmetic. The integer divider shortcuts divisions
by powers of two. This was previously called PTRDIF which only did a
right shift instead of a divide.
SUBDIV Rd, Rs1, Rs2, Rs3 ; Rd = (Rs1-Rs2)/Rs3
Is this seen/used often enough to save useful amounts of instructions ?
It does not appear to save execution time (except for power of 2 cases).
In My 66000, DIV is down near 0.5% seldom following a subtract.
At work again on Qupls4. Certain aspects seem to be stabilizing, like
the use of 48-bit instructions. The CPU currently has 64 GPRs. 8 GPRs
may be selected as carry registers and are selected by three-bit code in
some instructions.
Adding some graphics instructions to Q+. While doing so, it seems to me
like 24-bit load and store operations to handle RGB888 data might be handy.
It is a toss-up deciding to use single precision floats or 18.18 fixed
point arithmetic for graphics. The fixed point is about 3x faster
latency and a lot smaller. I am leaning towards using single precision floats though.
TEX - calculate texture index, TEX Rd, Rs1, Rs2, Rs3 ; Rs1 = U, Rs2 = V,
and Rs3 contains the texture width,height and bytes per pixel. The
texture cannot be more than 64k pixels high or wide.
RGBCVT - convert between RGB formats: eg. RGBCVT r2,r1,10,8 converts RGB8.8.8 to RGB10.10.10
BLEND - blend colors
TRANSFORM - transform point, performs matrix multiply for point transformation using coefficients that may be set prior to calc.
Robert Finch <[email protected]> posted:I have seen a 64-bit masked store operation in another architecture that allows suppressing the storage of bytes that match a condition like the transparent color or color mixing bits. It seems to me that architecture
Adding some graphics instructions to Q+. While doing so, it seems to me
like 24-bit load and store operations to handle RGB888 data might be handy.
A lot of GPUs use the other 8-bits as a mixing or transparency code.
It is a toss-up deciding to use single precision floats or 18.18 fixed
point arithmetic for graphics. The fixed point is about 3x faster
latency and a lot smaller. I am leaning towards using single precision
floats though.
TEX - calculate texture index, TEX Rd, Rs1, Rs2, Rs3 ; Rs1 = U, Rs2 = V,
and Rs3 contains the texture width,height and bytes per pixel. The
texture cannot be more than 64k pixels high or wide.
RGBCVT - convert between RGB formats: eg. RGBCVT r2,r1,10,8 converts
RGB8.8.8 to RGB10.10.10
BLEND - blend colors
TRANSFORM - transform point, performs matrix multiply for point
transformation using coefficients that may be set prior to calc.
Robert Finch <[email protected]> posted:
Adding some graphics instructions to Q+. While doing so, it seems to me
like 24-bit load and store operations to handle RGB888 data might be handy.
A lot of GPUs use the other 8-bits as a mixing or transparency code.
It is a toss-up deciding to use single precision floats or 18.18 fixed
point arithmetic for graphics. The fixed point is about 3x faster
latency and a lot smaller. I am leaning towards using single precision
floats though.
TEX - calculate texture index, TEX Rd, Rs1, Rs2, Rs3 ; Rs1 = U, Rs2 = V,
and Rs3 contains the texture width,height and bytes per pixel. The
texture cannot be more than 64k pixels high or wide.
RGBCVT - convert between RGB formats: eg. RGBCVT r2,r1,10,8 converts
RGB8.8.8 to RGB10.10.10
BLEND - blend colors
TRANSFORM - transform point, performs matrix multiply for point
transformation using coefficients that may be set prior to calc.
On 10/18/2026 12:50 PM, MitchAlsup wrote:
Robert Finch <[email protected]> posted:
Adding some graphics instructions to Q+. While doing so, it seems to me
like 24-bit load and store operations to handle RGB888 data might be
handy.
A lot of GPUs use the other 8-bits as a mixing or transparency code.
Yeah, 32-bit RGBA (RGBA32 / RGB8888) is pretty much standard, differing mostly as an unresolved fight over element ordering:
"R, G, B, A" vs "B, G, R, A".
24-bit is mostly a weird/awkward thing that is sometimes used but mostly
not really worth it; vs just ignoring the last 8 bits in a 32-bit word
when alpha isn't needed.
Some 10.10.10 formats exist, but are rarely used, and usually overkill.
3x E5.M5 does seem semi-popular here for HDR.
3x E4.M4 also works, and allows treating it like RGBA32.
And seems to match the look/behavior of HDR on a Radeon HD 4xxx.
3x E4.M6: No one uses it but would give better fidelity.
Personally, I use RGB555 a lot:
Mostly good enough for many uses;
Generally manages to look better than RGB565.
Here, 16 bits is a convenient size:
Nice space savings over 32 bit;
Works easily with 16 bit load/store ops, unlike 24 bits;
In practice the loss of visual fidelity isn't often that noticeable.
It is mostly obvious as banding in non-dithered gradients.
565 has an ugly issue that it introduces noisy greenish/purplish tints, whereas 555 at least provides proper grays and is more free of chromatic noise.
Depends on the up-conversion algo for 565 though, say:
Traditional:
R: Copy high 3 bits to low 3;
G: Copy high 2 bits to low 2;
B: Copy high 3 bits to low 3.
Result, chromatic noise.
Better visually:
R: Copy high 2 bits to low 2, bit 2 is LSB of G;
G: Copy high 2 bits to low 2;
B: Copy high 2 bits to low 2, bit 2 is LSB of G.
Avoids chromatic effect, but, this is non-traditional.
Though, often for 555 to look good some level of dithering is still
needed in many cases when down-converting from a higher bit-depth.
Personally, I have usually had best results with 2x2 or 4x4 Bayer.
People often argue that Floyd-Stanberg or Blue-Noise is better.
But, visually, 4x4 Bayer often seems to give the best results for me.
Dithering is also usually needed when down-converting to indexed color; otherwise bad posterization like effects may occur.
There are cases where it shouldn't be used, like SDF fonts:
Dithering an SDF makes it actively worse than posterizing it;
Also SDFs survive fairly well to indexed-color if the palette fits well (but, generally needs either palette optimization, or a generalized
palette optimized to SDFs; generic palettes don't really work).
Better to avoid using color-cell though, as traditional color-cell seems
to be more destructive to SDFs. So, was mostly having best results
storing them as 256-color (then applying LZ compression).
Have noted that there is another trick I have become aware of that can
boost compression of these sorts of images:
Encode the pixels in Hilbert (or maybe Morton) order rather than raster;
This seems to increase the effectiveness of the LZ compression even when
not using delta-filtering or entropy coding (and, unlike delta
filtering, does not derive its value from entropy coding; delta-
filtering without entropy-coding makes compression worse).
Theoretically, could do Hilbert-8 or Hilbert-16, but these patterns are
more complicated, and seemingly 2-levels of Hilbert-4 over a 16x16 block would achieve mostly the same effect. Computational cost is modest (and generally still notably less than that of using PNG style filters and entropy coding).
Though, an intermediate compromise here being to store pixels in Morton order; which mostly gives similar benefits for plain LZ (in the absence
of delta-filtering; Morton being notably worse for delta-filtering than Hilbert).
Even if, yes, this is mostly falling into wackiness.
Why not Vector / True-Type style fonts?
Mostly that these have higher computational cost.
And, for best results, need to render vector glyphs internally at a
somewhat higher resolution internally and then downsample them to the
target size (with many algos, trying to render them directly at the
target scale looks like broken crap).
However, bulk storage size for vector glyphs is less than that of SDFs,
and they are still better for dynamic scaling (SDFs usually have a
maximum useful size above which weirdness gets more obvious).
Say:
16x16 pixels SDF glyphs:
Effective range, ~ 8 to 32 pixels.
Below 8, need true mipmaps to avoid aliasing issues.
Above 32, jank is obvious.
32x32 glyphs could cover 5 to 64 pixels via mipmaps.
There is one trick I had found that works in both 3D rendering and SDFs: Rather than using true trilinear filtering, it is possible to use the
scale fraction mostly to pull the interpolation closer to the center in
a bilinear filter to mimic the effects of a trilinear filter at lower cost.
Or, basically, as it is about to jump to the next smaller mip-level, it
sees the average of the 4 texels, or basically, roughly the value it
would (presumably) have gotten from the next mip-level (if one assumes
each mip-level is offset at 1/2 texel relative to the one above).
Though, thinking, this does effectively have the property of going nearest-neighbor on the lower virtual mipmap level, rather than
accurately mimic the effect of trilinear, but usually doesn't matter.
Meanwhile, I have been having a weird experience recently mostly in that
my own long term memory seems to be garbled in some areas.
What was the trigger? A few old games, Myst and Riven.
Actually, it was more specifically catching some streams of someone
playing a modern remake of Riven; they were on one of the islands, had a response like "Wow, this looks a lot more immersive than the fixed view points in the original.", then was left questioning myself, like
"What?", part of my mind saying I had played it, another part not recognizing it.
I then had thought at first that they were games I was aware of when I
was much younger, but had mostly overlooked.
Downloaded them on GOG, started playing them.
First Riven, but was making unreasonably fast progress, like I kept just knowing where to go and what to do. Got a little weirded out.
Then went and did Myst, initially it was slow going (it didn't
immediately seem as familiar), but seemingly once I realized how to get
into the tower (by clicking one of the paintings to turn a bookshelf
into stairs), it was like I then knew the whole rest of the game (apart
from a few temporary snags). Like, once I got to each area, I somehow already knew what to do (well, except Stoneship, where I couldn't find
the compass at first and had mostly forgotten about it, it being a
necessary part of being able to return to the main island).
Got through the game in roughly 7 hours.
Then partly returned to Riven, have seemingly made it through much of
the game in roughly about 3 hours (remaining steps: Go visit the rebels through an animal ordering puzzle, to get back a trap-book, needed
before doing a fire-marble puzzle and facing off with the main villain).
Well, also need to fetch the code for opening the inner part of the dome (think it is in the notebook in the lab, need to go back there and look
at it more carefully... but they wrote it in cursive, so trying to read
it is "teh suck"). Well, and after the villain face-off, getting some
notes from a small music box to free someone, and crashing a telescope
into a window to end the game.
More or less... Trying to do any of these out-of-order leading to one of
the bad endings.
But, yeah, it is like the part of my mind that seemingly remembers the
game is winning this particular fight. If I hadn't played the game (or
if it were merely "contamination" from elsewhere, *2), I should have run into some major roadblock already. But, if I have, why don't I have consistent memories of the experience?... (The original memories I have
are fragmentary and garbled...).
*2: Well, say, if one sees parts of the game or knows plot spoilers,
this may allow cheating on some things, but wouldn't likely continue carrying someone through the whole game. Main reason I stopped when I
did, was because if I go through that animal-sequence puzzle, there was
a longish series of cutscenes on the other side. So, was more of a "will stop here, cutscenes some other day" thing. Then a few remaining things, then probably on to the endgame.
Like, I could probably do this for Half-Life, but, well, I actually
remember playing through Half-Life.
Well, among other things: Once, decades ago, I had a GF for a while. She
is seemingly tied in with these memories (mostly in that I think it was
her that had the game). But, this is where memories are most unstable (I don't really know if this is real or not). These memories also seem to characterize her somewhat different than in other memories.
But, it would seem in any case, this is not my first encounter with this game.
But, in some way, it is more a case of trying to figure out what exactly happened to my memory here. Most of the rest of my memory doesn't seem
quite to badly chewed.
Switched this to 16.16>It is a toss-up deciding to use single precision floats or 18.18 fixed
point arithmetic for graphics. The fixed point is about 3x faster
latency and a lot smaller. I am leaning towards using single precision
floats though.
In TKRA-GL, the internal rasterizer is mostly using 16 bit fixed point.
Or, 8.8, generally mapped to packed-16-bit SIMD vectors.
Ironically, for a while, I had thought that the reason TKRA-GL's
software rasterization was as fast as it was, was because of epic
properties of my ASM based span-drawing functions.
After the move to XG3, which goes back to using the same basic C based versions as used when building for other targets, it is more obvious it
is not.
Or, what seeming performance advantages exist for my ISA design,
relative to RV64G and x86, exist independent of any special merit of highly-tuned ASM code. But, then again, BGBCC has reached a point of (mostly) not producing horribly inefficient compiler output, so...
There was a false start, where I was wondering why a build of TKRA-GL + GLQuake for native Win10+X64 was performing so badly (barely much faster
at 640x480 than for my own ISA). But, then realized it is was because I
had misunderstood the meaning of an MSVC command-line option and then
left and forgot about it, so I was essentially comparing against an unoptimized debug build, and hence the lame performance.
Still weird in a way though that the gulf between 3.7 GHz and 50 MHz
manages to still be small enough that the effects of a debug build are obvious.
But, results do still seem my ISA is "punching above its weight class",
in being able to give any level of semi-usable OpenGL on a 50 MHz CPU.
Well, never-mind the seemingly impossible demand that I would seemingly either need 200 MHz or 4 cores working in parallel to be able to give playable results for Quake 3.
Though, if I was targeting mainly the XC7A200T, could try to do a setup like, maybe:
1 control core (full ISA);
4 render cores (more limited ISA);
2 rasterizer modules, probably dividing the screen in half.
Would need to split requests that cross halves though.
The most likely idea for the render cores being, say:
XG3+RV64G only (no RV-C or XG1/XG2 support);
Omits the Double-Precision FPU (saves a few kLUT);
Omits 64-bit integer multiply/divide (also another kLUT);
L1 D$ is aligned-only (also saves a big chunk of LUTs).
Missing functionality either being unsupported entirely, or faked via emulation traps. This is less bad though if one were to assume such
cores only exist to run the TKRA-GL transform and rendering pipeline.
Though, if all 4 cores are working on the same shared framebuffers,
would need cache coherence. Or some way to divide up geometry by
location, but can't know where geometry is on-screen until after the projection stage; which is one of the places one would want to split up.
Well, unless maybe:
Main CPU:
Runs GLQuake / Quake2 / Quake3
Deals with OpenGL;
Does initial projection;
Adds projected primitives to a global work list.
Worker Cores:
Grab a primitive, and check for need to subdivide;
If needs subdivision:
Subdivide primitive;
Keeps any pieces that belong to its area;
Others, pushed back to shared list.
If local to this cores region?
Process it.
Else:
Push it back to the list.
Though, in this case, the shared list is likely to become a bottleneck.
Could maybe reduce overhead by giving each core its own work queue, with
the main CPU having a push-back queue.
Each core only looks in its own list for new work, but may push work
over to other cores (if in their area), or back to the main CPU (if it
needs work there, like splitting a primitive between two workers).
For sake of sanity, the main CPU can wait around until it and all the workers complete the draw-call.
Though, another (maybe simpler) option in this case being to invest in a memory-coherence mechanism, which would allow simply dividing up the primitives sequentially hand handing each off to one of the cores (which
may then draw anywhere in the framebuffer).
Would mean the L2 cache or similar would need to track who "owns each
dirty cache line" and has the ability to issue "please write back this
line" requests to the cores.
Maybe this is optional, and so may only need to apply to specific memory mappings (via the TLB):
Default: Weak coherence only;
If enabled per-page: Memory access needs to be cache-coherent.
Then again, may also make sense to still have a single rasterizer module
for its MMIO interface, but if needed, the rasterizer could have
multiple "worker units" internally.
Would also need to add a step to the MMIO interface though to deal with multiple cores firing requests at is, say:
Core checks if unit is ready to accept work (status register);
Core writes a request requesting ability to use the interface;
Reads back status, seeing if its request was granted;
If not, retry until success.
(This overlaps with the existing busy / flow-control handling).
Core writes its request's content registers;
Core writes to status register to submit work to the FIFO.
This trying to avoid the situation where the cores step on each other by both trying to write to the registers for the MMIO interface at the same time.
There is already a flow-control mechanism (for busy signaling), but for muliple cores would need to add a "request in progress" mechanism to
this (submitting a request to this module basically involves setting up
a bunch of parameters to describe the part of the primitive to be rasterized).
Note that TKRA-GL uses a hybrid process, where simple tasks are handled
by the rasterizer module, but more advanced tasks use software rasterization.
At present, the software-rasterization seems to be managing alpha-
testing, may need to change this though.
Well, also software manages GL_LINES, GL_POINTS, and drawing primitives
as outlines (with these cases being annoyingly inefficient; as it takes almost as much computationally to draw a point or line as it does to
draw a small triangle or quad).
...
TEX - calculate texture index, TEX Rd, Rs1, Rs2, Rs3 ; Rs1 = U, Rs2 = V, >>> and Rs3 contains the texture width,height and bytes per pixel. The
texture cannot be more than 64k pixels high or wide.
I did this via an LDTEX instruction.
It passed U/V as 2x 16.16 though.
With the register understood as 2x 32-bit.
Also it used the tag-bits to encode texture resolution as a combined
log-2, with a few bits to encode the encoding format:
RGB555 (A.R5.R5.R5);
RGBA32 (A8.R8.G8.B8);
RGBA64 (A16.R16.G16.B16);
UTX2 (2x RGB555, 4x4x2 selector bits)
Functional stand-in for DXT1 / BC1
UTX3 (2x RGBA32, 4x4x2 RGB, 4x4x2 A)
Functional stand-in for DXT5 / BC3
Overlaps with BC7 in slightly higher color fidelity.
Or, with BC6H in the HDR mode.
Using E4.M4 per component...
There was UTX1, but it mostly isn't used much, as it packed both
endpoints into 16 bits (D4, RGB444), and used 4x4x1 selector bits.
Quality is worse than UTX1, so isn't usually a good option.
There is a restriction on LDTEX (and the rasterizer module) that only certain ranges of texture sizes are allowed, eg:
1x1, 2x1, 2x2, 4x2, 4x4, 8x4, 8x8, ..., 256x256, 512x256, 512x512, ...
Though, with 5 bits, will max out at 65536x32768.
But, 64k x 64k is impractically huge.
TKRA-GL currently maxes out at around 1024x1024 IIRC.
But, better to not exceed 256x256 without good reason.
While it doesn't directly support 256x512 or similar, it can fake it by swapping U and V.
Any textures further off from this will need to be resampled to one of
the valid sizes.
In this case, it is possible to pass off-size and NPOT images to glTexImage2D or similar, but they will be auto-resized internally, as it doesn't actually support NPOT internally.
Part of the quirk also is that the textures internally all use Morton- Order, and this size progression is what one gets by performing the
Morton shuffle and masking the result.
One other interesting/useful property of Morton order is that nearby
texels are more likely to be in-cache.
Morton order is also a lot simpler/cheaper to deal with than Hilbert
Order here, but Hilbert is better for locality.
The LDTEX instruction only does nearest-neighbor by default, though
there is a 64-bit encoding that allows also specifying which corner one wants.
Say:
LDTEX (R10, R11, 4), R28 //bottom left
LDTEX (R10, R11, 5), R29 //bottom right
LDTEX (R10, R11, 6), R30 //top left
LDTEX (R10, R11, 7), R31 //top right
Assuming a coordinate space where (0,0) is in the bottom-left corner and
V points upwards.
With the 32-bit encoding giving Nearest by default.
In this case, the span-drawing function needs to do its own
interpolation. Well, and for sake of speed, had often used 3 points and simplified interpolation, which was partly inspired by the GPU in the
N64, but differs in that I use a slightly different approach so the
result looks different.
In my case, interpolate along U and V, then a weighted difference to interpolate along the diagonal; the N64 version apparently mirrors the interpolation if it would fall near the far corner, essentially dividing
it into 2 triangular regions. Doing a little bit of mental grinding, I
think the behavior of the N64 style interpolation might be to simply
take (V-U) as the diagonal and let it wrap on overflow (as opposed to essentially (V-U)*0.5+0.5).
In this case, the low 48 bits of the texture encode the base address of
the image.
For the rasterizer module, the address requires an alignment. I forget
if 16 or 64 bytes at the moment; may have been 64 to match the L2
cache's internal cache-line size (this being because the module mostly
uses bare cache lines for its memory access to the RGB/Z buffers and textures).
In the RGA32 mode, as noted:
Framebuffer format: RGBA32
Z buffer format: Z24.S8
But, also has a 16-bit mode:
RGB: RGB5A (A.R5.G5.B5)
Z: Z16 | Z12.S4
TKRA-GL is currently often using things in 16-bit mode with Z12, which admittedly isn't great for Z-fighting (even my GLQuake port has some significant Z fighting with this).
The Z16 mode basically requires the program to swear that it will never enable stencil testing though.
A 4-bit stencil buffer is basically enough to handle things like stencil shadows and similar; though stencil shadowing is slow on TKRA-GL so not
a good idea. 2-bit would have given less Z-fighting, but is near useless
for stencil effects.
An RGB555 color buffer though does impact the allowed blending
operations (pretty much nothing that uses DEST_ALPHA will work
correctly). But, then again, it is pretty much never used as such
(things like light-mapping typically using DEST_COLOr instead).
Or, one can use the 32-bit mode for higher visual fidelity, but in this
case it uses more memory and is slower (and the final output stages
still require a conversion to RGB555).
...
RGBCVT - convert between RGB formats: eg. RGBCVT r2,r1,10,8 converts
RGB8.8.8 to RGB10.10.10
BLEND - blend colors
TRANSFORM - transform point, performs matrix multiply for point
transformation using coefficients that may be set prior to calc.
I didn't go this far.
Would make sense if defining a shader-ASM language, but probably not for
a CPU.
On 2026-10-19 5:46 p.m., BGB wrote:
On 10/18/2026 12:50 PM, MitchAlsup wrote:
Robert Finch <[email protected]> posted:
Adding some graphics instructions to Q+. While doing so, it seems to me >>> like 24-bit load and store operations to handle RGB888 data might be
handy.
A lot of GPUs use the other 8-bits as a mixing or transparency code.
Yeah, 32-bit RGBA (RGBA32 / RGB8888) is pretty much standard, differing mostly as an unresolved fight over element ordering:
"R, G, B, A" vs "B, G, R, A".
Figures. I use ARGB, putting the alpha in the MSBs.
24-bit is mostly a weird/awkward thing that is sometimes used but mostly not really worth it; vs just ignoring the last 8 bits in a 32-bit word when alpha isn't needed.
Some 10.10.10 formats exist, but are rarely used, and usually overkill.
3x E5.M5 does seem semi-popular here for HDR.
3x E4.M4 also works, and allows treating it like RGBA32.
And seems to match the look/behavior of HDR on a Radeon HD 4xxx.
3x E4.M6: No one uses it but would give better fidelity.
Most people cannot see color beyond RGB777 so 10.10.10 is overkill but I
had worried about rounding of colors and figure a few extra bits would
not hurt. ARGB3777 is 24-bit. Some of the very early display adapters
only supported 18 bits for color. So, ARGB6666 - fits nicely in 24 bits.
Robert Finch <[email protected]> posted:3x8-bit RGB is typically OK for finished photos, but for anything that's going to be edited, you want a _lot_ more.
On 2026-10-19 5:46 p.m., BGB wrote:
On 10/18/2026 12:50 PM, MitchAlsup wrote:Figures. I use ARGB, putting the alpha in the MSBs.
Robert Finch <[email protected]> posted:Yeah, 32-bit RGBA (RGBA32 / RGB8888) is pretty much standard, differing
Adding some graphics instructions to Q+. While doing so, it seems to me >>>>> like 24-bit load and store operations to handle RGB888 data might be >>>>> handy.
A lot of GPUs use the other 8-bits as a mixing or transparency code.>>>> >>>
mostly as an unresolved fight over element ordering:
 "R, G, B, A" vs "B, G, R, A".
Most people cannot see color beyond RGB777 so 10.10.10 is overkill but I
24-bit is mostly a weird/awkward thing that is sometimes used but mostly >>> not really worth it; vs just ignoring the last 8 bits in a 32-bit word
when alpha isn't needed.
Some 10.10.10 formats exist, but are rarely used, and usually overkill.
 3x E5.M5 does seem semi-popular here for HDR.
 3x E4.M4 also works, and allows treating it like RGBA32.
   And seems to match the look/behavior of HDR on a Radeon HD 4xxx.
 3x E4.M6: No one uses it but would give better fidelity.
had worried about rounding of colors and figure a few extra bits would>> not hurt. ARGB3777 is 24-bit. Some of the very early display adapters
only supported 18 bits for color. So, ARGB6666 - fits nicely in 24 bits.
And then there are those of us who edit photographs and hate it when
a change to gamma results in posterization of the "sky" or any other recognizable color with a small gradient. We also worry about gamut.
MitchAlsup wrote:
Robert Finch <[email protected]> posted:
On 2026-10-19 5:46 p.m., BGB wrote:
On 10/18/2026 12:50 PM, MitchAlsup wrote:Figures. I use ARGB, putting the alpha in the MSBs.
Robert Finch <[email protected]> posted:
Adding some graphics instructions to Q+. While doing so, it seems to me >>>>> like 24-bit load and store operations to handle RGB888 data might be >>>>> handy.
A lot of GPUs use the other 8-bits as a mixing or transparency code. >>>>
Yeah, 32-bit RGBA (RGBA32 / RGB8888) is pretty much standard, differing >>> mostly as an unresolved fight over element ordering:
 "R, G, B, A" vs "B, G, R, A".
Most people cannot see color beyond RGB777 so 10.10.10 is overkill but I >> had worried about rounding of colors and figure a few extra bits would
24-bit is mostly a weird/awkward thing that is sometimes used but mostly >>> not really worth it; vs just ignoring the last 8 bits in a 32-bit word >>> when alpha isn't needed.
Some 10.10.10 formats exist, but are rarely used, and usually overkill. >>> Â 3x E5.M5 does seem semi-popular here for HDR.
 3x E4.M4 also works, and allows treating it like RGBA32.
   And seems to match the look/behavior of HDR on a Radeon HD 4xxx.
 3x E4.M6: No one uses it but would give better fidelity.
not hurt. ARGB3777 is 24-bit. Some of the very early display adapters
only supported 18 bits for color. So, ARGB6666 - fits nicely in 24 bits.
And then there are those of us who edit photographs and hate it when
a change to gamma results in posterization of the "sky" or any other recognizable color with a small gradient. We also worry about gamut.
3x8-bit RGB is typically OK for finished photos, but for anything that's going to be edited, you want a _lot_ more.
Terje
Terje Mathisen <[email protected]> posted:
MitchAlsup wrote:
Robert Finch <[email protected]> posted:
On 2026-10-19 5:46 p.m., BGB wrote:And then there are those of us who edit photographs and hate it when
On 10/18/2026 12:50 PM, MitchAlsup wrote:Figures. I use ARGB, putting the alpha in the MSBs.
Robert Finch <[email protected]> posted:
Adding some graphics instructions to Q+. While doing so, it seems to me >>>>>>> like 24-bit load and store operations to handle RGB888 data might be >>>>>>> handy.
A lot of GPUs use the other 8-bits as a mixing or transparency code. >>>>>>
Yeah, 32-bit RGBA (RGBA32 / RGB8888) is pretty much standard, differing >>>>> mostly as an unresolved fight over element ordering:
 "R, G, B, A" vs "B, G, R, A".
Most people cannot see color beyond RGB777 so 10.10.10 is overkill but I >>>> had worried about rounding of colors and figure a few extra bits would >>>> not hurt. ARGB3777 is 24-bit. Some of the very early display adapters
24-bit is mostly a weird/awkward thing that is sometimes used but mostly >>>>> not really worth it; vs just ignoring the last 8 bits in a 32-bit word >>>>> when alpha isn't needed.
Some 10.10.10 formats exist, but are rarely used, and usually overkill. >>>>> Â 3x E5.M5 does seem semi-popular here for HDR.
 3x E4.M4 also works, and allows treating it like RGBA32.
   And seems to match the look/behavior of HDR on a Radeon HD 4xxx.
 3x E4.M6: No one uses it but would give better fidelity.
only supported 18 bits for color. So, ARGB6666 - fits nicely in 24 bits. >>>
a change to gamma results in posterization of the "sky" or any other
recognizable color with a small gradient. We also worry about gamut.
3x8-bit RGB is typically OK for finished photos, but for anything that's
going to be edited, you want a _lot_ more.
While 8-bits is sufficient for almost any viewing of an image
For editing::
10-bits is nowhere close to being enough
12-bits is pretty reasonable for gentle editing (old RAW circa 2005)
14-bits is very good for significant editing (new RAW circa 2015)
16-bits seems to be enough for all sensor types.
Terje
On 2026-10-19 5:46 p.m., BGB wrote:
On 10/18/2026 12:50 PM, MitchAlsup wrote:Figures. I use ARGB, putting the alpha in the MSBs.
Robert Finch <[email protected]> posted:
Adding some graphics instructions to Q+. While doing so, it seems to me >>>> like 24-bit load and store operations to handle RGB888 data might be
handy.
A lot of GPUs use the other 8-bits as a mixing or transparency code.
Yeah, 32-bit RGBA (RGBA32 / RGB8888) is pretty much standard,
differing mostly as an unresolved fight over element ordering:
"R, G, B, A" vs "B, G, R, A".
Most people cannot see color beyond RGB777 so 10.10.10 is overkill but I
24-bit is mostly a weird/awkward thing that is sometimes used but
mostly not really worth it; vs just ignoring the last 8 bits in a 32-
bit word when alpha isn't needed.
Some 10.10.10 formats exist, but are rarely used, and usually overkill.
3x E5.M5 does seem semi-popular here for HDR.
3x E4.M4 also works, and allows treating it like RGBA32.
And seems to match the look/behavior of HDR on a Radeon HD 4xxx.
3x E4.M6: No one uses it but would give better fidelity.
had worried about rounding of colors and figure a few extra bits would
not hurt. ARGB3777 is 24-bit. Some of the very early display adapters
only supported 18 bits for color. So, ARGB6666 - fits nicely in 24 bits.
The video hardware uses a 32-bit color bus. I had it at 40-bits (To
support ARGB10.10.10.10) but figured it would never get used. Really
needed to trim the bus size down to save LUTs. It is tempting to go to ARGB3777 for the display hardware. The RGB to HDMI converter only
supports 8.8.8.
Personally, I use RGB555 a lot:
Mostly good enough for many uses;
Generally manages to look better than RGB565.
Here, 16 bits is a convenient size:
Nice space savings over 32 bit;
Works easily with 16 bit load/store ops, unlike 24 bits;
In practice the loss of visual fidelity isn't often that noticeable.
It is mostly obvious as banding in non-dithered gradients.
I like the RGB555, it is the default format for my video hardware IIRC.
But I made the hardware completely programmable for just about any format.>
565 has an ugly issue that it introduces noisy greenish/purplish
tints, whereas 555 at least provides proper grays and is more free of
chromatic noise.
Depends on the up-conversion algo for 565 though, say:
Traditional:
R: Copy high 3 bits to low 3;
G: Copy high 2 bits to low 2;
B: Copy high 3 bits to low 3.
Result, chromatic noise.
Better visually:
R: Copy high 2 bits to low 2, bit 2 is LSB of G;
G: Copy high 2 bits to low 2;
B: Copy high 2 bits to low 2, bit 2 is LSB of G.
Avoids chromatic effect, but, this is non-traditional.
Though, often for 555 to look good some level of dithering is still
needed in many cases when down-converting from a higher bit-depth.
Personally, I have usually had best results with 2x2 or 4x4 Bayer.
People often argue that Floyd-Stanberg or Blue-Noise is better.
But, visually, 4x4 Bayer often seems to give the best results for me. >>
Dithering is also usually needed when down-converting to indexed
color; otherwise bad posterization like effects may occur.
What about 3x3 alternating? I tried dithering but could not get the
quality of results satisfactory. I could see the dither, figured it was better just to change the video resolution.>
There are cases where it shouldn't be used, like SDF fonts:
Dithering an SDF makes it actively worse than posterizing it;
Also SDFs survive fairly well to indexed-color if the palette fits
well (but, generally needs either palette optimization, or a
generalized palette optimized to SDFs; generic palettes don't really
work).
Better to avoid using color-cell though, as traditional color-cell
seems to be more destructive to SDFs. So, was mostly having best
results storing them as 256-color (then applying LZ compression).
Have noted that there is another trick I have become aware of that can
boost compression of these sorts of images:
Encode the pixels in Hilbert (or maybe Morton) order rather than raster;
This seems to increase the effectiveness of the LZ compression even
when not using delta-filtering or entropy coding (and, unlike delta
filtering, does not derive its value from entropy coding; delta-
filtering without entropy-coding makes compression worse).
Theoretically, could do Hilbert-8 or Hilbert-16, but these patterns
are more complicated, and seemingly 2-levels of Hilbert-4 over a 16x16
block would achieve mostly the same effect. Computational cost is
modest (and generally still notably less than that of using PNG style
filters and entropy coding).
Though, an intermediate compromise here being to store pixels in
Morton order; which mostly gives similar benefits for plain LZ (in the
absence of delta-filtering; Morton being notably worse for delta-
filtering than Hilbert).
Even if, yes, this is mostly falling into wackiness.
Why not Vector / True-Type style fonts?
Mostly that these have higher computational cost.
And, for best results, need to render vector glyphs internally at a
somewhat higher resolution internally and then downsample them to the
target size (with many algos, trying to render them directly at the
target scale looks like broken crap).
However, bulk storage size for vector glyphs is less than that of
SDFs, and they are still better for dynamic scaling (SDFs usually have
a maximum useful size above which weirdness gets more obvious).
Say:
16x16 pixels SDF glyphs:
Effective range, ~ 8 to 32 pixels.
Below 8, need true mipmaps to avoid aliasing issues.
Above 32, jank is obvious.
32x32 glyphs could cover 5 to 64 pixels via mipmaps.
There is one trick I had found that works in both 3D rendering and SDFs:
Rather than using true trilinear filtering, it is possible to use the
scale fraction mostly to pull the interpolation closer to the center
in a bilinear filter to mimic the effects of a trilinear filter at
lower cost.
Or, basically, as it is about to jump to the next smaller mip-level,
it sees the average of the 4 texels, or basically, roughly the value
it would (presumably) have gotten from the next mip-level (if one
assumes each mip-level is offset at 1/2 texel relative to the one above).
Though, thinking, this does effectively have the property of going
nearest-neighbor on the lower virtual mipmap level, rather than
accurately mimic the effect of trilinear, but usually doesn't matter.
Meanwhile, I have been having a weird experience recently mostly in
that my own long term memory seems to be garbled in some areas.
What was the trigger? A few old games, Myst and Riven.
Actually, it was more specifically catching some streams of someone
playing a modern remake of Riven; they were on one of the islands, had
a response like "Wow, this looks a lot more immersive than the fixed
view points in the original.", then was left questioning myself, like
"What?", part of my mind saying I had played it, another part not
recognizing it.
I played MYST. I got lost in the subway. It turns out my hearing was not good enough to hear the beeps, so I had no clues to go by. I had to
resort to looking up how to escape on the internet. Once I got out of
the subway I was able to finish the game.>
I then had thought at first that they were games I was aware of when ISwitched this to 16.16>
was much younger, but had mostly overlooked.
Downloaded them on GOG, started playing them.
First Riven, but was making unreasonably fast progress, like I kept
just knowing where to go and what to do. Got a little weirded out.
Then went and did Myst, initially it was slow going (it didn't
immediately seem as familiar), but seemingly once I realized how to
get into the tower (by clicking one of the paintings to turn a
bookshelf into stairs), it was like I then knew the whole rest of the
game (apart from a few temporary snags). Like, once I got to each
area, I somehow already knew what to do (well, except Stoneship, where
I couldn't find the compass at first and had mostly forgotten about
it, it being a necessary part of being able to return to the main
island).
Got through the game in roughly 7 hours.
Then partly returned to Riven, have seemingly made it through much of
the game in roughly about 3 hours (remaining steps: Go visit the
rebels through an animal ordering puzzle, to get back a trap-book,
needed before doing a fire-marble puzzle and facing off with the main
villain).
Well, also need to fetch the code for opening the inner part of the
dome (think it is in the notebook in the lab, need to go back there
and look at it more carefully... but they wrote it in cursive, so
trying to read it is "teh suck"). Well, and after the villain face-
off, getting some notes from a small music box to free someone, and
crashing a telescope into a window to end the game.
More or less... Trying to do any of these out-of-order leading to one
of the bad endings.
But, yeah, it is like the part of my mind that seemingly remembers the
game is winning this particular fight. If I hadn't played the game (or
if it were merely "contamination" from elsewhere, *2), I should have
run into some major roadblock already. But, if I have, why don't I
have consistent memories of the experience?... (The original memories
I have are fragmentary and garbled...).
*2: Well, say, if one sees parts of the game or knows plot spoilers,
this may allow cheating on some things, but wouldn't likely continue
carrying someone through the whole game. Main reason I stopped when I
did, was because if I go through that animal-sequence puzzle, there
was a longish series of cutscenes on the other side. So, was more of a
"will stop here, cutscenes some other day" thing. Then a few remaining
things, then probably on to the endgame.
Like, I could probably do this for Half-Life, but, well, I actually
remember playing through Half-Life.
Well, among other things: Once, decades ago, I had a GF for a while.
She is seemingly tied in with these memories (mostly in that I think
it was her that had the game). But, this is where memories are most
unstable (I don't really know if this is real or not). These memories
also seem to characterize her somewhat different than in other memories.
But, it would seem in any case, this is not my first encounter with
this game.
But, in some way, it is more a case of trying to figure out what
exactly happened to my memory here. Most of the rest of my memory
doesn't seem quite to badly chewed.
It is a toss-up deciding to use single precision floats or 18.18 fixed >>>> point arithmetic for graphics. The fixed point is about 3x faster
latency and a lot smaller. I am leaning towards using single precision >>>> floats though.
In TKRA-GL, the internal rasterizer is mostly using 16 bit fixed point.That is quite a difference in clock rate. I wonder what the difference
Or, 8.8, generally mapped to packed-16-bit SIMD vectors.
Ironically, for a while, I had thought that the reason TKRA-GL's
software rasterization was as fast as it was, was because of epic
properties of my ASM based span-drawing functions.
After the move to XG3, which goes back to using the same basic C based
versions as used when building for other targets, it is more obvious
it is not.
Or, what seeming performance advantages exist for my ISA design,
relative to RV64G and x86, exist independent of any special merit of
highly-tuned ASM code. But, then again, BGBCC has reached a point of
(mostly) not producing horribly inefficient compiler output, so...
There was a false start, where I was wondering why a build of TKRA-GL
+ GLQuake for native Win10+X64 was performing so badly (barely much
faster at 640x480 than for my own ISA). But, then realized it is was
because I had misunderstood the meaning of an MSVC command-line option
and then left and forgot about it, so I was essentially comparing
against an unoptimized debug build, and hence the lame performance.
Still weird in a way though that the gulf between 3.7 GHz and 50 MHz
manages to still be small enough that the effects of a debug build are
obvious.
is in memory performance. Maybe being able to execute a whole bunch more instructions does not make as much difference as one might think because
of the memory access time.>
But, results do still seem my ISA is "punching above its weight
class", in being able to give any level of semi-usable OpenGL on a 50
MHz CPU.
Well, never-mind the seemingly impossible demand that I would
seemingly either need 200 MHz or 4 cores working in parallel to be
able to give playable results for Quake 3.
Though, if I was targeting mainly the XC7A200T, could try to do a
setup like, maybe:
1 control core (full ISA);
4 render cores (more limited ISA);
2 rasterizer modules, probably dividing the screen in half.
Would need to split requests that cross halves though.
The most likely idea for the render cores being, say:
XG3+RV64G only (no RV-C or XG1/XG2 support);
Omits the Double-Precision FPU (saves a few kLUT);
Omits 64-bit integer multiply/divide (also another kLUT);
L1 D$ is aligned-only (also saves a big chunk of LUTs).
Missing functionality either being unsupported entirely, or faked via
emulation traps. This is less bad though if one were to assume such
cores only exist to run the TKRA-GL transform and rendering pipeline.
Though, if all 4 cores are working on the same shared framebuffers,
would need cache coherence. Or some way to divide up geometry by
location, but can't know where geometry is on-screen until after the
projection stage; which is one of the places one would want to split up.
Well, unless maybe:
Main CPU:
Runs GLQuake / Quake2 / Quake3
Deals with OpenGL;
Does initial projection;
Adds projected primitives to a global work list.
Worker Cores:
Grab a primitive, and check for need to subdivide;
If needs subdivision:
Subdivide primitive;
Keeps any pieces that belong to its area;
Others, pushed back to shared list.
If local to this cores region?
Process it.
Else:
Push it back to the list.
Though, in this case, the shared list is likely to become a bottleneck.
Could maybe reduce overhead by giving each core its own work queue,
with the main CPU having a push-back queue.
Each core only looks in its own list for new work, but may push work
over to other cores (if in their area), or back to the main CPU (if it
needs work there, like splitting a primitive between two workers).
For sake of sanity, the main CPU can wait around until it and all the
workers complete the draw-call.
Though, another (maybe simpler) option in this case being to invest in
a memory-coherence mechanism, which would allow simply dividing up the
primitives sequentially hand handing each off to one of the cores
(which may then draw anywhere in the framebuffer).
Would mean the L2 cache or similar would need to track who "owns each
dirty cache line" and has the ability to issue "please write back this
line" requests to the cores.
Maybe this is optional, and so may only need to apply to specific
memory mappings (via the TLB):
Default: Weak coherence only;
If enabled per-page: Memory access needs to be cache-coherent.
Then again, may also make sense to still have a single rasterizer
module for its MMIO interface, but if needed, the rasterizer could
have multiple "worker units" internally.
Would also need to add a step to the MMIO interface though to deal
with multiple cores firing requests at is, say:
Core checks if unit is ready to accept work (status register);
Core writes a request requesting ability to use the interface;
Reads back status, seeing if its request was granted;
If not, retry until success.
(This overlaps with the existing busy / flow-control handling).
Core writes its request's content registers;
Core writes to status register to submit work to the FIFO.
This trying to avoid the situation where the cores step on each other
by both trying to write to the registers for the MMIO interface at the
same time.
There is already a flow-control mechanism (for busy signaling), but
for muliple cores would need to add a "request in progress" mechanism
to this (submitting a request to this module basically involves
setting up a bunch of parameters to describe the part of the primitive
to be rasterized).
Note that TKRA-GL uses a hybrid process, where simple tasks are
handled by the rasterizer module, but more advanced tasks use software
rasterization.
At present, the software-rasterization seems to be managing alpha-
testing, may need to change this though.
Well, also software manages GL_LINES, GL_POINTS, and drawing
primitives as outlines (with these cases being annoyingly inefficient;
as it takes almost as much computationally to draw a point or line as
it does to draw a small triangle or quad).
...
TEX - calculate texture index, TEX Rd, Rs1, Rs2, Rs3 ; Rs1 = U, Rs2
= V,
and Rs3 contains the texture width,height and bytes per pixel. The
texture cannot be more than 64k pixels high or wide.
I did this via an LDTEX instruction.
I figured it was better to separate the address calculation from the
data load. TEX then a load. Teh TEX instruction has a fairly high
latency about 5 cycles for fixed point or 20 for floats. The pixels surrounding the source pixel could be fetched using displacements from
the TEX address avoiding multiple TEX instructions.
Might need to be able to load / store data based on a data size stored
in a register. I may change the 24-bit load/stores into variable data
size load/stores. There is also a 72-bit load/store for register values including an 8-bit tag. I would also like 48-bit load/stores for instructions.>
It passed U/V as 2x 16.16 though.Most GPUs are like this, so I have read. It allows a trick to be used
With the register understood as 2x 32-bit.
Also it used the tag-bits to encode texture resolution as a combined
log-2, with a few bits to encode the encoding format:
RGB555 (A.R5.R5.R5);
RGBA32 (A8.R8.G8.B8);
RGBA64 (A16.R16.G16.B16);
UTX2 (2x RGB555, 4x4x2 selector bits)
Functional stand-in for DXT1 / BC1
UTX3 (2x RGBA32, 4x4x2 RGB, 4x4x2 A)
Functional stand-in for DXT5 / BC3
Overlaps with BC7 in slightly higher color fidelity.
Or, with BC6H in the HDR mode.
Using E4.M4 per component...
There was UTX1, but it mostly isn't used much, as it packed both
endpoints into 16 bits (D4, RGB444), and used 4x4x1 selector bits.
Quality is worse than UTX1, so isn't usually a good option.
There is a restriction on LDTEX (and the rasterizer module) that only
certain ranges of texture sizes are allowed, eg:
1x1, 2x1, 2x2, 4x2, 4x4, 8x4, 8x8, ..., 256x256, 512x256, 512x512, ... >> Though, with 5 bits, will max out at 65536x32768.
But, 64k x 64k is impractically huge.
TKRA-GL currently maxes out at around 1024x1024 IIRC.
But, better to not exceed 256x256 without good reason.
with the float arithmetic. The exponent can be scaled instead of doing multiplies.
While it doesn't directly support 256x512 or similar, it can fake it
by swapping U and V.
Any textures further off from this will need to be resampled to one of
the valid sizes.
In this case, it is possible to pass off-size and NPOT images to
glTexImage2D or similar, but they will be auto-resized internally, as
it doesn't actually support NPOT internally.
Part of the quirk also is that the textures internally all use Morton-
Order, and this size progression is what one gets by performing the
Morton shuffle and masking the result.
What is Morton or Hilbert order? I would think raster order may be
better as it would allow one to read multiple pixels at a time.>
One other interesting/useful property of Morton order is that nearby
texels are more likely to be in-cache.
Morton order is also a lot simpler/cheaper to deal with than Hilbert
Order here, but Hilbert is better for locality.
The LDTEX instruction only does nearest-neighbor by default, though
there is a 64-bit encoding that allows also specifying which corner
one wants.
Say:
LDTEX (R10, R11, 4), R28 //bottom left
LDTEX (R10, R11, 5), R29 //bottom right
LDTEX (R10, R11, 6), R30 //top left
LDTEX (R10, R11, 7), R31 //top right
Assuming a coordinate space where (0,0) is in the bottom-left corner
and V points upwards.
I would think that the load should be able to load bottom-left, bottom- middle, and bottom-top pixels with a single load operation. Then extract
the pixels using a second instruction. Same for top and middle.
I have TEX calculating the address of the centre, then use displacements from that address in the loads.>
With the 32-bit encoding giving Nearest by default.Things are memory limited in my system, there being only a single DDRRAM
In this case, the span-drawing function needs to do its own
interpolation. Well, and for sake of speed, had often used 3 points
and simplified interpolation, which was partly inspired by the GPU in
the N64, but differs in that I use a slightly different approach so
the result looks different.
In my case, interpolate along U and V, then a weighted difference to
interpolate along the diagonal; the N64 version apparently mirrors the
interpolation if it would fall near the far corner, essentially
dividing it into 2 triangular regions. Doing a little bit of mental
grinding, I think the behavior of the N64 style interpolation might be
to simply take (V-U) as the diagonal and let it wrap on overflow (as
opposed to essentially (V-U)*0.5+0.5).
In this case, the low 48 bits of the texture encode the base address
of the image.
For the rasterizer module, the address requires an alignment. I forget
if 16 or 64 bytes at the moment; may have been 64 to match the L2
cache's internal cache-line size (this being because the module mostly
uses bare cache lines for its memory access to the RGB/Z buffers and
textures).
In the RGA32 mode, as noted:
Framebuffer format: RGBA32
Z buffer format: Z24.S8
But, also has a 16-bit mode:
RGB: RGB5A (A.R5.G5.B5)
Z: Z16 | Z12.S4
TKRA-GL is currently often using things in 16-bit mode with Z12, which
admittedly isn't great for Z-fighting (even my GLQuake port has some
significant Z fighting with this).
The Z16 mode basically requires the program to swear that it will
never enable stencil testing though.
A 4-bit stencil buffer is basically enough to handle things like
stencil shadows and similar; though stencil shadowing is slow on TKRA-
GL so not a good idea. 2-bit would have given less Z-fighting, but is
near useless for stencil effects.
An RGB555 color buffer though does impact the allowed blending
operations (pretty much nothing that uses DEST_ALPHA will work
correctly). But, then again, it is pretty much never used as such
(things like light-mapping typically using DEST_COLOr instead).
Or, one can use the 32-bit mode for higher visual fidelity, but in
this case it uses more memory and is slower (and the final output
stages still require a conversion to RGB555).
...
RGBCVT - convert between RGB formats: eg. RGBCVT r2,r1,10,8 converts
RGB8.8.8 to RGB10.10.10
BLEND - blend colors
TRANSFORM - transform point, performs matrix multiply for point
transformation using coefficients that may be set prior to calc.
I didn't go this far.
Would make sense if defining a shader-ASM language, but probably not
for a CPU.
so I want to put as much of the shader and other graphics into the CPU
as possible. Rather than arbitrate between an external shader the CPU.
Why have two sets of caches etc. when one set can offer the same performance?
Terje Mathisen <[email protected]> posted:If you have a log format sensor, then you can make do with a few less bits. Terje
MitchAlsup wrote:
Robert Finch <[email protected]> posted:
On 2026-10-19 5:46 p.m., BGB wrote:And then there are those of us who edit photographs and hate it when
On 10/18/2026 12:50 PM, MitchAlsup wrote:Figures. I use ARGB, putting the alpha in the MSBs.
Robert Finch <[email protected]> posted:
Adding some graphics instructions to Q+. While doing so, it seems to me >>>>>>> like 24-bit load and store operations to handle RGB888 data might be >>>>>>> handy.
A lot of GPUs use the other 8-bits as a mixing or transparency code. >>>>>>
Yeah, 32-bit RGBA (RGBA32 / RGB8888) is pretty much standard, differing >>>>> mostly as an unresolved fight over element ordering:
 "R, G, B, A" vs "B, G, R, A".
Most people cannot see color beyond RGB777 so 10.10.10 is overkill but I >>>> had worried about rounding of colors and figure a few extra bits would >>>> not hurt. ARGB3777 is 24-bit. Some of the very early display adapters
24-bit is mostly a weird/awkward thing that is sometimes used but mostly >>>>> not really worth it; vs just ignoring the last 8 bits in a 32-bit word >>>>> when alpha isn't needed.
Some 10.10.10 formats exist, but are rarely used, and usually overkill. >>>>>  3x E5.M5 does seem semi-popular here for HDR.
 3x E4.M4 also works, and allows treating it like RGBA32. >>>>>    And seems to match the look/behavior of HDR on a Radeon HD 4xxx.
 3x E4.M6: No one uses it but would give better fidelity. >>>>>
only supported 18 bits for color. So, ARGB6666 - fits nicely in 24 bits. >>>
a change to gamma results in posterization of the "sky" or any other
recognizable color with a small gradient. We also worry about gamut.
3x8-bit RGB is typically OK for finished photos, but for anything that's
going to be edited, you want a _lot_ more.
While 8-bits is sufficient for almost any viewing of an image
For editing::
10-bits is nowhere close to being enough
12-bits is pretty reasonable for gentle editing (old RAW circa 2005)
14-bits is very good for significant editing (new RAW circa 2015)
16-bits seems to be enough for all sensor types.
MitchAlsup wrote:
Terje Mathisen <[email protected]> posted:
MitchAlsup wrote:
Robert Finch <[email protected]> posted:
On 2026-10-19 5:46 p.m., BGB wrote:
On 10/18/2026 12:50 PM, MitchAlsup wrote:Figures. I use ARGB, putting the alpha in the MSBs.
Robert Finch <[email protected]> posted:
Adding some graphics instructions to Q+. While doing so, it
seems to me
like 24-bit load and store operations to handle RGB888 data
might be
handy.
A lot of GPUs use the other 8-bits as a mixing or transparency code. >>>>>>>
Yeah, 32-bit RGBA (RGBA32 / RGB8888) is pretty much standard,
differing
mostly as an unresolved fight over element ordering:
 "R, G, B, A" vs "B, G, R, A".
Most people cannot see color beyond RGB777 so 10.10.10 is overkill
24-bit is mostly a weird/awkward thing that is sometimes used but >>>>>> mostly
not really worth it; vs just ignoring the last 8 bits in a 32-bit >>>>>> word
when alpha isn't needed.
Some 10.10.10 formats exist, but are rarely used, and usually
overkill.
 3x E5.M5 does seem semi-popular here for HDR.
 3x E4.M4 also works, and allows treating it like RGBA32. >>>>>>    And seems to match the look/behavior of HDR on a
Radeon HD 4xxx.
 3x E4.M6: No one uses it but would give better fidelity. >>>>>>
but I
had worried about rounding of colors and figure a few extra bits would >>>>> not hurt. ARGB3777 is 24-bit. Some of the very early display adapters >>>>> only supported 18 bits for color. So, ARGB6666 - fits nicely in 24
bits.
And then there are those of us who edit photographs and hate it when
a change to gamma results in posterization of the "sky" or any other
recognizable color with a small gradient. We also worry about gamut.
3x8-bit RGB is typically OK for finished photos, but for anything that's >>> going to be edited, you want a _lot_ more.
While 8-bits is sufficient for almost any viewing of an image
For editing::
10-bits is nowhere close to being enough
12-bits is pretty reasonable for gentle editing (old RAW circa 2005)
14-bits is very good for significant editing (new RAW circa 2015)
16-bits seems to be enough for all sensor types.
If you have a log format sensor, then you can make do with a few less bits.
Terje
FWIW:
Pretty much all the cameras I have used have only offered T.81 JPEG as
the option for storage (though often with options to tweak image size
and quality, but not format).
High resolution, yes, but no options for RAW capture or similar.
I think this requires much more expensive cameras though.
FWIW:
Pretty much all the cameras I have used have only offered T.81 JPEG as
the option for storage (though often with options to tweak image size
and quality, but not format).
High resolution, yes, but no options for RAW capture or similar.
I think this requires much more expensive cameras though.
Though, an annoyance is that many I have used also need fairly bright lighting to avoid significant noise in the images (say, lighting levels
that seem fine in person giving a noisy mess on a camera, and the light level needs to be painfully bright before the image sensors give a clean image; or enable the use of a camera flash).
Well, or some cameras apparently internally take multiple images at different exposure levels and then combine them for better results.
Otherwise:
Something like E5.M7 would probably be pretty OK as a storage format, as
for the range of 0.5 to 1.0 would have basically the same accuracy as
8-bit LDR.
Could argue that something like Binary16 could make sense as a working format for HDR photo editing. Relatively few formats natively support
this though (excluding things like EXR).
Many of the other formats that claim HDR support do so instead by
storing a "tone mapped" image and an exponent image or similar (or, essentially, more like RGBE rather than by storing FP values directly).
Editing is also more of an issue as most normal editing software (say,
GIMP or Paint.NET or similar) don't really support much beyond normal
8-bit LDR.
...
Terje
BGB <[email protected]> posted:
--------------
FWIW:
Pretty much all the cameras I have used have only offered T.81 JPEG as
the option for storage (though often with options to tweak image size
and quality, but not format).
I have never owned a digital camera that did not allow RAW.
MitchAlsup wrote:
BGB <[email protected]> posted:
--------------
FWIW:
Pretty much all the cameras I have used have only offered T.81 JPEG as
the option for storage (though often with options to tweak image size
and quality, but not format).
I have never owned a digital camera that did not allow RAW.
Not even a cell phone camera?
Terje
MitchAlsup wrote:
BGB <[email protected]> posted:
--------------
FWIW:
Pretty much all the cameras I have used have only offered T.81 JPEG as
the option for storage (though often with options to tweak image size
and quality, but not format).
I have never owned a digital camera that did not allow RAW.
Not even a cell phone camera?
Terje
BGB <[email protected]> posted:[...]
--------------
FWIW:
Pretty much all the cameras I have used have only offered T.81 JPEG as
the option for storage (though often with options to tweak image size
and quality, but not format).
I have never owned a digital camera that did not allow RAW.
I have owned numerous film cameras (no bit depth or spatial array)
High resolution, yes, but no options for RAW capture or similar.
I think this requires much more expensive cameras though.
| Sysop: | DaiTengu |
|---|---|
| Location: | Appleton, WI |
| Users: | 1,142 |
| Nodes: | 10 (0 / 10) |
| Uptime: | 91:05:08 |
| Calls: | 14,704 |
| Calls today: | 2 |
| Files: | 186,497 |
| D/L today: |
1,890 files (562M bytes) |
| Messages: | 2,551,613 |