簡體   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