HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
gfx_pipeline_image_vulkan_intf.hpp
1// Copyright Take Vos 2019, 2021.
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_intf.hpp"
8#include "../container/container.hpp"
9#include "../geometry/geometry.hpp"
10#include "../image/image.hpp"
11#include "../codec/codec.hpp"
12#include "../macros.hpp"
13#include <vulkan/vulkan.hpp>
14#include <vma/vk_mem_alloc.h>
15
16hi_export_module(hikogui.GFX : gfx_pipeline_image_intf);
17
18hi_export namespace hi { inline namespace v1 {
19
23class gfx_pipeline_image : public gfx_pipeline {
24public:
28 struct alignas(16) vertex {
30 sfloat_rgba32 position;
31
34 sfloat_rgba32 clipping_rectangle;
35
37 sfloat_rgba32 atlas_position;
38
39 vertex(sfloat_rgba32 position, sfloat_rgba32 clipping_rectangle, sfloat_rgba32 atlas_position) noexcept :
41 {
42 }
43
44 static vk::VertexInputBindingDescription inputBindingDescription()
45 {
46 return {0, sizeof(vertex), vk::VertexInputRate::eVertex};
47 }
48
49 static std::vector<vk::VertexInputAttributeDescription> inputAttributeDescriptions()
50 {
51 return {
52 {0, 0, vk::Format::eR32G32B32A32Sfloat, offsetof(vertex, position)},
53 {1, 0, vk::Format::eR32G32B32A32Sfloat, offsetof(vertex, clipping_rectangle)},
54 {2, 0, vk::Format::eR32G32B32A32Sfloat, offsetof(vertex, atlas_position)},
55 };
56 }
57 };
58
60 sfloat_rg32 windowExtent = extent2{0.0, 0.0};
61 sfloat_rg32 viewportScale = scale2{0.0, 0.0};
62 sfloat_rg32 atlasExtent = extent2{0.0, 0.0};
63 sfloat_rg32 atlasScale = scale2{0.0, 0.0};
64
65 static std::vector<vk::PushConstantRange> pushConstantRanges()
66 {
67 return {{vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment, 0, sizeof(push_constants)}};
68 }
69 };
70
71 struct texture_map {
72 vk::Image image;
73 VmaAllocation allocation = {};
74 vk::ImageView view;
76 vk::ImageLayout layout = vk::ImageLayout::eUndefined;
77
78 void transitionLayout(const gfx_device& device, vk::Format format, vk::ImageLayout nextLayout);
79 };
80
83 struct paged_image {
84 enum class state_type { uninitialized, drawing, uploaded };
85
86 constexpr static std::size_t page_size = 62; // 64x64 including a 1 pixel border.
87
88 mutable std::atomic<state_type> state = state_type::uninitialized;
89 gfx_device *device = nullptr;
90 std::size_t width;
91 std::size_t height;
93
95 constexpr paged_image() noexcept = default;
96 paged_image(paged_image&& other) noexcept;
97 paged_image& operator=(paged_image&& other) noexcept;
98 paged_image(paged_image const& other) = delete;
99 paged_image& operator=(paged_image const& other) = delete;
100
101 paged_image(gfx_surface const *surface, std::size_t width, std::size_t height) noexcept;
102 paged_image(gfx_surface const *surface, pixmap_span<sfloat_rgba16 const> image) noexcept;
103 paged_image(gfx_surface const *surface, pixmap<sfloat_rgba16> const& image) noexcept :
105 {
106 }
107
108 paged_image(gfx_surface const *surface, png const& image) noexcept;
109
110 [[nodiscard]] constexpr explicit operator bool() const noexcept
111 {
112 return device != nullptr;
113 }
114
115 [[nodiscard]] constexpr extent2 size() const noexcept
116 {
117 return extent2{narrow_cast<float>(width), narrow_cast<float>(height)};
118 }
119
120 [[nodiscard]] constexpr std::pair<std::size_t, std::size_t> size_in_int_pages() const noexcept
121 {
122 auto const num_columns = (width + page_size - 1) / page_size;
123 auto const num_rows = (height + page_size - 1) / page_size;
124 return {num_columns, num_rows};
125 }
126
127 [[nodiscard]] constexpr extent2 size_in_float_pages() const noexcept
128 {
129 constexpr auto page_size_ = f32x4{narrow_cast<float>(page_size), narrow_cast<float>(page_size), 1.0f, 1.0f};
130 auto size = f32x4{narrow_cast<float>(width), narrow_cast<float>(height), 0.0f, 0.0f};
131 return extent2{size / page_size_};
132 }
133
136 void upload(pixmap_span<sfloat_rgba16 const> image) noexcept;
137
140 void upload(png const& image) noexcept;
141 };
142
144 constexpr static std::size_t atlas_num_pages_per_axis = 8;
145 constexpr static std::size_t atlas_num_pages_per_image = atlas_num_pages_per_axis * atlas_num_pages_per_axis;
146 constexpr static std::size_t atlas_image_axis_size = atlas_num_pages_per_axis * (paged_image::page_size + 2);
147 constexpr static std::size_t atlas_maximum_num_images = 64;
148 constexpr static std::size_t staging_image_width = 1024;
149 constexpr static std::size_t staging_image_height = 1024;
150
151 gfx_device const& device;
152
153 vk::ShaderModule vertex_shader_module;
154 vk::ShaderModule fragment_shader_module;
156
157 texture_map staging_texture;
158 std::vector<texture_map> atlas_textures;
159
161 vk::Sampler atlas_sampler;
162 vk::DescriptorImageInfo atlas_sampler_descriptor_image_info;
163
164 device_shared(gfx_device const& device);
166
167 device_shared(device_shared const&) = delete;
168 device_shared& operator=(device_shared const&) = delete;
169 device_shared(device_shared&&) = delete;
170 device_shared& operator=(device_shared&&) = delete;
171
175 void destroy(gfx_device const *vulkanDevice);
176
180
183 void free_pages(std::vector<std::size_t> const& pages) noexcept;
184
185 void draw_in_command_buffer(vk::CommandBuffer const& commandBuffer);
186
192
196
205 void place_vertices(
206 vector_span<vertex>& vertices,
207 aarectangle const& clipping_rectangle,
208 quad const& box,
209 paged_image const& image) noexcept;
210
211 private:
212 std::vector<std::size_t> _atlas_free_pages;
213
217 {
218 return get_staging_pixmap().subimage(0, 0, width, height);
219 }
220
225 void make_staging_border_transparent(aarectangle border_rectangle) noexcept;
226
232 void clear_staging_between_border_and_upload(aarectangle border_rectangle, aarectangle upload_rectangle) noexcept;
233
244 void prepare_staging_for_upload(paged_image const& image) noexcept;
245
248 void update_atlas_with_staging_pixmap(paged_image const& image) noexcept;
249
250 void build_shaders();
251 void teardown_shaders(gfx_device const *device);
252 void add_atlas_image();
253 void build_atlas();
254 void teardown_atlas(gfx_device const *device);
255
256 friend paged_image;
257 };
258
259 vector_span<vertex> vertexBufferData;
260
261 ~gfx_pipeline_image() = default;
262 gfx_pipeline_image(const gfx_pipeline_image&) = delete;
263 gfx_pipeline_image& operator=(const gfx_pipeline_image&) = delete;
265 gfx_pipeline_image& operator=(gfx_pipeline_image&&) = delete;
266
267 gfx_pipeline_image(gfx_surface *surface) : gfx_pipeline(surface) {}
268
269 void draw_in_command_buffer(vk::CommandBuffer commandBuffer, draw_context const& context) override;
270
271private:
272 push_constants pushConstants;
273 int numberOfAtlasImagesInDescriptor = 0;
274
275 vk::Buffer vertexBuffer;
276 VmaAllocation vertexBufferAllocation;
277
278 [[nodiscard]] std::vector<vk::PipelineShaderStageCreateInfo> createShaderStages() const override;
279 [[nodiscard]] std::vector<vk::DescriptorSetLayoutBinding> createDescriptorSetLayoutBindings() const override;
280 [[nodiscard]] std::vector<vk::WriteDescriptorSet> createWriteDescriptorSet() const override;
281 [[nodiscard]] size_t getDescriptorSetVersion() const override;
282 [[nodiscard]] std::vector<vk::PushConstantRange> createPushConstantRanges() const override;
283 [[nodiscard]] vk::VertexInputBindingDescription createVertexInputBindingDescription() const override;
284 [[nodiscard]] std::vector<vk::VertexInputAttributeDescription> createVertexInputAttributeDescriptions() const override;
285
286private:
287 void build_vertex_buffers() override;
288 void teardown_vertex_buffers() override;
289};
290
291}} // namespace hi::v1
@ other
The gui_event does not have associated data.
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition png.hpp:27
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:33
A high-level geometric extent.
Definition extent2.hpp:32
Definition scale2.hpp:18
Draw context for drawing using the HikoGUI shaders.
Definition draw_context_intf.hpp:209
Definition gfx_pipeline_image_vulkan_intf.hpp:23
Definition gfx_pipeline_image_vulkan_intf.hpp:28
sfloat_rgba32 atlas_position
The x, y coordinate inside the texture-atlas, z is used as an index in the texture-atlas array.
Definition gfx_pipeline_image_vulkan_intf.hpp:37
sfloat_rgba32 position
The pixel-coordinates where the origin is located relative to the bottom-left corner of the window.
Definition gfx_pipeline_image_vulkan_intf.hpp:30
sfloat_rgba32 clipping_rectangle
The position in pixels of the clipping rectangle relative to the bottom-left corner of the window,...
Definition gfx_pipeline_image_vulkan_intf.hpp:34
Definition gfx_pipeline_image_vulkan_intf.hpp:59
Definition gfx_pipeline_image_vulkan_intf.hpp:71
This is a image that is uploaded into the texture atlas.
Definition gfx_pipeline_image_vulkan_intf.hpp:83
void upload(pixmap_span< sfloat_rgba16 const > image) noexcept
Upload image to atlas.
Definition gfx_pipeline_image_vulkan_impl.hpp:243
Definition gfx_pipeline_image_vulkan_intf.hpp:143
void destroy(gfx_device const *vulkanDevice)
Definition gfx_pipeline_image_vulkan_impl.hpp:268
void place_vertices(vector_span< vertex > &vertices, aarectangle const &clipping_rectangle, quad const &box, paged_image const &image) noexcept
Place vertices for a single image.
Definition gfx_pipeline_image_vulkan_impl.hpp:626
std::vector< std::size_t > allocate_pages(std::size_t num_pages) noexcept
Allocate pages from the atlas.
Definition gfx_pipeline_image_vulkan_impl.hpp:275
void prepare_atlas_for_rendering()
Prepare the atlas so that it can be used as a texture map by the shaders.
Definition gfx_pipeline_image_vulkan_impl.hpp:463
hi::pixmap_span< sfloat_rgba16 > get_staging_pixmap()
Get the full staging pixel map excluding border.
Definition gfx_pipeline_image_vulkan_impl.hpp:295
void free_pages(std::vector< std::size_t > const &pages) noexcept
Deallocate pages back to the atlas.
Definition gfx_pipeline_image_vulkan_impl.hpp:290
A non-owning 2D pixel-based image.
Definition pixmap_span.hpp:34
A 2D pixel-based image.
Definition pixmap.hpp:38