public OptixIntersectionDevice(IRayEngineScene scene, bool lowLatency = false) : base(scene)
        {
            this.lowLatency = lowLatency;
            Context = new Context { CpuNumThreads = 4, RayTypeCount = 1, EntryPointCount = 1 };
            
            var rayBufferDesc = new BufferDesc()
            {
                Format = Format.User,
                Width = (uint)(lowLatency ? RayBuffer.RayBufferSize / 8 : RayBuffer.RayBufferSize),
                Type = BufferType.InputOutput,
                ElemSize = (uint)Marshal.SizeOf(typeof(RayData))
            };
            var rayHitBufferDesc = new BufferDesc()
            {
                Format = Format.User,
                Width =  (uint)(lowLatency ? RayBuffer.RayBufferSize / 8 : RayBuffer.RayBufferSize),
                Type = BufferType.InputOutput,
                ElemSize = (uint)Marshal.SizeOf(typeof(RayHit))
            };

            this.todoRayBuffers = new InputRayBufferCollection();
            this.doneRayBuffers = new OutputRayBufferCollection();
            this.started = false;

            Rays = new DeviceBuffer(Context, rayBufferDesc);
            RayHits = new DeviceBuffer(Context, rayHitBufferDesc);
            Context["rayHits"].Set(RayHits);
            Context["rays"].Set(Rays);
            Builder = AccelBuilder.TriangleKdTree;
            Traverser = AccelTraverser.KdTree;
            GeoGroup = new GeometryGroup(Context);
            this.SetScene(scene);
        }
        public OptixTraverseIntersectionDevice(IRayEngineScene scene, bool lowLatency = false)
            : base(scene)
        {
            this.lowLatency = lowLatency;
            Context = new Context { CpuNumThreads = 4, RayTypeCount = 1, EntryPointCount = 1 };


            this.todoRayBuffers = new InputRayBufferCollection();
            this.doneRayBuffers = new OutputRayBufferCollection();
            this.started = false;

            this.SetScene(scene);
        }
        public OptixPrimeIntersectionDevice(IRayEngineScene scene, bool lowLatency = false)
            : base(scene)
        {
            this.lowLatency = lowLatency;
            Context = new Context { CpuNumThreads = 4, RayTypeCount = 1, EntryPointCount = 1 };

            trav  = new OptixPrime(Context, QueryType.ClosestHit, RayFormat.OriginDirectionMinMaxInterleaved, TriFormat.Mesh, TraversalOutput.Normal, InitOptions.GpuOnly);

            this.todoRayBuffers = new InputRayBufferCollection();
            this.doneRayBuffers = new OutputRayBufferCollection();
            this.started = false;

            this.SetScene(scene);
        }
        public DadeCudaIntersectionDevice(RayEngineScene scene, NVContext ctx)
            : base(scene)
        {
            this.scene = scene;
            wallclock = new Stopwatch();
            this.todoRayBuffers = new InputRayBufferCollection();
            this.doneRayBuffers = new OutputRayBufferCollection();
            this.started = false;
            if (ctx != null)
            {
                this.cudaContext = ctx;
            }
            else
            {
                this.cudaContext = new NVContext() { Context = new CudaContext(CudaContext.GetMaxGflopsDeviceId()) };
            }
            using (var sr = new StreamReader(@"G:\Git\RayDen\CudaMegaRay\x64\Release\Intersection.cu.ptx"))
            {
                intersectKernel = cudaContext.Context.LoadKernelPTX(sr.BaseStream, "Intersect");
            }

            this.rays = new CudaDeviceVariable<RayData>(RayBuffer.RayBufferSize);
            this.hits = new CudaDeviceVariable<RayHit>(RayBuffer.RayBufferSize);
            verts = scene.Vertices.ToArray();
            tris=scene.Triangles.Select(i => i.GetInfo()).ToArray();

            if (GlobalConfiguration.Instance.UseSceneCaching && scene.Cache != null)
            {
                bvh = scene.Cache.BvhData;
                nodesCount = scene.Cache.BvhData.Length;
            }
            else
            {
                var da = new BvhDataAdapter(scene);
                var treeData = da.BuildData();
                bvh = treeData;
                nodesCount = treeData.Length;

            }

            Tracer.TraceLine("BVH Data Size {0:F3} MBytes", (nodesCount * 32f) / (1024f * 1024f));
        }
        public override void Stop()
        {
            wallclock.Stop();
            started = false;
            wallclock.Restart();
            if (intersectionTask.Status == TaskStatus.Running)
            {
                this.cancelToken.Cancel();
                Tracer.TraceLine("Attempting to stop Optix intersection device");
                while ((intersectionTask.Status == TaskStatus.Running))
                {
                    this.cancelToken.Cancel();
                    if (wallclock.Elapsed > new TimeSpan(0, 0, 30))
                    {
                        break;
                    }
                }
                intersectionTask.Dispose();
                intersectionTask = null;
            }

            this.todoRayBuffers = new InputRayBufferCollection();
            this.doneRayBuffers = new OutputRayBufferCollection();
        }
        public  void Stop()
        {
            wallclock.Stop();
            started = false;

            if (intersectionTask.Status == TaskStatus.Running)
            {
                cancelToken.Cancel();
                while ((intersectionTask.Status == TaskStatus.Running))
                {
                    
                }
                intersectionTask.Dispose();
                intersectionTask = null;
            }

            this.todoRayBuffers = new InputRayBufferCollection<RayBuffer>();
            this.doneRayBuffers = new OutputRayBufferCollection<RayBuffer>();
        }