간단한 조건의 경우 분기가 전혀 발생하지 않습니다. GPU에는 조건부 이동 명령이있어 3 진 표현식과 간단한 if-else 문으로 직접 변환됩니다.
중첩 된 조건부 또는 여러 조건부 종속 작업이있는 경우 문제가 발생합니다. 그런 다음 GLSL 컴파일러가 모든 것을 cmoves로 변환 할만큼 똑똑한 지 여부를 고려해야합니다. 가능할 때마다 컴파일러는 모든 분기를 실행하고 결과를 조건부 이동과 재결합하는 코드를 방출하지만 항상 그렇게 할 수는 없습니다.
도움이 필요할 때가 있습니다. 측정 할 수있는 때를 절대 추측하지 마십시오. AMD의 GPU 쉐이더 분석기 또는 엔비디아의 GCG를 사용하여 어셈블리 출력을 봅니다. GPU의 명령어 세트는 매우 제한적이며 단순하므로 '어셈블리'라는 단어를 두려워하지 마십시오.
다음은 어셈블리 출력과 함께 AMD의 GLSL 컴파일러와 잘 어울리게 변경 한 RGB/HSL 변환 함수입니다. Paul Bourke는 원래의 C 전환 코드를 신용했습니다. 이 기능에 대한
// HSL range 0:1
vec4 convertRGBtoHSL(vec4 col)
{
float red = col.r;
float green = col.g;
float blue = col.b;
float minc = min3(col.r, col.g, col.b);
float maxc = max3(col.r, col.g, col.b);
float delta = maxc - minc;
float lum = (minc + maxc) * 0.5;
float sat = 0.0;
float hue = 0.0;
if (lum > 0.0 && lum < 1.0) {
float mul = (lum < 0.5) ? (lum) : (1.0-lum);
sat = delta/(mul * 2.0);
}
vec3 masks = vec3(
(maxc == red && maxc != green) ? 1.0 : 0.0,
(maxc == green && maxc != blue) ? 1.0 : 0.0,
(maxc == blue && maxc != red) ? 1.0 : 0.0
);
vec3 adds = vec3(
((green - blue)/delta),
2.0 + ((blue - red )/delta),
4.0 + ((red - green)/delta)
);
float deltaGtz = (delta > 0.0) ? 1.0 : 0.0;
hue += dot(adds, masks);
hue *= deltaGtz;
hue /= 6.0;
if (hue < 0.0)
hue += 1.0;
return vec4(hue, sat, lum, col.a);
}
조립 출력 :
이 1 x: MIN ____, R0.y, R0.z
y: ADD R127.y, -R0.x, R0.z
z: MAX ____, R0.y, R0.z
w: ADD R127.w, R0.x, -R0.y
t: ADD R127.x, R0.y, -R0.z
2 y: MAX R126.y, R0.x, PV1.z
w: MIN R126.w, R0.x, PV1.x
t: MOV R1.w, R0.w
3 x: ADD R125.x, -PV2.w, PV2.y
y: SETE_DX10 ____, R0.x, PV2.y
z: SETNE_DX10 ____, R0.y, PV2.y
w: SETE_DX10 ____, R0.y, PV2.y
t: SETNE_DX10 ____, R0.z, PV2.y
4 x: CNDE_INT R123.x, PV3.y, 0.0f, PV3.z
y: CNDE_INT R125.y, PV3.w, 0.0f, PS3
z: SETNE_DX10 ____, R0.x, R126.y
w: SETE_DX10 ____, R0.z, R126.y
t: RCP_e R125.w, PV3.x
5 x: MUL_e ____, PS4, R127.y
y: CNDE_INT R123.y, PV4.w, 0.0f, PV4.z
z: ADD/2 R127.z, R126.w, R126.y VEC_021
w: MUL_e ____, PS4, R127.w
t: CNDE_INT R126.x, PV4.x, 0.0f, 1065353216
6 x: MUL_e ____, R127.x, R125.w
y: CNDE_INT R123.y, R125.y, 0.0f, 1065353216
z: CNDE_INT R123.z, PV5.y, 0.0f, 1065353216
w: ADD ____, PV5.x, (0x40000000, 2.0f).y
t: ADD ____, PV5.w, (0x40800000, 4.0f).z
7 x: DOT4 ____, R126.x, PV6.x
y: DOT4 ____, PV6.y, PV6.w
z: DOT4 ____, PV6.z, PS6
w: DOT4 ____, (0x80000000, -0.0f).x, 0.0f
t: SETGT_DX10 R125.w, 0.5, R127.z
8 x: ADD R126.x, PV7.x, 0.0f
y: SETGT_DX10 ____, R127.z, 0.0f
z: ADD ____, -R127.z, 1.0f
w: SETGT_DX10 ____, R125.x, 0.0f
t: SETGT_DX10 ____, 1.0f, R127.z
9 x: CNDE_INT R127.x, PV8.y, 0.0f, PS8
y: CNDE_INT R123.y, R125.w, PV8.z, R127.z
z: CNDE_INT R123.z, PV8.w, 0.0f, 1065353216
t: MOV R1.z, R127.z
10 x: MOV*2 ____, PV9.y
w: MUL ____, PV9.z, R126.x
11 z: MUL_e R127.z, PV10.w, (0x3E2AAAAB, 0.1666666716f).x
t: RCP_e ____, PV10.x
12 x: ADD ____, PV11.z, 1.0f
y: SETGT_DX10 ____, 0.0f, PV11.z
z: MUL_e ____, R125.x, PS11
13 x: CNDE_INT R1.x, PV12.y, R127.z, PV12.x
y: CNDE_INT R1.y, R127.x, 0.0f, PV12.z
주의 (非) 분화의 지시가 없음. 조건부 동작은 내가 작성한 것과 거의 똑같습니다.
조건부 이동에 필요한 하드웨어는 이진 비교기 (비트 당 5 게이트)와 추적 모음입니다. 매우 빠릅니다.
재미있는 점은 나누기가 없다는 것입니다. 대신 컴파일러는 대략적인 역수 및 곱셈 명령을 사용했습니다. 그것은 많은 시간뿐만 아니라 sqrt 작업을 위해 이것을 수행합니다. SSE rcpps 및 rsqrtps 명령과 함께 동일한 트릭을 CPU에서 가져올 수 있습니다.
지금은 역 동작 :
// HSL [0:1] to RGB [0:1]
vec4 convertHSLtoRGB(vec4 col)
{
const float onethird = 1.0/3.0;
const float twothird = 2.0/3.0;
const float rcpsixth = 6.0;
float hue = col.x;
float sat = col.y;
float lum = col.z;
vec3 xt = vec3(
rcpsixth * (hue - twothird),
0.0,
rcpsixth * (1.0 - hue)
);
if (hue < twothird) {
xt.r = 0.0;
xt.g = rcpsixth * (twothird - hue);
xt.b = rcpsixth * (hue - onethird);
}
if (hue < onethird) {
xt.r = rcpsixth * (onethird - hue);
xt.g = rcpsixth * hue;
xt.b = 0.0;
}
xt = min(xt, 1.0);
float sat2 = 2.0 * sat;
float satinv = 1.0 - sat;
float luminv = 1.0 - lum;
float lum2m1 = (2.0 * lum) - 1.0;
vec3 ct = (sat2 * xt) + satinv;
vec3 rgb;
if (lum >= 0.5)
rgb = (luminv * ct) + lum2m1;
else rgb = lum * ct;
return vec4(rgb, col.a);
}
(편집/2013 년 7 월/05 :. orignally이 기능을 번역 할 때 내가 실수를 조립도 업데이트되었습니다).
조립 출력 :
1 x: ADD ____, -R2.x, 1.0f
y: ADD ____, R2.x, (0xBF2AAAAB, -0.6666666865f).x
z: ADD R0.z, -R2.x, (0x3F2AAAAB, 0.6666666865f).y
w: ADD R0.w, R2.x, (0xBEAAAAAB, -0.3333333433f).z
2 x: SETGT_DX10 R0.x, (0x3F2AAAAB, 0.6666666865f).x, R2.x
y: MUL R0.y, PV2.x, (0x40C00000, 6.0f).y
z: MOV R1.z, 0.0f
w: MUL R1.w, PV2.y, (0x40C00000, 6.0f).y
3 x: MUL ____, R0.w, (0x40C00000, 6.0f).x
y: MUL ____, R0.z, (0x40C00000, 6.0f).x
z: ADD R0.z, -R2.x, (0x3EAAAAAB, 0.3333333433f).y
w: MOV ____, 0.0f
4 x: CNDE_INT R0.x, R0.x, R0.y, PV4.x
y: CNDE_INT R0.y, R0.x, R1.z, PV4.y
z: CNDE_INT R1.z, R0.x, R1.w, PV4.w
w: SETGT_DX10 R1.w, (0x3EAAAAAB, 0.3333333433f).x, R2.x
5 x: MUL ____, R2.x, (0x40C00000, 6.0f).x
y: MUL ____, R0.z, (0x40C00000, 6.0f).x
z: ADD R0.z, -R2.y, 1.0f
w: MOV ____, 0.0f
6 x: CNDE_INT R127.x, R1.w, R0.x, PV6.w
y: CNDE_INT R127.y, R1.w, R0.y, PV6.x
z: CNDE_INT R127.z, R1.w, R1.z, PV6.y
w: ADD R1.w, -R2.z, 1.0f
7 x: MULADD R0.x, R2.z, (0x40000000, 2.0f).x, -1.0f
y: MIN*2 ____, PV7.x, 1.0f
z: MIN*2 ____, PV7.y, 1.0f
w: MIN*2 ____, PV7.z, 1.0f
8 x: MULADD R1.x, PV8.z, R2.y, R0.z
y: MULADD R127.y, PV8.w, R2.y, R0.z
z: SETGE_DX10 R1.z, R2.z, 0.5
w: MULADD R0.w, PV8.y, R2.y, R0.z
9 x: MULADD R0.x, R1.w, PV9.x, R0.x
y: MULADD R0.y, R1.w, PV9.y, R0.x
z: MUL R0.z, R2.z, PV9.y
w: MULADD R1.w, R1.w, PV9.w, R0.x
10 x: MUL ____, R2.z, R0.w
y: MUL ____, R2.z, R1.x
w: MOV R2.w, R2.w
11 x: CNDE_INT R2.x, R1.z, R0.z, R0.y
y: CNDE_INT R2.y, R1.z, PV11.y, R0.x
z: CNDE_INT R2.z, R1.z, PV11.x, R1.w
다시 없는 지점. 얌!
위대한 답변, 그러나 나는 여전히 색상 변경과 관련하여 "유사한"비슷한 방법을 확신하지 못합니다. – ronag
색조 문제에 대한 설명이 추가되었습니다. – Virne