| 142 | } |
| 143 | |
| 144 | void MTGS::ThreadEntryPoint() |
| 145 | { |
| 146 | Threading::SetNameOfCurrentThread("GS"); |
| 147 | |
| 148 | // GS can hit SMC write traps when executing InitAndReadFIFO |
| 149 | // As racey as it sounds, it should be safe, since InitAndReadFIFO is requested and immediately waited for, |
| 150 | // so the EE thread shouldn't be touching any of its codegen structures while it happens. |
| 151 | PageFaultHandler::InstallSecondaryThread(); |
| 152 | |
| 153 | // Explicitly set rounding mode to default (nearest, FTZ off). |
| 154 | // Otherwise it appears to get inherited from the EE thread on Linux. |
| 155 | FPControlRegister::SetCurrent(FPControlRegister::GetDefault()); |
| 156 | |
| 157 | for (;;) |
| 158 | { |
| 159 | // wait until we're actually asked to initialize (and config has been loaded, etc) |
| 160 | while (!s_open_flag.load(std::memory_order_acquire)) |
| 161 | { |
| 162 | if (s_shutdown_flag.load(std::memory_order_acquire)) |
| 163 | { |
| 164 | s_sem_event.Kill(); |
| 165 | return; |
| 166 | } |
| 167 | |
| 168 | s_sem_event.WaitForWork(); |
| 169 | } |
| 170 | |
| 171 | // try initializing.. this could fail |
| 172 | std::memcpy(RingBuffer.Regs, PS2MEM_GS, sizeof(PS2MEM_GS)); |
| 173 | const bool opened = GSopen(EmuConfig.GS, EmuConfig.GS.Renderer, RingBuffer.Regs, |
| 174 | VMManager::GetEffectiveVSyncMode(), VMManager::ShouldAllowPresentThrottle()); |
| 175 | s_open_flag.store(opened, std::memory_order_release); |
| 176 | |
| 177 | // notify emu thread that we finished opening (or failed) |
| 178 | s_open_or_close_done.Post(); |
| 179 | |
| 180 | // are we open? |
| 181 | if (!opened) |
| 182 | { |
| 183 | // wait until we're asked to try again... |
| 184 | continue; |
| 185 | } |
| 186 | |
| 187 | // we're ready to go |
| 188 | MainLoop(); |
| 189 | |
| 190 | // when we come back here, it's because we closed (or shutdown) |
| 191 | // that means the emu thread should be blocked, waiting for us to be done |
| 192 | pxAssertRel(!s_open_flag.load(std::memory_order_relaxed), "Open flag is clear on close"); |
| 193 | GSclose(); |
| 194 | s_open_or_close_done.Post(); |
| 195 | |
| 196 | // we need to reset sem_event here, because MainLoop() kills it. |
| 197 | s_sem_event.Reset(); |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | void MTGS::ResetGS(bool hardware_reset) |