From: notaz Date: Sun, 8 Oct 2023 22:20:07 +0000 (+0300) Subject: gpu: a bit better idle bit handling X-Git-Tag: r24~125 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=pcsx_rearmed.git;a=commitdiff_plain;h=abf094858889145af1fde9840429dfb8a0e70a39 gpu: a bit better idle bit handling notaz/pcsx_rearmed#217 --- diff --git a/Makefile b/Makefile index c020274a..7c16e4a7 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ OBJS += libpcsxcore/cdriso.o libpcsxcore/cdrom.o libpcsxcore/cheat.o libpcsxcore libpcsxcore/misc.o libpcsxcore/plugins.o libpcsxcore/ppf.o libpcsxcore/psxbios.o \ libpcsxcore/psxcommon.o libpcsxcore/psxcounters.o libpcsxcore/psxdma.o \ libpcsxcore/psxhw.o libpcsxcore/psxinterpreter.o libpcsxcore/psxmem.o libpcsxcore/r3000a.o \ - libpcsxcore/sio.o libpcsxcore/spu.o + libpcsxcore/sio.o libpcsxcore/spu.o libpcsxcore/gpu.o OBJS += libpcsxcore/gte.o libpcsxcore/gte_nf.o libpcsxcore/gte_divider.o #OBJS += libpcsxcore/debug.o libpcsxcore/socket.o libpcsxcore/disr3000a.o ifeq "$(ARCH)" "arm" diff --git a/frontend/libretro.c b/frontend/libretro.c index b8b11665..d21b1a2b 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -27,6 +27,7 @@ #include "../libpcsxcore/cdriso.h" #include "../libpcsxcore/cheat.h" #include "../libpcsxcore/r3000a.h" +#include "../libpcsxcore/gpu.h" #include "../plugins/dfsound/out.h" #include "../plugins/dfsound/spu_config.h" #include "cspace.h" @@ -488,6 +489,7 @@ struct rearmed_cbs pl_rearmed_cbs = { .pl_vout_close = vout_close, .mmap = pl_mmap, .munmap = pl_munmap, + .gpu_state_change = gpu_state_change, /* from psxcounters */ .gpu_hcnt = &hSyncCount, .gpu_frame_count = &frame_counter, diff --git a/frontend/plugin_lib.c b/frontend/plugin_lib.c index 917ae179..2339028e 100644 --- a/frontend/plugin_lib.c +++ b/frontend/plugin_lib.c @@ -33,6 +33,7 @@ #include "psemu_plugin_defs.h" #include "../libpcsxcore/new_dynarec/new_dynarec.h" #include "../libpcsxcore/psxmem_map.h" +#include "../libpcsxcore/gpu.h" #define HUD_HEIGHT 10 @@ -770,6 +771,7 @@ struct rearmed_cbs pl_rearmed_cbs = { .mmap = pl_mmap, .munmap = pl_munmap, .pl_set_gpu_caps = pl_set_gpu_caps, + .gpu_state_change = gpu_state_change, }; /* watchdog */ diff --git a/frontend/plugin_lib.h b/frontend/plugin_lib.h index 4984d305..efd7d1e2 100644 --- a/frontend/plugin_lib.h +++ b/frontend/plugin_lib.h @@ -49,6 +49,7 @@ void pl_switch_dispmode(void); void pl_timing_prepare(int is_pal); void pl_frame_limit(void); +// for communication with gpulib struct rearmed_cbs { void (*pl_get_layer_pos)(int *x, int *y, int *w, int *h); int (*pl_vout_open)(void); @@ -61,6 +62,8 @@ struct rearmed_cbs { // only used by some frontends void (*pl_vout_set_raw_vram)(void *vram); void (*pl_set_gpu_caps)(int caps); + // emulation related + void (*gpu_state_change)(int what); // some stats, for display by some plugins int flips_per_sec, cpu_usage; float vsps_cur; // currect vsync/s diff --git a/libpcsxcore/gpu.c b/libpcsxcore/gpu.c new file mode 100644 index 00000000..1eadf59c --- /dev/null +++ b/libpcsxcore/gpu.c @@ -0,0 +1,32 @@ +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + ***************************************************************************/ + +#include "gpu.h" +#include "psxdma.h" + +void gpu_state_change(int what) +{ + enum psx_gpu_state state = what; + switch (state) + { + case PGS_VRAM_TRANSFER_START: + HW_GPU_STATUS &= ~SWAP32(PSXGPU_nBUSY); + break; + case PGS_VRAM_TRANSFER_END: + HW_GPU_STATUS |= SWAP32(PSXGPU_nBUSY); + break; + case PGS_PRIMITIVE_START: + HW_GPU_STATUS &= ~SWAP32(PSXGPU_nBUSY); + GPUDMA_INT(200); // see gpuInterrupt + break; + } +} diff --git a/libpcsxcore/gpu.h b/libpcsxcore/gpu.h index 21384e58..ef9c7183 100644 --- a/libpcsxcore/gpu.h +++ b/libpcsxcore/gpu.h @@ -43,4 +43,12 @@ HW_GPU_STATUS |= SWAP32(GPU_readStatus() & ~PSXGPU_TIMING_BITS); \ } +enum psx_gpu_state { + PGS_VRAM_TRANSFER_START, + PGS_VRAM_TRANSFER_END, + PGS_PRIMITIVE_START, // for non-dma only +}; + +void gpu_state_change(int what); + #endif /* __GPU_H__ */ diff --git a/libpcsxcore/psxdma.c b/libpcsxcore/psxdma.c index c0aee7ed..0ffec81c 100644 --- a/libpcsxcore/psxdma.c +++ b/libpcsxcore/psxdma.c @@ -156,6 +156,8 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU HW_DMA2_MADR = SWAPu32(madr + words_copy * 4); + // careful: gpu_state_change() also messes with this + HW_GPU_STATUS &= SWAP32(~PSXGPU_nBUSY); // already 32-bit word size ((size * 4) / 4) GPUDMA_INT(words / 4); return; @@ -177,6 +179,8 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU HW_DMA2_MADR = SWAPu32(madr); + // careful: gpu_state_change() also messes with this + HW_GPU_STATUS &= SWAP32(~PSXGPU_nBUSY); // already 32-bit word size ((size * 4) / 4) GPUDMA_INT(words / 4); return; @@ -214,6 +218,8 @@ void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU DMA_INTERRUPT(2); } +// note: this is also (ab)used for non-dma prim command +// to delay gpu returning to idle state, see gpu_state_change() void gpuInterrupt() { if (HW_DMA2_CHCR == SWAP32(0x01000401) && !(HW_DMA2_MADR & SWAP32(0x800000))) { diff --git a/plugins/gpulib/gpu.c b/plugins/gpulib/gpu.c index fec46882..15810b82 100644 --- a/plugins/gpulib/gpu.c +++ b/plugins/gpulib/gpu.c @@ -12,6 +12,7 @@ #include #include #include "gpu.h" +#include "../../libpcsxcore/gpu.h" // meh #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #ifdef __GNUC__ @@ -441,6 +442,8 @@ static void start_vram_transfer(uint32_t pos_word, uint32_t size_word, int is_re log_io("start_vram_transfer %c (%d, %d) %dx%d\n", is_read ? 'r' : 'w', gpu.dma.x, gpu.dma.y, gpu.dma.w, gpu.dma.h); + if (gpu.gpu_state_change) + gpu.gpu_state_change(PGS_VRAM_TRANSFER_START); } static void finish_vram_transfer(int is_read) @@ -452,6 +455,8 @@ static void finish_vram_transfer(int is_read) renderer_update_caches(gpu.dma_start.x, gpu.dma_start.y, gpu.dma_start.w, gpu.dma_start.h, 0); } + if (gpu.gpu_state_change) + gpu.gpu_state_change(PGS_VRAM_TRANSFER_END); } static void do_vram_copy(const uint32_t *params) @@ -630,12 +635,16 @@ static noinline int do_cmd_buffer(uint32_t *data, int count) return count - pos; } -static void flush_cmd_buffer(void) +static noinline void flush_cmd_buffer(void) { int left = do_cmd_buffer(gpu.cmd_buffer, gpu.cmd_len); if (left > 0) memmove(gpu.cmd_buffer, gpu.cmd_buffer + gpu.cmd_len - left, left * 4); - gpu.cmd_len = left; + if (left != gpu.cmd_len) { + if (!gpu.dma.h && gpu.gpu_state_change) + gpu.gpu_state_change(PGS_PRIMITIVE_START); + gpu.cmd_len = left; + } } void GPUwriteDataMem(uint32_t *mem, int count) @@ -914,6 +923,7 @@ void GPUrearmedCallbacks(const struct rearmed_cbs *cbs) gpu.mmap = cbs->mmap; gpu.munmap = cbs->munmap; + gpu.gpu_state_change = cbs->gpu_state_change; // delayed vram mmap if (gpu.vram == NULL) diff --git a/plugins/gpulib/gpu.h b/plugins/gpulib/gpu.h index dbca8081..4abc36b7 100644 --- a/plugins/gpulib/gpu.h +++ b/plugins/gpulib/gpu.h @@ -107,6 +107,7 @@ struct psx_gpu { (int *x, int *y, int *w, int *h, int *vram_h); void *(*mmap)(unsigned int size); void (*munmap)(void *ptr, unsigned int size); + void (*gpu_state_change)(int what); // psx_gpu_state }; extern struct psx_gpu gpu;