private void ParseGeometry(
            GameObject[] roots,
            ref SceneParseResult sceneParseResult)
        {
            var renderers = GetAllRenderers(roots);

            if (!IsAllGeometriesDirty(renderers) && sceneParseResult.Primitives.Count != 0)
            {
                // All the geometries are unchange, no need to rebuild
                return;
            }

            // TODO: Optimize dynamic array generation
            sceneParseResult.ClearAllPrimitives();
            sceneParseResult.ClearAllGeometries();
            sceneParseResult.ClearAllMaterials();
            sceneParseResult.ClearTopLevelBVH();

            foreach (var renderer in renderers)
            {
                if (renderer.gameObject.activeInHierarchy)
                {
                    RTMaterial material = renderer.material;
                    if (renderer.geometry == null || !renderer.geometry.IsGeometryValid() || material == null)
                    {
                        continue;
                    }

                    var closestShaderGUID    = renderer.material.GetClosestHitGUID();
                    int closestShaderIndex   = CustomShaderDatabase.Instance.GUIDToShaderIndex(closestShaderGUID, EShaderType.ClosestHit);
                    var intersectShaderGUID  = renderer.geometry.GetIntersectShaderGUID();
                    int intersectShaderIndex = CustomShaderDatabase.Instance.GUIDToShaderIndex(intersectShaderGUID, EShaderType.Intersect);

                    if (!sceneParseResult.GeometryStride.ContainsKey(intersectShaderIndex))
                    {
                        sceneParseResult.GeometryStride.Add(intersectShaderIndex, renderer.geometry.IsAccelerationStructure() ? 0 : renderer.geometry.GetStride());
                    }

                    if (renderer.geometry.IsAccelerationStructure())
                    {
                        // Such as Low-Level BVH (RTMeshBVH)
                        int mapOffset = sceneParseResult.ObjectLevelAccGeoMapCursor(intersectShaderIndex);
                        int geoOffset = sceneParseResult.ObjectLevelAccGeoCursor(intersectShaderIndex);
                        ((IRTMeshBVH)(renderer.geometry)).BuildBVHAndTriangleList(geoLocalToGlobalIndexOffset: geoOffset,
                                                                                  mappingLocalToGlobalIndexOffset: mapOffset);

                        List <float> geoInsData = renderer.geometry.GetGeometryInstanceData(geoLocalToGlobalIndexOffset: geoOffset,
                                                                                            mappingLocalToGlobalIndexOffset: mapOffset);
                        sceneParseResult.AddAccelerationStructureGeometry(
                            accelerationStructureData: geoInsData,
                            accelGeometryMapping: renderer.geometry.GetAccelerationStructureGeometryMapping(geoLocalToGlobalIndexOffset: geoOffset,
                                                                                                            mappingLocalToGlobalIndexOffset: mapOffset),
                            accelGeometryData: renderer.geometry.GetAccelerationStructureGeometryData(geoLocalToGlobalIndexOffset: geoOffset,
                                                                                                      mappingLocalToGlobalIndexOffset: mapOffset),
                            intersectIndex: intersectShaderIndex
                            );
                    }
                    else
                    {
                        // Standardized Geometry (Sphere, Triangle)
                        List <float> geoInsData = renderer.geometry.GetGeometryInstanceData(geoLocalToGlobalIndexOffset: 0, mappingLocalToGlobalIndexOffset: 0);  // No offset
                        sceneParseResult.AddGeometryData(
                            geometryData: geoInsData,
                            intersectIndex: intersectShaderIndex
                            );
                    }

                    int startIndex = sceneParseResult.AddGeometryCount(
                        count: renderer.geometry.GetCount(),
                        intersectIndex: intersectShaderIndex
                        );

                    int materialInstanceIndex = sceneParseResult.AddMaterial(material);

                    sceneParseResult.AddWorldToPrimitive(renderer.gameObject.transform.worldToLocalMatrix);

                    sceneParseResult.AddPrimitive(new Primitive(
                                                      geometryIndex: intersectShaderIndex,
                                                      geometryInstanceBegin: startIndex,
                                                      geometryInstanceCount: renderer.geometry.GetCount(),
                                                      materialIndex: closestShaderIndex,
                                                      materialInstanceIndex: materialInstanceIndex,
                                                      transformIndex: sceneParseResult.WorldToPrimitive.Count - 1
                                                      ));

                    var boxOfThisObject = renderer.geometry.GetTopLevelBoundingBox(assginedPrimitiveId: sceneParseResult.Primitives.Count - 1);
                    sceneParseResult.AddBoundingBox(boxOfThisObject);
                }
            }
        }