понедельник, 26 июля 2010 г.

Баг в геометрическом шейдере

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

Разница в том, что если использовать .fx формат D3DX, то с глобальными константами всё ок. Если же использовать простые шейдеры, то глобальные константы, например вида

const float4 g_plane = float4(1., 0., 0., 1.);

считаются находящимися в дефолтном cbuffer, который создаёт компилятор. Поэтому, чтобы вы там ни прописали в шейдере, компилятор это выбросит, а GPU будет ожидать данные из буфера.

Зараза, хоть бы warning выдавал!

8 комментариев:

  1. Привет!
    Cтолкнулся точно с такой же проблемой используя Dx10 и нативе HLSL. Обнаружил что при рефлекшене можно извлекать из D3D10_SHADER_VARIABLE_DESC дефолтовое значение из шейдера (мембер структуры DefaultValue). Я обрадовался думал все ок, но оказалось что он всегда возвращает NULL (т.е. нулевой поинтер). Гугл ничего не дал, никто его не использует что-ли?
    Думал найти ответ в недавно расшаренных сырцах Fx-ов, но они это поле структуры не используют, т.е. у них там насколько я понял свой парсер и скармливают НLSL-компилеру уже подготовленный текст шейдера. Вообщем пока забросил, может что значешь по-этому поводу?

    ОтветитьУдалить
  2. Удивляет одно, что привносят ООП в шейдеры, а банально константы времени компиляции приходится по-старинке делать уродскими макросами.:(
    P.S. Может оно и можно эти константы достать из шейдера, но уж сильно геморно имхо.
    P.S.2. Кстати может знаешь можно ли компилятору указать явно (не через макрос) что это константа времени компиляции, т.е. что это не униформ переменная, значение которой нельзя менять в шейдера, а именно константа времени компиляции?

    ОтветитьУдалить
  3. Shader Constants (DirectX HLSL)

    There are two default constant buffers available, $Global and $Param. Variables which are placed in the global scope are added implicitly to the $Global cbuffer, using the same packing method as is used for cbuffers.

    ОтветитьУдалить
  4. Попробуй флаг D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY.

    ОтветитьУдалить
  5. Вообщем все оказывается проще, если просто сесть и со светлой головой перечитать документацию.:)
    Вообщем почитав раздел Variable Syntax (DirectX HLSL)
    обнаружил что есть куча storage-class modifiers.
    Таким образом если глобальную перменную пометить как static она не видна приложению и в $Global cb не заносится. Т.е. это и есть самая настоящая переменная времени компиляции. (Проверил действительно не заносится, а считается константой).

    Единственное что я не понял это:
    "Global variables—that are not marked static or extern—are not compiled into the shader and cannot be optimized. To initialize this type of global variable, use reflection to get their value and then set the value in a shader using a constant buffer.
    "
    Т.е. как так может быть, если они пишут что все глобальные переменные по-умолчанию имеют storage-class modifiers ввиде extern uniform. Т.е. получается добится что бы этих модифаеров не было невозможно. Баг спецификации или я чего-то недопонимаю?

    ОтветитьУдалить
  6. //-- Попробуй флаг D3D10_SHADER_ENABLE_BACKWARDS_COMPATIBILITY.

    Не хочу. Т.к. не хочу ничего старого нести с собой.
    Это я пробовал, ничего не меняется по-моему, единственное что разрешается это запись в глобальную переменную. По-умолчанию в Dx >= 10 глобальные переменные объявленые как const.

    ОтветитьУдалить
  7. Я тоже подумал про static, но сейчас нет возможности проверить. Но если с ним работает, то можно и так жить.

    ОтветитьУдалить