예제 #1
0
        // executes a 3x3 gauss kernel on the given texture mipmap
        public void Run(ITexture texSrc, ITexture texDst, int mipmap, bool hasAlpha, UploadBuffer upload)
        {
            Debug.Assert(texSrc.NumLayers == texDst.NumLayers);
            Debug.Assert(texSrc.NumMipmaps == texDst.NumMipmaps);
            Debug.Assert(texSrc.Size == texDst.Size);

            var dev = Device.Get();

            dev.Compute.Set(texSrc.Is3D ? Shader3D.Compute : Shader.Compute);
            var builder = texSrc.Is3D ? ShaderBuilder.Builder3D : ShaderBuilder.Builder2D;

            var data = new BufferData
            {
                Size     = texSrc.Size.GetMip(mipmap),
                HasAlpha = hasAlpha?1:0,
            };

            foreach (var lm in texSrc.LayerMipmap.LayersOfMipmap(mipmap))
            {
                data.Layer = lm.Layer;
                upload.SetData(data);
                dev.Compute.SetConstantBuffer(0, upload.Handle);
                dev.Compute.SetShaderResource(0, texSrc.GetSrView(lm));
                dev.Compute.SetUnorderedAccessView(0, texDst.GetUaView(mipmap));

                dev.Dispatch(
                    Utility.Utility.DivideRoundUp(data.Size.Width, builder.LocalSizeX),
                    Utility.Utility.DivideRoundUp(data.Size.Height, builder.LocalSizeY),
                    Utility.Utility.DivideRoundUp(data.Size.Depth, builder.LocalSizeZ)
                    );
            }

            dev.Compute.SetShaderResource(0, null);
            dev.Compute.SetUnorderedAccessView(0, null);
        }
예제 #2
0
        private void swapTextures(ref bool readHelpTex, ITexture helpTex, ITexture pong, LayerMipmapSlice lm)
        {
            var dev = Device.Get();

            if (readHelpTex)
            {
                readHelpTex = false;

                dev.Compute.SetShaderResource(0, null);
                dev.Compute.SetUnorderedAccessView(0, null);

                dev.Compute.SetShaderResource(0, pong.GetSrView(lm));
                dev.Compute.SetUnorderedAccessView(0, helpTex.GetUaView(lm.Mipmap));
            }
            else
            {
                readHelpTex = true;

                dev.Compute.SetShaderResource(0, null);
                dev.Compute.SetUnorderedAccessView(0, null);

                dev.Compute.SetShaderResource(0, helpTex.GetSrView(lm));
                dev.Compute.SetUnorderedAccessView(0, pong.GetUaView(lm.Mipmap));
            }
        }
예제 #3
0
        public void Run(ImagesModel images, UploadBuffer constantBuffer, ITexture target)
        {
            var dev = Device.Get();

            dev.Compute.Set(shader.Compute);

            // src images
            for (int i = 0; i < images.NumImages; ++i)
            {
                dev.Compute.SetShaderResource(i, images.Images[i].Image.View);
            }

            for (int curMipmap = 0; curMipmap < images.NumMipmaps; ++curMipmap)
            {
                var size = images.GetSize(curMipmap);

                // dst image
                dev.Compute.SetUnorderedAccessView(0, target.GetUaView(curMipmap));

                for (int curLayer = 0; curLayer < images.NumLayers; ++curLayer)
                {
                    constantBuffer.SetData(new LayerLevelFilter {
                        Layer = curLayer, Level = curMipmap
                    });
                    dev.Compute.SetConstantBuffer(0, constantBuffer.Handle);
                    dev.Dispatch(
                        Utility.Utility.DivideRoundUp(size.Width, builder.LocalSizeX),
                        Utility.Utility.DivideRoundUp(size.Height, builder.LocalSizeY),
                        Utility.Utility.DivideRoundUp(size.Depth, builder.LocalSizeZ));
                }
            }

            // remove images from unordered acces view slots (otherwise they can't be bound as srv later)
            dev.Compute.SetUnorderedAccessView(0, null);
        }
예제 #4
0
        /// <summary>
        /// copies the values of the +4th mipmap into the specified mipmap
        /// </summary>
        /// <param name="tex"></param>
        /// <param name="lm">dst layer/mipmap</param>
        /// <param name="upload"></param>
        public void RunCopy(ITexture tex, LayerMipmapSlice lm, UploadBuffer upload)
        {
            var size     = tex.Size.GetMip(lm.SingleMipmap);
            var nMipmaps = tex.NumMipmaps - lm.Mipmap;

            if (nMipmaps == 1)
            {
                return;                // already finished
            }
            upload.SetData(new BufferData
            {
                Layer = lm.SingleLayer,
                Size  = size
            });
            var dev = Device.Get();

            var builder = tex.Is3D ? ShaderBuilder.Builder3D : ShaderBuilder.Builder2D;

            dev.Compute.Set(tex.Is3D ? CopyShader3D.Compute : CopyShader.Compute);
            dev.Compute.SetConstantBuffer(0, upload.Handle);
            dev.Compute.SetSampler(0, sampler);

            dev.Compute.SetUnorderedAccessView(0, tex.GetUaView(lm.Mipmap));
            dev.Compute.SetShaderResource(0, tex.GetSrView(lm.AddMipmap(Math.Min(4, nMipmaps - 1))));

            dev.Dispatch(
                Utility.Utility.DivideRoundUp(size.X, builder.LocalSizeX),
                Utility.Utility.DivideRoundUp(size.Y, builder.LocalSizeY),
                Utility.Utility.DivideRoundUp(size.Z, builder.LocalSizeZ)
                );

            dev.Compute.SetShaderResource(0, null);
            dev.Compute.SetUnorderedAccessView(0, null);
        }
        public void Run(ITexture src, ITexture guide, ITexture dst, int srcMipmap, int dstMipmap, bool hasAlpha, UploadBuffer upload)
        {
            Debug.Assert(guide.Size == dst.Size);
            Debug.Assert(guide.NumMipmaps >= dstMipmap);
            Debug.Assert(dst.NumMipmaps >= dstMipmap);
            Debug.Assert(guide.NumLayers == dst.NumLayers);
            Debug.Assert(src.NumLayers == dst.NumLayers);

            var bufferData = new BufferData
            {
                SrcSize  = src.Size.GetMip(srcMipmap),
                DstSize  = dst.Size.GetMip(dstMipmap),
                HasAlpha = hasAlpha?1:0,
            };

            bufferData.FilterSizeFloatX = bufferData.SrcSize.X / (float)bufferData.DstSize.X;
            bufferData.FilterSizeFloatY = bufferData.SrcSize.Y / (float)bufferData.DstSize.Y;
            bufferData.FilterSizeFloatZ = bufferData.SrcSize.Z / (float)bufferData.DstSize.Z;

            // select shader and builder
            var  builder      = src.Is3D ? ShaderBuilder.Builder3D : ShaderBuilder.Builder2D;
            bool isFastShader = (bufferData.SrcSize.X % bufferData.DstSize.X == 0) &&
                                (bufferData.SrcSize.Y % bufferData.DstSize.Y == 0) &&
                                (bufferData.SrcSize.Z % bufferData.DstSize.Z == 0);

            DirectX.Shader shader;
            if (isFastShader)
            {
                shader = src.Is3D ? FastShader3D : FastShader;
            }
            else
            {
                shader = src.Is3D ? SlowShader3D : SlowShader;
            }

            var dev = Device.Get();

            dev.Compute.Set(shader.Compute);

            for (int layer = 0; layer < src.NumLayers; ++layer)
            {
                bufferData.Layer = layer;
                upload.SetData(bufferData);
                dev.Compute.SetConstantBuffer(0, upload.Handle);
                dev.Compute.SetShaderResource(0, src.GetSrView(new LayerMipmapSlice(layer, srcMipmap)));
                dev.Compute.SetShaderResource(1, guide.GetSrView(new LayerMipmapSlice(layer, dstMipmap)));
                dev.Compute.SetUnorderedAccessView(0, dst.GetUaView(dstMipmap));

                dev.Dispatch(
                    Utility.Utility.DivideRoundUp(bufferData.DstSize.X, builder.LocalSizeX / 2),
                    Utility.Utility.DivideRoundUp(bufferData.DstSize.Y, builder.LocalSizeY / 2),
                    Utility.Utility.DivideRoundUp(bufferData.DstSize.Z, Math.Max(builder.LocalSizeZ / 2, 1))
                    );
            }

            dev.Compute.SetShaderResource(0, null);
            dev.Compute.SetShaderResource(1, null);
            dev.Compute.SetUnorderedAccessView(0, null);
        }
예제 #6
0
        /// <summary>
        /// binds dstTex as source and tmpTex as destination and then swaps the references.
        /// => after rendering, dst tex will be the texture with the result
        /// </summary>
        /// <param name="dstTex"></param>
        /// <param name="tmpTex"></param>
        /// <param name="lm"></param>
        private void BindAndSwapTextures(ref ITexture dstTex, ref ITexture tmpTex, LayerMipmapSlice lm)
        {
            var dev = Device.Get();

            dev.Compute.SetShaderResource(0, null);
            dev.Compute.SetUnorderedAccessView(0, null);

            dev.Compute.SetShaderResource(0, dstTex.GetSrView(lm));
            dev.Compute.SetUnorderedAccessView(0, tmpTex.GetUaView(lm.Mipmap));

            var tmp = tmpTex;

            tmpTex = dstTex;
            dstTex = tmp;
        }
예제 #7
0
        /// <summary>
        /// weights the values of the given mipmap with values from higher mipmaps (according to ms-ssim)
        /// </summary>
        /// <param name="tex"></param>
        /// <param name="lm">dst layer/mipmap</param>
        /// <param name="upload"></param>
        public void RunWeighted(ITexture tex, LayerMipmapSlice lm, UploadBuffer upload)
        {
            var size     = tex.Size.GetMip(lm.SingleMipmap);
            var nMipmaps = tex.NumMipmaps - lm.Mipmap;

            if (nMipmaps == 1)
            {
                return;                // already finished
            }
            upload.SetData(new BufferData
            {
                Layer        = lm.SingleLayer,
                Size         = size,
                InvWeightSum = GetInvWeightSum(nMipmaps),
                NumMipmaps   = nMipmaps
            });
            var dev = Device.Get();

            var builder = tex.Is3D ? ShaderBuilder.Builder3D : ShaderBuilder.Builder2D;

            dev.Compute.Set(tex.Is3D ? Shader3D.Compute : Shader.Compute);
            dev.Compute.SetConstantBuffer(0, upload.Handle);
            dev.Compute.SetSampler(0, sampler);

            dev.Compute.SetUnorderedAccessView(0, tex.GetUaView(lm.Mipmap));
            dev.Compute.SetShaderResource(0, nMipmaps >= 2 ? tex.GetSrView(lm.AddMipmap(1)) : null);
            dev.Compute.SetShaderResource(1, nMipmaps >= 3 ? tex.GetSrView(lm.AddMipmap(2)) : null);
            dev.Compute.SetShaderResource(2, nMipmaps >= 4 ? tex.GetSrView(lm.AddMipmap(3)) : null);
            dev.Compute.SetShaderResource(3, nMipmaps >= 5 ? tex.GetSrView(lm.AddMipmap(4)) : null);

            dev.Dispatch(
                Utility.Utility.DivideRoundUp(size.X, builder.LocalSizeX),
                Utility.Utility.DivideRoundUp(size.Y, builder.LocalSizeY),
                Utility.Utility.DivideRoundUp(size.Z, builder.LocalSizeZ)
                );

            for (var i = 0; i < 4; i++)
            {
                dev.Compute.SetShaderResource(i, null);
            }
            dev.Compute.SetUnorderedAccessView(0, null);
        }
예제 #8
0
        public void Run(ITexture[] sources, ITexture dst, LayerMipmapSlice lm, UploadBuffer upload)
        {
            Debug.Assert(sources.Length == inputs.Length);
            foreach (var src in sources)
            {
                Debug.Assert(src.HasSameDimensions(dst));
            }

            var size = sources[0].Size.GetMip(lm.SingleMipmap);

            upload.SetData(new BufferData
            {
                Layer = lm.SingleLayer,
                Size  = size
            });
            var dev     = Device.Get();
            var builder = sources[0].Is3D ? ShaderBuilder.Builder3D : ShaderBuilder.Builder2D;

            dev.Compute.Set(sources[0].Is3D ? Shader3D.Compute : Shader.Compute);
            dev.Compute.SetConstantBuffer(0, upload.Handle);
            for (var i = 0; i < sources.Length; i++)
            {
                var src = sources[i];
                dev.Compute.SetShaderResource(i, src.GetSrView(lm));
            }

            dev.Compute.SetUnorderedAccessView(0, dst.GetUaView(lm.SingleMipmap));

            dev.Dispatch(
                Utility.Utility.DivideRoundUp(size.X, builder.LocalSizeX),
                Utility.Utility.DivideRoundUp(size.Y, builder.LocalSizeY),
                Utility.Utility.DivideRoundUp(size.Z, builder.LocalSizeZ)
                );

            for (var i = 0; i < sources.Length; i++)
            {
                dev.Compute.SetShaderResource(i, null);
            }
            dev.Compute.SetUnorderedAccessView(0, null);
        }
예제 #9
0
        /// <summary>
        /// executes on iteration of the filter (for all layers and mipmaps)
        /// </summary>
        /// <param name="image">original images (might be used for texture bindings)</param>
        /// <param name="src">source texture</param>
        /// <param name="dst">destination texture</param>
        /// <param name="cbuffer">buffer that stores some runtime information</param>
        /// <param name="iteration">current filter iteration. Should be 0 if not separable. Should be 0 or 1 if separable (x- and y-direction pass) or 2 for z-direction pass</param>
        /// <remarks>make sure to call UpdateParamBuffer() if parameters have changed after the last invocation</remarks>
        internal void Run(ImagesModel image, ITexture src, ITexture dst, UploadBuffer cbuffer, int iteration)
        {
            if (parent.IsSepa)
            {
                Debug.Assert(iteration == 0 || iteration == 1 || iteration == 2);
            }
            else
            {
                Debug.Assert(iteration == 0);
            }

            // compatible textures?
            Debug.Assert(src.Is3D == is3D);
            Debug.Assert(dst.Is3D == is3D);

            var dev = Device.Get();

            dev.Compute.Set(shader.Compute);

            // filter parameters (constant)
            if (paramBuffer != null)
            {
                dev.Compute.SetConstantBuffer(1, paramBuffer.Handle);
            }

            dev.Compute.SetShaderResource(1, src.View);

            for (int curMipmap = 0; curMipmap < image.NumMipmaps; ++curMipmap)
            {
                // dst texture
                dev.Compute.SetUnorderedAccessView(0, dst.GetUaView(curMipmap));
                var size = image.GetSize(curMipmap);

                for (int curLayer = 0; curLayer < image.NumLayers; ++curLayer)
                {
                    // src textures
                    dev.Compute.SetShaderResource(0, src.GetSrView(curLayer, curMipmap));
                    BindTextureParameters(image, curLayer, curMipmap);

                    cbuffer.SetData(new LayerLevelFilter
                    {
                        Layer   = curLayer,
                        Level   = curMipmap,
                        FilterX = iteration == 0?1:0,
                        FilterY = iteration == 1?1:0,
                        FilterZ = iteration == 2?1:0
                    });

                    dev.Compute.SetConstantBuffer(0, cbuffer.Handle);

                    dev.Dispatch(
                        Utility.Utility.DivideRoundUp(size.Width, localSize),
                        Utility.Utility.DivideRoundUp(size.Height, localSize),
                        Utility.Utility.DivideRoundUp(size.Depth, localSize));
                }
            }

            // remove texture bindings
            dev.Compute.SetUnorderedAccessView(0, null);
            dev.Compute.SetShaderResource(0, null);
            dev.Compute.SetShaderResource(1, null);
        }
예제 #10
0
        public void Run(ITexture src, ITexture dst, ITexture tmpTex, LayerMipmapSlice lm, UploadBuffer upload)
        {
            var size = src.Size.GetMip(lm.Mipmap);
            var dev  = Device.Get();
            // debugging
            var originalDst = dst;

            initTexShader.Run(src, dst, lm, upload);
            initTexShader.Run(src, tmpTex, lm, upload);

            ImageFramework.DirectX.Query.SyncQuery syncQuery = new ImageFramework.DirectX.Query.SyncQuery();
            //var watch = new Stopwatch();
            //watch.Start();
            for (int i = 0; i < 254; ++i)
            {
                // bind textures
                dev.Compute.SetShaderResource(0, dst.GetSrView(lm));
                dev.Compute.SetUnorderedAccessView(0, tmpTex.GetUaView(lm.Mipmap));

                dev.Compute.Set(compute.Compute);
                upload.SetData(new BufferData
                {
                    Size      = size,
                    Iteration = i
                });
                dev.Compute.SetConstantBuffer(0, upload.Handle);

                // execute
                dev.Dispatch(
                    Utility.DivideRoundUp(size.X, workgroupSize.X),
                    Utility.DivideRoundUp(size.Y, workgroupSize.Y),
                    Utility.DivideRoundUp(size.Z, workgroupSize.Z)
                    );

                // unbind texture
                dev.Compute.SetShaderResource(0, null);
                dev.Compute.SetUnorderedAccessView(0, null);

                // swap textures
                var tmp = tmpTex;
                tmpTex = dst;
                dst    = tmp;

#if DEBUG
                if (i % 16 == 0)
                {
                    syncQuery.Set();
                    syncQuery.WaitForGpu();
                    Console.WriteLine("Iteration: " + i);
                }
#endif
            }

            /*syncQuery.Set();
             * syncQuery.WaitForGpu();
             * watch.Stop();
             *
             * Console.WriteLine($"Time: {watch.ElapsedMilliseconds}ms");
             */
            dev.Compute.Set(null);

            Debug.Assert(ReferenceEquals(originalDst, dst));
            syncQuery?.Dispose();
        }
예제 #11
0
        public void Run(ITexture src, ITexture dst, int srcMipmap, int dstMipmap, bool hasAlpha, UploadBuffer upload, ITextureCache cache)
        {
            Debug.Assert(cache.IsCompatibleWith(src));
            Debug.Assert(src.NumLayers == dst.NumLayers);
            Debug.Assert(dstMipmap < dst.NumMipmaps && dstMipmap >= 0);
            Debug.Assert(srcMipmap < src.NumMipmaps && dstMipmap >= 0);

            var dstSize = dst.Size.GetMip(dstMipmap);
            var srcSize = src.Size.GetMip(srcMipmap);
            var cbuffer = new BufferData
            {
                HasAlpha = hasAlpha ? 1 : 0
            };


            var      tmpTex1 = cache.GetTexture();
            ITexture tmpTex2 = null;

            if (src.Is3D)
            {
                tmpTex2 = cache.GetTexture();
            }


            foreach (var srcLm in src.LayerMipmap.LayersOfMipmap(srcMipmap))
            {
                cbuffer.Layer     = srcLm.Layer;
                cbuffer.DstSize   = srcSize;
                cbuffer.DstSize.X = dstSize.X;

                ExecuteDimension(ref cbuffer, upload, src.Is3D, 0, srcSize, src.GetSrView(srcLm), tmpTex1.GetUaView(srcMipmap));
                // var tst = tmpTex1.GetPixelColors(layer, 0);

                cbuffer.DstSize.Y = dstSize.Y;
                if (src.Is3D)
                {
                    ExecuteDimension(ref cbuffer, upload, src.Is3D, 1, srcSize, tmpTex1.GetSrView(srcLm), tmpTex2.GetUaView(srcMipmap));

                    cbuffer.DstSize.Z = dstSize.Z;
                    ExecuteDimension(ref cbuffer, upload, src.Is3D, 2, srcSize, tmpTex2.GetSrView(srcLm), dst.GetUaView(dstMipmap));
                }
                else
                {
                    ExecuteDimension(ref cbuffer, upload, src.Is3D, 1, srcSize, tmpTex1.GetSrView(srcLm), dst.GetUaView(dstMipmap));
                }
            }

            cache.StoreTexture(tmpTex1);
            if (tmpTex2 != null)
            {
                cache.StoreTexture(tmpTex2);
            }
        }
예제 #12
0
        public void Run(ITexture src, ITexture dst, LayerMipmapSlice lm, UploadBuffer buffer, ITextureCache cache)
        {
            Debug.Assert(src.HasSameDimensions(dst));
            Debug.Assert(cache.IsCompatibleWith(src));
            Debug.Assert(lm.IsIn(src.LayerMipmap));

            var srcSize = src.Size.GetMip(lm.Mipmap);

            var dev = Device.Get();

            dev.Compute.Set(src.Is3D ? Shader3D.Compute : Shader.Compute);
            var builder = src.Is3D ? ShaderBuilder.Builder3D : ShaderBuilder.Builder2D;

            // execute x
            buffer.SetData(new BufferData
            {
                Size      = srcSize,
                Direction = new Size3(1, 0, 0),
                Layer     = lm.Layer
            });
            dev.Compute.SetConstantBuffer(0, buffer.Handle);
            dev.Compute.SetShaderResource(0, src.GetSrView(lm));
            var      tmp1 = cache.GetTexture();
            ITexture tmp2 = null;

            dev.Compute.SetUnorderedAccessView(0, tmp1.GetUaView(lm.Mipmap));

            dev.Dispatch(
                Utility.Utility.DivideRoundUp(srcSize.Width, builder.LocalSizeX),
                Utility.Utility.DivideRoundUp(srcSize.Height, builder.LocalSizeY),
                Utility.Utility.DivideRoundUp(srcSize.Depth, builder.LocalSizeZ)
                );

            UnbindResources(dev);

            // execute y
            buffer.SetData(new BufferData
            {
                Size      = srcSize,
                Direction = new Size3(0, 1, 0),
                Layer     = lm.Layer
            });
            dev.Compute.SetConstantBuffer(0, buffer.Handle);
            dev.Compute.SetShaderResource(0, tmp1.GetSrView(lm));
            if (src.Is3D)
            {
                tmp2 = cache.GetTexture();
                dev.Compute.SetUnorderedAccessView(0, tmp2.GetUaView(lm.Mipmap));

                dev.Dispatch(
                    Utility.Utility.DivideRoundUp(srcSize.Width, builder.LocalSizeX),
                    Utility.Utility.DivideRoundUp(srcSize.Height, builder.LocalSizeY),
                    Utility.Utility.DivideRoundUp(srcSize.Depth, builder.LocalSizeZ)
                    );

                UnbindResources(dev);

                // execute z
                buffer.SetData(new BufferData
                {
                    Size      = srcSize,
                    Direction = new Size3(0, 0, 1),
                    Layer     = lm.Layer
                });
                dev.Compute.SetConstantBuffer(0, buffer.Handle);
                dev.Compute.SetShaderResource(0, tmp2.GetSrView(lm));
            }

            // bind final target
            dev.Compute.SetUnorderedAccessView(0, dst.GetUaView(lm.Mipmap));

            dev.Dispatch(
                Utility.Utility.DivideRoundUp(srcSize.Width, builder.LocalSizeX),
                Utility.Utility.DivideRoundUp(srcSize.Height, builder.LocalSizeY),
                Utility.Utility.DivideRoundUp(srcSize.Depth, builder.LocalSizeZ)
                );

            UnbindResources(dev);
            cache.StoreTexture(tmp1);
            if (tmp2 != null)
            {
                cache.StoreTexture(tmp2);
            }
        }