2014-03-03 1 views
0

iMX53의 GPU (AMD Z430)가 디코딩 된 비디오 프레임을 YUV420P 형식으로 가져 와서 RGB565로 변환하여 표시하는 작업 체인이 있습니다. 내 유일한 관심사는 속도, 더 정확히는 속도 부족입니다. 입력 비디오 프레임은 1920x1088 YUV420P이고, 변환 시간은 40ms입니다. 더 빠르게 실행할 수는 없습니다. 나는 쉐이더를 최적화하려고 노력했다. 운이 없다. 나는 2D gamut을 사용해 보았는데, 더 느리다. (2D 특성으로 인해 색상이 약간 잘못되었다.) 물론 OpenGL ES 전문가는 아닙니다. 이미지는 eglCreateImageKHR (...)에 의해 할당 및 glEGLImageTargetTexture2DOES (...)에 의해 텍스처에 할당,iMX53에서 YUV420 대 RGB 변환 속도가 느린 이유는 무엇입니까?

static const char *fragment_shader_yuv_src = 
    "const lowp mat3 rgb_coeff = mat3(1, 1, 1, 0, -0.344, 1.772, 1.402, -0.714, 0);\n" 
    "varying lowp vec2 v_texcoord;\n" 
    "uniform lowp sampler2D s_texture_y;\n" 
    "uniform lowp sampler2D s_texture_u;\n" 
    "uniform lowp sampler2D s_texture_v;\n" 
    "\n" 
    "void main()\n" 
    "{\n" 
    " lowp vec3 yuv = vec3(texture2D(s_texture_y, v_texcoord).r, texture2D(s_texture_u, v_texcoord).r - 0.5, texture2D(s_texture_v, v_texcoord).r - 0.5);\n" 
    " gl_FragColor = vec4(rgb_coeff * yuv, 1.0);\n" 
    "}\n"; 

static const char *vertex_shader_yuv_src = 
    "attribute lowp vec4 position; \n" 
    "attribute lowp vec2 texcoord; \n" 
    "varying lowp vec2 v_texcoord; \n" 
    "        \n" 
    "void main()     \n" 
    "{        \n" 
    " gl_Position = position; \n" 
    " v_texcoord = texcoord.xy; \n" 
    "}        \n"; 

s_texture_y/U/V 적절한 색상 구성 요소를 포함 : 여기

내 쉐이더입니다.

위에서 언급 한 것처럼 작동하지만 느립니다. 이것이 GPU의 최대 성능인지 아니면 셰이더에서 매우 잘못된 것인지를 결정할 수 없습니다 ...

(단순한 셰이더를 사용한 단순한 416x416 RGBA32 이미지의 렌더링 및 렌더링 또한 매우 느립니다. , ~ 23ms)

아무도 아이디어, 경험? 셰이더를 최적화하려면 어떻게해야합니까?

답변

2

언뜻보기에 쉐이더는 성능면에서 그리 좋지 않습니다. (참고로 OpenGL과 OpenGL ES 모두에서 일반적인 변환이 쉐이더에서 수행되는 gst-plugins-gl 파일 glupload.c을 확인하십시오.

플랫폼 특성에 들어 가지 않아도 성능이 떨어지면 GPU에 업로드하는 데 따른 불이익이있을 수 있습니다. dummy fragment shader로 시도해 보셨습니까? 즉 :

void main (void) 
{ 
    gl_FragColor = vec4 (0.0, 1.0, 0.0, 1.0); 
} 

다른 해상도로 프레임을 업로드하는 중입니까? 제 생각에 작은 프레임이라 할지라도, 10,20ms의 큰 시간 벌금이 부과 될 것입니다. 왜냐하면 새로운 데이터를 주입하기 전에 진행중인 모든 계산을 완료하고 파이프 라인을 플러시해야하기 때문입니다 (즉, 업로드는 GPU 관점에서의 동기 동작).

페널티가 큰 경우 GPU에 이중 업로드 (this post 참조)를 사용하여 특정 드라이버 + 하드웨어가 개선되는지 확인할 수 있습니다.

마지막으로 쉐이더와 glupload.c에서 3 가지 텍스처 (각 채널에 하나씩 사용)와 CPU 코드에서 전달 된 유니폼 사용은 성능을 향상시키는 데 도움이되지 않습니다. 두 가지를 시도해 볼 수 있습니다. 하나는 YUV를 3 개 채널로 묶어 한 묶음의 데이터를 업로드 한 다음 출력 픽셀 대 yuv 좌표 로직을 쉐이더 자체로 가져 오는 것입니다 (예 :

).
void main (void) 
{ 
    vec2 y_coord = <calculate the position to find the Y component for this pixel> 
    vec2 u_coord = <calculate the position to find the U component for this pixel> 
    vec2 v_coord = <calculate the position to find the V component for this pixel> 
    float y_value = texture2D(s_texture, y_coord).<appropriate channel> 
    float u_value = texture2D(s_texture, u_coord).<appropriate channel> 
    float v_value = texture2D(s_texture, v_coord).<appropriate channel> 
    gl_FragColor = vec4 (rgb_coeff * vec3(y_value, u_value, v_value), 1.0); 
} 

업로드가 병목 현상이 아닌 경우이 셰이더를 추가로 시험해보고 개발할 수 있습니다.

+0

답변 해 주셔서 감사합니다. 더미 조각 셰이더를 사용해 보았는데 1920x1088의 렌더링 시간은 ~ 17ms입니다. 아주 천천히. 나는 메모리 대역폭이 충분하지 않다는 것을 두려워한다. iMX53에서 비슷한 경우를 본 적이있다. GPU는 단순히 DMA 가능 메모리에서 데이터를 충분히 빠르게 복사 할 수 없습니다 (이 시스템에서는 버퍼링되지 않고 캐시되지 않으므로 속도가 매우 느립니다). 그건 그렇고, 나는이 머신에서 glTexImage2D를 사용하지 않는다. 왜냐하면 매우 천천히 ... 텍스처가 eglCreateImageKHR 이미지에 저장되기 때문이다. – tselmeci

+0

그러면 이중 텍스처 솔루션은 어떻습니까? 두 개의 텍스처를 할당하고, 하나는 변환 용으로 사용하고 다른 하나는 업로드 용으로 사용하십시오. – miguelao

+0

음, 비디오 프레임은 이제 eglCreateImageKHR에 의해 할당 된 이미지로 직접 디코딩되므로 memcpy (...) 또는 비슷한 것을 전혀 수행하지 않습니다. GPU는이 바이트들을 메모리에 복사해야하는데, 나는 이걸 저장할 수 없다고 믿는다. – tselmeci

관련 문제