Render-to-Vertex Buffer Approaches

Программирование с
Render to VB (R2VB)
Обзор материала
•Основы R2VB
•Изменения в DX9 API
•Хитрые приемы и оптимизации
Основы R2VB
•Идея: использовать текстуры и рендертекстуры как входныe данные вершинного
конвеера
VB
IB
VB
VS
Отрисовка в
вершинный буфер
RS
PS
Raster
Backend
Tex
Render Target
Depth/Stencil
Отрисовка в
текстуру
Приемущества R2VB метода
•Быстрота операций
•На Х1900: 8 верш. АЛУ, 48 пиксел. АЛУ
•Более совершенные динамические переходы
в пиксельном шейдере
•Очень быстрый доступ к текстурам
•Гибкость задания данных
•Все форматы текстур включая с компрессией
•Использование текстур как больших
буферов констант
•Похоже на унифицированную архитектуру
будущего
Проверка на поддержку R2VB
•Используется специальный Four-CC код
•MAKEFOURCC('R','2','V','B')
•Только для проверки, не для создания
ресурсов
bool supportsR2VB = false;
if (d3d->CheckDeviceFormat(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE,
(D3DFORMAT) MAKEFOURCC('R','2','V','B')) == D3D_OK)
{
supportsR2VB = true;
}
Использование текстур как VB
•С точки зрения GPU текстуры и VB –
массивы в видео памяти
•Теоретически можно установить указатель
потока вершин на текстуру
•Не любая текстура может быть подана на
вход вершинного конвеера
•«Swizzle» текстур не используется в VB
•Необходим механизм задания замещения
вершинных данных данными текстуры
•В DX9 нет встроеных возможностей
Интерпретация текстурных данных
•Проблема со «swizzle» решается легко – при
использовании D3DUSAGE_DMAP флага он
отключатся
•Линеаризация данных
0
3
4
8
0
1
2
3
4
11
5
6
7
8
9
10
11
Форматы
•Соответствие текстурных и вершинных
форматов
Texture format
Vertex declaration type
D3DFMT_R32F
D3DDECLTYPE_FLOAT1
D3DFMT_G32R32F
D3DDECLTYPE_FLOAT2
D3DFMT_A32B32G32R32F
D3DDECLTYPE_FLOAT4
D3DFMT_G16R16F
D3DDECLTYPE_FLOAT16_2
D3DFMT_A16B16G16R16F
D3DDECLTYPE_FLOAT16_4
D3DFMT_G16R16
D3DDECLTYPE_SHORT2
D3DDECLTYPE_SHORT2N
D3DDECLTYPE_USHORT2N
D3DFMT_A16B16G16R16
D3DDECLTYPE_SHORT4
D3DDECLTYPE_SHORT4N
D3DDECLTYPE_USHORT4N
D3DFMT_A8R8G8B8
D3DDECLTYPE_D3DCOLOR
D3DDECLTYPE_UBYTE4 (BGRA)
D3DDECLTYPE_UBYTE4N (BGRA)
Продвинутая интерпретация текстурных
данных
•Нет необходимости использовать 1:1
соответствие текселей к вершинам
•Пример 1
•2 пикселя на вершину – чередование
позиций и нормалей
Pos
Norm
Pos
Norm
... D3DFMT_A32B32G32R32F
D3DVERTEXELEMENT9 dwDecl[] = {
{0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0},
{0, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_NORMAL, 0},
{1, 0, /* ... other data */ },
D3DDECL_END()
};
Продвинутая интерпретация текстурных
данных
•Нет необходимости использовать 1:1
соответствие текселей к вершинам
•Пример 2
•1 пиксел на 4 вершины – одновременный
вывод значений для 4 вершин квада
Pixel 0 (FP32x4) Pixel 1 (FP32x4) ... D3DFMT_A32B32G32R32F
D3DVERTEXELEMENT9 dwDecl[] = {
{0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD0, 0},
{1, 0, /* ... other data */ },
D3DDECL_END()
};
Продвинутая интерпретация текстурных
данных
•Возможно даже интерпретировать текстуру
как другой тип данных
•Пример
•Чтение FP32 как 4 байта – например для
выявления «FP specials»
U8 U8 U8 U8
Pixel 0 (FP32)
Pixel 1 (FP32)
... D3DFMT_R32F
D3DVERTEXELEMENT9 dwDecl[] = {
{0, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD0, 0},
{1, 0, /* ... other data */ },
D3DDECL_END()
};
Создание R2VB текстур
•Создается как обычная текстура или
рендер-текстура
•Используется D3DUSAGE_DMAP флаг
dev->CreateTexture(width, height, 1,
D3DUSAGE_RENDERTARGET | D3DUSAGE_DMAP,
D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &d3drt, NULL);
•Текстура работает как обычно
«Улучшение» DX9 API
•Нет возможности подменить VB текстурой в
видео памяти через DX9 API
•IDirect3DVertexBuffer9 и IDirect3DTexture9 –
несовместимые интерфейсы API
•Реальные указатели на данные сокрыты в
глубине «runtime» и драйвера
•Единственные неиспользуемые текстуры
видимые вершинным процессором
•D3DDDMAPSAMPLER
• Доступен на всех ATI DX9 картах
•D3DVERTEXTEXTURESAMPLER[0..3]
• Доступны только он SM 3.0 картах
«Улучшение» DX9 API
•Стандартный вершинный конвеер
Stream 0
VB
…
Stream N
VB
Textures
DMAP
VS
VTF 0
…
VTF 3
«Улучшение» DX9 API
•Вершинный конвеер с R2VB
•Отображение данных из DMAP в поток 0
Stream 0
VB
…
Stream N
VB
Textures
DMAP
VS
VTF 0
…
VTF 3
Отображение текстур в потоки
•Не все потоки должны подменяться
•Можно перемешивать VB и текстуры
•Подмена указателей происходит в драйвере
•«Runtime» ничего об этом не знает
•Работает с отладочной версией «runtime»
•Инструкции о подмене посылаются
специальными R2VB маркерами через
D3DRS_POINTSIZE рендер-стейт
•Используется специальный диапазон
значений
Формат R2VB маркера
F
cmd
F
0 – disable/enable
1 – set mapping
F
data
F
0
F
F
0 – disable, 1 – enable
F
1
F
F
smp strm
Stream #
0 – override with DMAP sampler
1 – override with VTF0 sampler
2 – override with VTF1 sampler
3 – override with VTF2 sampler
4 – override with VTF3 sampler
5 – disable override
Вспомогательные функции
•Всё в файле atir2vb.h из ATI SDK
#define
#define
#define
#define
#define
#define
R2VB_VSMP_OVR_DMAP
R2VB_VSMP_OVR_VTX0
R2VB_VSMP_OVR_VTX1
R2VB_VSMP_OVR_VTX2
R2VB_VSMP_OVR_VTX3
R2VB_VSMP_OVR_DIS
0
1
2
3
4
5
DWORD r2vbGlbEnable_Set(BOOL ena);
DWORD r2vbVStrm2SmpMap_Set(DWORD str, DWORD smp);
Пример использования R2VB
•Поток 0 из VB, поток 1 из текстуры
// Enable render to vertex buffer extension
dev->SetRenderState(D3DRS_POINTSIZE, r2vbGlbEnable_Set(TRUE));
// Setup stream 0 – regular VB data
dev->SetStreamSource(0, staticVertexBuffer, 0, 2 * sizeof(float))
// Setup stream 1 – R2VB data
dev->SetTexture(D3DDMAPSAMPLER, renderTarget);
dev->SetRenderState(D3DRS_POINTSIZE,
r2vbVStrm2SmpMap_Set(1, R2VB_VSMP_OVR_DMAP));
// Setup stream 1 – dummy VB
dev->SetStreamSource(1, dummy, 0, 4 * sizeof(float))
// Draw ...
dev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, nVertices, 0, nPrimitives);
// Restore stream 1 to regular vertex buffer mode
dev->SetRenderState(D3DRS_POINTSIZE,
r2vbVStrm2SmpMap_Set(1, R2VB_VSMP_OVR_DIS));
dev->SetTexture(D3DDMAPSAMPLER, NULL);
// Disable render to vertex buffer extension
dev->SetRenderState(D3DRS_POINTSIZE, r2vbGlbEnable_Set(FALSE));
Особенности использования R2VB
•Необходимо задать подменяемый буфер с
помощью SetStreamSource
•При отладочной версией «runtime» должен
быть полного размера
•Для обычной версии «runtime» буфер может
быть любого размера (даже 1 байт)
•Сэмплер не может быть соединен больше
чем с одним потоком
•Предыдущее отображение будет отменено
•Не забудьте отключить отображение и
глобальное R2VB включение
«Хитрые» приёмы для SM 2.x
•Только одна текстура доступна на Radeon
9500-Х850
•VTF только для SM 3.0 карт
•Решение: чередование разных данных
(позиция, нормаль и т.д.)
•Вывод соответствующего значения пиксела
из пиксельного шейдера
•Отдельный проход чередующий данные
•Упаковка данных
«Хитрые» приёмы для SM 2.x
•Упаковка нормали в вектор позиции
•Используем .W для хранения
•Точность около 7 бит (используется мантисса
FP32 представления)
•Упаковка
•4 инструкции
pos.w = dot(floor(normal*127.5+127.5), float3(1/256.0,1,256.0));
•Распаковка
•3 инструкции
normal = frac(pos.w * float3(1,1/256.0,1/65536.0)) * 2 - 1;
Оптимизации R2VB
•Пользуйтесь параллельностью пиксельного
процессора
•Расчет и вывод 4-х скаляных значений как
один FP32x4 вектор
•Используйте наименьшие форматы текстур
•D3DFMT_A16B16G16R16(F) – 2 такта
•D3DFMT_A32B32G32R32F – 4 такта
•Используйте MRT для уменьшения кол-ва
проходов
Использование R2VB
•Модификация геометрии
•Карты смещения
•Генерация геометрии на GPU
•Тесселляция
•Физика на GPU
•IK, вода и т.д.
•Расчет сталкновений
•Сортировка частиц
•И многое другое...
Вопросы