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

问题描述

我想使用内置的导数函数

    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 变量数组,您可以通过工作组内的调用对其进行索引。每次调用都应该将自己的值写入自己的索引。

要计算导数,请在将值写入 barrier 变量后发出 memoryBarrierShared(带有 shared)。取同一个 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 变量。