Упаковка библиотеки шейдеров

Здесь мы покажем, как скомпилировать код шейдера, загрузить скомпилированный код в библиотеку шейдеров и привязать ресурсы из исходных слотов к целевым слотам.

Цель: Упаковка библиотеки шейдеров для связывания шейдеров.

Предварительные требования

Предполагается, что вы знакомы с C++. Также вы должны быть знакомы с основными принципами программирования графики.

Время выполнения: 30 минут.

Инструкции

1. Компиляция кода шейдера

Скомпилируйте код шейдера с помощью одной из функций компиляции. Например, в этом фрагменте кода используется D3DCompile.

    string source;
 
    ComPtr<ID3DBlob> codeBlob;
    ComPtr<ID3DBlob> errorBlob;
    HRESULT hr = D3DCompile(
        source.c_str(),
        source.size(),
        "ShaderModule",
        NULL,
        NULL,
        NULL,
        ("lib" + m_shaderModelSuffix).c_str(),
        D3DCOMPILE_OPTIMIZATION_LEVEL3,
        0,
        &codeBlob,
        &errorBlob
        );

Исходная строка содержит некомпилизованный код ASCII HLSL.

2. Загрузите скомпилированный код в библиотеку шейдеров.

Вызовите функцию D3DLoadModule , чтобы загрузить скомпилированный код (ID3DBlob) в модуль (ID3D11Module), представляющий библиотеку шейдера.

    // Load the compiled library code into a module object.
    ComPtr<ID3D11Module> shaderLibrary;
    DX::ThrowIfFailed(D3DLoadModule(codeBlob->GetBufferPointer(), codeBlob->GetBufferSize(), &shaderLibrary));

3. Привязка ресурсов из исходных слотов к слотам назначения.

Вызовите метод ID3D11Module::CreateInstance , чтобы создать экземпляр (ID3D11ModuleInstance) библиотеки, чтобы затем можно было определить привязки ресурсов для экземпляра.

Вызовите методы bind id3D11ModuleInstance , чтобы привязать необходимые ресурсы из исходных слотов к целевым слотам. Это могут быть текстуры, буферы, выборки, буферы констант или БПЛА. Как правило, используются те же слоты, что и исходная библиотека.

    // Create an instance of the library and define resource bindings for it.
    // In this sample we use the same slots as the source library however this is not required.
    ComPtr<ID3D11ModuleInstance> shaderLibraryInstance;
    DX::ThrowIfFailed(shaderLibrary->CreateInstance("", &shaderLibraryInstance));
    // HRESULTs for Bind methods are intentionally ignored as compiler optimizations may eliminate the source
    // bindings. In these cases, the Bind operation will fail, but the final shader will function normally.
    shaderLibraryInstance->BindResource(0, 0, 1);
    shaderLibraryInstance->BindSampler(0, 0, 1);
    shaderLibraryInstance->BindConstantBuffer(0, 0, 0);
    shaderLibraryInstance->BindConstantBuffer(1, 1, 0);
    shaderLibraryInstance->BindConstantBuffer(2, 2, 0);

Этот код HLSL показывает, что исходная библиотека использует те же слоты (t0, s0, b0, b1 и b2), что и слоты, используемые в предыдущих методах привязки ID3D11ModuleInstance.

// This is the default code in the fixed header section.
Texture2D<float3> Texture : register(t0);
SamplerState Anisotropic : register(s0);
cbuffer CameraData : register(b0)
{
    float4x4 Model;
    float4x4 View;
    float4x4 Projection;
};
cbuffer TimeVariantSignals : register(b1)
{
    float SineWave;
    float SquareWave;
    float TriangleWave;
    float SawtoothWave;
};

// This code is not displayed, but is used as part of the linking process.
cbuffer HiddenBuffer : register(b2)
{
    float3 LightDirection;
};

Сводка и дальнейшие действия

Мы скомпилировали код шейдера, загрузили скомпилированный код в библиотеку шейдеров и привязали ресурсы из исходных слотов к целевым слотам.

Далее мы создадим графы компоновки функций (FLG) для шейдеров, свяжем их с скомпилированным кодом и создадим большие двоичные объекты шейдеров, которые может использовать среда выполнения Direct3D.

Создание графа связывания функций и связывание его с скомпилированным кодом

Использование связывания шейдеров