mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-04 07:38:47 +00:00 
			
		
		
		
	Merge pull request #482 from yuriks/fix-vblank
Correctness fixes for GPU flipping and interrupts
This commit is contained in:
		
						commit
						4b47ed6194
					
				
					 6 changed files with 90 additions and 103 deletions
				
			
		| 
						 | 
				
			
			@ -210,14 +210,27 @@ void SignalInterrupt(InterruptId interrupt_id) {
 | 
			
		|||
    }
 | 
			
		||||
    for (int thread_id = 0; thread_id < 0x4; ++thread_id) {
 | 
			
		||||
        InterruptRelayQueue* interrupt_relay_queue = GetInterruptRelayQueue(thread_id);
 | 
			
		||||
        interrupt_relay_queue->number_interrupts = interrupt_relay_queue->number_interrupts + 1;
 | 
			
		||||
 | 
			
		||||
        u8 next = interrupt_relay_queue->index;
 | 
			
		||||
        next += interrupt_relay_queue->number_interrupts;
 | 
			
		||||
        next = next % 0x34; // 0x34 is the number of interrupt slots
 | 
			
		||||
 | 
			
		||||
        interrupt_relay_queue->number_interrupts += 1;
 | 
			
		||||
 | 
			
		||||
        interrupt_relay_queue->slot[next] = interrupt_id;
 | 
			
		||||
        interrupt_relay_queue->error_code = 0x0; // No error
 | 
			
		||||
 | 
			
		||||
        // 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.
 | 
			
		||||
        for (int screen_id = 0; screen_id < 2; ++screen_id) {
 | 
			
		||||
            FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id);
 | 
			
		||||
 | 
			
		||||
            if (info->is_dirty) {
 | 
			
		||||
                SetBufferSwap(screen_id, info->framebuffer_info[info->index]);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            info->is_dirty = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    Kernel::SignalEvent(g_interrupt_event);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -269,8 +282,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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -283,22 +294,6 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
 | 
			
		|||
        WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_size), params.out_buffer_size);
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
            if (info->is_dirty) {
 | 
			
		||||
                SetBufferSwap(screen_id, info->framebuffer_info[info->index]);
 | 
			
		||||
                info->framebuffer_info->active_fb = info->framebuffer_info->active_fb ^ 1;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            info->is_dirty = false;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,21 +45,16 @@ enum class CommandId : u32 {
 | 
			
		|||
 | 
			
		||||
/// GSP thread interrupt relay queue
 | 
			
		||||
struct InterruptRelayQueue {
 | 
			
		||||
    union {
 | 
			
		||||
        u32 hex;
 | 
			
		||||
    // Index of last interrupt in the queue
 | 
			
		||||
    u8 index;
 | 
			
		||||
    // Number of interrupts remaining to be processed by the userland code
 | 
			
		||||
    u8 number_interrupts;
 | 
			
		||||
    // Error code - zero on success, otherwise an error has occurred
 | 
			
		||||
    u8 error_code;
 | 
			
		||||
    u8 padding1;
 | 
			
		||||
 | 
			
		||||
        // Index of last interrupt in the queue
 | 
			
		||||
        BitField<0,8,u32>   index;
 | 
			
		||||
 | 
			
		||||
        // Number of interrupts remaining to be processed by the userland code
 | 
			
		||||
        BitField<8,8,u32>   number_interrupts;
 | 
			
		||||
 | 
			
		||||
        // Error code - zero on success, otherwise an error has occurred
 | 
			
		||||
        BitField<16,8,u32>  error_code;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    u32 unk0;
 | 
			
		||||
    u32 unk1;
 | 
			
		||||
    u32 missed_PDC0;
 | 
			
		||||
    u32 missed_PDC1;
 | 
			
		||||
 | 
			
		||||
    InterruptId slot[0x34];   ///< Interrupt ID slots
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue