Search Unity

Question Unity crashes when running effect

Discussion in 'General Graphics' started by MatheusMarkies, Jun 28, 2021.

  1. MatheusMarkies

    MatheusMarkies

    Joined:
    Apr 16, 2017
    Posts:
    67
    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.

    Code (CSharp):
    1.  
    2. public void buildObjectList()
    3.         {
    4.             int indicesCount = 0;
    5.             int verticesCount = 0;
    6.  
    7.             foreach (PathTracingObject pto in pathTracingObjects)
    8.             {
    9.                 int[] triangles;
    10.                 Vector3[] vertices;
    11.  
    12.                 triangles = pto.objectMesh.triangles;//Take a sequence of vertices that form a triangle.
    13.                 vertices = pto.objectMesh.vertices;//Take vertex list
    14.  
    15.                 pto._pathTracingObject.indicesOffset = indicesCount;//Offset: Where the list of indices belonging to the object starts. | indicesCount: How many indices were added before these.
    16.                 pto._pathTracingObject.indicesCount = triangles.Length;//How many indexes does this object have.
    17.  
    18.                 foreach (Vector3 vertice in vertices)
    19.                     this.vertices.Add(vertice);
    20.  
    21.                 for (int i = 0; i < triangles.Length; i++)
    22.                 {
    23.                     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
    24.  
    25.                     /*Example:
    26.                     If the previous object has 270 vertices.
    27.                     The first triangle of the next objects will be connected to the vertices(271, 272, 273) instead of(0,1,2).
    28.                     +1 because vertex 270 belongs to a different object.*/
    29.                 }
    30.  
    31.                 indicesCount += triangles.Length;//update index
    32.                 verticesCount += vertices.Length;//update index
    33.             }
    34.         }
    35.  
    In compute shader:

    Code (CSharp):
    1.  
    2. /*
    3. http://www.graphics.cornell.edu/pubs/1997/MT97.html
    4. https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates
    5. */
    6. bool IntersectTriangle(Ray ray, float3 vert0, float3 vert1, float3 vert2, inout float t, inout float u, inout float v)
    7. {
    8.     float3 edge1 = vert1 - vert0;
    9.     float3 edge2 = vert2 - vert0;
    10.     float3 pvec = cross(ray.rayDirection, edge2);
    11.     float det = dot(edge1, pvec);
    12.     if (det < EPSILON)
    13.         return false;
    14.     float inv_det = 1.0f / det;
    15.     float3 tvec = ray.raySource - vert0;
    16.     u = dot(tvec, pvec) * inv_det;
    17.     if (u < 0.0 || u > 1.0f)
    18.         return false;
    19.     float3 qvec = cross(tvec, edge1);
    20.     v = dot(ray.rayDirection, qvec) * inv_det;
    21.     if (v < 0.0 || u + v > 1.0f)
    22.         return false;
    23.     t = dot(edge2, qvec) * inv_det;
    24.     return true;
    25. }
    26.  
    Code (CSharp):
    1.  
    2. void IntersectMeshObject(pathTracingObject pto, Ray ray, inout RayHit bestHit)
    3. {
    4.     for (int i = 0; i < pto.indicesCount; i += 3) {
    5.         float3 v0 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i]], 1))).xyz;
    6.         float3 v1 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 1]], 1))).xyz;
    7.         float3 v2 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 2]], 1))).xyz;
    8.  
    9.         float t, u, v;
    10.         if (IntersectTriangle(ray, v0, v1, v2, t, u, v))
    11.         {
    12.             if (t > 0 && t < bestHit.hitDistance)
    13.             {
    14.                 /*            
    15.                 bestHit.hitDistance = t; // makes unity crash
    16.                 bestHit.hitPosition = ray.raySource + t * ray.rayDirection; // makes unity crash
    17.                 bestHit.hitNormal = normalize(bestHit.hitPosition); // makes unity crash
    18.  
    19.                 bestHit.hitAlbedo = float3(1,1,1); // makes unity crash
    20.                 */
    21.             }
    22.         }
    23.    
    Crash.PNG

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

    Full code:
    Code (CSharp):
    1.  
    2. // Each #kernel tells which function to compile; you can have many kernels
    3. #pragma kernel CSMain
    4.  
    5. #define PI 3.14159265359
    6. #define EPSILON 0.0000001
    7.  
    8. RWTexture2D<float4> Result;
    9.  
    10. struct pathTracingObject
    11. {
    12.     float4 Position;
    13.  
    14.     int indicesCount;
    15.     int indicesOffset;
    16.  
    17.     float4x4 localToWorldMatrix;
    18. };
    19.  
    20. StructuredBuffer<pathTracingObject> _pathTracingObject;
    21. StructuredBuffer<float3> _Vertices;
    22. StructuredBuffer<int> _Indices;
    23.  
    24. int _pathTracingObjectCount;
    25.  
    26. float4x4 _CameraToWorld;
    27. float4x4 _CameraInverseProjection;
    28.  
    29. struct Ray {
    30.     float3 raySource;
    31.     float3 rayDirection;
    32.     float3 rayColor;
    33. };
    34.  
    35. Ray CreateRay(float3 source, float3 direction)
    36. {
    37.     Ray ray;
    38.     ray.raySource = source;
    39.     ray.rayDirection = direction;
    40.  
    41.     return ray;
    42. }
    43.  
    44. Ray CreateCameraRay(float2 uv)
    45. {
    46.     float3 source = mul(_CameraToWorld, float4(0.0f, 0.0f, 0.0f, 1.0f)).xyz;
    47.  
    48.     float3 direction = mul(_CameraInverseProjection, float4(uv, 0.0f, 1.0f)).xyz;
    49.     direction = mul(_CameraToWorld, float4(direction, 0.0f)).xyz;
    50.     direction = normalize(direction);
    51.     return CreateRay(source, direction);
    52. }
    53.  
    54. struct RayHit
    55. {
    56.     float3 hitPosition;
    57.     float hitDistance;
    58.     float3 hitNormal;
    59.  
    60.     float3 hitAlbedo;
    61. };
    62.  
    63. RayHit CreateRayHit()
    64. {
    65.     RayHit hit;
    66.  
    67.     hit.hitPosition = float3(0.0f, 0.0f, 0.0f);
    68.     hit.hitDistance = 1.#INF;
    69.     hit.hitNormal = float3(0.0f, 0.0f, 0.0f);
    70.  
    71.     hit.hitAlbedo = float3(0.0f, 0.0f, 0.0f);
    72.  
    73.     return hit;
    74. }
    75.  
    76. /*
    77. http://www.graphics.cornell.edu/pubs/1997/MT97.html
    78. https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates
    79. */
    80. bool IntersectTriangle(Ray ray, float3 vert0, float3 vert1, float3 vert2, inout float t, inout float u, inout float v)
    81. {
    82.     float3 edge1 = vert1 - vert0;
    83.     float3 edge2 = vert2 - vert0;
    84.     float3 pvec = cross(ray.rayDirection, edge2);
    85.     float det = dot(edge1, pvec);
    86.     if (det < EPSILON)
    87.         return false;
    88.     float inv_det = 1.0f / det;
    89.     float3 tvec = ray.raySource - vert0;
    90.     u = dot(tvec, pvec) * inv_det;
    91.     if (u < 0.0 || u > 1.0f)
    92.         return false;
    93.     float3 qvec = cross(tvec, edge1);
    94.     v = dot(ray.rayDirection, qvec) * inv_det;
    95.     if (v < 0.0 || u + v > 1.0f)
    96.         return false;
    97.     t = dot(edge2, qvec) * inv_det;
    98.     return true;
    99. }
    100.  
    101.  
    102. void IntersectMeshObject(pathTracingObject pto, Ray ray, inout RayHit bestHit)
    103. {
    104.     for (int i = 0; i < pto.indicesCount; i += 3) {
    105.         float3 v0 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i]], 1))).xyz;
    106.         float3 v1 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 1]], 1))).xyz;
    107.         float3 v2 = (mul(pto.localToWorldMatrix, float4(_Vertices[_Indices[pto.indicesOffset + i + 2]], 1))).xyz;
    108.  
    109.         float t, u, v;
    110.         if (IntersectTriangle(ray, v0, v1, v2, t, u, v))
    111.         {
    112.             if (t > 0 && t < bestHit.hitDistance)
    113.             {
    114.                            
    115.                 bestHit.hitDistance = t; // makes unity crash
    116.                 bestHit.hitPosition = ray.raySource + t * ray.rayDirection; // makes unity crash
    117.                 bestHit.hitNormal = normalize(bestHit.hitPosition); // makes unity crash
    118.  
    119.                 bestHit.hitAlbedo = float3(1,1,1); // makes unity crash
    120.              
    121.             }
    122.         }
    123.  
    124.     }
    125. }
    126.  
    127. RayHit Trace(Ray ray)
    128. {
    129.     RayHit bestHit = CreateRayHit();
    130.  
    131.     for (int i = 0; i < _pathTracingObjectCount; i++) {
    132.         pathTracingObject pto = _pathTracingObject[i];
    133.         IntersectMeshObject(pto, ray, bestHit);
    134.     }
    135.  
    136.     return bestHit;
    137. }
    138.  
    139. [numthreads(8,8,1)]
    140. void CSMain (uint3 id : SV_DispatchThreadID)
    141. {
    142.     // TODO: insert actual code here!
    143.     float3 result = float3(0, 0, 0);
    144.  
    145.     int width, height;
    146.     Result.GetDimensions(width, height);
    147.     float2 uv = float2((id.xy + float2(0.5f, 0.5f)) / float2(width, height) * 2.0f - 1.0f);
    148.  
    149.     for(int i = 0; i < 1;i++) {
    150.         Ray ray = CreateCameraRay(id.xy);
    151.         RayHit hit = Trace(ray);
    152.         result += hit.hitAlbedo;
    153.     }
    154.     result /= float3(5,5,5);
    155.  
    156.     Result[id.xy] = float4(result, 1);
    157. }
    158.  
    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.Rendering;
    6.  
    7. [System.Serializable]
    8. class PathTracing
    9. {
    10.  
    11.     [SerializeField]
    12.     ComputeShader computeShader;
    13.     [SerializeField]
    14.     GameObject[] pathTracingObjects;
    15.    
    16.     class PathTracingComputeShader
    17.     {
    18.         PathTracingObject[] pathTracingObjects;
    19.  
    20.         public List<Vector3> vertices = new List<Vector3>();
    21.         public List<int> indices = new List<int>();
    22.  
    23.         RenderTexture RT;
    24.         public void loadRenderTexture()
    25.         {
    26.             RT = new RenderTexture(Mathf.CeilToInt(Screen.width / 4), Mathf.CeilToInt(Screen.height / 4), 0, RenderTextureFormat.DefaultHDR);
    27.             RT.enableRandomWrite = true;
    28.             RT.Create();
    29.         }
    30.         public RenderTexture OnRenderComputeShader(ComputeShader computeShader)
    31.         {
    32.             loadRenderTexture();
    33.  
    34.             #region Mesh Forwarding
    35.  
    36.             computeShader.SetInt("_pathTracingObjectCount", pathTracingObjects.Length);
    37.  
    38.             foreach (PathTracingObject pto in pathTracingObjects)
    39.                pto.OnExecutePathTracing();
    40.  
    41.             buildObjectList();
    42.  
    43.             ComputeBuffer objectsBuffer = new ComputeBuffer(pathTracingObjects.Length, 88) { name = "Scenes Objects Buffer" };
    44.             ComputeBuffer vertexBuffer = new ComputeBuffer(vertices.Count, 12) { name = "Vertices Buffer" };
    45.             ComputeBuffer indexBuffer = new ComputeBuffer(indices.Count, 4) { name = "Indices Buffer" };
    46.  
    47.             PathTracingObject.pathTracingObject[] sceneObjects = new PathTracingObject.pathTracingObject[pathTracingObjects.Length];
    48.             for (int i = 0; i < pathTracingObjects.Length; i++)
    49.             {
    50.                 sceneObjects[i] = pathTracingObjects[i]._pathTracingObject;
    51.             }
    52.  
    53.             objectsBuffer.SetData(sceneObjects);
    54.             vertexBuffer.SetData(vertices);
    55.             indexBuffer.SetData(indices);
    56.  
    57.             computeShader.SetBuffer(0, "_pathTracingObject", objectsBuffer);
    58.             computeShader.SetBuffer(0, "_Vertices", vertexBuffer);
    59.             computeShader.SetBuffer(0, "_Indices", indexBuffer);
    60.             #endregion
    61.  
    62.             computeShader.SetMatrix("_CameraToWorld", Camera.main.cameraToWorldMatrix);
    63.             computeShader.SetMatrix("_CameraInverseProjection", Camera.main.projectionMatrix.inverse);
    64.  
    65.             computeShader.SetTexture(0, "Result", RT);
    66.             computeShader.Dispatch(0, RT.width, RT.height, 24);
    67.  
    68.             return RT;
    69.         }
    70.         public void buildObjectList()
    71.         {
    72.             int indicesCount = 0;
    73.             int verticesCount = 0;
    74.  
    75.             foreach (PathTracingObject pto in pathTracingObjects)
    76.             {
    77.                 int[] triangles;
    78.                 Vector3[] vertices;
    79.  
    80.                 triangles = pto.objectMesh.triangles;//Take a sequence of vertices that form a triangle.
    81.                 vertices = pto.objectMesh.vertices;//Take vertex list
    82.  
    83.                 pto._pathTracingObject.indicesOffset = indicesCount;//Offset: Where the list of indices belonging to the object starts. | indicesCount: How many indices were added before these.
    84.                 pto._pathTracingObject.indicesCount = triangles.Length;//How many indexes does this object have.
    85.  
    86.                 foreach (Vector3 vertice in vertices)
    87.                     this.vertices.Add(vertice);
    88.  
    89.                 for (int i = 0; i < triangles.Length; i++)
    90.                 {
    91.                     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
    92.  
    93.                     /*Example:
    94.                     If the previous object has 270 vertices.
    95.                     The first triangle of the next objects will be connected to the vertices(271, 272, 273) instead of(0,1,2).
    96.                     +1 because vertex 270 belongs to a different object.*/
    97.                 }
    98.  
    99.                 indicesCount += triangles.Length;//update index
    100.                 verticesCount += vertices.Length;//update index
    101.             }
    102.         }
    103.         public void setPathTracingObjects(PathTracingObject[] pto) { pathTracingObjects = pto; }
    104.     }
    105.     public RenderTexture preProcessing()
    106.     {
    107.         PathTracingComputeShader pathTracingCompute = new PathTracingComputeShader();
    108.  
    109.         PathTracingObject[] objs = new PathTracingObject[pathTracingObjects.Length];
    110.         for (int i = 0; i < pathTracingObjects.Length; i++)
    111.             objs[i] = pathTracingObjects[i].GetComponent<PathTracingObject>();
    112.  
    113.         pathTracingCompute.setPathTracingObjects(objs);
    114.         return pathTracingCompute.OnRenderComputeShader(computeShader);
    115.     }
    116. }
    117.  
    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.