momodudu.zip

Metal 스터디(5) - MSL에서 packed_float 과 non-packed_float의 차이 본문

ios/Metal

Metal 스터디(5) - MSL에서 packed_float 과 non-packed_float의 차이

ally10 2022. 2. 9. 10:16

 

Non-Interlaved vertex를 그리는 쉐이더를 작성중에.. 이런 문제를 발견했다.

 

#include <metal_stdlib>
using namespace metal;
struct VertexIn {
    float3 position;
    float4 color;
};

struct VertexOut {
    float4 position [[position]];
    float4 color;
};


vertex VertexOut vertex_main(const device VertexIn* vertex_in [[ buffer(0) ]],
                          unsigned int vid [[vertex_id]]) {
    VertexIn in = vertex_in[vid];
    
    VertexOut out;
    out.position = float4(in.position.position, 1.0);
    out.color = in.color;

  return out;
}

fragment float4 fragment_main(VertexOut interpolated [[stage_in]] ) {
    return interpolated.color;
}

일단 쉐이더 코드는 위와 같다. 별로 어려운 코드는 아니고, 그냥 들어온 vertex마다 컬러값과 position값을 그대로 리턴해주는 코드다.

vertex data는 하나당 (x,y,z,r,g,b,a)를 가지고 있고, 각 좌표값은 (0, 1, 0) / (1, -1, 0) / (-1, -1, 0) 이고, 각 정점의 색은 모두 blue다. 화면에 가득차는 파란 삼각형이 나와야한다.

 

 

결과가 계속 이렇게 나와서 조금 찾아보다보니..

 

struct VertexIn {
    float3 position;
    float4 color;
};

위에서 작성한 쉐이더를 보면, VertexIn 내부가 float3 의 position과 float4의 color로 이루어져있는데, 구조체 패딩이 맞지 않다. 물론 vertex buffer에 집어넣을때도 패딩은 고려하지 않았다.

 

Metal에서 이런 데이터 구조는 정확한 결과값을 "보장하지않는다"라고 한다. 패딩이 맞춰져 있지 않을 경우, 그 데이터들이 다닥다닥 붙어있을거라는 보장이 없다는 말이다. 즉, 잘될수도 있고 안될수도 있는데 내 경우는 안됐던 것이다.

 

이러한 문제를 해결하기 위해서, msl에서는 packed type을 제공하는데, float3 -> packed_float3을 써준다면 데이터들이 다닥다닥 붙어있는것을 보장해줄 수 있다고 한다.

 

struct VertexIn {
    packed_float3 position;
    packed_float4 color;
};

 

packed_float type으로 바꾸어주면 간단히 해결된다.

 

 

혹은, 처음부터 패딩을 잘 맞춰서 쉐이더에서 불필요한 값을 빼고 쓰는 해결방법도 있다.

 

요즘 너무 좋은 프로그래밍 언어만 썼더니 이런부분에 문제가 있을거라곤 생각도 못했다;;