/// <summary> /// executes the shader for the outer image layer /// </summary> /// <returns></returns> public Color Run(TextureArray2D source, Models models) { var texDst = models.GlData.TextureCache.GetTexture(); models.GlData.BindSampler(0, false, false); source.BindAsTexture2D(0, 0, 0); texDst.BindAsImage(1, 0, 0, TextureAccess.WriteOnly); // bind and set uniforms program.Bind(); // direction GL.Uniform2(0, 1, 0); // stride var curStride = 2; GL.Uniform1(1, curStride); var curWidth = models.Images.Width; GL.DispatchCompute(Utility.Utility.DivideRoundUp(curWidth, LocalSize * 2), models.Images.Height, 1); // swap textures var texSrc = models.GlData.TextureCache.GetTexture(); GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit); // do invocation until finished while (curWidth > 2) { //curWidth /= 2; curWidth = Utility.Utility.DivideRoundUp(curWidth, 2); curStride *= 2; // swap textures Swap(ref texSrc, ref texDst); texSrc.BindAsTexture2D(0, 0, 0); texDst.BindAsImage(1, 0, 0, TextureAccess.WriteOnly); // stride GL.Uniform1(1, curStride); // dispatch GL.DispatchCompute(Utility.Utility.DivideRoundUp(curWidth, LocalSize * 2), models.Images.Height, 1); GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit); } // do the scan in y direction var curHeight = models.Images.Height; curStride = 2; // set direction GL.Uniform2(0, 0, 1); while (curHeight > 1) { // swap textures Swap(ref texSrc, ref texDst); texSrc.BindAsTexture2D(0, 0, 0); texDst.BindAsImage(1, 0, 0, TextureAccess.WriteOnly); // stride GL.Uniform1(1, curStride); GL.DispatchCompute(1, Utility.Utility.DivideRoundUp(curHeight, LocalSize * 2), 1); GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit); curHeight = Utility.Utility.DivideRoundUp(curHeight, 2); curStride *= 2; } GL.MemoryBarrier(MemoryBarrierFlags.AllBarrierBits); // the result is in pixel 0 0 texDst.BindAsTexture2D(models.GlData.GetPixelShader.GetTextureLocation(), 0, 0); // y coordinates for the texture fetch are reverted var res = models.GlData.GetPixelShader.GetPixelColor(0, 0, 0); // cleanup models.GlData.TextureCache.StoreTexture(texSrc); models.GlData.TextureCache.StoreTexture(texDst); return(ModifyResult(res)); }