public NNedi3Kernel(NNedi3Kernel config)
     : base(config)
 {
     NeuronCount   = config.NeuronCount;
     ReloadWeights = config.ReloadWeights;
     Buffer        = config.Buffer;
 }
            public NNediKernelHandle(NNedi3Kernel parameters, IShaderDefinition <IKernel> definition, bool horizontal)
                : base(parameters, definition)
            {
                m_NeuronCount   = parameters.NeuronCount;
                m_ReloadWeights = parameters.ReloadWeights;
                m_Horizontal    = horizontal;

                m_Buffer = parameters.Buffer;
            }
            protected override ITextureFilter CreateFilter(ITextureFilter input)
            {
                if (!Renderer.IsOpenClAvail || Renderer.RenderQuality.PerformanceMode())
                {
                    Renderer.FallbackOccurred = true; // Warn user via player stats OSD
                    return(input);                    // OpenCL is not available, or UNORM8 textures used (not supported); fallback
                }

                Func <TextureSize, TextureSize> transformWidth  = s => new TextureSize(2 * s.Width, s.Height);
                Func <TextureSize, TextureSize> transformHeight = s => new TextureSize(s.Width, 2 * s.Height);

                var neuronCount1 = s_NeuronCount[(int)Neurons1];
                var neuronCount2 = s_NeuronCount[(int)Neurons2];
                var weights1     = s_Weights[(int)Neurons1];
                var buffer1      = Renderer.CreateClBuffer(weights1);
                var buffer2      = buffer1;

                var differentWeights = neuronCount1 != neuronCount2;

                if (differentWeights)
                {
                    var weights2 = s_Weights[(int)Neurons2];
                    buffer2 = Renderer.CreateClBuffer(weights2);
                }

                var kernel  = GetKernel(); // Note Kernel is reused between different filters
                var shaderH = new NNedi3Kernel(kernel)
                {
                    Horizontal = true, Buffer = buffer1, NeuronCount = neuronCount1, Transform = transformWidth
                };
                var shaderV = new NNedi3Kernel(kernel)
                {
                    Horizontal = false, Buffer = buffer2, NeuronCount = neuronCount2, Transform = transformHeight, ReloadWeights = differentWeights
                };

                var sourceSize = input.Size();

                if ((Renderer.TargetSize <= sourceSize).Any)
                {
                    return(input);
                }

                var composition = input.Decompose();

                var nnedi3H = shaderH.ApplyTo(composition.Luma);
                var nnedi3V = shaderV.ApplyTo(nnedi3H);

                composition = nnedi3V.ComposeWith(composition.Chroma, chromaOffset: new Vector2(-0.25f, -0.25f));
                var result = ChromaScaler.ScaleChroma(composition);

                return(result.Convolve(null, offset: new Vector2(0.5f, 0.5f)));
            }
            public override ITextureFilter ScaleChroma(ICompositionFilter composition)
            {
                DisposeHelper.Dispose(ref m_Buffer1);
                DisposeHelper.Dispose(ref m_Buffer2);

                if (!Renderer.IsOpenClAvail || Renderer.RenderQuality.PerformanceMode())
                {
                    Renderer.FallbackOccurred = true; // Warn user via player stats OSD
                    return(composition);              // OpenCL is not available; fallback
                }

                var lumaSize   = composition.Luma.Size();
                var chromaSize = composition.Chroma.Size();

                if (lumaSize.Width != 2 * chromaSize.Width || lumaSize.Height != 2 * chromaSize.Height)
                {
                    return(composition); // Chroma shouldn't be doubled; fallback
                }
                Func <TextureSize, TextureSize> transformWidth  = s => new TextureSize(2 * s.Width, s.Height);
                Func <TextureSize, TextureSize> transformHeight = s => new TextureSize(s.Width, 2 * s.Height);

                var neuronCount1 = s_NeuronCount[(int)Neurons1];
                var neuronCount2 = s_NeuronCount[(int)Neurons2];

                var weights1 = s_Weights[(int)Neurons1];

                m_Buffer1 = Renderer.CreateClBuffer(weights1);
                var differentWeights = neuronCount1 != neuronCount2;

                if (differentWeights)
                {
                    var weights2 = s_Weights[(int)Neurons2];
                    m_Buffer2 = Renderer.CreateClBuffer(weights2);
                }

                var kernelU = CompileKernel(true);  // Note: compiled shader is shared between filters
                var kernelV = CompileKernel(false); // Note: compiled shader is shared between filters

                var shaderUh = new NNedi3Kernel(kernelU)
                {
                    Horizontal = true, Buffer = m_Buffer1, NeuronCount = neuronCount1, Transform = transformWidth
                };
                var shaderUv = new NNedi3Kernel(kernelU)
                {
                    Horizontal = false, Buffer = m_Buffer2, ReloadWeights = differentWeights, NeuronCount = neuronCount2, Transform = transformHeight
                };
                var shaderVh = new NNedi3Kernel(kernelV)
                {
                    Horizontal = true, Buffer = m_Buffer1, NeuronCount = neuronCount1, Transform = transformWidth
                };
                var shaderVv = new NNedi3Kernel(kernelV)
                {
                    Horizontal = false, Buffer = m_Buffer2, ReloadWeights = differentWeights, NeuronCount = neuronCount2, Transform = transformHeight
                };

                var nnedi3Uh = composition.Chroma.Apply(shaderUh);
                var nnedi3Uv = nnedi3Uh.Apply(shaderUv);

                var nnedi3Vh = composition.Chroma.Apply(shaderVh);
                var nnedi3Vv = nnedi3Vh.Apply(shaderVv);

                return(composition.Luma.MergeWith(nnedi3Uv, nnedi3Vv).ConvertToRgb());
            }