Unity crashes when running path tracing

I’m studying path tracing, at the moment I created a compute shader that aims to calculate the intersection of rays with meshes. However, when I run the code the unity crashes, displaying a graphics card error.

The error is in the detection of intersection with the meshes. When I put the lines of code responsible for writing a new ray.

But I’m not managing to fix it. I also don’t understand if it could be a problem with my video card or my code. I tested it with only 1 mesh triangle and got a lot of lag.

To send the vertices to the video card I did the following. I got the stitches from the scene. Then I took the indices and vertices arrays and merged them with the other meshes.

public void buildObjectList()
        {
            int indicesCount = 0;
            int verticesCount = 0;

            foreach (PathTracingObject pto in pathTracingObjects)
            {
                int[] triangles;
                Vector3[] vertices;

                triangles = pto.objectMesh.triangles;//Take a sequence of vertices that form a triangle.
                vertices = pto.objectMesh.vertices;//Take vertex list

                pto._pathTracingObject.indicesOffset = indicesCount;//Offset: Where the list of indices belonging to the object starts. | indicesCount: How many indices were added before these.
                pto._pathTracingObject.indicesCount = triangles.Length;//How many indexes does this object have.

                foreach (Vector3 vertice in vertices)
                    this.vertices.Add(vertice);

                for (int i = 0; i < triangles.Length; i++)
                {
                    this.indices.Add(triangles[i] + verticesCount + 1);//Variable containing all indices of all objects in the scene. | triangles[i] (take an index) +verticesCount(Add to the amount of vetices already added) + 1

                    /*Example:
                    If the previous object has 270 vertices.
                    The first triangle of the next objects will be connected to the vertices(271, 272, 273) instead of(0,1,2).
                    +1 because vertex 270 belongs to a different object.*/
                }

                indicesCount += triangles.Length;//update index
                verticesCount += vertices.Length;//update index
            }
        }

In compute shader:

/*
http://www.graphics.cornell.edu/pubs/1997/MT97.html
https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates
*/
bool IntersectTriangle(Ray ray, float3 vert0, float3 vert1, float3 vert2, inout float t, inout float u, inout float v)
{
    float3 edge1 = vert1 - vert0;
    float3 edge2 = vert2 - vert0;
    float3 pvec = cross(ray.rayDirection, edge2);
    float det = dot(edge1, pvec);
    if (det < EPSILON)
        return false;
    float inv_det = 1.0f / det;
    float3 tvec = ray.raySource - vert0;
    u = dot(tvec, pvec) * inv_det;
    if (u < 0.0 || u > 1.0f)
        return false;
    float3 qvec = cross(tvec, edge1);
    v = dot(ray.rayDirection, qvec) * inv_det;
    if (v < 0.0 || u + v > 1.0f)
        return false;
    t = dot(edge2, qvec) * inv_det;
    return true;
}


void IntersectMeshObject(pathTracingObject pto, Ray ray, inout RayHit bestHit)
{
    for (int i = 0; i < pto.indicesCount; i += 3) {
        float3 v0 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i]], 1))).xyz;
        float3 v1 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 1]], 1))).xyz;
        float3 v2 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 2]], 1))).xyz;

        float t, u, v;
        if (IntersectTriangle(ray, v0, v1, v2, t, u, v))
        {
            if (t > 0 && t < bestHit.hitDistance)
            {
                /*           
                bestHit.hitDistance = t; // makes unity crash
                bestHit.hitPosition = ray.raySource + t * ray.rayDirection; // makes unity crash
                bestHit.hitNormal = normalize(bestHit.hitPosition); // makes unity crash

                bestHit.hitAlbedo = float3(1,1,1); // makes unity crash
                */
            }
        }


Message information: We detected driver timeout on your system. A bug report was generated. this report can help AMD resolve the issue.

Full code:

// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CSMain

#define PI 3.14159265359
#define EPSILON 0.0000001

RWTexture2D<float4> Result;

struct pathTracingObject
{
    float4 Position;

    int indicesCount;
    int indicesOffset;

    float4x4 localToWorldMatrix;
};

StructuredBuffer<pathTracingObject> _pathTracingObject;
StructuredBuffer<float3> _Vertices;
StructuredBuffer<int> _Indices;

int _pathTracingObjectCount;

float4x4 _CameraToWorld;
float4x4 _CameraInverseProjection;
 
struct Ray {
    float3 raySource;
    float3 rayDirection;
    float3 rayColor;
};

Ray CreateRay(float3 source, float3 direction)
{
    Ray ray;
    ray.raySource = source;
    ray.rayDirection = direction;

    return ray;
}

Ray CreateCameraRay(float2 uv)
{
    float3 source = mul(_CameraToWorld, float4(0.0f, 0.0f, 0.0f, 1.0f)).xyz;

    float3 direction = mul(_CameraInverseProjection, float4(uv, 0.0f, 1.0f)).xyz;
    direction = mul(_CameraToWorld, float4(direction, 0.0f)).xyz;
    direction = normalize(direction);
    return CreateRay(source, direction);
}

struct RayHit
{
    float3 hitPosition;
    float hitDistance;
    float3 hitNormal;

    float3 hitAlbedo;
};

RayHit CreateRayHit()
{
    RayHit hit;

    hit.hitPosition = float3(0.0f, 0.0f, 0.0f);
    hit.hitDistance = 1.#INF;
    hit.hitNormal = float3(0.0f, 0.0f, 0.0f);

    hit.hitAlbedo = float3(0.0f, 0.0f, 0.0f);

    return hit;
}

/*
http://www.graphics.cornell.edu/pubs/1997/MT97.html
https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates
*/
bool IntersectTriangle(Ray ray, float3 vert0, float3 vert1, float3 vert2, inout float t, inout float u, inout float v)
{
    float3 edge1 = vert1 - vert0;
    float3 edge2 = vert2 - vert0;
    float3 pvec = cross(ray.rayDirection, edge2);
    float det = dot(edge1, pvec);
    if (det < EPSILON)
        return false;
    float inv_det = 1.0f / det;
    float3 tvec = ray.raySource - vert0;
    u = dot(tvec, pvec) * inv_det;
    if (u < 0.0 || u > 1.0f)
        return false;
    float3 qvec = cross(tvec, edge1);
    v = dot(ray.rayDirection, qvec) * inv_det;
    if (v < 0.0 || u + v > 1.0f)
        return false;
    t = dot(edge2, qvec) * inv_det;
    return true;
}


void IntersectMeshObject(pathTracingObject pto, Ray ray, inout RayHit bestHit)
{
    for (int i = 0; i < pto.indicesCount; i += 3) {
        float3 v0 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i]], 1))).xyz;
        float3 v1 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 1]], 1))).xyz;
        float3 v2 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 2]], 1))).xyz;

        float t, u, v;
        if (IntersectTriangle(ray, v0, v1, v2, t, u, v))
        {
            if (t > 0 && t < bestHit.hitDistance)
            {
                           
                bestHit.hitDistance = t; // makes unity crash
                bestHit.hitPosition = ray.raySource + t * ray.rayDirection; // makes unity crash
                bestHit.hitNormal = normalize(bestHit.hitPosition); // makes unity crash

                bestHit.hitAlbedo = float3(1,1,1); // makes unity crash
             
            }
        }

    }
}

RayHit Trace(Ray ray)
{
    RayHit bestHit = CreateRayHit();

    for (int i = 0; i < _pathTracingObjectCount; i++) {
        pathTracingObject pto = _pathTracingObject[i];
        IntersectMeshObject(pto, ray, bestHit);
    }

    return bestHit;
}

[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    // TODO: insert actual code here!
    float3 result = float3(0, 0, 0);

    int width, height;
    Result.GetDimensions(width, height);
    float2 uv = float2((id.xy + float2(0.5f, 0.5f)) / float2(width, height) * 2.0f - 1.0f);

    for(int i = 0; i < 1;i++) {
        Ray ray = CreateCameraRay(id.xy);
        RayHit hit = Trace(ray);
        result += hit.hitAlbedo;
    }
    result /= float3(5,5,5);

    Result[id.xy] = float4(result, 1);
}

C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

[System.Serializable]
class PathTracing
{
 
    [SerializeField]
    ComputeShader computeShader;
    [SerializeField]
    GameObject[] pathTracingObjects;
  
    class PathTracingComputeShader
    {
        PathTracingObject[] pathTracingObjects;

        public List<Vector3> vertices = new List<Vector3>();
        public List<int> indices = new List<int>();

        RenderTexture RT;
        public void loadRenderTexture()
        {
            RT = new RenderTexture(Mathf.CeilToInt(Screen.width / 4), Mathf.CeilToInt(Screen.height / 4), 0, RenderTextureFormat.DefaultHDR);
            RT.enableRandomWrite = true;
            RT.Create();
        }
        public RenderTexture OnRenderComputeShader(ComputeShader computeShader)
        {
            loadRenderTexture();

            #region Mesh Forwarding

            computeShader.SetInt("_pathTracingObjectCount", pathTracingObjects.Length);

            foreach (PathTracingObject pto in pathTracingObjects)
               pto.OnExecutePathTracing();

            buildObjectList();

            ComputeBuffer objectsBuffer = new ComputeBuffer(pathTracingObjects.Length, 88) { name = "Scenes Objects Buffer" };
            ComputeBuffer vertexBuffer = new ComputeBuffer(vertices.Count, 12) { name = "Vertices Buffer" };
            ComputeBuffer indexBuffer = new ComputeBuffer(indices.Count, 4) { name = "Indices Buffer" };

            PathTracingObject.pathTracingObject[] sceneObjects = new PathTracingObject.pathTracingObject[pathTracingObjects.Length];
            for (int i = 0; i < pathTracingObjects.Length; i++)
            {
                sceneObjects[i] = pathTracingObjects[i]._pathTracingObject;
            }

            objectsBuffer.SetData(sceneObjects);
            vertexBuffer.SetData(vertices);
            indexBuffer.SetData(indices);

            computeShader.SetBuffer(0, "_pathTracingObject", objectsBuffer);
            computeShader.SetBuffer(0, "_Vertices", vertexBuffer);
            computeShader.SetBuffer(0, "_Indices", indexBuffer);
            #endregion

            computeShader.SetMatrix("_CameraToWorld", Camera.main.cameraToWorldMatrix);
            computeShader.SetMatrix("_CameraInverseProjection", Camera.main.projectionMatrix.inverse);

            computeShader.SetTexture(0, "Result", RT);
            computeShader.Dispatch(0, RT.width, RT.height, 24);

            return RT;
        }
        public void buildObjectList()
        {
            int indicesCount = 0;
            int verticesCount = 0;

            foreach (PathTracingObject pto in pathTracingObjects)
            {
                int[] triangles;
                Vector3[] vertices;

                triangles = pto.objectMesh.triangles;//Take a sequence of vertices that form a triangle.
                vertices = pto.objectMesh.vertices;//Take vertex list

                pto._pathTracingObject.indicesOffset = indicesCount;//Offset: Where the list of indices belonging to the object starts. | indicesCount: How many indices were added before these.
                pto._pathTracingObject.indicesCount = triangles.Length;//How many indexes does this object have.

                foreach (Vector3 vertice in vertices)
                    this.vertices.Add(vertice);

                for (int i = 0; i < triangles.Length; i++)
                {
                    this.indices.Add(triangles[i] + verticesCount + 1);//Variable containing all indices of all objects in the scene. | triangles[i] (take an index) +verticesCount(Add to the amount of vetices already added) + 1

                    /*Example:
                    If the previous object has 270 vertices.
                    The first triangle of the next objects will be connected to the vertices(271, 272, 273) instead of(0,1,2).
                    +1 because vertex 270 belongs to a different object.*/
                }

                indicesCount += triangles.Length;//update index
                verticesCount += vertices.Length;//update index
            }
        }
        public void setPathTracingObjects(PathTracingObject[] pto) { pathTracingObjects = pto; }
    }
    public RenderTexture preProcessing()
    {
        PathTracingComputeShader pathTracingCompute = new PathTracingComputeShader();

        PathTracingObject[] objs = new PathTracingObject[pathTracingObjects.Length];
        for (int i = 0; i < pathTracingObjects.Length; i++)
            objs[i] = pathTracingObjects[i].GetComponent<PathTracingObject>();

        pathTracingCompute.setPathTracingObjects(objs);
        return pathTracingCompute.OnRenderComputeShader(computeShader);
    }
}

I believe it could be 2 things. Or my video card doesn’t count for work. Or there is a problem with the vertex array. (index out of range maybe?)

But I’m not sure, since it just crashes without an error message or something.

I know that the forum is not of unity, but if you can help me I really appreciate it.