private void Apply(TextureArray2D src, TextureArray2D dst, int dirX, int dirY)
        {
            quad.Bind(false);
            var dev = Device.Get();

            dev.Pixel.Set(shader.Pixel);

            cbuffer.SetData(new DirSizeData
            {
                DirX  = dirX,
                DirY  = dirY,
                SizeX = src.Size.Width,
                SizeY = src.Size.Height
            });

            dev.Pixel.SetConstantBuffer(0, cbuffer.Handle);
            dev.SetViewScissors(dst.Size.Width, dst.Size.Height);

            foreach (var lm in src.LayerMipmap.LayersOfMipmap(0))
            {
                dev.Pixel.SetShaderResource(0, src.GetSrView(lm));
                dev.OutputMerger.SetRenderTargets(dst.GetRtView(lm));
                dev.DrawQuad();
            }

            dev.Pixel.SetShaderResource(0, null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);
            quad.Unbind();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// copies a single mip from one layer of a texture to another layer of a texture. The formats don't have to match
        /// </summary>
        /// <param name="src">source texture</param>
        /// <param name="srcLayer"></param>
        /// <param name="srcMip"></param>
        /// <param name="dst">destination texture</param>
        /// <param name="dstLayer"></param>
        /// <param name="dstMip"></param>
        public void CopyLayer(TextureArray2D src, int srcLayer, int srcMip, TextureArray2D dst, int dstLayer,
                              int dstMip)
        {
            Debug.Assert(src.Size == dst.Size);

            var dev = DirectX.Device.Get();

            quad.Bind(false);
            dev.Pixel.Set(convert2D.Pixel);

            dev.Pixel.SetShaderResource(0, src.View);


            cbuffer.SetData(new LayerLevelOffsetData
            {
                Layer      = srcLayer,
                Level      = srcMip,
                Xoffset    = 0,
                Yoffset    = 0,
                Multiplier = 1.0f
            });

            var dim = dst.Size.GetMip(dstMip);

            dev.Pixel.SetConstantBuffer(0, cbuffer.Handle);
            dev.OutputMerger.SetRenderTargets(dst.GetRtView(dstLayer, dstMip));
            dev.SetViewScissors(dim.Width, dim.Height);
            dev.DrawQuad();

            // remove bindings
            dev.Pixel.SetShaderResource(0, null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);
        }
Ejemplo n.º 3
0
        /// converts a cubemap texture to a lat long map
        public TextureArray2D ConvertToLatLong(TextureArray2D cube, int resolution)
        {
            Debug.Assert(cube.NumLayers == 6);

            var dst = new TextureArray2D(LayerMipmapCount.One, new Size3(resolution, Math.Max(resolution / 2, 1)), Format.R32G32B32A32_Float, false);

            var dev = Device.Get();

            quad.Bind(false);
            dev.Pixel.Set(toLatLong.Pixel);

            var dim = dst.Size;

            dev.Pixel.SetShaderResource(0, cube.GetCubeView(0));
            dev.Pixel.SetSampler(0, sampler);
            dev.OutputMerger.SetRenderTargets(dst.GetRtView(LayerMipmapSlice.Mip0));
            dev.SetViewScissors(dim.Width, dim.Height);
            dev.DrawQuad();

            dev.Pixel.SetShaderResource(0, null);
            dev.Pixel.SetSampler(0, null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);
            quad.Unbind();

            return(dst);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// for unit testing purposes. Converts naked srv to TextureArray2D
        /// </summary>
        internal TextureArray2D ConvertFromRaw(SharpDX.Direct3D11.ShaderResourceView srv, Size3 size, SharpDX.DXGI.Format dstFormat)
        {
            var res = new TextureArray2D(1, 1, size, dstFormat, false);

            var dev = DirectX.Device.Get();

            quad.Bind(false);
            dev.Pixel.Set(convert2D.Pixel);

            dev.Pixel.SetShaderResource(0, srv);

            cbuffer.SetData(new LayerLevelOffsetData
            {
                Layer      = 0,
                Level      = 0,
                Xoffset    = 0,
                Yoffset    = 0,
                Multiplier = 1.0f
            });

            dev.Pixel.SetConstantBuffer(0, cbuffer.Handle);
            dev.OutputMerger.SetRenderTargets(res.GetRtView(0, 0));
            dev.SetViewScissors(size.Width, size.Height);
            dev.DrawQuad();

            // remove bindings
            dev.Pixel.SetShaderResource(0, null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);
            quad.Unbind();

            return(res);
        }
Ejemplo n.º 5
0
        private async Task CreateGifAsync(TextureArray2D left, TextureArray2D right, Config cfg, IProgress progress)
        {
            // delay in milliseconds
            var numFrames = cfg.FramesPerSecond * cfg.NumSeconds;

            try
            {
                progressModel.EnableDllProgress = false;
                var leftView  = left.GetSrView(LayerMipmapSlice.Mip0);
                var rightView = right.GetSrView(LayerMipmapSlice.Mip0);

                var curProg = progress.CreateSubProgress(0.9f);
                // create frames
                using (var dst = IO.CreateImage(new ImageFormat(Format.R8G8B8A8_UNorm_SRgb), left.Size, LayerMipmapCount.One))
                {
                    var dstMip  = dst.GetMipmap(LayerMipmapSlice.Mip0);
                    var dstPtr  = dstMip.Bytes;
                    var dstSize = dstMip.ByteSize;

                    // render frames into texture
                    using (var frame = new TextureArray2D(LayerMipmapCount.One, left.Size,
                                                          Format.R8G8B8A8_UNorm_SRgb, false))
                    {
                        var frameView = frame.GetRtView(LayerMipmapSlice.Mip0);

                        for (int i = 0; i < numFrames; ++i)
                        {
                            float t         = (float)i / (numFrames);
                            int   borderPos = (int)(t * frame.Size.Width);

                            // render frame
                            shader.Run(leftView, rightView, frameView, cfg.SliderWidth, borderPos,
                                       frame.Size.Width, frame.Size.Height);

                            // save frame as png
                            frame.CopyPixels(LayerMipmapSlice.Mip0, dstPtr, dstSize);
                            var filename = $"{cfg.TmpFilename}{i:D4}";
                            await Task.Run(() => IO.SaveImage(dst, filename, "png", GliFormat.RGBA8_SRGB), progress.Token);

                            curProg.Progress = i / (float)numFrames;
                            curProg.What     = "creating frames";
                        }
                    }
                }

                // convert video
                await FFMpeg.ConvertAsync(cfg, progress.CreateSubProgress(1.0f));
            }
            finally
            {
                progressModel.EnableDllProgress = true;
            }
        }
Ejemplo n.º 6
0
        // converts a lat long texture to a cubemap
        public TextureArray2D ConvertToCube(TextureArray2D latlong, int resolution)
        {
            Debug.Assert(latlong.NumLayers == 1);

            var dst = new TextureArray2D(new LayerMipmapCount(6, 1), new Size3(resolution, resolution), Format.R32G32B32A32_Float, false);

            var dev = Device.Get();

            quad.Bind(false);
            dev.Pixel.Set(toCube.Pixel);

            dev.Pixel.SetShaderResource(0, latlong.GetSrView(LayerMipmapSlice.Mip0));
            dev.Pixel.SetSampler(0, sampler);
            dev.OutputMerger.SetRenderTargets(null,
                                              dst.GetRtView(new LayerMipmapSlice(0, 0)),
                                              dst.GetRtView(new LayerMipmapSlice(1, 0)),
                                              dst.GetRtView(new LayerMipmapSlice(2, 0)),
                                              dst.GetRtView(new LayerMipmapSlice(3, 0)),
                                              dst.GetRtView(new LayerMipmapSlice(4, 0)),
                                              dst.GetRtView(new LayerMipmapSlice(5, 0)));
            dev.SetViewScissors(resolution, resolution);
            dev.DrawQuad();

            dev.Pixel.SetShaderResource(0, null);
            dev.Pixel.SetSampler(0, null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);
            quad.Unbind();

            return(dst);
        }
Ejemplo n.º 7
0
        public TextureArray2D ConvertToArray(Texture3D src, int fixedAxis1, int fixedAxis2, UploadBuffer cbuffer, int startLayer = 0, int numLayers = -1)
        {
            Debug.Assert(fixedAxis1 >= 0 && fixedAxis1 <= 2);
            Debug.Assert(fixedAxis2 >= 0 && fixedAxis2 <= 2);
            var dim       = src.Size;
            var layerAxis = 3 - fixedAxis1 - fixedAxis2;

            if (numLayers < 0)
            {
                numLayers = dim[layerAxis] - startLayer;
            }

            var dst = new TextureArray2D(
                new LayerMipmapCount(numLayers, 1),
                new Size3(dim[fixedAxis1], dim[fixedAxis2]),
                Format.R32G32B32A32_Float, false
                );

            var data = new LayerBufferData
            {
                XAxis = fixedAxis1,
                YAxis = fixedAxis2
            };

            var dev = Device.Get();

            quad.Bind(false);
            dev.Pixel.Set(shaderLayer.Pixel);
            dev.Pixel.SetShaderResource(0, src.GetSrView(0));
            dev.SetViewScissors(dst.Size.Width, dst.Size.Height);

            foreach (var lm in dst.LayerMipmap.Range)
            {
                data.ZValue = lm.Layer + startLayer;
                cbuffer.SetData(data);
                dev.Pixel.SetConstantBuffer(0, cbuffer.Handle);
                dev.OutputMerger.SetRenderTargets(dst.GetRtView(lm));

                dev.DrawFullscreenTriangle(1);
            }

            quad.Unbind();
            dev.Pixel.SetShaderResource(0, null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);

            return(dst);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// for unit testing purposes. Converts naked srv to TextureArray2D
        /// </summary>
        internal TextureArray2D ConvertFromRaw(SharpDX.Direct3D11.ShaderResourceView srv, Size3 size, SharpDX.DXGI.Format dstFormat, bool isInteger)
        {
            var res = new TextureArray2D(LayerMipmapCount.One, size, dstFormat, false);

            var dev = DirectX.Device.Get();

            quad.Bind(false);
            if (isInteger)
            {
                if (convert2DInt == null)
                {
                    convert2DInt = new DirectX.Shader(DirectX.Shader.Type.Pixel, GetSource(new ShaderBuilder2D("int4")), "ConvertInt");
                }
                dev.Pixel.Set(convert2DInt.Pixel);
            }
            else
            {
                dev.Pixel.Set(convert2D.Pixel);
            }

            dev.Pixel.SetShaderResource(0, srv);

            cbuffer.SetData(new LayerLevelOffsetData
            {
                Layer      = 0,
                Level      = 0,
                Xoffset    = 0,
                Yoffset    = 0,
                Multiplier = 1.0f,
                UseOverlay = 0,
                Scale      = 1
            });

            dev.Pixel.SetConstantBuffer(0, cbuffer.Handle);
            dev.OutputMerger.SetRenderTargets(res.GetRtView(LayerMipmapSlice.Mip0));
            dev.SetViewScissors(size.Width, size.Height);
            dev.DrawQuad();

            // remove bindings
            dev.Pixel.SetShaderResource(0, null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);
            quad.Unbind();

            return(res);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// creates a thumbnail for one image layer/mipmap
        /// </summary>
        /// <param name="size">maximum width/height of the thumbnail</param>
        /// <param name="texture">source texture</param>
        /// <param name="dstFormat">destination texture format</param>
        /// <param name="layer">source layer</param>
        /// <returns>texture with width, height smaller or equal to size. One layer and one mipmap</returns>
        public TextureArray2D CreateThumbnail(int size, ITexture texture,
                                              SharpDX.DXGI.Format dstFormat, int layer, ScalingModel scaling)
        {
            Debug.Assert(ImageFormat.IsSupported(dstFormat));
            Debug.Assert(ImageFormat.IsSupported(texture.Format));

            // determine dimensions of output texture
            var width  = 0;
            var height = 0;

            if (texture.Size.Width > texture.Size.Height)
            {
                width  = size;
                height = (texture.Size.Height * size) / texture.Size.Width;
            }
            else
            {
                height = size;
                width  = (texture.Size.Width * size) / texture.Size.Height;
            }
            Debug.Assert(width <= size);
            Debug.Assert(height <= size);

            var res = new TextureArray2D(LayerMipmapCount.One, new Size3(width, height), dstFormat, false);

            // compute which mipmap has the closest fit
            var mipmap   = 0;
            var curWidth = texture.Size.Width;

            while (curWidth >= width)
            {
                ++mipmap;
                curWidth /= 2;
            }
            // mipmap just jumped over the optimal size
            mipmap = Math.Max(0, mipmap - 1);

            var      dev    = Device.Get();
            ITexture tmpTex = null;

            if (texture.NumMipmaps < mipmap + 1)
            {
                // generate new texture with mipmaps
                tmpTex = texture.CloneWithMipmaps(mipmap + 1);

                scaling.WriteMipmaps(tmpTex);
                dev.Pixel.SetShaderResource(0, tmpTex.GetSrView(new LayerMipmapSlice(layer, mipmap)));
            }
            else
            {
                dev.Pixel.SetShaderResource(0, texture.GetSrView(new LayerMipmapSlice(layer, mipmap)));
            }

            quad.Bind(false);
            if (texture.Is3D)
            {
                dev.Pixel.Set(convert3D.Pixel);
            }
            else
            {
                dev.Pixel.Set(convert2D.Pixel);
            }

            dev.Pixel.SetSampler(0, sampler);

            dev.OutputMerger.SetRenderTargets(res.GetRtView(LayerMipmapSlice.Mip0));
            dev.SetViewScissors(width, height);
            dev.DrawFullscreenTriangle(1);

            // remove bindings
            dev.Pixel.SetShaderResource(0, null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);
            quad.Unbind();

            tmpTex?.Dispose();

            return(res);
        }
Ejemplo n.º 10
0
        private async Task CreateGifAsync(Config cfg, IProgress progress, SharedModel shared)
        {
            // delay in milliseconds
            var numFrames = cfg.FramesPerSecond * cfg.NumSeconds;
            var left      = cfg.Left;
            var right     = cfg.Right;
            var overlay   = cfg.Overlay;

            // size compatible?
            bool disposeImages = false;

            if ((left.Size.Width % 2) != 0 || (left.Size.Height % 2) != 0)
            {
                disposeImages = true;
                var pad = Size3.Zero;
                pad.X = left.Size.Width % 2;
                pad.Y = left.Size.Height % 2;
                left  = (TextureArray2D)shared.Padding.Run(left, Size3.Zero, pad, PaddingShader.FillMode.Clamp, null, shared, false);
                right = (TextureArray2D)shared.Padding.Run(right, Size3.Zero, pad, PaddingShader.FillMode.Clamp, null, shared, false);
                if (overlay != null)
                {
                    overlay = (TextureArray2D)shared.Padding.Run(overlay, Size3.Zero, pad,
                                                                 PaddingShader.FillMode.Transparent, null, shared, false);
                }

                Debug.Assert(left.Size.Width % 2 == 0 && left.Size.Height % 2 == 0);
            }

            try
            {
                progressModel.EnableDllProgress = false;
                var leftView    = left.GetSrView(LayerMipmapSlice.Mip0);
                var rightView   = right.GetSrView(LayerMipmapSlice.Mip0);
                var overlayView = overlay?.GetSrView(LayerMipmapSlice.Mip0);

                var curProg = progress.CreateSubProgress(0.9f);

                // prepare parallel processing
                var numTasks = Environment.ProcessorCount;
                var tasks    = new Task[numTasks];
                var images   = new DllImageData[numTasks];
                for (int i = 0; i < numTasks; ++i)
                {
                    images[i] = IO.CreateImage(new ImageFormat(Format.R8G8B8A8_UNorm_SRgb), left.Size,
                                               LayerMipmapCount.One);
                }
                int   textSize = left.Size.Y / 18;
                float padding  = textSize / 4.0f;

                // render frames into texture
                using (var frame = new TextureArray2D(LayerMipmapCount.One, left.Size,
                                                      Format.R8G8B8A8_UNorm_SRgb, false))
                {
                    var frameView = frame.GetRtView(LayerMipmapSlice.Mip0);
                    using (var d2d = new Direct2D(frame))
                    {
                        for (int i = 0; i < numFrames; ++i)
                        {
                            float t         = (float)i / (numFrames - 1);
                            int   borderPos = (int)(t * (frame.Size.Width - 1));
                            int   idx       = i % numTasks;

                            // render frame
                            shader.Run(leftView, rightView, overlayView, frameView, cfg.SliderWidth, borderPos,
                                       frame.Size.Width, frame.Size.Height, shared.QuadShader, shared.Upload);

                            // add text
                            using (var c = d2d.Begin())
                            {
                                c.Text(new Float2(padding), new Float2(left.Size.X - padding, left.Size.Y - padding),
                                       textSize, Colors.White, cfg.Label1, TextAlignment.Leading);

                                c.Text(new Float2(padding), new Float2(left.Size.X - padding, left.Size.Y - padding), textSize,
                                       Colors.White, cfg.Label2, TextAlignment.Trailing);
                            }

                            // copy frame from gpu to cpu
                            var dstMip  = images[idx].GetMipmap(LayerMipmapSlice.Mip0);
                            var dstPtr  = dstMip.Bytes;
                            var dstSize = dstMip.ByteSize;

                            // wait for previous task to finish before writing it to the file
                            if (tasks[idx] != null)
                            {
                                await tasks[idx];
                            }

                            frame.CopyPixels(LayerMipmapSlice.Mip0, dstPtr, dstSize);
                            var filename = $"{cfg.TmpFilename}{i:D4}";

                            // write to file
                            tasks[idx] = Task.Run(() =>
                            {
                                try
                                {
                                    IO.SaveImage(images[idx], filename, "png", GliFormat.RGBA8_SRGB);
                                }
                                catch (Exception)
                                {
                                    // ignored (probably cancelled by user)
                                }
                            }, progress.Token);

                            curProg.Progress = i / (float)numFrames;
                            curProg.What     = "creating frames";

                            progress.Token.ThrowIfCancellationRequested();
                        }
                    }
                }

                // wait for tasks to finish
                for (var i = 0; i < tasks.Length; i++)
                {
                    if (tasks[i] != null)
                    {
                        await tasks[i];
                    }
                    tasks[i] = null;
                }

                // convert video
                await FFMpeg.ConvertAsync(cfg, progress.CreateSubProgress(1.0f));
            }
            finally
            {
                progressModel.EnableDllProgress = true;

                if (disposeImages)
                {
                    left.Dispose();
                    right.Dispose();
                    overlay?.Dispose();
                }
            }
        }