mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2025-01-19 07:17:23 +01:00
Add dev doc about IIDX's rendering loops for up-/downscaling feature
This commit is contained in:
parent
29526e02ec
commit
79495ea687
88
doc/dev/iidx-gfx-rendering-loops.md
Normal file
88
doc/dev/iidx-gfx-rendering-loops.md
Normal file
@ -0,0 +1,88 @@
|
||||
# Notes outlining some aspects of the DirectX calls which were required to know to implement a up-/downscaling feature
|
||||
As the title says, this outlines some aspects I needed to figure out in order to implement a up-/downscaling feature
|
||||
within the d3d9 hook module that works on all currently available IIDX versions (9 to 26).
|
||||
|
||||
To analyze the rendering loops, I have used a tool called apitrace which traces the calls of many graphic APIs:
|
||||
https://github.com/apitrace/apitrace
|
||||
|
||||
Defintely recommended to quickly figure out what is going on regarding rendering. It also allows you to let you render
|
||||
parts of a scene after the application exited because it records all API calls and data passed to them.
|
||||
|
||||
Anyway, considering the various iterations in (GPU) hardware the game had to undergo combined with weird quirks and
|
||||
"fixes" Bemanitools is undoing, I wouldn't have guessed that their rendering engine was nearly the same until IIDX 20.
|
||||
That's when they introduced SD/HD mode.
|
||||
|
||||
In this case, that's great news because I had to craft a solution that allows up-/downscaling the final frame to
|
||||
different resolutions (see the iidxhook-util/d3d9 module for more details about the feature).
|
||||
|
||||
But first, we need a breakdown of the render loop's most relevant parts for this:
|
||||
|
||||
## IIDX pre 20
|
||||
Using apitrace, we can see the following outline of a frame (not counting the first one that does a lot of setup in
|
||||
the beginning):
|
||||
```
|
||||
BeginScene
|
||||
Clear
|
||||
...
|
||||
// Here are the main draw calls for the scene rendering to the back buffer
|
||||
EndScene
|
||||
Present
|
||||
```
|
||||
|
||||
No render target switching, simply render everything to the back buffer...plain and simple.
|
||||
|
||||
Note: The viewport size is determined by the size returned by GetClientRect, wtf.
|
||||
Welp, no official Konmai seal of approval without that. ¯\_(ツ)_/¯
|
||||
|
||||
## IIDX 20+
|
||||
Using apitrace, we can see the following outline of a frame (not counting the first one that does a lot of setup in
|
||||
the beginning):
|
||||
```
|
||||
BeginScene
|
||||
// tex1 is a render target texture with size 1280x720 (also in SD mode)
|
||||
// The game will render to this intermediate target and not directly to the fram ebuffer
|
||||
SetRenderTarget(0, tex1)
|
||||
...
|
||||
Clear
|
||||
BeginScene -> ErrInvalidCall return code
|
||||
Clear
|
||||
...
|
||||
// Here are the main draw calls for the scene rendering to tex1
|
||||
...
|
||||
// Sets the render target to the original frame buffer. The size of the framebuffer is set to the output mode
|
||||
// resolution, e.g. 1280x720 for HD mode and 640x480 for SD mode
|
||||
SetRenderTarget(0, frame_buffer)
|
||||
...
|
||||
Clear
|
||||
EndScene
|
||||
...
|
||||
// Render, texture and sampler state updates as well as a draw call that draws tex1 to a quad which fills the
|
||||
// screen space.
|
||||
...
|
||||
EndScene -> ErrInvalidCall return code
|
||||
Present
|
||||
```
|
||||
|
||||
This is quite a different flow to implement HD and SD mode but the solution to solve that particular problem is straight
|
||||
forward and easy to understand. This means that the game will always render in HD mode and only downscale the final
|
||||
frame to SD resolution for 640x480 output.
|
||||
|
||||
Also, why the fuck do they call BeginScene and EndScene twice? Looks like they wanted to do this in two separate scenes
|
||||
for some reason. Checking the return values would have revealed to them that something's not right...lucky them that
|
||||
this code works nevertheless.
|
||||
Another Konmai seal of approval, a job well done. ¯\_(ツ)_/¯
|
||||
|
||||
## iidxhook's up-/downscaling solution
|
||||
The initial solution simply hooked into BeginScene and EndScene and let the game render to an intermediate render
|
||||
target texture. The texture was scaled according to the actual target frame buffer size before getting presented. This
|
||||
solution worked fine for pre IIDX 20 games but created a black screen on IIDX 20+.
|
||||
|
||||
In order to avoid two different scaling flows, the final solution that works for both does the following:
|
||||
* Create a render target texture with native resolution and let the game render to it
|
||||
* Set the render target to that intermediate render target texture on BeginScene
|
||||
* Before Present
|
||||
* Scale the intermediate render target texture to the back buffer
|
||||
* Set the back buffer as the render target
|
||||
* Present frame
|
||||
|
||||
Just an outline which follows the actual implementation that you can find in the iidxhook-util/d3d9.
|
Loading…
x
Reference in New Issue
Block a user