Basic ringbuffer worker. Super hacky, not yet writing back to CPU.

This commit is contained in:
Ben Vanik
2013-06-01 01:13:30 -07:00
parent 3667821be3
commit 5b0fa8f17e
9 changed files with 270 additions and 29 deletions

View File

@@ -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_);
}
}