1

我正在为 SPIR-V 着色器编写二进制处理模块,以解决由于驱动程序错误而导致的 float4x3[6] 矩阵的对齐问题。现在我有:

  • 注入必要的适当 OpTypes 和 OpTypePointers。
  • 处理二进制文件以将常量缓冲区成员从 float4x3[6] 更改为 vec4[18]
  • 注入函数将 vec4[18] 正确解包到 float4x3[6] 中,接受 vec4[18] 作为指向统一数组 18 的指针。
  • 创建了私有存储限定符矩阵解包目标作为 OpVariables。(SPIR-V 中的私有只是意味着调用级全局......)。
  • 注入了关于复合提取和构造的序言来调用我的新函数。(因为我看到我们需要将参数从常量缓冲区复制到函数,所以这就是我所做的)。
  • 从入口点调用该函数,以便每个 float4x3[6] 成员在 main() 启动时准备好解包矩阵。
  • 更改了引用常量缓冲区中给定成员的 OpAccessChain 操作,并将它们与引用我的新私有目标的访问链交换。

但现在我遇到了麻烦。看起来 SPIR-V 中的函数可以接受 Private 或 Function 存储限定符指针。不是都。有什么办法可以告诉 SPIR-V “是的,你可以在这里将这两个存储类作为参数转储”?

或者我是否需要重新设计我的解决方案以利用函数存储类矩阵目标,并在每次将它们用于新函数时注入它们并调用以解压它们?这似乎不太优雅,因为那时可能会有更多的解包操作。而且更轻松,因为我必须分别扫描每个 OpFunction 块并将带有函数存储的 OpVariables 注入使用矩阵的每个块中。

我的问题是,在完成所有这些机器之后,我的目标是作为私有存储持续时间的 OpTypePointer 生活的。因此我不能在从 HLSL 生成的任何 SPIR-V 函数中使用它们,因为它们采用函数持续时间的 OpTypePointers。我的解包函数是唯一的例外,因为我直接将它逐字节地注入到 SPIR-V asm 中,并且能够精确地调整标头中的 OpFunctionParameters。

4

1 回答 1

0

这是调用约定的问题。或者更确切地说, SPIR-V 中缺少调用约定。

像 GLSL 和 HLSL 这样的高级语言有调用约定。他们解释了函数接受输入参数的含义以及它与给它的参数之间的关系。

SPIR-V 在这个意义上没有调用约定。或者更重要的是,您必须使用 SPIR-V构建所需的调用约定。

HLSL 中的参数在概念上始终由 copy 传递。如果参数是输入参数,则使用给定参数初始化副本。如果参数是输出参数,则在调用函数后将来自函数的数据复制到参数中。

HLSL 编译器必须在 SPIR-V 中实现这一点。因此,如果函数采用struct输入参数,则该函数的输入参数必须是来自任何现有对象的新存储。当调用者尝试调用此函数时,它必须为该参数创建存储。该存储将使用Function存储限定符,因此该参数也使用该限定符。

SPIR-V 要求指针类型指定它们指向的对象的存储限定符。这很重要,因为编译器生成访问对象的 GPU 程序集的方式可能会有所不同(可能非常不同)。因此,函数不能接受指向不同存储类的指针;该功能必须选择一个。

因此,如果您的 SPIR-V 调整系统看到一个函数调用,其源数据来自您需要调整的内容,那么您有两种选择:

  1. 创建一个新函数,它是旧函数的副本,除了它需要一个Private指针。

  2. 遵循调用约定,在调用函数之前创建Function-local 存储并将Private数据复制到其中(如果它是输出参数,则复制回来)。可能已经有代码可以执行此操作,因此您可能只需要更改它从/复制到的位置。

于 2022-01-31T16:54:34.717 回答