공부중
[DirectX12]Hello Wolrd Sample - D3D12HelloTexture - 6 본문
// Note: ComPtr은 CPU 개체이지만 이 리소스는 이를 참조하는 명령 목록이
// GPU에서 실행을 마칠 때까지 범위에 있어야합니다.
// 자원이 조기에 파괴되지 않도록
// 이 방법의 끝에서 GPU를 플러시합니다.
ComPtr<ID3D12Resource> textureUploadHeap;
// Create the texture.
{
// Describe and create a Texture2D.
D3D12_RESOURCE_DESC textureDesc = {};
textureDesc.MipLevels = 1;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.Width = TextureWidth;
textureDesc.Height = TextureHeight;
textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
textureDesc.DepthOrArraySize = 1;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&textureDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_texture)));
const UINT64 uploadBufferSize = GetRequiredIntermediateSize(m_texture.Get(), 0, 1);
// Create the GPU upload buffer.
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&textureUploadHeap)));
// 중간 업로드 힙에 데이터를 복사 한 다음
// 업로드 힙에서 Texture2D로 복사본을 예약하십시오.
std::vector<UINT8> texture = GenerateTextureData();
D3D12_SUBRESOURCE_DATA textureData = {};
textureData.pData = &texture[0];
textureData.RowPitch = TextureWidth * TexturePixelSize;
textureData.SlicePitch = textureData.RowPitch * TextureHeight;
UpdateSubresources(m_commandList.Get(), m_texture.Get(), textureUploadHeap.Get(), 0, 0, 1, &textureData);
m_commandList->ResourceBarrier(1,
&CD3DX12_RESOURCE_BARRIER::Transition(m_texture.Get(),
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
// 텍스처에 대한 SRV를 설명하고 생성하십시오.
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = textureDesc.Format;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
m_device->CreateShaderResourceView(m_texture.Get(), &srvDesc, m_srvHeap->GetCPUDescriptorHandleForHeapStart());
}
이번 코드는 꽤 긴 코드이며 텍스쳐 생성에 관련된 코드이다.
주석은 번역기를 돌렸다.
// Note: ComPtr은 CPU 개체이지만 이 리소스는 이를 참조하는 명령 목록이
// GPU에서 실행을 마칠 때까지 범위에 있어야합니다.
// 자원이 조기에 파괴되지 않도록
// 이 방법의 끝에서 GPU를 플러시합니다.
ComPtr<ID3D12Resource> textureUploadHeap;
제일 위에 있는 ComPtr로 ID3D12Resource 형의 textureUploadHeap을 만들었고 아래의 코드에서 업로드 버퍼로 쓰이는 모습이 보인다.
// Describe and create a Texture2D.
D3D12_RESOURCE_DESC textureDesc = {};
textureDesc.MipLevels = 1;
textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
textureDesc.Width = TextureWidth;
textureDesc.Height = TextureHeight;
textureDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
textureDesc.DepthOrArraySize = 1;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
일단 구문 안으로 들어가면 D3D12_RESOURCE_DESC형으로 사용하려는 텍스쳐에 관련된 정보들을 서술하고 있다.
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&textureDesc,
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_texture)));
CreateCommittedResource는 자원을 생성하고 지정된 속성들에 부합하는 힙에 그 자원을 맡긴다고 한다(commit)
첫번째 인자를 보면 &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT) 로 주어줬는데.
D3D12_HEAP_TYPE_DEFAULT는 기본 힙이며 전적으로 GPU가 접근할 자원들이 담긴다고 한다.
다른 타입을 보려면 D3D12_HEAP_TYPE enumeration - MSDN 을 살펴보자
두번째 인자는 자원을 맡길 힙이 가졌으면 하는 속성들을 나타내는 추가적인 플래그들이다.
플래그들의 정보를 보고 싶으면 D3D12_HEAP_FLAGS enumeration - MSDN 을 살펴보도록 하자
세번째 인자는 생성하고자 하는 자원을 서술하는 D3D12_RESOURCE_DESC 인스턴스의 포인터이다
여기서는 바로 위에서 작성한 textureDesc의 주소를 넘겨주었다.
네번째 인자는 자원에는 상태(state)가 있는데 자원의 초기 상태를 지정한다.
상태의 종류와 설명을 보고 시으면 D3D12_RESOURCE_STATES enumeration - MSDN을 살펴보자
다섯번째 인자는 자원 지우기에 최적화된 값을 나타내는 D3D12_CLEAR_VALUE 구조체를 가리키는 포인터이다.
따로 설정하지 않으러면 null을 지정하면 된다고 한다.
const UINT64 uploadBufferSize = GetRequiredIntermediateSize(m_texture.Get(), 0, 1);
// Create the GPU upload buffer.
ThrowIfFailed(m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&textureUploadHeap)));
다음 라인은 업로드할 버퍼의 사이즈를 UINT64에 저장했다.
GetRequiredIntermediateSize - MSDN는 데이터 업로드에 필요한 버퍼의 크기를 반환하는 함수이다.
그리고 하단에 GPU 업로드 버퍼를 생성하는데 위에서 사용한 CreateCommittedResource를 이용하고 있다.
첫번째 인자의 플래그로 D3D12_HEAP_TYPE_UPLOAD로 주었다.
첫번째 상태로는 D3D12_RESOURCE_STATE_GENERIC_READ를 주었다.
// 중간 업로드 힙에 데이터를 복사 한 다음
// 업로드 힙에서 Texture2D로 복사본을 예약하십시오.
std::vector<UINT8> texture = GenerateTextureData();
D3D12_SUBRESOURCE_DATA textureData = {};
textureData.pData = &texture[0];
textureData.RowPitch = TextureWidth * TexturePixelSize;
textureData.SlicePitch = textureData.RowPitch * TextureHeight;
std::vector로 texture라는 변수를 만들고 GenerateTextureData에서 값을 받아오고 있다. 저 GenerateTextureData를 살펴보면...
std::vector D3D12HelloTexture::GenerateTextureData() { const UINT rowPitch = TextureWidth * TexturePixelSize; const UINT cellPitch = rowPitch >> 3; // The width of a cell in the checkboard texture. const UINT cellHeight = TextureWidth >> 3; // The height of a cell in the checkerboard texture. const UINT textureSize = rowPitch * TextureHeight; std::vector data(textureSize); UINT8* pData = &data[0]; for (UINT n = 0; n < textureSize; n += TexturePixelSize) { UINT x = n % rowPitch; UINT y = n / rowPitch; UINT i = x / cellPitch; UINT j = y / cellHeight; if (i % 2 == j % 2) { pData[n] = 0x00; // R pData[n + 1] = 0x00; // G pData[n + 2] = 0x00; // B pData[n + 3] = 0xff; // A } else { pData[n] = 0xff; // R pData[n + 1] = 0xff; // G pData[n + 2] = 0xff; // B pData[n + 3] = 0xff; // A } }p return data; }
주석에 나온대로 간단한 체커보드 텍스쳐값을 가져온다...(애초에 이미지파일을 불러오는게 아니였다 -_-....)
이미지에서 긁어오든 뭐든 일단 저 코드가 하나의 이미지파일을 읽어다가 데이터를 긁어왔다고 생각해보자.
class D3D12HelloTexture : public DXSample { // 생략... static const UINT TextureWidth = 256; static const UINT TextureHeight = 256; static const UINT TexturePixelSize = 4; // The number of bytes used to represent a pixel in the texture. // 생략...
D3D12HelloTexture.h 에서 새로 추가된 부분중 하나인데 이 값들이 저 텍스쳐데이터를 가져오는데 쓰인다. 위에서부터 살펴보자..
const UINT rowPitch = TextureWidth * TexturePixelSize; const UINT cellPitch = rowPitch >> 3; // The width of a cell in the checkboard texture. const UINT cellHeight = TextureWidth >> 3; // The height of a cell in the checkerboard texture. const UINT textureSize = rowPitch * TextureHeight;
Pitch는 여기 링크를 참조해보도록 해보자 ( 링크1 , 링크2 ) 실제 데이터로 변환했을때 실제 가로의 바이트? 정도?
(솔직히 말하자면 내가 텍스처에 관해서 공부를 해야한다 -_-... 공부를 하고 따로 글을 적든지 해서 정리를 해야 겠다)
std::vector<UINT8> data(textureSize); UINT8* pData = &data[0];
vector로 UINT8 형으로 위에서 계산한 textureSize만큼 만들어 주었고
첫번째 주소가져오는 모습이다.
for (UINT n = 0; n < textureSize; n += TexturePixelSize) { UINT x = n % rowPitch; UINT y = n / rowPitch; UINT i = x / cellPitch; UINT j = y / cellHeight; if (i % 2 == j % 2) { pData[n] = 0x00; // R pData[n + 1] = 0x00; // G pData[n + 2] = 0x00; // B pData[n + 3] = 0xff; // A } else { pData[n] = 0xff; // R pData[n + 1] = 0xff; // G pData[n + 2] = 0xff; // B pData[n + 3] = 0xff; // A } } return data;
이후로 반복문을 통해서 텍스처의 데이터를 넣어준다.
if문의 구역에는 검정색으로...
else문은 하얀색으로 ....
반복문을 모두 돌면 data를 리턴한다.
저 텍스쳐에 대해서는 공부를 해서 다시 정리를 해봐야겠다 -_-... (기초가 부족하니 왜 저럴까 고민만 계속했다.)
아무튼 GenerateTextureData는 텍스처 데이터를 리턴하므로 텍스쳐 데이터를 받아올수 있다.
그리고 하단에 D3D12_SUBRESOURCE_DATA형으로 textureData를 서술하고 있다.
D3D12_SUBRESOURCE_DATA structure - MSDN
UpdateSubresources(m_commandList.Get(), m_texture.Get(), textureUploadHeap.Get(), 0, 0, 1, &textureData);
m_commandList->ResourceBarrier(1,
&CD3DX12_RESOURCE_BARRIER::Transition(m_texture.Get(),
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE));
UpdateSubresources 위에서 작성한 하위리소스를 업데이트 하고
ResourceBarrier를 통해서 복사 상태에서 픽셀셰이더 상태로 전환 하고 있다.
// 텍스처에 대한 SRV를 설명하고 생성하십시오.
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = textureDesc.Format;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = 1;
m_device->CreateShaderResourceView(m_texture.Get(), &srvDesc, m_srvHeap->GetCPUDescriptorHandleForHeapStart());
D3D12_SHADER_RESOURCE_VIEW_DESC형의 구조체를 만들고 서술하고 있다
각각의 멤버에 대해서는 D3D12_SHADER_RESOURCE_VIEW_DESC structure - MSDN 을 참조하자
CreateShaderResourceView를 통해서 위에서 생성한 srvDesc를 넘겨주어서 셰이더 리소스 뷰를 생성하였다.
이 글은 너무 엉망진창이라 -_- 나중에 다시 작성해야될 판이다...
으으으으....
열심히 공부해야지 ㅠㅠ
다음 코드는 GPU와 동기화 하는 부분이다.
저번 프로젝트와 차이가 없으므로 간단히 끝이날것같다...
다음글에서...
'Programing > DirectX' 카테고리의 다른 글
[DirectX] SwapChain, double buffering(더블 버퍼링) (0) | 2018.06.07 |
---|---|
[DirectX12]Hello Wolrd Sample - D3D12HelloTexture - 7 (0) | 2018.06.07 |
[DirectX12]Hello Wolrd Sample - D3D12HelloTexture - 5 (0) | 2018.06.05 |
[DirectX12]Hello Wolrd Sample - D3D12HelloTexture - 4 (0) | 2018.06.05 |
[DirectX12]Hello Wolrd Sample - D3D12HelloTexture - 3 (0) | 2018.06.03 |