有没有办法强制 SPIR-V 汇编函数接受私有和函数存储 class 数组?
Is there way to force SPIR-V assembly function to accept both Private and Function storage class arrays?
我正在为 SPIR-V 着色器编写二进制处理模块,以修复由于 driver 错误导致的 float4x3[6] 矩阵的对齐问题。现在我有:
- 注入必要的适当 OpTypes 和 OpTypePointers。
- 处理二进制文件以将常量缓冲区成员从 float4x3[6] 更改为 vec4[18]
- 注入函数正确地将 vec4[18] 解包为 float4x3[6],接受 vec4[18] 作为指向统一数组 18 的指针。
- 已创建专用存储限定符矩阵将目标解包为 OpVariables。(SPIR-V 中的专用仅意味着 invocation-level 全局...)。
- 注入了关于复合提取和构造的序言以调用我的新函数。 (因为从我看到的情况来看,我们总是需要将参数从常量缓冲区复制到函数,所以这就是我所做的)。
- 从入口点调用函数,以便每个 float4x3[6] 成员在 main() 启动时准备好解压缩矩阵。
- 更改了引用常量缓冲区中给定成员的 OpAccessChain 操作,并将它们与引用我的新私有目标的访问链交换。
但现在我 运行 遇到了麻烦。看起来 SPIR-V 中的函数可以接受 Private 或 Function 存储限定符指针。不是都。有什么方法可以告诉我 SPIR-V“是的,你可以将这两个存储 classes 作为参数转储到这里”?
或者我是否需要修改我的解决方案以利用函数存储 class 矩阵目标,并在每次将它们用于新函数时注入它们并调用解压缩它们?这看起来不太优雅,因为那时可能会有更多的解包操作。更不用说 hassle-free,因为我必须分别扫描每个 OpFunction 块,并将带有函数存储的 OpVariables 注入到每个使用矩阵的块中。
我的问题是,在完成所有这些机器之后,我的目标将作为私有存储持续时间的 OpTypePointer 存在。因此我不能在从 HLSL 生成的任何 SPIR-V 函数中使用它们,因为它们采用函数持续时间的 OpTypePointers。我的解包函数是唯一的例外,因为我直接将它逐字节注入 SPIR-V asm,并且能够在 header.
中精确调整 OpFunctionParameters
这是调用约定的问题。或者更确切地说,缺乏 SPIR-V.
中的调用约定
Higher-level 像 GLSL 和 HLSL 这样的语言有调用约定。他们解释了函数接受输入参数意味着什么,以及这与提供给它的参数有何关系。
SPIR-V 在这个意义上没有调用约定。或者更重要的是,您必须 构造 您想要使用 SPIR-V.
的调用约定
HLSL 中的参数是conceptually always passed by copy。如果参数是输入参数,则使用给定参数初始化副本。如果参数是输出参数,调用函数后将函数中的数据复制到参数中。
HLSL 编译器必须在 SPIR-V 中实现它。因此,如果函数采用 struct
输入参数,则该函数的输入参数必须是来自任何现有对象的 new storage。当调用者尝试调用此函数时,它必须为该参数创建存储。该存储将使用 Function
存储限定符,因此该参数也使用该限定符。
SPIR-V 要求指针类型指定它们指向的对象的存储限定符。这一点很重要,因为编译器生成访问对象的 GPU 程序集的方式可能不同(可能非常不同)。因此,函数不能接受指向不同存储的指针 类;函数必须选择一个。
因此,如果您的 SPIR-V 调整系统发现一个函数调用,其源数据来自您需要调整的内容,那么您有两个选择:
创建一个新函数,它是旧函数的副本,除了它需要一个 Private
指针。
通过创建 Function
本地存储并在调用函数之前将数据从 Private
复制到其中(如果是输出参数)。那里可能已经有执行此操作的代码,因此您可能只需要更改它复制的位置 from/to.
我正在为 SPIR-V 着色器编写二进制处理模块,以修复由于 driver 错误导致的 float4x3[6] 矩阵的对齐问题。现在我有:
- 注入必要的适当 OpTypes 和 OpTypePointers。
- 处理二进制文件以将常量缓冲区成员从 float4x3[6] 更改为 vec4[18]
- 注入函数正确地将 vec4[18] 解包为 float4x3[6],接受 vec4[18] 作为指向统一数组 18 的指针。
- 已创建专用存储限定符矩阵将目标解包为 OpVariables。(SPIR-V 中的专用仅意味着 invocation-level 全局...)。
- 注入了关于复合提取和构造的序言以调用我的新函数。 (因为从我看到的情况来看,我们总是需要将参数从常量缓冲区复制到函数,所以这就是我所做的)。
- 从入口点调用函数,以便每个 float4x3[6] 成员在 main() 启动时准备好解压缩矩阵。
- 更改了引用常量缓冲区中给定成员的 OpAccessChain 操作,并将它们与引用我的新私有目标的访问链交换。
但现在我 运行 遇到了麻烦。看起来 SPIR-V 中的函数可以接受 Private 或 Function 存储限定符指针。不是都。有什么方法可以告诉我 SPIR-V“是的,你可以将这两个存储 classes 作为参数转储到这里”?
或者我是否需要修改我的解决方案以利用函数存储 class 矩阵目标,并在每次将它们用于新函数时注入它们并调用解压缩它们?这看起来不太优雅,因为那时可能会有更多的解包操作。更不用说 hassle-free,因为我必须分别扫描每个 OpFunction 块,并将带有函数存储的 OpVariables 注入到每个使用矩阵的块中。
我的问题是,在完成所有这些机器之后,我的目标将作为私有存储持续时间的 OpTypePointer 存在。因此我不能在从 HLSL 生成的任何 SPIR-V 函数中使用它们,因为它们采用函数持续时间的 OpTypePointers。我的解包函数是唯一的例外,因为我直接将它逐字节注入 SPIR-V asm,并且能够在 header.
中精确调整 OpFunctionParameters这是调用约定的问题。或者更确切地说,缺乏 SPIR-V.
中的调用约定Higher-level 像 GLSL 和 HLSL 这样的语言有调用约定。他们解释了函数接受输入参数意味着什么,以及这与提供给它的参数有何关系。
SPIR-V 在这个意义上没有调用约定。或者更重要的是,您必须 构造 您想要使用 SPIR-V.
的调用约定HLSL 中的参数是conceptually always passed by copy。如果参数是输入参数,则使用给定参数初始化副本。如果参数是输出参数,调用函数后将函数中的数据复制到参数中。
HLSL 编译器必须在 SPIR-V 中实现它。因此,如果函数采用 struct
输入参数,则该函数的输入参数必须是来自任何现有对象的 new storage。当调用者尝试调用此函数时,它必须为该参数创建存储。该存储将使用 Function
存储限定符,因此该参数也使用该限定符。
SPIR-V 要求指针类型指定它们指向的对象的存储限定符。这一点很重要,因为编译器生成访问对象的 GPU 程序集的方式可能不同(可能非常不同)。因此,函数不能接受指向不同存储的指针 类;函数必须选择一个。
因此,如果您的 SPIR-V 调整系统发现一个函数调用,其源数据来自您需要调整的内容,那么您有两个选择:
创建一个新函数,它是旧函数的副本,除了它需要一个
Private
指针。通过创建
Function
本地存储并在调用函数之前将数据从Private
复制到其中(如果是输出参数)。那里可能已经有执行此操作的代码,因此您可能只需要更改它复制的位置 from/to.