diff options
| author | James Barnett <noreply@jamesbarnett.xyz> | 2022-01-02 18:23:36 +0000 |
|---|---|---|
| committer | James Barnett <noreply@jamesbarnett.xyz> | 2022-01-02 18:23:36 +0000 |
| commit | e075667cd2dc878dd9dceb07c85719f6712bcda1 (patch) | |
| tree | 414e76418d92a39c59b1f5faf08289c0a729ddb4 /src/RaytraceDispatcher.ts | |
| parent | 7ad1b7efabea1349107669a432e6c88305f8d825 (diff) | |
| download | js-raytracer-e075667cd2dc878dd9dceb07c85719f6712bcda1.tar.xz js-raytracer-e075667cd2dc878dd9dceb07c85719f6712bcda1.zip | |
Implement multi-threaded rendering
Diffstat (limited to 'src/RaytraceDispatcher.ts')
| -rw-r--r-- | src/RaytraceDispatcher.ts | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/RaytraceDispatcher.ts b/src/RaytraceDispatcher.ts new file mode 100644 index 0000000..866d2d1 --- /dev/null +++ b/src/RaytraceDispatcher.ts @@ -0,0 +1,70 @@ +import {Colour} from './Colour'; +import {Framebuffer} from './Framebuffer'; +import {RaytraceContext} from './RaytraceContext'; +import {instanceToPlain} from 'class-transformer'; +import 'reflect-metadata'; + +export class RaytraceDispatcher { + private renderStartMs: number; + private responsesReceived = 0; + constructor( + readonly framebuffer: Framebuffer, + readonly context: RaytraceContext + ) { + this.renderStartMs = new Date().getTime(); + } + + requestRender() { + // Assumes height and threads are always even + const rowBatchSize = this.context.height / this.context.options.numThreads; + + for (let y = 0; y < this.context.height; y += rowBatchSize) { + const rowStartIndex = y; + const rowEndIndex = y + rowBatchSize - 1; + this.dispatchRaytraceWorker(rowStartIndex, rowEndIndex, this.context); + } + } + + private dispatchRaytraceWorker( + rowStartIndex: number, + rowEndIndex: number, + context: RaytraceContext + ) { + console.log( + `Dispatching worker for lines ${rowStartIndex} to ${rowEndIndex}` + ); + + const raytracer = new Worker(new URL('./Raytracer.ts', import.meta.url)); + + raytracer.postMessage({ + type: 'raytraceStart', + rowStartIndex: rowStartIndex, + rowEndIndex: rowEndIndex, + context: JSON.stringify(instanceToPlain(context)), + }); + + raytracer.onmessage = ({data}) => { + if (data.type === 'raytraceResultRow') { + this.processResponse(data.rowIndex, data.resultBuffer); + } + if (data.type === 'raytraceComplete') { + this.handleWorkerComplete(); + } + }; + } + + private handleWorkerComplete() { + if (++this.responsesReceived === this.context.options.numThreads) { + console.log( + `Render completed in ${new Date().getTime() - this.renderStartMs}ms` + ); + } + } + + private processResponse(rowIndex: number, rowData: Colour[]) { + for (let x = 0; x < this.framebuffer.width; x++) { + this.framebuffer.writePixelAt(x, rowIndex, rowData[x]); + } + this.framebuffer.flush(); + } +} |