공부중

[DirectX12]Hello Wolrd Sample - D3D12HelloTriangle - 4 본문

Programing/DirectX

[DirectX12]Hello Wolrd Sample - D3D12HelloTriangle - 4

곤란 2018. 5. 24. 20:31
반응형

이번 글에서 볼 코드 전문이다.

 

	// Create the command list.
	ThrowIfFailed(m_device->CreateCommandList(0, 
						  D3D12_COMMAND_LIST_TYPE_DIRECT, 
						  m_commandAllocator.Get(), 
						  m_pipelineState.Get(), 
						  IID_PPV_ARGS(&m_commandList)));

	// Command lists are created in the recording state, but there is nothing
	// to record yet. The main loop expects it to be closed, so close it now.
	ThrowIfFailed(m_commandList->Close());

	// Create the vertex buffer.
	{
		// Define the geometry for a triangle.
		Vertex triangleVertices[] =
		{
			{ { 0.0f, 0.25f * m_aspectRatio, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
			{ { 0.25f, -0.25f * m_aspectRatio, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
			{ { -0.25f, -0.25f * m_aspectRatio, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }
		};

		const UINT vertexBufferSize = sizeof(triangleVertices);

		// Note: using upload heaps to transfer static data like vert buffers is not 
		// recommended. Every time the GPU needs it, the upload heap will be marshalled 
		// over. Please read up on Default Heap usage. An upload heap is used here for 
		// code simplicity and because there are very few verts to actually transfer.
		ThrowIfFailed(m_device->CreateCommittedResource(
			&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
			D3D12_HEAP_FLAG_NONE,
			&CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
			D3D12_RESOURCE_STATE_GENERIC_READ,
			nullptr,
			IID_PPV_ARGS(&m_vertexBuffer)));

		// Copy the triangle data to the vertex buffer.
		UINT8* pVertexDataBegin;
		CD3DX12_RANGE readRange(0, 0);		// We do not intend to read from this resource on the CPU.
		ThrowIfFailed(m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)));
		memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices));
		m_vertexBuffer->Unmap(0, nullptr);

		// Initialize the vertex buffer view.
		m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
		m_vertexBufferView.StrideInBytes = sizeof(Vertex);
		m_vertexBufferView.SizeInBytes = vertexBufferSize;
	}

 

명령리스트를 생성하고 그 후에 VertexBuffer생성에 관련된 내용을 다루고 있다.

 

 

	// Create the command list.
	ThrowIfFailed(m_device->CreateCommandList(0, 
						  D3D12_COMMAND_LIST_TYPE_DIRECT, 
						  m_commandAllocator.Get(), 
						  m_pipelineState.Get(), 
						  IID_PPV_ARGS(&m_commandList)));

	// Command lists are created in the recording state, but there is nothing
	// to record yet. The main loop expects it to be closed, so close it now.
	ThrowIfFailed(m_commandList->Close());

명령리스트(command list)를 생성하고는 있으나 딱히 명령을 기록할것은 없기에 그냥 다음줄에서 바로 닫아 버렸다.

 

다음 블록( 중괄호 부분 ) 에서는 VertexBuffer를 생성하고 있는데

 

제일 먼저 삼각형의 기하학을 정의 하고 있다.

 

		// Define the geometry for a triangle.
		Vertex triangleVertices[] =
		{
			{ { 0.0f, 0.25f * m_aspectRatio, 0.0f }, { 1.0f, 0.0f, 0.0f, 1.0f } },
			{ { 0.25f, -0.25f * m_aspectRatio, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f } },
			{ { -0.25f, -0.25f * m_aspectRatio, 0.0f }, { 0.0f, 0.0f, 1.0f, 1.0f } }
		};

		const UINT vertexBufferSize = sizeof(triangleVertices);

Vertex형으로 삼각형을 정의 하고 있다. 각각 첫번째는 정점의 위치(x, y, z)를 넣어줬고 두번째는 컬러값 (R, G, B, A)를 넣어주었다.

다음으로는 VertexBuffer의 사이즈를 저장하고 있다.

 

 

		// Note: 버텍스 버퍼와 같은 정적 데이터를 전송하기 위해 업로드 힙을 사용하는 것은 권장되지 않습니다. 
		//          GPU에서 필요할 때마다 업로드 힙이 정렬됩니다. 기본 힙 사용법을 읽어보십시오. 
		//          업로드 힙은 코드 단순화와 실제로 전송할 수있는 버트(verts)가 거의 없기 때문에 여기에서 사용됩니다.
		ThrowIfFailed(m_device->CreateCommittedResource(
			&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
			D3D12_HEAP_FLAG_NONE,
			&CD3DX12_RESOURCE_DESC::Buffer(vertexBufferSize),
			D3D12_RESOURCE_STATE_GENERIC_READ,
			nullptr,
			IID_PPV_ARGS(&m_vertexBuffer)));

 

주석의 번역은 번역기를 돌렸고.

GPU가 Vertex들의 배열에 접근하려면 Buffer라고 부르는 GPU의 자원에 넣어두어야 하는데

이를 정점들을 저장하는 VertexBuffer(정점 버퍼)라고 부른다.

이 VertexBuffer를 생성하려면 ID3D12Device::CreateCommittedResource 메서드를 호출해서 ID3D12Resource객체를 생성한다.

여기서는 m_vertexBuffer가 ID3D12Resource 형의 멤버이며 여기에 들어간다.

 

 

		// 삼각형 데이터를 Vertex Buffer(정점 버퍼)에 복사합니다.
		UINT8* pVertexDataBegin;
		CD3DX12_RANGE readRange(0, 0);		// 우리는 이 리소스를 CPU에서 읽을 생각이 없습니다.
		ThrowIfFailed(m_vertexBuffer->Map(0, &readRange, reinterpret_cast<void**>(&pVertexDataBegin)));
		memcpy(pVertexDataBegin, triangleVertices, sizeof(triangleVertices));
		m_vertexBuffer->Unmap(0, nullptr);

 

Resource 자료를 가리키는 포인터를 얻으러면 Map 메서드를 호출해서 얻을 수 있다.

대응시킬 메모리의 범위를 나타내는 Map 메서드의 두번째 매개변수는 D3D12_RANGE 구조체의 포인터인데 여기서는 0부터 0까지로 정해주었고

Resource 전체를 대응 시키려면 nullptr을 넣어주면 된다.

 

그리고 memcpy를 통해서 복사해 주고 있다.

 

자료를 모두 복사 했으면 Unmap을 호출해 주어야 한다.

 

 

		// 정점 버퍼 뷰를 초기화합니다.
		m_vertexBufferView.BufferLocation = m_vertexBuffer->GetGPUVirtualAddress();
		m_vertexBufferView.StrideInBytes = sizeof(Vertex);
		m_vertexBufferView.SizeInBytes = vertexBufferSize;

 

마지막 부분으로 정점 버퍼 뷰(Vertex Buffer View)를 초기화 해주고 있는 모습이다.

Vertex Buffer를 파이프 라인에 묶으려면 Vertex Buffer View를 만들어야 하는데 

여기에는 서술자 힙(descriptor heap)을 필요로 하지 않고 

Vertex Buffer View를 대표하는 형식은 D3D12_VERTEX_BUFFER_VIEW_DESC구조체 이다.

typedef struct D3D12_VERTEX_BUFFER_VIEW
    {
    D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
    UINT SizeInBytes;
    UINT StrideInBytes;
    } 	D3D12_VERTEX_BUFFER_VIEW;

* BufferLocation : 생성할 뷰의 대상이 되는 VertexBuffer 자원의 가상 주소이다.

                       이 주소는 ID3D12Resource::GetGPUVirtualAddress 메서드로 얻을수 있다.

* SizeInBytes : BufferLocation 에서 시작하는 정점 버퍼의 크기(Byte 갯수)

* StrideInBytes : 버퍼에 담긴 한 정점 원소의 크기(Byte 갯수)

 

특별한것은 없고 위에서 설명한 대로 멤버변수인 m_vertexBufferView에 대입만 해주고 있다.

 

다음글에서는 동기화 객체를 생성하고 에셋이 GPU에 업로드 되기를 기다리는 코드에 대해서 쓸예정이다.

 

 

다음글에서....

 

 

 

 

 

 

 

 

 

 

반응형