2 Copyright © 2017, The AROS Development Team. All rights reserved.
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>
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
);
28 struct MyMessage
*AllocMyMessage(struct MinList
*msgPool
)
30 struct MyMessage
*msg
= (struct MyMessage
*)REMHEAD(msgPool
);
33 msg
->mm_Message
.mn_Length
= sizeof(struct MyMessage
);
35 else bug("[SMP-Smallpt-Renderer] RUN OUT OF MESSAGES...\n");
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
)
50 struct MsgPort
*guiPort
= NULL
;
52 struct MyMessage
*messages
;
53 struct MyMessage
*deathMessage
= NULL
;
54 ULONG numberOfCores
= 0;
60 ULONG workerStack
= AROS_STACKSIZE
+ maximal_ray_depth
* 1000;
63 D(bug("[SMP-Smallpt-Renderer] Renderer started, ParentMailBox = %p\n", ParentMailbox
));
65 port
= CreateMsgPort();
69 struct Message startup
;
71 struct MinList workList
;
72 struct MinList doneList
;
73 struct MinList msgPool
;
74 struct tileWork
*workPackages
;
75 struct Worker
*workers
;
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
);
90 struct MyMessage
*msg
;
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
,
157 TASKTAG_PC
, RenderTile
,
158 TASKTAG_ARG1
, SysBase
,
160 TASKTAG_ARG3
, &workers
[i
].port
,
161 TASKTAG_STACKSIZE
, workerStack
,
164 cores_alive
= numberOfCores
;
166 D(bug("[SMP-Smallpt-Renderer] all set up, doing work\n"));
170 struct MyMessage
*msg
;
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"));
182 if (cores_alive
== 0)
185 ReplyMsg(&deathMessage
->mm_Message
);
188 FreeMyMessage(&msgPool
, msg
);
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
);
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
);
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
);
221 struct tileWork
*work
= (struct tileWork
*)REMHEAD(&workList
);
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
);
247 if (deathMessage
== NULL
)
249 struct MyMessage
*m
= AllocMyMessage(&msgPool
);
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
);
269 D(bug("[SMP-Smallpt-Renderer] goodbye!\n"));