GPU byte swapping.
A lot of other packets likely do this.
This commit is contained in:
@@ -161,7 +161,7 @@ void GraphicsSystem::WriteRegister(uint32_t r, uint64_t value) {
|
||||
}
|
||||
|
||||
void GraphicsSystem::DispatchInterruptCallback(
|
||||
uint32_t source, uint32_t cpu) {
|
||||
uint32_t source, uint32_t cpu) {
|
||||
// Pick a CPU, if needed. We're going to guess 2. Because.
|
||||
if (cpu == 0xFFFFFFFF) {
|
||||
cpu = 2;
|
||||
|
||||
@@ -483,13 +483,10 @@ uint32_t RingBufferWorker::ExecutePacket(PacketArgs& args) {
|
||||
// Write value.
|
||||
data_value = value;
|
||||
}
|
||||
if (!(address & 0xC0000000)) {
|
||||
XESETUINT32BE(p + TRANSLATE_ADDR(address), data_value);
|
||||
} else {
|
||||
// TODO(benvanik): read up on PM4_EVENT_WRITE_SHD.
|
||||
// No clue. Maybe relative write based on a register base?
|
||||
XELOGE("UNKNOWN FORM OF PM4_EVENT_WRITE_SHD");
|
||||
}
|
||||
uint32_t endianness = address >> 29;
|
||||
address &= ~0xC0000000;
|
||||
data_value = GpuSwap(data_value, endianness);
|
||||
XESETUINT32BE(p + TRANSLATE_ADDR(address), data_value);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -42,6 +42,22 @@ typedef enum {
|
||||
XE_GPU_PRIMITIVE_TYPE_LINE_LOOP = 0x0C,
|
||||
} XE_GPU_PRIMITIVE_TYPE;
|
||||
|
||||
XEFORCEINLINE uint32_t GpuSwap(uint32_t value, uint32_t endianness) {
|
||||
switch (endianness) {
|
||||
default:
|
||||
case 0x0: // No swap.
|
||||
return value;
|
||||
case 0x1: // Swap bytes in half words.
|
||||
return ((value << 8) & 0xFF00FF00) |
|
||||
((value >> 8) & 0x00FF00FF);
|
||||
case 0x2: // Swap bytes.
|
||||
// NOTE: we are likely doing two swaps here. Wasteful. Oh well.
|
||||
return XESWAP32(value);
|
||||
case 0x3: // Swap half words.
|
||||
return ((value >> 16) & 0xFFFF) | (value << 16);
|
||||
}
|
||||
}
|
||||
|
||||
// XE_GPU_REG_SQ_PROGRAM_CNTL
|
||||
typedef union {
|
||||
XEPACKEDSTRUCTANONYMOUS({
|
||||
|
||||
Reference in New Issue
Block a user