void HlslDispatchable::CompileWithDxc()

in DxDispatch/src/dxdispatch/HlslDispatchable.cpp [180:276]


void HlslDispatchable::CompileWithDxc()
{
    ComPtr<IDxcBlobEncoding> source;
    THROW_IF_FAILED(m_device->GetDxcUtils()->LoadFile(
        m_desc.sourcePath.c_str(), 
        nullptr, 
        &source));

    DxcBuffer sourceBuffer;
    sourceBuffer.Ptr = source->GetBufferPointer();
    sourceBuffer.Size = source->GetBufferSize();
    sourceBuffer.Encoding = DXC_CP_ACP;

    std::vector<std::wstring> compilerArgs(m_desc.compilerArgs.size());
    std::vector<LPCWSTR> lpcwstrArgs(m_desc.compilerArgs.size());
    for (size_t i = 0; i < m_desc.compilerArgs.size(); i++)
    {
        compilerArgs[i] = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(m_desc.compilerArgs[i]);
        lpcwstrArgs[i] = compilerArgs[i].data();
    }

    ComPtr<IDxcResult> result;
    THROW_IF_FAILED(m_device->GetDxcCompiler()->Compile(
        &sourceBuffer, 
        lpcwstrArgs.data(), 
        static_cast<UINT32>(lpcwstrArgs.size()), 
        m_device->GetDxcIncludeHandler(), 
        IID_PPV_ARGS(&result)));

    ComPtr<IDxcBlobUtf8> errors;
    THROW_IF_FAILED(result->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&errors), nullptr));
    if (errors != nullptr && errors->GetStringLength() != 0)
    {
        std::wcerr << L"Warnings and Errors:" << errors->GetStringPointer();
    }

    HRESULT compileStatus = S_OK;
    THROW_IF_FAILED(result->GetStatus(&compileStatus));
    if (FAILED(compileStatus))
    {
        throw std::invalid_argument("Failed to compile.");
    }

    ComPtr<IDxcBlob> shaderBlob;
    THROW_IF_FAILED(result->GetOutput(
        DXC_OUT_OBJECT, 
        IID_PPV_ARGS(&shaderBlob), 
        nullptr));

    ComPtr<IDxcBlob> reflectionBlob;
    THROW_IF_FAILED(result->GetOutput(
        DXC_OUT_REFLECTION, 
        IID_PPV_ARGS(&reflectionBlob), 
        nullptr));

    ComPtr<IDxcBlob> pdbBlob;
    ComPtr<IDxcBlobUtf16> pdbName;
    if (SUCCEEDED(result->GetOutput(
        DXC_OUT_PDB, 
        IID_PPV_ARGS(&pdbBlob), 
        &pdbName)))
    {
        // TODO: store this in a temp directory?
        FILE* fp = NULL;
        _wfopen_s(&fp, pdbName->GetStringPointer(), L"wb");
        fwrite(pdbBlob->GetBufferPointer(), pdbBlob->GetBufferSize(), 1, fp);
        fclose(fp);
    }

    DxcBuffer reflectionBuffer;
    reflectionBuffer.Ptr = reflectionBlob->GetBufferPointer();
    reflectionBuffer.Size = reflectionBlob->GetBufferSize();
    reflectionBuffer.Encoding = DXC_CP_ACP;

    THROW_IF_FAILED(m_device->GetDxcUtils()->CreateReflection(
        &reflectionBuffer, 
        IID_PPV_ARGS(m_shaderReflection.ReleaseAndGetAddressOf())));

    CreateRootSignatureAndBindingMap();

    D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {};
    psoDesc.pRootSignature = m_rootSignature.Get();
    psoDesc.CS.pShaderBytecode = shaderBlob->GetBufferPointer();
    psoDesc.CS.BytecodeLength = shaderBlob->GetBufferSize();
    THROW_IF_FAILED(m_device->D3D()->CreateComputePipelineState(
        &psoDesc, 
        IID_PPV_ARGS(m_pipelineState.ReleaseAndGetAddressOf())));

    ComPtr<ID3D12DescriptorHeap> descriptorHeap;
    D3D12_DESCRIPTOR_HEAP_DESC descriptorHeapDesc = {};
    descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
    descriptorHeapDesc.NumDescriptors = static_cast<uint32_t>(m_bindPoints.size());
    descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
    THROW_IF_FAILED(m_device->D3D()->CreateDescriptorHeap(
        &descriptorHeapDesc, 
        IID_PPV_ARGS(m_descriptorHeap.ReleaseAndGetAddressOf())));
}