Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GSdx-hw TC: improve search/invalidate tex in RT #3018

Merged
merged 4 commits into from
Aug 14, 2019

Conversation

iMineLink
Copy link
Contributor

@iMineLink iMineLink commented Jul 13, 2019

Fixes eyes rendering in Jak games both ingame and in cutscenes.
Previous method yielded no eyes in Jak 2/3/X cutscenes and no eyes invalidation in any Jak game (i.e. no blinking).

  • Keep track of Target TBP0 in Source built from Target
  • Invalidate Source using also from Target TBP0 information
  • Generalized offset search logic with caching system (works for BW > 1 and any PSM, limited to PSMCT32 for now)
  • CRC Flags mechanism for default behavior enabling in Jak games

https://www.youtube.com/watch?v=lXlOzzE7Qhw

Various:

  • Fix texture end block computation around the code, using the block of the bottom right texel as last valid block
  • Fix Target::Inside method which is now inclusive both on start and end blocks

Improve issue #168

Detailed explanation how the rendering is done:

So, the fix was achieved by working on two aspects of GS emulation in the GSdx plugin:

1) Palette related issues, which caused, for example, wrong Jak skin colors

Jak 2/3/X game uses a lot of sprite rendering to draw palettes.

In GSdx those renderings were emulated the hard way on GPU: setup scene and draw with shaders.

GSdx keeps a texture cache (both of input textures and framebuffer), with lightweight objects representing the framebuffer, called Target, that do not contain actual texture data, as reading back from GPU memory to CPU memory after each draw would be too slow.

Those rendered palettes (referred by Target objects in GSdx TC) are later used by the games for coloring skin (e.g. Jak 2/3) or generic scene elements (such as lights and screens in Jak X).

This means that at some point, the previously rendered framebuffer must be used as an input texture: GSdx TC currently needs to retrieve the correct Target object, read back its data from GPU to CPU, to provide input data for a new texture (called Source).

This operation is tremendously slow (for reading back data, every GPU/driver pipeline should be flushed), and pollutes the texture cache with many Target and Source objects.

GSdx TC is not perfect, but pretty efficient, still it failed in emulating the sprite rendering and readback correctly.

So, we decided, to write a reusable and fast CPU sprite renderer instead of focusing too much on achieving perfect TC: right now the CPU sprite renderer draws 2 pixels at a time using SSE acceleration and is pretty faster than rendering and reading back from GPU to CPU (some benchmarks shown up to 30% more FPS) and does not pollute the TC.

We plan on extending the usage of the CPU sprite render to other games (DBZ:BT2 has already shown benefits when using it), but right now it is limited to Jak 2/3/X games, where we are more confident about its benefits and we have tested the functionality.This fixed the colors issues.

​

2) Reading back from previously rendered framebuffer with generic <x,y> offset, and correctly discard copied textures as original framebuffer is updated, which solved eyes issues (black eyes and missing eyelids closing).

Eyes issues were present in all Jak games.

The rendering and usage pattern was the following for eyes:

The game drawn in a single framebuffer (at a given address) all the eyes for the characters in the scene, with given offsets one from each other, rendering pupils and eyelids dinamically.
Later on, the game read back from the single rendered framebuffer, at an address different for each eye (the offset is not explicit anymore), all the eyes for the characters in the scene, and rendered them into the correct place.
GSdx was correctly recycling the texture referred by the eye drawings because all the draws occurred with the same base address, so the correct Target object was retrieved for each eye.

So, at the end of the first point, on GPU memory we had the full texture with all the eyes dynamically rendered correctly.

Then, the game wanted to read back from the Target the drawn data.

At this point, we have an input address for reading the eye that coincide with the Target one only when the offset is <0,0>, so usually the first eye of the first character in the scene (which was correctly drawn even before the fix).

For the other eyes, for example an eye starting at <64,0>, GS wants to read from an address that is not anymore the same of the Target: it could be decomposed though, the new address, into a base address plus an offset.

There was already some code that tried to decompose the input address in base address plus offset, to correctly find the Target texture (which should have the same base address), but it was not generic enough and hit some bugs: we improved it by fixing the bugs and generalizing the code and this fixed eye rendering it in Jak 2/3 cutscenes; This code path as been enabled only for Jak games even if the code is generic, as it is the only game that shown such rendering behaviour.

Remember that when we reuse a framebuffer as input texture, we create and cache Source objects containing the readback data.

So now we fixed black eyes: still, the eyelids are not closing, as, each time we find a match from the Target texture plus an offset, we create the Source object containing the eye data and that is stored in the cache, but never invalidated, as invalidation was done only detecting draws at the base address.

By saving the base address of the original Target texture (containing all the eyes and dynamically rendered) in the eye Source texture (the addresses do not coincide), and invalidating from cache the Source when the original Target at the different address is drawn, we could fix also eyelids closing, as when a given eye is drawn again into the framebuffer, the Source containing the copy of the eye is invalidated and removed from TC, so the new copy is created when needed with updated data.

- compute bottom right texel block as last valid block
- inclusion shall not be strict only on start side
@iMineLink iMineLink force-pushed the fix-jak-games-eyes branch 2 times, most recently from 64a1738 to 1a026ee Compare August 11, 2019 12:43
Fixes eyes blinking in Jak games with tex in rt search
enabled.

- Target TEX0 in Source is Source TEX0 if the Source is
not build from Target, otherwise it is the Target TEX0,
allowing improved Source invalidation
Fixes eyes rendering in Jak games both ingame and in cutscenes.
Previous method yielded no eyes in Jak 2/3/X cutscenes.

- Generalized offset search logic with caching system (works for BW > 1
and any PSM, limited to PSMCT32 for now)
- CRC Flags mechanism for default behavior enabling in Jak games
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants