directx-11 - HLSL 编译器省略了关键语句
问题描述
我有这个遍历二叉树的计算着色器。它曾经与单独安装的 DirectX SDK(6 月)和编译器 #43 一起正常工作。
然而,编译器#46 和#47(分别来自 Windows SDK 8.0 和 8.1)似乎省略了两行非常关键的代码,它们使着色器循环运行,一遍又一遍地检查相同的树节点,直到 Windows 重新启动图形驱动程序(通过查看反汇编验证)。
这是展示此行为的最小代码示例:
#define LEFT_PROCESSED 1
#define RIGHT_PROCESSED 2
struct Node
{
float4 min;
float4 max;
int left;
int right;
int parent;
int flags;
};
RWStructuredBuffer<Node> tree: register(u0);
bool TreeSearch()
{
Node node = tree[0];
int nodeId = 0;
int statusStack[40];
int stackSize = 0;
statusStack[0] = 0;
while (true)
{
if (!(statusStack[stackSize] & LEFT_PROCESSED))
{
statusStack[stackSize] |= LEFT_PROCESSED;
++stackSize;
statusStack[stackSize] = 0;
nodeId = node.left;
node = tree[nodeId];
continue;
}
if (!(statusStack[stackSize] & RIGHT_PROCESSED))
{
statusStack[stackSize] |= RIGHT_PROCESSED; // this line
++stackSize;
statusStack[stackSize] = 0; // and this line
nodeId = node.right;
node = tree[nodeId];
continue;
}
if (node.parent != -1)
{
--stackSize;
nodeId = node.parent;
node = tree[nodeId];
}
else
return false;
}
return false;
}
[numthreads(32, 1, 1)]
void CSSearch(uint2 dispatchThreadId: SV_DispatchThreadID)
{
TreeSearch();
}
以及相应的组件:
cs_5_0
dcl_globalFlags refactoringAllowed
dcl_uav_structured u0, 48
dcl_temps 3
dcl_indexableTemp x0[40], 4
dcl_thread_group 32, 1, 1
ld_structured_indexable(structured_buffer, stride=48)(mixed,mixed,mixed,mixed) r0.xyz, l(0), l(32), u0.xyzx
mov x0[0].x, l(0)
mov r1.xyz, r0.yzxy
mov r0.w, l(0)
loop
mov r1.w, x0[r0.w + 0].x
and r2.x, r1.w, l(1)
if_z r2.x
or r1.w, r1.w, l(1) // here's the first one in the LEFT branch
mov x0[r0.w + 0].x, r1.w //
iadd r1.w, r0.w, l(1)
mov x0[r1.w + 0].x, l(0) // and the second one
ld_structured_indexable(structured_buffer, stride=48)(mixed,mixed,mixed,mixed) r2.xyz, r1.z, l(32), u0.yzxx
mov r1.xyz, r2.xyzx
mov r0.w, r1.w
continue
endif
mov r1.w, x0[r0.w + 0].x // why is there nothing in the RIGHT branch?
and r1.w, r1.w, l(2)
if_z r1.w
iadd r1.w, r0.w, l(1)
ld_structured_indexable(structured_buffer, stride=48)(mixed,mixed,mixed,mixed) r2.xyz, r1.x, l(32), u0.yzxx
mov r1.xyz, r2.xyzx
mov r0.w, r1.w
continue
endif
ine r1.w, r1.y, l(-1)
if_nz r1.w
iadd r0.w, r0.w, l(-1)
ld_structured_indexable(structured_buffer, stride=48)(mixed,mixed,mixed,mixed) r1.xyz, r1.y, l(32), u0.yzxx
else
break
endif
endloop
ret
当我省略第一行时continue
,它会为这两行生成代码,但随后它也被破坏了。
知道如何让更新的编译器生成该代码吗?
解决方案
请注意:我不熟悉GPU编程,不确定这是编译器的错还是代码的错。以下只是一种解决方法。
您可以通过使用显式变量来模仿continue
行为,希望编译器不会妨碍您:
bool TreeSearch()
{
Node node = tree[0];
int nodeId = 0;
int statusStack[40];
int stackSize = 0;
statusStack[0] = 0;
while (stackSize < 10) // Changed to make it compile.
{
int shouldContinue = 1;
if (!(statusStack[stackSize] & LEFT_PROCESSED))
{
statusStack[stackSize] |= LEFT_PROCESSED;
++stackSize;
statusStack[stackSize] = 0;
nodeId = node.left;
node = tree[nodeId];
shouldContinue = 0;
}
if (shouldContinue &&
!(statusStack[stackSize] & RIGHT_PROCESSED))
{
statusStack[stackSize] |= RIGHT_PROCESSED; // this line
++stackSize;
statusStack[stackSize] = 0; // and this line
nodeId = node.right;
node = tree[nodeId];
shouldContinue = 0;
}
if (shouldContinue)
{
if (node.parent != -1)
{
--stackSize;
nodeId = node.parent;
node = tree[nodeId];
}
else
return false;
}
}
return false;
}
反汇编输出似乎不缺少原始代码段中缺少的任何操作。不过,这可能会产生开销。
链接:http ://shader-playground.timjones.io/6abdc64cdf98e1840a3b38c629b4e217
推荐阅读
- reactjs - _firebase_js__WEBPACK_IMPORTED_MODULE_1__.firebase.auth.GoogleAuthProvider 不是构造函数
- javascript - 在网页上定位表格
- python - 如何仅用 1 个所需输出从字典中替换列表中的字符串
- python - 如何在python中发送消息并等待回复,whatsapp中的twilio
- javascript - 在 JavaScript 中创建自定义警报
- google-sheets - 电子表格:动态行数的总和
- python - statsmodel ARIMA 的不切实际的均方误差
- node.js - 如何解决 UnhandledPromiseWarning?
- python - 为什么我在 imac 上找不到 libc++.1.dylib?
- python - RuntimeError:设备类型为 cuda 的预期对象,但在调用 _thnn_conv2d_forward 时获得了参数 #1 'self' 的设备类型 cpu