Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Driver error when using multiple shaders

I'm using 3 different shaders:

  • a tessellation shader to use the tessellation feature of DirectX11 :)
  • a regular shader to show how it would look without tessellation
  • and a text shader to display debug-info such as FPS, model count etc.

All of these shaders are initialized at the beginning.

Using the keyboard, I can switch between the tessellation shader and regular shader to render the scene. Additionally, I also want to be able toggle the display of debug-info using the text shader.

Since implementing the tessellation shader the text shader doesn't work anymore. When I activate the DebugText (rendered using the text-shader) my screens go black for a while, and Windows displays the following message:

Display Driver stopped responding and has recovered

Display driver stopped

This happens with either of the two shaders used to render the scene.

Additionally: I can start the application using the regular shader to render the scene and then switch to the tessellation shader. If I try to switch back to the regular shader I get the same error as with the text shader.

What am I doing wrong when switching between shaders? What am I doing wrong when displaying text at the same time?

What file can I post to help you help me? :) thx

P.S. I already checked if my keyinputs interrupt at the wrong time (during render or so..), but that seems to be ok

Testing Procedure

  1. Regular Shader without text shader Regular Shader
  2. Add text shader to Regular Shader by keyinput (works now, I built the text shader back to only vertex and pixel shader) (somthing with the z buffer is stil wrong...) Regular Shader and Font Shader
  3. Remove text shader, then change shader to Tessellation Shader by key input Tessellation Shader without Font Shader
  4. Then if I add the Text Shader or switch back to the Regular Shader Display driver stopped

Switching/Render Shader

Here the code snipet from the Renderer.cpp where I choose the Shader according to the boolean "m_useTessellationShader":

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

And here the code snipet from the Mesh.cpp where I choose the Typology according to the boolean "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

Could there be a problem using sometimes only vertex and pixel shader and after switching using vertex, hull, domain and pixel shader? Here a little overview of my architecture:

  • TextClass: uses font.vs and font.ps

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

  • RegularShader: uses vertex.vs and pixel.ps

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

  • TessellationShader: uses 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

I'd like to switch between 2 shaders and it seems they have different context parameters, right? In clearstate methode it says it resets following params to NULL:

I found following in my Direct3D Class:

  • depth-stencil state -> m_deviceContext->OMSetDepthStencilState
  • rasterizer state -> m_deviceContext->RSSetState(m_rasterState);
  • blend state -> m_device->CreateBlendState
  • viewports -> m_deviceContext->RSSetViewports(1, &viewport);

I found following in every Shader Class:

  • input/output resource slots -> deviceContext->PSSetShaderResources
  • shaders -> deviceContext->VSSetShader to - deviceContext->PSSetShader
  • input layouts -> device->CreateInputLayout
  • sampler state -> device->CreateSamplerState

These two I didn't understand, where can I find them?

  • predications -> ?
  • scissor rectangles -> ?

Do I need to store them all localy so I can switch between them, because it doesn't feel right to reinitialize the Direct3d and the Shaders by every switch (key input)?!

like image 429
Jinxi Avatar asked May 15 '26 06:05

Jinxi


1 Answers

Right now you have

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

I would suggest doing something like so to catch the return value of 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);
}

Of course this is only MY way of doing it, and there are many. Also, I forgot to tell you that the issue I had in the past was also using the Effects library. Have you recompiled it in your system? If not, then do so. Or even better get rid of it, that's what I did when I solved my problem.

like image 127
Miguel Avatar answered May 17 '26 19:05

Miguel