您可以在计算着色器中使用内置的导数函数吗? (凡尔康)

Can you use the built in derivative functions in compute shaders? (vulkan)

我想使用内置的衍生函数:

    vec3 dpdx = dFdx(p);
    vec3 dpdy = dFdy(p);

在计算着色器中。但是我收到以下错误:

Message ID name: UNASSIGNED-CoreValidation-Shader-InconsistentSpirv
Message: Validation Error: [ UNASSIGNED-CoreValidation-Shader-InconsistentSpirv ] Object 0: handle = 0x5654380d4dd8, name = Logical device: GeForce GT 1030, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x6bbb14 | SPIR-V module not valid: OpEntryPoint Entry Point <id> '5[%main]'s callgraph contains function <id> 46[%BiplanarMapping_s21_vf3_vf3_f1_], which cannot be used with the current execution modes:
Derivative instructions require DerivativeGroupQuadsNV or DerivativeGroupLinearNV execution mode for GLCompute execution model: DPdx
Derivative instructions require DerivativeGroupQuadsNV or DerivativeGroupLinearNV execution mode for GLCompute execution model: DPdy

  %BiplanarMapping_s21_vf3_vf3_f1_ = OpFunction %v4float None %41

Severity: VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT

我在网上搜索时似乎没有找到任何关于该主题的内容。

导数函数仅适用于片段着色器。导数基于正在渲染的基元上的值的变化率。显然计算着色器不渲染基元,所以没有什么可计算的。

显然,NVIDIA has an extension that provides some derivative computation capabilities for compute shaders。这就是奇怪错误的来源。

片段着色器中的导数是通过从相邻调用中减去相同值来计算的。因此,您可以使用 shared 变量来模拟这一点。

首先,您必须确保空间上相邻的调用在同一个工作组中。因此,您的工作组大小需要是 2x2 调用的某个倍数。然后,您需要一个 shared 变量数组,您可以通过工作组内的调用对其进行索引。每次调用都应将自己的值写入自己的索引。

要计算导数,请在将值写入 shared 变量后发出 barrier(使用 memoryBarrierShared)。计算同一 2x2 四边形中一个调用与相邻调用之间的差异。您应该确保同一个四边形中的所有调用都获得相同的值,方法是始终在四边形中的较低索引和较高索引之间进行减法。像这样:

uvec2 quadIndex = gl_LocalInvocationID.xy / 2
/*type*/ derFdX = variable[quadIndex.x + 1][quadIndex.y + 0] - variable[quadIndex.x + 0][quadIndex.y + 0]
/*type*/ derFdY = variable[quadIndex.x + 0][quadIndex.y + 1] - variable[quadIndex.x + 0][quadIndex.y + 0]

NVIDIA 扩展程序基本上可以为您完成此操作,但它可能更有效,因为它不需要 shared 变量。