VkGraphicsPipelineCreateInfo
๊ทธ๋ํฝ์ค ํ์ดํ๋ผ์ธ์ ๋ง๋๋ ๊ณผ์ ์ ์ปดํจํธ ํ์ดํ๋ผ์ธ์ ๋ง๋ค ๋ ๋ณด๋ค ๊ฝค ๋ง์ ์์ ์ด ์ถ๊ฐ๋ก ํ์ํฉ๋๋ค. ์ปดํจํธ ํ์ดํ๋ผ์ธ์์๋ ๋จ์ผ ์ ฐ์ด๋ ๋ชจ๋๊ณผ ํ์ดํ๋ผ์ธ๋ง ํ์ํ์ต๋๋ค. ๋ฐ๋ผ์ ์ด๋ ํ ์ถ์ ๊ณ์ธต๋ ํ์๊ฐ ์์์ง๋ง, ๊ทธ๋ํฝ์ค ํ์ดํ๋ผ์ธ์ ์ค์ ํด์ผ ํ ์ต์ ์ด ์๋นํ ๋ง๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๋จ์ํํ์ง ์์ผ๋ฉด ์์ฑ ๊ณผ์ ์ด ์๋นํ ๋ณต์กํด์ง ๊ฒ์ ๋๋ค.
์ด๋ฌํ ์ด์ ๋ก, PipelineBuilder
๋ผ๋ ๊ตฌ์กฐ์ฒด๋ฅผ ์ถ๊ฐํ์ฌ ์ด๋ฌํ ๋ชจ๋ ์ต์
์ ์ถ์ ํ๋ ค ํฉ๋๋ค. ์ด ๊ตฌ์กฐ์ฒด๋ ๊ฐ๋ฅํ ๋ง์ ํญ๋ชฉ์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ ์งํ๋ฉด์, ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ธฐ๋ฅ๋ง ํ์ฑํ/๋นํ์ฑํํ๋ ๋จ์ํ ํจ์๋ฅผ ์ ๊ณตํ ๊ฒ์
๋๋ค. ํํ ๋ฆฌ์ผ์์๋ ์ฌ์ฉํ ์ค์ ์ด ๋ง์ง ์๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ณต์ก์ฑ์ ์ค์ด๋ ๊ฒ์ด ์ ์ฉํฉ๋๋ค.
ํ์ดํ๋ผ์ธ์ ์ด๋ฌํ ์ต์ ์ค ์ผ๋ถ๋ ๋์ ์ผ๋ก ์ค์ ๋ ์ ์์ผ๋ฉฐ, ์ด๋ ํ์ดํ๋ผ์ธ์ ๋ฐ์ธ๋ฉํ ๋์ ๊ทธ๋ฆฌ๊ธฐ ๋ช ๋ น์ ๊ธฐ๋กํ ๋ ํด๋น ์ต์ ์ ์ง์ ํ ์ ์๋ค๋ ์๋ฏธ์ ๋๋ค. ์๋ฅผ ๋ค์ด viewport๋ฅผ ๋์ ์ผ๋ก ์ง์ ํ ์์ ์ธ๋ฐ, ๋ง์ฝ ์ด๋ฅผ ๊ตฝ๋(baked in) ๋ฐฉ์์ผ๋ก ์ค์ ํ๋ฉด ๋ ๋๋ง ํด์๋๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ถ์ ๋๋ง๋ค ์๋ก์ด ํ์ดํ๋ผ์ธ์ ์์ฑํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
Builder๋ฅผ ์์ฑํ๊ธฐ ์ ์, ๋ฌด์์ ์ฑ์์ผ ํ๋์ง ๋จผ์ ์ดํด๋ด
์๋ค. ์ปดํจํธ ํ์ดํ๋ผ์ธ์ ์์ฑํ ๋์ ๊ฐ์ด ๊ทธ๋ํฝ์ค ํ์ดํ๋ผ์ธ์ VkGraphicsPipelineCreateInfo
๊ตฌ์กฐ์ฒด๋ฅผ ์ฑ์์ผ ํฉ๋๋ค.
typedef struct VkGraphicsPipelineCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineCreateFlags flags;
uint32_t stageCount;
const VkPipelineShaderStageCreateInfo* pStages;
const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
const VkPipelineTessellationStateCreateInfo* pTessellationState;
const VkPipelineViewportStateCreateInfo* pViewportState;
const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
const VkPipelineDynamicStateCreateInfo* pDynamicState;
VkPipelineLayout layout;
VkRenderPass renderPass;
uint32_t subpass;
VkPipeline basePipelineHandle;
int32_t basePipelineIndex;
} VkGraphicsPipelineCreateInfo;
๊ทธ๋ํฝ์ค ํ์ดํ๋ผ์ธ์ ๊ดํ ์ ๋ณด๋ ๋ค์ ๋งํฌ์์ ์ธ๋ถ ์ฌํญ์ ํ์ธํ ์ ์์ต๋๋ค.
stageCount
์ pStages
๋ ํ์ดํ๋ผ์ธ์ ๊ฐ ์
ฐ์ด๋ ๋จ๊ณ์ ํด๋นํ๋ ์
ฐ์ด๋ ๋ชจ๋ ์ ๋ณด๋ฅผ ๋ด๋ VkPipelineShaderStageCreateInfo
๋ฅผ ํฌํจํฉ๋๋ค. ์ฌ๊ธฐ์๋ ์ ์ ์
ฐ์ด๋์ ํ๋๊ทธ๋จผํธ ์
ฐ์ด๋๋ฅผ ์ ๋ฌํ ๊ฒ์
๋๋ค.
VkPipelineVertexInputStateCreateInfo
๋ ์ ์ ๋ฒํผ์ ์ฌ์ฉํ ์ ์ ์์ฑ ์
๋ ฅ ๊ตฌ์ฑ์ ๋ด์ต๋๋ค. ์ด๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ค์ ํ๋ฉด ์ ์ ์
ฐ์ด๋๋ ์ ์ ์์ฑ์ ์ต์ ํ๋ ๋ฐฉ์์ผ๋ก ์
๋ ฅ๋ฐ์ ์ ์์ต๋๋ค. ํ์ง๋ง ์ฐ๋ฆฌ๋ ์ด๋ฅผ ์ฌ์ฉํ์ง๋ ์์ ๊ฒ์
๋๋ค. ์
ฐ์ด๋์ ๋ฐ์ดํฐ์ ๋ฐฐ์ด์ ์ง์ ์ ๋ฌํ์ฌ ์ธ๋ฑ์ฑํ์ฌ ์ฌ์ฉํ ๊ฒ์
๋๋ค. ์ด ๋ฐฉ์์ ์ฑ๋ฅ์ ํฅ์์ํค๊ณ ๋ฐ์ดํฐ ์์ถ์ด ์ ์ฉ๋ ๋ ๋ณต์กํ ์ ์ ํฌ๋งท์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋ฐฉ์์ ์ผ๋ฐ์ ์ผ๋ก ์ ์ ํ๋ง(vertex pulling)์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ฉฐ, ๊ณ ์ ํ๋์จ์ด ๋ฐฉ์์ ์ ์ ์
๋ ฅ๊ณผ ๋์ผํ ์์
์ ์ํํ๋๋ผ๋, ํ๋ GPU์์๋ ๊ฑฐ์ ๋์ผํ ์ฑ๋ฅ์ ๋ณด์
๋๋ค.
VkPipelineInputAssemblyStateCreateInfo
๋ ์ผ๊ฐํ ํ ํด๋ก์ง๋ฅผ ๋ด์ต๋๋ค. ์ด ๊ตฌ์กฐ์ฒด๋ฅผ ํตํด ํ์ดํ๋ผ์ธ์ด ์ผ๊ฐํ, ์ , ์ ์ค ์ด๋ค ๋ํ์ ๊ทธ๋ฆด ์ง ์ค์ ํ ์ ์์ต๋๋ค.
VkPipelineTessellationStateCreateInfo
๋ ๊ณ ์ ๊ธฐ๋ฅ ํ
์
๋ ์ด์
์ ๊ตฌ์ฑํฉ๋๋ค. ์ด๋ฅผ ์ฌ์ฉํ์ง ์์ ๊ฒ์ด๋ฏ๋ก null๋ก ์ค์ ํ ๊ฒ์
๋๋ค.
VkPipelineViewportStateCreateInfo
๋ ํฝ์
์ด ๋ ๋๋ง๋ ๋ทฐํฌํธ์ ์ ๋ณด๋ฅผ ๋ด์ต๋๋ค. ์ด๋ ํ์ดํ๋ผ์ธ์ด ์ด๋ค ์์ญ์ ํฝ์
์ ๊ทธ๋ฆด์ง๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๋์ ์ํ๋ฅผ ์ฌ์ฉํ ๊ฒ์ด๋ฏ๋ก ์ด๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ค์ ํ ๊ฒ์
๋๋ค.
VkPipelineRasterizationStateCreateInfo
๋ ์ ์ ์
ฐ์ด๋์ ํ๋๊ทธ๋จผํธ ์
ฐ์ด๋ ๊ฐ ์ผ๊ฐํ์ ์ด๋ป๊ฒ ๋์คํฐํํ ์ง์ ๋ํ ์ ๋ณด๋ฅผ ๋ด์ต๊ณ ์์ต๋๋ค. ์ด๋ ๊น์ด ๋ฐ์ด์ด์ค(๊ทธ๋ฆผ์ ๋ ๋๋ง์ ์ฌ์ฉ๋ฉ๋๋ค), ์์ด์ดํ๋ ์๊ณผ ์๋ฆฌ๋ ๋ ๋๋ง ์ ํ, ๊ทธ๋ฆฌ๊ณ ๋ท๋ฉด ๋ ๋๋ง ์ฌ๋ถ ๋ฑ์ ์ต์
์ ์ ๊ณตํฉ๋๋ค.
VkPipelineMultisampleStateCreateInfo
๋ ๋ฉํฐ ์ํ๋ง ์ํฐ ์จ๋ฆฌ์ด์ฑ์ ๊ตฌ์ฑํ ์ ์๋๋ก ํฉ๋๋ค. ์ด๋ ์ผ๊ฐํ์ ๊ฒฝ๊ณ์์ ํ๋๊ทธ๋จผํธ๋ฅผ ์ฌ๋ฌ ๋ฒ ๋์คํฐํํจ์ผ๋ก์ ๋ ๋๋ง ํ์ง์ ํฅ์์ํค๋ ๊ธฐ๋ฒ์
๋๋ค. ์ํฐ ์จ๋ฆฌ์ด์ฑ์ ์ ์ฉํ์ง ์์ ๊ฒ์ด๋ฏ๋ก ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ค์ ํ์ง๋ง, ์ถํ ์ด๋ฅผ ์ ์ฉํ๋ ๊ฒ๋ ๊ณ ๋ คํ ๊ฒ์
๋๋ค.
VkPipelineDepthStencilStateCreateInfo
๋ ๊น์ด ํ
์คํธ์ ์คํ
์ค ์ค์ ์ ๋ณด๋ฅผ ๋ด์ต๋๋ค.
VkPipelineColorBlendStateCreateInfo
๋ ๋ธ๋ ๋ฉ๊ณผ ์ดํ์น ๋จผํธ ์ฐ๊ธฐ ์ค์ ์ ๋ด์ต๋๋ค. ํฌ๋ช
ํ ์ผ๊ฐํ์ ๋ ๋๋งํ๊ฑฐ๋ ๋ค์ํ ๋ธ๋ ๋ฉ ์ค์ ์ ์ฌ์ฉ๋ฉ๋๋ค.
VkPipelineDynamicStateCreateInfo
๋ ๋์ ์ํ๋ฅผ ๊ตฌ์ฑํ๋ ๊ตฌ์กฐ์ฒด์
๋๋ค. Vulkan ํ์ดํ๋ผ์ธ์ ๊ฐ์ฅ ํฐ ๋จ์ ์ค ํ๋๋ ํ์ดํ๋ผ์ธ ์ค์ ์ด ์์ฑ ์์ โํ๋์ฝ๋ฉโ ๋๋ค๋ ์ ์
๋๋ค. ์๋ฅผ ๋ค์ด ๊น์ด ํ
์คํธ๋ฅผ ์ผ๊ฑฐ๋ ๋๋ ๊ธฐ๋ฅ์ ์ํ๋ค๋ฉด 2๊ฐ์ ํ์ดํ๋ผ์ธ์ด ํ์ํ ๊ฒ์
๋๋ค. ๋ทฐํฌํธ๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค. ๋ ๋ ํ๊ฒ์ ํฌ๊ธฐ๋ฅผ ๋ฐ๊พธ๋ ค๋ฉด ๋ชจ๋ ํ์ดํ๋ผ์ธ์ ์ฌ๊ตฌ์ฑํด์ผ ํฉ๋๋ค. ํ์ดํ๋ผ์ธ์ ์์ฑํ๋ ๊ณผ์ ์ ๋งค์ฐ ๋ฌด๊ฑฐ์ด ์์
์ด๊ธฐ ๋๋ฌธ์ ํ์ดํ๋ผ์ธ์ ์๋ฅผ ๊ฐ๋ฅํ ํ ์ค์ด๋ ๊ฒ์ด ์ฑ๋ฅ์ ์ผ๋ก ์ค์ํฉ๋๋ค. ์ด๋ฌํ ์ด์ ๋ก, Vulkan ํ์ดํ๋ผ์ธ์ ์ผ๋ถ ์ํ๋ ๋์ ์ผ๋ก ์ค์ ๋ ์ ์์ผ๋ฉฐ, ์ด ๋ ์ค์ ๋ ์ต์
์ ๋ ๋๋ง ๋ช
๋ น์ ๊ธฐ๋กํ ๋ ๋ฐํ์์ ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค. ์ด๋ค ๋์ ์ํ๋ฅผ ์ง์ํ๋์ง๋ GPU ์ ์กฐ์ฌ, ๋๋ผ์ด๋ฒ ๋ฒ์ , ๊ธฐํ ํ๊ฒฝ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ์ ์์ต๋๋ค. ๋๋ถ๋ถ์ GPU๊ฐ ๋ทฐํฌํธ์ ๊ฐ์ ์ค์ ์ ๋ํ ๋์ ์ํ๋ฅผ ์ง์ํ๋ฏ๋ก, ์ฐ๋ฆฌ๋ ํด๋น ํญ๋ชฉ์ ๋์ ์ํ๋ก ์ค์ ํ ๊ฒ์
๋๋ค. ์ด๋ฅผ ํตํด ํ์ดํ๋ผ์ธ ์์ฑ ์์ ์ ์ด๋ฏธ์ง ํด์๋๋ฅผ ๊ณ ์ ํ ํ์ ์์ด ์ ์ฐํ๊ฒ ๋์ํ ์ ์์ต๋๋ค.
VkGraphicsPipelineCreateInfo
๋ ์ปดํจํธ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ ๋์ ๋์ผํ VkPipelineLayout
์ ์ธ์๋ก ๋ฐ์ต๋๋ค.
๋ํ VkRenderPass
์ ์๋ธํจ์ค ์ธ๋ฑ์ค๋ ๋ฐ์ง๋ง, ๋์ ๋ ๋๋ง์ ์ฌ์ฉํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฅผ ๊ตฌ์ฑํ์ง๋ ์์ ๊ฒ์
๋๋ค. ์ฆ, VkRenderPass
์ ๊ด๋ จ๋ ๋ชจ๋ ์ ์ฐจ๋ฅผ ๊ฑด๋๋ธ ๊ฒ์
๋๋ค. ๋์ , VkGraphicsPipelineCreateInfo
๋ฅผ pNext
์ ์ฐ๊ฒฐํ VkPipelineRenderingCreateInfo
๋ก ํ์ฅํด์ผ ํฉ๋๋ค. ์ด ๊ตฌ์กฐ์ฒด๋ ํ์ดํ๋ผ์ธ์ ์ฌ์ฉํ ์ดํ์น๋จผํธ ํฌ๋งท์ ๋ชฉ๋ก์ ๋ด์ต๋๋ค.
์ด์ ๋น๋ ํจ์๋ฅผ ์์ฑํด๋ด
์๋ค. ๋ชจ๋ ํ์ดํ๋ผ์ธ ์ฝ๋๋ vk_pipeline.s.h/cpp
์ ์์ต๋๋ค. ์ฑํฐ ์ฝ๋๋ฅผ ํ์ธํ๋ ค๋ฉด shared ํด๋์์ ํ์ธํ ์ ์์ต๋๋ค.
class PipelineBuilder {
public:
std::vector<VkPipelineShaderStageCreateInfo> _shaderStages;
VkPipelineInputAssemblyStateCreateInfo _inputAssembly;
VkPipelineRasterizationStateCreateInfo _rasterizer;
VkPipelineColorBlendAttachmentState _colorBlendAttachment;
VkPipelineMultisampleStateCreateInfo _multisampling;
VkPipelineLayout _pipelineLayout;
VkPipelineDepthStencilStateCreateInfo _depthStencil;
VkPipelineRenderingCreateInfo _renderInfo;
VkFormat _colorAttachmentformat;
PipelineBuilder(){ clear(); }
void clear();
VkPipeline build_pipeline(VkDevice device);
}
ํ์ดํ๋ผ์ธ ๋น๋๋ ์ฐ๋ฆฌ๊ฐ ์ถ์ ํด์ผ ํ ๋๋ถ๋ถ์ ์ํ ์ ๋ณด์ ์์ ์ดํ์น๋จผํธ ํฌ๋งท์ ๋ฐฐ์ด, ๊ทธ๋ฆฌ๊ณ ์
ฐ์ด๋ ๋จ๊ณ ์ ๋ณด๋ฅผ ๋ด์ ๊ฒ์
๋๋ค. ์ค์ CreateInfo ๊ตฌ์กฐ์ฒด๋ build_pipeline()
ํจ์์์ ์ฑ์์ง ๊ฒ์
๋๋ค. clear()
ํจ์๋ ๋ชจ๋ ์ํ๋ฅผ ์ด๊ธฐ๊ฐ ํน์ ๋น์ด์๋ ์ํ๋ก ์ค์ ํ ๊ฒ์
๋๋ค. ํ์ดํ๋ผ์ธ ๋น๋์ ์์ฑ์๊ฐ ์ด ํจ์๋ฅผ ํธ์ถํ ๊ฒ์ด์ง๋ง, ์๋์ ์ผ๋ก ์ด๊ธฐํ๊ฐ ํ์ํ ๋๋ฅผ ๋๋นํด ๋ณ๋์ ์ด๊ธฐํ ํจ์๋ก ๋ถ๋ฆฌํด๋๋ ํธ์ด ์ ์ฉํฉ๋๋ค.
๋จผ์ clear()
ํจ์๋ฅผ ์์ฑํด๋ด
์๋ค.
void PipelineBuilder::clear()
{
// clear all of the structs we need back to 0 with their correct stype
_inputAssembly = { .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO };
_rasterizer = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO };
_colorBlendAttachment = {};
_multisampling = { .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
_pipelineLayout = {};
_depthStencil = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO };
_renderInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO };
_shaderStages.clear();
}
๋ชจ๋ ๊ตฌ์กฐ์ฒด์ .sType
์ ์ฌ๊ธฐ์ ๋ช
์์ ์ผ๋ก ์ค์ ํด์ฃผ๊ณ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋๋จธ์ง ํ๋๋ค์ 0์ผ๋ก ์ค์ ํฉ๋๋ค. ์ด๋ C++20 ๊ตฌ์กฐ์ฒด ์ด๊ธฐํ ๋ฌธ๋ฒ์ ํ์ฉํ ๊ฒ์ผ๋ก, ์ค๊ดํธ์์ ๋ช
์ํ์ง ์์ ํ๋๋ ์๋์ผ๋ก 0์ผ๋ก ์ค์ ๋ฉ๋๋ค. Vulkan์ ๋๋ถ๋ถ์ Info ๊ตฌ์กฐ์ฒด๋ ๋ชจ๋ ํ๋๊ฐ 0์ผ๋ก ์ค์ ๋์ด ์์ด๋ ์ ํจํ ๊ธฐ๋ณธ ์ํ๊ฐ ๋๋๋ก ์ค๊ณ๋์ด ์๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ๋ฐฉ์์ ๋งค์ฐ ์ ์ ํ๊ฒ ๋์ํฉ๋๋ค.
์ด์ build_pipeline
ํจ์๋ฅผ ์์ฑํฉ์๋ค. ๋จผ์ ๊ตฌ์ฑ๋์ง ์์ ๋๋ฝ๋ info ๊ตฌ์กฐ์ฒด์ค ์ผ๋ถ๋ฅผ ์ค์ ํ๋ ๊ฒ๋ถํฐ ์์ํ๊ฒ ์ต๋๋ค.
VkPipeline PipelineBuilder::build_pipeline(VkDevice device)
{
// make viewport state from our stored viewport and scissor.
// at the moment we wont support multiple viewports or scissors
VkPipelineViewportStateCreateInfo viewportState = {};
viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
viewportState.pNext = nullptr;
viewportState.viewportCount = 1;
viewportState.scissorCount = 1;
// setup dummy color blending. We arent using transparent objects yet
// the blending is just "no blend", but we do write to the color attachment
VkPipelineColorBlendStateCreateInfo colorBlending = {};
colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
colorBlending.pNext = nullptr;
colorBlending.logicOpEnable = VK_FALSE;
colorBlending.logicOp = VK_LOGIC_OP_COPY;
colorBlending.attachmentCount = 1;
colorBlending.pAttachments = &_colorBlendAttachment;
// completely clear VertexInputStateCreateInfo, as we have no need for it
VkPipelineVertexInputStateCreateInfo _vertexInputInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
๋จผ์ VkPipelineViewportStateCreateInfo
๋ฅผ ๋ทฐํฌํธ ๊ฐ์๋ง ์ฑ์๋๋ค. ๋์ ๋ทฐํฌํธ ์ํ์์๋ ๋ทฐํฌํธ๋ ์คํ
์ค ์ต์
์ ์ฑ์ธ ํ์๋ ์์ต๋๋ค.
๊ทธ ํ VkPipelineColorBlendStateCreateInfo
์์ ๋ธ๋ ๋ฉ ๋ก์ง์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ์ฑ์๋๋ค(์ฐ๋ฆฌ๋ ์ฌ์ฉํ์ง ์์ ๊ฒ์
๋๋ค). ๊ทธ๋ฆฌ๊ณ ํ๋์ ์ดํ์น๋จผํธ ๋ธ๋ ๋ฉ ์์
์ ์ํ VkPipelineColorBlendAttachmentState
๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค. ํ๋์ ์ดํ์น๋จผํธ ๋ ๋๋ง๋ง์ ์ง์ํ ๊ฒ์ด๋ฏ๋ก ์ด์ ๋๋ก ์ถฉ๋ถํฉ๋๋ค. ์ฌ๋ฌ ์ดํ์น๋จผํธ์ ๊ทธ๋ฆด ํ์๊ฐ ์๋ค๋ฉด VkPipelineColorBlendAttachmentState
์ ๋ฐฐ์ด์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํจ์๋ฅผ ๊ณ์ํด VkGraphicsPipelineCreateInfo
๋ฅผ ์ฑ์๋ด
์๋ค.
// build the actual pipeline
// we now use all of the info structs we have been writing into into this one
// to create the pipeline
VkGraphicsPipelineCreateInfo pipelineInfo = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO };
// connect the renderInfo to the pNext extension mechanism
pipelineInfo.pNext = &_renderInfo;
pipelineInfo.stageCount = (uint32_t)_shaderStages.size();
pipelineInfo.pStages = _shaderStages.data();
pipelineInfo.pVertexInputState = &_vertexInputInfo;
pipelineInfo.pInputAssemblyState = &_inputAssembly;
pipelineInfo.pViewportState = &viewportState;
pipelineInfo.pRasterizationState = &_rasterizer;
pipelineInfo.pMultisampleState = &_multisampling;
pipelineInfo.pColorBlendState = &colorBlending;
pipelineInfo.pDepthStencilState = &_depthStencil;
pipelineInfo.layout = _pipelineLayout;
์ค๋นํ ๋ชจ๋ ๊ตฌ์กฐ์ฒด๋ฅผ ํ์ดํ๋ผ์ธ ๋น๋์ ์ฐ๊ฒฐํ๊ณ _renderInfo
๋ฅผ pNext
์ ์ถ๊ฐํฉ๋๋ค.
๋ค์์ ๋์ ์ํ๋ฅผ ์ค์ ํ๊ฒ ์ต๋๋ค.
VkDynamicState state[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
VkPipelineDynamicStateCreateInfo dynamicInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
dynamicInfo.pDynamicStates = &state[0];
dynamicInfo.dynamicStateCount = 2;
pipelineInfo.pDynamicState = &dynamicInfo;
๋์ ์ํ๋ฅผ ์ค์ ํ๋ ๊ฒ์ VkPipelineDynamicStateCreateInfo
๊ตฌ์กฐ์ฒด๋ฅผ VkDynamicState ์ด๊ฑฐํ์ ๋ฐฐ์ด๋ก ์ฑ์ฐ๋ ๊ฒ์ผ๋ก ์ด๋ฃจ์ด์ง๋๋ค. ์ฌ๊ธฐ์๋ 2๊ฐ์ ๋์ ์ํ๋ง ์ฌ์ฉํ ๊ฒ์
๋๋ค.
ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ๊ธฐ ์ํด ํ์ํ ๋ชจ๋ ๊ณผ์ ์ ๋ง์ณค์ผ๋ฏ๋ก, ์์ฑํจ์๋ฅผ ํธ์ถํด๋ด ์๋ค.
// its easy to error out on create graphics pipeline, so we handle it a bit
// better than the common VK_CHECK case
VkPipeline newPipeline;
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo,
nullptr, &newPipeline)
!= VK_SUCCESS) {
fmt::println("failed to create pipeline");
return VK_NULL_HANDLE; // failed to create graphics pipeline
} else {
return newPipeline;
}
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ผ๋ก ์ฃผ์ ์์ฑ ํจ์๋ ๋๋ฌ์ต๋๋ค. ์ด์ ์ค์ ๋ก ์ต์ ๋ค์ ์ ๋๋ก ์ค์ ํด์ผ ํฉ๋๋ค. ํ์ฌ๋ ๋ชจ๋ ํ์ดํ๋ผ์ธ ์ค์ ์ด ์ฌ์ค์ ๋น์ด ์์ด์, ํ์ํ ์ต์ ์ด ๋๋ฝ๋์ด ๊ทธ๋๋ก ์คํํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒ์ ๋๋ค.
void PipelineBuilder::set_shaders(VkShaderModule vertexShader, VkShaderModule fragmentShader)
{
_shaderStages.clear();
_shaderStages.push_back(
vkinit::pipeline_shader_stage_create_info(VK_SHADER_STAGE_VERTEX_BIT, vertexShader));
_shaderStages.push_back(
vkinit::pipeline_shader_stage_create_info(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShader));
}
์ ์ ์
ฐ์ด๋์ ํ๋๊ทธ๋จผํธ ์
ฐ์ด๋๋ฅผ ์ค์ ํ๋ ํจ์๋ฅผ ์ถ๊ฐํด๋ด
์๋ค. ์ปดํจํธ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ ๋ ์ฌ์ฉํ๋ ๋ฐฉ์๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, ์ด ์
ฐ์ด๋๋ค์ ์ ์ ํ ์ ๋ณด์ ํจ๊ป _shaderStages
๋ฐฐ์ด์ ์ถ๊ฐํฉ๋๋ค.
๋ค์์ ์ ๋ ฅ ํ ํด๋ก์ง๋ฅผ ์ค์ ํ๋ ํจ์๋ฅผ ์ถ๊ฐํฉ๋๋ค.
void PipelineBuilder::set_input_topology(VkPrimitiveTopology topology)
{
_inputAssembly.topology = topology;
// we are not going to use primitive restart on the entire tutorial so leave
// it on false
_inputAssembly.primitiveRestartEnable = VK_FALSE;
}
VkPrimitiveTopology
๋ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
, VK_PRIMITIVE_TOPOLOGY_POINT_LIST
๋ฑ์ ์ต์
์ด ์์ต๋๋ค. PrimitiveRestart๋ triangle strip์ด๋ line strip์ ์ฌ์ฉ๋์ง๋ง ์ฌ๊ธฐ์๋ ์ฌ์ฉํ์ง ์์ ๊ฒ์
๋๋ค.
๋์คํฐํ ์ํ๋ ๊ฝค ํฌ๋ฏ๋ก ์ด๋ฅผ ๋ช ๊ฐ์ ์ต์ ์ผ๋ก ๋๋๊ฒ ์ต๋๋ค.
void PipelineBuilder::set_polygon_mode(VkPolygonMode mode)
{
_rasterizer.polygonMode = mode;
_rasterizer.lineWidth = 1.f;
}
lineWidth
๋ฅผ ๊ธฐ๋ณธ์ ์ผ๋ก 1.f๋ก ์ค์ ํด์ผ ํฉ๋๋ค. ๊ทธ ํ ์์ด์ด ํ๋ ์, ์๋ฆฌ๋ ๋ ๋๋ง, ๊ทธ๋ฆฌ๊ณ ์ ๋ ๋๋ง ์ค ์ด๋ค ๋ฐฉ์์ผ๋ก ๋ ๋๋งํ ์ง๋ฅผ ์ ์ดํ๋ polygon ๋ชจ๋๋ฅผ ์ค์ ํฉ๋๋ค.
void PipelineBuilder::set_cull_mode(VkCullModeFlags cullMode, VkFrontFace frontFace)
{
_rasterizer.cullMode = cullMode;
_rasterizer.frontFace = frontFace;
}
์ปฌ๋ง ๋ชจ๋๋ ์ ๋ฉด ๋ฐฉํฅ๊ณผ ํ๋ฉด ์ปฌ๋ง์ ์ฌ์ฉํ ์ปฌ๋ง ๋ชจ๋๋ฅผ ์ค์ ํฉ๋๋ค.
๋ค์์ ๋ฉํฐ์ํ๋ง ์ํ์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก๋ ๋ฉํฐ์ํ๋ง์ด ๋นํ์ฑํ๋ ๊ตฌ์กฐ์ฒด๋ฅผ ์ฌ์ฉํ ๊ฒ์ ๋๋ค. ์ดํ ์ํฐ์จ๋ฆฌ์ด์ฑ์ ์ํด ๋ค์ํ ๋ฉํฐ์ํ๋ง ๋ ๋ฒจ์ ํ์ฑํํ๋ ํจ์๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
void PipelineBuilder::set_multisampling_none()
{
_multisampling.sampleShadingEnable = VK_FALSE;
// multisampling defaulted to no multisampling (1 sample per pixel)
_multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
_multisampling.minSampleShading = 1.0f;
_multisampling.pSampleMask = nullptr;
// no alpha to coverage either
_multisampling.alphaToCoverageEnable = VK_FALSE;
_multisampling.alphaToOneEnable = VK_FALSE;
}
๋ค์์ ๋ธ๋ ๋ฉ ๋ชจ๋๋ฅผ ์ํ ํจ์๋ฅผ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
void PipelineBuilder::disable_blending()
{
// default write mask
_colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
// no blending
_colorBlendAttachment.blendEnable = VK_FALSE;
}
disable_blending()
ํจ์๋ blendEnable
์ false
๋ก ์ค์ ํ์ง๋ง, ์ฌ๋ฐ๋ฅธ writeMask
๋ ์ค์ ํด์ผ ํฉ๋๋ค. ์ดํ ๋ ๋ง์ ๋ธ๋ ๋ฉ ๋ชจ๋๋ฅผ ์ถํ ์ถ๊ฐํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ฌ๊ธฐ์ ์ฌ๋ฐ๋ฅธ colorWriteMask
๋ฅผ ์ค์ ํ์ฌ ํฝ์
์ถ๋ ฅ์ด ์ดํ์น๋จผํธ๋ก ์ ํํ ๊ธฐ๋ก๋๋๋ก ํ ๊ฒ์
๋๋ค.
์ด์ ํฌ๋งท์ ์ฐ๊ฒฐํ๊ณ , ๊น์ด ํ ์คํธ์ ์์ ์ดํ์น๋จผํธ๋ฅผ ์ํ ํจ์๋ฅผ ์ถ๊ฐํ๊ฒ ์ต๋๋ค.
void PipelineBuilder::set_color_attachment_format(VkFormat format)
{
_colorAttachmentformat = format;
// connect the format to the renderInfo structure
_renderInfo.colorAttachmentCount = 1;
_renderInfo.pColorAttachmentFormats = &_colorAttachmentformat;
}
void PipelineBuilder::set_depth_format(VkFormat format)
{
_renderInfo.depthAttachmentFormat = format;
}
์์ ์ดํ์น๋จผํธ์ ๊ฒฝ์ฐ ํ์ดํ๋ผ์ธ์ด ์์ ์ดํ์น๋จผํธ ๋ฐฐ์ด์ ์ํ๊ธฐ ๋๋ฌธ์ ํฌ์ธํฐ๋ฅผ ์ ๋ฌํฉ๋๋ค. ์ด๋ ์ฌ๋ฌ ์ด๋ฏธ์ง๋ฅผ ํ๋ฒ์ ๊ทธ๋ฆฌ๋ ๋ํผ๋ ๋ ๋๋ง๊ณผ ๊ฐ์ ๊ณณ์์ ์ ์ฉํ์ง๋ง, ์ง๊ธ์ ํ์ํ์ง ์์ผ๋ฏ๋ก ๊ธฐ๋ณธ์ ์ผ๋ก ํ๋์ ์์ ํฌ๋งท๋ง์ ์ฌ์ฉํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก, ๊น์ด ํ ์คํธ ๋ก์ง์ ๋นํ์ฑํํ๋ ํจ์๊ฐ ํ์ํฉ๋๋ค.
void PipelineBuilder::disable_depthtest()
{
_depthStencil.depthTestEnable = VK_FALSE;
_depthStencil.depthWriteEnable = VK_FALSE;
_depthStencil.depthCompareOp = VK_COMPARE_OP_NEVER;
_depthStencil.depthBoundsTestEnable = VK_FALSE;
_depthStencil.stencilTestEnable = VK_FALSE;
_depthStencil.front = {};
_depthStencil.back = {};
_depthStencil.minDepthBounds = 0.f;
_depthStencil.maxDepthBounds = 1.f;
}
ํ์ดํ๋ผ์ธ ๋น๋์ ๋ชจ๋ ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ด ์ฑ์์ก์ผ๋ฏ๋ก, ์ด์ ์ผ๊ฐํ์ ๊ทธ๋ฆด ์ ์์ต๋๋ค. ์ด๋ฒ์๋ ์ ์ ์ ฐ์ด๋์์ ํ๋์ฝ๋ฉ๋ ์ ์ ์์น๋ฅผ ์ฌ์ฉํ๊ณ , ์ถ๋ ฅ์ ๋จ์์ผ๋ก ์ค์ ํ ๊ฒ์ ๋๋ค
๋ค์์ ์ฌ์ฉํ ์ ฐ์ด๋์ ๋๋ค.
colored_triangle.vert
#version 450
layout (location = 0) out vec3 outColor;
void main()
{
//const array of positions for the triangle
const vec3 positions[3] = vec3[3](
vec3(1.f,1.f, 0.0f),
vec3(-1.f,1.f, 0.0f),
vec3(0.f,-1.f, 0.0f)
);
//const array of colors for the triangle
const vec3 colors[3] = vec3[3](
vec3(1.0f, 0.0f, 0.0f), //red
vec3(0.0f, 1.0f, 0.0f), //green
vec3(00.f, 0.0f, 1.0f) //blue
);
//output the position of each vertex
gl_Position = vec4(positions[gl_VertexIndex], 1.0f);
outColor = colors[gl_VertexIndex];
}
colored_triangle.frag
#version 450
//shader input
layout (location = 0) in vec3 inColor;
//output write
layout (location = 0) out vec4 outFragColor;
void main()
{
//return red
outFragColor = vec4(inColor,1.0f);
}
์ ์ ์
ฐ์ด๋์๋ ํ๋์ฝ๋ฉ๋ ์์น ๋ฐฐ์ด์ด ์์ผ๋ฉฐ, gl_VertexIndex
๋ฅผ ํตํด ํด๋น ๋ฐฐ์ด์ ์ธ๋ฑ์ฑํฉ๋๋ค. ์ด ๋ฐฉ์์ ์ปดํจํธ ์
ฐ์ด๋์์์ LocalThreadID์ ์ ์ฌํ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค. ์ ์ ์
ฐ์ด๋๊ฐ ํธ์ถ๋ ๋๋ง๋ค ์๋ก ๋ค๋ฅธ ์ธ๋ฑ์ค๊ฐ ์ฃผ์ด์ง๋ฉฐ, ์ด๋ฅผ ํ์ฉํด ์ ์ ์ ์ฒ๋ฆฌํ๊ณ ๊ณ ์ ํจ์ ๋ณ์์ธ gl_Position
์ ๊ฐ์ ๊ธฐ๋กํฉ๋๋ค. ๋ฐฐ์ด์ ๊ธธ์ด๊ฐ 3์ด๊ธฐ ๋๋ฌธ์, ๋ง์ฝ 3๊ฐ ์ด์์ ์ ์ (1๊ฐ ์ด์์ ์ผ๊ฐํ)์ ๋ ๋๋งํ๋ค๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํ ๊ฒ์
๋๋ค.
ํ๋๊ทธ๋จผํธ ์
ฐ์ด๋์์๋ layout = 0
์ ์ถ๋ ฅ๊ฐ์ ์ ์ธํ๊ณ (์ด๋ ๋ ๋ํจ์ค์์ ์ค์ ํ ์ดํ์น๋จผํธ์ ์ฐ๊ฒฐ๋ฉ๋๋ค), ๋จ์ํ ํ๋์ฝ๋ฉ๋ ๋นจ๊ฐ์์ ์ถ๋ ฅํฉ๋๋ค.
์ด์ ์ผ๊ฐํ์ ๊ทธ๋ฆด ๋ ํ์ํ ํ์ดํ๋ผ์ธ๊ณผ ํ์ดํ๋ผ์ธ ๋ ์ด์์์ ๋ง๋ค๊ฒ ์ต๋๋ค. ์๋ก์ด ์ ฐ์ด๋ ํ์ผ์ ์ถ๊ฐํ์ผ๋ฏ๋ก CMake ํ๋ก์ ํธ๋ฅผ ์ฌ๋น๋ํ์ฌ Shaders ํ๊ฒ์ ๋น๋ํด์ผ ํฉ๋๋ค.
VulkanEngine
ํด๋์ค์ init_triangle_pipeline()
ํจ์๋ฅผ ์ถ๊ฐํ๊ณ , ํ์ดํ๋ผ์ธ๊ณผ ํ์ดํ๋ผ์ธ ๋ ์ด์์์ ๋ด๋ ๋ฉค๋ฒ๋ ์ถ๊ฐํ ๊ฒ์
๋๋ค.
VkPipelineLayout _trianglePipelineLayout;
VkPipeline _trianglePipeline;
void init_triangle_pipeline();
init_triangle_pipeline()
์ init_pipelines()
ํจ์์์ ํธ์ถํ ๊ฒ์
๋๋ค.
์ด์ ํด๋น ํจ์๋ฅผ ์์ฑํด๋ณด๊ฒ ์ต๋๋ค. ์ปดํจํธ ์ ฐ์ด๋์์์ ๋ง์ฐฌ๊ฐ์ง๋ก ํจ์๋ฅผ ๋ ์ ฐ์ด๋๋ฅผ ๋ถ๋ฌ์ค๋ ๊ฒ์ผ๋ก ์์ํ ๊ฒ์ ๋๋ค. ๋ค๋ง ์ด๋ฒ์๋ ๋ ๋ง์ ์ ฐ์ด๋๋ฅผ ์ฌ์ฉํฉ๋๋ค.
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.vert.spv", _device, &triangleVertexShader)) {
fmt::print("Error when building the triangle vertex shader module");
}
else {
fmt::print("Triangle vertex shader succesfully loaded");
}
//build the pipeline layout that controls the inputs/outputs of the shader
//we are not using descriptor sets or other systems yet, so no need to use anything other than empty default
VkPipelineLayoutCreateInfo pipeline_layout_info = vkinit::pipeline_layout_create_info();
VK_CHECK(vkCreatePipelineLayout(_device, &pipeline_layout_info, nullptr, &_trianglePipelineLayout));
๋ํ ํ์ดํ๋ผ์ธ ๋ ์ด์์๋ ์์ฑํฉ๋๋ค. ์ด์ ์ ์ปดํจํธ ์ ฐ์ด๋์๋ ๋ฌ๋ฆฌ, ์ด๋ฒ์๋ ํธ์ ์์๋ ๋์คํฌ๋ฆฝํฐ ๋ฐ์ธ๋ฉ์ด ์ ํ ์๊ธฐ ๋๋ฌธ์ ์์ ํ ๋น์ด์๋ ๋ ์ด์์์ ๋๋ค.
์ด์ ์์ ๋ง๋ PipelineBuilder
๋ฅผ ์ฌ์ฉํด ํ์ดํ๋ผ์ธ์ ์์ฑํ๊ฒ ์ต๋๋ค.
PipelineBuilder pipelineBuilder;
//use the triangle layout we created
pipelineBuilder._pipelineLayout = _trianglePipelineLayout;
//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();
//no depth testing
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
_trianglePipeline = pipelineBuilder.build_pipeline(_device);
//clean structures
vkDestroyShaderModule(_device, triangleFragShader, nullptr);
vkDestroyShaderModule(_device, triangleVertexShader, nullptr);
_mainDeletionQueue.push_function([&]() {
vkDestroyPipelineLayout(_device, _trianglePipelineLayout, nullptr);
vkDestroyPipeline(_device, _trianglePipeline, nullptr);
});
ํ์ดํ๋ผ์ธ์ด ์์ฑ๋์์ผ๋ฏ๋ก, ๋งค ํ๋ ์๋ง๋ค ์์ฑ๋๋ ์ปค๋งจ๋ ๋ฒํผ์์ ์ผ๊ฐํ์ ๊ทธ๋ฆด ์ ์์ต๋๋ค.
๋ฐฑ๊ทธ๋ผ์ด๋์ ์ฌ์ฉ๋ ์ปดํจํธ ์
ฐ์ด๋๋ GENERAL ๋ ์ด์์์ ์ด๋ฏธ์ง์ ์์ฑํด์ผ ํ์ง๋ง, ๋ํ(geometry) ๋ ๋๋ง์ ์ํํ ๋์๋ COLOR_ATTACHMENT_OPTIMAL
์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๊ทธ๋ํฝ์ค ํ์ดํ๋ผ์ธ์์ GENERAL ๋ ์ด์์์ ๊ทธ๋ฆด์๋ ์์ง๋ง ์ฑ๋ฅ์ด ๋ฎ๊ณ , ๊ฒ์ฆ ๋ ์ด์ด๊ฐ ๊ฒฝ๊ณ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๊ฒ ๋ฉ๋๋ค. ์ด๋ฌํ ๊ทธ๋ํฝ ๋ช
๋ น์ ๋ด๊ธฐ ์ํด ์๋ก์ด ํจ์ draw_geometry()
๋ฅผ ๋ง๋ค๊ณ , ๋จผ์ ๋ ๋๋ง ๋ฃจํ๋ฅผ ์
๋ฐ์ดํธ ํ๊ฒ ์ต๋๋ค.
VK_CHECK(vkBeginCommandBuffer(cmd, &cmdBeginInfo));
// transition our main draw image into general layout so we can write into it
// we will overwrite it all so we dont care about what was the older layout
vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL);
draw_background(cmd);
vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
draw_geometry(cmd);
//transtion the draw image and the swapchain image into their correct transfer layouts
vkutil::transition_image(cmd, _drawImage.image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
vkutil::transition_image(cmd, _swapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
์ด์ draw_geometry
ํจ์๋ฅผ ์ฑ์์๋ค.
void VulkanEngine::draw_geometry(VkCommandBuffer cmd)
{
//begin a render pass connected to our draw image
VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(_drawImage.imageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
VkRenderingInfo renderInfo = vkinit::rendering_info(_drawExtent, &colorAttachment, nullptr);
vkCmdBeginRendering(cmd, &renderInfo);
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _trianglePipeline);
//set dynamic viewport and scissor
VkViewport viewport = {};
viewport.x = 0;
viewport.y = 0;
viewport.width = _drawExtent.width;
viewport.height = _drawExtent.height;
viewport.minDepth = 0.f;
viewport.maxDepth = 1.f;
vkCmdSetViewport(cmd, 0, 1, &viewport);
VkRect2D scissor = {};
scissor.offset.x = 0;
scissor.offset.y = 0;
scissor.extent.width = _drawExtent.width;
scissor.extent.height = _drawExtent.height;
vkCmdSetScissor(cmd, 0, 1, &scissor);
//launch a draw command to draw 3 vertices
vkCmdDraw(cmd, 3, 1, 0, 0);
vkCmdEndRendering(cmd);
}
์ผ๊ฐํ์ ๊ทธ๋ฆฌ๊ธฐ ์ํด vkCmdBeginRendering
์ ํธ์ถํด ๋ ๋ํจ์ค๋ฅผ ์์ํด์ผ ํฉ๋๋ค. ์ด๋ ์ง๋ ์ฑํฐ์์์ ImGui์์์ ๋์ผํ์ง๋ง, ์ด๋ฒ์๋ ์ค์์ฒด์ธ ์ด๋ฏธ์ง๊ฐ ์๋๋ผ _drawImage
๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
vkCmdBindPipeline
๋ฅผ ํธ์ถํ ๋, ์ด์ ์ฒ๋ผ VK_PIPELINE_BIND_POINT_COMPUTE
์ด ์๋๋ผ VK_PIPELINE_BIND_POINT_GRAPHICS
๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์ดํ ๋ทฐํฌํธ์ ๊ฐ์๋ฅผ ์ค์ ํด์ผ ํฉ๋๋ค. ์ด๋ ํ์ดํ๋ผ์ธ ์์ฑ ์ ๋์ ํ์ดํ๋ผ์ธ ์ํ๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ํ์์ ์ผ๋ก ์ค์ ํด์ผ ํ๋ ๋ถ๋ถ์
๋๋ค. ์ค์ ์ด ์๋ฃ๋๋ฉด vkCmdDraw
๋ฅผ ํธ์ถํด ์ผ๊ฐํ์ ๊ทธ๋ฆด ์ ์๊ณ , ์ดํ ๋ ๋ํจ์ค๋ฅผ ์ข
๋ฃํ์ฌ ๊ทธ๋ฆฌ๊ธฐ ์์
์ ๋ง๋ฌด๋ฆฌํ ์ ์์ต๋๋ค.
์ด ์์ ์์ ํ๋ก๊ทธ๋จ์ ์คํํ๋ค๋ฉด ์ปดํจํธ ์ ฐ์ด๋๋ก ๊ทธ๋ฆฐ ๋ฐฐ๊ฒฝ ์์ ์ผ๊ฐํ์ด ๋ ๋๋ง ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
Next: Mesh buffers