могут ли несколько шейдеров с разными типами ввода вершин использовать один и тот же буфер вершин?

Допустим, у меня есть модель. Эта модель имеет данные о положении, цвете, нормалях и двух координатах текстуры. Теперь предположим, что у меня есть шейдер, который вводит только положение и цвет. Однако буфер вершин этой модели имеет формат:

struct Vertex_PCNT2
{
    D3DXVECTOR3 position;
    D3DXVECTOR4 color;
    D3DXVECTOR3 normal;
    D3DXVECTOR2 tex1;
    D3DXVECTOR2 tex2;
};

Несмотря на то, что в этой модели есть информация для шейдера, который принимает позицию и цвет, я не могу ее использовать, потому что есть лишние данные. Единственное другое решение, которое я могу придумать, - это иметь несколько буферов вершин с одинаковой информацией за вычетом пары полей, но это просто избыточно. Серьезно, должен быть лучший способ. Любая помощь здесь?

edit: Решил немного уточнить свой вопрос за некоторое время до работы. Говоря о буфере вершин, я имею в виду ID3D11Buffer *, который вы создаете с помощью ID3D11Device::CreateBuffer. Перед этим я заполнил массив вершин типом Vertex_PCNT2. Из того, что я могу сказать на данный момент, этот буфер теперь постоянно находится в этом формате, поэтому все шейдеры должны работать с этим форматом. Настройка других буферов будет просто нагрузкой на оперативную память, когда данные уже существуют.


person FatalCatharsis    schedule 11.07.2012    source источник
comment
Вы пытались просто не объявлять или использовать другой атрибут в своем вершинном шейдере? Вам не нужно использовать данные только потому, что они есть.   -  person John Calsbeek    schedule 11.07.2012
comment
не замедлит ли это шейдер передавать большие вершины, чем это необходимо? Я знаю, что эти дополнительные данные не будут использоваться ни для чего, но могу ли я где-то сэкономить несколько байтов или скорость, не передавая всю вершину целиком?   -  person FatalCatharsis    schedule 11.07.2012
comment
Неа! Все снижение производительности, которое вы получаете, связано, прежде всего, с наличием данных в буфере вершин. Шейдеры не будут загружаться и передавать данные, если вы их не используете.   -  person John Calsbeek    schedule 12.07.2012
comment
Итак, подождите, я должен просто дать всем шейдерам, которые я пишу, самый большой тип ввода вершин, который они когда-либо использовали, и просто выбрать данные, которые им нужны? производительность не упала?   -  person FatalCatharsis    schedule 12.07.2012
comment
что я имею в виду, скажем, у меня есть шейдер, который действительно использует только положение и цвет, или шейдер, который использует только нормали и положение, должен ли я просто сделать все типы ввода вершин моих шейдеров самыми большими типами ввода, за исключением специальности для специальных моделей с другим типом вершин?   -  person FatalCatharsis    schedule 12.07.2012
comment
Объявление вершины сообщает графической карте, как вершина размещена в памяти. Это не команда, говорящая использовать все эти фрагменты данных. Думайте об этом как о массиве структур — вы не стали бы изобретать новый тип и приводить к нему свой массив только потому, что вы передаете его функции, которая не использует каждый элемент структуры.   -  person John Calsbeek    schedule 12.07.2012
comment
Истинный. но, по крайней мере, я бы удостоверился, что эти массивы передаются по ссылке, чтобы избежать их копирования. Копируется ли весь буфер вершин в оперативную память перед операцией шейдера, копируется ли каждая вершина и освобождается при каждом вызове функции, или данные каким-то образом просто ссылаются в системной оперативной памяти? Если это первое, то снижение производительности будет связано с использованием VRAM. Почти в два раза больше фактически необходимых данных по-прежнему копируется в оперативную память (не то чтобы виртуальная память в наши дни действительно дефицитна). мне просто любопытно, есть ли более эффективный метод памяти (или если один из двух других верен).   -  person FatalCatharsis    schedule 12.07.2012
comment
Буферы вершин всегда находятся в VRAM. VRAM существует потому, что передача больших объемов данных туда и обратно происходит медленно. Таким образом, если у вас уже есть данные в VRAM, повторное обращение к ним не повлияет на производительность или память.   -  person John Calsbeek    schedule 13.07.2012
comment
Подождать? Итак, когда я вызываю ID3D11Device::CreateBuffer, все эти вершины сразу же сохраняются в vram? Вау, это немного меняет то, как я смотрю на все сейчас. И тогда вы правы, больше не будет попаданий в память при вызове шейдера, а не при его инициализации. Спасибо за помощь. нет ответов, чтобы принять, я думаю, но я думаю, что могу +1 вам   -  person FatalCatharsis    schedule 13.07.2012


Ответы (1)


Обычно это делается путем создания разных InputLayout для одного и того же буфера вершин. Помните, что InputLayout может действовать как отфильтрованное представление между входными данными вершины и ожидаемым вводом вершинного шейдера.

InputLayout точно создан для такого сценария. По сути, это разделение макета исходных данных и макета привязки к входным данным вершинного шейдера.

Например, если вам нужно только сопоставить положение и цвет, вам просто нужно создать макет ввода с массивом из двух D3D11_INPUT_ELEMENT_DESC с правильным набором AlignedByteOffset.

В случае выбора только "POSITION" (смещение 0) и "COLOR" (смещение в байтах: 12):

D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR"   , 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
}; 

но вы также можете выбрать только «POSITION» (смещение 0) и «NORMAL» (смещение 28):

D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL"  , 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },
}; 
person xoofx    schedule 30.08.2012