通常,使用顶点和片段着色器的电子游戏和其他图形软件将以实际着色器源代码的形式(通常在glsl或hlsl中)对着色器进行编译,以便在运行时与显示硬件一起使用。(我的理解是,着色器不能真正预编成游戏二进制代码,因为显示硬件使用的实际着色机代码取决于显卡品牌,甚至是它的模型/一代,它们很可能互不兼容。)
虽然我自己在游戏编程领域工作,使用着色器,但实际上我不知道图形管道的哪一部分实际上将着色器编译成显卡使用的机器代码。编译着色器本质上是一个黑匣子:把着色器源代码扔到你正在使用的任何库中,它会在幕后发挥它的魔力。
我想知道这个编译过程是在哪里进行的。整个系统的哪个部分获取着色器源代码并从中生成着色机代码?
我(疯狂)的猜测是,这是由图形卡驱动程序完成的(因为驱动程序知道它应该输出什么样的机器代码,以及如何对特定品牌和型号的图形卡进行优化)。
(如果确实如此,这至少部分解释了为什么图形驱动程序在游戏运行效率方面如此重要,因为它对着色机代码的优化将对渲染速度产生很大影响。)
有没有任何资源,我可以找到更多的信息,在一般情况下,这些事情?
发布于 2018-05-29 16:03:47
据我所知,着色器不能真正预编成游戏二进制,因为显示硬件使用的实际着色机代码取决于显卡品牌,甚至是它的模型/一代,它们很可能互不兼容。
这种理解是不正确的。
大多数游戏使用的模型是,着色器首先从基于文本的源代码(HLSL等)编译成独立于硬件的二进制中间语言。这会产生二进制blobs,可以随游戏一起运送,无论是作为嵌入式资源放入游戏二进制文件,还是在PAK文件中,或者在松散文件中,或者如何使用。然后在启动时(而不是在运行时)将这些二进制blobs编译成实际的硬件相关着色器对象。
因此,着色器编译是一个分两步的过程:
第一步是慢步骤,它需要文本解析、错误检查、死区代码删除、硬件配置文件验证等。
第二步快。
步骤1不需要驱动程序执行;它可以由命令行上的独立编译器执行,甚至不需要初始化图形设备或上下文来执行它。
步骤2需要初始化图形设备或上下文。
重要的是要理解的是,我前面描述的模型不是OpenGL使用的模型。如果您知道的唯一API是OpenGL,如果您假设其他API的工作方式与OpenGL相同,那么您可能会得出这样的结论:这个模型不会发生,也不会发生。
然而,这将是一个不正确的结论。
所有其他API都使用我前面描述的模型:金属、Direct3DDirect3D、瓦尔坎;该两步模型被广泛使用,并且很好地理解并且工作。
因此,要回答您的问题,通常着色器编译不是通过图形卡驱动程序,而是通过离线工具,编译是作为开发过程的一部分,甚至在游戏出厂之前。然后图形卡驱动程序获取离线工具的输出,并进行最后一次传递,将其转换为在特定硬件上可用的东西。这一最后一关通常不是在运行时完成的,而是在程序首次启动时完成的,驱动程序甚至可以在第二次和以后的运行中缓存更快的启动结果。
然而,OpenGL是一个奇数,因为完整的着色器编译器是驱动程序的一部分,因此步骤1和步骤2不能分开。
发布于 2018-05-29 09:44:32
OpenGL和DirectX不是传统意义上的库(如“库是一组函数”),它是一个定义。他们没有实现这些功能,只是声明了制造商需要实现什么来支持这些功能。这就是为什么图形卡支持某个版本,而不是相反。
因此,有了这一点,他们的实际行动就会更加清晰。他们只是告诉GPU驱动程序该怎么做,而不是怎么做。与着色器编译一样,它们将源代码发送到驱动程序,驱动程序对其进行编译。
从技术上讲,你可以预编译每一个着色器,但是你会用大量的存储空间换取很少的性能,特别是因为着色器是在游戏播放之前编译的。
https://gamedev.stackexchange.com/questions/159201
复制相似问题