(转载)(官方)UE4--图像编程----着色器开发----HLSL 交叉编译器

HLSL 交叉编译器

这个库将 高级着色语言 (HLSL) 着色器源代码编译成高级中间表示法,执行独立于设备的优化,并生成 OpenGL 着色语言 (GLSL) 兼容源代码。这个库在很大程度上基于 Mesa 的 GLSL 编译器。前端已进行大量重新编写,以解析 HLSL 并根据 HLSL 抽象语法树 (AST) 生成 Mesa IR。这个库利用 Mesa 的 IR 优化来简化代码,并根据 Mesa IR 最终生成 GLSL 源代码。GLSL 生成是以 GLSL 优化器中的工作为基础。

除了生成 GLSL 代码以外,这个编译器还将全局一致变量打包成数组以便轻松高效地进行设置,提供一种反射机制以通知高级代码需要哪些一致变量,并提供映射信息以使高级代码在运行时可通过索引而非名称来绑定资源。

UnrealBuildTool 不会检测对外部库(例如 HLSLCC)进行的更改。 当您重新构建 HLSLCC 库时,请在 OpenGLShaders.cpp 中添加一个空格,以便强制重新链接该模块。

主库入口点是 HLSLCrossCompile。此函数使用所请求的选项执行根据源 HLSL 生成 GLSL 代码所需执行的所有步骤。每个阶段的摘要如下所示:

 

操作


说明


预处理


代码通过类似于 C 的预处理器运行。此阶段是可选的,您可使用 NoPreprocess 标志省略此阶段。虚幻引擎会在编译前使用 MCPP 执行预处理,从而跳过此步骤。


解析


解析 HLSL 源代码以生成抽象语法树。此工作在 _mesa_hlsl_parse 函数中完成。词法分析器和解析器分别由 flex 和 bison 生成。有关更多信息,请参阅关于解析的小节。


编译


将 AST 编译为 Mesa 中间表示法。此过程在 _mesa_ast_to_hir 函数中发生。在此阶段,编译器执行隐式转换、函数重载解析、生成内部函数的指令等功能。将生成 GLSL 主入口点。请参阅“生成 GLSL 主入口点”。此阶段会将输入及输出变量的全局声明添加到 IR,计算 HLSL 入口点的输入,调用 HLSL 入口点,并将输出写入全局输出变量。


优化


对 IR 执行多遍优化,包括直接插入函数、消除无用代码、传播常量、消除公共的子表达式,等等。有关详细信息,请参阅“优化 IR”,尤其是参阅 do_optimization_pass


一致变量打包


将全局一致变量打包成数组并保留映射信息,以便引擎可将参数与一致变量数组的相关部分绑定。有关详细信息,请参阅“打包一致变量”。


最终优化


打包一致变量之后,将对 IR 运行第二遍优化,以简化打包一致变量时生成的代码。


生成 GLSL


最后,将经过优化的 IR 转换为 GLSL 源代码。从 IR 到 GLSL 的转换相对简单。除了生成所有构造及一致变量缓冲区的定义以及源代码本身以外,还会在文件开头的注释中写入一个映射表。虚幻引擎将解析这个映射表,以便绑定参数。有关详细信息,请参阅“生成 GLSL”,尤其是参阅 ir_gen_glsl_visitor 类。

解析

HLSL 解析器分为两部分:词法分析器和解析器。词法分析器通过使正则表达式与相应的标记匹配,将 HLSL 输入标记化。源文件是 hlsl_lexer.ll,并由 flex 处理以生成 C 代码。每一行都以一个正则表达式开头,后跟以 C 代码编写的语句。该正则表达式匹配时,将执行相应的 C 代码。状态存储在许多以 "yy" 为前缀的全局变量中。

解析器将规则与标记化输入匹配,以解释语言的语法并构建 AST。源文件是 hlsl_parser.yy,并由 bison 处理以生成 C 代码。对 bison 所使用的语法进行全面说明超出了本文档的范畴,但通过检视 HLSL 解析器可了解一些基本信息。通常,您将规则定义为与某个以递归方式求值的标记序列匹配。规则匹配时,将执行一些相应的 C 代码,这使您能够构建自己的 AST。C 代码块中的语法如下所示:

$$ = 解析此规则的结果,这通常是抽象语法树中的节点 $1、$2,等等 = 当前规则所匹配的子规则的输出

对词法分析器或解析器进行更改后,必须使用 flex 和 bison 重新生成 C 代码。GenerateParsers 批处理文件可处理此任务,但您必须根据系统上 flex 和 bison 的安装位置来设置目录。README 文件中包含的信息说明了使用的版本,以及可以从什么位置下载用于 Windows 的二进制文件。

编译

在编译期间,将遍历 AST 并使用 AST 来生成 IR 指令。您应掌握的一个重要概念是,IR 是非常低级别的操作序列。因此,它不会执行隐式转换或任何具有隐式转换性质的操作:所有操作都必须显式地执行。

下面是一些有趣的常用函数:

apply_type_conversion - 此函数将一种类型的值转换为另一种类型(如果有可能的话)。是执行隐式转换还是显式转换由参数控制。

arithmetic_result_type 等- 这组函数确定对输入值应用操作的结果类型。

validate_assignment - 确定某个 rvalue 是否可赋予特定类型的 lvalue。必要时,将应用允许的隐式转换。

do_assignment - 将 rvalue 赋予 lvalue(如果可使用 validate_assignment 完成)。

ast_expression::hir - 将 AST 中的表达式节点转换为一组 IR 指令。

process_initializer - 将初始化表达式应用于变量。

ast_struct_specifier::hir - 构建聚集类型,以表示所声明的结构。

ast_cbuffer_declaration::hir - 构建常量缓冲区布局的构造,并将其存储为一致变量块。

process_mul - 这是用于处理 HLSL 内部乘法的特殊代码。

match_function_by_name - 根据输入参数的名称和列表来查找函数特征符。

rank_parameter_lists - 对两个参数列表进行比较,并指定数字排名以指示这两个列表的匹配程度。这是一个辅助函数,用于执行重载解析:排名最低的特征符将胜出,如果有任何特征符的排名与排名最低的特征符相同,那么将函数调用声明为具有歧义。排名为零表示精确匹配。

gen_texture_op - 处理内置 HLSL 纹理和取样对象的方法调用。

_mesa_glsl_initialize_functions - 生成 HLSL 内部函数的内置函数。大部分函数(例如 sin 和 cos)会生成 IR 代码以执行操作,但某些函数(例如 transpose 和 determinant)会保留函数调用以推迟操作,使其由驱动程序的 GLSL 编译器执行。

扩展编译器

下面是一些有关实现某些类型的功能的提示:

新表达式

向 ir_expression_operation 枚举添加一个条目。
在 ir_expression 构造函数中,处理您的新表达式,以根据输入操作数的类型来设置表达式的类型化结果。
如果有可能,请向 ir_expression::constant_expression_value 添加一个处理程序,以便在编译时对常量表达式进行求值。
向 ir_validate::visit_leave(ir_expression *ir) 添加一个处理程序,以验证该表达式的正确性。
向 GLSLExpressionTable 添加一个条目,以将该表达式映射到 GLSL 表达式。
修改词法分析器,使其识别该表达式的标记(如果适用的话)。
修改解析器以使其识别该标记,并创建适当的 ast_expression 节点(如果适用的话)。

内部函数

向 _mesa_glsl_initialize_functions 添加内置函数定义。
在大部分情况下,内部函数将直接映射到单个表达式。如果是这样,您只需添加新的 ir_expression 并使用 make_intrinsic_genType 来生成内部函数。

类型

添加 glsl_type,以在 IR 中表示您的类型。您可将其添加到 _mesa_glsl_initialize_types,或添加到其中一个内置类型表,例如 glsl_type::builtin_core_types。对于模板化类型,请参阅 glsl_type::get_sampler_instance 作为示例。
修改词法分析器以使其识别必要的标记,并修改解析器以使其与您的标记匹配。请参阅 Texture2DArray 作为示例。
修改解析器以使其识别该标记,并创建必要的类型说明符。texture_type_specifier_nonarray 是一个不错的示例。
修改 ast_type_specifier::hir,以执行创建用户定义类型所需的任何处理。请参阅结构的处理作为示例。
修改 ast_type_specifier::glsl_type 以返回适当的 glsl_type。
如果类型包含方法,请修改 _mesa_ast_field_selection_to_hir 以处理这些方法。请参阅 gen_texture_op 作为示例。

属性、标志和限定符

将属性/标志/限定符添加到任何需要它们的 IR 和/或 AST 节点。
修改词法分析器,使其识别必要的标记。
修改解析器,以根据需要添加语法规则。例如,如果您要添加对 [loop] 属性的支持,请修改 iteration_statement 规则以接受其前面的可选属性。操作如下:将 iteration_statement 更改为 base_iteration_statement,并添加

iteration_statement:

iteration_attr base_iteration_statement
{
    // result is the iteration statement
    $$ = $2;
    // apply attribute
    $$->attr = $1;
}
base_iteration_statement
{
    // pass thru if no attribute
    $$ = $1;
}

最后,在编译器中任何需要了解该属性的位置进行修改。

原文:https://docs.unrealengine.com/latest/CHN/Programming/Rendering/ShaderDevelopment/HLSLCrossCompiler/index.html

原文地址:https://www.cnblogs.com/wodehao0808/p/8110533.html

时间: 2024-07-31 05:29:52

(转载)(官方)UE4--图像编程----着色器开发----HLSL 交叉编译器的相关文章

(转载)(官方)UE4--图像编程----着色器开发

着色器开发 快速入门 处理着色器时,请务必将 r.ShaderDevelopmentMode 设置为 1,以将其启用.最简单的方法是编辑 ConsoleVariables.ini,以便每次加载时都进行启用.这将启用"出错时重试"以及与着色器开发相关的日志和警告. 将更改保存到 .usf 文件之后,使用 Ctrl+Shift+. 可重新编译已更改的着色器. 如果您更改包括在许多着色器中的文件(例如,common.usf),那么此操作可能需要花费一些时间.如果您想对某个材质进行迭代,那么可

GPU渲染管线与可编程着色器

本文由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://blog.csdn.net/poem_qianmo/article/details/71978861 这篇文章是解析计算机图形学界"九阴真经总纲"一般存在的<Real-Time Rendering 3rd>系列文章的第三篇.将带来RTR3第三章内容"Chapter 3 The Graphics Processing Unit 图形处理器"的总结.概括与提炼. 这章的主要内容是介绍G

OpenGL管线(用经典管线代说着色器内部)

图形管线(graphics pipeline)向来以复杂为特点,这归结为图形任务的复杂性和挑战性.OpenGL作为图形硬件标准,是最通用的图形管线版本.本文用自顶向下的思路来简单总结OpenGL图形管线,即从最高层开始,然后逐步细化到管线图中的每个框,再进一步细化到OpenGL具体函数.注意,这里用经典管线代说着色器内部,也就是OpenGL固定管线功能(Fixed-Function,相对于programmable也即可编程着色器),也会涉及着色器,但差不多仅限于“这些固定管线功能对应xx着色器”

DirectX11 With Windows SDK--26 计算着色器:入门

前言 现在开始迎来所谓的高级篇了,目前计划是计算着色器部分的内容视项目情况,大概会分3-5章来讲述. DirectX11 With Windows SDK完整目录 Github项目源码 欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报. 概述 GPU通常被设计为从一个位置或连续的位置读取并处理大量的内存数据(即流操作),而CPU则被设计为专门处理随机内存的访问. 由于顶点数据和像素数据可以分开处理,GPU架构使得它能够高度并行,在处理图像上效率非常高.但

WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码

原文:WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码 HLSL,High Level Shader Language,高级着色器语言,是 Direct3D 着色器模型所必须的语言.WPF 支持 Direct3D 9,也支持使用 HLSL 来编写着色器.你可以使用任何一款编辑器来编写 HLSL,但 Shazzam Shader Editor 则是专门为 WPF 实现像素着色器而设计的一款编辑器,使用它来编写像素着色器,可以省去像素着色器接入

内置着色器包含文件

Unity包含了好几个文件,这些文件可以在你自己的shader 程序中使用,提供预定义的变量和功能函数.这个操作通过标准的指令 :#include来引入. CGPROGRAM // ... #include "UnityCG.cginc" // ... ENDCG 着色器包含文件在unity中以.cginc扩展名结尾,内置的为: HLSLSupport.cginc - (自动包含)用于跨平台着色程序编译的帮助宏和定义. UnityShaderVariables.cginc - (自动包

D3D三层Texture纹理经像素着色器实现渲染YUV420P

简单记录一下这两天用Texture实现渲染YUV420P的一些要点. 在视频播放的过程中,有的时候解码出来的数据是YUV420P的.表面(surface)通过设置参数是可以渲染YUV420P的,但Texture纹理似乎不支持直接渲染YUV420P.表面(surface)用法似乎比较单一,通常用来显示数据,用Texture的话就可以用上D3D的许多其他功能,做出一些效果.当然,这看个人需求,通常而言显示视频数据用表面就够了. 1.利用像素着色器把YUV420P数据转为RGB32 视频播放过程中帧与

Direct2D 1.1 开发笔记 特效篇(三) 简单的像素着色器特效

(转载请注明出处) 这次我们实现一个自定义的转变. 实现Direct2D 自定义转变Shader Models需要HLSL(High Level Shading Language)的实现. HLSL是Shader的一种实现,但是HLSL只能在D3D中使用,所以有点蛋疼. Shader被描述为显卡执行的小段程序,能够高效(并行)地执行. 没学过?没关系,笔者也没有,但是详细的不会在这里说明(你TM逗我(╯‵□′)╯︵┴─┴),请到官网中看看. D2D 特效能用 HLSL 的  4.0 及其以上版本

【浅墨Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 &amp; 纹理混合

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/41175585 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 邮箱: [email protected] 本文介绍了Unity中子着色器.通道和标签相关的详细概念与写法,以及纹理的设置方法,基本的纹理混合写法,写了5个Shader作为本文Shader讲解的实战内容,最后创建了一个梦幻的光之