From: notaz Date: Sun, 8 Oct 2023 22:20:07 +0000 (+0300) Subject: gpu: a bit better idle bit handling X-Git-Tag: r24l~144 X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1328fa326b0e51dca172bb59e355e964ac666b64;p=pcsx_rearmed.git gpu: a bit better idle bit handling notaz/pcsx_rearmed#217 --- diff --git a/Makefile b/Makefile index a083d528..9779ddcc 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,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 ifeq ($(DEBUG), 1) 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 e48ed521..6b2d7186 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/jni/Android.mk b/jni/Android.mk index 03c2a285..971c45d1 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -41,6 +41,7 @@ SOURCES_C := $(CORE_DIR)/cdriso.c \ $(CORE_DIR)/r3000a.c \ $(CORE_DIR)/sio.c \ $(CORE_DIR)/spu.c \ + $(CORE_DIR)/gpu.c \ $(CORE_DIR)/gte.c \ $(CORE_DIR)/gte_nf.c \ $(CORE_DIR)/gte_divider.c 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 271c89c9..6814819d 100644 --- a/plugins/gpulib/gpu.c +++ b/plugins/gpulib/gpu.c @@ -14,6 +14,7 @@ #include /* for calloc */ #include "gpu.h" +#include "../../libpcsxcore/gpu.h" // meh #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #ifdef __GNUC__ @@ -482,6 +483,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) @@ -493,6 +496,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) @@ -671,12 +676,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) @@ -963,6 +972,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 b3a23023..28458cf2 100644 --- a/plugins/gpulib/gpu.h +++ b/plugins/gpulib/gpu.h @@ -114,6 +114,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;