utasimaru
@utasimaru

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Unity ComputeShaderでSV_GroupIndexを利用したい(ができない)

解決したいこと

Unityで独自データに対するレイチェックを実装しています。コンピュートシェーダーでDispatch(カーネル,1,1,1)の1グループだけで動作するコードが期待通り動いたので、複数グループを想定した実装を始めたのですが、SV_GroupIndexを使ってインデックスを作成するとコンパイルエラーになります。どうか解決策を教えてください。

実現したい内容

  1. 独自データの四角形の配列全てに対し、16*16でテッセレーションをして格子点の配列を作る
  2. 1で作成された(四角形の数)*256 の格子点配列をシェーダーに渡す(tessedPos)
  3. Dispatch(四角形の数,1,1)で四角形の数だけグループを作成し、(グループインデックス)*256をオフセットとして使用し四角形のレイチェックをする

発生している問題・エラー

コメントアウトされている一文以外は、1グループだけで動作する実装の状態です。
この一文を追加しても、1グループだけで実行すれば増分は0であるはずなので、問題は起こらないと思います。
しかしコメントアウトを解除すると、コンパイルエラーが発生します。エラーメッセージはコンパイルが途中で停止したこと、エラーをUnityに報告しろということが書いてあるだけでした。(report済み)

#pragma kernel TessedQuadRayLength
#include "MollerTrumboreRayCheck.hlsl"
float3 rayOrigin;
float3 rayDirection;
RWStructuredBuffer<float> IntersectLength;
half3 tessedPos[64000];
[numthreads(15, 15, 1)]
void TessedQuadRayLength(uint3 threadID : SV_GroupThreadID, uint3 quadID : SV_GroupID)
{
    uint tessid = threadID.x + 16 * threadID.y;
    //tessid += quadID.x * 256;
    float3 LD = tessedPos[tessid];
    float3 LU = tessedPos[tessid + 16];
    float3 RD = tessedPos[tessid + 1];
    float3 RU = tessedPos[tessid + 17];
    
    uint resultIndex = threadID.x + threadID.y * 15;
    IntersectLength[resultIndex] = 9999;
    float lengthA = IntersectRayLengthFB(rayOrigin, rayDirection, RD, LD, LU);
    if (0 < lengthA)
    {
        IntersectLength[resultIndex] = lengthA;
        return;
    }
    float lengthB = IntersectRayLengthFB(rayOrigin, rayDirection, LU, RU, RD);
    if (0 < lengthB)
    {
        IntersectLength[resultIndex] = lengthB;
    }
}

再現方法

空プロジェクト(Unity2022.3.2f1) でも、関係する2ファイルをアセットに入れてから、プレイボタンを押すなどしてシェーダーコンパイルを走らせるとエラーが発生しました。

RayCheckTessedQuad.compute
#pragma kernel TessedQuadRayLength
#include "MollerTrumboreRayCheck.hlsl"
float3 rayOrigin;
float3 rayDirection;
RWStructuredBuffer<float> IntersectLength;

half3 tessedPos[64000];
[numthreads(15, 15, 1)]
void TessedQuadRayLength(uint3 threadID : SV_GroupThreadID, uint3 quadID : SV_GroupID)
{
    uint tessid = threadID.x + 16 * threadID.y;
    //tessid += quadID.x * 256;
    float3 LD = tessedPos[tessid];
    float3 LU = tessedPos[tessid + 16];
    float3 RD = tessedPos[tessid + 1];
    float3 RU = tessedPos[tessid + 17];
    
    uint resultIndex = threadID.x + threadID.y * 15;
    IntersectLength[resultIndex] = 9999;
    float lengthA = IntersectRayLengthFB(rayOrigin, rayDirection, RD, LD, LU);
    if (0 < lengthA)
    {
        IntersectLength[resultIndex] = lengthA;
        return;
    }
    float lengthB = IntersectRayLengthFB(rayOrigin, rayDirection, LU, RU, RD);
    if (0 < lengthB)
    {
        IntersectLength[resultIndex] = lengthB;
    }
}
MollerTrumboreRayCheck.hlsl
#define RayCheckEPSILON 0.0001
#define BaseProcess \
half3 edge1, edge2, h, s, q;\
half a, f, u, v;\
half resultFlag = 1.0;\
edge1 = vertex1 - vertex0;\
edge2 = vertex2 - vertex0;\
h = cross(rayDirection, edge2);\
a = dot(edge1, h);\
if(-RayCheckEPSILON < a && a < RayCheckEPSILON)return 0;\
f = 1.0 / a; \
s = rayOrigin - vertex0;\
u = f * dot(s, h); \
resultFlag *= (u < 0.0 || 1.0 < u) ? 0.0 : 1.0; \
q = cross(s, edge1); \
v = f * dot(rayDirection, q); \
resultFlag *= (v < 0.0 || 1.0 < u + v) ? 0.0 : 1.0; \
half length = f * dot(edge2, q) * resultFlag;

half IntersectRayLengthFB(half3 rayOrigin, half3 rayDirection, half3 vertex0, half3 vertex1, half3 vertex2)
{
    BaseProcess
    return length;
}
half IntersectRayLengthF(half3 rayOrigin, half3 rayDirection, half3 vertex0, half3 vertex1, half3 vertex2)
{
    BaseProcess
    half frontFlag = step(-RayCheckEPSILON, a);
    return length * frontFlag;
}
half IntersectRayLengthB(half3 rayOrigin, half3 rayDirection, half3 vertex0, half3 vertex1, half3 vertex2)
{
    BaseProcess
    half backFlag = step(a, RayCheckEPSILON);
    return length * backFlag;
}
0

1Answer

65536 bytesを超える変数を定義し、かつコンパイル時にアクセスするべき変数が65536 bytesを超える場合にコンパイルエラーになるようです。
解決策として、structuredbufferにしてデータを渡すことでこの上限を超えてコンパイルすることができました。

以下のフォーラムが役立ちました
https://forum.unity.com/threads/compute-shader-compiler-crashes-when-trying-to-read-value-from-an-array.1306776/

0Like

Your answer might help someone💌