forked from KhronosGroup/Vulkan-Samples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hpp_api_vulkan_sample.h
421 lines (341 loc) · 13.1 KB
/
hpp_api_vulkan_sample.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
/* Copyright (c) 2021-2024, NVIDIA CORPORATION. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 the "License";
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <camera.h>
#include <common/hpp_error.h>
#include <hpp_gui.h>
#include <scene_graph/components/hpp_image.h>
#include <scene_graph/components/hpp_sub_mesh.h>
#include "vulkan_sample.h"
/**
* @brief A swapchain buffer
*/
struct HPPSwapchainBuffer
{
vk::Image image;
vk::ImageView view;
};
/**
* @brief A texture wrapper that owns its image data and links it with a sampler
*/
struct HPPTexture
{
std::unique_ptr<vkb::scene_graph::components::HPPImage> image;
vk::Sampler sampler;
};
/**
* @brief The structure of a vertex
*/
struct HPPVertex
{
glm::vec3 pos;
glm::vec3 normal;
glm::vec2 uv;
glm::vec4 joint0;
glm::vec4 weight0;
};
/**
* @brief vulkan.hpp version of the vkb::ApiVulkanSample class
*
* See vkb::ApiVulkanSample for documentation
*/
class HPPApiVulkanSample : public vkb::VulkanSample<vkb::BindingType::Cpp>
{
public:
HPPApiVulkanSample() = default;
virtual ~HPPApiVulkanSample();
bool prepare(const vkb::ApplicationOptions &options) override;
void input_event(const vkb::InputEvent &input_event) override;
void update(float delta_time) override;
bool resize(const uint32_t width, const uint32_t height) override;
virtual void render(float delta_time) = 0;
enum RenderPassCreateFlags
{
ColorAttachmentLoad = 0x00000001
};
protected:
/// Stores the swapchain image buffers
std::vector<HPPSwapchainBuffer> swapchain_buffers;
void create_render_context() override;
void prepare_render_context() override;
// Handle to the device graphics queue that command buffers are submitted to
vk::Queue queue;
// Depth buffer format (selected during Vulkan initialization)
vk::Format depth_format;
// Command buffer pool
vk::CommandPool cmd_pool;
/** @brief Pipeline stages used to wait at for graphics queue submissions */
vk::PipelineStageFlags submit_pipeline_stages = vk::PipelineStageFlagBits::eColorAttachmentOutput;
// Contains command buffers and semaphores to be presented to the queue
vk::SubmitInfo submit_info;
// Command buffers used for rendering
std::vector<vk::CommandBuffer> draw_cmd_buffers;
// Global render pass for frame buffer writes
vk::RenderPass render_pass;
// List of available frame buffers (same as number of swap chain images)
std::vector<vk::Framebuffer> framebuffers;
// Active frame buffer index
uint32_t current_buffer = 0;
// Descriptor set pool
vk::DescriptorPool descriptor_pool;
// List of shader modules created (stored for cleanup)
std::vector<vk::ShaderModule> shader_modules;
// Pipeline cache object
vk::PipelineCache pipeline_cache;
// Synchronization semaphores
struct
{
// Swap chain image presentation
vk::Semaphore acquired_image_ready;
// Command buffer submission and execution
vk::Semaphore render_complete;
} semaphores;
// Synchronization fences
std::vector<vk::Fence> wait_fences;
/**
* @brief Creates a vulkan sampler
* @param address_mode The samplers address mode
* @param mipmaps_count The samplers mipmaps count
* @param format The image format that will be sampled
* @returns A valid vk::Sampler
*/
vk::Sampler create_default_sampler(vk::SamplerAddressMode address_mode, size_t mipmaps_count, vk::Format format);
/**
* @brief Populates the swapchain_buffers vector with the image and imageviews
*/
void create_swapchain_buffers();
/**
* @brief Updates the swapchains image usage, if a swapchain exists and recreates all resources based on swapchain images
* @param image_usage_flags The usage flags the new swapchain images will have
*/
void update_swapchain_image_usage_flags(std::set<vk::ImageUsageFlagBits> const &image_usage_flags);
/**
* @brief Handles changes to the surface, e.g. on resize
*/
void handle_surface_changes();
/**
* @brief Determine a vk::ImageLayout out of a vk::DescriptorType
* @param descriptor_type vk::DescriptorType to translate
* @param format vk::Format to use if descriptor_type is vk::DescriptorType::eCombinedImageSampler or vk::DescriptorType::eInputAttachment
*/
vk::ImageLayout descriptor_type_to_image_layout(vk::DescriptorType descriptor_type, vk::Format format) const;
/**
* @brief Loads in a ktx 2D texture
* @param file The filename of the texture to load
* @param content_type The type of content in the image file
* @param address_mode The address mode to use in u-, v-, and w-direction. Defaults to /c vk::SamplerAddressMode::eRepeat.
*/
HPPTexture
load_texture(const std::string &file, vkb::scene_graph::components::HPPImage::ContentType content_type, vk::SamplerAddressMode address_mode = vk::SamplerAddressMode::eRepeat);
/**
* @brief Loads in a ktx 2D texture array
* @param file The filename of the texture to load
* @param content_type The type of content in the image file
* @param address_mode The address mode to use in u-, v-, and w-direction. Defaults to /c vk::SamplerAddressMode::eClampToEdge.
*/
HPPTexture load_texture_array(const std::string &file,
vkb::scene_graph::components::HPPImage::ContentType content_type,
vk::SamplerAddressMode address_mode = vk::SamplerAddressMode::eClampToEdge);
/**
* @brief Loads in a ktx 2D texture cubemap
* @param file The filename of the texture to load
* @param content_type The type of content in the image file
*/
HPPTexture load_texture_cubemap(const std::string &file, vkb::scene_graph::components::HPPImage::ContentType content_type);
/**
* @brief Loads in a single model from a GLTF file
* @param file The filename of the model to load
* @param index The index of the model to load from the GLTF file (default: 0)
*/
std::unique_ptr<vkb::scene_graph::components::HPPSubMesh> load_model(const std::string &file, uint32_t index = 0);
/**
* @brief Records the necessary drawing commands to a command buffer
* @param model The model to draw
* @param command_buffer The command buffer to record to
* @param instance_count The number of instances (default: 1)
*/
void draw_model(std::unique_ptr<vkb::scene_graph::components::HPPSubMesh> &model, vk::CommandBuffer command_buffer, uint32_t instance_count = 1);
/**
* @brief Synchronously execute a block code within a command buffer, then submit the command buffer and wait for completion.
* @param f a block of code which is passed a command buffer which is already in the begin state.
* @param signalSemaphore An optional semaphore to signal when the commands have completed execution.
*/
void with_command_buffer(const std::function<void(vk::CommandBuffer command_buffer)> &f, vk::Semaphore signalSemaphore = nullptr);
public:
/**
* @brief Called when a view change occurs, can be overriden in derived samples to handle updating uniforms
*/
virtual void view_changed();
/**
* @brief Called after the mouse cursor is moved and before internal events (like camera rotation) is handled
* @param x The width from the origin
* @param y The height from the origin
* @param handled Whether the event was handled
*/
virtual void mouse_moved(double x, double y, bool &handled);
/**
* @brief To be overridden by the derived class. Records the relevant commands to the rendering command buffers
* Called when the framebuffers need to be rebuilt
*/
virtual void build_command_buffers() = 0;
/**
* @brief Rebuild the command buffers by first resetting the corresponding command pool and then building the command buffers.
*/
void rebuild_command_buffers();
/**
* @brief Creates the fences for rendering
*/
void create_synchronization_primitives();
/**
* @brief Creates a new (graphics) command pool object storing command buffers
*/
void create_command_pool();
/**
* @brief Setup default depth and stencil views
*/
virtual void setup_depth_stencil();
/**
* @brief Create framebuffers for all requested swap chain images
* Can be overriden in derived class to setup a custom framebuffer (e.g. for MSAA)
*/
virtual void setup_framebuffer();
/**
* @brief Setup a default render pass
* Can be overriden in derived class to setup a custom render pass (e.g. for MSAA)
*/
virtual void setup_render_pass();
/**
* @brief Update flags for the default render pass and recreate it
* @param flags Optional flags for render pass creation
*/
void update_render_pass_flags(RenderPassCreateFlags flags = {});
/**
* @brief Check if command buffers are valid (!= VK_NULL_HANDLE)
*/
bool check_command_buffers();
/**
* @brief Create command buffers for drawing commands
*/
void create_command_buffers();
/**
* @brief Destroy all command buffers, may be necessary during runtime if options are toggled
*/
void destroy_command_buffers();
/**
* @brief Create a cache pool for rendering pipelines
*/
void create_pipeline_cache();
/**
* @brief Load a SPIR-V shader
* @param file The file location of the shader relative to the shaders folder
* @param stage The shader stage
* @param src_language The shader language
*/
vk::PipelineShaderStageCreateInfo load_shader(const std::string &file, vk::ShaderStageFlagBits stage, vkb::ShaderSourceLanguage src_language = vkb::ShaderSourceLanguage::GLSL);
/**
* @brief Load a SPIR-V shader based on current shader language selection
* @param sample_folder_name Base folder where the shaders are located (without GLSL/HLSL sub folder)
* @param shader_filename Base name of the shader file
* @param stage The shader stage
*/
vk::PipelineShaderStageCreateInfo load_shader(const std::string &sample_folder_name, const std::string &shader_filename, vk::ShaderStageFlagBits stage);
/**
* @brief Updates the overlay
* @param delta_time The time taken since the last frame
* @param additional_ui Function that implements an additional Gui
*/
void update_overlay(float delta_time, const std::function<void()> &additional_ui) override;
/**
* @brief If the gui is enabled, then record the drawing commands to a command buffer
* @param command_buffer A valid command buffer that is ready to be recorded to
*/
void draw_ui(const vk::CommandBuffer command_buffer);
/**
* @brief Prepare the frame for workload submission, acquires the next image from the swap chain and
* sets the default wait and signal semaphores
*/
void prepare_frame();
/**
* @brief Submit the frames' workload
*/
void submit_frame();
/**
* @brief Called when the UI overlay is updating, can be used to add custom elements to the overlay
* @param drawer The drawer from the gui to draw certain elements
*/
virtual void on_update_ui_overlay(vkb::Drawer &drawer);
/**
* @brief Initializes the UI. Can be overridden to customize the way it is displayed.
*/
virtual void prepare_gui();
private:
/** brief Indicates that the view (position, rotation) has changed and buffers containing camera matrices need to be updated */
bool view_updated = false;
// Destination dimensions for resizing the window
vk::Extent2D dest_extent;
bool resizing = false;
void handle_mouse_move(int32_t x, int32_t y);
#if defined(VKB_DEBUG) || defined(VKB_VALIDATION_LAYERS)
/// The debug report callback
vk::DebugReportCallbackEXT debug_report_callback;
#endif
public:
bool prepared = false;
vk::Extent2D extent{1280, 720};
vk::ClearColorValue default_clear_color = std::array<float, 4>({{0.002f, 0.002f, 0.002f, 1.0f}});
float zoom = 0;
// Defines a frame rate independent timer value clamped from -1.0...1.0
// For use in animations, rotations, etc.
float timer = 0.0f;
// Multiplier for speeding up (or slowing down) the global timer
float timer_speed = 0.0025f;
bool paused = false;
// Use to adjust mouse rotation speed
float rotation_speed = 1.0f;
// Use to adjust mouse zoom speed
float zoom_speed = 1.0f;
vkb::Camera camera;
glm::vec3 rotation = glm::vec3();
glm::vec3 camera_pos = glm::vec3();
glm::vec2 mouse_pos;
std::string title = "HPP Vulkan API Example";
std::string name = "HPPAPIVulkanExample";
struct
{
vk::Image image;
vk::DeviceMemory mem;
vk::ImageView view;
} depth_stencil;
struct
{
bool left = false;
bool right = false;
bool middle = false;
} mouse_buttons;
// true if application has focused, false if moved to background
bool focused = false;
struct TouchPos
{
int32_t x;
int32_t y;
} touch_pos;
bool touch_down = false;
double touch_timer = 0.0;
uint32_t frame_count = 0;
float accumulated_time = 0.0f;
uint32_t fps = 1; // to prevent division by zero on first frame
};