개발 노트 [Vulkan 일지] DescriptorSets 2017/02/22 02:38 by cagetu

Shader를 생성하고, 셰이더의 Descriptor (변수)를 c++에서 선언하고 값을 연동하기 위해서 Descriptor에 대한 설정 시리즈를 진행하고 있다. DescriptorPool, DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSets...

결국 Shader에 맞는 DescriptorSets을 만들기 위함이다... 하악~~~

이 부분은 거의 언리얼4의 코드를 보면서 따라했다. 정확히 개념이 오지도 않고, 샘플코드를 보아도 말 그대로 "돌아가는 것을 보여주는 코드"일 뿐이라 별로 도움도 안되고 원하는 결과를 얻기도 어려워서 그냥 시원~하게 보면서 따라가고 있다. 

생각해보면, 항상 집에서 작업할 때 오픈소스를 많이 참고했었는데, Orge3D, irright, nebula2/3 에 영향을 참 많이 받았고, 보면서 정말 많은 것들을 배웠었다. 오픈소스가 거의 없어지고 이제는 언리얼4가 가장 잘 되어 있는 오픈소스가 되다보니 많이 보게 된다. (물론 회사에서도 보지만...)

이제 DescriptorSets에 값을 채워서 업데이트 해줘야 하는데, UniformBuffer를 할당하고 값을 채워서 그 버퍼를 UpdateDescriptorSet을 통해서 업데이트 해주면 될 것 같다.

Uniform Buffer를 잘 사용하려면 슬슬 메모리 관리 부분도 생각을 해야 할 것 같고, 이전에 이야기한 것처럼 memory 정렬도 잘 생각해야 할 것 같다.

DirectX11/12 개발자 모임 사이트인데, 어차피 DX12나 Vulkan이나 흐름이나 이슈가 거의 동일하다고 생각되니, 여기서 정보를 많이 얻도록 하자! 어차피 해본 사람은 영천님이나 포프님 밖에 없으니 물어보는 수 밖에 ㅎㅎ

아~ 언제가 되면 삼각형을 그려볼 수 있을 것인가... 쿠쿠쿠!! ㅠㅠ;;

나도 API 공부 마무리하고, 그래픽스 Feature들 하나씩 만들어보고 싶은데.. 흐규~ 흐규~

개발 노트 [Vulkan 일지] Uniform Buffer 연구 중 2017/02/17 02:30 by cagetu

Uniform Buffer를 처음 사용해보는 것이라서 조심스럽게 차근 차근 접근해가고 있다. 특히, DevU Seoul Case Study 강연을 다시 보니, uniform buffer 내에 버퍼 offset 을 잘 처리해야 한다고 나와 있어서 타입과 offset, size를 glsl -> spirv로 변환해보고 어떻게 처리되나 비교해보고 있다.

당연히 코드 상으로 구현 할 때에는 셰이더가 어떻게 작성되든 셰이더 변수와 c++에서 바인딩이 자동으로 하게 해주고 싶기 때문에, shader에 선언된 내용을 얻어올 수 없을까? 라는 생각을 해보게 된다. 이전에 소개한 것처럼 이 부분은 spriv_cross 라는 라이브러리가 담당할 수 있는데 좀 더 사용법을 연구해보니 다음과 같이 정보를 수집할 수 있게 되었다.

[셰이더]

/// UNIFORM
layout (binding=0) uniform TRANSFORMS
{
mat4 WORLDVIEWPROJECTION; // offset: 0
mat4 VIEWPROJECTION;
mat4 WORLD;
mat3 WORLDROTATION;
mat4 TMARRAY[10];
} tm;

[c++]
m_UniformBuffers[i].name = res.name;
m_UniformBuffers[i].binding = compiler.get_decoration(res.id, spv::DecorationBinding);
m_UniformBuffers[i].set = compiler.get_decoration(res.id, spv::DecorationDescriptorSet);

const spirv_cross::SPIRType& structType = compiler.get_type(res.base_type_id);
_ASSERT(structType.basetype == spirv_cross::SPIRType::Struct);

for (uint32 index = 0; index < structType.member_types.size(); index++)
{
std::string name = compiler.get_member_name(res.base_type_id, index);
uint32 offset = compiler.get_member_decoration(res.base_type_id, index, spv::DecorationOffset);
uint32 size = compiler.get_declared_struct_member_size(structType, index);

const spirv_cross::SPIRType& memberType = compiler.get_type(structType.member_types[index]);
memberType.basetype // Float, Sampler, ...
memberType.vecsize // vec2, vec3, vec3
memberType.columns // mat3, mat4
memberType.array // array

...
}

Shader Memory Alignment를 잘 설정해야 하는데 일단 이렇게 정보를 얻어올 수 있으니 연결하는데 도움이 많이 될 듯... 


개발 노트 [Vulkan 일지] Vulkan Shader Descriptor 2017/02/14 01:43 by cagetu

셰이더의 변수를 C++에서 연동하기 위해서 Vulkan에서는 Descriptor를 이용해야 하는데, DescriptorPool, DescriptorSetLayout, DescriptorSets를 정의해서 값을 채워야 한다. 

api를 설정하는 것도 중요하지만, 어떻게 사용하는 것이 효과적인지를 익혀야 하는데, 아직은 정보가 많이 없어서 진도가 더디게 나가고 있다. 

1. DescriptorPool은 어떻게 사용하고 관리해야 하는가?
2. DesscriptorSet은 어떻게 관리하고 데이터를 업데이트 해야 하는가?

아~ 놔... 이번 주는 이것만 봐야겠다.. ;;;;

[TODO]

* DescriptorPool을 언리얼을 보니까 하나만 생성하는 것이 아닌 것 같은데, 왜 일까?? 
  (효율적으로 하기 위해서 Descriptor Pool을 일하고 있을 때에 기다리지 말고 생성하라고 본 것 같은데 기억이. ;;;;; 이것도 찾아서 정리하자!)
* DescriptorSet을 어떻게 생성하고 관리할 것인가?
  (DescriptorSetLayout과 DescriptorSet을 1:1 만들어서 커멘트버퍼에 등록하는 것이 좋은가? 셰이더의 모든 DescriptorSetLayout을 DescriptorSet에 모두 추가해서 생성해서 사용하는 것이 좋은가? 변경 빈도에 대한 이슈...)
* DescriptorSet에 c++에서 셰이더 변수 값을 어떻게 업데이트 시켜줄 것인가? 
   (한번에 많이 업데이트 하는 것이 좋은지, 자잘하게 올리는 것인 좋은가?)
* 이를 위해서 효율적으로 Shader 변수 값들을 어떻게 관리할 것 인가?
* UniformBuffer를 사용해본 적이 없으니, UniformBuffer를 다루는 방법을 좀 더 공부하자!! 
   (UniformBuffer를 최대한 업데이트 빈도를 줄여야 하나? 자주 해도 되나?)
https://developer.nvidia.com/vulkan-shader-resource-binding 이 문서 형태로 만드는 것을 목표로 하자!!!

개발 노트 [Vulkan 일지] Vulkan Shader Cont' 2017/02/10 02:24 by cagetu

1. Shade에 버텍스 정보 연결

Shader에서 Vertex 정보를 얻어와서 C++에서 버텍스 구조체 정보와 버텍스 버퍼를 연결해줘야 한다. DirectX에서 사용하는 용어로 보면 VertexDeclaration과 VertexBuffer를 설정해줘야 하는 것이다.

VertexDeclaration
   |- VertexElemenent (Position, Bind VertexBuffer = 0)
   |- VertexElemenent (Texcoord, Bind VertexBuffer = 0)
   |- VertexElemenent (Color, Bind VertexBuffer = 1)

구조적으로 보면 위에 처럼 여러 개의 버텍스 버퍼가 연결되고, 각 버텍스 버퍼에 어떻게 버텍스들이 구성되어 있는지를 선언해주는 것이다. 이렇게 셰이더 - 메쉬 정보 (버텍스 버퍼)와 연결하도록 만들어주면 되는데, VertexDeclaration 작성하는데 생각을 많이 했다. 아직은 정리를 더 해야 하는데, 진행하면서 정리하도록 해보자!

2. Shader 변수 정보 연결

Uniform 버퍼를 연결해야 하기 때문에, UniformBuffer 클래스를 만들어줘야 하고, UniformBuffer를 셰이더의 정보와 연결하기 위해서는 DescriptorSet이라는 Vulkan 구조체를 만들어서 연결해 줘야 한다. 아직 진행 중인데, 개념적으로 이해가 조금 더 필요할 것 같다.

당분간 이렇게 셰이더 연결하는 작업을 계속 할 듯... 아~ 할 게 많다... 지금 엔진 만드는 것도 아니고, 그냥 렌더 디바이스 모듈인데도.. 젠장.. ㅎㅎㅎㅎ.. 그래도 재미는 있디~

개발 노트 Shader Compiler 2017/02/08 02:31 by cagetu

이전에 언리얼이나 유니티에서 사용하는 셰이더 컴파일 방식에 대해서는 몇 번 소개를 했었다. 이번에 Vulkan 만들어보면서 그 동안 공부했던 것을 바탕으로 OpenGLES에서도 문제가 되었던 것을 포함해서 나름 셰이더 컴파일러(?)를 구성해보았다.

쉽게 구분하기 위해서, 셰이더를 작성하는 부분을 프론트엔드라고 하고, 셰이더를 컴파일해서 셰이더를 뽑아주는 부분을 백엔드라고 하자. 

프론트엔드는 언리얼의 머터리얼 셰이더나, 유니티의 Unity Shader 같은 것이다. 나는 그냥 #if ~ #endif 방식의 UberShader를 이용해서 셰이더를 작성한다.

백엔드처리는 OpenGLES와 Vulkan은 약간 다르게 구성했다.

#OpenGLES

OpenGLES를 사용했을 때 가장 불편한 점은 기기에서 바이너리 셰이더를 사용할 수 없었기 때문에, glCompileShader를 했을 때에만 조합에 따른 셰이더를 만들어낼 수 있었다. 따라서 새로운 셰이더를 만났을 때에는 멈춤(hitch)현상이 발생할 수 있었다. (언리얼3도 이런 방식이라 가상으로 초반에 셰이더를 모두 미리 한번 렌더링했었던 것으로 기억한다)

그래서, glsloptimizer라는 라이브러리를 이용해서 미리 컴파일해서 셰이더를 뽑아놓고, 뽑아 놓은 셰이더를 Cache 해두면 실행 시간에 컴파일 하던 것을 사전에 할 수 있게 된다. 즉, glsl file -> glsloptimizer -> cached glsl file -> shader loading 형태로 진행이 된다.

#Vulkan

Vulkan은 spir-v를 사용하기 위해서는 glsl -> spir-v로 변환해줘야 한다. 이를 위해 glslangvalidator.exe 라는 프로그램이 있지만, 문제는 이 녀석으로 오프라인 변환을 하게 된다면, #define를 붙여서 조합 셰이더를 사용할 수 없게 된다. 따라서, 내부적으로 컴파일 할 때, #define을 붙여서 glsl -> spir-v로 만들어줘야 하는데, 이 역할을 해주는 라이브러리가 바로 google/shaderc 라는 라이브러리다. 이것을 통해서 glsl -> shaderc -> spirv-v (cache) -> shader loading 형태를 동일하게 만들어줄 수 있다. 추가적으로 vulkan에서는 로딩된 셰이더의 정보를 볼 수 없어서 버텍스 정보, 셰이더 변수 정보등을 알 수가 없는데, spirv-cross 라는 라이브러리를 이용하면 spirv reflection 정보를 얻어올 수 있다. 

이렇게 구성을 하게 되면, 상용엔진과 비슷한 결과와 파이프라인을 만들어낼 수 있다. 물론 자체 컴파일러를 사용하는 상용엔진이 당연히 조금 더 빠르거나 원하는 정보를 뽑아올 수 있겠지만 말이다. (컴파일러 만들 수 있는 정도가 안되어요. ㅠㅠ)

그래도 자체엔진을 사용하는데에는 전혀 문제없이 사용할 수 있을 정도는 될 것이다.


1 2 3 4 5 6 7 8 9 10 다음



메모장

내가 먼 훗날에 이 글들을 보았을 때, 좋은 추억이 될 수 있기를...

나를 위해... 나에게 쓰는...

msn: cagetu@hotmail.com
mail: cagetu79@gmail.com
twitter: twitter.com/cagetu
facebook: facebook.com/cagetu