vertex shader中怎么获取临近顶点的属性值?

共 1964字,需浏览 4分钟

 ·

2022-02-24 20:33

在知乎上看到这么个问题,挺感兴趣的,正好有大佬的高赞回答,和大家分享一些。

作者:无材补天的梧桐  原文链接是:

https://www.zhihu.com/question/516695017/answer/2356701024

以下的回复原文:

先说问题的答案,没办法获取:

能提出这样的问题,想必你对渲染管线在硬件上具体的实现细节很感兴趣,那我就简单介绍一下每类shader在并行性上的一些特点吧。

老死不相往来的vertex shader

我们先知道一个前提,无论是顶点也好、几何着色器对应的图元也好、光栅化后的片元也好、还是自己开辟的线程也好,以NVIDIA GPU为例,它们都是以32个为单位,称为一个warp。

GPU在接收到drawcall指令的时候,所有的顶点会根据其索引被Primitive Distributor拆分为每组最多32个顶点的batch,然后再发往运算单元SM,执行顶点着色器的代码。

每个线程映射的对象是一个顶点,每32个线程虽然锁步执行顶点着色器里的指令,它们彼此无法通信。

四人一组的fragment shader

那为什么fragment shader就能和邻居打交道呢,这是为了硬件能通过算梯度以计算mipmap层级,这是一个很重要的刚需,因此迫不得已支持的。这样的支持是需要付出代价的:

在三角形被光栅化成片元后,每四个相邻的片元组成一个小组,共八个这样的小组,总共32线程被捆绑成一个warp。是的,为了算ddx,ddy,就得确保有邻居,没有邻居也给你无中生有一个(图中黄色的片元),这就是代价。

很可能只有一个片元被三角形覆盖,为了支持这么一套机制,有三个不被三角形覆盖的片元被拖下了水(被迫占用三个线程,占着茅坑不拉屎)。而顶点着色器,目前没有这么刚需的需求值得显卡厂商去为此付出代价。

放飞自我的geometry shader

可是,如果我就想拿到同一个三角形的其他顶点怎么办?行吧,API制定者们搞出了一个几何着色器,一个线程对应一个图元(三角形),你可以拿到所有顶点,你还可以输出多个顶点。既实现了需求,也避免了为了这个并非刚需的需求,拖累了顶点着色器的大好前程。

本质上,图元与图元之间是并行的,但是几何着色器内部每个线程负责多个顶点的输出却是串行的,且数量不确定,这就埋下了效率低下的种子。实际上,显卡厂商们虽然不情不愿地支持了几何着色器,效率始终不尽人意。

未来可期的mesh shader

这样缝缝补补也没意思啊,而且这条饱经沧桑的管线也有一些其无法解决的硬伤。既然如此,英伟达大手一挥,给你们一个新玩具——mesh shader,直接让前面几何阶段的所有着色器(顶点、细分、几何)下岗。

怎么样才能又自由又高效呢?答案是,让你们程序员自己玩。mesh shader就是这么一个玩意儿,每个线程要映射什么玩意儿,程序员自己决定,线程组要怎么开也是程序员说了算。反正每一个线程组给我一堆顶点和索引就行(但这个数量是有限制的,不会有几何着色器那样的悲剧)。

这种让程序员维护线程组的方式,同以往的以线程为单位强行映射到顶点或图元有明显不同,是协作式的,更像compute shader,未来整条光栅化图形管线可以预见的会更加“通用化”,越来越像通用管线。

无拘无束的compute shader

说完图形管线,最后再简单谈谈通用管线吧。计算着色器从一开始就十分自由,同一个线程组内的数据可以访问同一块数据(共享内存),不过可能需要同步(因为一个线程组可以包含多个warp);更新的硬件特性还支持shuffle操作,直接在线程间传递数据。

正因为计算着色器从一开始就对程序员充分授权,让使用者自负盈亏,所以并不像图形管线那样拧巴:又要让图形中的固定操作尽可能高效;又要支持越来越多的意料之外的“需求”。

限于篇幅,很多概念只是蜻蜓点水,可能会有“懂的都懂,不懂的不明觉厉”的感觉。如果真想深刻地理解这些shader的工作原理,下面的专栏可能会对你有所帮助:

https://www.zhihu.com/column/c_1351502583832354816

一个音视频领域专业问答的小圈子!

推荐阅读:

音视频开发工作经验分享 || 视频版

OpenGL ES 学习资源分享

开通专辑 | 细数那些年写过的技术文章专辑

Android NDK 免费视频在线学习!!!

你想要的音视频开发资料库来了

推荐几个堪称教科书级别的 Android 音视频入门项目

觉得不错,点个在看呗~

浏览 15
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报