๊ฐ์ฒด๋ฅผ ์ ๋๋ก ๋ ๋๋งํ๋ ค๋ฉด ์ํด ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ ์ ฐ์ด๋๋ก ์ ๋ฌํด์ผ ํฉ๋๋ค. ์ง๊ธ์ ํ๋์ฝ๋ฉ๋ ๋ฐฐ์ด์ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๋จ์ผ ์ผ๊ฐํ ํน์ ๋จ์ํ ๋ํ์ธ์๋ ์ ๋๋ก ๋์ํ์ง ์์ต๋๋ค.
ํ์ดํ๋ผ์ธ์์ ๊ณ ์ ํจ์ ๋ฐฉ์์ ์ ์ ์์ฑ ๊ฐ์ ธ์ค๊ธฐ(fetch) ๋ก์ง์ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์, ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ ฐ์ด๋์์ ์ด๋ป๊ฒ ์ ํํ ๋ถ๋ฌ์ฌ์ง๋ ์ ์ ์ผ๋ก ์์ ์ ๋๋ค. ์ฐ๋ฆฌ๋ ์ ์ ๋ค์ Buffer Device Address๋ฅผ ํตํด ์ ๋ฌ๋ ๋์ฉ๋ GPU ๋ฒํผ๋ก๋ถํฐ ๋ถ๋ฌ์ฌ ๊ฒ์ ๋๋ค. ์ด๋ ๊ณ ์ฑ๋ฅ๊ณผ ๋์ ์ ์ฐ์ฑ์ ๋ถ์ฌํฉ๋๋ค.
Vulkan ๋ฒํผ
Vulkan์์๋ ๋ฒ์ฉ ๋ชฉ์ ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฒํผ๋ฅผ ํตํด ํ ๋นํ ์ ์์ต๋๋ค. ์ํ๋ฌ๋ฅผ ์๊ตฌํ์ง ์๊ณ ์ผ๋ฐ์ ์ธ CPU์ธก์ ๊ตฌ์กฐ์ฒด ํน์ ๋ฐฐ์ด์ฒ๋ผ ๋์ํ๋ ๋ฉด์์ ๋ฒํผ๋ ์ด๋ฏธ์ง์๋ ๋ค๋ฆ ๋๋ค. ๊ตฌ์กฐ์ฒด ํน์ ๊ตฌ์กฐ์ฒด ๋ฐฐ์ด๋ก ์ด๋ฅผ ์ ฐ์ด๋์์ ์ ๊ทผํ ์ ์์ต๋๋ค.
๋ฒํผ๊ฐ ์์ฑ๋ ๋ ์ฉ๋์ ๋ง๋ Usage ํ๋๊ทธ๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค.
์ ฐ์ด๋์๋ ๋ฒ์ฉ ์ฝ๊ธฐ/์ฐ๊ธฐ ์ฐ์ฐ์ ์ํ ๋ ์ข ๋ฅ์ ๋ฒํผ๊ฐ ์์ต๋๋ค. ์ ๋ํผ ๋ฒํผ์ ์คํ ๋ฆฌ์ง ๋ฒํผ์ ๋๋ค.
์ ๋ํผ ๋ฒํผ๋ ์ ฐ์ด๋์์ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ์ ๊ทผํ ์ ์์ผ๋ฉฐ, ์ ๊ทผ ๊ฐ๋ฅํ ํฌ๊ธฐ๋ ์ ์กฐ์ฌ๋ง๋ค ๋ค๋ฅด์ง๋ง ์ต์ 16KB๊ฐ ๋ณด์ฅ๋ฉ๋๋ค. ๋ฐ๋ฉด ํ์ดํ๋ผ์ธ์ ๋ถ๋ฌ์ฌ ๋ GPU๊ฐ ์ฌ์ ์บ์ฑ ํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ฐ์ฅ ๋น ๋ฅธ ์ ๊ทผ ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ํฌ๊ธฐ ์ ํ์ ์ ฐ์ด๋์ ๋ฐ์ธ๋ฉ๋ ๋ถ๋ถ์๋ง ์ ์ฉ๋ฉ๋๋ค. ๋ฐ๋ผ์ ํ๋์ ์ปค๋ค๋ ์ ๋ํผ ๋ฒํผ๋ฅผ ๋ง๋ค์ด ์ผ๋ถ๋ง ์ ฐ์ด๋๋ก ๋ฐ์ธ๋ฉํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค. ํ๋์จ์ด์ ๋ฐ๋ผ ํธ์์์๊ฐ ๋๋ผ์ด๋ฒ์ ์ํด ์ ๋ํผ ๋ฒํผ์ ํ ํํ๋ก ๊ตฌํ๋ ์ ์์ต๋๋ค.
์คํ ๋ฆฌ์ง ๋ฒํผ(SSBO)๋ ๋์ฉ๋์ ์ฝ๊ธฐ ์ฐ๊ธฐ ๊ฐ๋ฅํ ๋ฒํผ์ ๋๋ค. ์ต์ ํฌ๊ธฐ๋ 128MB์ด๋ฉฐ, ์ด ํํ ๋ฆฌ์ผ์์ ํ๊ฒํ ํ๋ ํ๋ PC์ GPU๋ 4GB๋ฅผ ์ง์ํฉ๋๋ค. ์ด ํฌ๊ธฐ๋ uint32 ํฌ๊ธฐ๋ก ํํํ ์ ์๋ ์ต๋ ๊ฐ์ ๊ธฐ๋ฐํ ์ ํ์ ๋๋ค. ์คํ ๋ฆฌ์ง ๋ฒํผ๋ ์ ๋ํผ ๋ฒํผ์ฒ๋ผ ์ฌ์ ๋ก๋ฉ๋์ง ์์ผ๋ฉฐ ๋ณด๋ค ์ผ๋ฐ์ ์ธ ํํ์ ๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ/์ ์ฅ(load/store)์ ์ํ ์ฉ๋๋ก ์ฌ์ฉ๋ฉ๋๋ค.
์ ๋ํผ ๋ฒํผ๋ ํฌ๊ธฐ๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ ์ ๋ํ ๋ฐ์ดํฐ๋ฅผ ๋ด๊ธฐ์๋ ์ ํฉํ์ง ์์ต๋๋ค. ํ์ง๋ง ๋จธํ ๋ฆฌ์ผ ์ธ์์ ์ ์ญ ์ฌ ๊ตฌ์ฑ์ ์ ๋ฌํ๋ ๋ฐ์๋ ๋งค์ฐ ํจ๊ณผ์ ์ ๋๋ค.
์ ๋ํผ ๋ฒํผ์ ์คํ ๋ฆฌ์ง ๋ฒํผ์ ์ ํํ ์๋ ์ฐจ์ด๋ GPU์ ์ ฐ์ด๋์ ์์ ๋ด์ฉ์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. ๋ฐ๋ผ์ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ๋์ ์ ์ฐ์ฑ์ ์ํด ์คํ ๋ฆฌ์ง๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ณดํธ์ ์ ๋๋ค. ์ฑ๋ฅ ์ฐจ์ด๊ฐ ํ๋ก์ ํธ์ ์ค์ง์ ์ธ ์ํฅ์ ์ฃผ์ง ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด ๋ฒค์น๋งํฌ์์ ๋ฒํผ์ ์ ๊ทผํ๋ ๋ค์ํ ๋ฐฉ๋ฒ์ ๋น๊ตํ ์ ์์ต๋๋ค. https://github.com/sebbbi/perftest .
๋์คํฌ๋ฆฝํฐ๋ฅผ ์์ฑํ ๋ ๋์ ๋ฒํผ๋ก ์ค์ ํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค. ๋์ ๋ฒํผ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ๋ช ๋ น์ ๊ธฐ๋กํ ๋ ๋ฒํผ๊ฐ ๋ฐ์ธ๋ฉ๋๋ ์คํ์ ์ ์ ์ดํ ์ ์์ต๋๋ค. ์ด ๋ฐฉ์์ ํ์ฉํ๋ฉด ํ๋์ ์ปค๋ค๋ ๋ฒํผ์ ์ฌ๋ฌ ์ค๋ธ์ ํธ์ ์ ๋ํผ ๋ฐ์ดํฐ๋ฅผ ๋ด๊ณ ๋์คํฌ๋ฆฝํฐ ์ ํ๋๋ก ๋ค์ํ ์คํ์ ์ ๋ฐ์ธ๋ฉํ์ฌ ์ฌ๋ฌ ์ค๋ธ์ ํธ๋ฅผ ๋ ๋๋งํ ์ ์์ต๋๋ค. ์ด๋ ์ ๋ํผ ๋ฒํผ์ ์ ์ด์ธ๋ฆฌ์ง๋ง ์คํ ๋ฆฌ์ง ๋ฒํผ์๋ ๋๋ฐ์ด์ค ์ด๋๋ ์ค๋ฅผ ์ฐ๋ ํธ์ด ์ ํฉํฉ๋๋ค.
Buffer Device Address
์ผ๋ฐ์ ์ผ๋ก ๋ฒํผ๋ ๋์คํฌ๋ฆฝํฐ ์ ์ ํตํด ๋ฐ์ธ๋ฉํด์ผ ํ๋ฉฐ, ์ด๋ CPU์์ ํน์ ๋ฒํผ์ ํฌ๊ธฐ๋ ๋ ์ด์์์ ๋ฏธ๋ฆฌ ์๊ณ ์์ด์ผ ํ๊ณ , ๋์คํฌ๋ฆฝํฐ ์ ์ ์๋ช ๊ด๋ฆฌ๋ ํจ๊ป ๊ณ ๋ คํด์ผ ํ๋ค๋ ์๋ฏธ์ ๋๋ค. ํ์ง๋ง ์ด ํ๋ก์ ํธ์์๋ Vulkan 1.3์ ๋์์ผ๋ก ํ๊ธฐ ๋๋ฌธ์ ๋ฒํผ ๋๋ฐ์ด์ค ์ด๋๋ ์ค๋ผ๋ ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ ํ์ฉํ ์ ์์ต๋๋ค. ์ด๋ int64ํฌ์ธํฐ๋ฅผ GPU๋ก ์ ๋ฌํ์ฌ ์ ฐ์ด๋์์ ์ ๊ทผํ ์ ์๊ฒ ํ๋ฉฐ ํฌ์ธํฐ ์ฐ์ฐ๋ ๊ฐ๋ฅํฉ๋๋ค. C++ ํฌ์ธํฐ์ ๋์ผํ ๋งค์ปค๋์ฆ์ด๋ฉฐ ๋งํฌ๋ ๋ฆฌ์คํธ๋ ๊ฐ์ (indirect) ์ ๊ทผ๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ ๊ตฌํ์ด ๊ฐ๋ฅํฉ๋๋ค.
์ด๋ฅผ ์ ์ ๋ฐ์ดํฐ ์ ๋ฌ์์ฌ์ฉํ ์์ ์ ๋๋ค. ๋๋ฐ์ด์ค ์ด๋๋ ์ค๋ฅผ ํตํ SSBO ์ ๊ทผ์ ๋์คํฌ๋ฆฝํฐ ์ ์ ํตํ ์ ๊ทผ๋ณด๋ค ๋ ๋น ๋ฅด๋ฉฐ, ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ ฐ์ด๋์ ๋ฐ์ธ๋ฉํ ๋ ํธ์์์๋ฅผ ํตํด ๋งค์ฐ ๋น ๋ฅด๊ณ ๊ฐ๋จํ๊ฒ ์ ๋ฌํ ์ ์์ต๋๋ค.
๋ฒํผ ์์ฑํ๊ธฐ
๋ฉ์๋ฅผ GPU๋ก ์ ๋ก๋ ํ๋ ์ฝ๋๋ฅผ ์์ฑํ๊ฒ ์ต๋๋ค. ๋จผ์ ๋ฒํผ๋ฅผ ์์ฑํ ๋ฐฉ๋ฒ์ด ํ์ํฉ๋๋ค.
์ด๋ฅผ vk_types.h
์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
struct AllocatedBuffer {
VkBuffer buffer;
VmaAllocation allocation;
VmaAllocationInfo info;
};
์ด ๊ตฌ์กฐ์ฒด๋ ์ฃผ์ด์ง ๋ฒํผ์ ๊ด๋ จ๋ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ๋ ์ฌ์ฉํ ๊ฒ์
๋๋ค. Vulkan ํธ๋ค์ธ VkBuffer
์ VmaAllocation
, ๊ทธ๋ฆฌ๊ณ ๋ฒํผ๋ฅผ ํด์ ํ ๋ ํ์ํ ๋ฒํผ์ ๋ฒํผ ํ ๋น์ ๊ดํ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ด๋ VmaAllocationInfo
๋ฅผ ํฌํจํฉ๋๋ค.
VulkanEngine
์ ์ด๋ฅผ ์์ฑํ๊ธฐ ์ํ ํจ์๋ฅผ ์ถ๊ฐํฉ๋๋ค.
AllocatedBuffer create_buffer(size_t allocSize, VkBufferUsageFlags usage, VmaMemoryUsage memoryUsage);
ํ ๋น ํฌ๊ธฐ์ usage
ํ๋๊ทธ, ๊ทธ๋ฆฌ๊ณ VmaMemoryUsage
ํ๋๊ทธ๋ฅผ ์ธ์๋ก ๋ฐ์ ๋ฒํผ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ด๋์ ํ ๋น๋ ์ง๋ฅผ ์ ์ดํ ์ ์๋๋ก ํฉ๋๋ค
์๋๋ ๊ตฌํ๋ถ์ ๋๋ค.
AllocatedBuffer VulkanEngine::create_buffer(size_t allocSize, VkBufferUsageFlags usage, VmaMemoryUsage memoryUsage)
{
// allocate buffer
VkBufferCreateInfo bufferInfo = {.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};
bufferInfo.pNext = nullptr;
bufferInfo.size = allocSize;
bufferInfo.usage = usage;
VmaAllocationCreateInfo vmaallocInfo = {};
vmaallocInfo.usage = memoryUsage;
vmaallocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
AllocatedBuffer newBuffer;
// allocate the buffer
VK_CHECK(vmaCreateBuffer(_allocator, &bufferInfo, &vmaallocInfo, &newBuffer.buffer, &newBuffer.allocation,
&newBuffer.info));
return newBuffer;
}
๋จผ์ VkBuffeCreateInfo
๊ตฌ์กฐ์ฒด๋ฅผ ์ฑ์์ผ ํฉ๋๋ค. ์ด ๊ตฌ์กฐ์ฒด์๋ ๋ฒํผ์ ํฌ๊ธฐ์ Usage ํ๋๊ทธ๋ฅผ ์ง์ ํฉ๋๋ค. ๊ทธ ํ VMA๊ฐ ์ฌ์ฉํ ์์ฑ๋ค์ ๋ด๋ AllocationCreateInfo
๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ VmaMemoryUsage
ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ VMA๊ฐ ๋ฒํผ๋ฅผ ์ด๋ค ๋ฉ๋ชจ๋ฆฌ ํ์
์ ๋ฐฐ์นํ ์ง ์ ์ดํ ์ ์์ต๋๋ค. ์ด๋ฏธ์ง์ ๊ฒฝ์ฐ GPU์์ ์ ๊ทผํ ์ ์๋ ๊ฐ์ฅ ๋น ๋ฅธ ๊ณต๊ฐ์ธ ๋๋ฐ์ด์ค ์ ์ฉ ๋ฉ๋ชจ๋ฆฌ์ ํ ๋นํ์ต๋๋ค. ํ์ง๋ง ๋ฒํผ์์๋ CPU์์ ์ง์ ์ธ์ ์๋๋ก ๋ง๋ค ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํด์ผ ํฉ๋๋ค. ์ด๋ ์ฃผ ์ฌ์ฉ ๋ชฉ์ ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ค.
VMA_MEMORY_USAGE_GPU_ONLY
๋ GPU ์ ์ฉ ๋ฉ๋ชจ๋ฆฌ์ ๋๋ค. ์ด ๋ฉ๋ชจ๋ฆฌ๋ GPU VRAM ๊ณต๊ฐ์ ์์นํ๋ฏ๋ก CPU์์ ์ฝ๊ณ ์ธ ์ ์์ง๋ง, ์ ฐ์ด๋์์ ์ฝ๊ณ ์ฐ๊ธฐ๊ฐ ๊ฐ์ฅ ๋น ๋ฆ ๋๋ค.VMA_MEMORY_USAGE_CPU_ONLY
๋ CPU RAM์ ์๋ ๊ณต๊ฐ์ ๋๋ค. ์ด๋ CPU์์ ์ธ ์ ์์ง๋ง GPU๋ ์ฝ๊ธฐ๋ง ํ ์ ์์ต๋๋ค. ์ด๊ฒ์ CPU RAM์ด GPU ์ธ๋ถ์ ์์ด์ ๊ทธ๋ฐ ๊ฒ์ด๋ผ๋ ์ฌ์ค์ ๋ช ์ฌํ์ธ์. GPU์์ RAM์ ์ ๊ทผํ ๋์๋ ์ฑ๋ฅ ์์ค์ด ์ผ์ด๋ ์ ์์ต๋๋ค. ํ๋ ์๋ง๋ค ์์ฃผ ๋ณ๊ฒฝ๋๋ ๋ฐ์ดํฐ๋, ์ ๊ทผ ์๋๊ฐ ํฌ๊ฒ ์ค์ํ์ง ์์ ์๋์ ๋ฐ์ดํฐ์ ์ ์ฉํฉ๋๋ค.VMA_MEMORY_USAGE_CPU_TO_GPU
๋ CPU์์ ์ฐ๊ธฐ๊ฐ ๊ฐ๋ฅํ๊ณ , GPU์์๋ ๋น๊ต์ ๋น ๋ฅด๊ฒ ์ ๊ทผํ ์ ์๋ ๋ฉ๋ชจ๋ฆฌ์ ๋๋ค. Vulkan 1.2๋ฒ์ ์ด์์์๋ GPU๊ฐ ์์ฒด VRAM ๋ด์ CPU์์ ์ฐ๊ธฐ ๊ฐ๋ฅํ ์์ ์์ญ์ ์ ๊ณตํ๋๋ฐ, ์ด ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ฌ๊ธฐ์ ํด๋นํฉ๋๋ค. Resizable BAR๋ฅผ ์ฌ์ฉํ์ง ์๋ ํ ์ฉ๋์ ์ ํ์ ์ด์ง๋ง, CPU์์ ์ง์ ์ฐ๊ณ GPU์์๋ ๋น ๋ฅด๊ฒ ์ ๊ทผํ ์ ์๋ ์ฅ์ ์ด ์์ต๋๋ค.VMA_MEMORY_USAGE_GPU_TO_CPU
๋ CPU์์ ์์ ํ๊ฒ ์ฝ์ด์ผ ํ๋ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ ๋ ์ฌ์ฉํฉ๋๋ค.
VMA_ALLOCATION_CREATE_MAPPED_BIT
์ ๋ชจ๋ ๋ฒํผ ํ ๋น์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ด๋ VMA๊ฐ ํฌ์ธํฐ๋ฅผ ์๋์ผ๋ก ๋งคํํ์ฌ ๋ฒํผ๊ฐ CPU์์ ์ ๊ทผ ๊ฐ๋ฅํ ๊ฒฝ์ฐ ๋ฐ๋ก ๋ฉ๋ชจ๋ฆฌ์ ์ธ ์ ์์ต๋๋ค. VMA๋ ์ด ํฌ์ธํฐ๋ฅผ allocationInfo์ ์ ์ฅํฉ๋๋ค.
๋ฒํผ ์์ฑ ํจ์๋ฅผ ๋ง๋ค์์ผ๋ฏ๋ก ํ๊ดด ํจ์๋ ํ์ํฉ๋๋ค. ๋ฒํผ๋ฅผ ํ๊ดดํ ๋์๋ vmaDestroyBuffer
๋ง ํธ์ถํ๋ฉด ๋ฉ๋๋ค.
void VulkanEngine::destroy_buffer(const AllocatedBuffer& buffer)
{
vmaDestroyBuffer(_allocator, buffer.buffer, buffer.allocation);
}
์ด๋ฅผ ํตํด ๋ฉ์ ๊ตฌ์กฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ ์ ๋ฒํผ๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
GPU์์์ ๋ฉ์ ๋ฒํผ
vk_types.h
struct Vertex {
glm::vec3 position;
float uv_x;
glm::vec3 normal;
float uv_y;
glm::vec4 color;
};
// holds the resources needed for a mesh
struct GPUMeshBuffers {
AllocatedBuffer indexBuffer;
AllocatedBuffer vertexBuffer;
VkDeviceAddress vertexBufferAddress;
};
// push constants for our mesh object draws
struct GPUDrawPushConstants {
glm::mat4 worldMatrix;
VkDeviceAddress vertexBuffer;
};
์ฐ๋ฆฌ๋ ์ ์ ํฌ๋งท์ด ํ๋ฏ๋ก ์ฌ๊ธฐ์๋ ์ด ํฌ๋งท์ ์ฌ์ฉํ๊ฒ ์ต๋๋ค. ์ ์ ํฌ๋งท์ ์ ์ํ ๋๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ฅํ ํ ์์ถํ๋ ๊ฒ์ด ๋งค์ฐ ์ค์ํ์ง๋ง, ํ์ฌ ํํ ๋ฆฌ์ผ ๋จ๊ณ์์๋ ์ฑ๋ฅ์ ํฐ ์ํฅ์ ์ฃผ์ง ์์ผ๋ฏ๋ก ์ฐ์ ์ ๊ฐ๋จํ๊ฒ ์งํํ๊ฒ ์ต๋๋ค. ์ดํ ๋จ๊ณ์์ ์ด ์ ์ ํฌ๋งท์ ์ต์ ํํ ์์ ์ ๋๋ค. UV ๋ณ์๊ฐ ์ค๊ฐ์ ์ฝ์ ๋ ์ด์ ๋ GPU์ ์ ๋ ฌ ์ ํ ๋๋ฌธ์ ๋๋ค. ์ด ๊ตฌ์กฐ์ฒด๋ฅผ ์ ฐ์ด๋์์ ์ฌ์ฉํ๋ ๊ตฌ์กฐ์ ๋์ผํ๊ฒ ๋ง์ถ๋ ๊ฒ์ด ์ค์ํ๊ธฐ ๋๋ฌธ์, ์ด๋ฐ ๋ฐฉ์์ ํฌ๋งท์ด ์ฑ๋ฅ์ด๋ ํธํ์ฑ ์ธก๋ฉด์์ ๋ ๋ฐ๋์งํฉ๋๋ค.
๋ฉ์ ๋ฐ์ดํฐ๋ฅผ GPUMeshBuffers
๊ตฌ์กฐ์ฒด์ ๋ด์ ๊ฒ์
๋๋ค. ์ด ๊ตฌ์กฐ์ฒด๋ ์ ์ ๊ณผ ์ธ๋ฑ์ค ๋ฒํผ ๋ชจ๋๋ฅผ ํฌํจํ๋ฉฐ, ์ ์ ๋ฒํผ์ ๋ฒํผ ๋๋ฐ์ด์ค ์ด๋๋ ์ค๋ฅผ ํฌํจํฉ๋๋ค.
๋ฉ์๋ฅผ ๋ ๋๋งํ ๋ ํ์ํ ํธ์์์ ๊ตฌ์กฐ์ฒด๋ ์ ์ํ ๊ฒ์ด๋ฉฐ, ์ด ๊ตฌ์กฐ์ฒด์๋ ๊ฐ์ฒด์ ๋ณํ ํ๋ ฌ๊ณผ ๋ฉ์ ๋ฒํผ์ ๋๋ฐ์ด์ค ์ด๋๋ ์ค๋ฅผ ๋ด์ ๊ฒ์ ๋๋ค.
์ด๋ฌํ ๋ฒํผ๋ฅผ ์์ฑํ๊ณ GPU์ ์ ๋ก๋ํ๋ ํจ์๋ฅผ ์์ฑํด๋ด ์๋ค.
GPUMeshBuffers VulkanEngine::uploadMesh(std::span<uint32_t> indices, std::span<Vertex> vertices)
{
const size_t vertexBufferSize = vertices.size() * sizeof(Vertex);
const size_t indexBufferSize = indices.size() * sizeof(uint32_t);
GPUMeshBuffers newSurface;
//create vertex buffer
newSurface.vertexBuffer = create_buffer(vertexBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
VMA_MEMORY_USAGE_GPU_ONLY);
//find the adress of the vertex buffer
VkBufferDeviceAddressInfo deviceAdressInfo{ .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,.buffer = newSurface.vertexBuffer.buffer };
newSurface.vertexBufferAddress = vkGetBufferDeviceAddress(_device, &deviceAdressInfo);
//create index buffer
newSurface.indexBuffer = create_buffer(indexBufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VMA_MEMORY_USAGE_GPU_ONLY);
}
์ด๋ฅผ VulkanEngine
ํด๋์ค ์ ์ธ์ ์ถ๊ฐํฉ๋๋ค.
์ด ํจ์๋ ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ํ Vertex
ํ์
์ std::span
๊ณผ ์ธ๋ฑ์ค๋ฅผ ์ํ int
ํ์
์ std::span
์ ์ธ์๋ก ๋ฐ์ต๋๋ค. std::span
์ ํฌ์ธํฐ์ ํฌ๊ธฐ๋ก ๊ตฌ์ฑ๋ ๊ตฌ์กฐ๋ก, C ์คํ์ผ์ ๋ฐฐ์ด์ด๋ std::vector
์์ ๋ณํํ ์๋ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ถํ์ํ ๋ฐ์ดํฐ ๋ณต์ฌ๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
๋จผ์ ํ์ํ ๋ฒํผ๊ฐ ์ผ๋ง๋ ํฐ์ง ๊ณ์ฐํ๊ณ , GPU ์ ์ฉ ๋ฉ๋ชจ๋ฆฌ์ ๋ฒํผ๋ฅผ ์์ฑํฉ๋๋ค.
์ ์ ๋ฒํผ์๋ ๋ค์๊ณผ ๊ฐ์ Usage ํ๋๊ทธ๋ฅผ ์ฌ์ฉํฉ๋๋ค. SSBO๋ฅผ ์ํดVK_BUFFER_USAGE_STORAGE_BUFFER_BIT
๋ฅผ, ๋ฒํผ ๋๋ฐ์ด์ค ์ด๋๋ ์ค๋ฅผ ๋ฐ์์ค๊ธฐ ์ํด VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
์ธ๋ฑ์ค ๋ฒํผ์๋ VK_BUFFER_USAGE_INDEX_BUFFER_BIT
๋ฅผ ์ฌ์ฉํด ํด๋น ๋ฒํผ๋ฅผ ์ธ๋ฑ์ค ๋๋ก์ฐ ํธ์ถ์ ์ฌ์ฉํ ๊ฒ์ด๋ผ๊ณ Vulkan์๊ฒ ์๋ ค์ค๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ ๋ฒํผ ๋ชจ๋์ VK_BUFFER_USAGE_TRANSFER_DST_BIT
๋ฅผ ์ฌ์ฉํ๋๋ฐ ์ด๋ ๋ฉ๋ชจ๋ฆฌ ๋ณต์ฌ ๋ช
๋ น์ ์ํํ๊ธฐ ์ํด์์
๋๋ค.
๋ฒํผ ๋๋ฐ์ด์ค ์ด๋๋ ์ค๋ฅผ ์ป๊ธฐ ์ํด vkGetBufferDeviceAddress
๋ฅผ ํธ์ถํด์ผ ํฉ๋๋ค.์ฃผ์๋ฅผ ์กฐํํ๊ณ ์ ํ๋ VkBuffer
๋ฅผ ์ ๋ฌํด์ผ ํฉ๋๋ค. VkDeviceAddress
๋ฅผ ์ป๊ณ ๋๋ฉด, ํฌ์ธํฐ ์ฐ์ฐ๋ ๊ฐ๋ฅํ๋ฉฐ, ์ด๋ ์ปค๋ค๋ ๋ฒํผ์ ํ์ํ ๋น์ ํ ๋ ์ ์ฉํฉ๋๋ค.
๋ฒํผ๋ฅผ ํ ๋นํ ์ดํ์๋ ๋ฒํผ์ ๋ฐ์ดํฐ๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ์ํด Vulkan์์ ํํ ์ฌ์ฉ๋๋ ๋ฐฉ์์ธ ์คํ ์ด์ง ๋ฒํผ๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. GPU_ONLY ๋ฉ๋ชจ๋ฆฌ๋ CPU์์ ์ง์ ์ ๊ทผํ ์ ์๊ธฐ ๋๋ฌธ์ ๋จผ์ CPU ์ฐ๊ธฐ ๊ฐ๋ฅํ ์์ ์คํ ์ด์ง ๋ฒํผ์ ๋ฉ๋ชจ๋ฆฌ์ ์์ฑํ๊ณ , ์ดํ ๋ณต์ฌ ๋ช ๋ น์ ํตํด GPU ์ ์ฉ ๋ฒํผ๋ก ๋ณต์ฌํฉ๋๋ค. mesh์ ๊ผญ GPU_ONLY ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉํ ํ์๋ ์์ง๋ง, CPU์์ ํํฐํด ์์คํ ์ด๋ ๋ค๋ฅธ ๋์ ํจ๊ณผ๊ฐ ์๋ ํ GPU_ONLY ๋ฒํผ๋ฅผ ๊ถ์ฅํฉ๋๋ค.
AllocatedBuffer staging = create_buffer(vertexBufferSize + indexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
void* data = staging.allocation->GetMappedData();
// copy vertex buffer
memcpy(data, vertices.data(), vertexBufferSize);
// copy index buffer
memcpy((char*)data + vertexBufferSize, indices.data(), indexBufferSize);
immediate_submit([&](VkCommandBuffer cmd) {
VkBufferCopy vertexCopy{ 0 };
vertexCopy.dstOffset = 0;
vertexCopy.srcOffset = 0;
vertexCopy.size = vertexBufferSize;
vkCmdCopyBuffer(cmd, staging.buffer, newSurface.vertexBuffer.buffer, 1, &vertexCopy);
VkBufferCopy indexCopy{ 0 };
indexCopy.dstOffset = 0;
indexCopy.srcOffset = vertexBufferSize;
indexCopy.size = indexBufferSize;
vkCmdCopyBuffer(cmd, staging.buffer, newSurface.indexBuffer.buffer, 1, &indexCopy);
});
destroy_buffer(staging);
return newSurface;
๋จผ์ ์คํ
์ด์ง ๋ฒํผ๋ฅผ ์์ฑํฉ๋๋ค. ์ด ๋ฒํผ ํ๋๋ก ์ธ๋ฑ์ค ๋ฒํผ์ ์ ์ ๋ฒํผ๋ก์ ๋ณต์ฌ๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํ ๊ฒ์
๋๋ค. ์คํ
์ด์ง ๋ฒํผ์ ๋ฉ๋ชจ๋ฆฌ ํ์
์ CPU_ONLY ์ด๋ฉฐ Usage ํ๋๊ทธ๋ ๋ณต์ฌ๋ง ์ํํ๊ธฐ ๋๋ฌธ์ VK_BUFFER_USAGE_TRANSFER_SRC_BIT
์
๋๋ค.
๋ฒํผ๊ฐ ์์ฑ๋๋ฉด GetMappedData()
๋ฅผ ํตํด ๋งคํ๋ ์ฃผ์๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค. ์ด๋ void* ํํ์ ํฌ์ธํฐ๋ก, ์ง์ ๋ฐ์ดํฐ๋ฅผ ์ธ ์ ์์ต๋๋ค. memcpy๋ฅผ ๋ ๋ฒ ์ฌ์ฉํ์ฌ ๊ฐ span์ ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํฉ๋๋ค.
์คํ
์ด์ง ๋ฒํผ๊ฐ ์์ฑ๋๋ฉด immediate_submit
์ ์คํํด GPU ์ธก์์์ ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ๋ ๋ช
๋ น์ ์ํํฉ๋๋ค. ์ด ๋ช
๋ น์ 2๊ฐ์ VkCmdCopyBuffer
๋ช
๋ น์ ์ํํฉ๋๋ค. ์ด๋ GPU์์ ์ํ๋๋ memcpy
์ญํ ์
๋๋ค. ์ฌ์ฉ๋ VkBufferCopy
๊ตฌ์กฐ์ฒด๋ ์คํ
์ด์ง ๋ฒํผ์ ๋ฐ์ดํฐ๋ฅผ ์ธ ๋ ์ํํ๋ memcpy
๋ฅผ ๊ทธ๋๋ก ๋ฐ์ํ๋ ํํ์
๋๋ค.
immediate submit์ด ์ํ๋๋ฉด ์์ ํ๊ฒ ์คํ ์ด์ง ๋ฒํผ๋ฅผ ํด์ ํ ์ ์์ต๋๋ค.
GPU ๋ช ๋ น์ ์์ ํ ์คํ๋ ๋ ๊น์ง CPU ์ธก์ด ๋๊ธฐํด์ผ ํ๊ธฐ ๋๋ฌธ์ ์ด ํจํด์ด ํจ์จ์ ๋ง์ ์๋ค๋ ์ ์ ๋ช ์ฌํ์ธ์. ์ด๋ฌํ ๋ฐ์ดํฐ ์ ๋ก๋๋ ์ผ๋ฐ์ ์ผ๋ก ๋ฐฑ๊ทธ๋ผ์ด๋ ์ฐ๋ ๋์์ ์ํํ๋ ํธ์ด ์ข์ต๋๋ค.
๋ฉ์ ๊ทธ๋ฆฌ๊ธฐ
์ง๊ธ๊น์ง ๋ง๋ ํจ์๋ค์ ์ฌ์ฉํด ๋ฉ์๋ฅผ ์์ฑํ๊ณ ์ค์ ๋ก ๋ ๋๋ง์ ์ํํด ๋ด ์๋ค. ์ผ๊ฐํ์ ์กฐํฉํ์ฌ ์ธ๋ฑ์ฑ๋ ์ฌ๊ฐํ์ ๊ทธ๋ฆด ๊ฒ์ ๋๋ค.
์ ์ ๋ฒํผ๋ฅผ ์ฌ์ฉํ๊ฒ ๋์์ผ๋ฏ๋ก, ์
ฐ์ด๋๋ ์ด์ ๋ง๊ฒ ์์ ํด์ผ ํฉ๋๋ค. ํ๋๊ทธ๋จผํธ ์
ฐ์ด๋๋ ๊ธฐ์กด๊ณผ ๋์ผํ๊ฒ colored_triangle.frag
๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ฉฐ, ์ ์ ์
ฐ์ด๋๋ง ๋ฐ์ดํฐ๋ฅผ ํธ์ ์์์์ ๋ถ๋ฌ์ค๋๋ก ๋ณ๊ฒฝํด์ผ ํฉ๋๋ค. ์ด ์๋ก์ด ์ ์ ์
ฐ์ด๋๋ ๊ธฐ์กด์ ํ๋์ฝ๋ฉ๋ ์ผ๊ฐํ ์
ฐ์ด๋์ ์ ์ฌํ๋ฏ๋ก, colored_triangle_mesh.vert
๋ผ๋ ์ด๋ฆ์ผ๋ก ์๋ก ์์ฑํ๊ฒ ์ต๋๋ค.
#version 450
#extension GL_EXT_buffer_reference : require
layout (location = 0) out vec3 outColor;
layout (location = 1) out vec2 outUV;
struct Vertex {
vec3 position;
float uv_x;
vec3 normal;
float uv_y;
vec4 color;
};
layout(buffer_reference, std430) readonly buffer VertexBuffer{
Vertex vertices[];
};
//push constants block
layout( push_constant ) uniform constants
{
mat4 render_matrix;
VertexBuffer vertexBuffer;
} PushConstants;
void main()
{
//load vertex data from device adress
Vertex v = PushConstants.vertexBuffer.vertices[gl_VertexIndex];
//output data
gl_Position = PushConstants.render_matrix *vec4(v.position, 1.0f);
outColor = v.color.xyz;
outUV.x = v.uv_x;
outUV.y = v.uv_y;
}
GL_EXT_buffer_reference
ํ์ฅ์ ํ์ฑํํด์ผ ์
ฐ์ด๋ ์ปดํ์ผ๋ฌ๊ฐ ๋ฒํผ ๋ ํผ๋ฐ์ค๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
๊ทธ ํ ์ ์ ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ํฉ๋๋ค. ์ด๋ CPU์์์ ๊ตฌ์กฐ์ฒด์ ๋์ผํฉ๋๋ค.
์ดํ ์ ์ ๋ฒํผ๋ฅผ ์ ์ธํฉ๋๋ค. ์ด ๋ฒํผ๋ ์ ์ ๊ตฌ์กฐ์ฒด (unsized) ๋ฐฐ์ด์ ๊ฐ๋ ์ฝ๊ธฐ ์ ์ฉ ๋ฒํผ์
๋๋ค. layout
์ buffer_reference
๋ฅผ ์ ์ธํจ์ผ๋ก์ ์
ฐ์ด๋์๊ฒ ํด๋น ๊ตฌ์กฐ์ฒด๊ฐ ๋ฒํผ ์ฃผ์ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ๋จ์ ์๋ ค์ค๋๋ค. std430
์ GPU์์ ์ฌ์ฉํ๋ ๋ฉ๋ชจ๋ฆฌ ์ ๋ ฌ ๊ท์น์
๋๋ค.
ํธ์ ์์ ๋ธ๋ญ์๋ ์ ์ ์
ฐ์ด๋์ ๋จ์ผ ์ธ์คํด์ค์ ํ๋ ฌ์ ๋ด๊ณ ์์ต๋๋ค. ์ ์ ๋ฒํผ๊ฐ buffer_reference
๋ก ์ ์ธ๋์์ผ๋ฏ๋ก ์ด๋ ์ค์ ๋ก๋ uint64
ํธ๋ค์ด๋ฉฐ, ํ๋ ฌ์ ์ผ๋ฐ์ ์ธ ํ๋ ฌ์
๋๋ค.
main()์๋ gl_VertexIndex
๋ฅผ ์ฌ์ฉํด ์ ์ ๋ฐฐ์ด์ ์ธ๋ฑ์ฑํฉ๋๋ค. ํ๋์ฝ๋ฉ๋ ๋ฐฐ์ด์์ ์ํํ๋ ๊ฒ๊ณผ ๋์ผํฉ๋๋ค. GLSL์์๋ ๋ฒํผ ์ฐธ์กฐ๋ ์ผ๋ฐ ๋ณ์์ฒ๋ผ ๋ค๋ฃจ๊ธฐ ๋๋ฌธ์ C++ ์ฒ๋ผ ->๊ฐ ์๋๋ผ .
์ ์ฌ์ฉํด ๋ฉค๋ฒ์ ์ ๊ทผํฉ๋๋ค. ์ ์ ์ ์ป์ ํ์๋ ํด๋น ์ ์ ์ ์์๊ณผ ์์น ์ ๋ณด๋ฅผ ์ถ๋ ฅํ๋ฉด ๋ฉ๋๋ค. ์์น๋ ๋ ๋๋ง ํ๋ ฌ๊ณผ ๊ณฑํด์ ธ ๋ณํ๋ฉ๋๋ค.
์ด์ ํ์ดํ๋ผ์ธ์ ์์ฑํ๊ฒ ์ต๋๋ค. ๊ธฐ์กด์ init_triangle_pipeline()
๊ณผ๋ ๋ณ๋๋ก ํ์ดํ๋ผ์ธ์ ๋ง๋ค์ง๋ง ๊ตฌ์กฐ๋ ๊ฑฐ์ ๋์ผํฉ๋๋ค. VulkanEngine์ ์ถ๊ฐํฉ๋๋ค.
VkPipelineLayout _meshPipelineLayout;
VkPipeline _meshPipeline;
GPUMeshBuffers rectangle;
void init_mesh_pipeline();
init_triangle_pipeline()
์ ๊ฑฐ์ ๋ณต์ฌ๋ณธ์ด ๋ ๊ฒ์
๋๋ค.
VkShaderModule triangleFragShader;
if (!vkutil::load_shader_module("../../shaders/colored_triangle.frag.spv", _device, &triangleFragShader)) {
fmt::print("Error when building the triangle fragment shader module");
}
else {
fmt::print("Triangle fragment shader succesfully loaded");
}
VkShaderModule triangleVertexShader;
if (!vkutil::load_shader_module("../../shaders/colored_triangle_mesh.vert.spv", _device, &triangleVertexShader)) {
fmt::print("Error when building the triangle vertex shader module");
}
else {
fmt::print("Triangle vertex shader succesfully loaded");
}
VkPushConstantRange bufferRange{};
bufferRange.offset = 0;
bufferRange.size = sizeof(GPUDrawPushConstants);
bufferRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
VkPipelineLayoutCreateInfo pipeline_layout_info = vkinit::pipeline_layout_create_info();
pipeline_layout_info.pPushConstantRanges = &bufferRange;
pipeline_layout_info.pushConstantRangeCount = 1;
VK_CHECK(vkCreatePipelineLayout(_device, &pipeline_layout_info, nullptr, &_meshPipelineLayout));
์ ์ ์
ฐ์ด๋๋ฅผ colored_triangle_mesh.vert.spv
๋ก ๊ต์ฒดํ๊ณ , ์์์ ์ ์ํ ํธ์ ์์ ๊ตฌ์กฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์๋๋ก ํ์ดํ๋ผ์ธ ๋ ์ด์์์ ์์ ํฉ๋๋ค.
๋๋จธ์ง ํจ์ ๋ด์ฉ์ triangle pipeline ํจ์์ ๋์ผํ์ง๋ง, ํ์ดํ๋ผ์ธ ๋ ์ด์์๊ณผ ํ์ดํ๋ผ์ธ ๊ฐ์ฒด ์ด๋ฆ์ ์๋ก์ด ๊ฒ์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
PipelineBuilder pipelineBuilder;
//use the triangle layout we created
pipelineBuilder._pipelineLayout = _meshPipelineLayout;
//connecting the vertex and pixel shaders to the pipeline
pipelineBuilder.set_shaders(triangleVertexShader, triangleFragShader);
//it will draw triangles
pipelineBuilder.set_input_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
//filled triangles
pipelineBuilder.set_polygon_mode(VK_POLYGON_MODE_FILL);
//no backface culling
pipelineBuilder.set_cull_mode(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE);
//no multisampling
pipelineBuilder.set_multisampling_none();
//no blending
pipelineBuilder.disable_blending();
pipelineBuilder.disable_depthtest();
//connect the image format we will draw into, from draw image
pipelineBuilder.set_color_attachment_format(_drawImage.imageFormat);
pipelineBuilder.set_depth_format(VK_FORMAT_UNDEFINED);
//finally build the pipeline
_meshPipeline = pipelineBuilder.build_pipeline(_device);
//clean structures
vkDestroyShaderModule(_device, triangleFragShader, nullptr);
vkDestroyShaderModule(_device, triangleVertexShader, nullptr);
_mainDeletionQueue.push_function([&]() {
vkDestroyPipelineLayout(_device, _meshPipelineLayout, nullptr);
vkDestroyPipeline(_device, _meshPipeline, nullptr);
});
์ด์ init_pipelines()
ํจ์์์ ์ด๋ฅผ ํธ์ถํฉ๋๋ค.
void VulkanEngine::init_pipelines()
{
//COMPUTE PIPELINES
init_background_pipelines();
// GRAPHICS PIPELINES
init_triangle_pipeline();
init_mesh_pipeline();
}
๋ค์์ ๋ฉ์๋ฅผ ์์ฑํ๊ณ ์
๋ก๋ ํ๋ ๊ฒ์
๋๋ค. ์์ง์ ๊ธฐ๋ณธ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ์๋ก์ด ์ด๊ธฐํ ํจ์ init_default_data()
๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ฅผ init ํจ์์ ๋ง์ง๋ง์ ์ถ๊ฐํฉ๋๋ค.
void VulkanEngine::init_default_data() {
std::array<Vertex,4> rect_vertices;
rect_vertices[0].position = {0.5,-0.5, 0};
rect_vertices[1].position = {0.5,0.5, 0};
rect_vertices[2].position = {-0.5,-0.5, 0};
rect_vertices[3].position = {-0.5,0.5, 0};
rect_vertices[0].color = {0,0, 0,1};
rect_vertices[1].color = { 0.5,0.5,0.5 ,1};
rect_vertices[2].color = { 1,0, 0,1 };
rect_vertices[3].color = { 0,1, 0,1 };
std::array<uint32_t,6> rect_indices;
rect_indices[0] = 0;
rect_indices[1] = 1;
rect_indices[2] = 2;
rect_indices[3] = 2;
rect_indices[4] = 1;
rect_indices[5] = 3;
rectangle = uploadMesh(rect_indices,rect_vertices);
//delete the rectangle data on engine shutdown
_mainDeletionQueue.push_function([&](){
destroy_buffer(rectangle.indexBuffer);
destroy_buffer(rectangle.vertexBuffer);
});
}
์ ์ ๊ณผ ์ธ๋ฑ์ค๋ฅผ ์ํ 2๊ฐ์ ๋ฐฐ์ด์ ๋ง๋ค๊ณ uploadMesh ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ฒํผ๋ก ์ ๋ก๋ํฉ๋๋ค.
์ด์ ๋ ๋๋ง์ ์ํํ ์ ์์ต๋๋ค. draw_geometry()
ํจ์์์ ๊ธฐ์กด์ ์ผ๊ฐํ์ ๊ทธ๋ฆฐ ๋ค, ๊ทธ ์๋์ ์๋ก์ด ๊ทธ๋ฆฌ๊ธฐ ๋ช
๋ น์ ์ถ๊ฐํฉ๋๋ค.
//launch a draw command to draw 3 vertices
vkCmdDraw(cmd, 3, 1, 0, 0);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _meshPipeline);
GPUDrawPushConstants push_constants;
push_constants.worldMatrix = glm::mat4{ 1.f };
push_constants.vertexBuffer = rectangle.vertexBufferAddress;
vkCmdPushConstants(cmd, _meshPipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(GPUDrawPushConstants), &push_constants);
vkCmdBindIndexBuffer(cmd, rectangle.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0);
vkCmdEndRendering(cmd);
์ด๋ฒ์๋ ์ฌ๊ฐํ ๋ฉ์๋ฅผ ์ํ ํ์ดํ๋ผ์ธ์ ๋ฐ์ธ๋ฉํฉ๋๋ค.
๊ทธ ํ, ํธ์ ์์๋ฅผ ์ฌ์ฉํด vertexBufferAddress๋ฅผ GPU๋ก ์ ๋ก๋ ํฉ๋๋ค. ํ๋ ฌ์ ๋ฉ์ ๋ณํ์ ์ํํ ๋ ๊น์ง๋ ๊ธฐ๋ณธ ํ๋ ฌ์ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
๊ทธ ํ vkCmdBindIndexBuffer
๋ฅผ ์ฌ์ฉํด ์ธ๋ฑ์ค ๋ฒํผ๋ฅผ ๋ฐ์ธ๋ฉํฉ๋๋ค. ์์ฝ๊ฒ๋ ์ฌ๊ธฐ์๋ ๋๋ฐ์ด์ค ์ด๋๋ ์ค๋ฅผ ์ฌ์ฉํ ์ ์๊ณ , ๋์ VkBuffer
์ ์คํ์
์ ์ ๋ฌํด์ผ ํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก vkCmdDrawIndexed
๋ฅผ ์ฌ์ฉํด 2๊ฐ์ ์ผ๊ฐํ(6๊ฐ์ ์ธ๋ฑ์ค)๋ฅผ ๊ทธ๋ฆฝ๋๋ค. ์ด๋ vkCmdDraw
์ ๊ฐ์ง๋ง ํ์ฌ ๋ฐ์ธ๋ฉ๋ ์ธ๋ฑ์ค ๋ฒํผ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ์๋ฅผ ๊ทธ๋ฆฐ๋ค๋ ์ ์ด ๋ค๋ฆ
๋๋ค.
์ด๊ฒ์ผ๋ก ๋๋ฌ์ต๋๋ค. ์ด์ ์ด๋ค ๋ฉ์๋ ๋ ๋๋งํ ์ ์๋ ์ผ๋ฐ์ ์ธ ์๋จ์ด ๋ง๋ จ๋์์ต๋๋ค.
๋ค์์ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก GLTF๋ก๋ถํฐ ๋ฉ์ ํ์ผ์ ๋ถ๋ฌ์ ์ฌ๊ฐํ๋ณด๋ค๋ ๋ ๋ณต์กํ๊ณ ๋ฉ์๋ ๊ฒ์ ๋ค๋ค๋ณด๊ฒ ์ต๋๋ค.
Next: Mesh Loading