compute shader
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
- 在你的脚本中,定义一个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;}
- 在resource界面,将compute shader赋过来:
- 调用代码如下:先设置参数,再用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上。
特定平台的差异
- Metal(ios或tvOS平台)不支持贴图上的原子操作。Metal也不支持buffer上的GetDimensions查询。将buffer大小当成常量传给shader如果必要的话。
- 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相关推荐
- android device monitor命令行窗口在哪里_Vulkan在Android使用Compute shader
oeip 相关功能只能运行在window平台,想移植到android平台,暂时选择vulkan做为图像处理,主要一是里面有单独的计算管线且支持好,二是熟悉下最新的渲染技术思路. 这个 demo(git ...
- OpenGL Compute Shader计算着色器的实例
OpenGL Compute Shader计算着色器 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 // #define USE_GL3W #include &l ...
- OpenGL Compute Shader Raytracing 计算着色器光线追踪的实例
OpenGL Compute Shader Raytracing 计算着色器光线追踪 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 // #define USE_ ...
- OpenGL Compute Shader Particle System计算着色器粒子系统的实例
OpenGL Compute Shader Particle System计算着色器粒子系统 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include &l ...
- OpenGL Compute Shader Image Processing计算着色器图像处理的实例
OpenGL Compute Shader Image Processing计算着色器图像处理 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include & ...
- Compute Shader次世代优化方案
这是侑虎科技第498篇文章,感谢作者凯奥斯供稿.欢迎转发分享,未经作者授权请勿转载.如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨.(QQ群:793972859) 作者主页:https://z ...
- OpenGL ES3.1使用计算着色器(Compute Shader)
OpenGL ES3.1使用计算着色器(Compute Shader) 1.基本介绍 OpenGL ES从3.1版本开始支持计算着色器 工作模型有全局工作组和本地工作组,全局工作组包含 ...
- Directx 计算着色器(compute shader)
原文 :http://www.cnblogs.com/Ninputer/archive/2009/12/11/1622190.html 博者注:计算着色器调试(http://msdn.microsof ...
- opengl使用compute shader的生成纹理,解决残影的问题
在做AR云渲染的项目中,经常会有残影出现,定位问题吧. 在我们项目中,使用到了compute shader来定制一些纹理的输出,每帧的写纹理可能没有覆盖纹理的每个像素,这样就造成了问题,下一帧的渲染这 ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十三章:计算着色器(The Compute Shader)...
Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十三章:计算着色器(The Compute Shader) 原文: Int ...
最新文章
- 网络推广计划浅析外链发布要遵循的几点小技巧!
- linux_软件安装策略和升级策略
- Spring Cloud【Finchley】-03将微服务注册到Eureka Server上 + 为Eureka Server添加用户认证
- 大学期间承接软件项目的一些个人观点
- hdu 5570(数学期望)
- python 查询sqlserver 视图_SQL Server查看视图定义总结
- eplise怎么连接数据库_eclipse连接mysql
- 石头剪刀布小游戏开发的需求说明
- 微软发布了Visual Stduio 2010 RTM版本的虚拟机vhd文件,包含样例和动手实验(免费)...
- 求最大和 java_三种算法求最大子段和问题——Java实现
- 为什么人们常说“十个创业九个死”?
- 13 万字 C 语言从入门到精通保姆级教程2021 年版
- python定时任务启动与停止_Python启动定时任务
- 洛必达法则及极限问题总结
- Openwrt下ipk包的安装、卸载与更新
- git 删除历史记录
- google 企业邮箱 smtp pop3设置
- 海信Vidda S65 2023款和2020款有什么区别?哪个更好
- 逻辑回归(Logistic Regression)原理(理论篇)
- 【C语言面试复试汇总】
热门文章
- 介绍几款低代码生成器,神器
- 海康大华宇视硬件NVR通过GB28181注册接入到LiveGBS国标流媒体服务后通道显示为0如何处理
- STM32 USB Mass Storage 例程调试笔记
- [iOS]在xib中设置YYLabel自适应高度
- params.c:Parameter() - Ignoring badly formed line in configuration file: ignore errors 解决方法
- C/C++的刷题练习之牛客网,一个友好的网站
- USB Type C 接口引脚详解
- JUCE框架教程(8)——DSP Module基础
- 爬取淘宝买家秀,sign值的生成
- 数码照片的Photoshop清晰化处理漫谈-photoshop-Photoshop-天极Yesky