mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	HLE/GSP: Only trigger GSP interrupts for the current active GSP thread.
This is true for all interrupts except PDC0 and PDC1, which should be triggered for all registered threads. TODO: The real GSP module seems to only trigger PDC0 after updating the screens (both top and bottom). PDC1 doesn't seem to be triggered at all.
This commit is contained in:
		
							parent
							
								
									05a44ed353
								
							
						
					
					
						commit
						68fc3b36e6
					
				
					 1 changed files with 19 additions and 1 deletions
				
			
		|  | @ -50,6 +50,9 @@ constexpr ResultCode ERR_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorM | |||
|                                            ErrorSummary::InvalidArgument, | ||||
|                                            ErrorLevel::Usage); // 0xE0E02BEC
 | ||||
| 
 | ||||
| /// Maximum number of threads that can be registered at the same time in the GSP module.
 | ||||
| constexpr u32 MaxGSPThreads = 4; | ||||
| 
 | ||||
| /// Gets a pointer to a thread command buffer in GSP shared memory
 | ||||
| static inline u8* GetCommandBuffer(Kernel::SharedPtr<Kernel::SharedMemory> shared_memory, | ||||
|                                    u32 thread_id) { | ||||
|  | @ -325,6 +328,7 @@ void GSP_GPU::RegisterInterruptRelayQueue(Kernel::HLERequestContext& ctx) { | |||
|     interrupt_event->name = "GSP_GSP_GPU::interrupt_event"; | ||||
| 
 | ||||
|     u32 thread_id = next_thread_id++; | ||||
|     ASSERT_MSG(thread_id < MaxGSPThreads, "GSP thread id overflow"); | ||||
| 
 | ||||
|     SessionData* session_data = GetSessionData(ctx.Session()); | ||||
|     session_data->thread_id = thread_id; | ||||
|  | @ -370,11 +374,23 @@ void GSP_GPU::UnregisterInterruptRelayQueue(Kernel::HLERequestContext& ctx) { | |||
|  * @todo This probably does not belong in the GSP module, instead move to video_core | ||||
|  */ | ||||
| void GSP_GPU::SignalInterrupt(InterruptId interrupt_id) { | ||||
|     // Don't do anything if no process has acquired the GPU right.
 | ||||
|     if (active_thread_id == -1) | ||||
|         return; | ||||
| 
 | ||||
|     if (nullptr == shared_memory) { | ||||
|         LOG_WARNING(Service_GSP, "cannot synchronize until GSP shared memory has been created!"); | ||||
|         return; | ||||
|     } | ||||
|     for (int thread_id = 0; thread_id < 0x4; ++thread_id) { | ||||
| 
 | ||||
|     // Normal interrupts are only signaled for the active thread (ie, the thread that has the GPU
 | ||||
|     // right), but the PDC0/1 interrupts are signaled for every registered thread.
 | ||||
|     for (int thread_id = 0; thread_id < MaxGSPThreads; ++thread_id) { | ||||
|         if (interrupt_id != InterruptId::PDC0 && interrupt_id != InterruptId::PDC1) { | ||||
|             // Ignore threads that aren't the current active thread
 | ||||
|             if (thread_id != active_thread_id) | ||||
|                 continue; | ||||
|         } | ||||
|         SessionData* session_data = FindRegisteredThreadData(thread_id); | ||||
|         if (session_data == nullptr) | ||||
|             continue; | ||||
|  | @ -398,6 +414,8 @@ void GSP_GPU::SignalInterrupt(InterruptId interrupt_id) { | |||
|         // Update framebuffer information if requested
 | ||||
|         // TODO(yuriks): Confirm where this code should be called. It is definitely updated without
 | ||||
|         //               executing any GSP commands, only waiting on the event.
 | ||||
|         // TODO(Subv): The real GSP module triggers PDC0 after updating both the top and bottom
 | ||||
|         // screen, it is currently unknown what PDC1 does.
 | ||||
|         int screen_id = | ||||
|             (interrupt_id == InterruptId::PDC0) ? 0 : (interrupt_id == InterruptId::PDC1) ? 1 : -1; | ||||
|         if (screen_id != -1) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue