mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-09-17 08:02:41 +00:00
System: Fix HW/SW rendering swap
This commit is contained in:
parent
facfea5389
commit
14f69b7b78
|
@ -43,11 +43,12 @@ u16 g_gpu_clut[GPU_CLUT_SIZE];
|
||||||
|
|
||||||
const GPU::GP0CommandHandlerTable GPU::s_GP0_command_handler_table = GPU::GenerateGP0CommandHandlerTable();
|
const GPU::GP0CommandHandlerTable GPU::s_GP0_command_handler_table = GPU::GenerateGP0CommandHandlerTable();
|
||||||
|
|
||||||
static bool CompressAndWriteTextureToFile(u32 width, u32 height, std::string filename, FileSystem::ManagedCFilePtr fp,
|
static TimingEvent s_crtc_tick_event(
|
||||||
u8 quality, bool clear_alpha, bool flip_y, std::vector<u32> texture_data,
|
"GPU CRTC Tick", 1, 1, [](void* param, TickCount ticks, TickCount ticks_late) { g_gpu->CRTCTickEvent(ticks); },
|
||||||
u32 texture_data_stride, GPUTexture::Format texture_format,
|
nullptr);
|
||||||
bool display_osd_message, bool use_thread);
|
static TimingEvent s_command_tick_event(
|
||||||
static void JoinScreenshotThreads();
|
"GPU Command Tick", 1, 1, [](void* param, TickCount ticks, TickCount ticks_late) { g_gpu->CommandTickEvent(ticks); },
|
||||||
|
nullptr);
|
||||||
|
|
||||||
static std::deque<std::thread> s_screenshot_threads;
|
static std::deque<std::thread> s_screenshot_threads;
|
||||||
static std::mutex s_screenshot_threads_mutex;
|
static std::mutex s_screenshot_threads_mutex;
|
||||||
|
@ -60,22 +61,21 @@ static u32 s_active_gpu_cycles_frames = 0;
|
||||||
|
|
||||||
static constexpr GPUTexture::Format DISPLAY_INTERNAL_POSTFX_FORMAT = GPUTexture::Format::RGBA8;
|
static constexpr GPUTexture::Format DISPLAY_INTERNAL_POSTFX_FORMAT = GPUTexture::Format::RGBA8;
|
||||||
|
|
||||||
|
static bool CompressAndWriteTextureToFile(u32 width, u32 height, std::string filename, FileSystem::ManagedCFilePtr fp,
|
||||||
|
u8 quality, bool clear_alpha, bool flip_y, std::vector<u32> texture_data,
|
||||||
|
u32 texture_data_stride, GPUTexture::Format texture_format,
|
||||||
|
bool display_osd_message, bool use_thread);
|
||||||
|
static void JoinScreenshotThreads();
|
||||||
|
|
||||||
GPU::GPU()
|
GPU::GPU()
|
||||||
: m_crtc_tick_event(
|
|
||||||
"GPU CRTC Tick", 1, 1,
|
|
||||||
[](void* param, TickCount ticks, TickCount ticks_late) { static_cast<GPU*>(param)->CRTCTickEvent(ticks); }, this),
|
|
||||||
m_command_tick_event(
|
|
||||||
"GPU Command Tick", 1, 1,
|
|
||||||
[](void* param, TickCount ticks, TickCount ticks_late) { static_cast<GPU*>(param)->CommandTickEvent(ticks); },
|
|
||||||
this)
|
|
||||||
{
|
{
|
||||||
ResetStatistics();
|
ResetStatistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
GPU::~GPU()
|
GPU::~GPU()
|
||||||
{
|
{
|
||||||
m_command_tick_event.Deactivate();
|
s_command_tick_event.Deactivate();
|
||||||
m_crtc_tick_event.Deactivate();
|
s_crtc_tick_event.Deactivate();
|
||||||
|
|
||||||
JoinScreenshotThreads();
|
JoinScreenshotThreads();
|
||||||
DestroyDeinterlaceTextures();
|
DestroyDeinterlaceTextures();
|
||||||
|
@ -89,7 +89,7 @@ bool GPU::Initialize()
|
||||||
{
|
{
|
||||||
m_force_progressive_scan = g_settings.gpu_disable_interlacing;
|
m_force_progressive_scan = g_settings.gpu_disable_interlacing;
|
||||||
m_force_ntsc_timings = g_settings.gpu_force_ntsc_timings;
|
m_force_ntsc_timings = g_settings.gpu_force_ntsc_timings;
|
||||||
m_crtc_tick_event.Activate();
|
s_crtc_tick_event.Activate();
|
||||||
m_fifo_size = g_settings.gpu_fifo_size;
|
m_fifo_size = g_settings.gpu_fifo_size;
|
||||||
m_max_run_ahead = g_settings.gpu_max_run_ahead;
|
m_max_run_ahead = g_settings.gpu_max_run_ahead;
|
||||||
m_console_is_pal = System::IsPALRegion();
|
m_console_is_pal = System::IsPALRegion();
|
||||||
|
@ -192,8 +192,8 @@ void GPU::Reset(bool clear_vram)
|
||||||
m_blitter_state = BlitterState::Idle;
|
m_blitter_state = BlitterState::Idle;
|
||||||
|
|
||||||
// Force event to reschedule itself.
|
// Force event to reschedule itself.
|
||||||
m_crtc_tick_event.Deactivate();
|
s_crtc_tick_event.Deactivate();
|
||||||
m_command_tick_event.Deactivate();
|
s_command_tick_event.Deactivate();
|
||||||
|
|
||||||
SoftReset();
|
SoftReset();
|
||||||
UpdateDisplay();
|
UpdateDisplay();
|
||||||
|
@ -460,7 +460,7 @@ u32 GPU::ReadRegister(u32 offset)
|
||||||
if (IsCRTCScanlinePending())
|
if (IsCRTCScanlinePending())
|
||||||
SynchronizeCRTC();
|
SynchronizeCRTC();
|
||||||
if (IsCommandCompletionPending())
|
if (IsCommandCompletionPending())
|
||||||
m_command_tick_event.InvokeEarly();
|
s_command_tick_event.InvokeEarly();
|
||||||
|
|
||||||
return m_GPUSTAT.bits;
|
return m_GPUSTAT.bits;
|
||||||
}
|
}
|
||||||
|
@ -552,7 +552,7 @@ void GPU::AddCommandTicks(TickCount ticks)
|
||||||
|
|
||||||
void GPU::SynchronizeCRTC()
|
void GPU::SynchronizeCRTC()
|
||||||
{
|
{
|
||||||
m_crtc_tick_event.InvokeEarly();
|
s_crtc_tick_event.InvokeEarly();
|
||||||
}
|
}
|
||||||
|
|
||||||
float GPU::ComputeHorizontalFrequency() const
|
float GPU::ComputeHorizontalFrequency() const
|
||||||
|
@ -838,17 +838,17 @@ void GPU::UpdateCRTCDisplayParameters()
|
||||||
|
|
||||||
TickCount GPU::GetPendingCRTCTicks() const
|
TickCount GPU::GetPendingCRTCTicks() const
|
||||||
{
|
{
|
||||||
const TickCount pending_sysclk_ticks = m_crtc_tick_event.GetTicksSinceLastExecution();
|
const TickCount pending_sysclk_ticks = s_crtc_tick_event.GetTicksSinceLastExecution();
|
||||||
TickCount fractional_ticks = m_crtc_state.fractional_ticks;
|
TickCount fractional_ticks = m_crtc_state.fractional_ticks;
|
||||||
return SystemTicksToCRTCTicks(pending_sysclk_ticks, &fractional_ticks);
|
return SystemTicksToCRTCTicks(pending_sysclk_ticks, &fractional_ticks);
|
||||||
}
|
}
|
||||||
|
|
||||||
TickCount GPU::GetPendingCommandTicks() const
|
TickCount GPU::GetPendingCommandTicks() const
|
||||||
{
|
{
|
||||||
if (!m_command_tick_event.IsActive())
|
if (!s_command_tick_event.IsActive())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return SystemTicksToGPUTicks(m_command_tick_event.GetTicksSinceLastExecution());
|
return SystemTicksToGPUTicks(s_command_tick_event.GetTicksSinceLastExecution());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::UpdateCRTCTickEvent()
|
void GPU::UpdateCRTCTickEvent()
|
||||||
|
@ -905,7 +905,7 @@ void GPU::UpdateCRTCTickEvent()
|
||||||
ticks_until_event = std::min(ticks_until_event, ticks_until_hblank_start_or_end);
|
ticks_until_event = std::min(ticks_until_event, ticks_until_hblank_start_or_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_crtc_tick_event.Schedule(CRTCTicksToSystemTicks(ticks_until_event, m_crtc_state.fractional_ticks));
|
s_crtc_tick_event.Schedule(CRTCTicksToSystemTicks(ticks_until_event, m_crtc_state.fractional_ticks));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU::IsCRTCScanlinePending() const
|
bool GPU::IsCRTCScanlinePending() const
|
||||||
|
@ -1089,11 +1089,11 @@ void GPU::UpdateCommandTickEvent()
|
||||||
if (m_pending_command_ticks <= 0)
|
if (m_pending_command_ticks <= 0)
|
||||||
{
|
{
|
||||||
m_pending_command_ticks = 0;
|
m_pending_command_ticks = 0;
|
||||||
m_command_tick_event.Deactivate();
|
s_command_tick_event.Deactivate();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_command_tick_event.SetIntervalAndSchedule(GPUTicksToSystemTicks(m_pending_command_ticks));
|
s_command_tick_event.SetIntervalAndSchedule(GPUTicksToSystemTicks(m_pending_command_ticks));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1223,7 +1223,7 @@ void GPU::WriteGP1(u32 value)
|
||||||
case 0x00: // Reset GPU
|
case 0x00: // Reset GPU
|
||||||
{
|
{
|
||||||
DEBUG_LOG("GP1 reset GPU");
|
DEBUG_LOG("GP1 reset GPU");
|
||||||
m_command_tick_event.InvokeEarly();
|
s_command_tick_event.InvokeEarly();
|
||||||
SynchronizeCRTC();
|
SynchronizeCRTC();
|
||||||
SoftReset();
|
SoftReset();
|
||||||
}
|
}
|
||||||
|
@ -1232,7 +1232,7 @@ void GPU::WriteGP1(u32 value)
|
||||||
case 0x01: // Clear FIFO
|
case 0x01: // Clear FIFO
|
||||||
{
|
{
|
||||||
DEBUG_LOG("GP1 clear FIFO");
|
DEBUG_LOG("GP1 clear FIFO");
|
||||||
m_command_tick_event.InvokeEarly();
|
s_command_tick_event.InvokeEarly();
|
||||||
SynchronizeCRTC();
|
SynchronizeCRTC();
|
||||||
|
|
||||||
// flush partial writes
|
// flush partial writes
|
||||||
|
@ -1246,7 +1246,7 @@ void GPU::WriteGP1(u32 value)
|
||||||
m_blit_buffer.clear();
|
m_blit_buffer.clear();
|
||||||
m_blit_remaining_words = 0;
|
m_blit_remaining_words = 0;
|
||||||
m_pending_command_ticks = 0;
|
m_pending_command_ticks = 0;
|
||||||
m_command_tick_event.Deactivate();
|
s_command_tick_event.Deactivate();
|
||||||
UpdateDMARequest();
|
UpdateDMARequest();
|
||||||
UpdateGPUIdle();
|
UpdateGPUIdle();
|
||||||
}
|
}
|
||||||
|
@ -1364,7 +1364,7 @@ void GPU::WriteGP1(u32 value)
|
||||||
{
|
{
|
||||||
// Have to be careful when setting this because Synchronize() can modify GPUSTAT.
|
// Have to be careful when setting this because Synchronize() can modify GPUSTAT.
|
||||||
static constexpr u32 SET_MASK = UINT32_C(0b00000000011111110100000000000000);
|
static constexpr u32 SET_MASK = UINT32_C(0b00000000011111110100000000000000);
|
||||||
m_command_tick_event.InvokeEarly();
|
s_command_tick_event.InvokeEarly();
|
||||||
SynchronizeCRTC();
|
SynchronizeCRTC();
|
||||||
m_GPUSTAT.bits = (m_GPUSTAT.bits & ~SET_MASK) | (new_GPUSTAT.bits & SET_MASK);
|
m_GPUSTAT.bits = (m_GPUSTAT.bits & ~SET_MASK) | (new_GPUSTAT.bits & SET_MASK);
|
||||||
UpdateCRTCConfig();
|
UpdateCRTCConfig();
|
||||||
|
|
|
@ -201,6 +201,10 @@ public:
|
||||||
ALWAYS_INLINE s32 GetCRTCDisplayWidth() const { return m_crtc_state.display_width; }
|
ALWAYS_INLINE s32 GetCRTCDisplayWidth() const { return m_crtc_state.display_width; }
|
||||||
ALWAYS_INLINE s32 GetCRTCDisplayHeight() const { return m_crtc_state.display_height; }
|
ALWAYS_INLINE s32 GetCRTCDisplayHeight() const { return m_crtc_state.display_height; }
|
||||||
|
|
||||||
|
// Ticks for hblank/vblank.
|
||||||
|
void CRTCTickEvent(TickCount ticks);
|
||||||
|
void CommandTickEvent(TickCount ticks);
|
||||||
|
|
||||||
// Dumps raw VRAM to a file.
|
// Dumps raw VRAM to a file.
|
||||||
bool DumpVRAMToFile(const char* filename);
|
bool DumpVRAMToFile(const char* filename);
|
||||||
|
|
||||||
|
@ -275,10 +279,6 @@ protected:
|
||||||
void UpdateDMARequest();
|
void UpdateDMARequest();
|
||||||
void UpdateGPUIdle();
|
void UpdateGPUIdle();
|
||||||
|
|
||||||
// Ticks for hblank/vblank.
|
|
||||||
void CRTCTickEvent(TickCount ticks);
|
|
||||||
void CommandTickEvent(TickCount ticks);
|
|
||||||
|
|
||||||
/// Returns 0 if the currently-displayed field is on odd lines (1,3,5,...) or 1 if even (2,4,6,...).
|
/// Returns 0 if the currently-displayed field is on odd lines (1,3,5,...) or 1 if even (2,4,6,...).
|
||||||
ALWAYS_INLINE u32 GetInterlacedDisplayField() const { return ZeroExtend32(m_crtc_state.interlaced_field); }
|
ALWAYS_INLINE u32 GetInterlacedDisplayField() const { return ZeroExtend32(m_crtc_state.interlaced_field); }
|
||||||
|
|
||||||
|
@ -411,9 +411,6 @@ protected:
|
||||||
AddCommandTicks(std::max(drawn_width, drawn_height));
|
AddCommandTicks(std::max(drawn_width, drawn_height));
|
||||||
}
|
}
|
||||||
|
|
||||||
TimingEvent m_crtc_tick_event;
|
|
||||||
TimingEvent m_command_tick_event;
|
|
||||||
|
|
||||||
union GPUSTAT
|
union GPUSTAT
|
||||||
{
|
{
|
||||||
u32 bits;
|
u32 bits;
|
||||||
|
|
Loading…
Reference in a new issue