Welcome to Fractal Forums

Fractal Software => Programming => Topic started by: ker2x on October 19, 2017, 07:30:44 AM




Title: pipelines pattern
Post by: ker2x on October 19, 2017, 07:30:44 AM
Hello hello ! I'm just wondering, anyone played with this https://msdn.microsoft.com/en-us/library/ff963548.aspx?f=255&MSPPError=-2147217396 ?

I always wanted to try something like this to generate buddhabrot.

eg :
generate random complex -> quick rejection test (cardioid and Nth order bulb) -> escape test (interation) -> draw orbit -> merge with display -> post process display (gamma/brightness/contrast)


Title: Re: pipelines pattern
Post by: ker2x on October 20, 2017, 07:23:17 AM
It's surprisingly easy to use.

Exemple of 2 stage pipeline :

Code:
            var buffer1 = new BlockingCollection<double>(512);
            var f = new TaskFactory(TaskCreationOptions.LongRunning,
                                                     TaskContinuationOptions.None);
            var stage1 = f.StartNew(() => Buddhapipeline.RandomGenerator(buffer1, 32));
            var stage2 = f.StartNew(() => Buddhapipeline.PointGenerator(buffer1, pBackBuffer));


Then you create a bunch of static method that produce/consume using "add" to add item in a queue.
And "take" or a "foreach(var item in intput.GetConsumingEnumerable()) {...}" loop to consume.


Title: Re: pipelines pattern
Post by: ker2x on October 20, 2017, 11:36:16 AM
a more useful sample :

Code:
            //Pipeline are magic <3
            var bufferRandom = new BlockingCollection<double>(4096);
            var bufferComplex = new BlockingCollection<Complex>(4096);
            var bufferFiltered = new BlockingCollection<Complex>(4096);
            var bufferFiltered2 = new BlockingCollection<Complex>(4096);
            var bufferBmp = new BlockingCollection<Tuple<int, int>>(4096);

            var f = new TaskFactory(TaskCreationOptions.LongRunning, TaskContinuationOptions.None);
            var stage1 = f.StartNew(() => Buddhapipeline.RandomGenerator(bufferRandom, 32));
            var stage2 = f.StartNew(() => Buddhapipeline.ComplexGenerator(bufferRandom, bufferComplex, -2, 1.0, -1.5, 1.5));
            var stage3 = f.StartNew(() => Buddhapipeline.quickRejectionFilter(bufferComplex, bufferFiltered));
            var stage4 = f.StartNew(() => Buddhapipeline.iterativeRejectionFilter(bufferFiltered, bufferFiltered2));
            var stage5 = f.StartNew(() => Buddhapipeline.complexToBmp(bufferFiltered2, bufferBmp, -2, 1.0, -1.5, 1.5, imageWidth, imageHeight));
            var stage6 = f.StartNew(() => Buddhapipeline.pointToScreen(bufferBmp, pBackBuffer));

And 2 sample consumer/producer :

Code:
        /*
         * quick rejection filter
         */
         public static void quickRejectionFilter(BlockingCollection<Complex> input, BlockingCollection<Complex> output)
        {
            foreach(var item in input.GetConsumingEnumerable())
            {
                if (Complex.Abs(item) > 2.0) continue;
                if (((Complex.Abs(item - new Complex(-1, 0))) < 0.25)) continue;
                if ((Complex.Abs(1.0 - Complex.Sqrt(Complex.One - (4 * item))) < 1.0)) continue; //may be wrong
                if ((((item.Real + 1.309) * (item.Real + 1.309)) + item.Imaginary * item.Imaginary) < 0.00345) continue;
                if ((((item.Real + 0.125) * (item.Real + 0.125)) + (item.Imaginary - 0.744) * (item.Imaginary - 0.744)) < 0.0088) continue;
                if ((((item.Real + 0.125) * (item.Real + 0.125)) + (item.Imaginary + 0.744) * (item.Imaginary + 0.744)) < 0.0088) continue;
 
                //We tried every known quick filter and didn't reject the item, adding it to next queue.
                output.Add(item);
            }
        }

        /* iterative rejection filter */
        public static void iterativeRejectionFilter(BlockingCollection<Complex> input, BlockingCollection<Complex> output)
        {
            foreach (var item in input.GetConsumingEnumerable())
            {
                int iter = 0;
                Complex z = Complex.Zero;
                while ((Complex.Abs(z) < 4.0) && (iter < 2000))
                {
                    iter++;
                    z = z * z + item;
                }
                if (iter == 2000) continue;

                //We tried, couldn't reject it, adding it to next queue
                output.Add(item);
            }
        }


Title: Re: pipelines pattern
Post by: ker2x on October 20, 2017, 12:52:33 PM
i finished most of the code before i knew it :o

(https://i.imgur.com/JYeWOSV.jpg)


Title: Re: pipelines pattern
Post by: ker2x on October 21, 2017, 07:21:15 AM
tadaaaa ! superheavily multithreaded, very reactive, only the luminosity and  contrast works and no zoom yet.

BUT

IT

WORKS!

(https://i.imgur.com/X0fvSWU.jpg)


Title: Re: pipelines pattern
Post by: ker2x on October 21, 2017, 02:48:21 PM
in action. I added nice bar to the bottom left to monitor thread starvation / empty pipeline

https://www.youtube.com/watch?v=-T6wy7xLxmE&feature=youtu.be