HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
gfx_pipeline_vulkan_impl.hpp
1// Copyright Take Vos 2019-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "gfx_pipeline_vulkan.hpp"
8#include "gfx_device_vulkan_impl.hpp"
9#include "gfx_surface_vulkan.hpp"
10#include "../telemetry/telemetry.hpp"
11#include "../macros.hpp"
12#include <array>
13#include <vector>
14
15namespace hi { inline namespace v1 {
16
17[[nodiscard]] inline gfx_device *gfx_pipeline::device() const noexcept
18{
19 hi_axiom_not_null(surface);
20 return surface->device();
21}
22
23inline void gfx_pipeline::draw_in_command_buffer(vk::CommandBuffer commandBuffer, draw_context const& context)
24{
25 commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, intrinsic);
26
27 if (descriptorSet) {
28 if (descriptorSetVersion < getDescriptorSetVersion()) {
29 descriptorSetVersion = getDescriptorSetVersion();
30
31 hi_axiom_not_null(device());
32 device()->updateDescriptorSets(createWriteDescriptorSet(), {});
33 }
34
35 commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, {descriptorSet}, {});
36 }
37}
38
39inline void gfx_pipeline::build_descriptor_sets()
40{
41 hilet descriptorSetLayoutBindings = createDescriptorSetLayoutBindings();
42
44 // Make sure that there is no descriptor set.
45 descriptorSet = nullptr;
46 return;
47 }
48
49 hilet descriptorSetLayoutCreateInfo = vk::DescriptorSetLayoutCreateInfo{
50 vk::DescriptorSetLayoutCreateFlags(),
53
54 hi_axiom_not_null(device());
55 descriptorSetLayout = device()->createDescriptorSetLayout(descriptorSetLayoutCreateInfo);
56
59 return {x.descriptorType, narrow_cast<uint32_t>(x.descriptorCount)};
60 });
61
62 descriptorPool = device()->createDescriptorPool(
63 {vk::DescriptorPoolCreateFlags(),
64 1, // maxSets
66 descriptorPoolSizes.data()});
67
68 hilet descriptorSetLayouts = std::array{descriptorSetLayout};
69
70 hilet descriptorSets = device()->allocateDescriptorSets(
71 {descriptorPool, narrow_cast<uint32_t>(descriptorSetLayouts.size()), descriptorSetLayouts.data()});
72
73 descriptorSet = descriptorSets.at(0);
74 descriptorSetVersion = 0;
75}
76
77inline void gfx_pipeline::teardown_descriptor_sets()
78{
79 if (!descriptorSet) {
80 return;
81 }
82
83 hi_axiom_not_null(device());
84 device()->destroy(descriptorPool);
85 device()->destroy(descriptorSetLayout);
86 descriptorSet = nullptr;
87}
88
89inline vk::PipelineDepthStencilStateCreateInfo gfx_pipeline::getPipelineDepthStencilStateCreateInfo() const
90{
91 // Reverse-z depth configuration
92 return {
93 vk::PipelineDepthStencilStateCreateFlags(),
94 VK_TRUE, // depthTestEnable;
95 VK_TRUE, // depthWriteEnable;
96 vk::CompareOp::eGreaterOrEqual, // depthCompareOp
97 VK_FALSE, // depthBoundsTestEnable
98 VK_FALSE, // stencilTestEnable,
99 vk::StencilOpState(), // front
100 vk::StencilOpState(), // back
101 1.0f, // minDepthBounds
102 0.0f, // maxDepthBounds
103 };
104}
105
106/* pre-multiplied alpha blending.
107 */
108inline std::vector<vk::PipelineColorBlendAttachmentState> gfx_pipeline::getPipelineColorBlendAttachmentStates() const
109{
110 return {
111 {VK_TRUE, // blendEnable
112 vk::BlendFactor::eOne, // srcColorBlendFactor
113 vk::BlendFactor::eOneMinusSrcAlpha, // dstColorBlendFactor
114 vk::BlendOp::eAdd, // colorBlendOp
115 vk::BlendFactor::eOne, // srcAlphaBlendFactor
116 vk::BlendFactor::eOneMinusSrcAlpha, // dstAlphaBlendFactor
117 vk::BlendOp::eAdd, // aphaBlendOp
118 vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB |
119 vk::ColorComponentFlagBits::eA}};
120}
121
122inline void gfx_pipeline::build_pipeline(vk::RenderPass renderPass, uint32_t renderSubpass, vk::Extent2D _extent)
123{
124 hi_log_info("buildPipeline previous size ({}, {})", extent.width, extent.height);
125 extent = _extent;
126
127 const auto pushConstantRanges = createPushConstantRanges();
128 const auto vertexInputBindingDescription = createVertexInputBindingDescription();
129 const auto vertexInputAttributeDescriptions = createVertexInputAttributeDescriptions();
130 const auto shaderStages = createShaderStages();
131
133 if (descriptorSet) {
134 descriptorSetLayouts.push_back(descriptorSetLayout);
135 }
136
137 hi_axiom_not_null(device());
138 pipelineLayout = device()->createPipelineLayout(
139 {vk::PipelineLayoutCreateFlags(),
142 narrow_cast<uint32_t>(pushConstantRanges.size()),
143 pushConstantRanges.data()});
144
145 const vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = {
146 vk::PipelineVertexInputStateCreateFlags(),
147 1,
151
152 const vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo = {
153 vk::PipelineInputAssemblyStateCreateFlags(), vk::PrimitiveTopology::eTriangleList, VK_FALSE};
154
155 const std::array<vk::Viewport, 1> viewports = {vk::Viewport{
156 0.0f,
157 0.0f,
158 narrow_cast<float>(extent.width),
159 narrow_cast<float>(extent.height),
160 // Reverse-z, with float buffer this will give a linear depth buffer.
161 1.0f,
162 0.0f}};
163
164 hilet scissor = vk::Rect2D{vk::Offset2D{0, 0}, extent};
165
166 hilet scissors = std::array{scissor};
167
168 const vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = {
169 vk::PipelineViewportStateCreateFlags(),
171 viewports.data(),
173 scissors.data()};
174
175 const vk::PipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo = {
176 vk::PipelineRasterizationStateCreateFlags(),
177 VK_FALSE, // depthClampEnable
178 VK_FALSE, // rasterizerDiscardEnable
179 vk::PolygonMode::eFill,
180 vk::CullModeFlagBits::eBack,
181 vk::FrontFace::eCounterClockwise,
182 VK_FALSE, // depthBiasEnable
183 0.0, // depthBiasConstantFactor
184 0.0, // depthBiasClamp
185 0.0, // depthBiasSlopeFactor
186 1.0 // lineWidth
187 };
188
189 const vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = {
190 vk::PipelineMultisampleStateCreateFlags(),
191 vk::SampleCountFlagBits::e1,
192 VK_FALSE, // sampleShadingEnable
193 1.0f, // minSampleShading
194 nullptr, // sampleMask
195 VK_FALSE, // alphaToCoverageEnable
196 VK_FALSE // alphaToOneEnable
197 };
198
199 hilet pipelineDepthStencilStateCreateInfo = getPipelineDepthStencilStateCreateInfo();
200
201 /* Pre-multiplied alpha blending.
202 */
203 hilet pipelineColorBlendAttachmentStates = getPipelineColorBlendAttachmentStates();
204
205 const vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = {
206 vk::PipelineColorBlendStateCreateFlags(),
207 VK_FALSE, // logicOpenable
208 vk::LogicOp::eCopy,
211
212 hilet dynamicStates = std::array{vk::DynamicState::eScissor};
213
214 hilet pipelineDynamicStateInfo = vk::PipelineDynamicStateCreateInfo{
215 vk::PipelineDynamicStateCreateFlags(), narrow_cast<uint32_t>(dynamicStates.size()), dynamicStates.data()};
216
217 const vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo = {
218 vk::PipelineCreateFlags(),
219 narrow_cast<uint32_t>(shaderStages.size()),
220 shaderStages.data(),
223 nullptr, // tesselationStateCreateInfo
230 pipelineLayout,
231 renderPass,
232 renderSubpass, // subpass
233 vk::Pipeline(), // basePipelineHandle
234 -1 // basePipelineIndex
235 };
236
237 hi_axiom_not_null(device());
238 intrinsic = device()->createGraphicsPipeline(vk::PipelineCache(), graphicsPipelineCreateInfo);
239 hi_log_info("/buildPipeline new size ({}, {})", extent.width, extent.height);
240}
241
242inline void gfx_pipeline::teardown_pipeline()
243{
244 hi_axiom_not_null(device());
245 device()->destroy(intrinsic);
246 device()->destroy(pipelineLayout);
247}
248
249inline void gfx_pipeline::build_for_new_device()
250{
251 build_vertex_buffers();
252}
253
254inline void gfx_pipeline::teardown_for_device_lost()
255{
256 teardown_vertex_buffers();
257}
258
259inline void gfx_pipeline::build_for_new_swapchain(vk::RenderPass renderPass, uint32_t renderSubpass, vk::Extent2D _extent)
260{
261 // Input attachments described by the descriptor set will change when a
262 // new swap chain is created.
263 build_descriptor_sets();
264 build_pipeline(renderPass, renderSubpass, _extent);
265}
266
267inline void gfx_pipeline::teardown_for_swapchain_lost()
268{
269 teardown_pipeline();
270 teardown_descriptor_sets();
271}
272
273}} // namespace hi::inline v1
DOXYGEN BUG.
Definition algorithm.hpp:16
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
T data(T... args)
T push_back(T... args)