티스토리 뷰

Game/MMD

Stream Out - Skinned Data

newpolaris 2017. 11. 11. 22:47

발단은 여러 이유가 있지만,

MMD의 model type은 PMD/PMX가 존재한다. 또한 x 파일도 컨버팅해서 들어간다

문제는 이 2개의 skinning 방식이 서로 다른데도 동일한 shader를 탄다는 것이다

Effect라 불리는 쉐이더를 까보면 skinning 을 하지 않고 vertex/normal 이 그냥 들어온다

Direct 9 기반이므로 software skinning을 썻을 거라 추측한다

아니면 이래저래 우회를 했거나;

MMDAI의 경우 PPL 을 타거나, OpenCL 을 태우는 거 같다

MMD는 4가지 skinning type이 있으므로 속도만 괜찮으면 해당 분기도 태울 수 있을 것 같았다.

CPU 프로그래밍은 간단하다

TaskManager::parallel_for(0, position.size(), [&](size_t i) {
    const auto& id = m_Model.m_BoneID[i];
    const auto& weight = m_Model.m_BoneWeight[i];
    const Vector3 pos( m_VertexMorphedPos[i] );
    Vector3 skinned( kZero );
    skinned += (m_Skinning[id.x] * pos) * Scalar( weight.x );
    skinned += (m_Skinning[id.y] * pos) * Scalar( weight.y );
    skinned += (m_Skinning[id.z] * pos) * Scalar( weight.z );
    skinned += (m_Skinning[id.w] * pos) * Scalar( weight.w );
    position[i] = skinned;
});

이걸 GPU서 하려면 으아.

DirectX Math를 backend로 사용하는데 SIMD는 되니까 AVX는 아니더라도

어느정도는 기대했건만

개체 1개

개체 2개

이래저래 비용을 숨기고 Converting 비용을 없애면 잘처야 2~3배인데 잘안되면 1.5배라

포기하고 따른걸 찾아보았다. CPU는 이미 100% 쳐서;

https://forum.unity.com/threads/cpu-gpu-skinning.59565/

superpig said: ↑
The skinning is performed by the vertex shader, and the results written to a new VB via StreamOut (which is why D3D11 is required). The new VB is then rendered similarly to any other mesh.
Yep, that's how it works on DX11\. On OGLES3.0 it uses transform feedback. Here's the relevant change on the 4.2 release:

GPU Skinning (requires Unity Pro)
Completely automatic, no custom shaders needed.
Works on DirectX 11 (via stream-out), OpenGL ES 3.0 (via transform feedback) and Xbox 360 (via memexport). Other platforms will continue to use CPU skinning.

https://www.gamedev.net/forums/topic/631948-what-is-the-current-trend-for-skinning/

2012년도 글인데 streamout 말고 UAV 를 사용해도 된다고 한다.

https://m.blog.naver.com/sorkelf/40171948938

streamout API는 거지같이 많으므로 포기하고 UAV를 vertex buffer에 사용하려고했는데

VertexBuffer에서 UAV Access는 Feature 11_1 이상에서 된다고 해서 streamout 으로 돌아왔다.

거지 같은 API 연결, 기준 구조 변경 뒤에 드디어 결과가 나왔다.

대체 CreateGeometryShaderWithStreamOutput 같은건 왜 그따구로 거기에 위치했어야하는지

속도는 빨라지는 요소 + 느린 요소 합쳤는데 크게 차이안난다.

frame 단위로 1ms 씩 출렁여서 정밀하게 비교하기 힘들다

돈벌어서 GPU 바꾸고 UAV 쓰는 걸로 바꿔야겠다

https://fgiesen.wordpress.com/2011/08/14/a-trip-through-the-graphics-pipeline-2011-part-11/

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크