// 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); }
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)); } }
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); }
/// <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); }
/// <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; }
/// <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); }
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); }
/// <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); }
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(); }
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); } }
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); } }