Войти
ПрограммированиеФорумГрафика

Как передать в шейдер данные в формате float 16 ? (2 стр)

Страницы: 1 2
#15
13:00, 6 авг. 2019

http://blog.fpmurphy.com/2008/12/half-precision-floating-point-format_14.html


#16
14:32, 6 авг. 2019

Спасибо всем за ссылки, но все же - кто нибудь на ПРАКТИКЕ делал передачу 16 битных float в шейдер через константный буфер?

#17
(Правка: 14:45) 14:42, 6 авг. 2019

san
да все блин делали. любая библиотека умеет их конвертить одинаково(правильно). разбирайся с выравниванием, потому что выравнивается константный буффер по миллиону правил. для тестирования добавляй padding везде до float4, чтобы выравнивая избежать:

#pragma pack(push, 1)
struct SampleBuffer
{
  half4 half_test;
  float padding0[2];

  int some_other_test;
  float padding1[3];

  float4 more_tests;
};
#pragma pack(pop)
и рефлекшеном проверяй, что суммарный размер constant buffer'а в шейдере совпадает с тем, что ты ожидаешь на стороне c++. если у тебя массивы используются, то правила ещё сложнее, потому что к паддингу добавляется выравнивание по миллиону правил вроде размера самого большого мембера в элементе массива итп.
#18
(Правка: 15:19) 15:06, 6 авг. 2019

Suslik
> разбирайся с выравниванием, потому что выравнивается константный буффер по миллиону правил
?? "Миллион правил" это значит отсутствие всяких правил.
Правильно ли я тебя понимаю, что на стороне шейдера надо дополнять ВСЕ элементы буфера до float4? Это несколько странно, поскольку передача 4х float стоящих подряд выравнивания не требует. ОК, попробую дополнить каждый элемент half4 двумя float'ами. Сейчас не за компом, так что смогу проверить только через пару часов.

#19
(Правка: 15:57) 15:52, 6 авг. 2019

san
> Правильно ли я тебя понимаю, что на стороне шейдера надо дополнять ВСЕ элементы буфера до float4?
я же сказал:
Suslik
> для тестирования

когда убедишься, что с padding'ом работает, тогда уже padding убираешь и смотришь, в чём дело.

san
> ?? "Миллион правил" это значит отсутствие всяких правил.
"миллион правил" означает, что их надо читать в спеке, а не спрашивать на форуме, потому что по ним не просто так 50 страниц написано: https://renderdoc.org/vkspec_chunked/chap14.html#interfaces-resources-layout

#20
16:11, 6 авг. 2019

Suslik
> когда убедишься, что с padding'ом работает, тогда уже padding убираешь и смотришь, в чём дело.
Опять ничего не понял. Если "с padding'ом работает", т.е. я могу корректно читать значения half4, то зачем мне это "убирать и смотреть в чем дело"?

>надо читать в спеке, а не спрашивать их на форуме
Так для того и форум, что бы быстро получить совет тех, кто прочитал эти "50 страниц" и уже поимел необходимый опыт. Банальная экономия времени и пример взаимопомощи. Так что не надо раздражаться. Можешь помочь - спасибо. Нет желания разжевывать и тратить время - ну так не отвечай. А то вроде и помогаешь, но все как-то через губу. Зачем - непонятно.

#21
17:01, 6 авг. 2019

san
ты смог даже суслика достать :)

#22
(Правка: 7:48) 3:03, 7 авг. 2019

Для тех кому интересна тема - как мне удалось заставить это работать.
Итак - задача была упаковать данные при передаче в шейдер для экономии места в константном буфере. В самом шейдере я предпочитаю работать во float, но размер буфера был критичен, так как вылазил за 64 float'а.

Подход "в лоб" успехом не увенчался - half в константном буфере требует 6 версию шейдеров, но даже с ней не работает - принимается мусор.
Вторая итерация с min16float4 уже запускалась на 5 версии шейдеров, но все равно не работала.
Наконец я решил принимать 16 битные float'у как uint2 а потом распаковывать их в вертексном шейдере. И все заработало.  Выравнивать ничего не потребовалось, изучать 50 страниц спеков тоже, все оказалось просто и понятно.

Вот как это выглядит:

cbuffer cbPass : register(b0)
{
  float4x4 ProjView;
  float4x4 ModelMat;

  float4 m_Dir;

  float  m_Light;
  float  m_Time;
  float  m_Test;  // distance test
  float  m_Britness;

  float4 m_Pos; 

    // left and right controllers - 16 bit float

  uint2 p_Left_Pos;
  uint2 p_Left_Dir;
  uint2 p_Right_Pos;
  uint2 p_Right_Dir;
}  
// размер буфера - 256 байт.

// unpacked data
static  float4 Left_Pos;
static  float4 Left_Dir;
static  float4 Right_Pos;
static  float4 Right_Dir;

float2 UnpackFloat16( uint a )
{
    return f16tof32( uint2( a & 0xFFFF, a >> 16 ) );
}
float4 UnpackFloat16( uint2 v )
{
    return float4( UnpackFloat16( v.x ), UnpackFloat16( v.y ) );
}

void UnpackData()
{
   Left_Pos     = UnpackFloat16(p_Left_Pos);
   Left_Dir     = UnpackFloat16(p_Left_Dir);
   Right_Pos    = UnpackFloat16(p_Right_Pos);
   Right_Dir    = UnpackFloat16(p_Right_Dir);
}

Далее я функцию UnpackData() включил во все вертексные шейдера и получил искомые позиции контроллеров в нормальном формате.

На стороне C++ используется библиотека Half (http://half.sourceforge.net/) с минимальной доработкой, а именно:

struct vec4_half
{
  inline vec4_half() : x(0), y(0), z(0), w(0) { }
  inline vec4_half(const vec4 &v) : x(v.x), y(v.y), z(v.z), w(v.w) {}
  
  half_float::half x;
  half_float::half y;
  half_float::half z;
  half_float::half w;
};

Страницы: 1 2
ПрограммированиеФорумГрафика