diff --git a/src/ipu/ipu_interface.h b/src/ipu/ipu_interface.h index 4531e6d..2ac07ac 100644 --- a/src/ipu/ipu_interface.h +++ b/src/ipu/ipu_interface.h @@ -18,7 +18,7 @@ extern "C" { #define IPUMAXEVENTSPERTIC (5) #define IPUAMMARKBUFSIZE (544) #define IPUMAPPEDLINEUPDATES (2) -#define IPUPROGBUFSIZE (32) +#define IPUPROGBUFSIZE (128) #define IPUFIRSTRENDERTILE (0) #define IPUNUMRENDERTILES (32) diff --git a/src/ipu/ipu_texturetiles.cpp b/src/ipu/ipu_texturetiles.cpp index c795255..8dca173 100644 --- a/src/ipu/ipu_texturetiles.cpp +++ b/src/ipu/ipu_texturetiles.cpp @@ -67,6 +67,12 @@ void IPU_R_FulfilColumnRequest(unsigned* progBuf, unsigned* textureBuf) { textureBuf[i] = 0x20202020; } XCOM_Execute(sendProgram, textureBuf, NULL); + + // TMP + asm volatile(R"( + sans 1 + sync 0x1 + )"); } } @@ -103,61 +109,115 @@ void IPU_R_InitColumnRequester(unsigned* progBuf, int progBufSize) { textureTileLUT[i] = XCOM_logical2physical(firstTextureTile + i); } - // Prog Buf starts with directory of programs + // ProgBuf starts with directory of programs unsigned* progHead = progBuf + 3; unsigned* progEnd = &progBuf[progBufSize]; - { - progBuf[0] = progHead - progBuf; - XCOMAssembler assembler; - int messageSize = sizeof(IPUColRequest_t) / sizeof(int); - assembler.addSend(0, messageSize, XCOM_BROADCAST, XCOM_WORSTSENDDELAY); - progHead = assembler.assemble(progHead, progEnd - progHead); - } - { - XCOMAssembler assembler; - int messageSize = IPUTEXTURECACHELINESIZE; - assembler.addRecv(0, messageSize, 0, XCOM_WORSTRECVDELAY); - unsigned* newProgHead = assembler.assemble(progHead, progEnd - progHead); - for (unsigned* inst = progHead; inst < newProgHead; ++inst) { - if ((*inst & 0xfc003fffu) == 0x64000000u) { - muxInstructionOffset = (inst - &progBuf[progBuf[0]]); - break; - } + XCOMAssembler assembler; + + // First Program: performs the request and receives the response + progBuf[0] = progHead - progBuf; + int messageSize = sizeof(IPUColRequest_t) / sizeof(int); + assembler.addSend(0, messageSize, XCOM_BROADCAST, XCOM_WORSTSENDDELAY); + progHead = assembler.assemble(progHead, progEnd - progHead); + assembler.reset(); + assembler.addRecv(0, IPUTEXTURECACHELINESIZE, 0, XCOM_WORSTRECVDELAY); + unsigned* newProgHead = assembler.assemble(progHead, progEnd - progHead); + // Record the mux location for later live patching + for (unsigned* inst = progHead; inst < newProgHead; ++inst) { + if ((*inst & 0xfc003fffu) == 0x64000000u) { + muxInstructionOffset = (inst - &progBuf[progBuf[0]]); + break; } - progHead = newProgHead; - } - // Third program sends finished flag to flag reducer - // { - // progBuf[2] = progHead - progBuf; - // XCOMAssembler assembler; - // int messageSize = 1; - // int recvCycle = XCOM_WORSTRECVDELAY; - // int sendCycle = recvCycle - XCOM_TimeToMux(__builtin_ipu_get_tile_id(), renderTile); - // int direction = XCOM_EastOrWest(__builtin_ipu_get_tile_id(), renderTile); - // assembler.addSend(0, messageSize, direction, sendCycle); - // progHead = assembler.assemble(progHead, progEnd - progHead); - // progHead++; - // } + } + progHead = newProgHead + 1; // +1 => don't overwrite the return statement + assembler.reset(); + + // Second Program: aggregates the 'done' flag across render tiles + progBuf[1] = progHead - progBuf; + int aggrTile = XCOM_logical2physical(IPUFIRSTRENDERTILE); + if (__builtin_ipu_get_tile_id() == aggrTile) { + for (int slot = 0; slot < IPUNUMRENDERTILES - 1; ++slot) { + int senderID = XCOM_logical2physical(IPUFIRSTRENDERTILE + 1 + slot); + assembler.addRecv((unsigned*)(4*(slot + 1)), 1, senderID, XCOM_WORSTRECVDELAY + slot, + slot == IPUNUMRENDERTILES - 2); + } + progHead = assembler.assemble(progHead, progEnd - progHead); + progHead++; + + // Third Program: aggregation tile distributes the answer + progBuf[2] = progHead - progBuf; + assembler.reset(); + assembler.addSend(0, 1, XCOM_BROADCAST, XCOM_WORSTSENDDELAY); + progHead = assembler.assemble(progHead, progEnd - progHead); + progHead++; + + } else { + int myTimeSlot = tileID - (IPUFIRSTRENDERTILE + 1); + int direction = XCOM_EastOrWest(__builtin_ipu_get_tile_id(), aggrTile); + int muxCycle = XCOM_WORSTRECVDELAY + myTimeSlot; + int sendCycle = muxCycle - XCOM_TimeToMux(__builtin_ipu_get_tile_id(), aggrTile); + assembler.addSend(0, 1, direction, sendCycle); + progHead = assembler.assemble(progHead, progEnd - progHead); + + assembler.reset(); + sendCycle = XCOM_WORSTSENDDELAY; + muxCycle = sendCycle + XCOM_TimeToMux(aggrTile, __builtin_ipu_get_tile_id()); + assembler.addRecv(0, 1, aggrTile, muxCycle); + progHead = assembler.assemble(progHead, progEnd - progHead); + progHead++; + } + + // assembler.reset(); } +__SUPER__ +static bool checkRenderingFinished() { + auto aggregateProgA = &tileLocalProgBuf[tileLocalProgBuf[1]]; + auto aggregateProgB = &tileLocalProgBuf[tileLocalProgBuf[2]]; + + tileLocalTextureBuf[0] = tileID + 100; + XCOM_Execute( + aggregateProgA, + tileLocalTextureBuf, + tileLocalTextureBuf + ); + if (tileID == IPUFIRSTRENDERTILE) { + for (int i = 1; i < IPUNUMRENDERTILES; i++) { + tileLocalTextureBuf[0] += tileLocalTextureBuf[i]; + } + XCOM_Execute( + aggregateProgB, + tileLocalTextureBuf, + NULL + ); + } + printf("Aggregation result: %d\n", tileLocalTextureBuf[0]); + + return tileLocalTextureBuf[0]; +} + extern "C" __SUPER__ byte* IPU_R_RequestColumn(int texture, int column) { // progBuff starts with a program directory auto requestProg = &tileLocalProgBuf[tileLocalProgBuf[0]]; + auto aggregateProgA = &tileLocalProgBuf[tileLocalProgBuf[1]]; + auto aggregateProgB = &tileLocalProgBuf[tileLocalProgBuf[2]]; if (textureFetchCount++ < 6) { int sourceTile = 0; XCOM_PatchMuxAndExecute( - requestProg, // Prog + requestProg, // Prog tileLocalTextureBuf, // Read offset tileLocalTextureBuf, // Write offset muxInstructionOffset, // Patch offset textureTileLUT[sourceTile] // Mux value ); + checkRenderingFinished(); + return (byte*) tileLocalTextureBuf; } return columnCache[texture % NUMCACHECOLS]; @@ -192,6 +252,12 @@ void IPU_R_Sans(unsigned* progBuf, int progBufSize) { sans 1 sync 0x1 )"); + + // TMP + asm volatile(R"( + sans 1 + sync 0x1 + )"); } } diff --git a/src/ipu_host.cpp b/src/ipu_host.cpp index fd7df21..ff29ccf 100644 --- a/src/ipu_host.cpp +++ b/src/ipu_host.cpp @@ -310,6 +310,8 @@ void IpuDoom::buildIpuGraph() { for (unsigned tile = IPUFIRSTTEXTURETILE + IPUNUMTEXTURETILES; tile < totalTiles; ++tile) { m_ipuGraph.setTileMapping(m_ipuGraph.addVertex(R_RenderPlayerView_CS, "R_Sans_Vertex"), tile); } + // Cache line is used as the aggregation buffer, make sure it's big enough + assert(IPUTEXTURECACHELINESIZE >= IPUNUMRENDERTILES); poplar::program::Sequence R_RenderPlayerView_prog({ poplar::program::Copy(miscValuesStream, m_miscValuesBuf),