OSSCA Chromium

기여 목록 / 8424960

[webgl] Return null for invalid uniform queries

BlinkfixMerged

Chromium의 WebGL 2 API인 getUniformIndices()가 오류 상황에서 잘못된 반환값을 전달하는 문제를 수정하고, Khronos WebGL 테스트에 회귀 테스트를 추가했습니다.

문제 설명

getUniformIndices()는 정상 호출에서는 인덱스 배열을 반환하고, GL 오류가 발생하면 null을 반환해야 합니다. 하지만 기존 Chromium 구현은 program 검증에 실패했을 때 빈 배열을 반환했습니다.

  • 다른 context의 program이나 삭제된 program을 전달하면 오류 코드는 맞지만 반환값이 잘못됐습니다.
  • context가 손실된 경우에도 null 반환을 보장하지 못했습니다.
  • 정상적인 빈 입력의 결과인 []와 오류 결과인 null을 구분하는 테스트가 필요했습니다.

해결 내용

Chromium 반환값 수정

program 검증 실패 시 빈 결과 벡터 대신 std::nullopt를 반환하도록 변경했습니다.

함수의 반환 타입은 std::optional<Vector> 입니다. 따라서 빈 벡터를 반환하면 값이 존재하는 optional 이 되어 Javascript 에는 [] 로 전달됩니다. 명세가 요구하는 null을 반환하려면 값이 없는 optional인 std::nullopt를 반환해야 합니다.

std::optional<Vector<GLuint>> WebGL2RenderingContextBase::getUniformIndices(
    WebGLProgram* program,
    const Vector<String>& uniform_names) {
-  // TODO(https://crbug.com/1465002): This should return std::nullopt
-  // if there is an error.
-  Vector<GLuint> result;
   if (!ValidateWebGLProgramOrShader("getUniformIndices", program))
-    return result;
+    return std::nullopt;

  PointableStringArray uniform_strings(uniform_names);

+  Vector<GLuint> result;
   result.resize(uniform_names.size());
   ContextGL()->GetUniformIndices(ObjectOrZero(program), uniform_strings.size(),
                                    uniform_strings.data(), result.data());
   return result;
}
  • program 검증 실패 시 std::nullopt를 반환합니다.
  • 결과 벡터는 검증을 통과한 이후에 생성합니다.
  • 이번 변경으로 해결한 오류 반환 관련 TODO를 제거합니다.

이렇게 하면 다른 context의 program, 삭제된 program, 손실된 context에 대한 검증 실패는 null로 전달됩니다. 정상 program에 빈 이름 목록을 전달했을 때는 기존처럼 []를 반환합니다.

첫 WPT 테스트 작성

third_party/blink/web_tests/external/wpt/webgl/getUniformIndices.html 위치에 정상 호출과 오류 호출을 구분하기 위해 다섯 가지 시나리오를 작성했습니다.

  1. 정상 program에 빈 이름 목록 전달
  2. 정상 program에 존재하지 않는 uniform 이름 전달
  3. 다른 context에서 생성한 program 전달
  4. 삭제된 program 전달
  5. context 손실 후 호출

반환값뿐 아니라 다른 context의 program에서는 INVALID_OPERATION, 삭제된 program에서는 INVALID_VALUE가 발생하는지도 확인했습니다.

리뷰 후 Khronos WebGL 저장소로 이동

WebGL 의 경우 WPT 에 테스트를 작성하는것이 아니라, KhronosGroup/WebGL 저장소의 기존 테스트에 추가해야한다고 합니다.

실제로 이번 동작을 검사할 파일도 이미 존재하고 있었습니다. sdk/tests/conformance2/programs/get-uniform-indices.html

이에 따라 Chromium CL에서 새 WPT 파일을 제거하고, WebGL 저장소에 별도 브랜치를 만들어 기존 테스트를 확장했습니다. 기존 셰이더와 WebGLTestUtils 헬퍼를 재사용하고, 앞서 작성한 다섯 가지 시나리오를 해당 테스트 하네스에 맞게 옮겼습니다. (https://github.com/KhronosGroup/WebGL/pull/3794)

테스트 진행

WPT 테스트 진행과 WebGL 내 기존 존재 html 실행의 테스트 방식에는 차이가 있습니다.

  1. 기존 WPT 테스트를 진행
# 테스트 실행에 필요한 바이너리 빌드
autoninja -C out/Default blink_tests

# 추가한 WPT 테스트 실행
third_party/blink/tools/run_web_tests.py \
  -t Default \
  external/wpt/webgl/getUniformIndices.html
  • 테스트는 모두 통과
  1. WebGL 내 html 실행 테스트

테스트를 진행할 때, 현재 chrome 과 수정이 적용된 빌드된 chrome 2군데에서 각각 실행 검증이 필요했습니다.

  • 현재 chrome : 4개의 추가된 테스트 실패
  • 빌드된 chrome : 모두 패스

빌드 chrome 테스트는 원격으로 진행하였기에, 8000 포트를 허용한 뒤, 직접 get-uniform-indices.html 을 실행한 뒤, 결과를 확인했습니다.

배운 점

chrome 에는 여전히 제가 모르는 다양한 테스트 방식이 존재하고, 그렇기에 작은 코드를 수정하더라도 연관되었다 판단되는 테스트들을 놓치지 않고 검증해서 문제가 없음을 증명해야 겠다 생각하였습니다. 또한 webGL 의 경우 웹 표준을 다루고 있었음에도 WPT 로 관리되지 않았다는 점이 신기했습니다.

참고 자료