C# 遮挡剔除期间OpenTK图形卡崩溃

C# 遮挡剔除期间OpenTK图形卡崩溃,c#,crash,opentk,C#,Crash,Opentk,我最近在我的游戏中实现了截头体剔除,为了压缩渲染周期中的每一个细节,我还决定实现遮挡剔除。它工作得非常出色,但是,我很沮丧地发现,如果我不看游戏中的任何东西(如果我看向虚空并远离游戏对象),我的图形卡实际上会崩溃。我正在运行一个体素类型的游戏,这意味着它是一个充满立方体的世界。如果在我的视线中没有立方体,就会发生崩溃 以下是我的渲染循环,其中包含遮挡代码: protected override void OnRenderFrame( FrameEventArgs e ) { base.O

我最近在我的游戏中实现了截头体剔除,为了压缩渲染周期中的每一个细节,我还决定实现遮挡剔除。它工作得非常出色,但是,我很沮丧地发现,如果我不看游戏中的任何东西(如果我看向虚空并远离游戏对象),我的图形卡实际上会崩溃。我正在运行一个体素类型的游戏,这意味着它是一个充满立方体的世界。如果在我的视线中没有立方体,就会发生崩溃

以下是我的渲染循环,其中包含遮挡代码:

protected override void OnRenderFrame( FrameEventArgs e ) {
    base.OnRenderFrame( e );

    GL.MatrixMode( MatrixMode.Modelview );
    GL.Clear( ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit );
    GL.EnableClientState( ArrayCap.VertexArray );
    GL.EnableClientState( ArrayCap.TextureCoordArray );
    GL.DisableClientState( ArrayCap.ColorArray );

    /**
     * Pass 1
     * Do Occlusion Testing
     */
    GameCamera.LookThrough( this , _mousePosition , e );
    foreach( Voxel voxel in World.VisibleVoxels ) {
        if( GameCamera.Frustum.SphereInFrustum( voxel.Location.X , voxel.Location.Y , voxel.Location.Z , 2.0f ) ) {
            try {
                GL.BeginQuery( QueryTarget.SamplesPassed , voxel.OcclusionID );
                voxel.Render( GameCamera );
                GL.EndQuery( QueryTarget.SamplesPassed );
            } catch( Exception ex ) {
                //
                Console.WriteLine( "Setting It" );
                Console.WriteLine( ex.StackTrace );
            }
        }
    }
    GL.Clear( ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit );
    /**
     * Pass 2
     * Normal Rendering
     */
    GameCamera.LookThrough( this , _mousePosition , e );
    foreach( Voxel voxel in World.VisibleVoxels ) {
        if( GameCamera.Frustum.SphereInFrustum( voxel.Location.X , voxel.Location.Y , voxel.Location.Z , 2.0f ) ) {
            try {
                GL.NV.BeginConditionalRender( voxel.OcclusionID , NvConditionalRender.QueryWaitNv );
                voxel.Render( GameCamera );
                GL.NV.EndConditionalRender();
            } catch( Exception ex ) {
                Console.WriteLine( "Testing It" );
                Console.WriteLine( ex.StackTrace );
            }

        }
    }
    GL.DisableClientState( ArrayCap.VertexArray );
    GL.DisableClientState( ArrayCap.TextureCoordArray );
    GL.DisableClientState( ArrayCap.ColorArray );
    RenderDeveloperHud();
    SwapBuffers();
    this.Title = GAME_NAME + " FPS: " + ( int )this.RenderFrequency;
}
我迫切需要找到解决这个问题的办法。在我看来,当我的视口中看不到任何东西时,OpenTK/OpenGL就会大惊小怪,但我不知道为什么。如果看不到任何东西,则循环本身应该通过。我是不是遗漏了什么


每次我开始游戏并从关卡上移开视线时,我都能真实地再现这次崩溃。崩溃是指我的整个显示器变黑,挂断,然后恢复,并显示一条消息,说明我的显示器驱动程序停止工作

应用程序可以通过传递无效状态或数据(有时甚至是有效状态或数据)使GPU崩溃

尝试使用跟踪发送给驱动程序的OpenGL命令,并捕获导致崩溃的命令


使用调试版本的
OpenTK.dll
运行应用程序也将帮助您捕获错误:OpenTK将在每个GL命令之后使用
GL.GetError()
,如果出现问题,将引发异常。为了构建OpenTK的调试版本,并构建
OpenTK.sln

,我必须再次回答我自己的问题。我想我指出了错误,虽然我不太理解它…它不再崩溃了。我将渲染周期压缩为一次迭代,而不是两次;这解决了图形卡崩溃问题。任何人都知道这是为什么:

protected override void OnRenderFrame( FrameEventArgs e ) {

    base.OnRenderFrame( e );

    GL.MatrixMode( MatrixMode.Modelview );
    GL.Clear( ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit );
    GL.EnableClientState( ArrayCap.VertexArray );
    GL.EnableClientState( ArrayCap.TextureCoordArray );
    GL.DisableClientState( ArrayCap.ColorArray );

    /**
     * Pass 1
     * Normal Rendering && Occlusion Test
     */
    GameCamera.LookThrough( this , _mousePosition , e );
    if(NeedsOcclusionPass) {
        foreach(Voxel voxel in World.VisibleVoxels) {
            if(GameCamera.Frustum.SphereInFrustum(voxel.Location.X, voxel.Location.Y, voxel.Location.Z, 2.0f)) {
                GL.BeginQuery(QueryTarget.SamplesPassed, voxel.OcclusionID);
                voxel.Render(GameCamera);
                GL.EndQuery(QueryTarget.SamplesPassed);
            }
        }
        NeedsOcclusionPass = false;
    } else {
        foreach( Voxel voxel in World.VisibleVoxels ) {
            if( GameCamera.Frustum.SphereInFrustum( voxel.Location.X , voxel.Location.Y , voxel.Location.Z , 2.0f ) ) {
                GL.NV.BeginConditionalRender( voxel.OcclusionID , NvConditionalRender.QueryNoWaitNv );
                voxel.Render( GameCamera );
                GL.NV.EndConditionalRender();
            }
        }
        NeedsOcclusionPass = true;
    }

    GL.DisableClientState( ArrayCap.VertexArray );
    GL.DisableClientState( ArrayCap.TextureCoordArray );
    GL.DisableClientState( ArrayCap.ColorArray );
    //RenderDeveloperHud();
    SwapBuffers();
    this.Title = GAME_NAME + " FPS: " + ( int )this.RenderFrequency;
}
但是我上面的原始代码导致了崩溃?现在我比什么都糊涂。(不,这个问题并不是由GameCamera.LookThrough()的双重调用引起的;似乎只有两次传递本身才是错误


编辑:经过进一步测试和各种形式的文献,我得出结论,我使用上述代码完全错误。根据其他来源,我应该在开始遮挡查询之前禁用几乎所有内容。这意味着:纹理、照明,甚至深度缓冲。我仍然不知道是什么导致了崩溃然而,我的图形卡被损坏,最明显的原因是我对该主题缺乏理解。

可能是因为您在两个过程之间添加了以下行:


GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

可以
\u鼠标位置
异步更改吗?您可以调用
GameCamera.LookThrough()
在两个循环之前。您可能需要对遮挡过程和渲染过程使用相同的视图转换。不确定为什么要设置两次视图。据我所知,我需要在每次循环之前查看摄影机,以正确设置视图平截头体。我当时也无法重新测试,因为我取消了视图转换编码并使用我自己的体素镶嵌排列。它现在让我保持稳定的60fps。然而,当我有时间时,我会尝试重新实现它;我只是不能因为可以用其他方式完成的事情而停止我的项目。尽管如此,我仍然期待着有人的回答。我认为视锥体不应该在这两者之间改变遮挡过程和相应的渲染过程。否则,如果平截头体确实发生了更改,则可以在不提交相应查询的情况下对体素进行条件渲染调用。如果删除第二个
LookThrough()
call。为了满足您的建议,我目前正在重新实现上面的代码。我将在大约30分钟后与您联系。我仍然认为我的思路是正确的。:)由于您在循环中调用了
GameCamera.Frustum.SphereInFrustum()
,如果在渲染执行时相机发生变化,您可能仍然会遇到问题。关键是要为遮挡和渲染过程处理完全相同的体素列表。如果
SphereInFrustum()
测试在两个过程中对所有体素产生的结果都不相同,那么您就有麻烦了。等等,小提琴手,就像编写OpenTK的人一样?伙计,我现在很荣幸。我会研究你关于Apitrace的建议,看看是否能找出错误;谢谢