gsl минус в swizzling

Может шизлинг в GLSL как-то с минусом? Например: vec.-yx-wz
Целью этого является получение нормали 2D с помощью простого определения:

#DEFINE NORMALE_PACK(v) (v).-yx-wz
#DEFINE NORMALE_1(v) dir.-yx
#DEFINE NORMALE_2(v) vec.-wz

void main(){
... 
float l = dot( NORMALE_PACK(dir), dir2);
}

без этого я достигаю этого с помощью:

void main(){
... 
vec4 normale = vec4(-dir.y, dir.x, -dir.w, dir.z);      // +1 cycle on modern hardware, more - on older
float l = dot( normale, dir2);
}

person tower120    schedule 31.03.2014    source источник


Ответы (1)


+1 цикл по сравнению с чем? Есть ли у вас другой вариант работы, который представляет собой только одну инструкцию и не требует дополнительных накладных расходов?

Ни один язык ассемблера шейдеров, который я видел, не может выполнять отрицание для каждого компонента. То, что вы описали, - это два swizzled movs (один из которых с префиксом отрицания), например

MOV result.position.xz, -vertex.position.yyww;
MOV result.position.yw, vertex.position.xxzz;

Вы можете сократить его до одной инструкции, используя что-то вроде vec4 n = vec4(dir.yxwz) * vec4(-1.0, 1.0, -1.0, 1.0). Это было бы так:

PARAM c[1] = { { -1, 1 } };
MUL result.position, vertex.position.yxwz, c[0].xyxy;

(в обоих случаях я использовал result.position и vertex.position из вершинной программы ARB просто в качестве примера).

Но он использует дополнительный постоянный регистр, так что это не обязательно лучше.

Конечно, обе версии можно было бы завернуть в макрос.

обновить

Теперь я вижу, что вы хотели сделать. Что-то, что генерирует код вроде (для последней версии AMD):

  0  x: DOT4        R0.x, -R0.y,  R1.x      
     y: DOT4        ____,  R0.x,  R1.y      
     z: DOT4        ____, -R0.w,  R1.z      
     w: DOT4        ____,  R0.z,  R1.w 

Вместо этого вы видите дополнительные MOV. Однако это не похоже на корректный код (я не думаю, что DOT может принимать аргументы с частичным отрицанием. Не могу сказать больше, не прочитав внимательно руководство по эксплуатации), поэтому компилятор добавляет дополнительный MOV (что не обязательно приводит к дополнительному циклу). , кстати - зависит от других инструкций рядом).

person keltar    schedule 31.03.2014
comment
+1 цикл по сравнению с чем? - Не сравнивается - эта инструкция занимает всего 1 такт (в лучшем случае, согласно анализатору шейдеров AMD). С определением рабочего решения вообще не будет накладных расходов. - person tower120; 31.03.2014
comment
И похоже, что AMD может выполнять согласование для каждого компонента. Если я правильно понимаю z: MOV R0.z, R1.z w: MOV R1.w, -R1.w t: MOV R1.y, -R1.y Это из сборки HD2900 (от анализатора шейдеров AMD) - person tower120; 31.03.2014
comment
Возможно, у них нет сборочного представительства, и я не читал их последнюю инструкцию по эксплуатации. Но я не получаю того, что вы хотите - сделать стоимость назначения 0 циклов? Не случится, любая операция чего-то стоит. 1 уже очень хорошо (как во втором моем примере). - person keltar; 31.03.2014
comment
Даже шипеть? Без переопределения в другое значение? Посмотрите на мой не сработавший 1-й пример :) - person tower120; 31.03.2014
comment
Нет, выпивка практически ничего не стоит, но это не обучение. Назначить (mov), однако, является инструкцией и стоит как минимум один цикл (если не в комплекте с другими совместимыми инструкциями - в этом случае они будут выполняться параллельно, но все же потреблять как минимум один цикл вместе). - person keltar; 31.03.2014