Тип bool в шейдерах DirectX11

189
30 января 2019, 22:00

Имею DirectX11 и небольшой движок. Что хочу сделать - отправить в вершинный шейдер структурный буфер собственного типа(в типе единственный член, который имеет тип bool), и уже в вершинном шейдере получить информацию из структурного буфера, ну и с ней что-то сделать. Как создаю структурный буфер: Тип структурного буфера:

template<class T> struct LogicBuffer
{
    T data;
    // конструкторы
    LogicBuffer(const T& v);
    LogicBuffer(LogicBuffer&& v);
    const LogicBuffer& operator=(LogicBuffer&& v);
};

Опустим дополнительные подробности, здесь само создание буфера:

template<class T>
void PhysicBuffer<T>::rebuildPages(ID3D11Device* device)
{
    // bufferCPU - это массив структур на CPU, std::vector<LogicBuffer<bool>>
    size_t vfStride = sizeof((*bufferCPU.begin()).data); // размер одной структуры
    if (physicBuffer != nullptr)     physicBuffer->Release();
    if (physicShaderResourceView != nullptr) physicShaderResourceView->Release();
    // описатель буфера
    D3D11_BUFFER_DESC bufferDesc;
    ZeroMemory(&bufferDesc, sizeof(bufferDesc));
    bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    bufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
    bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
    bufferDesc.StructureByteStride = vfStride;
    bufferDesc.ByteWidth = this->bufferCPU.size() * vfStride;
    D3D11_SUBRESOURCE_DATA bufferData;
    ZeroMemory(&bufferData, sizeof(bufferData));
    bufferData.pSysMem = this->bufferCPU.data();
    // создали сам буфер
    HRESULT hr = device->CreateBuffer(&bufferDesc, &bufferData, &physicBuffer);
    // создали представление ресурсов, для отображения в GPU
    D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    ZeroMemory(&srvDesc, sizeof(srvDesc));
    srvDesc.Format = DXGI_FORMAT_UNKNOWN;
    srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
    srvDesc.Buffer.ElementWidth = this->bufferCPU.size();
    hr = device->CreateShaderResourceView(physicBuffer, &srvDesc, &physicShaderResourceView);
    // проверки опущены умышленно, пока всё в режиме теста
}

Также, создаем переменную physicVisible типа PhysicBuffer, и добавляем в неё несколько элементов типа bool(все true, проверено), думаю, этот код не нужен.

Буфер создан. Здесь отправляем его на GPU:

devcontx->VSSetShaderResources(1, 1, &physicVisible->physicShaderResourceView); // индекс буфера 1, т.к. перед ним идет еще один буфер

И вот вершинный шейдер:

    struct LogicBufferPosition
    {
        matrix Pos;
    };
    struct LogicBufferBool
    {
        bool flag;
    };
    StructuredBuffer<LogicBufferPosition> arrayPositions: register(t0);
    StructuredBuffer<LogicBufferBool> arrayBools: register(t1);
    cbuffer ConstantBufferVS: register(b0)
    { 
        matrix World; 
        matrix View; 
        matrix Perspective; 
    };
    ////////////////////////////
    struct VS_INPUT 
    { 
        float3 Pos: POSITION; 
        float4 Color: COLOR;
    }; 
    struct GS_INPUT
    { 
        float4 Pos: POSITION; 
        float4 Color: COLOR;
        bool visible: Output;
    }; 
    GS_INPUT main(VS_INPUT input, uint id: SV_InstanceID) 
    { 
        bool tmp = arrayBools[id].flag; // здесь проблема
        // .... etc
    } 

Сам вопрос. Как было написано выше, в шейдер передаются значения типа true, однако в шейдере уже значение false(смотрел отладчиком). Почему так? Работает ли тип bool в шейдерах, или по - старинке, сменить на float?

P.S.: ах да, рендерю в режиме инстансинга в стиле DirectX11, т.е. метод DrawInstanced

Answer 1

sizeof((*bufferCPU.begin()).data) выглядит очень подозрительно. Следует использовать размер самой структуры sizeof(LogicBuffer<bool>). А заодно еще проверить, что он соответствует ожиданиям static_assert(1 == sizeof(LogicBuffer<bool>));.

Также есть мнение, что размер hlsl bool равен 4 байтам, а не 1. Соответственно имеет смысл на стороне С/C++ вместо bool использовать BOOL из SDK.

READ ALSO
Для чего нужно (char *) при взятии адреса &amp;mass_size?

Для чего нужно (char *) при взятии адреса &mass_size?

Нужно записать в бинарный файл число типа int, хранящееся в переменной mass_size

192
Как разбить элемент массива строк на массив из его символов?

Как разбить элемент массива строк на массив из его символов?

Есть массивы a и b типа string, где a[1]="hello"; a[2]="woRlD"; a[3]="qejqjekqew"; Массив b изначально пустой

212
C++ atomic runtime error

C++ atomic runtime error

Программа компилируеться, но выводит всегда одно и тоже число, и не выходит корректно

329
Поиск по базе данных с использованием фильтров Qt

Поиск по базе данных с использованием фильтров Qt

В задании сказанно реализовать приложение, которое будет искать в базе данных элементы по заданным параметрамКоличество параметров и их названия...

243