Adding vblank interrupt.

This commit is contained in:
Ben Vanik 2013-09-25 00:46:09 -07:00
parent 998467ce05
commit 91f62918f6
8 changed files with 116 additions and 7 deletions

View File

@ -45,7 +45,8 @@ namespace {
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);
backend_ = backend;
@ -64,6 +65,9 @@ Processor::~Processor() {
}
modules_.clear();
DeallocThread(interrupt_thread_state_);
xe_mutex_free(interrupt_thread_lock_);
delete jit_;
delete sym_table_;
@ -98,6 +102,9 @@ void Processor::set_export_resolver(
int Processor::Setup() {
XEASSERTNULL(jit_);
interrupt_thread_lock_ = xe_mutex_alloc(10000);
interrupt_thread_state_ = AllocThread(16 * 1024, 0, 0);
sym_table_ = new SymbolTable();
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];
}
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) {
// Attempt to grab the function symbol from the global lookup table.
FunctionSymbol* fn_symbol = sym_table_->GetFunction(address);

View File

@ -56,10 +56,14 @@ public:
ThreadState* AllocThread(uint32_t stack_size, uint32_t thread_state_address,
uint32_t thread_id);
void DeallocThread(ThreadState* thread_state);
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 arg1);
uint64_t ExecuteInterrupt(uint32_t address, uint64_t arg0, uint64_t arg1);
sdb::FunctionSymbol* GetFunction(uint32_t address);
void* GetFunctionPointer(uint32_t address);
@ -72,6 +76,9 @@ private:
sdb::SymbolTable* sym_table_;
JIT* jit_;
std::vector<ExecModule*> modules_;
xe_mutex_t* interrupt_thread_lock_;
ThreadState* interrupt_thread_state_;
};

View File

@ -8,7 +8,8 @@
*/
#include <xenia/gpu/graphics_system.h>
#include <xenia/cpu/processor.h>
#include <xenia/gpu/ring_buffer_worker.h>
@ -16,7 +17,8 @@ using namespace xe;
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);
worker_ = new RingBufferWorker(memory_);
@ -33,6 +35,21 @@ xe_memory_ref GraphicsSystem::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) {
worker_->Initialize(ptr, page_count);
}
@ -44,6 +61,12 @@ void GraphicsSystem::EnableReadPointerWriteBack(uint32_t ptr,
uint64_t GraphicsSystem::ReadRegister(uint32_t r) {
XELOGGPU("ReadRegister(%.4X)", r);
switch (r) {
case 0x6544: // ? vblank pending?
return 1;
}
return 0;
}
@ -60,3 +83,12 @@ void GraphicsSystem::WriteRegister(uint32_t r, uint64_t value) {
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_);
}

View File

@ -13,6 +13,13 @@
#include <xenia/core.h>
namespace xe {
namespace cpu {
class Processor;
} // namespace cpu
} // namespace xe
namespace xe {
namespace gpu {
@ -32,19 +39,25 @@ public:
virtual ~GraphicsSystem();
xe_memory_ref memory();
shared_ptr<cpu::Processor> processor();
void set_processor(shared_ptr<cpu::Processor> processor);
virtual void Initialize() = 0;
void SetInterruptCallback(uint32_t callback, uint32_t user_data);
void InitializeRingBuffer(uint32_t ptr, uint32_t page_count);
void EnableReadPointerWriteBack(uint32_t ptr, uint32_t block_size);
virtual uint64_t ReadRegister(uint32_t r);
virtual void WriteRegister(uint32_t r, uint64_t value);
void DispatchInterruptCallback();
public:
static uint64_t ReadRegisterThunk(GraphicsSystem* this_ptr, uint32_t 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);
}
@ -52,8 +65,12 @@ protected:
GraphicsSystem(const CreationParams* params);
xe_memory_ref memory_;
shared_ptr<cpu::Processor> processor_;
RingBufferWorker* worker_;
uint32_t interrupt_callback_;
uint32_t interrupt_callback_data_;
};

View File

@ -17,12 +17,41 @@ using namespace xe::gpu;
using namespace xe::gpu::nop;
namespace {
void __stdcall NopGraphicsSystemVsyncCallback(NopGraphicsSystem* gs, BOOLEAN) {
gs->DispatchInterruptCallback();
}
}
NopGraphicsSystem::NopGraphicsSystem(const CreationParams* params) :
GraphicsSystem(params) {
GraphicsSystem(params),
timer_queue_(NULL),
vsync_timer_(NULL) {
}
NopGraphicsSystem::~NopGraphicsSystem() {
if (vsync_timer_) {
DeleteTimerQueueTimer(timer_queue_, vsync_timer_, NULL);
}
if (timer_queue_) {
DeleteTimerQueueEx(timer_queue_, NULL);
}
}
void NopGraphicsSystem::Initialize() {
XEASSERTNULL(timer_queue_);
XEASSERTNULL(vsync_timer_);
timer_queue_ = CreateTimerQueue();
CreateTimerQueueTimer(
&vsync_timer_,
timer_queue_,
(WAITORTIMERCALLBACK)NopGraphicsSystemVsyncCallback,
this,
16,
100,
WT_EXECUTEINTIMERTHREAD);
}

View File

@ -27,6 +27,10 @@ public:
virtual ~NopGraphicsSystem();
virtual void Initialize();
private:
HANDLE timer_queue_;
HANDLE vsync_timer_;
};

View File

@ -130,7 +130,7 @@ void xeVdInitializeEngines(uint32_t unk0, uint32_t callback, uint32_t unk1,
}
// r3 = 0x4F810000
// r4 = function ptr (ready callback?)
// r4 = function ptr (cleanup callback?)
// r5 = 0
// 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
// 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);
// 0x0110343c
// r3 = 0x2B10(d3d?) + 0x3C
//((p + 0x3C) & 0x1FFFFFFF) + ((((p + 0x3C) >> 20) + 0x200) & 0x1000)
//also 0x3C offset into WriteBacks is PrimaryRingBufferReadIndex
//(1:17:38 AM) Rick: .text:8201B348 lwz r11, 0x2B10(r31)

View File

@ -68,6 +68,8 @@ int Run::Setup() {
processor_ = shared_ptr<Processor>(new Processor(memory_, backend_));
processor_->set_graphics_system(graphics_system_);
graphics_system_->set_processor(processor_);
XEEXPECTZERO(processor_->Setup());
runtime_ = shared_ptr<Runtime>(new Runtime(processor_, XT("")));