@@ -59,92 +59,140 @@ class PipelineBuilder {
59
59
};
60
60
```
61
61
62
- Implement ` build() ` :
62
+ Before implementing ` build() ` , add some helper functions/constants, starting with the viewport and dynamic states :
63
63
64
64
``` cpp
65
- auto PipelineBuilder::build (vk::PipelineLayout const layout,
66
- PipelineState const& state) const
67
- -> vk::UniquePipeline {
65
+ // single viewport and scissor.
66
+ constexpr auto viewport_state_v =
67
+ vk::PipelineViewportStateCreateInfo ({}, 1, {}, 1);
68
+
69
+ // these dynamic states are guaranteed to be available.
70
+ constexpr auto dynamic_states_v = std::array{
71
+ vk::DynamicState::eViewport,
72
+ vk::DynamicState::eScissor,
73
+ vk::DynamicState::eLineWidth,
74
+ };
75
+ ```
76
+
77
+ The shader stages:
78
+
79
+ ```cpp
80
+ [[nodiscard]] constexpr auto
81
+ create_shader_stages(vk::ShaderModule const vertex,
82
+ vk::ShaderModule const fragment) {
68
83
// set vertex (0) and fragment (1) shader stages.
69
- auto shader_stages = std::array<vk::PipelineShaderStageCreateInfo, 2>{};
70
- shader_stages [ 0]
84
+ auto ret = std::array<vk::PipelineShaderStageCreateInfo, 2>{};
85
+ ret [0]
71
86
.setStage(vk::ShaderStageFlagBits::eVertex)
72
87
.setPName("main")
73
- .setModule(state.vertex_shader );
74
- shader_stages [ 1]
88
+ .setModule(vertex );
89
+ ret [1]
75
90
.setStage(vk::ShaderStageFlagBits::eFragment)
76
91
.setPName("main")
77
- .setModule(state.fragment_shader);
78
-
79
- auto pvisci = vk::PipelineVertexInputStateCreateInfo{};
80
- pvisci.setVertexAttributeDescriptions(state.vertex_attributes)
81
- .setVertexBindingDescriptions(state.vertex_bindings);
92
+ .setModule(fragment);
93
+ return ret;
94
+ }
95
+ ```
82
96
83
- auto prsci = vk::PipelineRasterizationStateCreateInfo{};
84
- prsci.setPolygonMode(state.polygon_mode).setCullMode(state.cull_mode);
97
+ The depth/stencil state:
85
98
86
- auto pdssci = vk::PipelineDepthStencilStateCreateInfo{};
99
+ ``` cpp
100
+ [[nodiscard]] constexpr auto
101
+ create_depth_stencil_state (std::uint8_t flags,
102
+ vk::CompareOp const depth_compare) {
103
+ auto ret = vk::PipelineDepthStencilStateCreateInfo{};
87
104
auto const depth_test =
88
- (state.flags & PipelineFlag::DepthTest) == PipelineFlag::DepthTest;
89
- pdssci.setDepthTestEnable(depth_test ? vk::True : vk::False)
90
- .setDepthCompareOp(state.depth_compare);
105
+ (flags & PipelineFlag::DepthTest) == PipelineFlag::DepthTest;
106
+ ret.setDepthTestEnable(depth_test ? vk::True : vk::False)
107
+ .setDepthCompareOp(depth_compare);
108
+ return ret;
109
+ }
110
+ ```
91
111
92
- auto const piasci =
93
- vk::PipelineInputAssemblyStateCreateInfo{{}, state.topology};
112
+ And a color blend attachment:
94
113
95
- auto pcbas = vk::PipelineColorBlendAttachmentState{};
114
+ ```cpp
115
+ [[nodiscard]] constexpr auto
116
+ create_color_blend_attachment(std::uint8_t const flags) {
117
+ auto ret = vk::PipelineColorBlendAttachmentState{};
96
118
auto const alpha_blend =
97
- (state. flags & PipelineFlag::AlphaBlend) == PipelineFlag::AlphaBlend;
119
+ (flags & PipelineFlag::AlphaBlend) == PipelineFlag::AlphaBlend;
98
120
using CCF = vk::ColorComponentFlagBits;
99
- pcbas .setColorWriteMask(CCF::eR | CCF::eG | CCF::eB | CCF::eA)
121
+ ret .setColorWriteMask(CCF::eR | CCF::eG | CCF::eB | CCF::eA)
100
122
.setBlendEnable(alpha_blend ? vk::True : vk::False)
123
+ // standard alpha blending:
124
+ // (alpha * src) + (1 - alpha) * dst
101
125
.setSrcColorBlendFactor(vk::BlendFactor::eSrcAlpha)
102
126
.setDstColorBlendFactor(vk::BlendFactor::eOneMinusSrcAlpha)
103
127
.setColorBlendOp(vk::BlendOp::eAdd)
104
128
.setSrcAlphaBlendFactor(vk::BlendFactor::eOne)
105
129
.setDstAlphaBlendFactor(vk::BlendFactor::eZero)
106
130
.setAlphaBlendOp(vk::BlendOp::eAdd);
107
- auto pcbsci = vk::PipelineColorBlendStateCreateInfo{};
108
- pcbsci.setAttachments(pcbas);
109
-
110
- // these dynamic states are guaranteed to be available.
111
- auto const pdscis = std::array{
112
- vk::DynamicState::eViewport,
113
- vk::DynamicState::eScissor,
114
- vk::DynamicState::eLineWidth,
115
- };
116
- auto pdsci = vk::PipelineDynamicStateCreateInfo{};
117
- pdsci.setDynamicStates(pdscis);
131
+ return ret;
132
+ }
133
+ ```
134
+
135
+ Now we can implement ` build() ` :
118
136
119
- // single viewport and scissor.
120
- auto const pvsci = vk::PipelineViewportStateCreateInfo({}, 1, {}, 1);
137
+ ``` cpp
138
+ auto PipelineBuilder::build (vk::PipelineLayout const layout,
139
+ PipelineState const& state) const
140
+ -> vk::UniquePipeline {
141
+ auto const shader_stage_ci =
142
+ create_shader_stages(state.vertex_shader, state.fragment_shader);
121
143
122
- auto pmsci = vk::PipelineMultisampleStateCreateInfo{};
123
- pmsci.setRasterizationSamples(m_info.samples)
144
+ auto vertex_input_ci = vk::PipelineVertexInputStateCreateInfo{};
145
+ vertex_input_ci.setVertexAttributeDescriptions(state.vertex_attributes)
146
+ .setVertexBindingDescriptions(state.vertex_bindings);
147
+
148
+ auto multisample_state_ci = vk::PipelineMultisampleStateCreateInfo{};
149
+ multisample_state_ci.setRasterizationSamples(m_info.samples)
124
150
.setSampleShadingEnable(vk::False);
125
151
126
- auto prci = vk::PipelineRenderingCreateInfo{};
127
- // could be a depth-only pass.
152
+ auto const input_assembly_ci =
153
+ vk::PipelineInputAssemblyStateCreateInfo{{}, state.topology};
154
+
155
+ auto rasterization_state_ci = vk::PipelineRasterizationStateCreateInfo{};
156
+ rasterization_state_ci.setPolygonMode(state.polygon_mode)
157
+ .setCullMode(state.cull_mode);
158
+
159
+ auto const depth_stencil_state_ci =
160
+ create_depth_stencil_state(state.flags, state.depth_compare);
161
+
162
+ auto const color_blend_attachment =
163
+ create_color_blend_attachment(state.flags);
164
+ auto color_blend_state_ci = vk::PipelineColorBlendStateCreateInfo{};
165
+ color_blend_state_ci.setAttachments(color_blend_attachment);
166
+
167
+ auto dynamic_state_ci = vk::PipelineDynamicStateCreateInfo{};
168
+ dynamic_state_ci.setDynamicStates(dynamic_states_v);
169
+
170
+ // Dynamic Rendering requires passing this in the pNext chain.
171
+ auto rendering_ci = vk::PipelineRenderingCreateInfo{};
172
+ // could be a depth-only pass, argument is a span-like (notice the plural
173
+ // ` Formats() ` ), only set if not Undefined.
128
174
if (m_info.color_format != vk::Format::eUndefined) {
129
- prci .setColorAttachmentFormats(m_info.color_format);
175
+ rendering_ci .setColorAttachmentFormats(m_info.color_format);
130
176
}
131
- prci.setDepthAttachmentFormat(m_info.depth_format);
132
-
133
- auto gpci = vk::GraphicsPipelineCreateInfo{};
134
- gpci.setStages(shader_stages)
135
- .setPRasterizationState(&prsci)
136
- .setPDepthStencilState(&pdssci)
137
- .setPInputAssemblyState(&piasci)
138
- .setPColorBlendState(&pcbsci)
139
- .setPDynamicState(&pdsci)
140
- .setPViewportState(&pvsci)
141
- .setPMultisampleState(&pmsci)
142
- .setLayout(layout)
143
- .setPNext(&prci);
177
+ // single depth attachment format, ok to set to Undefined.
178
+ rendering_ci.setDepthAttachmentFormat(m_info.depth_format);
179
+
180
+ auto pipeline_ci = vk::GraphicsPipelineCreateInfo{};
181
+ pipeline_ci.setLayout(layout)
182
+ .setStages(shader_stage_ci)
183
+ .setPVertexInputState(&vertex_input_ci)
184
+ .setPViewportState(&viewport_state_v)
185
+ .setPMultisampleState(&multisample_state_ci)
186
+ .setPInputAssemblyState(&input_assembly_ci)
187
+ .setPRasterizationState(&rasterization_state_ci)
188
+ .setPDepthStencilState(&depth_stencil_state_ci)
189
+ .setPColorBlendState(&color_blend_state_ci)
190
+ .setPDynamicState(&dynamic_state_ci)
191
+ .setPNext(&rendering_ci);
144
192
145
193
auto ret = vk::Pipeline{};
146
194
// use non-throwing API.
147
- if (m_info.device.createGraphicsPipelines({}, 1, &gpci , {}, &ret) !=
195
+ if (m_info.device.createGraphicsPipelines({}, 1, &pipeline_ci , {}, &ret) !=
148
196
vk::Result::eSuccess) {
149
197
return {};
150
198
}
0 commit comments