简体   繁体   English

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

[英]Input Assembler - Vertex Shader Linkage error

I'm trying to render text in my DX11 project, by using SpriteFont and SpriteBatch . 我正在尝试使用SpriteFontSpriteBatch在DX11项目中渲染文本。

Everything worked before adding the code in, but when the code in uncommented, I get the following error and nothing renders. 在添加代码之前,一切正常,但是在未注释代码的情况下,出现以下错误,并且没有任何显示。

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]

I have tried to change the DeviceContext & Device, but still the same error. 我试图更改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();

I've tried using different Devices and DeviceContext's, but still the same error. 我尝试使用不同的Devices和DeviceContext,但仍然是相同的错误。


I have been trying many different ways to get this working. 我一直在尝试许多不同的方法来使其工作。 This is what my render function looks like at the moment 这就是我目前的渲染功能

Updated: 18/02/2019 更新日期: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);

}

When running the project, I get the following error 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] 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]

This is the code that stores the data for a tri and sets up the index/vertex buffer 这是用于存储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;
    }

I have changed D3D11_BIND_INDEX_BUFFER to D3D11_BIND_VERTEX_BUFFER and the same error occurs. 我已将D3D11_BIND_INDEX_BUFFER更改为D3D11_BIND_VERTEX_BUFFER并且发生相同的错误。

Following this, the following warnings are produced too. 此后,还会产生以下警告。

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: You need to set your cube's Input Layout, Vertex Shader, and Pixel Shader each frame before you call Draw . TL; DR:在调用Draw之前,需要在每帧设置多维数据集的输入布局,顶点着色器和像素着色器。

Specifically, you forgot to set your Vertex Buffer as you left that code commented out: 具体来说,您忘记设置代码注释掉时就设置了顶点缓冲区:

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

Your comment includes the Debug Device error you get that caused you to comment it out in the first place. 您的注释中包括您收到的“调试设备”错误,该错误首先导致您对其进行注释。 It is pretty clear that your bug is actually where you call CreateBuffer for a VB without setting D3D11_BUFFER_DESC.BindFlags to D3D11_BIND_VERTEX_BUFFER . 很明显,您的错误实际上是在不将D3D11_BUFFER_DESC.BindFlags设置为D3D11_BIND_VERTEX_BUFFER情况下为VB调用CreateBufferD3D11_BIND_VERTEX_BUFFER

Before each call to Draw* you need to set any state that is required for that draw. 在每次调用Draw*之前,您需要设置该绘图所需的任何状态。

The exact state that is changed by calling SpriteFont::Begin/End is documented on the wiki . Wiki记录了通过调用SpriteFont::Begin/End更改的确切状态。 In particular, it changes both the input layout and the vertex shader. 特别是,它会更改输入布局和顶点着色器。 Your "cube drawing" code is relying on these states to be unchanged between each frame, which really only works in trivial cases. 您的“多维数据集绘制”代码依靠这些状态在每帧之间保持不变,这实际上仅在平凡的情况下有效。

At the start of each render frame, you should: 在每个渲染帧的开始,您应该:

  • Clear the render target and/or depth stencil buffer 清除渲染目标和/或深度模板缓冲区
  • Call OMSetRenderTargets to set your primary render target 调用OMSetRenderTargets设置您的主要渲染目标
  • Call RSSetViewports to set your viewport state 调用RSSetViewports设置视口状态

Then before each time you call Draw* set all the state you use. 然后,在每次调用Draw*之前,请设置您使用的所有状态。 For a simple 3D cube drawing, this includes at a minimum: 对于简单的3D立方体图,至少包括:

  • Render Target view, Depth Stencil view, Viewport (which in simple cases can be set once at the start of the frame) 渲染目标视图,深度模板视图,视口(在简单情况下,可以在帧的开始处设置一次)
  • BlendState, DepthStencilState, RasterizerState BlendState,DepthStencilState,RasterizerState
  • Input layout 输入布局
  • Any Constant buffers, Pixel shader, Vertex shader, and any required SamplerState or Shader resources. 任何常量缓冲区,像素着色器,顶点着色器以及任何必需的SamplerState或Shader资源。

The DirectX Tool Kit includes a number of helpers like CommonState and Effects to make this easier to manage, but you still have to make sure all state you rely on is set. DirectX工具包包含许多帮助程序,例如CommonStateEffects以使其更易于管理,但是您仍然必须确保设置了您依赖的所有状态。

State management 国家管理

State management is an essential requirement for Direct3D programming, and particularly important for performance. 状态管理是Direct3D编程的基本要求,并且对性能尤为重要。 At any given time when you call Draw* , all the state needed for that draw needs to be set on the rendering pipeline, yet you really want to minimize the number of times you change state for performance. 在调用Draw*任何给定时间,都需要在渲染管道上设置该绘制所需的所有状态,但您确实希望最大程度地减少更改状态以提高性能的次数。

There are really three basic strategies for state management in utility libraries like DirectX Tool Kit : 在实用程序库(例如DirectX Tool Kit)中,实际上有三种用于状态管理的基本策略:

  1. Capture and restore all state . 捕获并恢复所有状态 This is what the legacy Direct3D 9 era ID3DXFont code in the deprecated D3DX9 library did. 这就是不推荐使用的D3DX9库中的Direct3D 9时代ID3DXFont代码的D3DX9 In Direct3D 9, this was originally accomplished through the fact that the runtime tracked the current state. 在Direct3D 9中,这最初是通过运行时跟踪当前状态的事实来实现的。 The "PURE" device was introduced specifically to try to remove this overhead, so state blocks were added as a way to try to make it work. 专门引入了“ PURE”设备以尝试消除这种开销,因此添加了状态块作为尝试使其工作的方式。 The state vector in Direct3D 11 is also quite large, and the runtime doesn't support 'state blocks' in the same way. Direct3D 11中的状态向量也很大,并且运行时不以相同的方式支持“状态块”。 Overall, this approach is super easy to use, but never fast. 总体而言,这种方法超级易于使用,但速度却不快。

  2. Set all required state, clear used state afterwards . 设置所有必需状态,然后清除使用状态 Another option would be to set all the state every time you use any helper functions like SpriteBatch::Begin , and then when you call SpriteBatch::End clear any state values it used. 另一个选择是每次使用诸如SpriteBatch::Begin类的任何辅助功能时都设置所有状态,然后在调用SpriteBatch::End清除其使用的任何状态值。 This approach again is conceptually easy because there's no lingering side-effects, but in practice is also slow because there's lots of extra calls to set null state. 从概念上讲,这种方法再次很容易,因为没有持久的副作用,但实际上,它也很慢,因为有很多额外的调用来设置空状态。

  3. Set required state, let later draws clean up the state . 设置所需状态,让以后绘制清理状态 This is the option that DirectX Tool Kit uses. 这是DirectX工具套件使用的选项。 I set the state I need to draw, and then leave it alone. 我设置需要绘制的状态,然后不理会它。 If you have more drawing to do after you call my code before the end of the frame, you need to set them. 如果在框架结尾之前调用我的代码后还有其他工作要做,则需要进行设置。 In practice the helpers in DirectX Tool Kit only used the standard states common to basically all drawing, but you definitely can get some strange interactions if you aren't aware of this behavior. 实际上, DirectX Tool Kit中的助手只使用了基本上所有图形都通用的标准状态,但是如果您不知道这种行为,则肯定会得到一些奇怪的交互。 For example, if you have a Geometry Shader set before calling SpriteBatch , weird things will happen when you call End . 例如,如果在调用SpriteBatch之前已设置了Geometry Shader,则在调用End时会发生奇怪的事情。 I assume if you used something beyond the usual VS/PS combo, you cleared it before calling into my code. 我假设,如果您使用的不是常规的VS / PS组合,则在调用我的代码之前先清除它。 I document all the state used by each helper on the wiki, and in practice this is a good balance of performance and predictable behavior even though it does sometimes confuse people. 我在Wiki上记录了每个助手所使用的所有状态,并且在实践中,这有时在性能和可预测的行为之间取得了很好的平衡,尽管有时确实会使人们感到困惑。

Direct3D 11 vs. Direct3D 12 Notes Direct3D 11与Direct3D 12的注意事项

In Direct3D 11, any state set at the end of a frame when you call Present is still set at the start of the next frame, so you'll see some older tutorials set some state up once before starting the rendering loop and assume remains unchanged. 在Direct3D 11中,调用Present时在帧末尾设置的任何状态仍会在下一帧的开始处设置,因此您将看到一些较早的教程在开始渲染循环之前设置了一些状态,并假定保持不变。 This is not true of Direct3D 12 where the state is completely reset by the Present . Direct3D 12的状态已被Present完全重置, 事实并非如此。 Therefore, it's much better to get in the habit of setting all the state every frame. 因此,养成每帧设置所有状态的习惯要好得多。 One way to validate you did this correctly is to call ClearState right after the Present each frame, although you probably only want to do this in Debug builds since it's a waste of time otherwise in a properly written program. 验证您正确地做这方面的一个方法是调用ClearState后右Present每一帧,虽然你可能只需要做到这一点的调试版本,因为它在一个正确编写的程序是在浪费时间,否则。

In Direct3D 11, the call to RSSetViewports to set the viewport will also initialize the clipping scissor rectangles to the same value. 在Direct3D 11中,调用RSSetViewports设置视口的操作也会将剪切式剪刀矩形初始化为相同的值。 In Direct3D 12, you need to do this explicitly by calling RSSetScissorRects otherwise you end up with a (0,0,0,0) clipping rectangle which clips out everything. 在Direct3D 12中,您需要通过调用RSSetScissorRects显式地执行此RSSetScissorRects否则最终将出现一个(0,0,0,0)剪切矩形,该矩形将所有内容都剪切掉。

See GitHub for some examples of these basic render loops. 有关这些基本渲染循环的一些示例,请参见GitHub

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

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