Компилятор HLSL, пропускающий важные утверждения
У меня есть этот вычислительный шейдер, который проходит через двоичное дерево. Он хорошо работал с отдельно установленным DirectX SDK (июнь), с компилятором № 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
, он генерирует код для этих двух строк, но затем он также не работает.
Есть идеи, как заставить новый компилятор генерировать этот код?
1 ответ
Обратите внимание: я не знаком с программированием на 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