mirror of
https://github.com/PSI-Rockin/DobieStation.git
synced 2024-05-20 13:08:11 -04:00
Merge pull request #450 from refractionpcsx2/gs_download_v2
VIF/GS: Enhanced GS Download behaviour
This commit is contained in:
commit
6fdbdf39e3
|
@ -309,7 +309,10 @@ int DMAC::process_VIF1()
|
|||
if (std::get<1>(quad_data))
|
||||
store128(channels[VIF1].address, std::get<0>(quad_data));
|
||||
else
|
||||
{
|
||||
arbitrate();
|
||||
return count;
|
||||
}
|
||||
}
|
||||
advance_source_dma(VIF1);
|
||||
count++;
|
||||
|
|
|
@ -96,9 +96,10 @@ void VectorInterface::update(int cycles)
|
|||
if (fifo_reverse)
|
||||
{
|
||||
vif_cmd_status = VIF_IDLE;
|
||||
if (FIFO.size() <= (fifo_size - 4))
|
||||
|
||||
while (cycles--)
|
||||
{
|
||||
while (cycles--)
|
||||
if (FIFO.size() <= (fifo_size - 4))
|
||||
{
|
||||
auto fifo_data = gif->read_GSFIFO();
|
||||
//Check the GS still wants to send data
|
||||
|
@ -108,7 +109,10 @@ void VectorInterface::update(int cycles)
|
|||
for (int i = 0; i < 4; i++)
|
||||
FIFO.push(std::get<0>(fifo_data)._u32[i]);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//Since the loop processes per-word, we need to multiply cycles by 4
|
||||
|
|
|
@ -494,9 +494,9 @@ void GraphicsInterface::send_PATH3_FIFO(uint128_t data)
|
|||
}
|
||||
}
|
||||
|
||||
std::tuple<uint128_t, uint32_t>GraphicsInterface::read_GSFIFO()
|
||||
std::tuple<uint128_t, bool>GraphicsInterface::read_GSFIFO()
|
||||
{
|
||||
return gs->request_gs_download();
|
||||
return gs->read_gs_download();
|
||||
}
|
||||
|
||||
void GraphicsInterface::flush_path3_fifo()
|
||||
|
|
|
@ -88,7 +88,7 @@ class GraphicsInterface
|
|||
void send_PATH2(uint32_t data[4]);
|
||||
void send_PATH3(uint128_t quad);
|
||||
void send_PATH3_FIFO(uint128_t quad);
|
||||
std::tuple<uint128_t, uint32_t>read_GSFIFO();
|
||||
std::tuple<uint128_t, bool>read_GSFIFO();
|
||||
|
||||
void intermittent_check();
|
||||
|
||||
|
@ -112,7 +112,7 @@ inline bool GraphicsInterface::path_active(int index, bool canInterruptPath3)
|
|||
{
|
||||
interrupt_path3(index);
|
||||
}
|
||||
return (active_path == index) && !gs->stalled() && !gif_temporary_stop;
|
||||
return (active_path == index) && !gs->stalled() && !gif_temporary_stop && !gs->get_busdir();
|
||||
}
|
||||
|
||||
inline void GraphicsInterface::resume_path3()
|
||||
|
|
|
@ -25,6 +25,7 @@ GraphicsSynthesizer::~GraphicsSynthesizer()
|
|||
|
||||
delete[] output_buffer1;
|
||||
delete[] output_buffer2;
|
||||
delete[] gs_download_buffer;
|
||||
}
|
||||
|
||||
void GraphicsSynthesizer::reset()
|
||||
|
@ -37,6 +38,12 @@ void GraphicsSynthesizer::reset()
|
|||
if (!output_buffer2)
|
||||
output_buffer2 = new uint32_t[1920 * 1280];
|
||||
|
||||
if (!gs_download_buffer)
|
||||
gs_download_buffer = new uint128_t[(2048 * 2048) / 4];
|
||||
|
||||
gs_download_qwc = 0;
|
||||
gs_download_addr = 0;
|
||||
|
||||
current_lock = std::unique_lock<std::mutex>();
|
||||
using_first_buffer = true;
|
||||
frame_count = 0;
|
||||
|
@ -228,6 +235,9 @@ void GraphicsSynthesizer::write64_privileged(uint32_t addr, uint64_t value)
|
|||
|
||||
gs_thread.send_message({ GSCommand::write64_privileged_t,payload });
|
||||
|
||||
if (addr == 0x12001040 && !reg.BUSDIR && value)
|
||||
request_gs_download();
|
||||
|
||||
bool old_IMR = reg.IMR.signal;
|
||||
reg.write64_privileged(addr, value);
|
||||
|
||||
|
@ -246,6 +256,9 @@ void GraphicsSynthesizer::write32_privileged(uint32_t addr, uint32_t value)
|
|||
|
||||
gs_thread.send_message({ GSCommand::write32_privileged_t,payload });
|
||||
|
||||
if (addr == 0x12001040 && !reg.BUSDIR && value)
|
||||
request_gs_download();
|
||||
|
||||
bool old_IMR = reg.IMR.signal;
|
||||
reg.write32_privileged(addr, value);
|
||||
//When SIGNAL is written to twice, the interrupt will not be processed until IMR.signal is flipped from 1 to 0.
|
||||
|
@ -355,14 +368,48 @@ void GraphicsSynthesizer::wake_gs_thread()
|
|||
gs_thread.wake_thread();
|
||||
}
|
||||
|
||||
std::tuple<uint128_t, uint32_t>GraphicsSynthesizer::request_gs_download()
|
||||
void GraphicsSynthesizer::request_gs_download()
|
||||
{
|
||||
GSMessagePayload payload;
|
||||
payload.no_payload = {};
|
||||
GSReturnMessage return_packet;
|
||||
|
||||
payload.download_payload = { gs_download_buffer, &download_mutex };
|
||||
gs_thread.send_message({ GSCommand::request_local_host_tx, payload });
|
||||
gs_thread.wake_thread();
|
||||
GSReturnMessage data;
|
||||
gs_thread.wait_for_return(GSReturn::local_host_transfer, data);
|
||||
return std::make_tuple(data.payload.data_payload.quad_data, data.payload.data_payload.status);
|
||||
|
||||
gs_thread.wait_for_return(GSReturn::local_host_transfer, return_packet);
|
||||
|
||||
while (!download_mutex.try_lock())
|
||||
{
|
||||
printf("[GS] buffer 1 lock failed!\n");
|
||||
std::this_thread::yield();
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(download_mutex, std::adopt_lock);
|
||||
|
||||
gs_download_addr = 0;
|
||||
gs_download_qwc = return_packet.payload.download_payload.quad_count;
|
||||
}
|
||||
|
||||
std::tuple<uint128_t, bool>GraphicsSynthesizer::read_gs_download()
|
||||
{
|
||||
bool have_data;
|
||||
uint128_t quad_data;
|
||||
|
||||
if (gs_download_qwc)
|
||||
{
|
||||
quad_data._u64[0] = gs_download_buffer[gs_download_addr]._u64[0];
|
||||
quad_data._u64[1] = gs_download_buffer[gs_download_addr]._u64[1];
|
||||
have_data = true;
|
||||
|
||||
gs_download_addr++;
|
||||
gs_download_qwc--;
|
||||
}
|
||||
else
|
||||
{
|
||||
quad_data._u64[0] = 0;
|
||||
quad_data._u64[1] = 0;
|
||||
have_data = false;
|
||||
}
|
||||
return std::make_tuple(quad_data, have_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,10 @@ class GraphicsSynthesizer
|
|||
int frame_count;
|
||||
uint32_t* output_buffer1;
|
||||
uint32_t* output_buffer2;//double buffered to prevent mutex lock
|
||||
std::mutex output_buffer1_mutex, output_buffer2_mutex;
|
||||
uint128_t* gs_download_buffer;
|
||||
uint32_t gs_download_qwc;
|
||||
uint32_t gs_download_addr;
|
||||
std::mutex output_buffer1_mutex, output_buffer2_mutex, download_mutex;
|
||||
bool using_first_buffer;
|
||||
std::unique_lock<std::mutex> current_lock;
|
||||
|
||||
|
@ -65,6 +68,7 @@ class GraphicsSynthesizer
|
|||
void send_message(GSMessage message);
|
||||
void wake_gs_thread();
|
||||
|
||||
std::tuple<uint128_t, uint32_t>request_gs_download();
|
||||
void request_gs_download();
|
||||
std::tuple<uint128_t, bool>read_gs_download();
|
||||
};
|
||||
#endif // GS_HPP
|
||||
|
|
|
@ -402,9 +402,16 @@ void GraphicsSynthesizerThread::event_loop()
|
|||
}
|
||||
case request_local_host_tx:
|
||||
{
|
||||
auto p = data.payload.download_payload;
|
||||
|
||||
while (!p.target_mutex->try_lock())
|
||||
{
|
||||
printf("[GS_t] buffer lock failed!\n");
|
||||
std::this_thread::yield();
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(*p.target_mutex, std::adopt_lock);
|
||||
GSReturnMessagePayload return_payload;
|
||||
return_payload.data_payload.status = (TRXDIR != 3);
|
||||
return_payload.data_payload.quad_data = local_to_host();
|
||||
return_payload.download_payload.quad_count = local_to_host(p.target);
|
||||
return_queue->push({ GSReturn::local_host_transfer, return_payload });
|
||||
std::unique_lock<std::mutex> lk(data_mutex);
|
||||
recieve_data = true;
|
||||
|
@ -3055,21 +3062,23 @@ void GraphicsSynthesizerThread::write_HWREG(uint64_t data)
|
|||
}
|
||||
}
|
||||
|
||||
uint128_t GraphicsSynthesizerThread::local_to_host()
|
||||
uint32_t GraphicsSynthesizerThread::local_to_host(uint128_t *target)
|
||||
{
|
||||
int ppd = 0; //pixels per doubleword (64-bits)
|
||||
uint128_t return_data;
|
||||
return_data._u64[0] = 0;
|
||||
return_data._u64[1] = 0;
|
||||
uint32_t return_qwc = 0;
|
||||
target[0]._u64[0] = 0;
|
||||
target[0]._u64[1] = 0;
|
||||
printf("[GS_t] Local to Host transfer started\n");
|
||||
|
||||
if (TRXDIR == 3)
|
||||
return return_data;
|
||||
return return_qwc;
|
||||
|
||||
//Invalid transfer if no height/width has been set
|
||||
if (TRXREG.width == 0 || TRXREG.height == 0)
|
||||
{
|
||||
TRXDIR = 3;
|
||||
pixels_transferred = 0;
|
||||
return return_data;
|
||||
return return_qwc;
|
||||
}
|
||||
|
||||
switch (BITBLTBUF.source_format)
|
||||
|
@ -3109,103 +3118,105 @@ uint128_t GraphicsSynthesizerThread::local_to_host()
|
|||
default:
|
||||
Errors::die("[GS_t] GS Download Unrecognized BITBLTBUF source format $%02X\n", BITBLTBUF.source_format);
|
||||
}
|
||||
uint64_t data = 0;
|
||||
for (int datapart = 0; datapart < 2; datapart++)
|
||||
{
|
||||
for (int i = 0; i < ppd; i++)
|
||||
{
|
||||
switch (BITBLTBUF.source_format)
|
||||
{
|
||||
case 0x00:
|
||||
data |= (uint64_t)(read_PSMCT32_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFFFFFF) << (i * 32);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x01:
|
||||
data = pack_PSMCT24(false);
|
||||
break;
|
||||
case 0x02:
|
||||
data |= (uint64_t)(read_PSMCT16_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFF) << (i * 16);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x0A:
|
||||
data |= (uint64_t)(read_PSMCT16S_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFF) << (i * 16);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x13:
|
||||
data |= (uint64_t)(read_PSMCT8_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFF) << (i * 8);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x14:
|
||||
data |= (uint64_t)(read_PSMCT4_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xf) << (i * 4);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x1B:
|
||||
data |= (uint64_t)((read_PSMCT32_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) >> 24) & 0xFF) << (i * 8);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x30:
|
||||
data |= (uint64_t)(read_PSMCT32Z_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFFFFFF) << (i * 32);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x31:
|
||||
data = pack_PSMCT24(true);
|
||||
break;
|
||||
case 0x32:
|
||||
data |= (uint64_t)(read_PSMCT16Z_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFF) << (i * 16);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x3A:
|
||||
data |= (uint64_t)(read_PSMCT16SZ_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFF) << (i * 16);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
default:
|
||||
Errors::die("[GS_t] GS Download Unrecognized BITBLTBUF source format $%02X\n", BITBLTBUF.source_format);
|
||||
}
|
||||
|
||||
|
||||
if (pixels_transferred % TRXREG.width == 0)
|
||||
{
|
||||
TRXPOS.int_source_x = TRXPOS.source_x;
|
||||
TRXPOS.int_source_y++;
|
||||
}
|
||||
|
||||
//Coordinates wrap at 2048 pixels
|
||||
TRXPOS.int_source_x %= 2048;
|
||||
TRXPOS.int_source_y %= 2048;
|
||||
}
|
||||
|
||||
return_data._u64[datapart] = data;
|
||||
data = 0;
|
||||
}
|
||||
|
||||
|
||||
int max_pixels = TRXREG.width * TRXREG.height;
|
||||
if (pixels_transferred >= max_pixels)
|
||||
|
||||
while (pixels_transferred < max_pixels)
|
||||
{
|
||||
//Deactivate the transmisssion
|
||||
printf("[GS_t] Local to Host transfer ended\n");
|
||||
TRXDIR = 3;
|
||||
pixels_transferred = 0;
|
||||
uint64_t data = 0;
|
||||
for (int datapart = 0; datapart < 2; datapart++)
|
||||
{
|
||||
for (int i = 0; i < ppd; i++)
|
||||
{
|
||||
switch (BITBLTBUF.source_format)
|
||||
{
|
||||
case 0x00:
|
||||
data |= (uint64_t)(read_PSMCT32_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFFFFFF) << (i * 32);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x01:
|
||||
data = pack_PSMCT24(false);
|
||||
break;
|
||||
case 0x02:
|
||||
data |= (uint64_t)(read_PSMCT16_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFF) << (i * 16);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x0A:
|
||||
data |= (uint64_t)(read_PSMCT16S_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFF) << (i * 16);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x13:
|
||||
data |= (uint64_t)(read_PSMCT8_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFF) << (i * 8);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x14:
|
||||
data |= (uint64_t)(read_PSMCT4_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xf) << (i * 4);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x1B:
|
||||
data |= (uint64_t)((read_PSMCT32_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) >> 24) & 0xFF) << (i * 8);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x30:
|
||||
data |= (uint64_t)(read_PSMCT32Z_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFFFFFF) << (i * 32);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x31:
|
||||
data = pack_PSMCT24(true);
|
||||
break;
|
||||
case 0x32:
|
||||
data |= (uint64_t)(read_PSMCT16Z_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFF) << (i * 16);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
case 0x3A:
|
||||
data |= (uint64_t)(read_PSMCT16SZ_block(BITBLTBUF.source_base, BITBLTBUF.source_width,
|
||||
TRXPOS.int_source_x, TRXPOS.int_source_y) & 0xFFFF) << (i * 16);
|
||||
pixels_transferred++;
|
||||
TRXPOS.int_source_x++;
|
||||
break;
|
||||
default:
|
||||
Errors::die("[GS_t] GS Download Unrecognized BITBLTBUF source format $%02X\n", BITBLTBUF.source_format);
|
||||
}
|
||||
|
||||
if (pixels_transferred % TRXREG.width == 0)
|
||||
{
|
||||
TRXPOS.int_source_x = TRXPOS.source_x;
|
||||
TRXPOS.int_source_y++;
|
||||
}
|
||||
|
||||
//Coordinates wrap at 2048 pixels
|
||||
TRXPOS.int_source_x %= 2048;
|
||||
TRXPOS.int_source_y %= 2048;
|
||||
}
|
||||
|
||||
target[return_qwc]._u64[datapart] = data;
|
||||
data = 0;
|
||||
}
|
||||
return_qwc++;
|
||||
}
|
||||
|
||||
return return_data;
|
||||
//Deactivate the transmisssion
|
||||
printf("[GS_t] Local to Host transfer ended\n");
|
||||
TRXDIR = 3;
|
||||
pixels_transferred = 0;
|
||||
|
||||
return return_qwc;
|
||||
}
|
||||
|
||||
void GraphicsSynthesizerThread::unpack_PSMCT24(uint64_t data, int offset, bool z_format)
|
||||
|
|
|
@ -90,6 +90,11 @@ union GSMessagePayload
|
|||
std::mutex* target_mutex;
|
||||
} render_payload;
|
||||
struct
|
||||
{
|
||||
uint128_t* target;
|
||||
std::mutex* target_mutex;
|
||||
} download_payload;
|
||||
struct
|
||||
{
|
||||
std::ofstream* state;
|
||||
} save_state_payload;
|
||||
|
@ -136,9 +141,9 @@ union GSReturnMessagePayload
|
|||
} no_payload;//C++ doesn't like the empty struct
|
||||
struct
|
||||
{
|
||||
uint128_t quad_data;
|
||||
uint32_t status;
|
||||
} data_payload;
|
||||
uint32_t quad_count;
|
||||
} download_payload;
|
||||
|
||||
};
|
||||
|
||||
struct GSReturnMessage
|
||||
|
@ -506,7 +511,7 @@ class GraphicsSynthesizerThread
|
|||
float step_x0, float step_x1, float scx1, float scx2, TexLookupInfo& tex_info);
|
||||
void render_sprite();
|
||||
void write_HWREG(uint64_t data);
|
||||
uint128_t local_to_host();
|
||||
uint32_t local_to_host(uint128_t *target);
|
||||
void unpack_PSMCT24(uint64_t data, int offset, bool z_format);
|
||||
uint64_t pack_PSMCT24(bool z_format);
|
||||
void local_to_local();
|
||||
|
|
Loading…
Reference in a new issue