• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
LOFLY
终其一生,编织快乐
博客园    首页    新随笔    联系   管理    订阅  订阅

DXIL之类型体系

DXIL中的类型系统

DXIL之类型体系

  DXIL 中大部分 LLVM 类型系统的构造都是合法的。

基本类型

支持以下基本类型:

  • void
  • metadata
  • i1, i8, i16, i32, i64
  • half, float, double

SM6.0 假设原生硬件支持 i32 和 float 类型。
i8 仅在一些内置函数中用于表示掩码、枚举常量值或元数据,它不支持在着色器中进行内存访问或计算。

HLSL 中的 min12int、min16int 和 min16uint 数据类型被映射为 i16。

在 SM6.0 中,half 和 i16 被视为对应的 DXBC min-precision 类型(min16float、min16int/min16uint)。

HLSL 编译器优化器将 half、i16 和 i8 数据视为硬件原生支持的数据类型;也就是说,饱和度、范围裁剪以及 INF/NaN 处理都按照 IEEE 标准进行。这样的语义允许优化器重用 LLVM 优化 passes。

硬件对于双精度(double)的支持是可选的,并且由 RequiresHardwareDouble CAP 位进行保护。

硬件对于 i64 的支持是可选的,并且由 CAP 位进行保护。

向量 Vectors

  HLSL 向量会被标量化。它们不参与计算,但可以在声明中存在,以将原始变量布局传达给工具、调试器和反射机制。

  未来的 DXIL 可能会增加对于 <2 x half> 和 <2 x i16> 向量的支持,或是提供关于打包相关 half 和 i16 数量的提示。

矩阵 Matrics

  矩阵会被降低为向量,并且不会被指令引用。它们可以在声明中存在,以将原始变量布局传达给工具、调试器和反射机制。

数组 Arrays

   指令只能引用一维基本类型数组。然而,复杂的数组,例如多维数组或用户定义类型,可以存在以将基本变量布局传达给工具、调试器和反射机制。

用户定义的类型

  原始的 HLSL 用户自定义类型(UDT)会被降级,不会被指令引用。然而,它们可以在声明中存在,以将原始变量布局传达给工具、调试器和反射机制。某些资源操作会返回“分组”UDT,用于将多个返回值组合在一起;这样的UDT会立即被“解构”,转换为组件,然后被其他指令使用。

类型转换

   LLVM指令支持类型之间的显式转换。

精度限定符

   默认情况下,所有的浮点数 HLSL 操作被视为“快速”或非精确的操作。HLSL 和驱动程序编译器可以对这些操作进行重构。非精确的 LLVM 指令包括:fadd、fsub、fmul、fdiv、frem、fcmp,它们都标有“快速”数学标志。

   HLSL 中的 precise 类型限定符要求所有对值有贡献的操作在进行优化时都需要遵守 IEEE 标准。编译器开关 /Gis 隐式地将所有变量和值声明为 precise 类型。

   精确行为在 LLVM 指令中以不设置“快速”数学标志的方式表示:fadd、fsub、fmul、fdiv、frem、fcmp。每个与计算精确值相关的调用指令都用 dx.precise 元数据进行注释,指示驱动程序编译器不得执行不符合 IEEE 标准的优化操作。

类型注释

   在DXIL中,用户自定义类型可以用于为结构字段“附加”其他属性。例如,DXIL可以包含用于反射目的的结构和函数的类型注释。

namespace MyNameSpace {
  struct MyType {
      float field1;
      int2 field2;
  };
}

float main(float col : COLOR) : SV_Target {
  .....
}

!dx.typeAnnotations = !{!3, !7}
!3 = !{i32 0, %"struct.MyNameSpace::MyType" undef, !4}
!4 = !{i32 12, !5, !6}
!5 = !{i32 6, !"field1", i32 3, i32 0, i32 7, i32 9}
!6 = !{i32 6, !"field2", i32 3, i32 4, i32 7, i32 4}
!7 = !{i32 1, void (float, float*)* @"main", !8}
!8 = !{!9, !11, !14}
!9 = !{i32 0, !10, !10}
!10 = !{}
!11 = !{i32 0, !12, !13}
!12 = !{i32 4, !"COLOR", i32 7, i32 9}
!13 = !{i32 0}
!14 = !{i32 1, !15, !13}
!15 = !{i32 4, !"SV_Target", i32 7, i32 9}
!16 = !{null, !"lib.no::entry", null, null, null}

  类型/字段注释元数据层次结构在DXIL中递归地模仿了LLVM类型层次结构。dx.typeAnnotations是一种类型注释节点的元数据,其中每个节点代表特定类型的类型注释。

   对于每个类型注释节点,第一个值表示注释的类型:

!3 = !{i32 0, %"struct.MyNameSpace::MyType" undef, !4}
!7 = !{i32 1, void (float, float*)* @"main", !8}

!3是一个节点表示一种类型, !7是一种节点表示一种类型。

!dx.typeAnnotations = !{!3, !7}

Idx type
0 结构体注释
1 函数注释

   第二个值表示名称,第三个值是相应的类型元数据节点。

结构体注解从结构体大小(以字节为单位)开始,然后是字段注解列表:

!4 = !{i32 12, !5, !6}
!5 = !{i32 6, !"field1", i32 3, i32 0, i32 7, i32 9}
!6 = !{i32 6, !"field2", i32 3, i32 4, i32 7, i32 4}

  !4中描述了结构体总大小是12字节,第一个字段放在!5中,第2个字段放在!6中。

   字段注释是一系列由标签号和其值组成的对。字段注释对的定义如下:

Idx Type
0 SNorm
1 UNorm
2 Matrix
3 Buffer Offset
4 Semantic String
5 Interpolation Mode
6 Field Name
7 Component Type
8 Precise

函数注解是一系列的参数注解:

!7 = !{i32 1, void (float, float*)* @"main", !8}
!8 = !{!9, !11, !14}

每个参数注解包含输入/输出类型,字段注释和语义索引:

!9 = !{i32 0, !10, !10}
!10 = !{}
!11 = !{i32 0, !12, !13}
!12 = !{i32 4, !"COLOR", i32 7, i32 9}
!13 = !{i32 0}
!14 = !{i32 1, !15, !13}
!15 = !{i32 4, !"SV_Target", i32 7, i32 9}

上一节 下一节

posted @ 2023-06-25 16:01  编织快乐  阅读(137)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3