2018년 4월 11일 수요일

5.3 쉐이더 스토리지 블록


  1. 쉐이더 스토리지 블록
    1. 유니폼 블록과 쉐이더 스토리지 블록의 차이점
      1. 쉐이더가 쉐이더 스토리지 블록에 쓸 수 있다.
      2. 쉐이더 스토리지 공간의 멤버에 대해 어토믹 연산을 수행할 수 있다.
      3. 쉐이더 스토리지 블록은 크기 제한값이 훨씬 더 크다.
      4. std430의 새로운 패킹 규칙을 통해 데이터가 유니폼 블록보다 더 효율적으로 패킹되며 더 직접적인 접근이 가능하다.
    2. 사용
      1. 유니폼 블록을 선언하듯이 쉐이더에서 블록을 선언하면 된다.
        단, uniform 키워드 대신 buffer 키워드 사용.
      2. std140 뿐만 아니라 std430 패킹 레이아웃도 지원한다.
        1. 패킹 레이아웃 이름은 쉐이딩 언어 버전을 따라 지어졌다. std140은 GLSL1.40(OpenGL 3.1), std430은 GLSL 4.30(OpenGL 4.3)
      3. Example
        1. #version 430 core

        2. struct my_structure
        3. {
        4.   int pea;
        5.   int carrot;
        6.   vec4 potato;
        7. };

        8. layout (binding = 0, std430) buffer my_storage_block
        9. {
        10.   vec4 foo;
        11.   vec3 bar;
        12.   int baz[24];
        13.   my_structure veggies;
        14. };
    3. glBufferData를 사용하여 버퍼에 데이터를 전달 할 수 있다.
    4. glMapBuffer를 GL_READ_ONLY로 사용하여 쉐이더에서 생산한 데이터를 읽을 수 있다.
    5. 버텍스 속성 대신 쉐이더 스토리지 블록 사용
      1. #version 430 core

      2. struct vertex
      3. {
      4.   vec4 position;
      5.   vec3 color;
      6. };

      7. layout (binding = 0, std430) buffer my_vertices
      8. {
      9.   vertex vertices[];
      10. };

      11. uniform mat4 transform_matrix;

      12. out VS_OUT
      13. {
      14. vec3 color;
      15. };

      16. void main(void)
      17. {
      18.   gl_Position = transform_matrix * vertices[gl_VertexID].position;
      19.   vs_out.color = vertices[gl_VertexID].color;
      20. }
    6. 유니폼 블록이나 버텍스 속성에 비해 최적화가 어려움.
  2. 어토믹 메모리 연산
    1. 메모리 읽기와 쓰기 중간에 인터럽트가 일어나지 않아 결과가 보장되는 것
    2. 같은 메모리 위치의 값을 동시에 접근하여 수정하면서 충돌이 발생함.
    3. 어토믹 메모리 함수
      1. int atomicAdd(inout int mem,
         int data);
         
        uint atomicAdd(inout uint mem,
         uint data);
        1. mem을 읽어 data에 더한다. 결과를 mem에 쓰고, 원래 mem에 저장되어 있던 값을 리턴한다.
      2. atomicAnd, atomicOr, atomicXor 등
      3. 리턴형이 int와 unit가 있다.
      4. 어토믹 연산이 동일 위치에 동시에 발생하는 경우 각 호출은 직렬화 됨.
    4. 메모리 관련 문제
      1. RAW(Read-After-Write): 메모리에 쓴 다음 읽기를 시도하는 경우, 시스템에서 순서가 조정되어 쓰기가 완료되기 전에 읽기를 수행하는 경우.
      2. WAW(Write-After-Write): 쓰는 도중에 쓰는 경우
      3. WAR(Write-After-Read): 병렬 처리 시스템에서 다른 쓰레드간 동일 위치에 쓰기를 수행하는 경우.
    5. OpenGL의 병렬성 때문에 메모리 문제를 피하기 위한 여러가지 방법이 필요하다.
    6. 메모리 베리어(Memory Barrier)
      1. void glMemoryBarrier(GLbitfield barriers);
        1. GL_ALL_BARRIER_BITS
          1. 모든 메모리 연산 순서를 동기화
        2. GL_SHADER_STORAGE_BARRIER_BIT
          1. 다음 쉐이더가 데이터를 액세스 하기 전에 이전 접근(쓰기)를 완료하도록 함.
          2. 베리어 이후에 실행하는 쉐이더는 쓰기 동작이 완료된 후의 데이터를 보게 됨.
        3. GL_UNIFORM_BARRIER_BIT
          1. 데이터를 쓴 메모리가 베리어 이후에 유니폼 버퍼로 사용되는 경우, 쓰기가 완료 될 때 까지 기다렸다가 유니폼 버퍼를 사용하도록 함.
        4. GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT
          1. 버텍스 속성을 통해 버텍스 데이터로 버퍼를 사용하기 전에 버퍼 쓰기 작업을 완료하도록 함.
      2. GLSL
        1. uint memoryBarrier(void);
          1. 쉐이더 내에서 호출 시 기존에 수행했던 메모리 읽기/쓰기 동작을 완료시킴.

댓글 없음:

댓글 쓰기