3

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

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

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

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

由于实现了镶嵌着色器,文本着色器不再起作用。当我激活 DebugText(使用文本着色器渲染)时,我的屏幕会变黑一段时间,Windows 会显示以下消息:

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

显示驱动程序停止

这发生在用于渲染场景的两个着色器中的任何一个上。

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

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

我可以发布什么文件来帮助您帮助我?:) 谢谢

PS我已经检查过我的按键输入是否在错误的时间中断(在渲染期间左右..),但这似乎没问题

测试程序

  1. 没有文本着色器的常规着色器 常规着色器
  2. 通过 keyinput 将文本着色器添加到常规着色器(现在可以使用,我将文本着色器构建回仅顶点和像素着色器)(z 缓冲区的某些东西仍然是错误的......) 常规着色器和字体着色器
  3. 移除文本着色器,然后通过按键输入将着色器更改为镶嵌着色器 没有字体着色器的镶嵌着色器
  4. 然后如果我添加文本着色器或切换回常规着色器 显示驱动程序停止

切换/渲染着色器

这里是来自 Renderer.cpp 的代码片段,我根据布尔值“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);
}

这里是来自 Mesh.cpp 的代码片段,我根据布尔值“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;
}

渲染着色器

有时仅使用顶点和像素着色器并在使用顶点、外壳、域和像素着色器进行切换后会出现问题吗?这里是我的架构的一些概述:

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

清除状态

我想在 2 个着色器之间切换,它们似乎有不同的上下文参数,对吧?在clearstate 方法中,它说它将以下参数重置为 NULL:

我在我的 Direct3D 类中发现了以下内容:

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

我在每个着色器类中都发现了以下内容:

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

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

  • 谓词->?
  • 剪刀矩形->?

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

4

2 回答 2

1

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

如果这是问题所在,只需重新创建设备和上下文就可以了。

于 2013-04-12T18:19:59.310 回答
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);
}

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

于 2013-04-16T23:03:25.177 回答