private void ResultFunc( IPixelBuffer pixelBuffer, RendererData rendererData, ConcurrentQueue <RenderLineResult> resultQueue, AutoResetEvent queueDataAvailableEvent) { var incompleteRows = new HashSet <int>(); for (var y = 0; y < pixelBuffer.Height; y++) { incompleteRows.Add(y); } while (incompleteRows.Count > 0) { queueDataAvailableEvent.WaitOne(TimeSpan.FromMilliseconds(1000)); while (resultQueue.TryDequeue(out var renderLineResult)) { foreach (var data in renderLineResult.RowPixels) { rendererData.SetPixelData(data); } // assert pixelArray.Width == renderLineResult.Count pixelBuffer.SetPixelRowColors(renderLineResult.Y, renderLineResult.RowPixels.Select(x => x.Color)); incompleteRows.Remove(renderLineResult.Y); var totalRows = Convert.ToSingle(pixelBuffer.Height); var completeRows = Convert.ToSingle(pixelBuffer.Height - incompleteRows.Count); var percentComplete = completeRows / totalRows * 100.0f; Console.WriteLine($"Percent Complete: {percentComplete:F}%"); Progress?.Invoke(this, new RenderProgressEventArgs(percentComplete)); } } }
private void ResultFunc( IPixelBuffer pixelBuffer, RendererData rendererData, ConcurrentQueue <RenderResult> resultQueue, AutoResetEvent queueDataAvailableEvent) { try { var incompletePixels = new HashSet <Tuple <int, int> >(); for (var y = 0; y < pixelBuffer.Height; y++) { for (int x = 0; x < pixelBuffer.Width; x++) { incompletePixels.Add(Tuple.Create(x, y)); } } var totalPixels = Convert.ToSingle(pixelBuffer.Height * pixelBuffer.Width); int previousPercent = 0; while (incompletePixels.Count > 0) { queueDataAvailableEvent.WaitOne(TimeSpan.FromMilliseconds(1000)); while (resultQueue.TryDequeue(out var renderResult)) { rendererData.SetPixelData(renderResult.PixelData); // assert pixelArray.Width == renderLineResult.Count pixelBuffer.SetPixelColor(renderResult.X, renderResult.Y, renderResult.PixelData.Color); incompletePixels.Remove(Tuple.Create(renderResult.X, renderResult.Y)); var completePixels = Convert.ToSingle(totalPixels - incompletePixels.Count); var percentComplete = completePixels / totalPixels * 100.0f; int intPercent = Convert.ToInt32(percentComplete); if (intPercent > previousPercent) { previousPercent = intPercent; Console.WriteLine($"Percent Complete: {percentComplete:F}%"); Progress?.Invoke(this, new RenderProgressEventArgs(percentComplete)); } } } } catch (Exception ex) { Console.WriteLine(ex); } }
private RendererData RenderMultiThreaded( IPixelBuffer pixelArray, Camera camera, IHitable world, IHitable lightHitable, RenderConfig renderConfig, Func <Ray, ColorVector> backgroundFunc) { var rendererData = new RendererData(pixelArray.Width, pixelArray.Height); var rayTracer = new RayTracer(camera, world, lightHitable, renderConfig, pixelArray.Width, pixelArray.Height, backgroundFunc); ThreadPool.SetMinThreads(renderConfig.NumThreads * 3, renderConfig.NumThreads * 3); var queueDataAvailableEvent = new AutoResetEvent(false); var inputQueue = new ConcurrentQueue <RenderInput>(); var resultQueue = new ConcurrentQueue <RenderResult>(); for (var y = pixelArray.Height - 1; y >= 0; y--) { for (var x = 0; x < pixelArray.Width; x++) { inputQueue.Enqueue(new RenderInput(x, y)); } } var tasks = new List <Task>(); try { for (var thid = 0; thid < renderConfig.NumThreads; thid++) { Console.WriteLine($"Creating task for thread id: {thid}"); tasks.Add( Task.Run(() => RenderFunc(rayTracer, inputQueue, resultQueue, queueDataAvailableEvent))); } tasks.Add(Task.Run(() => ResultFunc(pixelArray, rendererData, resultQueue, queueDataAvailableEvent))); Task.WaitAll(tasks.ToArray()); } catch (Exception ex) { Console.WriteLine(ex); } return(rendererData); }