Starting to drive command buffer actions down to a graphics driver.
This commit is contained in:
parent
371075f154
commit
651954ccae
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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/graphics_driver.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace xe;
|
||||||
|
using namespace xe::gpu;
|
||||||
|
|
||||||
|
|
||||||
|
GraphicsDriver::GraphicsDriver(xe_memory_ref memory) {
|
||||||
|
memory_ = xe_memory_retain(memory);
|
||||||
|
|
||||||
|
memset(®ister_file_, 0, sizeof(register_file_));
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsDriver::~GraphicsDriver() {
|
||||||
|
xe_memory_release(memory_);
|
||||||
|
}
|
||||||
|
|
||||||
|
xe_memory_ref GraphicsDriver::memory() {
|
||||||
|
return xe_memory_retain(memory_);
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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_GRAPHICS_DRIVER_H_
|
||||||
|
#define XENIA_GPU_GRAPHICS_DRIVER_H_
|
||||||
|
|
||||||
|
#include <xenia/core.h>
|
||||||
|
#include <xenia/gpu/xenos/registers.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace gpu {
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
XE_GPU_SHADER_TYPE_VERTEX = 0x00,
|
||||||
|
XE_GPU_SHADER_TYPE_PIXEL = 0x01,
|
||||||
|
} XE_GPU_SHADER_TYPE;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
XE_GPU_INVALIDATE_MASK_VERTEX_SHADER = 1 << 8,
|
||||||
|
XE_GPU_INVALIDATE_MASK_PIXEL_SHADER = 1 << 9,
|
||||||
|
|
||||||
|
XE_GPU_INVALIDATE_MASK_ALL = 0x7FFF,
|
||||||
|
} XE_GPU_INVALIDATE_MASK;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
XE_GPU_PRIMITIVE_TYPE_POINT_LIST = 0x01,
|
||||||
|
XE_GPU_PRIMITIVE_TYPE_LINE_LIST = 0x02,
|
||||||
|
XE_GPU_PRIMITIVE_TYPE_LINE_STRIP = 0x03,
|
||||||
|
XE_GPU_PRIMITIVE_TYPE_TRIANGLE_LIST = 0x04,
|
||||||
|
XE_GPU_PRIMITIVE_TYPE_TRIANGLE_FAN = 0x05,
|
||||||
|
XE_GPU_PRIMITIVE_TYPE_TRIANGLE_STRIP = 0x06,
|
||||||
|
XE_GPU_PRIMITIVE_TYPE_UNKNOWN_07 = 0x07,
|
||||||
|
XE_GPU_PRIMITIVE_TYPE_RECTANGLE_LIST = 0x08,
|
||||||
|
XE_GPU_PRIMITIVE_TYPE_LINE_LOOP = 0x0C,
|
||||||
|
} XE_GPU_PRIMITIVE_TYPE;
|
||||||
|
|
||||||
|
|
||||||
|
class GraphicsDriver {
|
||||||
|
public:
|
||||||
|
virtual ~GraphicsDriver();
|
||||||
|
|
||||||
|
xe_memory_ref memory();
|
||||||
|
xenos::RegisterFile* register_file() { return ®ister_file_; };
|
||||||
|
|
||||||
|
virtual void Initialize() = 0;
|
||||||
|
|
||||||
|
virtual void InvalidateState(
|
||||||
|
uint32_t mask) = 0;
|
||||||
|
virtual void SetShader(
|
||||||
|
XE_GPU_SHADER_TYPE type,
|
||||||
|
uint32_t address,
|
||||||
|
uint32_t start,
|
||||||
|
uint32_t size_dwords) = 0;
|
||||||
|
virtual void DrawIndexed(
|
||||||
|
XE_GPU_PRIMITIVE_TYPE prim_type,
|
||||||
|
uint32_t index_count) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GraphicsDriver(xe_memory_ref memory);
|
||||||
|
|
||||||
|
xe_memory_ref memory_;
|
||||||
|
|
||||||
|
xenos::RegisterFile register_file_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace gpu
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_GPU_GRAPHICS_DRIVER_H_
|
|
@ -8,13 +8,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xenia/gpu/graphics_system.h>
|
#include <xenia/gpu/graphics_system.h>
|
||||||
|
|
||||||
#include <xenia/cpu/processor.h>
|
#include <xenia/cpu/processor.h>
|
||||||
|
#include <xenia/gpu/graphics_driver.h>
|
||||||
#include <xenia/gpu/ring_buffer_worker.h>
|
#include <xenia/gpu/ring_buffer_worker.h>
|
||||||
|
#include <xenia/gpu/xenos/registers.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
using namespace xe::gpu;
|
using namespace xe::gpu;
|
||||||
|
using namespace xe::gpu::xenos;
|
||||||
|
|
||||||
|
|
||||||
GraphicsSystem::GraphicsSystem(const CreationParams* params) :
|
GraphicsSystem::GraphicsSystem(const CreationParams* params) :
|
||||||
|
@ -22,6 +25,9 @@ GraphicsSystem::GraphicsSystem(const CreationParams* params) :
|
||||||
memory_ = xe_memory_retain(params->memory);
|
memory_ = xe_memory_retain(params->memory);
|
||||||
|
|
||||||
worker_ = new RingBufferWorker(memory_);
|
worker_ = new RingBufferWorker(memory_);
|
||||||
|
|
||||||
|
// Set during Initialize();
|
||||||
|
driver_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphicsSystem::~GraphicsSystem() {
|
GraphicsSystem::~GraphicsSystem() {
|
||||||
|
@ -51,7 +57,8 @@ void GraphicsSystem::SetInterruptCallback(uint32_t callback,
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
XEASSERTNOTNULL(driver_);
|
||||||
|
worker_->Initialize(driver_, ptr, page_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsSystem::EnableReadPointerWriteBack(uint32_t ptr,
|
void GraphicsSystem::EnableReadPointerWriteBack(uint32_t ptr,
|
||||||
|
@ -62,26 +69,31 @@ 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);
|
||||||
|
|
||||||
|
RegisterFile* regs = driver_->register_file();
|
||||||
|
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case 0x6544: // ? vblank pending?
|
case 0x6544: // ? vblank pending?
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
XEASSERT(r >= 0 && r < kXEGpuRegisterCount);
|
||||||
|
return regs->values[r].u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsSystem::WriteRegister(uint32_t r, uint64_t value) {
|
void GraphicsSystem::WriteRegister(uint32_t r, uint64_t value) {
|
||||||
XELOGGPU("WriteRegister(%.4X, %.8X)", r, value);
|
XELOGGPU("WriteRegister(%.4X, %.8X)", r, value);
|
||||||
|
|
||||||
|
RegisterFile* regs = driver_->register_file();
|
||||||
|
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case 0x0714: // CP_RB_WPTR
|
case 0x0714: // CP_RB_WPTR
|
||||||
worker_->UpdateWritePointer((uint32_t)value);
|
worker_->UpdateWritePointer((uint32_t)value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
XELOGW("Unknown GPU register %.4X write: %.8X", r, value);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XEASSERT(r >= 0 && r < kXEGpuRegisterCount);
|
||||||
|
XELOGW("Unknown GPU register %.4X write: %.8X", r, value);
|
||||||
|
regs->values[r].u32 = (uint32_t)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsSystem::DispatchInterruptCallback() {
|
void GraphicsSystem::DispatchInterruptCallback() {
|
||||||
|
|
|
@ -13,16 +13,17 @@
|
||||||
#include <xenia/core.h>
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
class Processor;
|
class Processor;
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
|
class GraphicsDriver;
|
||||||
class RingBufferWorker;
|
class RingBufferWorker;
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,6 +54,8 @@ public:
|
||||||
void DispatchInterruptCallback();
|
void DispatchInterruptCallback();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// TODO(benvanik): have an HasRegisterHandler() so that the JIT can
|
||||||
|
// just poke the register file directly.
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -67,6 +70,7 @@ protected:
|
||||||
xe_memory_ref memory_;
|
xe_memory_ref memory_;
|
||||||
shared_ptr<cpu::Processor> processor_;
|
shared_ptr<cpu::Processor> processor_;
|
||||||
|
|
||||||
|
GraphicsDriver* driver_;
|
||||||
RingBufferWorker* worker_;
|
RingBufferWorker* worker_;
|
||||||
|
|
||||||
uint32_t interrupt_callback_;
|
uint32_t interrupt_callback_;
|
||||||
|
|
|
@ -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. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xenia/gpu/nop/nop_graphics_driver.h>
|
||||||
|
|
||||||
|
#include <xenia/gpu/gpu-private.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace xe;
|
||||||
|
using namespace xe::gpu;
|
||||||
|
using namespace xe::gpu::nop;
|
||||||
|
|
||||||
|
|
||||||
|
NopGraphicsDriver::NopGraphicsDriver(xe_memory_ref memory) :
|
||||||
|
GraphicsDriver(memory) {
|
||||||
|
}
|
||||||
|
|
||||||
|
NopGraphicsDriver::~NopGraphicsDriver() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void NopGraphicsDriver::Initialize() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void NopGraphicsDriver::InvalidateState(
|
||||||
|
uint32_t mask) {
|
||||||
|
if (mask == XE_GPU_INVALIDATE_MASK_ALL) {
|
||||||
|
XELOGGPU("NOP: (invalidate all)");
|
||||||
|
}
|
||||||
|
if (mask & XE_GPU_INVALIDATE_MASK_VERTEX_SHADER) {
|
||||||
|
XELOGGPU("NOP: invalidate vertex shader");
|
||||||
|
}
|
||||||
|
if (mask & XE_GPU_INVALIDATE_MASK_PIXEL_SHADER) {
|
||||||
|
XELOGGPU("NOP: invalidate pixel shader");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NopGraphicsDriver::SetShader(
|
||||||
|
XE_GPU_SHADER_TYPE type,
|
||||||
|
uint32_t address,
|
||||||
|
uint32_t start,
|
||||||
|
uint32_t size_dwords) {
|
||||||
|
XELOGGPU("NOP: set shader %d at %0.8X (%db)",
|
||||||
|
type, address, size_dwords * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NopGraphicsDriver::DrawIndexed(
|
||||||
|
XE_GPU_PRIMITIVE_TYPE prim_type,
|
||||||
|
uint32_t index_count) {
|
||||||
|
XELOGGPU("NOP: draw indexed %d (%d indicies)",
|
||||||
|
prim_type, index_count);
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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_NOP_NOP_GRAPHICS_DRIVER_H_
|
||||||
|
#define XENIA_GPU_NOP_NOP_GRAPHICS_DRIVER_H_
|
||||||
|
|
||||||
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
#include <xenia/gpu/graphics_driver.h>
|
||||||
|
#include <xenia/gpu/nop/nop-private.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace gpu {
|
||||||
|
namespace nop {
|
||||||
|
|
||||||
|
|
||||||
|
class NopGraphicsDriver : public GraphicsDriver {
|
||||||
|
public:
|
||||||
|
NopGraphicsDriver(xe_memory_ref memory);
|
||||||
|
virtual ~NopGraphicsDriver();
|
||||||
|
|
||||||
|
virtual void Initialize();
|
||||||
|
|
||||||
|
virtual void InvalidateState(
|
||||||
|
uint32_t mask);
|
||||||
|
virtual void SetShader(
|
||||||
|
XE_GPU_SHADER_TYPE type,
|
||||||
|
uint32_t address,
|
||||||
|
uint32_t start,
|
||||||
|
uint32_t size_dwords);
|
||||||
|
virtual void DrawIndexed(
|
||||||
|
XE_GPU_PRIMITIVE_TYPE prim_type,
|
||||||
|
uint32_t index_count);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace nop
|
||||||
|
} // namespace gpu
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_GPU_NOP_NOP_GRAPHICS_DRIVER_H_
|
|
@ -10,6 +10,7 @@
|
||||||
#include <xenia/gpu/nop/nop_graphics_system.h>
|
#include <xenia/gpu/nop/nop_graphics_system.h>
|
||||||
|
|
||||||
#include <xenia/gpu/gpu-private.h>
|
#include <xenia/gpu/gpu-private.h>
|
||||||
|
#include <xenia/gpu/nop/nop_graphics_driver.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
|
@ -42,6 +43,9 @@ NopGraphicsSystem::~NopGraphicsSystem() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NopGraphicsSystem::Initialize() {
|
void NopGraphicsSystem::Initialize() {
|
||||||
|
XEASSERTNULL(driver_);
|
||||||
|
driver_ = new NopGraphicsDriver(memory_);
|
||||||
|
|
||||||
XEASSERTNULL(timer_queue_);
|
XEASSERTNULL(timer_queue_);
|
||||||
XEASSERTNULL(vsync_timer_);
|
XEASSERTNULL(vsync_timer_);
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
'nop-private.h',
|
'nop-private.h',
|
||||||
'nop.cc',
|
'nop.cc',
|
||||||
'nop.h',
|
'nop.h',
|
||||||
|
'nop_graphics_driver.cc',
|
||||||
|
'nop_graphics_driver.h',
|
||||||
'nop_graphics_system.cc',
|
'nop_graphics_system.cc',
|
||||||
'nop_graphics_system.h',
|
'nop_graphics_system.h',
|
||||||
],
|
],
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include <xenia/gpu/ring_buffer_worker.h>
|
#include <xenia/gpu/ring_buffer_worker.h>
|
||||||
|
|
||||||
|
#include <xenia/gpu/graphics_driver.h>
|
||||||
#include <xenia/gpu/xenos/packets.h>
|
#include <xenia/gpu/xenos/packets.h>
|
||||||
#include <xenia/gpu/xenos/registers.h>
|
#include <xenia/gpu/xenos/registers.h>
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ using namespace xe::gpu::xenos;
|
||||||
|
|
||||||
|
|
||||||
RingBufferWorker::RingBufferWorker(xe_memory_ref memory) :
|
RingBufferWorker::RingBufferWorker(xe_memory_ref memory) :
|
||||||
memory_(memory) {
|
memory_(memory), driver_(0) {
|
||||||
running_ = true;
|
running_ = true;
|
||||||
write_ptr_index_event_ = CreateEvent(
|
write_ptr_index_event_ = CreateEvent(
|
||||||
NULL, FALSE, FALSE, NULL);
|
NULL, FALSE, FALSE, NULL);
|
||||||
|
@ -37,7 +38,9 @@ RingBufferWorker::~RingBufferWorker() {
|
||||||
CloseHandle(write_ptr_index_event_);
|
CloseHandle(write_ptr_index_event_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RingBufferWorker::Initialize(uint32_t ptr, uint32_t page_count) {
|
void RingBufferWorker::Initialize(GraphicsDriver* driver,
|
||||||
|
uint32_t ptr, uint32_t page_count) {
|
||||||
|
driver_ = driver;
|
||||||
primary_buffer_ptr_ = ptr;
|
primary_buffer_ptr_ = ptr;
|
||||||
primary_buffer_size_ = page_count * 4 * 1024;
|
primary_buffer_size_ = page_count * 4 * 1024;
|
||||||
read_ptr_index_ = 0;
|
read_ptr_index_ = 0;
|
||||||
|
@ -100,6 +103,7 @@ void RingBufferWorker::ThreadStart() {
|
||||||
|
|
||||||
void RingBufferWorker::ExecuteSegment(uint32_t ptr, uint32_t length) {
|
void RingBufferWorker::ExecuteSegment(uint32_t ptr, uint32_t length) {
|
||||||
uint8_t* p = xe_memory_addr(memory_);
|
uint8_t* p = xe_memory_addr(memory_);
|
||||||
|
RegisterFile* regs = driver_->register_file();
|
||||||
|
|
||||||
// Adjust pointer base.
|
// Adjust pointer base.
|
||||||
ptr = (primary_buffer_ptr_ & ~0x1FFFFFFF) | (ptr & 0x1FFFFFFF);
|
ptr = (primary_buffer_ptr_ & ~0x1FFFFFFF) | (ptr & 0x1FFFFFFF);
|
||||||
|
@ -138,7 +142,10 @@ void RingBufferWorker::ExecuteSegment(uint32_t ptr, uint32_t length) {
|
||||||
const char* reg_name = xenos::GetRegisterName(base_index + m);
|
const char* reg_name = xenos::GetRegisterName(base_index + m);
|
||||||
XELOGGPU(" %.8X -> %.4X %s", reg_data, base_index + m,
|
XELOGGPU(" %.8X -> %.4X %s", reg_data, base_index + m,
|
||||||
reg_name ? reg_name : "");
|
reg_name ? reg_name : "");
|
||||||
// TODO(benvanik): process register writes.
|
// TODO(benvanik): exec write handler (if special).
|
||||||
|
if (base_index + m < kXEGpuRegisterCount) {
|
||||||
|
regs->values[base_index + m].u32 = reg_data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
n += 1 + count;
|
n += 1 + count;
|
||||||
}
|
}
|
||||||
|
@ -158,7 +165,14 @@ void RingBufferWorker::ExecuteSegment(uint32_t ptr, uint32_t length) {
|
||||||
reg_name_1 ? reg_name_1 : "");
|
reg_name_1 ? reg_name_1 : "");
|
||||||
XELOGGPU(" %.8X -> %.4X %s", reg_data_2, reg_index_2,
|
XELOGGPU(" %.8X -> %.4X %s", reg_data_2, reg_index_2,
|
||||||
reg_name_2 ? reg_name_2 : "");
|
reg_name_2 ? reg_name_2 : "");
|
||||||
// TODO(benvanik): process register writes.
|
// TODO(benvanik): exec write handler (if special).
|
||||||
|
if (reg_index_1 < kXEGpuRegisterCount) {
|
||||||
|
regs->values[reg_index_1].u32 = reg_data_1;
|
||||||
|
}
|
||||||
|
if (reg_index_2 < kXEGpuRegisterCount) {
|
||||||
|
regs->values[reg_index_2].u32 = reg_data_2;
|
||||||
|
}
|
||||||
|
|
||||||
n += 1 + 2;
|
n += 1 + 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -242,56 +256,31 @@ void RingBufferWorker::ExecuteSegment(uint32_t ptr, uint32_t length) {
|
||||||
// initiate fetch of index buffer and draw
|
// initiate fetch of index buffer and draw
|
||||||
{
|
{
|
||||||
XELOGGPU("Packet(%.8X): PM4_DRAW_INDX", packet);
|
XELOGGPU("Packet(%.8X): PM4_DRAW_INDX", packet);
|
||||||
|
LOG_DATA(count);
|
||||||
// d0 = viz query info
|
// d0 = viz query info
|
||||||
uint32_t d0 = XEGETUINT32BE(packet_base + 1 * 4);
|
uint32_t d0 = XEGETUINT32BE(packet_base + 1 * 4);
|
||||||
uint32_t d1 = XEGETUINT32BE(packet_base + 2 * 4);
|
uint32_t d1 = XEGETUINT32BE(packet_base + 2 * 4);
|
||||||
uint32_t index_count = d1 >> 16;
|
uint32_t index_count = d1 >> 16;
|
||||||
uint32_t prim_type = d1 & 0x3F;
|
uint32_t prim_type = d1 & 0x3F;
|
||||||
// Not sure what the other bits mean - 'SrcSel=AutoIndex'?
|
// Not sure what the other bits mean - 'SrcSel=AutoIndex'?
|
||||||
const char* prim_type_name = "UNKNOWN";
|
driver_->DrawIndexed(
|
||||||
switch (prim_type) {
|
(XE_GPU_PRIMITIVE_TYPE)prim_type,
|
||||||
case 1:
|
index_count);
|
||||||
prim_type_name = "pointlist";
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
prim_type_name = "trilist";
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
prim_type_name = "rectlist";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
XEASSERTALWAYS();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
XELOGGPU(" %d indices of %s", index_count, prim_type_name);
|
|
||||||
LOG_DATA(count);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PM4_DRAW_INDX_2:
|
case PM4_DRAW_INDX_2:
|
||||||
// draw using supplied indices in packet
|
// draw using supplied indices in packet
|
||||||
{
|
{
|
||||||
XELOGGPU("Packet(%.8X): PM4_DRAW_INDX_2", packet);
|
XELOGGPU("Packet(%.8X): PM4_DRAW_INDX_2", packet);
|
||||||
|
LOG_DATA(count);
|
||||||
uint32_t d0 = XEGETUINT32BE(packet_base + 1 * 4);
|
uint32_t d0 = XEGETUINT32BE(packet_base + 1 * 4);
|
||||||
uint32_t index_count = d0 >> 16;
|
uint32_t index_count = d0 >> 16;
|
||||||
uint32_t prim_type = d0 & 0x3F;
|
uint32_t prim_type = d0 & 0x3F;
|
||||||
// Not sure what the other bits mean - 'SrcSel=AutoIndex'?
|
// Not sure what the other bits mean - 'SrcSel=AutoIndex'?
|
||||||
const char* prim_type_name = "UNKNOWN";
|
// TODO(benvanik): verify this matches DRAW_INDX
|
||||||
switch (prim_type) {
|
driver_->DrawIndexed(
|
||||||
case 1:
|
(XE_GPU_PRIMITIVE_TYPE)prim_type,
|
||||||
prim_type_name = "pointlist";
|
index_count);
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
prim_type_name = "trilist";
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
prim_type_name = "rectlist";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
XEASSERTALWAYS();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
XELOGGPU(" %d indices of %s", index_count, prim_type_name);
|
|
||||||
LOG_DATA(count);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -299,6 +288,7 @@ void RingBufferWorker::ExecuteSegment(uint32_t ptr, uint32_t length) {
|
||||||
// load sequencer instruction memory (pointer-based)
|
// load sequencer instruction memory (pointer-based)
|
||||||
{
|
{
|
||||||
XELOGGPU("Packet(%.8X): PM4_IM_LOAD", packet);
|
XELOGGPU("Packet(%.8X): PM4_IM_LOAD", packet);
|
||||||
|
LOG_DATA(count);
|
||||||
uint32_t addr_type = XEGETUINT32BE(packet_base + 1 * 4);
|
uint32_t addr_type = XEGETUINT32BE(packet_base + 1 * 4);
|
||||||
uint32_t type = addr_type & 0x3;
|
uint32_t type = addr_type & 0x3;
|
||||||
uint32_t addr = addr_type & ~0x3;
|
uint32_t addr = addr_type & ~0x3;
|
||||||
|
@ -306,20 +296,11 @@ void RingBufferWorker::ExecuteSegment(uint32_t ptr, uint32_t length) {
|
||||||
uint32_t start = start_size >> 16;
|
uint32_t start = start_size >> 16;
|
||||||
uint32_t size = start_size & 0xFFFF; // dwords
|
uint32_t size = start_size & 0xFFFF; // dwords
|
||||||
XEASSERT(start == 0);
|
XEASSERT(start == 0);
|
||||||
switch (type) {
|
driver_->SetShader(
|
||||||
case 0:
|
(XE_GPU_SHADER_TYPE)type,
|
||||||
XELOGGPU(" vertex shader");
|
TRANSLATE_ADDR(addr),
|
||||||
break;
|
start,
|
||||||
case 1:
|
size);
|
||||||
XELOGGPU(" pixel shader");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
XEASSERTALWAYS();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
XELOGGPU(" %0.8X, %db / %dw",
|
|
||||||
TRANSLATE_ADDR(addr), size * 4, size);
|
|
||||||
LOG_DATA(count);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PM4_IM_LOAD_IMMEDIATE:
|
case PM4_IM_LOAD_IMMEDIATE:
|
||||||
|
@ -331,27 +312,23 @@ void RingBufferWorker::ExecuteSegment(uint32_t ptr, uint32_t length) {
|
||||||
uint32_t start = start_size >> 16;
|
uint32_t start = start_size >> 16;
|
||||||
uint32_t size = start_size & 0xFFFF; // dwords
|
uint32_t size = start_size & 0xFFFF; // dwords
|
||||||
XEASSERT(start == 0);
|
XEASSERT(start == 0);
|
||||||
switch (type) {
|
|
||||||
case 0:
|
|
||||||
XELOGGPU(" vertex shader");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
XELOGGPU(" pixel shader");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
XEASSERTALWAYS();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
XELOGGPU(" %db / %dw", size * 4, size);
|
|
||||||
LOG_DATA(count);
|
LOG_DATA(count);
|
||||||
|
driver_->SetShader(
|
||||||
|
(XE_GPU_SHADER_TYPE)type,
|
||||||
|
ptr + n * 4 + 3 * 4,
|
||||||
|
start,
|
||||||
|
size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PM4_INVALIDATE_STATE:
|
case PM4_INVALIDATE_STATE:
|
||||||
// selective invalidation of state pointers
|
// selective invalidation of state pointers
|
||||||
XELOGGPU("Packet(%.8X): PM4_INVALIDATE_STATE", packet);
|
{
|
||||||
LOG_DATA(count);
|
XELOGGPU("Packet(%.8X): PM4_INVALIDATE_STATE", packet);
|
||||||
//*cmd++ = 0x00000300; /* 0x100 = Vertex, 0x200 = Pixel */
|
LOG_DATA(count);
|
||||||
|
uint32_t mask = XEGETUINT32BE(packet_base + 1 * 4);
|
||||||
|
driver_->InvalidateState(mask);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -12,10 +12,13 @@
|
||||||
|
|
||||||
#include <xenia/core.h>
|
#include <xenia/core.h>
|
||||||
|
|
||||||
|
#include <xenia/gpu/xenos/registers.h>
|
||||||
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
|
|
||||||
|
class GraphicsDriver;
|
||||||
|
|
||||||
class RingBufferWorker {
|
class RingBufferWorker {
|
||||||
public:
|
public:
|
||||||
|
@ -24,7 +27,8 @@ public:
|
||||||
|
|
||||||
xe_memory_ref memory();
|
xe_memory_ref memory();
|
||||||
|
|
||||||
void Initialize(uint32_t ptr, uint32_t page_count);
|
void Initialize(GraphicsDriver* driver,
|
||||||
|
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);
|
||||||
|
|
||||||
void UpdateWritePointer(uint32_t value);
|
void UpdateWritePointer(uint32_t value);
|
||||||
|
@ -41,6 +45,8 @@ protected:
|
||||||
xe_thread_ref thread_;
|
xe_thread_ref thread_;
|
||||||
bool running_;
|
bool running_;
|
||||||
|
|
||||||
|
GraphicsDriver* driver_;
|
||||||
|
|
||||||
uint32_t primary_buffer_ptr_;
|
uint32_t primary_buffer_ptr_;
|
||||||
uint32_t primary_buffer_size_;
|
uint32_t primary_buffer_size_;
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
'gpu-private.h',
|
'gpu-private.h',
|
||||||
'gpu.cc',
|
'gpu.cc',
|
||||||
'gpu.h',
|
'gpu.h',
|
||||||
|
'graphics_driver.cc',
|
||||||
|
'graphics_driver.h',
|
||||||
'graphics_system.cc',
|
'graphics_system.cc',
|
||||||
'graphics_system.h',
|
'graphics_system.h',
|
||||||
'ring_buffer_worker.cc',
|
'ring_buffer_worker.cc',
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace gpu {
|
||||||
namespace xenos {
|
namespace xenos {
|
||||||
|
|
||||||
|
|
||||||
static const uint32_t kXEGpuRegisterCount = 0x3000;
|
static const uint32_t kXEGpuRegisterCount = 0x5003;
|
||||||
|
|
||||||
|
|
||||||
enum Registers {
|
enum Registers {
|
||||||
|
@ -33,13 +33,13 @@ const char* GetRegisterName(uint32_t index);
|
||||||
|
|
||||||
|
|
||||||
union RegisterValue {
|
union RegisterValue {
|
||||||
uint32_t dword_value;
|
uint32_t u32;
|
||||||
float float_value;
|
float f32;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct RegisterFile {
|
struct RegisterFile {
|
||||||
RegisterValue registers[kXEGpuRegisterCount];
|
RegisterValue values[kXEGpuRegisterCount];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue