Input Assembler - ошибка связывания вершинного шейдера - PullRequest
0 голосов
/ 01 февраля 2019

Я пытаюсь отобразить текст в моем проекте DX11, используя SpriteFont и SpriteBatch.

Все работало до добавления кода, но когда код в незакомментированном виде, я получаю следующую ошибку, и ничего не отображается.

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 & Device, ноошибка та же.

    //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();

Я пытался использовать разные устройства и 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]

Это код, который хранит данные для 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]

1 Ответ

0 голосов
/ 07 февраля 2019

TL; DR: Перед каждым вызовом Draw.

вам необходимо установить формат ввода входного куба, вершинный шейдер и пиксельный шейдер. В частности, вы забыли установитьБуфер вершин, когда вы оставили этот код закомментированным:

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

Ваш комментарий включает в себя полученную вами ошибку отладочного устройства, из-за которой вы сначала закомментировали ее.Совершенно очевидно, что ваша ошибка в действительности заключается в том, что вы вызываете CreateBuffer для VB без установки D3D11_BUFFER_DESC.BindFlags в D3D11_BIND_VERTEX_BUFFER.

Перед каждым вызовом Draw* вам нужно установить любое состояниеэто требуется для этого розыгрыша.

Точное состояние, которое изменяется при вызове SpriteFont::Begin/End, задокументировано в wiki .В частности, он меняет как входной макет, так и вершинный шейдер.Ваш код "рисования куба" полагается, что эти состояния будут неизменными между каждым кадром, что действительно работает только в тривиальных случаях.

В начале каждого кадра рендеринга вы должны:

  • Очистить целевой объект рендеринга и / или буфер трафарета глубины
  • Позвонить OMSetRenderTargets, чтобы установить основную цель рендеринга
  • Вызвать RSSetViewports, чтобы установить состояние вашего окна просмотра

Затем перед каждым звонком Draw* установите все используемое вами состояние.Для простого трехмерного чертежа куба это включает как минимум:

  • Вид цели рендеринга, вид Трафарета глубины, Видовой экран (который в простых случаях можно установить один раз в начале кадра)
  • BlendState, DepthStencilState, RasterizerState
  • Макет ввода
  • Любые постоянные буферы, пиксельный шейдер, вершинный шейдер и любые необходимые ресурсы SamplerState или Shader.

DirectX Tool Kit включает в себя несколько помощников, таких как CommonState и Effects, чтобы упростить управление, но вы все равно должны убедиться, что установлено состояние all , на которое вы полагаетесь.

Управление состоянием

Управление состоянием является важным требованием для программирования Direct3D и особенно важно для производительности.В любой момент времени, когда вы вызываете Draw*, все состояние, необходимое для этого отрисовки, должно быть установлено в конвейере рендеринга, но вы действительно хотите минимизировать количество раз, которое вы меняете состояние для производительности.

Тамна самом деле это три основные стратегии управления состоянием в служебных библиотеках, такие как DirectX Tool Kit :

  1. Захват и восстановление всех состояний .Именно так поступил устаревший код Direct3D 9 эпохи ID3DXFont в устаревшей библиотеке D3DX9.В Direct3D 9 это было первоначально достигнуто благодаря тому факту, что среда выполнения отслеживала текущее состояние.Устройство «PURE» было введено специально для того, чтобы попытаться устранить эти издержки, поэтому были добавлены блоки состояния, чтобы попытаться заставить его работать.Вектор состояния в Direct3D 11 также довольно велик, и среда выполнения не поддерживает «блоки состояния» таким же образом.В целом, этот подход очень прост в использовании, но никогда не бывает быстрым.

  2. Установите все необходимое состояние, затем очистите использованное состояние .Другой вариант - установить все состояния каждый раз, когда вы используете какие-либо вспомогательные функции, такие как SpriteBatch::Begin, а затем, когда вы вызываете SpriteBatch::End, сбросить все используемые значения состояний.Этот подход снова концептуально прост, потому что нет никаких побочных эффектов, но на практике он также медленный, потому что есть много дополнительных вызовов для установки нулевого состояния.

  3. Устанавливаем требуемое состояние, пусть потом рисует, очищают состояние .Это опция, которую использует DirectX Tool Kit .Я устанавливаю состояние, которое мне нужно нарисовать, а затем оставляю его в покое.Если вам нужно больше рисовать после того, как вы вызовете мой код до конца фрейма, вам нужно установить их.На практике помощники в DirectX Tool Kit использовали только стандартные состояния, общие для практически всех чертежей, но вы определенно можете получить некоторые странные взаимодействия, если не знаете об этом.Например, если у вас установлен Geometry Shader перед вызовом SpriteBatch, странные вещи произойдут, когда вы вызовете End.Я предполагаю, что если вы использовали что-то помимо обычной комбо VS / PS, вы очистили это перед вызовом в мой код.Я документирую все состояния, используемые каждым помощником в вики, и на практике это хороший баланс производительности и предсказуемого поведения, хотя иногда это сбивает людей с толку.

Direct3D 11 противПримечания Direct3D 12

В Direct3D 11 любое состояние, установленное в конце кадра при вызове Present, все еще устанавливается в начале следующего кадра, поэтому вы увидите, что некоторые более ранние учебники устанавливают некоторое состояниеодин раз перед запуском цикла рендеринга и предположить, что остается неизменным.Это не верно для Direct3D 12, где состояние полностью сбрасывается Present.Поэтому гораздо лучше привыкнуть устанавливать все состояния в каждом кадре.Один из способов убедиться, что вы сделали это правильно, - это вызывать ClearState сразу после Present каждого кадра, хотя вы, вероятно, хотите делать это только в сборках Debug, поскольку в правильно написанной программе это пустая трата времени.

В Direct3D 11 вызов RSSetViewports для установки области просмотра также инициализирует прямоугольники обрезки ножниц тем же значением.В Direct3D 12 вам нужно сделать это явно, вызвав RSSetScissorRects, в противном случае вы получите (0,0,0,0) обтравочный прямоугольник, который вырезает все.

См. GitHub для некоторых примеров этих основных циклов рендеринга.

...