mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-24 05:10:42 -04:00
3DS: Refactor vblank handling
This commit is contained in:
parent
4003ff7d6b
commit
c6fada2c1f
@ -7,6 +7,7 @@
|
||||
#define BUFFER_BASE_PADDR OS_VRAM_PADDR // VRAM physical address
|
||||
#include "../../third_party/citro3d.c"
|
||||
|
||||
#include "gsp_gpu.h"
|
||||
#include "pica_gpu.h"
|
||||
// See the .v.pica shader files in misc/3ds
|
||||
#define CONST_MVP 0 // c0-c3
|
||||
@ -121,9 +122,7 @@ static aptHookCookie hookCookie;
|
||||
static void AptEventHook(APT_HookType hookType, void* param) {
|
||||
if (hookType == APTHOOK_ONSUSPEND) {
|
||||
C3Di_RenderQueueWaitDone();
|
||||
C3Di_RenderQueueDisableVBlank();
|
||||
} else if (hookType == APTHOOK_ONRESTORE) {
|
||||
C3Di_RenderQueueEnableVBlank();
|
||||
C3Di_OnRestore();
|
||||
}
|
||||
}
|
||||
@ -153,6 +152,8 @@ static void InitCitro3D(void) {
|
||||
gfxSetDoubleBuffering(GFX_TOP, true);
|
||||
SetDefaultState();
|
||||
AllocShaders();
|
||||
|
||||
GSP_setup();
|
||||
}
|
||||
|
||||
static GfxResourceID white_square;
|
||||
@ -547,7 +548,7 @@ void Gfx_SetVSync(cc_bool vsync) {
|
||||
void Gfx_BeginFrame(void) {
|
||||
rendering3D = false;
|
||||
// wait for vblank for both screens TODO move to end?
|
||||
if (gfx_vsync) C3D_FrameSync();
|
||||
if (gfx_vsync) GSP_wait_for_full_vblank();
|
||||
|
||||
C3D_FrameBegin(0);
|
||||
topTarget = &topTargetLeft;
|
||||
|
25
src/3ds/gsp_gpu.h
Normal file
25
src/3ds/gsp_gpu.h
Normal file
@ -0,0 +1,25 @@
|
||||
static volatile uint32_t vblanks_0;
|
||||
static volatile uint32_t vblanks_1;
|
||||
|
||||
static void handle_vblank(void* ptr) {
|
||||
uint32_t* counter = (uint32_t*)ptr;
|
||||
(*counter)++;
|
||||
}
|
||||
|
||||
static void GSP_setup(void) {
|
||||
// Start listening for VBLANK events
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank0, handle_vblank, (void*)&vblanks_0, false);
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank1, handle_vblank, (void*)&vblanks_1, false);
|
||||
}
|
||||
|
||||
// Waits for VBLANK for both top and bottom screens
|
||||
static void GSP_wait_for_full_vblank(void) {
|
||||
uint32_t init0 = vblanks_0;
|
||||
uint32_t init1 = vblanks_1;
|
||||
|
||||
for (;;) {
|
||||
gspWaitForAnyEvent();
|
||||
if (vblanks_0 != init0 && vblanks_1 != init1) return;
|
||||
}
|
||||
}
|
||||
|
66
third_party/citro3d.c
vendored
66
third_party/citro3d.c
vendored
@ -245,12 +245,9 @@ struct C3D_RenderTarget_tag
|
||||
// Flags for C3D_FrameBegin
|
||||
enum
|
||||
{
|
||||
C3D_FRAME_SYNCDRAW = BIT(0), // Perform C3D_FrameSync before checking the GPU status
|
||||
C3D_FRAME_NONBLOCK = BIT(1), // Return false instead of waiting if the GPU is busy
|
||||
};
|
||||
|
||||
static void C3D_FrameSync(void);
|
||||
|
||||
static bool C3D_FrameBegin(u8 flags);
|
||||
static bool C3D_FrameDrawOn(C3D_RenderTarget* target);
|
||||
static void C3D_FrameSplit(u8 flags);
|
||||
@ -404,10 +401,6 @@ static bool C3Di_SplitFrame(u32** pBuf, u32* pSize);
|
||||
static void C3Di_RenderQueueInit(void);
|
||||
static void C3Di_RenderQueueExit(void);
|
||||
static void C3Di_RenderQueueWaitDone(void);
|
||||
static void C3Di_RenderQueueEnableVBlank(void);
|
||||
static void C3Di_RenderQueueDisableVBlank(void);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -837,21 +830,10 @@ static void C3D_ImmDrawEnd(void)
|
||||
static C3D_RenderTarget *linkedTarget[3];
|
||||
|
||||
static bool inFrame, inSafeTransfer;
|
||||
static bool needSwapTop, needSwapBot, isTopStereo;
|
||||
static u32 vblankCounter[2];
|
||||
static bool swapPending, isTopStereo;
|
||||
|
||||
static void C3Di_RenderTargetDestroy(C3D_RenderTarget* target);
|
||||
|
||||
static void onVBlank0(void* unused)
|
||||
{
|
||||
vblankCounter[0]++;
|
||||
}
|
||||
|
||||
static void onVBlank1(void* unused)
|
||||
{
|
||||
vblankCounter[1]++;
|
||||
}
|
||||
|
||||
static void onQueueFinish(gxCmdQueue_s* queue)
|
||||
{
|
||||
if (inSafeTransfer)
|
||||
@ -863,61 +845,28 @@ static void onQueueFinish(gxCmdQueue_s* queue)
|
||||
gxCmdQueueClear(queue);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (swapPending)
|
||||
{
|
||||
if (needSwapTop)
|
||||
{
|
||||
gfxScreenSwapBuffers(GFX_TOP, isTopStereo);
|
||||
needSwapTop = false;
|
||||
}
|
||||
if (needSwapBot)
|
||||
{
|
||||
gfxScreenSwapBuffers(GFX_BOTTOM, false);
|
||||
needSwapBot = false;
|
||||
}
|
||||
gfxScreenSwapBuffers(GFX_TOP, isTopStereo);
|
||||
gfxScreenSwapBuffers(GFX_BOTTOM, false);
|
||||
}
|
||||
}
|
||||
|
||||
static void C3D_FrameSync(void)
|
||||
{
|
||||
u32 cur[2];
|
||||
u32 start[2] = { vblankCounter[0], vblankCounter[1] };
|
||||
do
|
||||
{
|
||||
gspWaitForAnyEvent();
|
||||
cur[0] = vblankCounter[0];
|
||||
cur[1] = vblankCounter[1];
|
||||
} while (cur[0]==start[0] || cur[1]==start[1]);
|
||||
}
|
||||
|
||||
static bool C3Di_WaitAndClearQueue(s64 timeout)
|
||||
{
|
||||
gxCmdQueue_s* queue = &C3Di_GetContext()->gxQueue;
|
||||
if (!gxCmdQueueWait(queue, timeout))
|
||||
return false;
|
||||
|
||||
gxCmdQueueStop(queue);
|
||||
gxCmdQueueClear(queue);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void C3Di_RenderQueueEnableVBlank(void)
|
||||
{
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank0, onVBlank0, NULL, false);
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank1, onVBlank1, NULL, false);
|
||||
}
|
||||
|
||||
static void C3Di_RenderQueueDisableVBlank(void)
|
||||
{
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank0, NULL, NULL, false);
|
||||
gspSetEventCallback(GSPGPU_EVENT_VBlank1, NULL, NULL, false);
|
||||
}
|
||||
|
||||
static void C3Di_RenderQueueInit(void)
|
||||
{
|
||||
C3D_Context* ctx = C3Di_GetContext();
|
||||
|
||||
C3Di_RenderQueueEnableVBlank();
|
||||
|
||||
GX_BindQueue(&ctx->gxQueue);
|
||||
gxCmdQueueSetCallback(&ctx->gxQueue, onQueueFinish, NULL);
|
||||
gxCmdQueueRun(&ctx->gxQueue);
|
||||
@ -928,8 +877,6 @@ static void C3Di_RenderQueueExit(void)
|
||||
C3Di_WaitAndClearQueue(-1);
|
||||
gxCmdQueueSetCallback(&C3Di_GetContext()->gxQueue, NULL, NULL);
|
||||
GX_BindQueue(NULL);
|
||||
|
||||
C3Di_RenderQueueDisableVBlank();
|
||||
}
|
||||
|
||||
static void C3Di_RenderQueueWaitDone(void)
|
||||
@ -987,8 +934,7 @@ static void C3D_FrameEnd(u8 flags)
|
||||
|
||||
C3D_RenderTarget* target;
|
||||
isTopStereo = false;
|
||||
needSwapTop = true;
|
||||
needSwapBot = true;
|
||||
swapPending = true;
|
||||
|
||||
for (int i = 2; i >= 0; i --)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user