How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
johnsa
Member
Member
Posts: 321
Joined: Mon Oct 15, 2007 3:04 pm

Re: How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Post by johnsa »

Next discovery...
In the command streaming PRM ~pg. 49, there is a table defining what the context image should look like, which includes NOOPS, headers and register/value pairs.
The header words shown are actually opcodes, with what appears to be some undocumented opcode structure.

The table for example shows 0x1108_1019 which looks like a magic value but it's not.
This is the MI_LOAD_REG_IMMEDIATE instruction.

The opcode is 0x22 at bit 23, then there are two undocumented bits:
MMIO (bit 19)
POSTED (bit 12)
the low 8 bits is a formula for the number of reg/value pairs that follow and it's value is (2 * regCount - 1) & 0xff.

So the example in the PRM is saying load 25 register pairs.

I'm assuming the table is really just more of an example, and the registers your chose to load are up to you to some extent, with a typical example provided for GTT mode and PPGTT mode.
johnsa
Member
Member
Posts: 321
Joined: Mon Oct 15, 2007 3:04 pm

Re: How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Post by johnsa »

Next update..

I now have contexts swapping in and out and working!

As a bit of a brain dump, here is my current understanding of the "image" or LRC (logical ring context) that you setup (comprised of 1 4kb page of PPHWSP + 320 bytes of register writes as described at pg. 49 in prior post + engine state) is best thought of as a self-modifying Amiga style copperlist!

You create the image, with initial known-good register values, it looks like the GPU has some clever logic that latches those writes and knows where in memory the register write is in the LRC, a bit like a COPPER MOVE instruction. When work happens against the context, those register values are actually written back to the LRC and patched into those addresses where you built the initial write!

What this means is that reading an MMIO register like RINGBUFFER_TAIL isn't actually accurate once under a context / execlist, you actually want to get the "real" value by reading it back out of the offset in the LRC you initially built.

At least, that is what I'm seeing when looking at ringbuffer tail and head values, the LRC is being update.

To update the tail value to trigger new ring buffer commands to run, I first tried writing to the MMIO register RINGBUFFER_TAIL - which does nothing, you actually have to update it in the LRC and re-submit a new context. Assuming the context has the same Context SW ID and LRCA (logical ring context address - the GPU should pick this up as a "lite restore" - which is basically no flushing, no context swapping going on in the slow/traditional sense).

I have the ringbuffer and batch buffers running - the new problem is that ONLY MI_NOOP and MI_BATCH_BUFFER_START/END commands seem to complete - these result in the ring buffer head value being fully updated and the execlist stats reporting that it's gone idle again.

As soon as I try to run any sort of MI_FLUSH or BLT command it silently fails and looks like the Command Streamer has died. The execlist status remains active and the HEAD is stuck at it's original position.

I have various avenues of suspicion as to why this might be, the first was that you MUST configure MOCS and L3CC tables on the GPU before using any operation/command that works with memory. I've now done this - and again, these tables and configurations vary per generation/sku - so you need to build them up and program them according to the exact GPU you have - bearing in mind once again that the discrete GPUs need MCR and register steering.

Even with MOCS+L3CC done, the result is the same - so my next theory is that you can't actually do anything with the GT/Render domains on the GPU without loading the HuC/GuC (graphics microcode) firmware :( - these require the firmware blobs, and loading/configuring them into write once protected memory + init/handshakes etc.

And this where the rabbit hole is at....
johnsa
Member
Member
Posts: 321
Joined: Mon Oct 15, 2007 3:04 pm

Re: How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Post by johnsa »

Success! - I have a blue rectangle on screen created courtesy of XY_FAST_COLOR_BLT :)

The MoCs and L3CC setup is essential, otherwise flushes and cache coherence simply don't work at all.

The PRM description of the XY_FAST_COLOR_BLT is wrong, the MoCs bits must be << 22, not << 21 as per older generations (if you're on XE+).
Depending on how the MoCs are setup - and the standard for UC type is value 3, so you'd put (3 << 22) into the BLT command.

Once you get the BLT to actually run - and you need the ring buffer AND batch buffers to make it so, you still won't see anything on the screen...

This is due to a very complex interplay between the framebuffer in GGTT, CPU ownership semantics if you do S/W rendering to it via UC or WC memory type and the fact that the BLT writes into GPU LLC (last level cache). You need some form of ordering/memory barrier sync point to ensure the Display Engine actually sees the changes in the framebuffer written by the BLT and updates what it scan-outs. You can verify this by reading back a pixel from the framebuffer after the BLT - and you'll get the correct BLTed value - but nothing on screen will actually change. It's all cache-coherence.
http://www.terraspace.co.uk/os.jpg
User avatar
bellezzasolo
Member
Member
Posts: 163
Joined: Sun Feb 20, 2011 2:01 pm

Re: How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Post by bellezzasolo »

johnsa wrote: Tue Dec 16, 2025 10:50 am Success! - I have a blue rectangle on screen created courtesy of XY_FAST_COLOR_BLT :)

The MoCs and L3CC setup is essential, otherwise flushes and cache coherence simply don't work at all.

The PRM description of the XY_FAST_COLOR_BLT is wrong, the MoCs bits must be << 22, not << 21 as per older generations (if you're on XE+).
Depending on how the MoCs are setup - and the standard for UC type is value 3, so you'd put (3 << 22) into the BLT command.

Once you get the BLT to actually run - and you need the ring buffer AND batch buffers to make it so, you still won't see anything on the screen...

This is due to a very complex interplay between the framebuffer in GGTT, CPU ownership semantics if you do S/W rendering to it via UC or WC memory type and the fact that the BLT writes into GPU LLC (last level cache). You need some form of ordering/memory barrier sync point to ensure the Display Engine actually sees the changes in the framebuffer written by the BLT and updates what it scan-outs. You can verify this by reading back a pixel from the framebuffer after the BLT - and you'll get the correct BLTed value - but nothing on screen will actually change. It's all cache-coherence.
http://www.terraspace.co.uk/os.jpg
Hmm, that definitely brings to mind DirectX 12!
https://learn.microsoft.com/en-us/windo ... rce_states

Not that it has display output pipes as an option, but I wouldn't be surprised if that's one of those internal states under the hood.
Whoever said you can't do OS development on Windows?
https://github.com/ChaiSoft/ChaiOS
CasualKyle
Posts: 12
Joined: Fri Oct 24, 2025 2:38 pm

Re: How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Post by CasualKyle »

Amazing work!
RyanK
Posts: 2
Joined: Tue Feb 18, 2025 11:18 pm
GitHub: https://github.com/KdotDevelopment
Contact:

Re: How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Post by RyanK »

Hi, I hate to hijack this post, but I was wondering if anyone here has any experience with the HDMI display enable sequence on integrated intel gpus? This is currently where I am stuck. I have pulled EDID data, enabled the power wells, calculated P0, P1, P2 values for DPLL and set up all the plane/transcoder registers all according to chapter 12 of the PRM. My display, however, will immediately say it has no signal and go into power saving mode after I flip off the VGA_CONTROL enable bit to turn off the GOP graphics and the monitor never comes back to life. I should mention that this isn't a laptop, its just a normal desktop with an i5 7500 cpu and a reliable serial output. I'm assuming at this point in the process the lcd backlight should stick on, at least. I can provide code if anyone's interested in helping.

Thanks!
sounds
Member
Member
Posts: 136
Joined: Sat Feb 04, 2012 5:03 pm

Re: How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Post by sounds »

I'm interested in what you're doing but my testbed with Intel Integrated graphics wouldn't help you figure out how to do the HDMI sequencing.

If you share code, someone might come along who knows. You can try blindly emailing someone from the mesa-devel mailing list and see if they have more info.
johnsa
Member
Member
Posts: 321
Joined: Mon Oct 15, 2007 3:04 pm

Re: How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Post by johnsa »

I have display enable and mode setting working on HDMI and DisplayPort, 2xpipes with planes and cursors on my AlderLake Gen12 XE iGPU.

There is a lot more to the process than meets the eye or what the PRMs talk about, some of the register offsets are plain wrong, they vary per generation, the order of operations is touchy.

I assume you have the GGTT configured and framebuffer mapped in?
(I think you also need to do some device level config before anything else, like MoCs and L3CC, there is also SAGV config, DDBs, Watermarks, steering and MCR, DDI/PHY configuration, for HDMI specifically you also need to send out AVI DIP packets.

For the clock calculations, you also need to read the MAILBOXES to get the correct ref clock and memory latency timings.
You also need the CDCLK, init ABOX/MBOX and DBUF power.

I had HDMI "no signal" pretty much right up until the end when everything was done, it wasn't an incremental process :(

If you're actively working on this, I'm happy to share my code/learning - for the sake of all humanity being able to actually initialize a damn GPU as display device lol.
RyanK
Posts: 2
Joined: Tue Feb 18, 2025 11:18 pm
GitHub: https://github.com/KdotDevelopment
Contact:

Re: How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Post by RyanK »

Thanks for the responses. Here is the github link: https://github.com/KdotDevelopment/c-ry ... l_hd_630.c (The code is far from clean but I commented the hell out of the gpu part)

I don't have the GGTT set up yet, I figured I'd get the display to stay on before I try plotting pixels. I never read the mailboxes but I did write the values to them (lines 580-582 in github) that I found in the PRM for CDCLK. I missed the MoCs, L3CC, SAGV, DDBs, Watermarks etc but I did get DDI/PHY configuration (line 340, called at 607) and also enabled AVI DIP packets (line 652), although I haven't manually sent anything over AVI.

I went through the steps to do the CDCLK (line 555) and I cannot find any references to ABOX or MBOX in the manuals (at least for KBL gen 9.5). The DBUF power thing was a little complicated but the PRM gave example values to use if you haven't done anything else, so I just used that. I'm vaguely familiar with needing to "train" these voltage values?

So basically it looks like I've done about half the work, because I was unaware of the other half :shock: . Actually, it looks like the other half is easier than the first, assuming I actually did everything correct so far.

Also, the serial data I printed out in my latest run can be found here: https://rkoc.net/gpu/serial_output_2_5_26.txt I can't guarantee this will stay up for too long, if you're reading this post 2 years from now....
sounds
Member
Member
Posts: 136
Joined: Sat Feb 04, 2012 5:03 pm

Re: How to draw graphics to a high resolution and high refresh rate monitor with vsync?

Post by sounds »

Posting a follow up.

@johnsa, it looks like https://github.com/Terraspace is your github profile (based on https://github.com/Terraspace/UASM linking to the same domain http://www.terraspace.co.uk/uasm.html ). I've included a screenshot you posted:
terraspace-os-resized.jpg
No source code, but there is some description of what steps you took in the screenshot.

@RyanK posted c-ryanos' Intel HD 630 driver here and the log output, but his display says "No Signal" still:

Code: Select all

=-=-= EDID INFO =-=-=
 number_extensions: 1
 video_input: 0x00000080
 max_horizontal_size: 60cm
 max_vertical_size: 33cm
 DPMS_flags: 0x0000002A
detailed_timing_desc_1
 pixel_clock: 24170 * 10kHz
 h_active_time: 0
 h_blank_time: 160
 h_active_blanking: 160
 v_active_time: 160
 v_blank_time: 41
 v_active_blanking: 80
 h_size: 86mm
 v_size: 80mm


0x00000080 0x00000000 0x00000000 0x00000000 0x00000000 0x000000FF 0x000000FF 0x000000FF
0x000000FF 0x000000FF 0x000000FF 0x00000000 0x0000004E 0x00000014 0x000000B9 0x0000000A
0x00000000 0x00000000 0x00000000 0x00000000 0x00000033 0x0000001E 0x00000001 0x00000003
0x00000080 0x0000003C 0x00000021 0x00000078 0x0000002A 0x000000AA 0x000000B5 0x000000A6
0x00000055 0x0000004D 0x000000A0 0x00000023 0x0000000C 0x00000050 0x00000054 0x000000A5
0x000000CB 0x00000000 0x00000081 0x000000C0 0x00000081 0x00000080 0x00000095 0x00000000
0x000000A9 0x000000C0 0x000000B3 0x00000000 0x000000D1 0x000000C0 0x00000001 0x00000001
0x00000001 0x00000001 0x0000006A 0x0000005E 0x00000000 0x000000A0 0x000000A0 0x000000A0
0x00000029 0x00000050 0x00000030 0x00000020 0x00000035 0x00000000 0x00000056 0x00000050
0x00000021 0x00000000 0x00000000 0x0000001A 0x00000000 0x00000000 0x00000000 0x000000FD
0x00000000 0x00000030 0x00000090 0x0000001E 0x000000F0 0x0000003C 0x00000001 0x0000000A
0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000020 0x00000000 0x00000000
0x00000000 0x000000FC 0x00000000 0x00000053 0x00000063 0x00000065 0x00000070 0x00000074
0x00000072 0x00000065 0x00000020 0x00000059 0x00000032 0x00000037 0x0000000A 0x00000020
0x00000000 0x00000000 0x00000000 0x000000FF 0x00000000 0x00000030 0x00000030 0x00000030
0x00000030 0x00000030 0x00000030 0x00000030 0x00000030 0x00000030 0x00000030 0x00000030

h_active: 2560
h_blank: 160
h_total: 2720
h_active: 1440
v_blank: 41
v_total: 1481

DDI_BUF_CTL (before): 0x80000000
pixel clock: 24170
target symbol freq: 241
dco freq: 9640
central freq: 9600
afe clock: 241
P0: 2
P1: 10
P2: 2
DPLL_CFGCR1: 0x80AAAB91
DCO Integer: 401
DCO Fraction: 21845
DPLL_CFGCR2: 0x000008A4
DPLL_STATUS: 0x00001111
DC_STATE_EN: 0x00000000

End of sequence.

AHCI Controller found
The update from me is that I am attempting to get my hands on a Macbook Pro 2019 which uses an Intel chip with the Intel HD 630 graphics.
Post Reply