Etherliah
Etherliah

Reputation: 11

Output of Compute Shader with error (inconsistent value)

I have a issue in unity3D with ComputeShader.

My objective : find all normals facing the camera (dot of two vector > 0)

As my camera and my model are fixed, I expect to get always the same amount of normal in output of my compute shader.

But, each time I use the compute shader, the count increase, leading me to a number of normals facing the camera superior to the number in the mesh and it quickly reach a point where I have 10e9 normals. And sometime this value is negative.

I use a append buffer for this purpose, and my hlsh only test the dot , and append the value to the buffer.

My question is : Where is the problem ?

I suspect a problem with the GPU memory, but I can't find why (first time hlsl/unity3)

C# : Note : Key is for another test

public static Vector3[] KeyCam(Vector3 key, Vector3 cam, Vector3[] normal) {
ComputeShader shader = (ComputeShader) Resources.Load("ComputeShader/Normal");
int _kernel = shader.FindKernel("KeyCam");

#region init Buffer
ComputeBuffer inputBuffer = new ComputeBuffer(normal.Length, sizeof(float) * 3);
inputBuffer.SetData(normal);
ComputeBuffer outputBuffer = new ComputeBuffer(normal.Length, sizeof(float) * 3, ComputeBufferType.Append);
#endregion

#region set
shader.SetBuffer(_kernel, "input", inputBuffer);
shader.SetBuffer(_kernel, "output", outputBuffer);
shader.SetVector("key", key);
shader.SetVector("cam", cam);
#endregion

shader.Dispatch(_kernel, 1, 1, 1);

#region get count
//https://sites.google.com/site/aliadevlog/counting-buffers-in-directcompute
ComputeBuffer countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.IndirectArguments);
ComputeBuffer.CopyCount(outputBuffer, countBuffer, 0);

//Debug.Log("Copy buffer : " + countBuffer.count);
int[] counter = new int[1] { 0 };
countBuffer.GetData(counter);
countBuffer.Release();
int c = counter[0];
#endregion

//int c = GetAppendCount(outputBuffer);
Debug.Log("Normals : " + c +"/"+normal.Length);
if(c <= 0)
    return null;

Vector3[] output = new Vector3[c];
outputBuffer.GetData(output);

inputBuffer.Release();
outputBuffer.Release();

return output;
    }

HLSL :

    #pragma kernel KeyCam
StructuredBuffer<float3> input;
float3 key;
float3 cam;
AppendStructuredBuffer<float3> output;

[numthreads(64,1,1)]
void KeyCam(uint3 id : SV_DispatchThreadID) {

    if (dot(input[id.x], cam) >= 0.05)
        output.Append(input[id.x]);
}

Upvotes: 1

Views: 1571

Answers (2)

Etherliah
Etherliah

Reputation: 11

Sorry I forgot to answer

I found the answer after

The problem was indeed the counter but also the method of recovery of the value.

outputBuffer.SetCounterValue(0);

and for the value

        ComputeBuffer counter = new ComputeBuffer(4, sizeof(int), ComputeBufferType.IndirectArguments);
        int[] Counts = new int[] { 0, 1, 0, 0 };
        counter.SetData(Counts);

        counter.SetData(Counts);
        ComputeBuffer.CopyCount(outputBuffer, counter, 0);
        counter.GetData(Counts);
        counter.Release();
        return Counts[0];

Upvotes: 0

mrvux
mrvux

Reputation: 8963

Since you use an apppend/counter buffer, it seems you miss the call to reset counter.

This can be done using :

outputBuffer.SetCounterValue(0);

Before the dispatch call.

If you don't reset counter, it will keep previous value as a starting point (and hence increasing every call)

See this link for more info

Upvotes: 1

Related Questions