Ejemplo n.º 1
0
        /// <summary>
        /// Consumer-producer based multithreading work distribution
        /// Each thread waits for a new Assignment to be added to availableAssignments queue
        /// Most of the time is number of items in availableAssignments expected to be several times larger than number of threads
        /// </summary>
        protected void Consume()
        {
            // Set TLS.
            MT.InitThreadData();
            MT.SetRendering(scene, imageFunction, renderer);

            // Animation time (fore debugging animated scenes).
            if (scene is ITimeDependent sc)
            {
                sc.Time = 0.0;
            }

            while (!availableAssignments.IsEmpty ||
                   finishedAssignments < totalNumberOfAssignments - threads ||
                   NetworkWorker.assignmentsAtClients > 0)
            {
                availableAssignments.TryDequeue(out Assignment newAssignment);

                if (!progressData.Continue) // test whether rendering should end (Stop button pressed)
                {
                    return;
                }

                if (newAssignment == null) // TryDequeue was not successful
                {
                    continue;
                }

                float[] colorArray = newAssignment.Render(false, renderer, progressData);
                BitmapMerger(colorArray, newAssignment.x1, newAssignment.y1, newAssignment.x2 + 1, newAssignment.y2 + 1);

                if (newAssignment.stride == 1)
                {
                    finishedAssignments++;
                    assignmentRoundsFinished++;
                }
                else
                {
                    newAssignment.stride >>= 1; // stride values: 8 > 4 > 2 > 1
                    assignmentRoundsFinished++;
                    availableAssignments.Enqueue(newAssignment);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Shoots single primary ray only
        /// </summary>
        /// <param name="x">X-coordinate inside the raster image</param>
        /// <param name="y">Y-coordinate inside the raster image</param>
        private void singleSample(int x, int y)
        {
            MT.singleRayTracing = true;
            rayVisualizer.Reset();

            // determine output image size:
            ActualWidth = ImageWidth;
            if (ActualWidth <= 0)
            {
                ActualWidth = panel1.Width;
            }
            ActualHeight = ImageHeight;
            if (ActualHeight <= 0)
            {
                ActualHeight = panel1.Height;
            }

            if (dirty || imfs == null)
            {
                int ss = 1;

                // Force preprocess.
                ctx = null;

                _ = FormSupport.getScene(
                    out _, out _,
                    ref ActualWidth,
                    ref ActualHeight,
                    ref ss,
                    TextParam.Text);

                sc = FormSupport.getScene(
                    out imfs,
                    out rend,
                    ref ActualWidth,
                    ref ActualHeight,
                    ref ss,
                    TextParam.Text);

                // IImageFunction.
                if (imfs == null) // not defined in the script
                {
                    imfs = getImageFunction(imfs, sc);
                }
                else
                if (imfs is RayCasting imfray)
                {
                    imfray.Scene = sc;
                }
                imfs.Width  = ActualWidth;
                imfs.Height = ActualHeight;

                // IRenderer.
                if (rend == null) // not defined in the script
                {
                    rend = getRenderer();
                }
                rend.ImageFunction = imfs;
                rend.Width         = ActualWidth;
                rend.Height        = ActualHeight;
                rend.Adaptive      = 0; // 8?
                rend.ProgressData  = progress;

                dirty = false;
            }

            // Set TLS.
            MT.SetRendering(sc, imfs, rend);

            double[] color = new double[3];
            long     hash  = imfs.GetSample(x + 0.5, y + 0.5, color);

            labelSample.Text = string.Format(CultureInfo.InvariantCulture,
                                             "Sample at [{0},{1}] = [{2:f},{3:f},{4:f}], {5:X}",
                                             x, y, color[0], color[1], color[2], hash);

            // Reset TLS.
            MT.ResetRendering();

            rayVisualizer.AddingRaysFinished();

            MT.singleRayTracing = false;
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates threadpool and starts all threads on Consume method
        /// Thread which calls this method will take care of preparing assignments and receiving rendered images from RenderClients meanwhile
        /// </summary>
        public void RunThreads()
        {
            pool = new Thread[MT.threads];

            AssignNetworkWorkerToStream();

            WaitHandle[] waitHandles = new WaitHandle[MT.threads];

            // Multiply animated instances.
            int i;

            // Scene definitions.
            if (scenes[0] is ITimeDependent scenea)
            {
                scenea.Time = time;
                scenes      = new IRayScene[MT.threads];
                for (i = 0; i < MT.threads; i++)
                {
                    scenes[i] = i == 0 ? (IRayScene)scenea : (IRayScene)scenea.Clone();
                }
            }

            // Image functions.
            if (imageFunctions[0] is ITimeDependent imfa)
            {
                imfa.Time      = time;
                imageFunctions = new IImageFunction[MT.threads];
                for (i = 0; i < MT.threads; i++)
                {
                    imageFunctions[i] = i == 0 ? (IImageFunction)imfa : (IImageFunction)imfa.Clone();
                }
            }

            // Renderers.
            if (renderers[0] is ITimeDependent renda)
            {
                renda.Time = time;
                renderers  = new IRenderer[MT.threads];
                for (i = 0; i < MT.threads; i++)
                {
                    renderers[i] = i == 0 ? (IRenderer)renda : (IRenderer)renda.Clone();
                }
            }

            for (i = 0; i < MT.threads; i++)
            {
                EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset);

                // Thread-specific instances: thread's id.
                int tid = i;

                Thread newThread = new Thread(() =>
                {
                    // Set TLS.
                    MT.threadID = tid;
                    MT.InitThreadData();
                    MT.SetRendering(
                        scenes[Math.Min(tid, scenes.Length - 1)],
                        imageFunctions[Math.Min(tid, imageFunctions.Length - 1)],
                        renderers[Math.Min(tid, renderers.Length - 1)]);

                    Consume();

                    // Signal finishing the work.
                    handle.Set();
                });

                newThread.Name = "RenderThread #" + i;
                pool[i]        = newThread;
                newThread.Start();

                waitHandles[i] = handle;
            }

            mainRenderThread = pool[0];

            Thread imageReceiver = new Thread(RenderedImageReceiver);

            imageReceiver.Name = "ImageReceiver";
            imageReceiver.Start();

            WaitHandle.WaitAll(waitHandles);

            if (networkWorkers?.Count > 0)
            {
                foreach (NetworkWorker worker in networkWorkers) // sends ending assignment to all clients
                {
                    worker.SendSpecialAssignment(Assignment.AssignmentType.Ending);
                }
            }

            // Reset the pool-thread.
            pool = null;
        }