简体   繁体   English

咬合剔除期间OpenTK图形卡崩溃

[英]OpenTK Graphics Card Crashing During Occlusion Culling

I recently implemented Frustum culling in my game, and in an attempt to squeeze every last drop out of my render cycle I also decided to implement Occlusion Culling. 我最近在我的游戏中实现了视锥剔除,并且为了挤压渲染周期中的最后每一个下降,我还决定实施遮挡剔除。 It works brilliantly, however, I was distressed to discover that if I dont look at anything in my game( If I look out into the void and away from my game objects) my graphics card literally crashes . 它的运行非常出色,但是,我很沮丧地发现,如果我不看游戏中的任何东西( 如果我望着空白,远离游戏对象),我的显卡就会崩溃 I am running a voxel-type game, which means it is a world filled with cubes. 我正在运行体素型游戏,这意味着它是一个充满立方体的世界。 If there is no cubes present in my line of sight the crash occurs. 如果我的视线中没有立方体,则会发生崩溃。

Here is my render loop which contains the Occlusion code: 这是我的渲染循环,其中包含遮挡代码:

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;
}

I desperatly need to find a solution for this. 我迫切需要为此找到解决方案。 It seems to me that OpenTK/OpenGL flips its shit when there is nothing visible in my viewport, but I dont know why. 在我看来,当我的视口中看不到任何东西时,OpenTK / OpenGL会翻转它的内容,但我不知道为什么。 The loop itself should pass through if nothing is visible. 如果看不到任何内容,则循环本身应该通过。 Am I missing something here? 我在这里想念什么吗?

I can literally reproduce this crash every time I start the game and look away from the level. 每当我开始游戏并移离关卡时,我都可以从字面上重现此崩溃。 And by crash I mean my entire monitor goes black, hangs up, and then resumes with a message saying my display driver stopped working 通过崩溃,我的意思是我的整个显示器变黑了,挂断了,然后继续显示一条消息,说我的显示驱动程序停止工作

Applications can crash GPUs by passing invalid state or data - or sometimes even with valid ones. 应用程序可能会通过传递无效的状态或数据(有时甚至传递有效的状态或数据)而使GPU崩溃。

Try using apitrace to trace the OpenGL commands issued to the driver and catch the command that is causing the crash. 尝试使用apitrace跟踪发布给驱动程序的OpenGL命令,并捕获导致崩溃的命令。

Running your application with a debug version of OpenTK.dll will also help you catch errors: OpenTK will use GL.GetError() after every GL command and raise an exception if something is amiss. 使用OpenTK.dll的调试版本运行应用程序还可以帮助您捕获错误:OpenTK将在每个GL命令之后使用GL.GetError() ,如果出现问题则引发异常。 To build a debug version of OpenTK, download the source code and build OpenTK.sln . 要构建OpenTK的调试版本,请下载源代码并构建OpenTK.sln

As much as it infuriates me, I have to answer my own question again. 令我非常恼火的是,我不得不再次回答自己的问题。 I think I pinpointed the error, although I dont particularly understand it...it doesnt crash anymore. 我想我已经指出了错误,尽管我不是特别了解它……它不再崩溃了。 Instead of having two passes, i compressed my render cycle down to a single iteration; 我没有两次通过,而是将渲染周期压缩为一个迭代。 this solved the graphics card crash. 这样就解决了显卡崩溃的问题。 Anyone know why this works: 任何人都知道为什么这样做:

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;
}

But my original code above causes a crash? 但是我上面的原始代码会导致崩溃吗? Now I am just more confused than anything. 现在我比什么都更困惑。 (And no the issue was not caused by the double call of GameCamera.LookThrough(); It just seems that having two passes itself was the error. (而且问题并非不是由GameCamera.LookThrough()的两次调用引起的;似乎只有两次通过本身才是错误。

Edit: After further testing and various forms of literature I have come to the conclusion that I was using the above code completely wrong. 编辑:经过进一步测试和各种形式的文献后,我得出的结论是我使用上述代码完全错误。 According to other sources, I should be disabling almost EVERYTHING before beginning the occlusion queries. 根据其他消息来源,在开始遮挡查询之前,我应该禁用几乎所有功能。 This means: textures, lighting,and even the depth buffer. 这意味着:纹理,光照,甚至深度缓冲。 I still don't know what caused the crashing of my graphics card, however, it most certainly stems from my lack of understanding on the topic. 我仍然不知道是什么原因导致了显卡崩溃,但是,这肯定是由于我对该主题缺乏了解而引起的。

perhaps it is because you add the following line between two passes: 可能是因为您在两遍之间添加了以下行:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM