ps2dev / gsKit

gsKit is a C interface to the PS2 Graphics Synthesizer
Other
107 stars 28 forks source link

FullHD background, screen positioning and fixes #12

Closed rickgaiser closed 7 years ago

rickgaiser commented 7 years ago

After the first OPL test builds multiple users have reported the screen positioning for 720p and 1080i is off by a lot. So in this pull-request I am again requesting to change the screen positioning for these two modes.

Also in this pull-request:

sp193 commented 7 years ago

I am having this feeling that the GS HSINT interrupt is working as it was supposed to be, but the GS documentation just didn't clearly document how to clear the interrupt condition on the GS. Perhaps it is a technical oversight because the chapter on "signal" seems to have been marked as a new addition (there's the vertical line along most of it, which indicates new changes).

Personally, I didn't get the GS interrupt to continuously assert if I re-enabled HSINT within IMR again after invoking EnableIntc. It doesn't make sense to me anyway.

If you examined the documentation for the SIGNAL cause, it states that "The interrupt state is cleared when the SIGNAL flag of the CSR register is cleared". The documentation for when 1 is written to the the SIGNAL bit within CSR is also unusual, compared to the other bits: "Old event is cleared and event is enabled".

According to this clause within the chapter titled "Outline on Signal Processing" that states "The GS can generate a signal (an interrupt) to the host", it is possible that the title of the chapter "signal" actually refers interrupt processing. After all, the signal event is only one of the three possible signal events (and one out of the five documented GS interrupt causes).

With DSEDB, I didn't get the GS interrupt going again by one write to GS IMR that enabled HSINT. I also needed to write to the SIGNAL (1) and HSYNC (4) bits within the CSR, within the GS interrupt handler. If this isn't done, then the interrupt isn't observed occurring again (according to the EE I_STAT register). I have tried making a single write to CSR by writing a 5 to it, and it works the same as writing a 1 before a 4. Writing only either a 1 or 4 to CSR does not work.

It also states that if the SIGNAL interrupt occurs again before the interrupt condition is cleared, then writing to the SIGNAL bit within the CSR will not clear the interrupt state. Instead, the SIGNAL event must be masked and unmasked with IMR, before that event will continue working. And indeed, we're probably also doing this (hence your additional call to GsPutIMR after EnableIntc), but for HSINT instead. I've tested that only HSINT must be re-unmasked for things to work.

This may be why SONY's libgraph actually masks all interrupts (0xFF00 is written to IMR) before the GS is reset. If that is so, then perhaps we should do the same for gsKit, and only unmask HSINT/VSINT when required (after EnableIntc). IMR is write-only, but we can use GsGetIMR to avoid masking/unmasking other events. The developer will have to clear the SIGNAL event and to re-enable the HSync event within the CSR from the interrupt handler as well.

sp193 commented 7 years ago

By the way, if you're reading my post from your e-mail inbox, I hope that you will log into Github to read the latest "edition" of my reply. I edited it a few times for clarity, but I do not know what version is sent via e-mail. :(

rickgaiser commented 7 years ago

I think you are confused about what the "signal registers" do. There are three "signal registers" you can use to "signal" your own application. By writing to any of these three registers (from the command stream you dma-transmit to the GS) you can:

But the SIGNAL and FINISH registers have nothing to do with the HSYNC and VSYNC interrupt. After unmasking the VSYNC/HSYNC interrupts in IMR, the interrupts should start firing. After each interrupt/event, CSR must be written so "Old event is cleared and event is enabled". This is what I'm doing (in gsHires.c):

static int hsync_callback()
{
    if (*GS_CSR & (1<<2)) {
        *GS_CSR = (1<<2);
        hsync_count++;
    }

    //...

    ExitHandler();
    return 0;
}

This works for all video modes on my SCPH-90006, and it also works on my SCPH-50004 except for 720p and 1080i.

I think it's a bug (possibly in SetGsCrt). Perhaps it's masking the interrupts again in IMR? Becouse unmasking the interrupts again fixes the problem. This somehow only affects the HD modes, and is somehow fixed in later models. After unmaking the interrupts again, but only once, the interrupts start firing and everything starts to work as before.

It's probably better to:

But I was only interested in a fix for this one problem, and not rewrite the way interrupts are handled in gsKit.


What do you think about the other commits?

sp193 commented 7 years ago

No, I am not confused. I mentioned SIGNAL because there is no documentation on how to handle HSINT. On my SCPH-39006, the INTC_GS interrupt does not seem to continuously trigger, even in NTSC mode. It only started to work, when I did what I wrote I did. Unless I did something wrong, which can happen after hours of trying to understand why you had to do what you did.

I'm pretty sure that IMR is not getting masked again. I disassembled the code for SetGsCrt five years ago, but I don't remember seeing IMR being changed. Anyway, even if it's being masked, it didn't work immediately after I re-enabled HSINT.

I wasn't suggesting that you change how interrupts are handled within gsKit. It's about how the interrupt is serviced (as you have done) and unmasking the interrupt when required (as you have also suggested).


I'm fine with your other commits.

sp193 commented 7 years ago

Okay, so I switched the console back on and it seems like it's now working as you wrote. For the HD modes, GsPutIMR has to be issued again.

There's no need to involve the signal bit, I guess. If there's anything I gained from this, it's how to service the GS interrupt events. Thanks for confirming the findings that should be valid.


And now it seems like GsPutIMR doesn't have to be issued multiple times. :| So I guess this behaviour depends on the previous hardware state.

sp193 commented 7 years ago

I think I may have found something. :O The issue occurs when you write 0x7300 to the IMR. My older tests were using 0xF000, which also gave the same (or just similar) issue. Enabling only HSINT didn't cause the stall.

If 0x7300 is written (HSINT and VSINT enabled), then writing (when servicing the interrupt) to HSync and VSync of the CSR causes things to work. BTW, the GS documentation states that 1 should be written to undefined bits, to perhaps 0xF300 should be used instead (to fill in 1s for the * bits)?

Jay-Jay-OPL commented 7 years ago

@rickgaiser

I tried your new test found here: http://psx-scene.com/forums/f19/high-resolution-3d-rendering-156426/index4.html#post1214696

It doesn't seem to display the (1920x1080) background image I chose from my folder. I did rename the jpg file like you instruct there.

fhdbg.jpg

I load it from:

mass:/TEST/gsKit_hires_1080i_v2/gsKit_hires_1080i_v2.elf

Here is the zip I am sharing with at PS2-HOME so the members there could conduct the test -- it has the same image I'm having an issue with as well: http://www.ps2-home.com/forum/viewtopic.php?p=19463#p19463

rickgaiser commented 7 years ago

Please keep the discussion/questions about the demo at psx-scene. Short answer: The example loads "host:fhdbg.jpg".


If 0x7300 is written (HSINT and VSINT enabled), then writing (when servicing the interrupt) to HSync and VSync of the CSR causes things to work.

Isn't that exactly what I'm doing? I've also tried writing to HSync and VSync of the CSR when adding the handler, but it doesn't work for the two modes on the older model, only unmasking the interrupt again seems to work.

BTW, the GS documentation states that 1 should be written to undefined bits, to perhaps 0xF300 should be used instead (to fill in 1s for the * bits)?

Those are bits 13 and 14 (not 15 in the documentation I have), so they should already be set to 1 (0x6000), masking everything plus these two bits would be 0x7F00. Enabling only VSYNC and HSYNC is then 0x7300.

I can change the code to only unmask VSYNC in the init call (as it used to be), and then unmask/mask HSYNC when the handler is added/removed. Would this be a good solution?

sp193 commented 7 years ago

Isn't that exactly what I'm doing? I've also tried writing to HSync and VSync of the CSR when adding the handler, but it doesn't work for the two modes on the older model, only unmasking the interrupt again seems to work.

If you mean your sample code that you posted above, I can see that you're only re-enabling HSync, but not VSync (you're writing to only bit 2).

I can change the code to only unmask VSYNC in the init call (as it used to be), and then unmask/mask HSYNC when the handler is added/removed. Would this be a good solution?

I would recommend that we do two things:

  1. Confirm whether you're actually acknowledging all unmasked interrupts. Then we can also document this undocumented behaviour (whereby failure to acknowledge an unmasked interrupt can cause further interrupt assertions to not work) within gsKit.
  2. Mask all interrupts as in the SCE libgraph, and only unmask when an INTC handler is registered and the interrupt is unmasked. This is assuming that what I observed is true for all PlayStation 2 models. It doesn't sound like a good idea to keep unhandled interrupt causes unmasked if the problem is caused by the VSync interrupt not being handled by the reset, although it sounds like what you are doing does work. What do you think about this?

If (2) should probably go into another commit since gsKit was originally designed like that, it's fine as well. I can make my own commit.

Regarding the undefined bits: oh okay. Yeah, then 0x7300 is fine if we just followed the documentation. I was confused by what SCE wrote, which is 0xFF00. Thanks.

Jay-Jay-OPL commented 7 years ago

@rickgaiser -- I'm not sure if you know this, but myself and other members can't login at psx-scene. It's been a problem for months -- sadly, the site is poorly managed and pretty much imploding.

Heck! I even have moderator privileges at psx-scene and even still with those privileges I can't login sometimes. It's very odd when I can, or if by luck I can login, when I try to post something -- I get logged out. :(

So if I try to keep the discussion elsewhere, is because that's an alternative place where we can have a discussion or provide feedback about it.

Please clarify, does the jpg file load from the root where the elf file is (if placed inside a subfolder)? Or does it load from the root of the device?

rickgaiser commented 7 years ago

I'm not sure if you know this, but myself and other members can't login at psx-scene. It's been a problem for months

I had the same problem, try checking the "remember me" box. It worked for me and others.

Please clarify, does the jpg file load from the root where the elf file is (if placed inside a subfolder)? Or does it load from the root of the device?

"host:" is the prefix used when loading from ps2link/ps2client. Load the file using ps2client, and have the jpeg in the same folder.

rickgaiser commented 7 years ago

1 Confirm whether you're actually acknowledging all unmasked interrupts. Then we can also document this undocumented behaviour (whereby failure to acknowledge an unmasked interrupt can cause further interrupt assertions to not work) within gsKit. 2 Mask all interrupts as in the SCE libgraph, and only unmask when an INTC handler is registered and the interrupt is unmasked. This is assuming that what I observed is true for all PlayStation 2 models.

Will try this and push the changes if it works. Thank you.

Jay-Jay-OPL commented 7 years ago

I had the same problem, try checking the "remember me" box. It worked for me and others.

If only it was that simple. But I'm afraid it doesn't help. I've already gone full circle with the forum admins about this issue, they simply can't figure it out.

I see my error now. I was trying to load it from mass, not from ps2client. Damn! Haven't had to use ps2client for years! lol

How come it's set up that way? Why the need for ps2client? Just wondering?

I'll make sure to pass on that info to the others... :)

rickgaiser commented 7 years ago

How come it's set up that way? Why the need for ps2client? Just wondering?

ps2client gives a much faster development cycle. I type "make reset test", and I get to see the latest changes I made to the gsKit example. I use it for OPL development also. By default when I reboot my ps2 it boots up ps2link.

It's too bad the path always has to be prefixed with the driver you want to use, even when using a local path :( @sp193 is this something that can be fixed or improved?:

sp193 commented 7 years ago

Rightfully, development of PlayStation 2 software is done over the network anyway.

We cannot change the way that modules are loaded because it (i.e. LoadModule) is part of the IOP kernel. We can change the EE RPC function, but this design keeps things simple and compliant with the documentation. If you want to make things robust anyway, you can get the CWD with getcwd and use it to generate the full path to your modules.

rickgaiser commented 7 years ago

55c4478 should fix the problem.

sp193 commented 7 years ago

So did you get the HSync interrupt event to work by acknowledging VSync?

rickgaiser commented 7 years ago

No, I got the HSync interrupt event working (in 55c4478) by unmasking the interrupt (in IMR) when adding the handler, instead of during init. I already tried acknowledging VSync without effect.


I see now that I accidentally added the texture manager (860fec6) that I was working on when rebasing the commits, oops! You've also merged it.

It's been tested only a little and I wasn't done with it, but it should not give any problems in existing applications. I was hoping to get feedback before doing a pull-request, but I guess that's too late now.

The texture manager uses all the VRAM that's left as a texture cache. It will use free space if possible, and when there is no free space it will try to be as clever as possible in removing another texture from the cache (VRAM). For instance, if a texture has not been used in this frame and the previous frame, then it's probably no longer needed. The code is as simple as possible, so you can take a look there to see how decisions are made.

I've been testing with the texture allocation used by Quake1 GL (not the game itself, just a text-file with all the texture loading/binding and frame swapping). The output demonstrates what can be expected of the texture manager and looks like this:

Video Memory Manager Test
Framebuffer: 704x480x32bpp = 1320KiB (2x)
Z-buffer:    704x480x16bpp = 660KiB
Textures:    796KiB
Cache hit percentage per frame:
 35% 100% 100%  91% 100% 100% 100% 100% 100% 100% 100% 100%  51%  52%  63% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  88% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  67%  45%  94%  64%  79%  89%  93%  93%  93%  93%  93%  93%  91%  93%  95%  95%  95%  95%  94%  96%  93%  96% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  85% 100%  94%  98% 100% 100% 100%  99% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  97% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  89%  94%  86%  76%  84%  94%  91%  97%  96%  97% 100% 100% 100%  99% 100% 100%  85%  99% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  97% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  96% 100%  77%  93% 100% 100% 100%  99% 100% 100% 100% 100%  93%  98%  91% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  89%  95% 100% 100%  63% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  99% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  99% 100% 100% 100% 100% 100% 100% 100% 100% 100%  78% 100% 100% 100% 100% 100% 100% 100% 100%  83%  79% 100% 100% 100% 100% 100% 100% 100%  97% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  80% 100%  92%  94%  81%  69%  77%  54%  76%  76%  90%  96% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  91% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  82%  92% 100% 100% 100% 100% 100% 100%  98% 100% 100% 100% 100%  85%  90%  85%  65%  68%  79%  86%  89%  89%  89%  90%  91%  91%  90%  91%  91%  91%  88%  88% 100%  88% 100% 100% 100% 100%  87%  65%  80%  95% 100% 100% 100% 100% 100%  86% 100% 100% 100% 100% 100%  96% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  97%  97% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  97% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  74%  60%  50%  65%  70%  69%  69%  67%  64%  88% 100% 100% 100% 100% 100% 100% 100% 100%  80%  79%  61%  52%  83% 100% 100% 100% 100% 100%  86% 100% 100%  96% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  93%  86%  98% 100% 100% 100%  96%  88%  69%  77%  91%  93%  81%  95%  80%  96% 100% 100% 100% 100%  91%  98% 100% 100% 100% 100%  96% 100% 100% 100% 100% 100% 100%  74%  61%  74%  91%  97%  94%  94%  97%  99%  91%  90%  91%  92%  92%  91%  92% 100% 100% 100%  93%  90%  90%  90%  93% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  89%  90%  62%  77%  95% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  64%  66%  74%  84% 100%  91%  66%  99%  98%  99%  95%  97% 100% 100% 100% 100% 100% 100% 100%  96%  85% 100% 100% 100% 100% 100%  68%  72%  84%  97% 100% 100% 100% 100% 100%  99%  98%  96%  96%  97% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100% 100%  98%  99% 100% 100% 100% 100% 
 - Total texture size:   3680KiB
 - Total texture usage:   483MiB ( 775KiB / frame)
 - Total send size:        29MiB
 - Cache hit percentage:   95%

As you can see, Quake1 uses 3680KiB of textures for these frames, and there is only 796KiB of VRAM space. The total number of "bind" calls accumulates to 483MiB of textures used. But using the texture manager only 29MiB of textures needs to be transferred to VRAM.

I hope you like the work. If there is anything I need to change or if you want to revert this commit please let me know.

sp193 commented 7 years ago

Thanks for trying out my suggestion and for bringing up this issue in the first place.


I am personally happy with your work on gsKit, so long as it is furthers the cause of PlayStation 2 development. Thank you for showing us new things, particularly new tricks that we don't usually see in action everyday.

If it's necessary, I can also rewrite history to undo the merging of the said commit. Otherwise, we can just leave it be until an issue is found.

sp193 commented 6 years ago

Sorry for digging this up again, but what exactly was the fault? Did HSINT assert only once, and never again? If so, maybe we've encountered a documented EE-GS restriction, whereby the EE may fail to receive further interrupt signals, depending on the description of the interrupt handler. It would fail, if the EE was servicing the interrupt handler, while additional interrupts occur from the GS. The Sony-recommended workaround is to mask the interrupt during the duration of the interrupt handler code.

Just adding on, since I don't think we got a really satisfying answer to why this problem occurs.

rickgaiser commented 6 years ago

Only on older ps2 models and only 720p and 1080i mode did not assert HSINT. I'm not sure if it did fire once or not, but I suspect it didn't fire at all.

I suspect it's a bug in older versions of SetGsCrt. Since unmasking the IMR flag a little later (after SetGsCrt), but still only once, fixed the problem. Here: 55c4478b012b87401914b78730d09ab6d3706001