From b3e47e87ecf63edbf4a4b8f9788b9f984e9b3b87 Mon Sep 17 00:00:00 2001 From: Aaron Giles Date: Mon, 12 Jul 2021 19:27:19 -0700 Subject: voodoo: Improve fidelity of synchronization points. Add synchronization back to NOP to fix flicker in gtfore06. --- src/devices/video/poly.h | 6 +++--- src/devices/video/voodoo.cpp | 39 +++++++++++++++++++++++++----------- src/devices/video/voodoo_2.cpp | 20 ++++++++++-------- src/devices/video/voodoo_banshee.cpp | 14 ++++++++++--- src/devices/video/voodoo_render.cpp | 2 +- src/devices/video/voodoo_render.h | 20 +++++++++++------- 6 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/devices/video/poly.h b/src/devices/video/poly.h index 9cd91a69323..6d1f10e7efd 100644 --- a/src/devices/video/poly.h +++ b/src/devices/video/poly.h @@ -519,8 +519,8 @@ poly_manager::~poly_manager() #if TRACK_POLY_WAITS { osd_printf_info("Wait summary:\n"); - osd_printf_info("Cause Cycles Waits Actuals Average <100 100-1k 1k-10k 10k+\n"); - osd_printf_info("------------------ ------- ------- ------- ------- ------- ------- ------- -------\n"); + osd_printf_info("Cause Cycles Waits Actuals Average <100 100-1k 1k-10k 10k+\n"); + osd_printf_info("-------------------------- ------- ------- ------- ------- ------- ------- ------- -------\n"); while (1) { typename waitmap_t::value_type *biggest = nullptr; @@ -532,7 +532,7 @@ poly_manager::~poly_manager() if (biggest == nullptr) break; - osd_printf_info("%-20s%-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s\n", + osd_printf_info("%-28s%-7s %-7s %-7s %-7s %-7s %-7s %-7s %-7s\n", biggest->first.c_str(), friendly_number(biggest->second.total_cycles).c_str(), friendly_number(biggest->second.total_waits).c_str(), diff --git a/src/devices/video/voodoo.cpp b/src/devices/video/voodoo.cpp index 40049adfe4e..6a7b2ec9736 100644 --- a/src/devices/video/voodoo.cpp +++ b/src/devices/video/voodoo.cpp @@ -1033,7 +1033,7 @@ void voodoo_1_device::device_start() void voodoo_1_device::device_stop() { - m_renderer->wait("Destruction"); + m_renderer->wait("device_stop"); } @@ -1540,7 +1540,7 @@ u32 voodoo_1_device::internal_lfb_r(offs_t offset) } // wait for any outstanding work to finish before reading - m_renderer->wait("LFB read"); + m_renderer->wait("internal_lfb_r"); // read and assemble two pixels u32 data = buffer[0] | (buffer[1] << 16); @@ -1629,7 +1629,7 @@ void voodoo_1_device::internal_lfb_w(offs_t offset, u32 data, u32 mem_mask) depth += scry * m_renderer->rowpixels() + x; // wait for any outstanding work to finish - m_renderer->wait("LFB Write"); + m_renderer->wait("internal_lfb_w(raw)"); // loop over up to two pixels voodoo::dither_helper dither(scry, fbzmode); @@ -1891,9 +1891,6 @@ void voodoo_1_device::internal_texture_w(offs_t offset, u32 data) if (!BIT(m_chipmask, 1 + tmunum)) return; - // wait for any outstanding work to finish - m_renderer->wait("Texture write"); - // the seq_8_downld flag seems to always come from TMU #0 bool seq_8_downld = m_tmu[0].regs().texture_mode().seq_8_downld(); @@ -1924,6 +1921,9 @@ void voodoo_1_device::internal_texture_w(offs_t offset, u32 data) return; u8 *dest = texture.write_ptr(lod, ts, tt, bytes_per_texel); + // wait for any outstanding work to finish + m_renderer->wait("internal_texture_w"); + // write the four bytes in little-endian order if (bytes_per_texel == 1) { @@ -2282,6 +2282,12 @@ u32 voodoo_1_device::reg_triangle_w(u32 chipmask, u32 regnum, u32 data) u32 voodoo_1_device::reg_nop_w(u32 chipmask, u32 regnum, u32 data) { + // NOP should synchronize the pipeline; in theory we can mostly get away without + // it, but gtfore06 shows flicker on some golfers if we don't respect it; some + // games (notably gradius4) take a noticeable hit when this is present, so it + // may be worth adding an option to not block here + m_renderer->wait("reg_nop_w"); + if (BIT(data, 0)) reset_counters(); if (BIT(data, 1)) @@ -2321,8 +2327,6 @@ u32 voodoo_1_device::reg_fastfill_w(u32 chipmask, u32 regnum, u32 data) u32 voodoo_1_device::reg_swapbuffer_w(u32 chipmask, u32 regnum, u32 data) { - m_renderer->wait("swapbufferCMD"); - // the don't swap value is Voodoo 2-only, masked off by the register engine m_vblank_swap_pending = true; m_vblank_swap = BIT(data, 1, 8); @@ -2360,7 +2364,7 @@ u32 voodoo_1_device::reg_fbiinit_w(u32 chipmask, u32 regnum, u32 data) { if (BIT(chipmask, 0) && m_init_enable.enable_hw_init()) { - m_renderer->wait("fbi_init"); + m_renderer->wait("reg_fbiinit_w"); m_reg.write(regnum, data); // handle resets written to fbiInit0 @@ -2394,7 +2398,7 @@ u32 voodoo_1_device::reg_video_w(u32 chipmask, u32 regnum, u32 data) { if (BIT(chipmask, 0)) { - m_renderer->wait("video_configuration"); + m_renderer->wait("reg_video_w"); m_reg.write(regnum, data); auto const hsync = m_reg.hsync(); @@ -2423,12 +2427,12 @@ u32 voodoo_1_device::reg_clut_w(u32 chipmask, u32 regnum, u32 data) { if (BIT(chipmask, 0)) { - m_renderer->wait("clut"); if (m_reg.fbi_init1().video_timing_reset() == 0) { int index = BIT(data, 24, 8); if (index <= 32 && m_clut[index] != data) { + screen().update_partial(screen().vpos()); m_clut[index] = data; m_clut_dirty = true; } @@ -2607,6 +2611,7 @@ void voodoo_1_device::swap_buffers() logerror("--- swap_buffers @ %d\n", screen().vpos()); // force a partial update + m_renderer->wait("swap_buffers"); screen().update_partial(screen().vpos()); m_video_changed = true; @@ -2677,6 +2682,16 @@ void voodoo_1_device::rotate_buffers() int voodoo_1_device::update_common(bitmap_rgb32 &bitmap, const rectangle &cliprect, rgb_t const *pens) { + // flush the pipes + if (operation_pending()) + { + if (LOG_VBLANK_SWAP) + logerror("---- update flush begin\n"); + flush_fifos(machine().time()); + if (LOG_VBLANK_SWAP) + logerror("---- update flush end\n"); + } + // reset the video changed flag bool changed = m_video_changed; m_video_changed = false; @@ -2687,9 +2702,9 @@ int voodoo_1_device::update_common(bitmap_rgb32 &bitmap, const rectangle &clipre drawbuf = m_backbuf; // copy from the current front buffer - if (LOG_VBLANK_SWAP) logerror("--- update_common @ %d from %08X\n", screen().vpos(), m_rgboffs[m_frontbuf]); u32 rowpixels = m_renderer->rowpixels(); u16 *buffer_base = draw_buffer(drawbuf); + if (LOG_VBLANK_SWAP) logerror("--- update_common %d-%d @ %d from %08X\n", cliprect.min_y, cliprect.max_y, screen().vpos(), u32((u8 *)buffer_base - m_fbram)); for (s32 y = cliprect.min_y; y <= cliprect.max_y; y++) { if (y < m_yoffs) diff --git a/src/devices/video/voodoo_2.cpp b/src/devices/video/voodoo_2.cpp index 5f805d1f604..6a86195081f 100644 --- a/src/devices/video/voodoo_2.cpp +++ b/src/devices/video/voodoo_2.cpp @@ -578,6 +578,7 @@ u32 command_fifo::packet_type_5(u32 command) if (LOG_CMDFIFO) m_device.logerror(" PACKET TYPE 5: FB count=%d dest=%08X bd2=%X bdN=%X\n", count, target, BIT(command, 26, 4), BIT(command, 22, 4)); + m_device.renderer().wait("packet_type_5(0)"); for (u32 word = 0; word < count; word++) m_ram[target++ & m_mask] = little_endianize_int32(read_next()); break; @@ -945,7 +946,7 @@ u32 voodoo_2_device::reg_video2_w(u32 chipmask, u32 regnum, u32 data) { if (BIT(chipmask, 0)) { - m_renderer->wait("video_configuration"); + m_renderer->wait("reg_video2_w"); m_reg.write(regnum, data); auto const hsync = m_reg.hsync(); @@ -988,7 +989,7 @@ u32 voodoo_2_device::reg_sargb_w(u32 chipmask, u32 regnum, u32 data) u32 voodoo_2_device::reg_userintr_w(u32 chipmask, u32 regnum, u32 data) { - m_renderer->wait("userIntrCMD"); + m_renderer->wait("reg_userintr_w"); // Bit 5 of intrCtrl enables user interrupts if (m_reg.intr_ctrl().user_interrupt_enable()) @@ -1015,7 +1016,7 @@ u32 voodoo_2_device::reg_cmdfifo_w(u32 chipmask, u32 regnum, u32 data) { if (BIT(chipmask, 0)) { - m_renderer->wait("cmdFifo write"); + m_renderer->wait("reg_cmdfifo_w"); m_reg.write(regnum, data); m_cmdfifo.set_base(BIT(m_reg.read(voodoo_regs::reg_cmdFifoBaseAddr), 0, 10) << 12); m_cmdfifo.set_end((BIT(m_reg.read(voodoo_regs::reg_cmdFifoBaseAddr), 16, 10) + 1) << 12); @@ -1034,7 +1035,6 @@ u32 voodoo_2_device::reg_cmdfifoptr_w(u32 chipmask, u32 regnum, u32 data) { if (BIT(chipmask, 0)) { - m_renderer->wait("cmdFifoReadPtr"); m_reg.write(regnum, data); m_cmdfifo.set_read_pointer(data); } @@ -1051,7 +1051,6 @@ u32 voodoo_2_device::reg_cmdfifodepth_w(u32 chipmask, u32 regnum, u32 data) { if (BIT(chipmask, 0)) { - m_renderer->wait("cmdFifoDepth"); m_reg.write(regnum, data); m_cmdfifo.set_depth(data); } @@ -1068,7 +1067,6 @@ u32 voodoo_2_device::reg_cmdfifoholes_w(u32 chipmask, u32 regnum, u32 data) { if (BIT(chipmask, 0)) { - m_renderer->wait("cmdFifoHoles"); m_reg.write(regnum, data); m_cmdfifo.set_holes(data); } @@ -1084,10 +1082,16 @@ u32 voodoo_2_device::reg_fbiinit5_7_w(u32 chipmask, u32 regnum, u32 data) { if (BIT(chipmask, 0) && m_init_enable.enable_hw_init()) { - m_renderer->wait("fbiInit5-7"); + u32 delta = m_reg.read(regnum) ^ data; m_reg.write(regnum, data); - if (regnum == voodoo_regs::reg_fbiInit5 || regnum == voodoo_regs::reg_fbiInit6) + + // a few bits affect video memory configuration + if ((regnum == voodoo_regs::reg_fbiInit5 && BIT(delta, 9, 2) != 0) || + (regnum == voodoo_regs::reg_fbiInit6 && BIT(delta, 30, 1) != 0)) + { + m_renderer->wait("reg_fbiinit5_7_w"); recompute_video_memory(); + } m_cmdfifo.set_enable(m_reg.fbi_init7().cmdfifo_enable()); m_cmdfifo.set_count_holes(!m_reg.fbi_init7().disable_cmdfifo_holes()); } diff --git a/src/devices/video/voodoo_banshee.cpp b/src/devices/video/voodoo_banshee.cpp index 6ead666df8f..5ad277c83e0 100644 --- a/src/devices/video/voodoo_banshee.cpp +++ b/src/devices/video/voodoo_banshee.cpp @@ -331,6 +331,7 @@ u32 voodoo_banshee_device::read_lfb(offs_t offset, u32 mem_mask) u32 addr = offset * 4; if (addr <= m_fbmask) { + m_renderer->wait("read_lfb"); u32 result = *(u32 *)&m_fbram[addr]; if (LOG_LFB) logerror("%s:read_lfb(%X) = %08X\n", machine().describe_context(), addr, result); @@ -363,6 +364,7 @@ void voodoo_banshee_device::write_lfb(offs_t offset, u32 data, u32 mem_mask) // writes below the LFB base are direct? if (addr <= m_fbmask) { + m_renderer->wait("write_lfb"); if (LOG_LFB) logerror("%s:write_lfb(%X) = %08X & %08X\n", machine().describe_context(), addr, data, mem_mask); COMBINE_DATA((u32 *)&m_fbram[addr]); @@ -800,6 +802,7 @@ void voodoo_banshee_device::internal_io_w(offs_t offset, u32 data, u32 mem_mask) u32 dacaddr = BIT(m_io_regs.read(banshee_io_regs::dacAddr), 0, 9); if (newval != m_clut[dacaddr]) { + screen().update_partial(screen().vpos()); m_clut[dacaddr] = newval; m_clut_dirty = true; } @@ -1062,9 +1065,6 @@ void voodoo_banshee_device::internal_texture_w(offs_t offset, u32 data) if (!BIT(m_chipmask, 1 + tmunum)) return; - // wait for any outstanding work to finish - m_renderer->wait("Texture write"); - // pull out modes from the TMU and update state auto ®s = m_tmu[tmunum].regs(); auto const texlod = regs.texture_lod(); @@ -1080,6 +1080,9 @@ void voodoo_banshee_device::internal_texture_w(offs_t offset, u32 data) // determine destination pointer u8 *dest = texture.write_ptr(0, offset * 4, 0, 1); + // wait for any outstanding work to finish + m_renderer->wait("internal_texture_w"); + // write the four bytes in little-endian order u32 bytes_per_texel = (texmode.format() < 8) ? 1 : 2; if (bytes_per_texel == 1) @@ -1142,6 +1145,9 @@ void voodoo_banshee_device::internal_lfb_direct_w(offs_t offset, u32 data, u32 m // advance pointers to the proper row dest += y * m_renderer->rowpixels() + x; + // wait for any outstanding work to finish + m_renderer->wait("internal_lfb_direct_w"); + // write to the RGB buffer if (ACCESSING_BITS_0_15 && dest < end) dest[0] = BIT(data, 0, 16); @@ -1560,6 +1566,8 @@ void voodoo_banshee_device::execute_blit(u32 data) if (LOG_BANSHEE_2D) logerror(" blit_2d:host_to_screen: %08x -> %08x, %d, %d\n", data, addr, m_blt_dst_x, m_blt_dst_y); + m_renderer->wait("execute_blit(3)"); + switch (m_blt_dst_bpp) { case 1: diff --git a/src/devices/video/voodoo_render.cpp b/src/devices/video/voodoo_render.cpp index 7a3d91e0661..756dff823c2 100644 --- a/src/devices/video/voodoo_render.cpp +++ b/src/devices/video/voodoo_render.cpp @@ -2195,7 +2195,7 @@ void voodoo_renderer::pixel_pipeline(thread_stats_block &threadstats, u16 *dest, } // wait for any outstanding work to finish - wait("LFB Write"); + wait("pixel_pipeline"); // perform alpha blending if (alphamode.alphablend()) diff --git a/src/devices/video/voodoo_render.h b/src/devices/video/voodoo_render.h index 90499df6978..b428494f5ef 100644 --- a/src/devices/video/voodoo_render.h +++ b/src/devices/video/voodoo_render.h @@ -536,24 +536,30 @@ public: // update the fog tables void write_fog(u32 base, u32 data) { - wait("Fog write"); - m_fogdelta[base + 0] = (data >> 0) & 0xff; - m_fogblend[base + 0] = (data >> 8) & 0xff; - m_fogdelta[base + 1] = (data >> 16) & 0xff; - m_fogblend[base + 1] = (data >> 24) & 0xff; + u32 oldval = m_fogdelta[base + 0] | (m_fogblend[base + 0] << 8) | (m_fogdelta[base + 1] << 16) | (m_fogblend[base + 1] << 24); + if (oldval != data) + { + wait("write_fog"); + m_fogdelta[base + 0] = BIT(data, 0, 8); + m_fogblend[base + 0] = BIT(data, 8, 8); + m_fogdelta[base + 1] = BIT(data, 16, 8); + m_fogblend[base + 1] = BIT(data, 24, 8); + } } // update the Y origin void set_yorigin(s32 yorigin) { - wait("Y origin write"); + if (m_yorigin != yorigin) + wait("set_yorigin"); m_yorigin = yorigin; } // update the rowpixels void set_rowpixels(u32 rowpixels) { - wait("Rowpixels write"); + if (m_rowpixels != rowpixels) + wait("set_rowpixels"); m_rowpixels = rowpixels; } -- cgit v1.2.3