Adding vblank interrupt.
This commit is contained in:
parent
998467ce05
commit
91f62918f6
|
@ -45,7 +45,8 @@ namespace {
|
||||||
|
|
||||||
|
|
||||||
Processor::Processor(xe_memory_ref memory, shared_ptr<Backend> backend) :
|
Processor::Processor(xe_memory_ref memory, shared_ptr<Backend> backend) :
|
||||||
sym_table_(NULL), jit_(NULL) {
|
sym_table_(NULL), jit_(NULL),
|
||||||
|
interrupt_thread_lock_(NULL), interrupt_thread_state_(NULL) {
|
||||||
memory_ = xe_memory_retain(memory);
|
memory_ = xe_memory_retain(memory);
|
||||||
backend_ = backend;
|
backend_ = backend;
|
||||||
|
|
||||||
|
@ -64,6 +65,9 @@ Processor::~Processor() {
|
||||||
}
|
}
|
||||||
modules_.clear();
|
modules_.clear();
|
||||||
|
|
||||||
|
DeallocThread(interrupt_thread_state_);
|
||||||
|
xe_mutex_free(interrupt_thread_lock_);
|
||||||
|
|
||||||
delete jit_;
|
delete jit_;
|
||||||
delete sym_table_;
|
delete sym_table_;
|
||||||
|
|
||||||
|
@ -98,6 +102,9 @@ void Processor::set_export_resolver(
|
||||||
int Processor::Setup() {
|
int Processor::Setup() {
|
||||||
XEASSERTNULL(jit_);
|
XEASSERTNULL(jit_);
|
||||||
|
|
||||||
|
interrupt_thread_lock_ = xe_mutex_alloc(10000);
|
||||||
|
interrupt_thread_state_ = AllocThread(16 * 1024, 0, 0);
|
||||||
|
|
||||||
sym_table_ = new SymbolTable();
|
sym_table_ = new SymbolTable();
|
||||||
|
|
||||||
jit_ = backend_->CreateJIT(memory_, sym_table_);
|
jit_ = backend_->CreateJIT(memory_, sym_table_);
|
||||||
|
@ -245,6 +252,15 @@ uint64_t Processor::Execute(ThreadState* thread_state, uint32_t address,
|
||||||
return ppc_state->r[3];
|
return ppc_state->r[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t Processor::ExecuteInterrupt(uint32_t address,
|
||||||
|
uint64_t arg0, uint64_t arg1) {
|
||||||
|
// Acquire lock on interrupt thread (we can only dispatch one at a time).
|
||||||
|
xe_mutex_lock(interrupt_thread_lock_);
|
||||||
|
uint64_t result = Execute(interrupt_thread_state_, address, arg0, arg1);
|
||||||
|
xe_mutex_unlock(interrupt_thread_lock_);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
FunctionSymbol* Processor::GetFunction(uint32_t address) {
|
FunctionSymbol* Processor::GetFunction(uint32_t address) {
|
||||||
// Attempt to grab the function symbol from the global lookup table.
|
// Attempt to grab the function symbol from the global lookup table.
|
||||||
FunctionSymbol* fn_symbol = sym_table_->GetFunction(address);
|
FunctionSymbol* fn_symbol = sym_table_->GetFunction(address);
|
||||||
|
|
|
@ -56,10 +56,14 @@ public:
|
||||||
ThreadState* AllocThread(uint32_t stack_size, uint32_t thread_state_address,
|
ThreadState* AllocThread(uint32_t stack_size, uint32_t thread_state_address,
|
||||||
uint32_t thread_id);
|
uint32_t thread_id);
|
||||||
void DeallocThread(ThreadState* thread_state);
|
void DeallocThread(ThreadState* thread_state);
|
||||||
|
|
||||||
int Execute(ThreadState* thread_state, uint32_t address);
|
int Execute(ThreadState* thread_state, uint32_t address);
|
||||||
uint64_t Execute(ThreadState* thread_state, uint32_t address, uint64_t arg0);
|
uint64_t Execute(ThreadState* thread_state, uint32_t address, uint64_t arg0);
|
||||||
uint64_t Execute(ThreadState* thread_state, uint32_t address,
|
uint64_t Execute(ThreadState* thread_state, uint32_t address,
|
||||||
uint64_t arg0, uint64_t arg1);
|
uint64_t arg0, uint64_t arg1);
|
||||||
|
|
||||||
|
uint64_t ExecuteInterrupt(uint32_t address, uint64_t arg0, uint64_t arg1);
|
||||||
|
|
||||||
sdb::FunctionSymbol* GetFunction(uint32_t address);
|
sdb::FunctionSymbol* GetFunction(uint32_t address);
|
||||||
void* GetFunctionPointer(uint32_t address);
|
void* GetFunctionPointer(uint32_t address);
|
||||||
|
|
||||||
|
@ -72,6 +76,9 @@ private:
|
||||||
sdb::SymbolTable* sym_table_;
|
sdb::SymbolTable* sym_table_;
|
||||||
JIT* jit_;
|
JIT* jit_;
|
||||||
std::vector<ExecModule*> modules_;
|
std::vector<ExecModule*> modules_;
|
||||||
|
|
||||||
|
xe_mutex_t* interrupt_thread_lock_;
|
||||||
|
ThreadState* interrupt_thread_state_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <xenia/gpu/graphics_system.h>
|
#include <xenia/gpu/graphics_system.h>
|
||||||
|
|
||||||
|
#include <xenia/cpu/processor.h>
|
||||||
#include <xenia/gpu/ring_buffer_worker.h>
|
#include <xenia/gpu/ring_buffer_worker.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,7 +17,8 @@ using namespace xe;
|
||||||
using namespace xe::gpu;
|
using namespace xe::gpu;
|
||||||
|
|
||||||
|
|
||||||
GraphicsSystem::GraphicsSystem(const CreationParams* params) {
|
GraphicsSystem::GraphicsSystem(const CreationParams* params) :
|
||||||
|
interrupt_callback_(0), interrupt_callback_data_(0) {
|
||||||
memory_ = xe_memory_retain(params->memory);
|
memory_ = xe_memory_retain(params->memory);
|
||||||
|
|
||||||
worker_ = new RingBufferWorker(memory_);
|
worker_ = new RingBufferWorker(memory_);
|
||||||
|
@ -33,6 +35,21 @@ xe_memory_ref GraphicsSystem::memory() {
|
||||||
return xe_memory_retain(memory_);
|
return xe_memory_retain(memory_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shared_ptr<cpu::Processor> GraphicsSystem::processor() {
|
||||||
|
return processor_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSystem::set_processor(shared_ptr<cpu::Processor> processor) {
|
||||||
|
processor_ = processor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSystem::SetInterruptCallback(uint32_t callback,
|
||||||
|
uint32_t user_data) {
|
||||||
|
interrupt_callback_ = callback;
|
||||||
|
interrupt_callback_data_ = user_data;
|
||||||
|
XELOGGPU("SetInterruptCallback(%.4X, %.4X)", callback, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
void GraphicsSystem::InitializeRingBuffer(uint32_t ptr, uint32_t page_count) {
|
void GraphicsSystem::InitializeRingBuffer(uint32_t ptr, uint32_t page_count) {
|
||||||
worker_->Initialize(ptr, page_count);
|
worker_->Initialize(ptr, page_count);
|
||||||
}
|
}
|
||||||
|
@ -44,6 +61,12 @@ void GraphicsSystem::EnableReadPointerWriteBack(uint32_t ptr,
|
||||||
|
|
||||||
uint64_t GraphicsSystem::ReadRegister(uint32_t r) {
|
uint64_t GraphicsSystem::ReadRegister(uint32_t r) {
|
||||||
XELOGGPU("ReadRegister(%.4X)", r);
|
XELOGGPU("ReadRegister(%.4X)", r);
|
||||||
|
|
||||||
|
switch (r) {
|
||||||
|
case 0x6544: // ? vblank pending?
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,3 +83,12 @@ void GraphicsSystem::WriteRegister(uint32_t r, uint64_t value) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphicsSystem::DispatchInterruptCallback() {
|
||||||
|
// NOTE: we may be executing in some random thread.
|
||||||
|
if (!interrupt_callback_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
processor_->ExecuteInterrupt(
|
||||||
|
interrupt_callback_, 0, interrupt_callback_data_);
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,13 @@
|
||||||
#include <xenia/core.h>
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
class Processor;
|
||||||
|
} // namespace cpu
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
|
@ -32,19 +39,25 @@ public:
|
||||||
virtual ~GraphicsSystem();
|
virtual ~GraphicsSystem();
|
||||||
|
|
||||||
xe_memory_ref memory();
|
xe_memory_ref memory();
|
||||||
|
shared_ptr<cpu::Processor> processor();
|
||||||
|
void set_processor(shared_ptr<cpu::Processor> processor);
|
||||||
|
|
||||||
virtual void Initialize() = 0;
|
virtual void Initialize() = 0;
|
||||||
|
void SetInterruptCallback(uint32_t callback, uint32_t user_data);
|
||||||
void InitializeRingBuffer(uint32_t ptr, uint32_t page_count);
|
void InitializeRingBuffer(uint32_t ptr, uint32_t page_count);
|
||||||
void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size);
|
void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size);
|
||||||
|
|
||||||
virtual uint64_t ReadRegister(uint32_t r);
|
virtual uint64_t ReadRegister(uint32_t r);
|
||||||
virtual void WriteRegister(uint32_t r, uint64_t value);
|
virtual void WriteRegister(uint32_t r, uint64_t value);
|
||||||
|
|
||||||
|
void DispatchInterruptCallback();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static uint64_t ReadRegisterThunk(GraphicsSystem* this_ptr, uint32_t r) {
|
static uint64_t ReadRegisterThunk(GraphicsSystem* this_ptr, uint32_t r) {
|
||||||
return this_ptr->ReadRegister(r);
|
return this_ptr->ReadRegister(r);
|
||||||
}
|
}
|
||||||
static void WriteRegisterThunk(GraphicsSystem* this_ptr, uint32_t r, uint64_t value) {
|
static void WriteRegisterThunk(GraphicsSystem* this_ptr, uint32_t r,
|
||||||
|
uint64_t value) {
|
||||||
this_ptr->WriteRegister(r, value);
|
this_ptr->WriteRegister(r, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +65,12 @@ protected:
|
||||||
GraphicsSystem(const CreationParams* params);
|
GraphicsSystem(const CreationParams* params);
|
||||||
|
|
||||||
xe_memory_ref memory_;
|
xe_memory_ref memory_;
|
||||||
|
shared_ptr<cpu::Processor> processor_;
|
||||||
|
|
||||||
RingBufferWorker* worker_;
|
RingBufferWorker* worker_;
|
||||||
|
|
||||||
|
uint32_t interrupt_callback_;
|
||||||
|
uint32_t interrupt_callback_data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,41 @@ using namespace xe::gpu;
|
||||||
using namespace xe::gpu::nop;
|
using namespace xe::gpu::nop;
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void __stdcall NopGraphicsSystemVsyncCallback(NopGraphicsSystem* gs, BOOLEAN) {
|
||||||
|
gs->DispatchInterruptCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NopGraphicsSystem::NopGraphicsSystem(const CreationParams* params) :
|
NopGraphicsSystem::NopGraphicsSystem(const CreationParams* params) :
|
||||||
GraphicsSystem(params) {
|
GraphicsSystem(params),
|
||||||
|
timer_queue_(NULL),
|
||||||
|
vsync_timer_(NULL) {
|
||||||
}
|
}
|
||||||
|
|
||||||
NopGraphicsSystem::~NopGraphicsSystem() {
|
NopGraphicsSystem::~NopGraphicsSystem() {
|
||||||
|
if (vsync_timer_) {
|
||||||
|
DeleteTimerQueueTimer(timer_queue_, vsync_timer_, NULL);
|
||||||
|
}
|
||||||
|
if (timer_queue_) {
|
||||||
|
DeleteTimerQueueEx(timer_queue_, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NopGraphicsSystem::Initialize() {
|
void NopGraphicsSystem::Initialize() {
|
||||||
|
XEASSERTNULL(timer_queue_);
|
||||||
|
XEASSERTNULL(vsync_timer_);
|
||||||
|
|
||||||
|
timer_queue_ = CreateTimerQueue();
|
||||||
|
CreateTimerQueueTimer(
|
||||||
|
&vsync_timer_,
|
||||||
|
timer_queue_,
|
||||||
|
(WAITORTIMERCALLBACK)NopGraphicsSystemVsyncCallback,
|
||||||
|
this,
|
||||||
|
16,
|
||||||
|
100,
|
||||||
|
WT_EXECUTEINTIMERTHREAD);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,10 @@ public:
|
||||||
virtual ~NopGraphicsSystem();
|
virtual ~NopGraphicsSystem();
|
||||||
|
|
||||||
virtual void Initialize();
|
virtual void Initialize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
HANDLE timer_queue_;
|
||||||
|
HANDLE vsync_timer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ void xeVdInitializeEngines(uint32_t unk0, uint32_t callback, uint32_t unk1,
|
||||||
}
|
}
|
||||||
|
|
||||||
// r3 = 0x4F810000
|
// r3 = 0x4F810000
|
||||||
// r4 = function ptr (ready callback?)
|
// r4 = function ptr (cleanup callback?)
|
||||||
// r5 = 0
|
// r5 = 0
|
||||||
// r6/r7 = some binary data in .data
|
// r6/r7 = some binary data in .data
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ void xeVdSetGraphicsInterruptCallback(uint32_t callback, uint32_t user_data) {
|
||||||
// r3 = bool 0/1 - 0 is normal interrupt, 1 is some acquire/lock mumble
|
// r3 = bool 0/1 - 0 is normal interrupt, 1 is some acquire/lock mumble
|
||||||
// r4 = user_data (r4 of VdSetGraphicsInterruptCallback)
|
// r4 = user_data (r4 of VdSetGraphicsInterruptCallback)
|
||||||
|
|
||||||
//gs->SetupInterruptCallback(callback, user_data);
|
gs->SetInterruptCallback(callback, user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -230,6 +230,8 @@ void xeVdEnableRingBufferRPtrWriteBack(uint32_t ptr, uint32_t block_size) {
|
||||||
printf("%.8X", ptr);
|
printf("%.8X", ptr);
|
||||||
// 0x0110343c
|
// 0x0110343c
|
||||||
|
|
||||||
|
// r3 = 0x2B10(d3d?) + 0x3C
|
||||||
|
|
||||||
//((p + 0x3C) & 0x1FFFFFFF) + ((((p + 0x3C) >> 20) + 0x200) & 0x1000)
|
//((p + 0x3C) & 0x1FFFFFFF) + ((((p + 0x3C) >> 20) + 0x200) & 0x1000)
|
||||||
//also 0x3C offset into WriteBacks is PrimaryRingBufferReadIndex
|
//also 0x3C offset into WriteBacks is PrimaryRingBufferReadIndex
|
||||||
//(1:17:38 AM) Rick: .text:8201B348 lwz r11, 0x2B10(r31)
|
//(1:17:38 AM) Rick: .text:8201B348 lwz r11, 0x2B10(r31)
|
||||||
|
|
|
@ -68,6 +68,8 @@ int Run::Setup() {
|
||||||
|
|
||||||
processor_ = shared_ptr<Processor>(new Processor(memory_, backend_));
|
processor_ = shared_ptr<Processor>(new Processor(memory_, backend_));
|
||||||
processor_->set_graphics_system(graphics_system_);
|
processor_->set_graphics_system(graphics_system_);
|
||||||
|
graphics_system_->set_processor(processor_);
|
||||||
|
|
||||||
XEEXPECTZERO(processor_->Setup());
|
XEEXPECTZERO(processor_->Setup());
|
||||||
|
|
||||||
runtime_ = shared_ptr<Runtime>(new Runtime(processor_, XT("")));
|
runtime_ = shared_ptr<Runtime>(new Runtime(processor_, XT("")));
|
||||||
|
|
Loading…
Reference in New Issue