| 237 | }; |
| 238 | |
| 239 | void MTGS::PostVsyncStart(bool registers_written) |
| 240 | { |
| 241 | // Optimization note: Typically regset1 isn't needed. The regs in that area are typically |
| 242 | // changed infrequently, usually during video mode changes. However, on modern systems the |
| 243 | // 256-byte copy is only a few dozen cycles -- executed 60 times a second -- so probably |
| 244 | // not worth the effort or overhead of trying to selectively avoid it. |
| 245 | |
| 246 | uint packsize = sizeof(RingCmdPacket_Vsync) / 16; |
| 247 | PrepDataPacket(Command::VSync, packsize); |
| 248 | MemCopy_WrappedDest((u128*)PS2MEM_GS, RingBuffer.m_Ring, s_packet_writepos, RingBufferSize, 0xf); |
| 249 | |
| 250 | u32* remainder = (u32*)GetDataPacketPtr(); |
| 251 | remainder[0] = GSCSRr; |
| 252 | remainder[1] = GSIMR._u32; |
| 253 | (GSRegSIGBLID&)remainder[2] = GSSIGLBLID; |
| 254 | remainder[4] = static_cast<u32>(registers_written); |
| 255 | s_packet_writepos = (s_packet_writepos + 2) & RingBufferMask; |
| 256 | |
| 257 | SendDataPacket(); |
| 258 | |
| 259 | // Vsyncs should always start the GS thread, regardless of how little has actually be queued. |
| 260 | if (s_CopyDataTally != 0) |
| 261 | SetEvent(); |
| 262 | |
| 263 | // If the MTGS is allowed to queue a lot of frames in advance, it creates input lag. |
| 264 | // Use the Queued FrameCount to stall the EE if another vsync (or two) are already queued |
| 265 | // in the ringbuffer. The queue limit is disabled when both FrameLimiting and Vsync are |
| 266 | // disabled, since the queue can have perverse effects on framerate benchmarking. |
| 267 | |
| 268 | // Edit: It's possible that MTGS is that much faster than GS that it creates so much lag, |
| 269 | // a game becomes uncontrollable (software rendering for example). |
| 270 | // For that reason it's better to have the limit always in place, at the cost of a few max FPS in benchmarks. |
| 271 | // If those are needed back, it's better to increase the VsyncQueueSize via PCSX_vm.ini. |
| 272 | // (The Xenosaga engine is known to run into this, due to it throwing bulks of data in one frame followed by 2 empty frames.) |
| 273 | |
| 274 | if ((s_QueuedFrameCount.fetch_add(1) < EmuConfig.GS.VsyncQueueSize) /*|| (!EmuConfig.GS.VsyncEnable && !EmuConfig.GS.FrameLimitEnable)*/) |
| 275 | return; |
| 276 | |
| 277 | s_VsyncSignalListener.store(true, std::memory_order_release); |
| 278 | //Console.WriteLn( Color_Blue, "(EEcore Sleep) Vsync\t\tringpos=0x%06x, writepos=0x%06x", m_ReadPos.load(), m_WritePos.load() ); |
| 279 | |
| 280 | s_sem_Vsync.Wait(); |
| 281 | } |
| 282 | |
| 283 | void MTGS::InitAndReadFIFO(u8* mem, u32 qwc) |
| 284 | { |
nothing calls this directly
no test coverage detected