compute shader dx11
DESCRIPTION
DX11 ComputeShaderTRANSCRIPT
이민웅
Shader Study
http://www.youtube.com/watch?v=7VFV0_69AcE&feature=related
http://www.youtube.com/watch?feature=player_embedded&v=NAsoXHHCqWM
http://www.youtube.com/watch?feature=player_embed
http://www.youtube.com/watch?feature=player_embedded&v=z_7DgpJK-eI ded&v=_ubIvvzl7HY
DX8과 DX9의 차이◦ 텍스쳐 메모리를 버텍스 쉐이더 단계에서도 참조할 수 있다는 정
도◦ API 를 설계할 때 항상 싱글 코어를 고려◦ API 자체가 GPU 의 정점 처리 기능을 규정
특징◦ GPU Tessellation.◦ Compute Shader.◦ Multi-threaded rendering.
이미 XBOX360에서는Compute Shader 를 제외한 두가지는 지원
멀티코어(CPU)와 GPU에게최대한 많은 일을 시킬 수 있는 구조로 하드웨어를 구성했고, 그것을 기반으로 해서런타임과 API 를 설계
GPU의 부동소수점 연산 능력이 CPU보다 빠르다 CPU는 GPU보다 상대적으로 메모리 용량이 크다 GPU와 메모리 간의 대역폭이 넓어 대량의 데이터 전송
에 유리하다 GPU와 메모리 간 대역폭보다 CPU와 GPU 간의 대역폭
이 좁다
SIMD( Single Instruction Multiple Data ) 라는 것은 병렬 프로세서의 한 종류
벡터 기반의 프로세서에서 주로 사용
하나의 명령어를 통해서 여러 개의 값을 동시에 계산
GPGPU 를 활용하는 목적은 주로 수치 연산에만 국한된 이야기
GPGPU 가 활용되고 있는 영역은 이미지 프로세싱, 비디오 프로세싱, 시뮬레이션 등과 같이 많은 수학 연산이 필요한 영역
GPU 를 활용한 일반적인 처리 방식◦ GPGPU( General-purpose computing on graphics
processing uints )
GPU 는 그래픽 처리를 위한 산술 연산에 특화된
processing unit
GPU 의 경우에는 병렬처리 형식에 완전히 특화된
형태
◦ GPU의 코어는 32개라면 32개가 연산이 동시에 실행될
수 있다는 얘기
DirectCompute 는 마이크로소프트에서 가지고나온 GPGPU 모델
CUDA 도 굉장히 훌륭한 GPGPU 모델
CUDA와 DirectCompute 의 속도 차이는 거의 없
을 것
CUDA 의 경우에는 이미 몇년전에 공개가 되어서
지금 가장 앞선 GPGPU 환경
CUDA 의 이점은 XP에서도 가능
DirectCompute 는 XP 에서 실행이 안됨
DirectCompute 는 아직 문법적인 내용은 많이 공
개가 되지 않았지만, HLSL 이라는 쉐이더 기반의
언어를 사용하기 때문에 게임 개발자들쪽에 포커
스가 간 것이 사실
DirectCompute는 이론적으로는 그래픽 하드웨어
의 특성을 타지 않음
◦ 현실은 아님
AMD와 NVIDIA의 SIMT(Single Instruction, Multiple Thread)실행에서 한번에 처리하는 병
렬 스레드 수의 차이
◦ AMD는 WAVEFRONT라고 부르며 64개, NVIDIA는
WAPP라고 부르며 그 수는 32개
◦ 실행하는데는 전혀 문제가 없지만 성능을 최대한 내고 싶
을 때는 하드웨어 차이를 의식해야 함
DirectX 10의 셰이더 모델인 SM4.0에도 도입 SM4.0에서의 컴퓨트 셰이더에는 아래와 같은 제한
◦ [최대 스레드 수]는 각 그룹당 768개 ( SM 5.0은 1024)◦ numthreads 의 Z값은 1까지 ( SM5.0 에서는 64)◦ Dispatch의 Z값은 1로 제한◦ 컴퓨트 셰이더에 바인드 가능한 [ Unordered Access View ]는 딱 1개◦ [RW Structured Buffers]와 [ RWByteAddressBuffers]만이
[ Unordered Access View ]로써 사용가능◦ 쓰기용 [ 스레드 그룹 공유 메모리(Groupshared) ]에 액세스 할 경우
[SV_GroupIndex]를 사용해야 한다. 읽기는 임의의 장소에서 가능◦ 스레드 그룹 공유 메모리는 각 그룹당 16KB로 제한 (SM5.0에서는 32KB]◦ 단일 스레드는 쓰기용으로는 [스레드 그룹 공유메모리]의 256바이트 영
역으로 제한◦ 아토믹 명령([InterlockedAdd]등)은 사용 불가능◦ 배수정밀도 값(double등은) 사용 불가능
ComputeShader 는 HLSL 이라는 기존
DirectX 의 쉐이더 문법 구조로 작성
HLSL 은 결국 최적화된 IL 코드를 생성하
게 되고, 이 IL 코드를 기반으로 런타임에
각각의 하드웨어에 최적화된 명령어들로
변환되어져서 실행
GPU 는 병렬 처리에 최적화된 많은 SIMD 형태로
구성
◦ 스레드들의 그룹으로써 실행
◦ 큰 그룹으로 나누어 주는 API 는ID3D11DeviceContext::Dispatch()
ipImmediateContextPtr->Dispatch( 3, 2, 1 );
[numthreads(4, 4, 1)]void MainCS( ... ){
....}
3x2x1= 6개의 스레드 그룹생성을 가정
Total threads = 3*2*4*4 = 96
Compute Shader
DirectCompute
GPGPU
DirectCompute 를 초
기화하는 작업은 바로
전통적인
CreateDevice() API 를사용
hr = D3D11CreateDevice(
NULL, // default gfx adapterD3D_DRIVER_TYPE_HARDWARE, // use hw
NULL, // not sw rasterizeruCreationFlags, // Debug, Threaded, etc.NULL, // feature levels0, // size of aboveD3D11_SDK_VERSION, // SDK versionppDeviceOut, // D3D Device&FeatureLevelOut, // of actual deviceppContextOut ); // subunit of device
);
StructuredBuffer◦ 개발자가 정의한 구조체
◦ 앞에 식별자가 없으면 읽기전용이라는 의미
‘RW' 라고 명시된 버퍼는읽기/쓰기 가 가능한 버퍼라는 의미◦ GPU 가 처리한 결과는 읽기/
쓰기가 가능
최적화를 위해서 각 목적에 맞게 버퍼를 사용
샘플 ) ComputeShader
#define BLOCK_SIZE 256StructuredBuffer gBuf1;StructuredBuffer gBuf2;RWStructuredBuffer gBufOut;
[numthreads(BLOCK_SIZE,1,1)]void VectorAdd( uint3 id: SV_DispatchThreadID ){gBufOut[id] = gBuf1[id] + gBuf2[id];
}
CreateComputeShader() 생성
pD3D->CreateComputeShader( pBlob->GetBufferPointer(),pBlob->GetBufferSize(),NULL,&pMyShader ); // hw fmt
D3D11_BUFFER_DESC descBuf;ZeroMemory( &descBuf, sizeof(descBuf) );desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;desc.StructureByteStride = uElementSize;desc.ByteWidth = uElementSize * uCount;desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;pD3D->CreateBuffer( &desc, pInput, ppBuffer );
• DirectX 인터페이스를 통해서 비디오 메모리를 생성– 주의해야 할 것은 바로 'BindFlags‘ – 'D3D11_BIND_UNORDERED_ACCESS' 라는 플래그
– PixelShader 나 ComputeShader 에서 병렬적으로 실행하는 버퍼를 의미
ShaderResourceView 는 파이프라인 스테이지에서 읽기전용
UnorderedAccessView 는 읽기/쓰기가 가능한 형태◦ 비디오 메모리에 있는 버퍼에 결과를 기록할 수 있음
ViewDimension◦ 'D3D11_UAV_DIMENSION_BUFFER' 를 설정하고 있는데,
이는 ComputeShader 상에서 이 버퍼를 일반적인 버퍼로 보겠다는 의미
◦ 즉, 샘플링 작업을 전혀하지 않음 (어떠한 수정도 없이 데이터를있는 그대로 보존)
D3D11_UNORDERED_ACCESS_VIEW_DESC desc;ZeroMemory( &desc, sizeof(desc) );desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;desc.Buffer.FirstElement = 0;desc.Format = DXGI_FORMAT_UNKNOWN;desc.Buffer.NumElements = uCount;pD3D->CreateUnorderedAccessView(
pBuffer, // Buffer view is into&desc, // above data&pMyUAV ); // result
실행 결과가 비디오 메모리에 존재
결과를 확인하기 위해서는 CPU 가 액세스할 수 있
는 버퍼로 결과를 복사
pD3D->CSSetShader( pMyShader, NULL, 0 );- 파이프라인 스테이지에 바인딩
pD3D->CSSetUnorderedAccessViews( 0, 1, &pMyUAV, NULL );- 뷰에 바인딩pD3D->Dispatch( GrpsX, GrpsY, GrpsZ );- GPU 에게 현재 바인딩된 내용을 바탕으로 연산해 줄 것을 요청
D3D11_CPU_ACCESS_READ' 라는 플래그를 통해
서, 이 버퍼는 CPU 가 액세스 할 수 있는 형태로
만듬
'D3D11_USAGE_STAGING' 라는 플래그를 통해서
단순히 비디오 메모리에 있는 내용을 CPU 도 접근
할 수 있는 메모리로 복사해오는 버퍼임을 명시
D3D11_BUFFER_DESC desc;ZeroMemory( &desc, sizeof(desc) );desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;desc.Usage = D3D11_USAGE_STAGING;desc.BindFlags = 0;desc.MiscFlags = 0;pD3D->CreateBuffer( &desc, NULL, &StagingBuf );
pD3D->CopyResource( StagingBuf, pBuffer );
Luminous Studio◦ [ 천의 시뮬레이션], [파티클시스템]
파티클 시스템에 관해서는 , 10만개 이상의 파티클을 생성
시키는 것을 차세대 표현의 목표
http://gigaboy.egloos.com/10849570
http://vsts2010.net/150 http://www.microsoft.com/ko-
kr/showcase/details.aspx?uuid=0d587c62-b53b-4eb1-be18-f7c9e7b75987
http://gigglehd.com/zbxe/newsreport/2837990
http://blog.naver.com/leemwymw http://vsts2010.net/520 http://blog.naver.com/sorkelf/40163424175 http://gigaboy.egloos.com/10849570 http://gtgames.egloos.com/5127042