2018년 4월 18일 수요일

5.4 어토믹 카운터


  1. 여러 쉐이더에서 공유되는 특별한 변수 타입
  2. 버퍼 객체에 의해 채워진다.
  3. 버퍼에 저장된 값을 증가시키거나 감소시키며, Atomic 한 특징이 있다.
  4. 쉐이더에서 동시에 호출하는 경우 Atomic은 보장되지만, 연산이 수행되는 순서는 보장되지 않으므로 특정 값을 받을 것이라고 기대하면 안된다.
  5. 버퍼 바인딩 인덱스 및 버퍼 내 오프셋은 binding 및 offset 레이아웃 지시어로 설정할 수 있다.
  6. 선언
    1. layout (binding = 3, offset = 8) uniform atomic_unit my_variable;
      1. binding: 어토믹 카운터 바인딩 포인트
      2. offset: 버퍼 내 오프셋

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "OpenGL.h"
 
#ifdef EX5_20
 
GLuint program;
GLuint buffer;
 
int getWindowWidth()
{
    return 800;
}
 
int getWindowHeight()
{
    return 600;
}
 
void onAwake()
{
    static const char * vs_source[] =
    {
        "#version 430 core                                                  \n"
        "                                                                   \n"
        "layout (binding = 0) uniform area_block                            \n"
        "{                                                                  \n"
        "    uint counter_value;                                            \n"
        "};                                                                 \n"
        "                                                                   \n"
        "out vec4 color;                                                    \n"
        "                                                                   \n"
        "uniform float max_area;                                            \n"
        "                                                                   \n"
        "void main(void)                                                    \n"
        "{                                                                  \n"
        "    float brightness = clamp(float(counter_value) / max_area,      \n"
        "                       0.0, 1.0);                                  \n"
        "    color = vec4(brightness, brightness, brightness, 1.0);         \n"
        "}                                                                  \n"
    };
 
    static const char * fs_source[] =
    {
        "#version 430 core                                                  \n"
        "                                                                   \n"
        "layout (binding = 0, offset = 0) uniform atomic_uint area;         \n"
        "                                                                   \n"
        "void main(void)                                                    \n"
        "{                                                                  \n"
        "    atomicCounterIncrement(area);                                  \n"
        "}                                                                  \n"
    };
 
    program = glCreateProgram();
    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fs, 1, fs_source, NULL);
    glCompileShader(fs);
 
    GLuint vs = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vs, 1, vs_source, NULL);
    glCompileShader(vs);
 
    CheckShaderCompileError(fs);
    CheckShaderCompileError(vs);
 
    glAttachShader(program, vs);
    glAttachShader(program, fs);
 
    glLinkProgram(program);
 
    glGenBuffers(1&buffer);
 
    glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer);
    glBufferData(GL_ATOMIC_COUNTER_BUFFER, 16 * sizeof(GLuint), NULL, GL_DYNAMIC_COPY);
 
    glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 3, buffer);
 
    const GLuint zero = 0;
    glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer);
 
    // 방법 1 - glBufferSubData를 사용하여 어토믹 카운터를 리셋한다.
    glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 2 * sizeof(GLuint), sizeof(GLuint), &zero);
 
    // 방법 2 - 버퍼를 매핑하여 직접 값을 쓴다
    //GLuint *data = (GLuint *)glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 16 * sizeof(GLuint), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
    //data[2] = 0;
    //glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
 
    //// 방법 3 - glCelarBufferSubData를 사용한다.
    //glClearBufferSubData(GL_ATOMIC_COUNTER_BUFFER,
    //    GL_R32UI,
    //    2 * sizeof(GLuint),
    //    sizeof(GLuint),
    //    GL_RED_INTEGER, GL_UNSIGNED_INT, &zero);
}
 
 
 
void onUpdate(double current_time)
{
}
 
void onShutdown()
{
    glDeleteProgram(program);
    glDeleteBuffers(1&buffer);
}
 
#endif
cs

댓글 없음:

댓글 쓰기