繁体   English   中英

输入汇编器-顶点着色器链接错误

[英]Input Assembler - Vertex Shader Linkage error

我正在尝试使用SpriteFontSpriteBatch在DX11项目中渲染文本。

在添加代码之前,一切正常,但是在未注释代码的情况下,出现以下错误,并且没有任何显示。

D3D11 ERROR: ID3D11DeviceContext::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. Semantic 'TEXCOORD' is defined for mismatched hardware registers between the output stage and input stage. [ EXECUTION ERROR #343: DEVICE_SHADER_LINKAGE_REGISTERINDEX]
D3D11 ERROR: ID3D11DeviceContext::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. The input stage requires Semantic/Index (POSITION,0) as input, but it is not provided by the output stage. [ EXECUTION ERROR #342: DEVICE_SHADER_LINKAGE_SEMANTICNAME_NOT_FOUND]
D3D11 ERROR: ID3D11DeviceContext::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. The input stage requires Semantic/Index (NORMAL,0) as input, but it is not provided by the output stage. [ EXECUTION ERROR #342: DEVICE_SHADER_LINKAGE_SEMANTICNAME_NOT_FOUND]

我试图更改DeviceContext和设备,但仍然是相同的错误。

    //Draw Text
    g_spriteBatch = std::make_unique<SpriteBatch>(g_pImmediateContext);
    g_spriteFont = std::make_unique<SpriteFont>(g_pd3dDevice1, L"Data\\game_font.spritefont");

    //Render Text
    g_spriteBatch->Begin();
    //g_spriteFont->DrawString(g_spriteBatch.get(), L"Score: 0", XMFLOAT2(0,0), DirectX::Colors::White);
    g_spriteBatch->End();

我尝试使用不同的Devices和DeviceContext,但仍然是相同的错误。


我一直在尝试许多不同的方法来使其工作。 这就是我目前的渲染功能

更新日期:18/02/2019

void Render() {

    float backgroundColour[] = { 0.0f, 0.1f, 0.5f, 0.0f };
    g_pImmediateContext->ClearRenderTargetView(g_pRenderTargetView, backgroundColour);
    g_pImmediateContext->ClearDepthStencilView(g_depthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

    g_pImmediateContext->IASetInputLayout(g_pVertexLayout);
    g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY::D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    g_pImmediateContext->RSSetState(g_rasterState);
    g_pImmediateContext->OMSetDepthStencilState(g_depthStencilState, 0);
    g_pImmediateContext->VSSetShader(g_pVertexShader, NULL, 0);
    g_pImmediateContext->PSSetShader(g_pPixelShader, NULL, 0);

    UINT stride = sizeof(SimpleVertex);
    UINT offset = 0;

    g_pImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);
    g_pImmediateContext->Draw(3, 0);
    //g_pImmediateContext->DrawIndexed(36, 0, 0);

    //Draw Text
    spriteBatch->Begin();
    spriteFont->DrawString(spriteBatch.get(), L"Test", DirectX::XMFLOAT2(0, 0), DirectX::Colors::White);
    spriteBatch->End();

    //Present our back buffer to the front buffer
    g_pSwapChain->Present(0, NULL);

}

运行项目时,出现以下错误D3D11 ERROR: ID3D11DeviceContext::IASetVertexBuffers: A Buffer trying to be bound to slot 0 did not have the appropriate bind flag set at creation time to allow the Buffer to be bound as a VertexBuffer. [ STATE_SETTING ERROR #238: IASETVERTEXBUFFERS_INVALIDBUFFER] D3D11 ERROR: ID3D11DeviceContext::IASetVertexBuffers: A Buffer trying to be bound to slot 0 did not have the appropriate bind flag set at creation time to allow the Buffer to be bound as a VertexBuffer. [ STATE_SETTING ERROR #238: IASETVERTEXBUFFERS_INVALIDBUFFER]

这是用于存储tri数据并​​设置索引/顶点缓冲区的代码

    SimpleVertex vertices[] =
    {           
        SimpleVertex(-0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f),
        SimpleVertex( 0.0f,  0.5f, 1.0f, 1.0f, 0.0f, 0.0f),
        SimpleVertex( 0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 0.0f),
    };

    D3D11_BUFFER_DESC bd = {};
    ZeroMemory(&bd, sizeof(bd));
    bd.Usage = D3D11_USAGE_DEFAULT;
    bd.ByteWidth = sizeof( SimpleVertex ) * ARRAYSIZE(vertices);
    bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
    bd.CPUAccessFlags = 0;
    bd.MiscFlags = 0;

    D3D11_SUBRESOURCE_DATA InitData;
    InitData.pSysMem = vertices;
    hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
    if (FAILED(hr))
    {
        printf("Failed ro Create Vertex Buffer.");
        return hr;
    }

我已将D3D11_BIND_INDEX_BUFFER更改为D3D11_BIND_VERTEX_BUFFER并且发生相同的错误。

此后,还会产生以下警告。

D3D11 WARNING: ID3D11DeviceContext::Draw: Vertex Buffer at the input vertex slot 0 is not big enough for what the Draw*() call expects to traverse. This is OK, as reading off the end of the Buffer is defined to return 0. However the developer probably did not intend to make use of this behavior.  [ EXECUTION WARNING #356: DEVICE_DRAW_VERTEX_BUFFER_TOO_SMALL]

D3D11 WARNING: ID3D11DeviceContext::Draw: The size of the Constant Buffer at slot 0 of the Vertex Shader unit is too small (64 bytes provided, 192 bytes, at least, expected). This is OK, as out-of-bounds reads are defined to return 0. It is also possible the developer knows the missing data will not be used anyway. This is only a problem if the developer actually intended to bind a sufficiently large Constant Buffer for what the shader expects.  [ EXECUTION WARNING #351: DEVICE_DRAW_CONSTANT_BUFFER_TOO_SMALL]

D3D11 WARNING: ID3D11DeviceContext::Draw: Input vertex slot 0 has stride 24 which is less than the minimum stride logically expected from the current Input Layout (32 bytes). This is OK, as hardware is perfectly capable of reading overlapping data. However the developer probably did not intend to make use of this behavior.  [ EXECUTION WARNING #355: DEVICE_DRAW_VERTEX_BUFFER_STRIDE_TOO_SMALL]

TL; DR:在调用Draw之前,需要在每帧设置多维数据集的输入布局,顶点着色器和像素着色器。

具体来说,您忘记设置代码注释掉时就设置了顶点缓冲区:

// >>> Set vertex buffer
//g_pImmediateContext->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);

您的注释中包括您收到的“调试设备”错误,该错误首先导致您对其进行注释。 很明显,您的错误实际上是在不将D3D11_BUFFER_DESC.BindFlags设置为D3D11_BIND_VERTEX_BUFFER情况下为VB调用CreateBufferD3D11_BIND_VERTEX_BUFFER

在每次调用Draw*之前,您需要设置该绘图所需的任何状态。

Wiki记录了通过调用SpriteFont::Begin/End更改的确切状态。 特别是,它会更改输入布局和顶点着色器。 您的“多维数据集绘制”代码依靠这些状态在每帧之间保持不变,这实际上仅在平凡的情况下有效。

在每个渲染帧的开始,您应该:

  • 清除渲染目标和/或深度模板缓冲区
  • 调用OMSetRenderTargets设置您的主要渲染目标
  • 调用RSSetViewports设置视口状态

然后,在每次调用Draw*之前,请设置您使用的所有状态。 对于简单的3D立方体图,至少包括:

  • 渲染目标视图,深度模板视图,视口(在简单情况下,可以在帧的开始处设置一次)
  • BlendState,DepthStencilState,RasterizerState
  • 输入布局
  • 任何常量缓冲区,像素着色器,顶点着色器以及任何必需的SamplerState或Shader资源。

DirectX工具包包含许多帮助程序,例如CommonStateEffects以使其更易于管理,但是您仍然必须确保设置了您依赖的所有状态。

国家管理

状态管理是Direct3D编程的基本要求,并且对性能尤为重要。 在调用Draw*任何给定时间,都需要在渲染管道上设置该绘制所需的所有状态,但您确实希望最大程度地减少更改状态以提高性能的次数。

在实用程序库(例如DirectX Tool Kit)中,实际上有三种用于状态管理的基本策略:

  1. 捕获并恢复所有状态 这就是不推荐使用的D3DX9库中的Direct3D 9时代ID3DXFont代码的D3DX9 在Direct3D 9中,这最初是通过运行时跟踪当前状态的事实来实现的。 专门引入了“ PURE”设备以尝试消除这种开销,因此添加了状态块作为尝试使其工作的方式。 Direct3D 11中的状态向量也很大,并且运行时不以相同的方式支持“状态块”。 总体而言,这种方法超级易于使用,但速度却不快。

  2. 设置所有必需状态,然后清除使用状态 另一个选择是每次使用诸如SpriteBatch::Begin类的任何辅助功能时都设置所有状态,然后在调用SpriteBatch::End清除其使用的任何状态值。 从概念上讲,这种方法再次很容易,因为没有持久的副作用,但实际上,它也很慢,因为有很多额外的调用来设置空状态。

  3. 设置所需状态,让以后绘制清理状态 这是DirectX工具套件使用的选项。 我设置需要绘制的状态,然后不理会它。 如果在框架结尾之前调用我的代码后还有其他工作要做,则需要进行设置。 实际上, DirectX Tool Kit中的助手只使用了基本上所有图形都通用的标准状态,但是如果您不知道这种行为,则肯定会得到一些奇怪的交互。 例如,如果在调用SpriteBatch之前已设置了Geometry Shader,则在调用End时会发生奇怪的事情。 我假设,如果您使用的不是常规的VS / PS组合,则在调用我的代码之前先清除它。 我在Wiki上记录了每个助手所使用的所有状态,并且在实践中,这有时在性能和可预测的行为之间取得了很好的平衡,尽管有时确实会使人们感到困惑。

Direct3D 11与Direct3D 12的注意事项

在Direct3D 11中,调用Present时在帧末尾设置的任何状态仍会在下一帧的开始处设置,因此您将看到一些较早的教程在开始渲染循环之前设置了一些状态,并假定保持不变。 Direct3D 12的状态已被Present完全重置, 事实并非如此。 因此,养成每帧设置所有状态的习惯要好得多。 验证您正确地做这方面的一个方法是调用ClearState后右Present每一帧,虽然你可能只需要做到这一点的调试版本,因为它在一个正确编写的程序是在浪费时间,否则。

在Direct3D 11中,调用RSSetViewports设置视口的操作也会将剪切式剪刀矩形初始化为相同的值。 在Direct3D 12中,您需要通过调用RSSetScissorRects显式地执行此RSSetScissorRects否则最终将出现一个(0,0,0,0)剪切矩形,该矩形将所有内容都剪切掉。

有关这些基本渲染循环的一些示例,请参见GitHub

暂无
暂无

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

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