diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 2b115240f1..9504ab5bbc 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -269,8 +269,6 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_end), Memory::VirtualToPhysicalAddress(params.end2) >> 3); WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].size), params.end2 - params.start2); WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].value), params.value2); - - SignalInterrupt(InterruptId::PSC0); break; } @@ -284,10 +282,6 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags); WriteGPURegister(GPU_REG_INDEX(display_transfer_config.trigger), 1); - // TODO(bunnei): Determine if these interrupts should be signalled here. - SignalInterrupt(InterruptId::PSC1); - SignalInterrupt(InterruptId::PPF); - // Update framebuffer information if requested for (int screen_id = 0; screen_id < 2; ++screen_id) { FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id); diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 3b730a0de4..ad39fdc498 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -27,8 +27,6 @@ Regs g_regs; bool g_skip_frame = false; ///< True if the current frame was skipped static u64 frame_ticks = 0; ///< 268MHz / gpu_refresh_rate frames per second -static u64 line_ticks = 0; ///< Number of ticks for a screen line -static u32 cur_line = 0; ///< Current screen line static u64 last_update_tick = 0; ///< CPU ticl count from last GPU update static u64 frame_count = 0; ///< Number of frames drawn static bool last_skip_frame = false; ///< True if the last frame was skipped @@ -79,6 +77,12 @@ inline void Write(u32 addr, const T data) { *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); + + if (!is_second_filler) { + GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0); + } else { + GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC1); + } } break; } @@ -152,6 +156,8 @@ inline void Write(u32 addr, const T data) { config.GetPhysicalInputAddress(), (u32)config.input_width, (u32)config.input_height, config.GetPhysicalOutputAddress(), (u32)config.output_width, (u32)config.output_height, config.output_format.Value()); + + GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); } break; } @@ -193,20 +199,14 @@ void Update() { // blank, we need to simulate it. Based on testing, it seems that retail applications work more // accurately when this is signalled between thread switches. - if (HLE::g_reschedule) { - u64 current_ticks = Core::g_app_core->GetTicks(); - u32 num_lines = static_cast((current_ticks - last_update_tick) / line_ticks); + u64 current_ticks = Core::g_app_core->GetTicks(); - // Synchronize line... - if (num_lines > 0) { - GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0); - cur_line += num_lines; - last_update_tick += (num_lines * line_ticks); - } + + if (HLE::g_reschedule) { // Synchronize frame... - if (cur_line >= framebuffer_top.height) { - cur_line = 0; + if ((current_ticks - last_update_tick) >= frame_ticks) { + last_update_tick += frame_ticks; frame_count++; last_skip_frame = g_skip_frame; g_skip_frame = (frame_count & Settings::values.frame_skip) != 0; @@ -223,6 +223,11 @@ void Update() { } // Signal to GSP that GPU interrupt has occurred + // TODO(yuriks): hwtest to determine if PDC0 is for the Top screen and PDC1 for the Sub + // screen, or if both use the same interrupts and these two instead determine the + // beginning and end of the VBlank period. If needed, split the interrupt firing into + // two different intervals. + GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0); GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); // TODO(bunnei): Fake a DSP interrupt on each frame. This does not belong here, but @@ -264,8 +269,6 @@ void Init() { framebuffer_sub.active_fb = 0; frame_ticks = 268123480 / Settings::values.gpu_refresh_rate; - line_ticks = (GPU::frame_ticks / framebuffer_top.height); - cur_line = 0; last_update_tick = Core::g_app_core->GetTicks(); last_skip_frame = false; g_skip_frame = false;