IPU: Redo FIFO transfers, plus small IPU_TO DMA tweak

This commit is contained in:
refractionpcsx2 2023-06-24 13:15:28 +01:00
parent ff23f87010
commit 3c0b7f7724
3 changed files with 42 additions and 40 deletions

View File

@ -72,25 +72,28 @@ std::string IPU_Fifo_Output::desc() const
return StringUtil::StdStringFromFormat("IPU Fifo Output: readpos = 0x%x, writepos = 0x%x, data = 0x%x", readpos, writepos, data);
}
int IPU_Fifo_Input::write(u32* pMem, int size)
int IPU_Fifo_Input::write(const u32* pMem, int size)
{
int transsize;
int firsttrans = std::min(size, 8 - (int)g_BP.IFC);
const int transfer_size = std::min(size, 8 - (int)g_BP.IFC);
if (!transfer_size) return 0;
g_BP.IFC += firsttrans;
transsize = firsttrans;
const int first_words = std::min((32 - writepos), transfer_size << 2);
const int second_words = (transfer_size << 2) - first_words;
while (transsize-- > 0)
{
CopyQWC(&data[writepos], pMem);
writepos = (writepos + 4) & 31;
pMem += 4;
}
memcpy(&data[writepos], pMem, first_words << 2);
pMem += first_words;
if(second_words)
memcpy(&data[0], pMem, second_words << 2);
writepos = (writepos + (transfer_size << 2)) & 31;
g_BP.IFC += transfer_size;
if (g_BP.IFC == 8)
IPU1Status.DataRequested = false;
return firsttrans;
return transfer_size;
}
int IPU_Fifo_Input::read(void *value)
@ -121,26 +124,25 @@ int IPU_Fifo_Output::write(const u32 *value, uint size)
{
pxAssertMsg(size>0, "Invalid size==0 when calling IPU_Fifo_Output::write");
uint origsize = size;
/*do {*/
//IPU0dma();
const int transfer_size = std::min(size, 8 - (uint)ipuRegs.ctrl.OFC);
if(!transfer_size) return 0;
uint transsize = std::min(size, 8 - (uint)ipuRegs.ctrl.OFC);
if(!transsize) return 0;
const int first_words = std::min((32 - writepos), transfer_size << 2);
const int second_words = (transfer_size << 2) - first_words;
memcpy(&data[writepos], value, first_words << 2);
value += first_words;
if (second_words)
memcpy(&data[0], value, second_words << 2);
writepos = (writepos + (transfer_size << 2)) & 31;
ipuRegs.ctrl.OFC += transfer_size;
ipuRegs.ctrl.OFC += transsize;
size -= transsize;
while (transsize > 0)
{
CopyQWC(&data[writepos], value);
writepos = (writepos + 4) & 31;
value += 4;
--transsize;
}
/*} while(true);*/
if(ipu0ch.chcr.STR)
IPU_INT_FROM(ipuRegs.ctrl.OFC * BIAS);
return origsize - size;
return transfer_size;
}
void IPU_Fifo_Output::read(void *value, uint size)
@ -151,16 +153,16 @@ void IPU_Fifo_Output::read(void *value, uint size)
// Zeroing the read data is not needed, since the ringbuffer design will never read back
// the zero'd data anyway. --air
//__m128 zeroreg = _mm_setzero_ps();
while (size > 0)
{
CopyQWC(value, &data[readpos]);
//_mm_store_ps((float*)&data[readpos], zeroreg);
const int first_words = std::min((32 - readpos), static_cast<int>(size << 2));
const int second_words = static_cast<int>(size << 2) - first_words;
readpos = (readpos + 4) & 31;
value = (u128*)value + 1;
--size;
}
memcpy(value, &data[readpos], first_words << 2);
value = static_cast<u32*>(value) + first_words;
if (second_words)
memcpy(value, &data[0], second_words << 2);
readpos = (readpos + static_cast<int>(size << 2)) & 31;
}
void ReadFIFO_IPUout(mem128_t* out)
@ -177,7 +179,7 @@ void WriteFIFO_IPUin(const mem128_t* value)
IPU_LOG( "WriteFIFO/IPUin <- 0x%08X.%08X.%08X.%08X", value->_u32[0], value->_u32[1], value->_u32[2], value->_u32[3]);
//committing every 16 bytes
if( ipu_fifo.in.write((u32*)value, 1) == 0 )
if( ipu_fifo.in.write(value->_u32, 1) == 0 )
{
if (ipuRegs.ctrl.BUSY && !CommandExecuteQueued)
{

View File

@ -27,7 +27,7 @@ struct IPU_Fifo_Input
alignas(16) u32 data[32];
int readpos, writepos;
int write(u32* pMem, int size);
int write(const u32* pMem, int size);
int read(void *value);
void clear();
std::string desc() const;

View File

@ -123,7 +123,7 @@ void IPU1dma()
totalqwc += IPU1chain();
//Do this here to prevent double settings on Chain DMA's
if(totalqwc == 0 || (IPU1Status.DMAFinished && !IPU1Status.InProgress))
if((totalqwc == 0 && g_BP.IFC < 8) || (IPU1Status.DMAFinished && !IPU1Status.InProgress))
{
totalqwc = std::max(4, totalqwc) + tagcycles;
IPU_INT_TO(totalqwc * BIAS);