From 73576bb61ed1fb90be962f87028c3a6244b7723d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 5 Mar 2025 01:23:37 +0600 Subject: [PATCH 1/2] Revert "S3 ViRGE: Make IRQs happen in main thread" This reverts commit fae26729f103010ddc7e621a37083bc4ae6d5736. --- src/video/vid_s3_virge.c | 57 +++++----------------------------------- 1 file changed, 6 insertions(+), 51 deletions(-) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 62ffcff0cf..af33003cb5 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -338,7 +338,6 @@ typedef struct virge_t { event_t * fifo_not_full_event; atomic_int virge_busy; - atomic_uint virge_irq_req; uint8_t subsys_stat; uint8_t subsys_cntl; @@ -374,9 +373,6 @@ typedef struct virge_t { uint32_t dma_mmio_addr; uint32_t dma_data_type; - pc_timer_t wake_timer; - pc_timer_t irq_timer; - int pci; int is_agp; } virge_t; @@ -387,28 +383,6 @@ wake_fifo_thread(virge_t *virge) { thread_set_event(virge->wake_fifo_thread); } -void -s3_virge_wake_fifo_timer(void* priv) -{ - virge_t *virge = (virge_t *) priv; - - thread_set_event(virge->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ -} - -void -s3_virge_wake_fifo_thread(virge_t *virge) -{ - if (!timer_is_enabled(&virge->wake_timer)) { - /*Don't wake FIFO thread immediately - if we do that it will probably - process one word and go back to sleep, requiring it to be woken on - almost every write. Instead, wait a short while so that the CPU - emulation writes more data so we have more batched-up work.*/ - timer_on_auto(&virge->wake_timer, 100.0); - } - if (!timer_is_enabled(&virge->irq_timer)) - timer_on_auto(&virge->irq_timer, 100.0); -} - static virge_t *reset_state = NULL; static video_timings_t timing_diamond_stealth3d_2000_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; @@ -497,19 +471,6 @@ s3_virge_update_irqs(virge_t *virge) pci_clear_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); } -void -s3_virge_update_irq_timer(void* priv) -{ - virge_t *virge = (virge_t *) priv; - - if (virge->virge_irq_req) { - virge->virge_irq_req--; - s3_virge_update_irqs(virge); - } - - timer_on_auto(&virge->irq_timer, 100.); -} - static void s3_virge_out(uint16_t addr, uint8_t val, void *priv) { @@ -1140,9 +1101,6 @@ static void s3_virge_vblank_start(svga_t *svga) { virge_t *virge = (virge_t *) svga->priv; - if (virge->virge_irq_req) - virge->virge_irq_req--; - virge->subsys_stat |= INT_VSY; s3_virge_update_irqs(virge); } @@ -1837,8 +1795,7 @@ fifo_thread(void *param) if (virge->cmd_dma) virge->subsys_stat |= (INT_HOST_DONE | INT_CMD_DONE); - //s3_virge_update_irqs(virge); - virge->virge_irq_req++; + s3_virge_update_irqs(virge); } } @@ -1878,8 +1835,10 @@ s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) virge->fifo_write_idx++; - if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 16) - s3_virge_wake_fifo_thread(virge); + if (FIFO_ENTRIES > 0xe000) + wake_fifo_thread(virge); + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) + wake_fifo_thread(virge); } static void @@ -4445,8 +4404,7 @@ render_thread(void *param) } virge->s3d_busy = 0; virge->subsys_stat |= INT_S3D_DONE; - //s3_virge_update_irqs(virge); - virge->virge_irq_req++; + s3_virge_update_irqs(virge); } } @@ -5375,9 +5333,6 @@ s3_virge_init(const device_t *info) virge->fifo_not_full_event = thread_create_event(); virge->fifo_thread = thread_create(fifo_thread, virge); - timer_add(&virge->wake_timer, s3_virge_wake_fifo_timer, virge, 0); - timer_add(&virge->irq_timer, s3_virge_update_irq_timer, virge, 0); - virge->local = info->local; *reset_state = *virge; From 92d69475f4eea136226842784ffdcf2d862dbb77 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 5 Mar 2025 02:17:51 +0600 Subject: [PATCH 2/2] Only retain the newer IRQ updating code --- src/video/vid_s3_virge.c | 43 ++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index af33003cb5..904d4a4cf0 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -338,6 +338,7 @@ typedef struct virge_t { event_t * fifo_not_full_event; atomic_int virge_busy; + atomic_uint irq_pending; uint8_t subsys_stat; uint8_t subsys_cntl; @@ -375,6 +376,8 @@ typedef struct virge_t { int pci; int is_agp; + + pc_timer_t irq_timer; } virge_t; static __inline void @@ -471,6 +474,19 @@ s3_virge_update_irqs(virge_t *virge) pci_clear_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); } +static void +s3_virge_update_irq_timer(void* priv) +{ + virge_t *virge = (virge_t *) priv; + + if (virge->irq_pending) { + virge->irq_pending--; + s3_virge_update_irqs(virge); + } + + timer_on_auto(&virge->irq_timer, 100.); +} + static void s3_virge_out(uint16_t addr, uint8_t val, void *priv) { @@ -1101,6 +1117,8 @@ static void s3_virge_vblank_start(svga_t *svga) { virge_t *virge = (virge_t *) svga->priv; + if (virge->irq_pending) + virge->irq_pending--; virge->subsys_stat |= INT_VSY; s3_virge_update_irqs(virge); } @@ -1784,18 +1802,18 @@ fifo_thread(void *param) virge->fifo_read_idx++; fifo->addr_type = FIFO_INVALID; - if (FIFO_ENTRIES > 0xe000) - thread_set_event(virge->fifo_not_full_event); + if (FIFO_ENTRIES > 0xe000) + thread_set_event(virge->fifo_not_full_event); - end_time = plat_timer_read(); - virge_time += end_time - start_time; - } - virge->virge_busy = 0; - virge->subsys_stat |= (INT_FIFO_EMP | INT_3DF_EMP); - if (virge->cmd_dma) - virge->subsys_stat |= (INT_HOST_DONE | INT_CMD_DONE); + end_time = plat_timer_read(); + virge_time += end_time - start_time; + } + virge->virge_busy = 0; + virge->subsys_stat |= (INT_FIFO_EMP | INT_3DF_EMP); + if (virge->cmd_dma) + virge->subsys_stat |= (INT_HOST_DONE | INT_CMD_DONE); - s3_virge_update_irqs(virge); + virge->irq_pending++; } } @@ -4404,7 +4422,7 @@ render_thread(void *param) } virge->s3d_busy = 0; virge->subsys_stat |= INT_S3D_DONE; - s3_virge_update_irqs(virge); + virge->irq_pending++; } } @@ -5062,6 +5080,7 @@ s3_virge_disable_handlers(virge_t *dev) reset_state->svga.timer = dev->svga.timer; reset_state->svga.timer8514 = dev->svga.timer8514; + reset_state->irq_timer = dev->irq_timer; } static void @@ -5333,6 +5352,8 @@ s3_virge_init(const device_t *info) virge->fifo_not_full_event = thread_create_event(); virge->fifo_thread = thread_create(fifo_thread, virge); + timer_add(&virge->irq_timer, s3_virge_update_irq_timer, virge, 1); + virge->local = info->local; *reset_state = *virge;