在图形应用程序中,为什么着色器会在运行时加载到应用程序中?

时间:2017-05-03 20:11:11

标签: c++ performance opengl glsl shader

用GLSL编写的着色器通常在运行时加载到图形应用程序中。我想知道为什么不使用着色器编译应用程序,以便以后不必加载它们。像这样:

#define glsl(version, glsl) "#version " #version "\n" #glsl

namespace glsl { namespace vs {
//VERTEX SHADERS
//=========================
// simple VS
//=========================
constexpr GLchar * const simple = glsl(450 core, 
    layout(location = 0) in vec3 position;

    void main() {
        gl_Position = vec4(position, 1.0f);
    }
    );

} namespace fs {
//FRAGMENT SHADERS
//=========================
// simple FS
//=========================
constexpr GLchar * const simple = glsl(450 core,
    out vec4 color;

    void main() {
        color = vec4(1.0f, 0.0f, 0.0f, 1.0f);
    }       
    );

} }

我认为这不会导致exe文件太大而且会加快加载时间;除非我误认为有多少着色器用于典型的图形应用程序。我意识到你可能想在编译时更新着色器,但这确实发生了吗?

我有什么理由不想这样做吗?

3 个答案:

答案 0 :(得分:3)

有几个原因:

  • 在开发过程中,“热加载”着色器非常方便,无需重新启动应用程序,因此您可以在调试或性能调整时进行更改,并立即查看结果。当着色器存储为单独的文件时,这会更简单。
  • 如评论中所述,根据您的平台,通常将着色器从高级着色语言预编译为中间字节代码表示或实际的最终GPU代码(例如,在GPU硬件为a的控制台的情况下)固定目标)。着色器编译可能非常耗时,因此最好离线而不是在运行时进行。
  • 在小型/简单的应用程序中,您采用的方法实际上并不少见,您的应用程序越大,您需要管理的着色器越多,就会变得更加痛苦。就个人而言,我喜欢即使在小型个人项目上也可以加载着色器。
  • 这实际上是一个比着色器更普遍的问题。在任何项目中,您可以选择何时在可执行文件中嵌入资源(直接在源代码中或通过单独的构建步骤(如Windows资源))或将它们存储为单独的文件。这两种方法都有利有弊,但嵌入的主要优点是应用程序可能需要的所有资源都嵌入到可执行文件中,因此您不必担心/处理可能缺少的资源。缺点是如果你把所有东西都塞进可执行文件中(特别是对于像游戏那样有很多大资产的项目)那么你就会增加构建时间,使加载变得困难,并且会使资产组织问题变得更加困难。

答案 1 :(得分:1)

你怎么认为它会加快加载时间?它没有!

如果您从使用fopen(或std::ifstreamCreateFile或其他)打开的常规文件中读取数据并从中读取数据,或者您正在访问过程映像的某些部分。哎呀,在大多数情况下,访问过程映像中的一些大页面的页面可能会表现得更糟,因为大多数操作系统都是在不可执行的,只读数据的段中延迟填充页面;未填充页面上的mmaped读取访问实际上比简单读取更慢,因为它涉及故障页面表和随后的I / O读取以使用数据填充页面。

强制性阅读:http://lkml.iu.edu/hypermail/linux/kernel/0004.0/0728.html

OpenGL API指定GLSL源代码是实际加载着色器的唯一方法。有一个缓存API(glShaderBinary,glProgramBinary),但是通过它加载的二进制文件是一种未指定的格式,可能随时改变,并且它是一个有效的错误条件,驱动程序因任何原因拒绝二进制文件强制加载原始的GLSL源。要实际获得这样的着色器二进制文件,首先要加载一个常规的GLSL着色器源,编译它,然后从OpenGL中检索二进制blob。

答案 2 :(得分:-1)

着色器编译过程是OpenGL的glsl编译器的一部分,而您可以将着色器作为字符串硬化到内存中,每次对着色器进行任何编辑时都需要重新编译。

在游戏编程中,当您对代码,着色器,库等的数百个部分进行小的调整时,通常不希望重新编译整个项目。这是所有大型游戏引擎都有脚本编写的主要原因之一引擎,编写额外的样板代码以将脚本集成到引擎中通常比编译程序10次只是为了使对象的颜色/光泽/位置恰到好处更好。尝试对所有着色器进行硬编码,以便它们在运行时在内存中进行编译,您将看到它在一天之后变得多么乏味!