Basic ringbuffer worker. Super hacky, not yet writing back to CPU.
This commit is contained in:
parent
3667821be3
commit
5b0fa8f17e
|
@ -11,7 +11,7 @@
|
||||||
#include <xenia/gpu/gpu-private.h>
|
#include <xenia/gpu/gpu-private.h>
|
||||||
|
|
||||||
#if XE_PLATFORM(WIN32)
|
#if XE_PLATFORM(WIN32)
|
||||||
#include <xenia/gpu/d3d11/d3d11.h>
|
//#include <xenia/gpu/d3d11/d3d11.h>
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
#include <xenia/gpu/nop/nop.h>
|
#include <xenia/gpu/nop/nop.h>
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#include <xenia/gpu/graphics_system.h>
|
#include <xenia/gpu/graphics_system.h>
|
||||||
|
|
||||||
|
#include <xenia/gpu/ring_buffer_worker.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
using namespace xe::gpu;
|
using namespace xe::gpu;
|
||||||
|
@ -16,12 +18,40 @@ using namespace xe::gpu;
|
||||||
|
|
||||||
GraphicsSystem::GraphicsSystem(const CreationParams* params) {
|
GraphicsSystem::GraphicsSystem(const CreationParams* params) {
|
||||||
memory_ = xe_memory_retain(params->memory);
|
memory_ = xe_memory_retain(params->memory);
|
||||||
|
|
||||||
|
worker_ = new RingBufferWorker(memory_);
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsSystem::~GraphicsSystem() {
|
GraphicsSystem::~GraphicsSystem() {
|
||||||
|
// TODO(benvanik): worker join/etc.
|
||||||
|
delete worker_;
|
||||||
|
|
||||||
xe_memory_release(memory_);
|
xe_memory_release(memory_);
|
||||||
}
|
}
|
||||||
|
|
||||||
xe_memory_ref GraphicsSystem::memory() {
|
xe_memory_ref GraphicsSystem::memory() {
|
||||||
return xe_memory_retain(memory_);
|
return xe_memory_retain(memory_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphicsSystem::InitializeRingBuffer(uint32_t ptr, uint32_t page_count) {
|
||||||
|
worker_->Initialize(ptr, page_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t GraphicsSystem::ReadRegister(uint32_t r) {
|
||||||
|
XELOGGPU("ReadRegister(%.4X)", r);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsSystem::WriteRegister(uint32_t r, uint64_t value) {
|
||||||
|
XELOGGPU("WriteRegister(%.4X, %.8X)", r, value);
|
||||||
|
|
||||||
|
switch (r) {
|
||||||
|
case 0x0714: // CP_RB_WPTR
|
||||||
|
worker_->UpdateWritePointer((uint32_t)value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
XELOGW("Unknown GPU register %.4X write: %.8X", r, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
|
class RingBufferWorker;
|
||||||
|
|
||||||
|
|
||||||
class CreationParams {
|
class CreationParams {
|
||||||
public:
|
public:
|
||||||
|
@ -31,9 +33,13 @@ public:
|
||||||
|
|
||||||
xe_memory_ref memory();
|
xe_memory_ref memory();
|
||||||
|
|
||||||
virtual uint64_t ReadRegister(uint32_t r) = 0;
|
virtual void Initialize() = 0;
|
||||||
virtual void WriteRegister(uint32_t r, uint64_t value) = 0;
|
void InitializeRingBuffer(uint32_t ptr, uint32_t page_count);
|
||||||
|
|
||||||
|
virtual uint64_t ReadRegister(uint32_t r);
|
||||||
|
virtual void WriteRegister(uint32_t r, uint64_t value);
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +50,9 @@ public:
|
||||||
protected:
|
protected:
|
||||||
GraphicsSystem(const CreationParams* params);
|
GraphicsSystem(const CreationParams* params);
|
||||||
|
|
||||||
xe_memory_ref memory_;
|
xe_memory_ref memory_;
|
||||||
|
|
||||||
|
RingBufferWorker* worker_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,11 +24,5 @@ NopGraphicsSystem::NopGraphicsSystem(const CreationParams* params) :
|
||||||
NopGraphicsSystem::~NopGraphicsSystem() {
|
NopGraphicsSystem::~NopGraphicsSystem() {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t NopGraphicsSystem::ReadRegister(uint32_t r) {
|
void NopGraphicsSystem::Initialize() {
|
||||||
XELOGGPU("ReadRegister(%.4X)", r);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NopGraphicsSystem::WriteRegister(uint32_t r, uint64_t value) {
|
|
||||||
XELOGGPU("WriteRegister(%.4X, %.8X)", r, value);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,7 @@ public:
|
||||||
NopGraphicsSystem(const CreationParams* params);
|
NopGraphicsSystem(const CreationParams* params);
|
||||||
virtual ~NopGraphicsSystem();
|
virtual ~NopGraphicsSystem();
|
||||||
|
|
||||||
virtual uint64_t ReadRegister(uint32_t r);
|
virtual void Initialize();
|
||||||
virtual void WriteRegister(uint32_t r, uint64_t value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xenia/gpu/ring_buffer_worker.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace xe;
|
||||||
|
using namespace xe::gpu;
|
||||||
|
|
||||||
|
|
||||||
|
RingBufferWorker::RingBufferWorker(xe_memory_ref memory) :
|
||||||
|
memory_(memory) {
|
||||||
|
running_ = true;
|
||||||
|
read_ptr_index_event_ = CreateEvent(
|
||||||
|
NULL, FALSE, FALSE, NULL);
|
||||||
|
write_ptr_index_event_ = CreateEvent(
|
||||||
|
NULL, FALSE, FALSE, NULL);
|
||||||
|
|
||||||
|
thread_ = xe_thread_create(
|
||||||
|
"RingBufferWorker",
|
||||||
|
(xe_thread_callback)ThreadStartThunk, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
RingBufferWorker::~RingBufferWorker() {
|
||||||
|
// TODO(benvanik): thread join.
|
||||||
|
running_ = false;
|
||||||
|
SetEvent(write_ptr_index_event_);
|
||||||
|
xe_thread_release(thread_);
|
||||||
|
CloseHandle(write_ptr_index_event_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RingBufferWorker::Initialize(uint32_t ptr, uint32_t page_count) {
|
||||||
|
primary_buffer_ptr_ = ptr;
|
||||||
|
primary_buffer_size_ = page_count * 4 * 1024;
|
||||||
|
read_ptr_index_ = 0;
|
||||||
|
|
||||||
|
xe_thread_start(thread_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RingBufferWorker::UpdateWritePointer(uint32_t value) {
|
||||||
|
write_ptr_index_ = value;
|
||||||
|
SetEvent(write_ptr_index_event_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RingBufferWorker::ThreadStart() {
|
||||||
|
uint8_t* p = xe_memory_addr(memory_);
|
||||||
|
|
||||||
|
while (running_) {
|
||||||
|
if (write_ptr_index_ == 0xBAADF00D ||
|
||||||
|
read_ptr_index_ == write_ptr_index_) {
|
||||||
|
// Wait for the command buffer pointer to move.
|
||||||
|
// TODO(benvanik): only wait for a bit and check running_.
|
||||||
|
WaitForSingleObject(write_ptr_index_event_, INFINITE);
|
||||||
|
if (!running_) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (read_ptr_index_ == write_ptr_index_) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the new commands.
|
||||||
|
XELOGGPU("Ring buffer thread work");
|
||||||
|
|
||||||
|
#define READ_UINT32() \
|
||||||
|
XEGETUINT32BE(p + primary_buffer_ptr_ + read_ptr_index_ * 4); \
|
||||||
|
read_ptr_index_ = (read_ptr_index_ + 1) % (primary_buffer_size_ / 4);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
uint32_t command = READ_UINT32();
|
||||||
|
XELOGGPU("Command(%.8X)", command);
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case 0xC0114800:
|
||||||
|
// Init packet.
|
||||||
|
// Will have 18-19 ops after it. Maybe.
|
||||||
|
for (int n = 0; n < 18; n++) {
|
||||||
|
READ_UINT32();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0xC0013F00:
|
||||||
|
// Kick segment.
|
||||||
|
uint32_t segment_ptr = READ_UINT32();
|
||||||
|
uint32_t length = READ_UINT32();
|
||||||
|
XELOGGPU("Command(%.8X): kick segment %.8X (%db)",
|
||||||
|
command, segment_ptr, length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_ptr_index_ == write_ptr_index_) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetEvent(read_ptr_index_event_);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_GPU_RING_BUFFER_WORKER_H_
|
||||||
|
#define XENIA_GPU_RING_BUFFER_WORKER_H_
|
||||||
|
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace gpu {
|
||||||
|
|
||||||
|
|
||||||
|
class RingBufferWorker {
|
||||||
|
public:
|
||||||
|
RingBufferWorker(xe_memory_ref memory);
|
||||||
|
virtual ~RingBufferWorker();
|
||||||
|
|
||||||
|
xe_memory_ref memory();
|
||||||
|
|
||||||
|
void Initialize(uint32_t ptr, uint32_t page_count);
|
||||||
|
|
||||||
|
void UpdateWritePointer(uint32_t value);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void ThreadStartThunk(RingBufferWorker* this_ptr) {
|
||||||
|
this_ptr->ThreadStart();
|
||||||
|
}
|
||||||
|
void ThreadStart();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
xe_memory_ref memory_;
|
||||||
|
xe_thread_ref thread_;
|
||||||
|
bool running_;
|
||||||
|
HANDLE read_ptr_index_event_;
|
||||||
|
HANDLE write_ptr_index_event_;
|
||||||
|
|
||||||
|
uint32_t primary_buffer_ptr_;
|
||||||
|
uint32_t primary_buffer_size_;
|
||||||
|
uint32_t secondary_buffer_ptr_;
|
||||||
|
uint32_t secondary_buffer_size_;
|
||||||
|
uint32_t read_ptr_index_;
|
||||||
|
uint32_t write_ptr_index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace gpu
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_GPU_RING_BUFFER_WORKER_H_
|
|
@ -6,6 +6,8 @@
|
||||||
'gpu.h',
|
'gpu.h',
|
||||||
'graphics_system.cc',
|
'graphics_system.cc',
|
||||||
'graphics_system.h',
|
'graphics_system.h',
|
||||||
|
'ring_buffer_worker.cc',
|
||||||
|
'ring_buffer_worker.h',
|
||||||
],
|
],
|
||||||
|
|
||||||
'includes': [
|
'includes': [
|
||||||
|
@ -15,7 +17,7 @@
|
||||||
'conditions': [
|
'conditions': [
|
||||||
['OS == "win"', {
|
['OS == "win"', {
|
||||||
'includes': [
|
'includes': [
|
||||||
'd3d11/sources.gypi',
|
#'d3d11/sources.gypi',
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
],
|
],
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <xenia/kernel/modules/xboxkrnl/xboxkrnl_video.h>
|
#include <xenia/kernel/modules/xboxkrnl/xboxkrnl_video.h>
|
||||||
|
|
||||||
|
#include <xenia/gpu/gpu.h>
|
||||||
#include <xenia/kernel/shim_utils.h>
|
#include <xenia/kernel/shim_utils.h>
|
||||||
#include <xenia/kernel/modules/xboxkrnl/kernel_state.h>
|
#include <xenia/kernel/modules/xboxkrnl/kernel_state.h>
|
||||||
#include <xenia/kernel/modules/xboxkrnl/xboxkrnl_private.h>
|
#include <xenia/kernel/modules/xboxkrnl/xboxkrnl_private.h>
|
||||||
|
@ -16,6 +17,7 @@
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
|
using namespace xe::gpu;
|
||||||
using namespace xe::kernel;
|
using namespace xe::kernel;
|
||||||
using namespace xe::kernel::xboxkrnl;
|
using namespace xe::kernel::xboxkrnl;
|
||||||
|
|
||||||
|
@ -83,10 +85,19 @@ SHIM_CALL VdQueryVideoMode_shim(
|
||||||
|
|
||||||
void xeVdInitializeEngines(uint32_t unk0, uint32_t callback, uint32_t unk1,
|
void xeVdInitializeEngines(uint32_t unk0, uint32_t callback, uint32_t unk1,
|
||||||
uint32_t unk2_ptr, uint32_t unk3_ptr) {
|
uint32_t unk2_ptr, uint32_t unk3_ptr) {
|
||||||
|
KernelState* state = shared_kernel_state_;
|
||||||
|
XEASSERTNOTNULL(state);
|
||||||
|
GraphicsSystem* gs = state->processor()->graphics_system().get();
|
||||||
|
if (!gs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// r3 = 0x4F810000
|
// r3 = 0x4F810000
|
||||||
// r4 = function ptr (ready callback?)
|
// r4 = function ptr (ready callback?)
|
||||||
// r5 = 0
|
// r5 = 0
|
||||||
// r6/r7 = some binary data in .data
|
// r6/r7 = some binary data in .data
|
||||||
|
|
||||||
|
gs->Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,9 +118,18 @@ SHIM_CALL VdInitializeEngines_shim(
|
||||||
|
|
||||||
|
|
||||||
void xeVdSetGraphicsInterruptCallback(uint32_t callback, uint32_t user_data) {
|
void xeVdSetGraphicsInterruptCallback(uint32_t callback, uint32_t user_data) {
|
||||||
|
KernelState* state = shared_kernel_state_;
|
||||||
|
XEASSERTNOTNULL(state);
|
||||||
|
GraphicsSystem* gs = state->processor()->graphics_system().get();
|
||||||
|
if (!gs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// callback takes 2 params
|
// callback takes 2 params
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,21 +146,36 @@ SHIM_CALL VdSetGraphicsInterruptCallback_shim(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// VdInitializeRingBuffer
|
void xeVdInitializeRingBuffer(uint32_t ptr, uint32_t page_count) {
|
||||||
// r3 = result of MmGetPhysicalAddress
|
KernelState* state = shared_kernel_state_;
|
||||||
// r4 = number of pages? page size?
|
XEASSERTNOTNULL(state);
|
||||||
// 0x8000 -> cntlzw=16 -> 0x1C - 16 = 12
|
GraphicsSystem* gs = state->processor()->graphics_system().get();
|
||||||
// ring_buffer_t {
|
if (!gs) {
|
||||||
// uint 0
|
return;
|
||||||
// uint buffer_0_size
|
}
|
||||||
// uint buffer_0_ptr
|
|
||||||
// uint buffer_1_size
|
// r3 = result of MmGetPhysicalAddress
|
||||||
// uint buffer_1_ptr
|
// r4 = number of pages? page size?
|
||||||
// uint segment_count -- 32 common
|
// 0x8000 -> cntlzw=16 -> 0x1C - 16 = 12
|
||||||
// }
|
// Buffer pointers are from MmAllocatePhysicalMemory with WRITE_COMBINE.
|
||||||
// Buffer pointers are from MmAllocatePhysicalMemory with WRITE_COMBINE.
|
// Sizes could be zero? XBLA games seem to do this. Default sizes?
|
||||||
// Sizes could be zero? XBLA games seem to do this. Default sizes?
|
// D3D does size / region_count - must be > 1024
|
||||||
// D3D does size / region_count - must be > 1024
|
|
||||||
|
gs->InitializeRingBuffer(ptr, page_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SHIM_CALL VdInitializeRingBuffer_shim(
|
||||||
|
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||||
|
uint32_t ptr = SHIM_GET_ARG_32(0);
|
||||||
|
uint32_t page_count = SHIM_GET_ARG_32(1);
|
||||||
|
|
||||||
|
XELOGD(
|
||||||
|
"VdInitializeRingBuffer(%.8X, %.8X)",
|
||||||
|
ptr, page_count);
|
||||||
|
|
||||||
|
xeVdInitializeRingBuffer(ptr, page_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// void VdEnableRingBufferRPtrWriteBack
|
// void VdEnableRingBufferRPtrWriteBack
|
||||||
|
@ -148,6 +183,17 @@ SHIM_CALL VdSetGraphicsInterruptCallback_shim(
|
||||||
// r4 = 6, usually --- <=19
|
// r4 = 6, usually --- <=19
|
||||||
// Same value used to calculate the pointer is later written to
|
// Same value used to calculate the pointer is later written to
|
||||||
// Maybe GPU-memory relative?
|
// Maybe GPU-memory relative?
|
||||||
|
SHIM_CALL VdEnableRingBufferRPtrWriteBack_shim(
|
||||||
|
xe_ppc_state_t* ppc_state, KernelState* state) {
|
||||||
|
uint32_t ptr = SHIM_GET_ARG_32(0);
|
||||||
|
uint32_t unk1 = SHIM_GET_ARG_32(1);
|
||||||
|
|
||||||
|
XELOGD(
|
||||||
|
"VdEnableRingBufferRPtrWriteBack(%.8X, %.8X)",
|
||||||
|
ptr, unk1);
|
||||||
|
|
||||||
|
// TODO(benvanik): something?
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// VdSetSystemCommandBufferGpuIdentifierAddress
|
// VdSetSystemCommandBufferGpuIdentifierAddress
|
||||||
|
@ -176,6 +222,8 @@ void xe::kernel::xboxkrnl::RegisterVideoExports(
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdQueryVideoMode, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", VdQueryVideoMode, state);
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdInitializeEngines, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", VdInitializeEngines, state);
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", VdSetGraphicsInterruptCallback, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", VdSetGraphicsInterruptCallback, state);
|
||||||
|
SHIM_SET_MAPPING("xboxkrnl.exe", VdInitializeRingBuffer, state);
|
||||||
|
SHIM_SET_MAPPING("xboxkrnl.exe", VdEnableRingBufferRPtrWriteBack, state);
|
||||||
|
|
||||||
xe_memory_ref memory = state->memory();
|
xe_memory_ref memory = state->memory();
|
||||||
uint8_t* mem = xe_memory_addr(memory);
|
uint8_t* mem = xe_memory_addr(memory);
|
||||||
|
|
Loading…
Reference in New Issue