GLSL (v450) のコンピューティング シェーダーで、リアルタイムのレイ マーチングを使用するレベル アルゴリズムを使用して、octree をトラバースしようとしています。私はなんとかそれを横断し、画像を取得しましたが、私の fps は非常に低く、約 0 ~ 5 fps です。アルゴリズムの疑似コードは再帰的なものなので、スタックを使用してループに変換しました (GLSL では再帰が許可されていないため)。問題は、このループを動的に均一にしないとすぐに、約 30 ~ 40 のこの巨大な fps 低下が発生することです。
スタックで共有属性を使用すると、この fps を元に戻すことができます。これは、グローバル変数の計算シェーダーでのみ使用できます。
shared struct stack{
float tx0;
float tx1;
float ty0;
float ty1;
float tz0;
float tz1;
float txm;
float tym;
float tzm;
int currNode;
int node;
}travStack[10];
ワークグループ内のすべてのスレッド間で共有および使用できるようにします。問題は、ループを動的に均一にする必要があるように見えるため、これらをbarrier()および/またはmemoryBarrierShared()関数と同期できないことです (共有変数の下を参照してください www.opengl.org/wiki/Compute_Shader)。同期できないため、画像がピクセル化されてちらつきます。
このアルゴリズムを動的に均一なループに変換する方法はありますか? ループが動的に均一でなくなると fps が低下するのはなぜですか?
以下は、メインループの私のコードです。
void traverse(vec3 rayOrigin, vec3 direction){
rayParameter(rayOrigin, direction); //Set parameters
stackRoot = true;
bool backfire = false;
//----
float tx0;
float tx1;
float ty0;
float ty1;
float tz0;
float tz1;
float txm;
float tym;
float tzm;
//----
int v;
int v1;
int v2;
int v3;
int v4;
int v5;
int v6;
int v7;
// Test variables
int itrCount = 0;
int itrCheck = 3;
int limit = 200;
stackPointer = 0;
if ((max(max(travStack[0].tx0, travStack[0].ty0), travStack[0].tz0)) < (min(min(travStack[0].tx1, travStack[0].ty1), travStack[0].tz1))){
travStack[0].currNode = procSubtree(travStack[0].tx0, travStack[0].ty0, travStack[0].tz0, travStack[0].tx1, travStack[0].ty1, travStack[0].tz1, travStack[0].node);
while (stackPointer >= 0 ){ //itrCount < limit){
//----
tx0 = travStack[stackPointer].tx0;
tx1 = travStack[stackPointer].tx1;
ty0 = travStack[stackPointer].ty0;
ty1 = travStack[stackPointer].ty1;
tz0 = travStack[stackPointer].tz0;
tz1 = travStack[stackPointer].tz1;
txm = travStack[stackPointer].txm;
tym = travStack[stackPointer].tym;
tzm = travStack[stackPointer].tzm;
//----
switch (travStack[stackPointer].currNode){
case 0:
{
if (!backfire){
stackPointer++;
int index = travStack[stackPointer - 1].node + a + a4 + a2;
v = procSubtree(tx0, ty0, tz0, txm, tym, tzm, treeArray[index]);
if (v == -1){ //Go up one level. Either hit empty, an edge or a leaf.
stackPointer--;
travStack[stackPointer].currNode = newNode(txm, 4, tym, 2, tzm, 1);
}
else{
travStack[stackPointer].currNode = v;
}
}
else{
travStack[stackPointer].currNode = newNode(txm, 4, tym, 2, tzm, 1);
backfire = false;
}
break;
}
case 1:
{
if (!backfire){
stackPointer++;
int index1 = travStack[stackPointer - 1].node + (1 - a) + a4 + a2;
v1 = procSubtree(tx0, ty0, tzm, txm, tym, tz1, treeArray[index1]);
if (v1 == -1){ //Go up one level. Either hit empty, an edge or a leaf.
stackPointer--;
travStack[stackPointer].currNode = newNode(txm, 5, tym, 3, tz1, 8);
}
else{
travStack[stackPointer].currNode = v1;
}
}
else{
travStack[stackPointer].currNode = newNode(txm, 5, tym, 3, tz1, 8);
backfire = false;
}
break;
}
case 2:
{
if (!backfire){
stackPointer++;
int index2 = travStack[stackPointer - 1].node + (2 + a) + a4 - a2;
v2 = procSubtree(tx0, tym, tz0, txm, ty1, tzm, treeArray[index2]);
if (v2 == -1){ //Go up one level. Either hit empty, an edge or a leaf.
stackPointer--;
travStack[stackPointer].currNode = newNode(txm, 6, ty1, 8, tzm, 3);
}
else{
travStack[stackPointer].currNode = v2;
}
}
else{
travStack[stackPointer].currNode = newNode(txm, 6, ty1, 8, tzm, 3);
backfire = false;
}
break;
}
case 3:
{
if (!backfire){
stackPointer++;
int index3 = travStack[stackPointer - 1].node + (3 - a) + a4 - a2;
v3 = procSubtree(tx0, tym, tzm, txm, ty1, tz1, treeArray[index3]);
if (v3 == -1){ //Go up one level. Either hit empty, an edge or a leaf.
stackPointer--;
travStack[stackPointer].currNode = newNode(txm, 7, ty1, 8, tz1, 8);
}
else{
travStack[stackPointer].currNode = v3;
}
}
else{
travStack[stackPointer].currNode = newNode(txm, 7, ty1, 8, tz1, 8);
backfire = false;
}
break;
}
case 4:{
if (!backfire){
stackPointer++;
int index4 = travStack[stackPointer - 1].node + (4 + a) - a4 + a2;
v4 = procSubtree(txm, ty0, tz0, tx1, tym, tzm, treeArray[index4]);
if (v4 == -1){ //Go up one level. Either hit empty, an edge or a leaf.
stackPointer--;
travStack[stackPointer].currNode = newNode(tx1, 8, tym, 6, tzm, 5);
}
else{
travStack[stackPointer].currNode = v4;
}
}
else{
travStack[stackPointer].currNode = newNode(tx1, 8, tym, 6, tzm, 5);
backfire = false;
}
break;
}
case 5:
{
if (!backfire){
stackPointer++;
int index5 = travStack[stackPointer - 1].node + (5 - a) - a4 + a2;
v5 = procSubtree(txm, ty0, tzm, tx1, tym, tz1, treeArray[index5]);
if (v5 == -1){ //Go up one level. Either hit empty, an edge or a leaf.
stackPointer--;
travStack[stackPointer].currNode = newNode(tx1, 8, tym, 7, tz1, 8);
}
else{
travStack[stackPointer].currNode = v5;
}
}
else{
travStack[stackPointer].currNode = newNode(tx1, 8, tym, 7, tz1, 8);
backfire = false;
}
break;
}
case 6:
{
if (!backfire){
stackPointer++;
int index6 = travStack[stackPointer - 1].node + (6 + a) - a4 - a2;
v6 = procSubtree(txm, tym, tz0, tx1, ty1, tzm, treeArray[index6]);
if (v6 == -1){ //Go up one level. Either hit empty, an edge or a leaf.
stackPointer--;
travStack[stackPointer].currNode = newNode(tx1, 8, ty1, 8, tzm, 7);
}
else{
travStack[stackPointer].currNode = v6;
}
}
else{
travStack[stackPointer].currNode = newNode(tx1, 8, ty1, 8, tzm, 7);
backfire = false;
}
break;
}
case 7:
{
if (!backfire){
stackPointer++;
int index7 = travStack[stackPointer - 1].node + (7 - a) - a4 - a2;
v7 = procSubtree(txm, tym, tzm, tx1, ty1, tz1, treeArray[index7]);
if (v7 == -1){ //Go up one level. Either hit empty, an edge or a leaf.
stackPointer--;
travStack[stackPointer].currNode = 8;
}
else{
travStack[stackPointer].currNode = v7;
}
}
else{
travStack[stackPointer].currNode = 8;
backfire = false;
}
break;
}
}
//itrCount++;
if (noiseAlpha >= 1.0){
break;
}
if (!(travStack[stackPointer].currNode < 8)){
stackPointer--;
backfire = true;
}
}
}
}