HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
gfx_pipeline_box_vulkan_impl.hpp
1// Copyright Take Vos 2020-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_box_vulkan.hpp"
8#include "gfx_device_vulkan_impl.hpp"
9#include "draw_context.hpp"
10#include "../macros.hpp"
11
12namespace hi { inline namespace v1 {
13
14inline void gfx_pipeline_box::draw_in_command_buffer(vk::CommandBuffer commandBuffer, draw_context const& context)
15{
16 gfx_pipeline::draw_in_command_buffer(commandBuffer, context);
17
18 hi_axiom_not_null(device());
19 device()->flushAllocation(vertexBufferAllocation, 0, vertexBufferData.size() * sizeof(vertex));
20
23 hi_assert(tmpvertexBuffers.size() == tmpOffsets.size());
24
25 device()->box_pipeline->drawInCommandBuffer(commandBuffer);
26
27 commandBuffer.bindVertexBuffers(0, tmpvertexBuffers, tmpOffsets);
28
29 pushConstants.windowExtent = extent2{narrow_cast<float>(extent.width), narrow_cast<float>(extent.height)};
30 pushConstants.viewportScale = scale2{2.0f / extent.width, 2.0f / extent.height};
31 commandBuffer.pushConstants(
32 pipelineLayout,
33 vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment,
34 0,
35 sizeof(push_constants),
36 &pushConstants);
37
38 hilet numberOfRectangles = vertexBufferData.size() / 4;
40
41 device()->cmdBeginDebugUtilsLabelEXT(commandBuffer, "draw boxes");
42 commandBuffer.drawIndexed(narrow_cast<uint32_t>(numberOfTriangles * 3), 1, 0, 0, 0);
43 device()->cmdEndDebugUtilsLabelEXT(commandBuffer);
44}
45
46inline std::vector<vk::PipelineShaderStageCreateInfo> gfx_pipeline_box::createShaderStages() const
47{
48 hi_axiom_not_null(device());
49 return device()->box_pipeline->shaderStages;
50}
51
52inline std::vector<vk::DescriptorSetLayoutBinding> gfx_pipeline_box::createDescriptorSetLayoutBindings() const
53{
54 return {};
55}
56
57inline std::vector<vk::WriteDescriptorSet> gfx_pipeline_box::createWriteDescriptorSet() const
58{
59 return {};
60}
61
62inline size_t gfx_pipeline_box::getDescriptorSetVersion() const
63{
64 return 0;
65}
66
67inline std::vector<vk::PushConstantRange> gfx_pipeline_box::createPushConstantRanges() const
68{
69 return push_constants::pushConstantRanges();
70}
71
72inline vk::VertexInputBindingDescription gfx_pipeline_box::createVertexInputBindingDescription() const
73{
74 return vertex::inputBindingDescription();
75}
76
77inline std::vector<vk::VertexInputAttributeDescription> gfx_pipeline_box::createVertexInputAttributeDescriptions() const
78{
79 return vertex::inputAttributeDescriptions();
80}
81
82inline void gfx_pipeline_box::build_vertex_buffers()
83{
84 using vertexIndexType = uint16_t;
85 constexpr ssize_t numberOfVertices = 1 << (sizeof(vertexIndexType) * CHAR_BIT);
86
87 vk::BufferCreateInfo const bufferCreateInfo = {
88 vk::BufferCreateFlags(),
89 sizeof(vertex) * numberOfVertices,
90 vk::BufferUsageFlagBits::eVertexBuffer,
91 vk::SharingMode::eExclusive};
94 allocationCreateInfo.pUserData = const_cast<char *>("box-pipeline vertex buffer");
96
97 hi_axiom_not_null(device());
98 std::tie(vertexBuffer, vertexBufferAllocation) = device()->createBuffer(bufferCreateInfo, allocationCreateInfo);
99 device()->setDebugUtilsObjectNameEXT(vertexBuffer, "box-pipeline vertex buffer");
100 vertexBufferData = device()->mapMemory<vertex>(vertexBufferAllocation);
101}
102
103inline void gfx_pipeline_box::teardown_vertex_buffers()
104{
105 hi_axiom_not_null(device());
106 device()->unmapMemory(vertexBufferAllocation);
107 device()->destroyBuffer(vertexBuffer, vertexBufferAllocation);
108}
109
110inline gfx_pipeline_box::device_shared::device_shared(gfx_device const &device) : device(device)
111{
112 buildShaders();
113}
114
115inline gfx_pipeline_box::device_shared::~device_shared() {}
116
117inline void gfx_pipeline_box::device_shared::destroy(gfx_device const *vulkanDevice)
118{
119 hi_assert_not_null(vulkanDevice);
120 teardownShaders(vulkanDevice);
121}
122
123inline void gfx_pipeline_box::device_shared::drawInCommandBuffer(vk::CommandBuffer const &commandBuffer)
124{
125 commandBuffer.bindIndexBuffer(device.quadIndexBuffer, 0, vk::IndexType::eUint16);
126}
127
128inline void gfx_pipeline_box::device_shared::place_vertices(
129 vector_span<vertex> &vertices,
130 aarectangle clipping_rectangle,
131 quad box,
132 quad_color fill_colors,
133 quad_color line_colors,
134 float line_width,
136{
137 // Include the half line_width, so that the border is drawn centered
138 // around the box outline. Then add 1 pixel for anti-aliasing.
139 // The shader will compensate for the pixel and half the border.
140 hilet extra_space = (line_width * 0.5f) + 1.0f;
141 hilet[box_, lengths] = expand_and_edge_hypots(box, extent2{extra_space, extra_space});
142
143 // t0-t3 are used inside the shader to determine how far from the corner
144 // a certain fragment is.
145 //
146 // x = Number of pixels from the right edge.
147 // y = Number of pixels above the bottom edge.
148 // z = Number of pixels from the left edge.
149 // w = Number of pixels below the top edge.
150 hilet t0 = sfloat_rgba32{lengths._00xy()};
151 hilet t1 = sfloat_rgba32{lengths.x00w()};
152 hilet t2 = sfloat_rgba32{lengths._0yz0()};
153 hilet t3 = sfloat_rgba32{lengths.zw00()};
154
155 hilet clipping_rectangle_ = sfloat_rgba32{clipping_rectangle};
156 hilet corner_radii_ = sfloat_rgba32{corner_radii};
157
158 vertices.emplace_back(box_.p0, clipping_rectangle_, t0, corner_radii_, fill_colors.p0, line_colors.p0, line_width);
159 vertices.emplace_back(box_.p1, clipping_rectangle_, t1, corner_radii_, fill_colors.p1, line_colors.p1, line_width);
160 vertices.emplace_back(box_.p2, clipping_rectangle_, t2, corner_radii_, fill_colors.p2, line_colors.p2, line_width);
161 vertices.emplace_back(box_.p3, clipping_rectangle_, t3, corner_radii_, fill_colors.p3, line_colors.p3, line_width);
162}
163
164inline void gfx_pipeline_box::device_shared::buildShaders()
165{
166 vertexShaderModule = device.loadShader(URL("resource:shaders/box.vert.spv"));
167 device.setDebugUtilsObjectNameEXT(vertexShaderModule, "box-pipeline vertex shader");
168
169 fragmentShaderModule = device.loadShader(URL("resource:shaders/box.frag.spv"));
170 device.setDebugUtilsObjectNameEXT(vertexShaderModule, "box-pipeline fragment shader");
171
172 shaderStages = {
173 {vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eVertex, vertexShaderModule, "main"},
174 {vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderModule, "main"}};
175}
176
177inline void gfx_pipeline_box::device_shared::teardownShaders(gfx_device const*vulkanDevice)
178{
179 hi_assert_not_null(vulkanDevice);
180 vulkanDevice->destroy(vertexShaderModule);
181 vulkanDevice->destroy(fragmentShaderModule);
182}
183
184}} // namespace hi::inline v1::gfx_pipeline_box
DOXYGEN BUG.
Definition algorithm.hpp:16
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
std::ptrdiff_t ssize_t
Signed size/index into an array.
Definition misc.hpp:33
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
A color for each corner of a quad.
Definition quad_color.hpp:20
color p0
left-bottom
Definition quad_color.hpp:22
color p2
left-top
Definition quad_color.hpp:24
color p3
right-top
Definition quad_color.hpp:25
color p1
right-bottom
Definition quad_color.hpp:23
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:29
The 4 radii of the corners of a quad or rectangle.
Definition corner_radii.hpp:19
A high-level geometric extent.
Definition extent2.hpp:29
T tie(T... args)