使用多个着色器时出现驱动程序错误

时间:2013-03-26 18:54:08

标签: c++ shader directx-11

我正在使用3种不同的着色器:

  • 使用DirectX11曲面细分功能的曲面细分着色器:)
  • 一个常规着色器,用于显示没有镶嵌细分的外观
  • 和一个文本着色器,用于显示调试信息,如FPS,型号等。

所有这些着色器都在开头初始化。

使用键盘,我可以在曲面细分着色器和常规着色器之间切换以渲染场景。此外,我还希望能够使用文本着色器切换debug-info的显示。

自实施曲面细分着色器后,文本着色器不再起作用。当我激活DebugText(使用文本着色器渲染)时,我的屏幕会变黑一段时间,Windows会显示以下消息:

  

显示驱动程序停止响应并已恢复

Display driver stopped

用于渲染场景的两个着色器中的任何一个都会发生这种情况。

此外: 我可以使用常规着色器启动应用程序来渲染场景,然后切换到曲面细分着色器。如果我尝试切换回常规着色器,我会得到与文本着色器相同的错误。

在着色器之间切换时我做错了什么? 在同时显示文字时我做错了什么?

我可以发布哪些文件来帮助您? :) thx

P.S。我已经检查过我的keyinputs是否在错误的时间中断(渲染期间等等),但这似乎没问题

测试程序

  1. 不带文字着色器的常规着色器 Regular Shader
  2. 通过keyinput将文本着色器添加到Regular Shader(现在工作,我将文本着色器重新构建回顶点和像素着色器)(使用z缓冲区的东西是stil错误...) Regular Shader and Font Shader
  3. 删除文本着色器,然后通过键输入将着色器更改为Tessellation Shader Tessellation Shader without Font Shader
  4. 然后,如果我添加文本着色器或切换回常规着色器 Display driver stopped
  5. 切换/渲染着色器

    这里是来自Renderer.cpp的代码snipet,我根据布尔值“m_useTessellationShader”选择了Shader:

    if(m_useTessellationShader) 
    {
        // Render the model using the tesselation shader
        ecResult = m_ShaderManager->renderTessellationShader(m_D3D->getDeviceContext(), meshes[lod_level]->getIndexCount(), 
            worldMatrix, viewMatrix, projectionMatrix, textures, texturecount, 
            m_Light->getDirection(), m_Light->getAmbientColor(), m_Light->getDiffuseColor(), 
            (D3DXVECTOR3)m_Camera->getPosition(), TESSELLATION_AMOUNT);
    } else { 
        // todo: loaded model depends on distance to camera
        // Render the model using the light shader.
        ecResult = m_ShaderManager->renderShader(m_D3D->getDeviceContext(), 
            meshes[lod_level]->getIndexCount(), lod_level, textures, texturecount,
            m_Light->getDirection(), m_Light->getAmbientColor(), m_Light->getDiffuseColor(),
            worldMatrix, viewMatrix, projectionMatrix);
    }
    

    这里是来自Mesh.cpp的代码snipet,我根据布尔“useTessellationShader”选择了类型:

    // RenderBuffers is called from the Render function. The purpose of this function is to set the vertex buffer and index buffer as active on the input assembler in the GPU. Once the GPU has an active vertex buffer it can then use the shader to render that buffer.
    void Mesh::renderBuffers(ID3D11DeviceContext* deviceContext, bool useTessellationShader)
    {
        unsigned int stride;
        unsigned int offset;
    
        // Set vertex buffer stride and offset.
        stride = sizeof(VertexType); 
        offset = 0;
    
        // Set the vertex buffer to active in the input assembler so it can be rendered.
        deviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);
    
        // Set the index buffer to active in the input assembler so it can be rendered.
        deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
    
        // Check which Shader is used to set the appropriate Topology
        // Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
        if(useTessellationShader)
        {       
            deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST);
        }else{
            deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
        }
    
        return;
    }
    

    RenderShader

    有时候只使用顶点和像素着色器以及使用顶点,外壳,域和像素着色器切换后会出现问题吗? 这里有一点关于我的架构的概述:

    • TextClass:使用font.vs和font.ps

      deviceContext-> VSSetShader(m_vertexShader,NULL,0); deviceContext-> PSSetShader(m_pixelShader,NULL,0); deviceContext-> PSSetSamplers(0,1,& m_sampleState);

    • RegularShader:使用vertex.vs和pixel.ps

      deviceContext-> VSSetShader(m_vertexShader,NULL,0); deviceContext-> PSSetShader(m_pixelShader,NULL,0); deviceContext-> PSSetSamplers(0,1,& m_sampleState);

    • TessellationShader:使用tessellation.vs,tessellation.hs,tessellation.ds,tessellation.ps

      deviceContext-> VSSetShader(m_vertexShader,NULL,0); deviceContext-> HSSetShader(m_hullShader,NULL,0); deviceContext-> DSSetShader(m_domainShader,NULL,0); deviceContext-> PSSetShader(m_pixelShader,NULL,0); deviceContext-> PSSetSamplers(0,1,& m_sampleState);

    ClearState

    我想在两个着色器之间切换,看起来它们有不同的上下文参数,对吧?在clearstate methode中它表示它会将params重置为NULL:

    我在Direct3D课程中找到了以下内容:

    • 深度模板状态 - > m_deviceContext-> OMSetDepthStencilState
    • 光栅化器状态 - > m_deviceContext-> RSSetState(m_rasterState);
    • 混合状态 - > m_device-> CreateBlendState
    • viewports - > m_deviceContext-> RSSetViewports(1,& viewport);

    我在每个着色器类中找到了以下内容:

    • 输入/输出资源槽 - > deviceContext-> PSSetShaderResources
    • 着色器 - > deviceContext-> VSSetShader to - deviceContext-> PSSetShader
    • 输入布局 - >装置 - > CreateInputLayout
    • 采样器状态 - >装置 - > CreateSamplerState

    这两个我不明白,我在哪里可以找到它们?

    • 预测 - > ?
    • 剪刀矩形 - > ?

    我是否需要将它们全部存储在本地,以便我可以在它们之间切换,因为每个开关(键输入)重新初始化Direct3d和着色器感觉不正确?!

2 个答案:

答案 0 :(得分:1)

您是否检查过系统是否正在重置设备。检查Present()方法的返回变量。当突然切换着色器时,DX会因某些奇怪的原因而重置设备。

如果这是问题,只需重新创建设备和上下文,你应该做得很好。

答案 1 :(得分:1)

现在你有

void Direct3D::endScene()
{
    // Present the back buffer to the screen since rendering is complete.
    if(m_vsync_enabled)
    {
        // Lock to screen refresh rate.
        m_swapChain->Present(1, 0);
    }
    else
    {
        // Present as fast as possible.
        m_swapChain->Present(0, 0);
    }

    return;
}

我建议做类似的事情来捕捉Present()

的返回值
ULONG Direct3D::endScene()
{
  int synch = 0;

  if(m_vsync_enabled)
    synch = 1;

  // Present as fast as possible or synch it to 1 vertical blank
  return m_swapChain->Present(synch, 0);
}

当然这只是我做这件事的方式,而且还有很多。另外,我忘了告诉你,我过去遇到的问题也是使用效果库。你有没有在你的系统中重新编译它?如果没有,那就这样做。或者甚至更好地摆脱它,这就是我解决问题时的所作所为。