computer shader是在显卡上运行的程序,在正常的渲染管道之外。被用于大量并行的gpu算法,或加速部分游戏渲染。想要高效利用他们,最好深入的理解cpu机制和并行算法。还有DirectCompute,OpenGL Compute,CUDA或openCL。
unity 的compute shader很像DX11 DirectCompute技术。能工作的平台有:
1. windows,有Dx11或Dx12显卡Api,shader model 4.5 gpu;
2. 用metal显卡api的macOS和ios;
3. Android linux和windows有Vulkan Api;
4. 现代openGL平台(openGL 4.3在linux和windows;gl es 3.1在安卓)。注意mac os x不支持opengl 4.3;
5. 现代控制台(sony ps4和微软xbox one)
运行时判断是否支持compute shader可以用SystemInfo.supportsComputeShaders。

compute shader资源

类似于普通的shader,compute shader在工程里也是资源文件,.compute扩展名。他们是用Dx11风格的hlsl语言缩写。用#pragma 编译指令指定哪些很少被当成compute shader核心编译,如下:

#pragma kernel KMain
[numthreads(8, 8, 1)]
void KMain(uint2 groupId : SV_GroupID, uint2 groupThreadId : SV_GroupThreadID, uint2 dispatchThreadId : SV_DispatchThreadID)
{// Upper-left pixel coordinate of quad that this thread will readint2 threadUL = (groupThreadId << 1) + (groupId << 3) - 4;// Downsample the blockfloat2 offset = float2(threadUL);float4 p00 = _Source.SampleLevel(sampler_LinearClamp, (offset                    + 0.5) * _Size.zw, 0.0);float4 p10 = _Source.SampleLevel(sampler_LinearClamp, (offset + float2(1.0, 0.0) + 0.5) * _Size.zw, 0.0);float4 p01 = _Source.SampleLevel(sampler_LinearClamp, (offset + float2(0.0, 1.0) + 0.5) * _Size.zw, 0.0);float4 p11 = _Source.SampleLevel(sampler_LinearClamp, (offset + float2(1.0, 1.0) + 0.5) * _Size.zw, 0.0);// Store the 4 downsampled pixels in LDSuint destIdx = groupThreadId.x + (groupThreadId.y << 4u);Store2Pixels(destIdx     , p00, p10);Store2Pixels(destIdx + 8u, p01, p11);GroupMemoryBarrierWithGroupSync();// Horizontally blur the pixels in LDSuint row = groupThreadId.y << 4u;BlurHorizontally(row + (groupThreadId.x << 1u), row + groupThreadId.x + (groupThreadId.x & 4u));GroupMemoryBarrierWithGroupSync();// Vertically blur the pixels in LDS and write the result to memoryBlurVertically(dispatchThreadId, (groupThreadId.y << 3u) + groupThreadId.x);
}

表示kMain函数被当作compute shader编译,以及:

// test.compute#pragma kernel FillWithRedRWTexture2D<float4> res;[numthreads(1,1,1)]
void FillWithRed (uint3 dtid : SV_DispatchThreadID)
{res[dtid.xy] = float4(1,0,0,1);
}

语言是标准dx 11 hlsl语言。一个compute shader资源文件必须包含至少一个会被调用的compute kernel。可以有多个,写多行#pragma语句即可。
当用#pragma时,注意同一行加“// 。。”这种注释会产生编译错误。
#pragma后面可以跟这个shader编译需要的宏

#pragma kernel KernelOne SOME_DEFINE DEFINE_WITH_VALUE=1337
#pragma kernel KernelTwo OTHER_DEFINE

调用compute shader

  1. 在你的脚本中,定义一个ComputeShader类型的变量,给这个资源一个引用。
    如下在resource类里定义ComputeShader,如下:
public sealed class ComputeShaders{public ComputeShader exposureHistogram;public ComputeShader lut3DBaker;public ComputeShader texture3dLerp;public ComputeShader gammaHistogram;public ComputeShader waveform;public ComputeShader vectorscope;public ComputeShader multiScaleAODownsample1;public ComputeShader multiScaleAODownsample2;public ComputeShader multiScaleAORender;public ComputeShader multiScaleAOUpsample;public ComputeShader gaussianDownsample;}
  1. 在resource界面,将compute shader赋过来:
  2. 调用代码如下:先设置参数,再用ComputeShader.Dispatch方法调用。从unity脚本文档里查ComputeShader类的使用。如下CommandBuffer用

public void DispatchCompute(ComputeShader computeShader, int kernelIndex, int threadGroupsX, int threadGroupsY, int threadGroupsZ);
调用computeShader:

void PushUpsampleCommands(CommandBuffer cmd, int lowResDepth, int interleavedAO, int highResDepth, int? highResAO, RenderTargetIdentifier dest, Vector3 lowResDepthSize, Vector2 highResDepthSize, bool invert = false){var cs = m_Resources.computeShaders.multiScaleAOUpsample;int kernel = cs.FindKernel(highResAO == null? invert? "main_invert": "main": "main_blendout");float stepSize = 1920f / lowResDepthSize.x;float bTolerance = 1f - Mathf.Pow(10f, m_Settings.blurTolerance.value) * stepSize;bTolerance *= bTolerance;float uTolerance = Mathf.Pow(10f, m_Settings.upsampleTolerance.value);float noiseFilterWeight = 1f / (Mathf.Pow(10f, m_Settings.noiseFilterTolerance.value) + uTolerance);cmd.SetComputeVectorParam(cs, "InvLowResolution", new Vector2(1f / lowResDepthSize.x, 1f / lowResDepthSize.y));cmd.SetComputeVectorParam(cs, "InvHighResolution", new Vector2(1f / highResDepthSize.x, 1f / highResDepthSize.y));cmd.SetComputeVectorParam(cs, "AdditionalParams", new Vector4(noiseFilterWeight, stepSize, bTolerance, uTolerance));cmd.SetComputeTextureParam(cs, kernel, "LoResDB", lowResDepth);cmd.SetComputeTextureParam(cs, kernel, "HiResDB", highResDepth);cmd.SetComputeTextureParam(cs, kernel, "LoResAO1", interleavedAO);if (highResAO != null)cmd.SetComputeTextureParam(cs, kernel, "HiResAO", highResAO.Value);cmd.SetComputeTextureParam(cs, kernel, "AoResult", dest);int xcount = ((int)highResDepthSize.x + 17) / 16;int ycount = ((int)highResDepthSize.y + 17) / 16;cmd.DispatchCompute(cs, kernel, xcount, ycount, 1);}

和compute shader联系紧密的是compute buffer,用法如下

if (m_Data == null)m_Data = new ComputeBuffer(m_NumBins, sizeof(uint));var compute = context.resources.computeShaders.gammaHistogram;var cmd = context.command;cmd.BeginSample("GammaHistogram");// Clear the buffer on every frame as we use it to accumulate values on every frameint kernel = compute.FindKernel("KHistogramClear");cmd.SetComputeBufferParam(compute, kernel, "_HistogramBuffer", m_Data);cmd.DispatchCompute(compute, kernel, Mathf.CeilToInt(m_NumBins / (float)m_ThreadGroupSizeX), 1, 1);

另外,其他用法请搜索文档。
RenderTextures也可以从compute shader写入,如果设置随机访问权限的话。查询RenderTexture.enableRandomWrite。

compute shader中的texture 采样

在unity中,贴图和采样器不是分开的事物。所以要在compute shader中使用采样器的话,需要遵循下面的unity专门的规则:
1. 和贴图名称用同样的名称,如贴图名为Texture2D MyTex,则SamplerState samplerMyTex。这样,sampler会被初始化为该贴图的过滤模式,wrap模式,异向模式。
2. 用预定于的采样器,名称必须带有Linear或Point(过滤模式)和Clamp或Repeat(wrap模式)。比如SamplerState MyLinearClampSamplers创建一个linear过滤模式和Clamp wrap模式的采样器。更多的内容查询SamplerState

跨平台支持

像正常shader一样,unity能把compute shader从hlsl转换成其他shader语言。所以,为了最简单的跨平台编译,你可以用hlsl写compute shader。然而有几个因素需要考虑。

跨平台最好的实践

Dx 11支持许多其他平台不支持的行为(比如metal 或OpenGL ES)。所以,你需要保证你的shader在其他支持能力低的平台上工作正常。下面几个问题要注意:
1. 内存溢出访问。Dx11 读的时候会返回0,不会出问题。但很少支持的平台可能会gpu崩溃。另外,dx11的一些技巧,比如buffer大小和你的线程组数量是无关的,[ 试图从缓冲区的开始或结束读取相邻的数据元素,以及类似的不兼容性。
2. 初始化你的资源,新的缓冲区和贴图内容是未定义的。一些平台可能全是0,其他的可能是任意东西,包括为空。
3. 绑定你的compute shader需要的所有资源。即使你确定地知道这个shader在他的当前状态下由于分支原因不会用到这个资源,你仍然需要确定这个资源绑定到shader上。

特定平台的差异

  1. Metal(ios或tvOS平台)不支持贴图上的原子操作。Metal也不支持buffer上的GetDimensions查询。将buffer大小当成常量传给shader如果必要的话。
  2. openGL ES3.1(安卓、ios或txOS平台)一次只支持4个compute buffer。实际实现可能支持更多,但是如果开发openGL ES,你应该将相关的数据分组放到一个结构里,而不是每种数据放到自己的buffer里。

hlsl-only和glsl-only compute shader

一般,compute shader文件是用hlsl写的,被自动编译或翻译到所有必要的平台。然而,可以阻止将它翻译到其他语言,或者手动写glsl compute shader。
下面的内容只应用于hlsl-only和glsl-only compute shader,而不是跨平台编译。因为这些内容会导致compute shader从一些平台排除。
1.被CGPROGRAM和ENDCG包围的 compute shader不能被非hlsl平台处理;
2. 被GLSLPROGRAM和ENDGLSL包围的compute shader被当作glsl处理,逐字排除。你要注意,自动翻译的shader的buffer遵循hlsl数据布局,手动写的glsl shader遵循glsl布局规则。

compute shader相关推荐

  1. android device monitor命令行窗口在哪里_Vulkan在Android使用Compute shader

    oeip 相关功能只能运行在window平台,想移植到android平台,暂时选择vulkan做为图像处理,主要一是里面有单独的计算管线且支持好,二是熟悉下最新的渲染技术思路. 这个 demo(git ...

  2. OpenGL Compute Shader计算着色器的实例

    OpenGL Compute Shader计算着色器 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 // #define USE_GL3W #include &l ...

  3. OpenGL Compute Shader Raytracing 计算着色器光线追踪的实例

    OpenGL Compute Shader Raytracing 计算着色器光线追踪 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 // #define USE_ ...

  4. OpenGL Compute Shader Particle System计算着色器粒子系统的实例

    OpenGL Compute Shader Particle System计算着色器粒子系统 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include &l ...

  5. OpenGL Compute Shader Image Processing计算着色器图像处理的实例

    OpenGL Compute Shader Image Processing计算着色器图像处理 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include & ...

  6. Compute Shader次世代优化方案

    这是侑虎科技第498篇文章,感谢作者凯奥斯供稿.欢迎转发分享,未经作者授权请勿转载.如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨.(QQ群:793972859) 作者主页:https://z ...

  7. OpenGL ES3.1使用计算着色器(Compute Shader)

    OpenGL ES3.1使用计算着色器(Compute Shader) 1.基本介绍 OpenGL ES从3.1版本开始支持计算着色器         工作模型有全局工作组和本地工作组,全局工作组包含 ...

  8. Directx 计算着色器(compute shader)

    原文 :http://www.cnblogs.com/Ninputer/archive/2009/12/11/1622190.html 博者注:计算着色器调试(http://msdn.microsof ...

  9. opengl使用compute shader的生成纹理,解决残影的问题

    在做AR云渲染的项目中,经常会有残影出现,定位问题吧. 在我们项目中,使用到了compute shader来定制一些纹理的输出,每帧的写纹理可能没有覆盖纹理的每个像素,这样就造成了问题,下一帧的渲染这 ...

  10. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十三章:计算着色器(The Compute Shader)...

    Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十三章:计算着色器(The Compute Shader) 原文: Int ...

最新文章

  1. Java微信公众平台开发(四)--回复消息的分类及实体的创建
  2. 福建2020年3月计算机二级报名时间,福建2020年3月计算机等级考试报名时间
  3. python爬虫本科容易找工作吗_python爬虫基础学完了,我真的能找到一份工作吗?...
  4. html图片多边形怎么写,使用CSS3构建的图像多边形裁剪动画特效
  5. 【Hadoop】:Windows下使用IDEA搭建Hadoop开发环境
  6. 软件质量与测试的新纪元
  7. 决策树ID3算法,计算过程
  8. vmware虚拟机安装win11系统教程
  9. typora激活方法及使用教程
  10. roundcube邮箱手机端_手机QQ邮箱在哪里找
  11. 彻底卸载360安全卫士的方法
  12. poj3294Life Forms
  13. 魔方机器人-复原步骤(一)
  14. Leetcode 460. LFU 缓存
  15. Qt5:报错error: 'tr' was not declared in this scop
  16. 嫁了这么有本事的程序员,凭什么不珍惜?|葡萄语录
  17. STL笔记:rb_tree
  18. 陕西黑布林滞销只是一篇营销广告,炒作夸大背后多是利益
  19. HTML5轻松实现全屏视频背景
  20. notepad++ 16进制数字加前缀0x

热门文章

  1. 计算机便签中字的大小,Windows便签字体怎么调整?电脑便签怎么改字体大小
  2. 用ES6语法存储美国邮政编码的IndexedDB数据库
  3. 二叉树非递归遍历思路总结
  4. 蔡学镛:编译、反编译、反反编译(转)
  5. 解决Tomcat显示中文乱码问题
  6. 软件备份(拷贝构造函数)
  7. 转载:为某燃气公司做的一部卡通角色广告动画
  8. 多源多目标统计信息融合 目标跟踪 信息融合 贝叶斯滤波总结
  9. 这家估值83亿美元的公司,是「侠盗」还是「割韭菜」?
  10. 介绍html5ppt模板,html5简单介绍.ppt