move the debug folder to the top level
[AROS.git] / test / smp / smp-smallpt / renderer.c
blobb78bd9bd7b4750a71ab019c4a23feeec83c049b3
1 /*
2 Copyright © 2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 1
7 #include <aros/debug.h>
8 #include <aros/atomic.h>
10 #include <proto/exec.h>
11 #include <proto/kernel.h>
13 #include <exec/tasks.h>
14 #include <exec/ports.h>
15 #include <exec/rawfmt.h>
17 #include "renderer.h"
19 extern void render_tile(int w, int h, int samps, int tile_x, int tile_y, ULONG *buffer, struct Task *gfx);
20 extern void RenderTile(struct ExecBase *SysBase, struct MsgPort *masterPort, struct MsgPort **myPort);
22 struct Worker {
23 struct Task * task;
24 struct MsgPort *port;
25 char * name;
28 struct MyMessage *AllocMyMessage(struct MinList *msgPool)
30 struct MyMessage *msg = (struct MyMessage *)REMHEAD(msgPool);
31 if (msg)
33 msg->mm_Message.mn_Length = sizeof(struct MyMessage);
35 else bug("[SMP-Smallpt-Renderer] RUN OUT OF MESSAGES...\n");
37 return msg;
40 void FreeMyMessage(struct MinList *msgPool, struct MyMessage *msg)
42 ADDHEAD(msgPool, &msg->mm_Message.mn_Node);
45 void Renderer(struct ExecBase *ExecBase, struct MsgPort *ParentMailbox)
47 ULONG width = 0;
48 ULONG height = 0;
49 ULONG *bitmap = NULL;
50 struct MsgPort *guiPort = NULL;
51 struct MsgPort *port;
52 struct MyMessage *messages;
53 struct MyMessage *deathMessage = NULL;
54 ULONG numberOfCores = 0;
55 ULONG maxIter = 0;
56 int cores_alive = 0;
57 int tasks_in = 0;
58 int tasks_out = 0;
59 int tasks_work = 0;
60 ULONG workerStack = AROS_STACKSIZE + maximal_ray_depth * 1000;
61 int expl_mode = 0;
63 D(bug("[SMP-Smallpt-Renderer] Renderer started, ParentMailBox = %p\n", ParentMailbox));
65 port = CreateMsgPort();
67 if (port)
69 struct Message startup;
70 int stayAlive = TRUE;
71 struct MinList workList;
72 struct MinList doneList;
73 struct MinList msgPool;
74 struct tileWork *workPackages;
75 struct Worker *workers;
77 NEWLIST(&workList);
78 NEWLIST(&doneList);
79 NEWLIST(&msgPool);
81 /* Prepare initial message and wait for startup msg */
82 startup.mn_Length = sizeof(startup);
83 startup.mn_ReplyPort = port;
85 D(bug("[SMP-Smallpt-Renderer] Sending welcome msg to parent\n"));
86 PutMsg(ParentMailbox, &startup);
88 while(width == 0)
90 struct MyMessage *msg;
92 WaitPort(port);
94 while ((msg = (struct MyMessage *)GetMsg(port)))
96 if (msg->mm_Message.mn_Node.ln_Type == NT_REPLYMSG)
98 D(bug("[SMP-Smallpt-Renderer] Parent replied to welcome msg\n"));
100 else if (msg->mm_Message.mn_Length >= sizeof(struct Message))
102 if (msg->mm_Type == MSG_STARTUP)
104 D(bug("[SMP-Smallpt-Renderer] recieved startup message at %p\n", msg));
106 guiPort = msg->mm_Message.mn_ReplyPort;
107 width = msg->mm_Body.Startup.Width;
108 height = msg->mm_Body.Startup.Height;
109 bitmap = msg->mm_Body.Startup.ChunkyBM;
110 //mainTask = msg->mm_Message.mn_ReplyPort->mp_SigTask;
111 numberOfCores = msg->mm_Body.Startup.coreCount;
112 maxIter = msg->mm_Body.Startup.numberOfSamples;
113 expl_mode = msg->mm_Body.Startup.explicitMode;
115 ReplyMsg(&msg->mm_Message);
120 D(bug("[SMP-Smallpt-Renderer] Bitmap size %dx%d, chunky buffer at %p\n", width, height, bitmap));
122 ULONG tile_count = (width / TILE_SIZE) * (height / TILE_SIZE);
124 tasks_in = tile_count;
126 workPackages = AllocMem(tile_count * sizeof(struct tileWork), MEMF_ANY);
128 D(bug("[SMP-Smallpt-Renderer] Preparing work packages\n"));
130 for (ULONG i=0; i < tile_count; i++)
132 workPackages[i].x = i % (width / TILE_SIZE);
133 workPackages[i].y = i / (width / TILE_SIZE);
134 ADDHEAD(&workList, &workPackages[i].node);
137 messages = AllocMem(sizeof(struct MyMessage) * numberOfCores * 10, MEMF_PUBLIC | MEMF_CLEAR);
138 for (int i=0; i < numberOfCores * 10; i++)
139 FreeMyMessage(&msgPool, &messages[i]);
141 D(bug("[SMP-Smallpt-Renderer] creating %d workers\n", numberOfCores));
142 workers = AllocMem(sizeof(struct Worker) * numberOfCores, MEMF_PUBLIC | MEMF_CLEAR);
144 D(bug("[SMP-Smallpt-Renderer] worker stack size : %d bytes\n", workerStack));
146 for (ULONG i=0; i < numberOfCores; i++)
148 void *coreAffinity = KrnAllocCPUMask();
149 KrnGetCPUMask(i, coreAffinity);
151 workers[i].name = AllocMem(30, MEMF_PUBLIC | MEMF_CLEAR);
152 NewRawDoFmt("SMP-SmallPT Worker.#%03u", RAWFMTFUNC_STRING, workers[i].name, i);
154 workers[i].task = NewCreateTask(TASKTAG_NAME, workers[i].name,
155 TASKTAG_AFFINITY, coreAffinity,
156 TASKTAG_PRI, 0,
157 TASKTAG_PC, RenderTile,
158 TASKTAG_ARG1, SysBase,
159 TASKTAG_ARG2, port,
160 TASKTAG_ARG3, &workers[i].port,
161 TASKTAG_STACKSIZE, workerStack,
162 TAG_DONE);
164 cores_alive = numberOfCores;
166 D(bug("[SMP-Smallpt-Renderer] all set up, doing work\n"));
168 while(stayAlive)
170 struct MyMessage *msg;
171 WaitPort(port);
173 while ((msg = (struct MyMessage *)GetMsg(port)))
175 if (msg->mm_Message.mn_Node.ln_Type == NT_REPLYMSG)
177 if (msg->mm_Type == MSG_DIE)
179 D(bug("[SMP-Smallpt-Renderer] death of smallpt task detected...\n"));
180 cores_alive--;
182 if (cores_alive == 0)
184 stayAlive = FALSE;
185 ReplyMsg(&deathMessage->mm_Message);
188 FreeMyMessage(&msgPool, msg);
190 else
192 if (msg->mm_Type == MSG_DIE)
194 D(bug("[SMP-Smallpt-Renderer] time to die...\n"));
196 for (ULONG i=0; i < numberOfCores; i++)
198 struct MyMessage *m = AllocMyMessage(&msgPool);
199 if (m)
201 m->mm_Type = MSG_DIE;
202 m->mm_Message.mn_ReplyPort = port;
204 D(bug("[SMP-Smallpt-Renderer] telling task %s to shut down\n", workers[i].task->tc_Node.ln_Name));
205 PutMsg(workers[i].port, &m->mm_Message);
208 deathMessage = msg;
210 else if (msg->mm_Type == MSG_HUNGRY)
212 struct MsgPort *workerPort = msg->mm_Message.mn_ReplyPort;
213 ReplyMsg(&msg->mm_Message);
215 if (!IsMinListEmpty(&workList))
217 struct MyMessage *m = AllocMyMessage(&msgPool);
219 if (m)
221 struct tileWork *work = (struct tileWork *)REMHEAD(&workList);
222 tasks_in--;
223 tasks_work++;
225 m->mm_Type = MSG_RENDERTILE;
226 m->mm_Message.mn_ReplyPort = port;
227 m->mm_Body.RenderTile.tile = work;
228 m->mm_Body.RenderTile.buffer = bitmap;
229 m->mm_Body.RenderTile.guiPort = guiPort;
230 m->mm_Body.RenderTile.width = width;
231 m->mm_Body.RenderTile.height = height;
232 m->mm_Body.RenderTile.numberOfSamples = maxIter;
233 m->mm_Body.RenderTile.explicitMode = expl_mode;
235 PutMsg(workerPort, &m->mm_Message);
239 else if (msg->mm_Type == MSG_RENDERREADY)
241 struct tileWork *work = msg->mm_Body.RenderTile.tile;
242 ReplyMsg(&msg->mm_Message);
243 ADDHEAD(&doneList, work);
244 tasks_out++;
245 tasks_work--;
247 if (deathMessage == NULL)
249 struct MyMessage *m = AllocMyMessage(&msgPool);
250 if (m)
252 m->mm_Type = MSG_STATS;
253 m->mm_Message.mn_ReplyPort = port;
254 m->mm_Body.Stats.tasksIn = tasks_in;
255 m->mm_Body.Stats.tasksOut = tasks_out;
256 m->mm_Body.Stats.tasksWork = tasks_work;
257 PutMsg(guiPort, &m->mm_Message);
264 FreeMem(workPackages, tile_count * sizeof(struct tileWork));
265 FreeMem(messages, sizeof(struct MyMessage) * numberOfCores * 10);
266 FreeMem(workers, sizeof(struct Worker) * numberOfCores);
267 DeleteMsgPort(port);
269 D(bug("[SMP-Smallpt-Renderer] goodbye!\n"));