mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	GSP: Trigger GPU interrupts at more accurate locations.
This commit is contained in:
		
							parent
							
								
									e90b37b935
								
							
						
					
					
						commit
						f94d8f9603
					
				
					 3 changed files with 21 additions and 8 deletions
				
			
		|  | @ -173,6 +173,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { | ||||||
|  * Signals that the specified interrupt type has occurred to userland code |  * Signals that the specified interrupt type has occurred to userland code | ||||||
|  * @param interrupt_id ID of interrupt that is being signalled |  * @param interrupt_id ID of interrupt that is being signalled | ||||||
|  * @todo This should probably take a thread_id parameter and only signal this thread? |  * @todo This should probably take a thread_id parameter and only signal this thread? | ||||||
|  |  * @todo This probably does not belong in the GSP module, instead move to video_core | ||||||
|  */ |  */ | ||||||
| void SignalInterrupt(InterruptId interrupt_id) { | void SignalInterrupt(InterruptId interrupt_id) { | ||||||
|     if (0 == g_interrupt_event) { |     if (0 == g_interrupt_event) { | ||||||
|  | @ -211,6 +212,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | ||||||
|         memcpy(Memory::GetPointer(command.dma_request.dest_address), |         memcpy(Memory::GetPointer(command.dma_request.dest_address), | ||||||
|                Memory::GetPointer(command.dma_request.source_address), |                Memory::GetPointer(command.dma_request.source_address), | ||||||
|                command.dma_request.size); |                command.dma_request.size); | ||||||
|  |         SignalInterrupt(InterruptId::DMA); | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     // ctrulib homebrew sends all relevant command list data with this command,
 |     // ctrulib homebrew sends all relevant command list data with this command,
 | ||||||
|  | @ -219,13 +221,13 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | ||||||
|     case CommandId::SET_COMMAND_LIST_LAST: |     case CommandId::SET_COMMAND_LIST_LAST: | ||||||
|     { |     { | ||||||
|         auto& params = command.set_command_list_last; |         auto& params = command.set_command_list_last; | ||||||
|  | 
 | ||||||
|         WriteGPURegister(GPU_REG_INDEX(command_processor_config.address), Memory::VirtualToPhysicalAddress(params.address) >> 3); |         WriteGPURegister(GPU_REG_INDEX(command_processor_config.address), Memory::VirtualToPhysicalAddress(params.address) >> 3); | ||||||
|         WriteGPURegister(GPU_REG_INDEX(command_processor_config.size), params.size); |         WriteGPURegister(GPU_REG_INDEX(command_processor_config.size), params.size); | ||||||
| 
 | 
 | ||||||
|         // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though
 |         // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though
 | ||||||
|         WriteGPURegister(GPU_REG_INDEX(command_processor_config.trigger), 1); |         WriteGPURegister(GPU_REG_INDEX(command_processor_config.trigger), 1); | ||||||
| 
 | 
 | ||||||
|         SignalInterrupt(InterruptId::P3D); |  | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -243,6 +245,8 @@ 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].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].size), params.end2 - params.start2); | ||||||
|         WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].value), params.value2); |         WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].value), params.value2); | ||||||
|  | 
 | ||||||
|  |         SignalInterrupt(InterruptId::PSC0); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -256,14 +260,9 @@ 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.flags), params.flags); | ||||||
|         WriteGPURegister(GPU_REG_INDEX(display_transfer_config.trigger), 1); |         WriteGPURegister(GPU_REG_INDEX(display_transfer_config.trigger), 1); | ||||||
| 
 | 
 | ||||||
|         // TODO(bunnei): Signalling all of these interrupts here is totally wrong, but it seems to
 |         // TODO(bunnei): Determine if these interrupts should be signalled here.
 | ||||||
|         // work well enough for running demos. Need to figure out how these all work and trigger
 |  | ||||||
|         // them correctly.
 |  | ||||||
|         SignalInterrupt(InterruptId::PSC0); |  | ||||||
|         SignalInterrupt(InterruptId::PSC1); |         SignalInterrupt(InterruptId::PSC1); | ||||||
|         SignalInterrupt(InterruptId::PPF); |         SignalInterrupt(InterruptId::PPF); | ||||||
|         SignalInterrupt(InterruptId::P3D); |  | ||||||
|         SignalInterrupt(InterruptId::DMA); |  | ||||||
| 
 | 
 | ||||||
|         // Update framebuffer information if requested
 |         // Update framebuffer information if requested
 | ||||||
|         for (int screen_id = 0; screen_id < 2; ++screen_id) { |         for (int screen_id = 0; screen_id < 2; ++screen_id) { | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
| #include "pica.h" | #include "pica.h" | ||||||
| #include "primitive_assembly.h" | #include "primitive_assembly.h" | ||||||
| #include "vertex_shader.h" | #include "vertex_shader.h" | ||||||
|  | #include "core/hle/service/gsp_gpu.h" | ||||||
| 
 | 
 | ||||||
| #include "debug_utils/debug_utils.h" | #include "debug_utils/debug_utils.h" | ||||||
| 
 | 
 | ||||||
|  | @ -40,6 +41,11 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||||
|     DebugUtils::OnPicaRegWrite(id, registers[id]); |     DebugUtils::OnPicaRegWrite(id, registers[id]); | ||||||
| 
 | 
 | ||||||
|     switch(id) { |     switch(id) { | ||||||
|  |         // Trigger IRQ
 | ||||||
|  |         case PICA_REG_INDEX(trigger_irq): | ||||||
|  |             GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D); | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|         // It seems like these trigger vertex rendering
 |         // It seems like these trigger vertex rendering
 | ||||||
|         case PICA_REG_INDEX(trigger_draw): |         case PICA_REG_INDEX(trigger_draw): | ||||||
|         case PICA_REG_INDEX(trigger_draw_indexed): |         case PICA_REG_INDEX(trigger_draw_indexed): | ||||||
|  |  | ||||||
|  | @ -45,10 +45,16 @@ struct Regs { | ||||||
| #define INSERT_PADDING_WORDS_HELPER2(x, y) INSERT_PADDING_WORDS_HELPER1(x, y) | #define INSERT_PADDING_WORDS_HELPER2(x, y) INSERT_PADDING_WORDS_HELPER1(x, y) | ||||||
| #define INSERT_PADDING_WORDS(num_words) u32 INSERT_PADDING_WORDS_HELPER2(pad, __LINE__)[(num_words)]; | #define INSERT_PADDING_WORDS(num_words) u32 INSERT_PADDING_WORDS_HELPER2(pad, __LINE__)[(num_words)]; | ||||||
| 
 | 
 | ||||||
|     INSERT_PADDING_WORDS(0x41); |     INSERT_PADDING_WORDS(0x10); | ||||||
|  | 
 | ||||||
|  |     u32 trigger_irq; | ||||||
|  | 
 | ||||||
|  |     INSERT_PADDING_WORDS(0x30); | ||||||
| 
 | 
 | ||||||
|     BitField<0, 24, u32> viewport_size_x; |     BitField<0, 24, u32> viewport_size_x; | ||||||
|  | 
 | ||||||
|     INSERT_PADDING_WORDS(0x1); |     INSERT_PADDING_WORDS(0x1); | ||||||
|  | 
 | ||||||
|     BitField<0, 24, u32> viewport_size_y; |     BitField<0, 24, u32> viewport_size_y; | ||||||
| 
 | 
 | ||||||
|     INSERT_PADDING_WORDS(0x9); |     INSERT_PADDING_WORDS(0x9); | ||||||
|  | @ -544,6 +550,7 @@ struct Regs { | ||||||
|                     map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))});       \ |                     map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))});       \ | ||||||
|             } while(false) |             } while(false) | ||||||
| 
 | 
 | ||||||
|  |         ADD_FIELD(trigger_irq); | ||||||
|         ADD_FIELD(viewport_size_x); |         ADD_FIELD(viewport_size_x); | ||||||
|         ADD_FIELD(viewport_size_y); |         ADD_FIELD(viewport_size_y); | ||||||
|         ADD_FIELD(viewport_depth_range); |         ADD_FIELD(viewport_depth_range); | ||||||
|  | @ -607,6 +614,7 @@ private: | ||||||
| #ifndef _MSC_VER | #ifndef _MSC_VER | ||||||
| #define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(Regs, field_name) == position * 4, "Field "#field_name" has invalid position") | #define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(Regs, field_name) == position * 4, "Field "#field_name" has invalid position") | ||||||
| 
 | 
 | ||||||
|  | ASSERT_REG_POSITION(trigger_irq, 0x10); | ||||||
| ASSERT_REG_POSITION(viewport_size_x, 0x41); | ASSERT_REG_POSITION(viewport_size_x, 0x41); | ||||||
| ASSERT_REG_POSITION(viewport_size_y, 0x43); | ASSERT_REG_POSITION(viewport_size_y, 0x43); | ||||||
| ASSERT_REG_POSITION(viewport_depth_range, 0x4d); | ASSERT_REG_POSITION(viewport_depth_range, 0x4d); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue