├── .gitignore ├── README.md ├── build_ebook.py ├── code ├── 00_base_code.cpp ├── 01_instance_creation.cpp ├── 02_validation_layers.cpp ├── 03_physical_device_selection.cpp ├── 04_logical_device.cpp ├── 05_window_surface.cpp ├── 06_swap_chain_creation.cpp ├── 07_image_views.cpp ├── 08_graphics_pipeline.cpp ├── 09_shader_base.frag ├── 09_shader_base.vert ├── 09_shader_modules.cpp ├── 10_fixed_functions.cpp ├── 11_render_passes.cpp ├── 12_graphics_pipeline_complete.cpp ├── 13_framebuffers.cpp ├── 14_command_buffers.cpp ├── 15_hello_triangle.cpp ├── 16_swap_chain_recreation.cpp ├── 17_shader_vertexbuffer.frag ├── 17_shader_vertexbuffer.vert ├── 17_vertex_input.cpp ├── 18_vertex_buffer.cpp ├── 19_staging_buffer.cpp ├── 20_index_buffer.cpp ├── 21_descriptor_layout.cpp ├── 21_shader_ubo.frag ├── 21_shader_ubo.vert ├── 22_descriptor_sets.cpp ├── 23_texture_image.cpp ├── 24_sampler.cpp ├── 25_shader_textures.frag ├── 25_shader_textures.vert ├── 25_texture_mapping.cpp ├── 26_depth_buffering.cpp ├── 26_shader_depth.frag ├── 26_shader_depth.vert ├── 27_model_loading.cpp ├── 28_mipmapping.cpp ├── 29_multisampling.cpp ├── build │ └── msvc │ │ └── VulkanTutorial │ │ ├── .gitignore │ │ ├── 00_base_code │ │ ├── 00_base_code.vcxproj │ │ ├── 00_base_code.vcxproj.filters │ │ └── 00_base_code.vcxproj.user │ │ ├── 01_instance_creation │ │ ├── 01_instance_creation.vcxproj │ │ ├── 01_instance_creation.vcxproj.filters │ │ └── 01_instance_creation.vcxproj.user │ │ ├── 02_validation_layers │ │ ├── 02_validation_layers.vcxproj │ │ ├── 02_validation_layers.vcxproj.filters │ │ └── 02_validation_layers.vcxproj.user │ │ ├── 03_physical_device_selection │ │ ├── 03_physical_device_selection.vcxproj │ │ ├── 03_physical_device_selection.vcxproj.filters │ │ └── 03_physical_device_selection.vcxproj.user │ │ ├── 04_logical_device │ │ ├── 04_logical_device.vcxproj │ │ ├── 04_logical_device.vcxproj.filters │ │ └── 04_logical_device.vcxproj.user │ │ ├── 05_window_surface │ │ ├── 05_window_surface.vcxproj │ │ ├── 05_window_surface.vcxproj.filters │ │ └── 05_window_surface.vcxproj.user │ │ ├── 06_swap_chain_creation │ │ ├── 06_swap_chain_creation.vcxproj │ │ ├── 06_swap_chain_creation.vcxproj.filters │ │ └── 06_swap_chain_creation.vcxproj.user │ │ ├── 07_image_views │ │ ├── 07_image_views.vcxproj │ │ ├── 07_image_views.vcxproj.filters │ │ └── 07_image_views.vcxproj.user │ │ ├── 08_graphics_pipeline │ │ ├── 08_graphics_pipeline.vcxproj │ │ ├── 08_graphics_pipeline.vcxproj.filters │ │ └── 08_graphics_pipeline.vcxproj.user │ │ ├── 09_shader_modules │ │ ├── 09_shader_modules.vcxproj │ │ ├── 09_shader_modules.vcxproj.filters │ │ └── 09_shader_modules.vcxproj.user │ │ ├── 10_fixed_functions │ │ ├── 10_fixed_functions.vcxproj │ │ ├── 10_fixed_functions.vcxproj.filters │ │ └── 10_fixed_functions.vcxproj.user │ │ ├── 11_render_passes │ │ ├── 11_render_passes.vcxproj │ │ ├── 11_render_passes.vcxproj.filters │ │ └── 11_render_passes.vcxproj.user │ │ ├── 12_graphics_pipeline_complete │ │ ├── 12_graphics_pipeline_complete.vcxproj │ │ ├── 12_graphics_pipeline_complete.vcxproj.filters │ │ └── 12_graphics_pipeline_complete.vcxproj.user │ │ ├── 13_framebuffers │ │ ├── 13_framebuffers.vcxproj │ │ ├── 13_framebuffers.vcxproj.filters │ │ └── 13_framebuffers.vcxproj.user │ │ ├── 14_command_buffers │ │ ├── 14_command_buffers.vcxproj │ │ ├── 14_command_buffers.vcxproj.filters │ │ └── 14_command_buffers.vcxproj.user │ │ ├── 15_hello_triangle │ │ ├── 15_hello_triangle.vcxproj │ │ ├── 15_hello_triangle.vcxproj.filters │ │ └── 15_hello_triangle.vcxproj.user │ │ ├── 16_swap_chain_recreation │ │ ├── 16_swap_chain_recreation.vcxproj │ │ ├── 16_swap_chain_recreation.vcxproj.filters │ │ └── 16_swap_chain_recreation.vcxproj.user │ │ ├── 17_vertex_input │ │ ├── 17_vertex_input.vcxproj │ │ ├── 17_vertex_input.vcxproj.filters │ │ └── 17_vertex_input.vcxproj.user │ │ ├── 18_vertex_buffer │ │ ├── 18_vertex_buffer.vcxproj │ │ ├── 18_vertex_buffer.vcxproj.filters │ │ └── 18_vertex_buffer.vcxproj.user │ │ ├── 19_staging_buffer │ │ ├── 19_staging_buffer.vcxproj │ │ ├── 19_staging_buffer.vcxproj.filters │ │ └── 19_staging_buffer.vcxproj.user │ │ ├── 20_index_buffer │ │ ├── 20_index_buffer.vcxproj │ │ ├── 20_index_buffer.vcxproj.filters │ │ └── 20_index_buffer.vcxproj.user │ │ ├── 21_descriptor_layout │ │ ├── 21_descriptor_layout.vcxproj │ │ ├── 21_descriptor_layout.vcxproj.filters │ │ └── 21_descriptor_layout.vcxproj.user │ │ ├── 22_descriptor_sets │ │ ├── 22_descriptor_sets.vcxproj │ │ ├── 22_descriptor_sets.vcxproj.filters │ │ └── 22_descriptor_sets.vcxproj.user │ │ ├── 23_texture_image │ │ ├── 23_texture_image.vcxproj │ │ ├── 23_texture_image.vcxproj.filters │ │ └── 23_texture_image.vcxproj.user │ │ ├── 24_sampler │ │ ├── 24_sampler.vcxproj │ │ ├── 24_sampler.vcxproj.filters │ │ └── 24_sampler.vcxproj.user │ │ ├── 25_texture_mapping │ │ ├── 25_texture_mapping.vcxproj │ │ ├── 25_texture_mapping.vcxproj.filters │ │ └── 25_texture_mapping.vcxproj.user │ │ ├── 26_depth_buffering │ │ ├── 26_depth_buffering.vcxproj │ │ ├── 26_depth_buffering.vcxproj.filters │ │ └── 26_depth_buffering.vcxproj.user │ │ ├── 27_model_loading │ │ ├── 27_model_loading.vcxproj │ │ ├── 27_model_loading.vcxproj.filters │ │ └── 27_model_loading.vcxproj.user │ │ ├── 28_mipmapping │ │ ├── 28_mipmapping.vcxproj │ │ ├── 28_mipmapping.vcxproj.filters │ │ └── 28_mipmapping.vcxproj.user │ │ ├── 29_multisampling │ │ ├── 29_multisampling.vcxproj │ │ ├── 29_multisampling.vcxproj.filters │ │ └── 29_multisampling.vcxproj.user │ │ ├── README.md │ │ ├── VulkanTutorial.sln │ │ ├── clean.sh │ │ └── create_projects.sh └── incremental_patch.sh ├── config.json ├── ebook ├── Vulkan Tutorial en.epub ├── Vulkan Tutorial en.pdf ├── Vulkan Tutorial fr.epub ├── Vulkan Tutorial fr.pdf ├── cover.kra ├── cover.png └── listings-setup.tex ├── en ├── 00_Introduction.md ├── 01_Overview.md ├── 02_Development_environment.md ├── 03_Drawing_a_triangle │ ├── 00_Setup │ │ ├── 00_Base_code.md │ │ ├── 01_Instance.md │ │ ├── 02_Validation_layers.md │ │ ├── 03_Physical_devices_and_queue_families.md │ │ └── 04_Logical_device_and_queues.md │ ├── 01_Presentation │ │ ├── 00_Window_surface.md │ │ ├── 01_Swap_chain.md │ │ └── 02_Image_views.md │ ├── 02_Graphics_pipeline_basics │ │ ├── 00_Introduction.md │ │ ├── 01_Shader_modules.md │ │ ├── 02_Fixed_functions.md │ │ ├── 03_Render_passes.md │ │ └── 04_Conclusion.md │ ├── 03_Drawing │ │ ├── 00_Framebuffers.md │ │ ├── 01_Command_buffers.md │ │ └── 02_Rendering_and_presentation.md │ └── 04_Swap_chain_recreation.md ├── 04_Vertex_buffers │ ├── 00_Vertex_input_description.md │ ├── 01_Vertex_buffer_creation.md │ ├── 02_Staging_buffer.md │ └── 03_Index_buffer.md ├── 05_Uniform_buffers │ ├── 00_Descriptor_layout_and_buffer.md │ └── 01_Descriptor_pool_and_sets.md ├── 06_Texture_mapping │ ├── 00_Images.md │ ├── 01_Image_view_and_sampler.md │ └── 02_Combined_image_sampler.md ├── 07_Depth_buffering.md ├── 08_Loading_models.md ├── 09_Generating_Mipmaps.md ├── 10_Multisampling.md ├── 90_FAQ.md └── 95_Privacy_policy.md ├── fr ├── 00_Introduction.md ├── 01_Vue_d'ensemble.md ├── 02_Environnement_de_développement.md ├── 03_Dessiner_un_triangle │ ├── 00_Mise_en_place │ │ ├── 00_Code_de_base.md │ │ ├── 01_Instance.md │ │ ├── 02_Validation_layers.md │ │ ├── 03_Physical_devices_et_queue_families.md │ │ └── 04_Logical_device_et_queues.md │ ├── 01_Présentation │ │ ├── 00_Window_surface.md │ │ ├── 01_Swap_chain.md │ │ └── 02_Image_views.md │ ├── 02_Pipeline_graphique_basique │ │ ├── 00_Introduction.md │ │ ├── 01_Modules_shaders.md │ │ ├── 02_Fonctions_fixées.md │ │ ├── 03_Render_pass.md │ │ └── 04_Conclusion.md │ ├── 03_Effectuer_le_rendu │ │ ├── 00_Framebuffers.md │ │ ├── 01_Command_buffers.md │ │ └── 02_Rendu_et_présentation.md │ └── 04_Recréation_de_la_swap_chain.md ├── 04_Vertex_buffers │ ├── 00_Description_des_entrées_des_sommets.md │ ├── 01_Création_de_vertex_buffers.md │ ├── 02_Buffer_intermédiaire.md │ └── 03_Index_buffer.md ├── 05_Uniform_buffers │ ├── 00_Descriptor_layout_et_buffer.md │ └── 01_Descriptor_pool_et_sets.md ├── 06_Texture_mapping │ ├── 00_Images.md │ ├── 01_Vue_sur_image_et_sampler.md │ └── 02_Sampler_d'image_combiné.md ├── 07_Buffer_de_profondeur.md ├── 08_Charger_des_modèles.md ├── 09_Générer_des_mipmaps.md ├── 10_Multisampling.md ├── 90_FAQ.md └── 95_Politique_de_confidentialité.md ├── images ├── aliasing.png ├── anisotropic_filtering.png ├── antialiasing.png ├── cube_demo.png ├── cube_demo_mac.png ├── cube_demo_nowindow.png ├── depth_correct.png ├── depth_issues.png ├── drawing_model.png ├── extra_square.svg ├── favicon.png ├── glfw_directory.png ├── highmipmaps.png ├── include_dirs_stb.png ├── include_dirs_tinyobjloader.png ├── indexed_rectangle.png ├── inverted_texture_coordinates.png ├── library_directory.png ├── mipmaps.png ├── mipmaps_comparison.png ├── mipmaps_example.jpg ├── multisampling.png ├── multisampling_comparison.png ├── multisampling_comparison2.png ├── normalized_device_coordinates.svg ├── sample_shading.png ├── select_develop_branch.png ├── semaphore_in_use.png ├── spinning_quad.png ├── steam_layers_env.png ├── swap_chain_validation_layer.png ├── texcoord_visualization.png ├── texture.jpg ├── texture_addressing.png ├── texture_filtering.png ├── texture_on_square.png ├── texture_on_square_colorized.png ├── texture_on_square_repeated.png ├── triangle.png ├── triangle_coordinates.svg ├── triangle_coordinates_colors.png ├── triangle_white.png ├── unsubmitted_fence.png ├── validation_layer_anisotropy.png ├── validation_layer_test.png ├── vertex_vs_index.svg ├── viewports_scissors.png ├── vs_all_configs.png ├── vs_application_settings.png ├── vs_build_mode.png ├── vs_cpp17.png ├── vs_cpp_general.png ├── vs_dependencies.png ├── vs_export_template.png ├── vs_include_dirs.png ├── vs_link_dirs.png ├── vs_link_input.png ├── vs_link_settings.png ├── vs_new_cpp_project.png ├── vs_new_item.png ├── vs_new_source_file.png ├── vs_open_project_properties.png ├── vs_template.png ├── vs_test_window.png ├── vulkan_sdk_download_buttons.png ├── vulkan_simplified_pipeline.svg ├── xcode_frameworks.png ├── xcode_new_project.png ├── xcode_new_project_2.png ├── xcode_output.png ├── xcode_paths.png └── xcode_variables.png └── resources ├── viking_room.obj └── viking_room.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | ads.txt 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository is a derivative of [vulkan-tutorial.com](https://vulkan-tutorial.com) / [VulkanTutorial@github](https://github.com/Overv/VulkanTutorial). 2 | 3 | The only change is: 4 | 5 | * added MS Visual Studio 2019 [project files](code/build/msvc/VulkanTutorial/) 6 | 7 | License 8 | ------- 9 | 10 | The contents of this repository are licensed as [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/), 11 | unless stated otherwise. By contributing to this repository, you agree to license 12 | your contributions to the public under that same license. 13 | 14 | The code listings in the `code` directory are licensed as [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/). 15 | By contributing to that directory, you agree to license your contributions to 16 | the public under that same public domain-like license. 17 | -------------------------------------------------------------------------------- /build_ebook.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import datetime 3 | import os 4 | import re 5 | 6 | 7 | def create_ebook(path): 8 | 9 | name_path = path 10 | print('\n Creating \"' + name_path + '\" ebook') 11 | # Recursively gather all markdown files in the right order 12 | markdownFiles = [] 13 | 14 | for root, subdirs, files in os.walk(name_path): 15 | for fn in files: 16 | if 'md' in fn and 'ebook.md' not in fn: 17 | path = os.path.join(root, fn) 18 | 19 | # "02_Development_environment.md" -> "Development environment" 20 | # "02_Development_environment.md" -> "02_Development_environment" 21 | title = fn.split('.')[0] 22 | # "02_Development_environment" -> "02 Development environment" 23 | title = title.replace('_', ' ') 24 | # "02 Development environment" -> "Development environment" 25 | title = ' '.join(title.split(' ')[1:]) 26 | 27 | with open(path, 'r') as f: 28 | markdownFiles.append({ 29 | 'title': title, 30 | 'filename': os.path.join(root, fn), 31 | 'contents': f.read() 32 | }) 33 | 34 | markdownFiles.sort(key=lambda entry: entry['filename']) 35 | 36 | # Create concatenated document 37 | print('processing markdown...') 38 | 39 | allMarkdown = '' 40 | 41 | for entry in markdownFiles: 42 | contents = entry['contents'] 43 | 44 | # Add title 45 | contents = '# ' + entry['title'] + '\n\n' + contents 46 | 47 | # Fix image links 48 | contents = re.sub(r'\/images\/', 'images/', contents) 49 | contents = re.sub(r'\.svg', '.png', contents) 50 | 51 | # Fix remaining relative links (e.g. code files) 52 | contents = re.sub( 53 | r'\]\(\/', '](https://vulkan-tutorial.com/', contents) 54 | 55 | # Fix chapter references 56 | def repl(m): 57 | target = m.group(1) 58 | target = target.lower() 59 | target = re.sub('_', '-', target) 60 | target = target.split('/')[-1] 61 | 62 | return '](#' + target + ')' 63 | 64 | contents = re.sub(r'\]\(!([^)]+)\)', repl, contents) 65 | 66 | allMarkdown += contents + '\n\n' 67 | 68 | # Add title 69 | dateNow = datetime.datetime.now() 70 | 71 | metadata = '% Vulkan Tutorial\n' 72 | metadata += '% Alexander Overvoorde\n' 73 | metadata += '% ' + dateNow.strftime('%B %Y') + '\n\n' 74 | 75 | allMarkdown = metadata + allMarkdown 76 | 77 | with open('ebook.md', 'w') as f: 78 | f.write(allMarkdown) 79 | 80 | # Building PDF 81 | print('building pdf...') 82 | 83 | subprocess.check_output(['pandoc', 'ebook.md', '-V', 'documentclass=report', '-t', 'latex', '-s', 84 | '--toc', '--listings', '-H', 'ebook/listings-setup.tex', '-o', 'ebook/Vulkan Tutorial ' + name_path + '.pdf', '--pdf-engine=xelatex']) 85 | 86 | print('building epub...') 87 | 88 | subprocess.check_output( 89 | ['pandoc', 'ebook.md', '--toc', '-o', 'ebook/Vulkan Tutorial ' + name_path + '.epub', '--epub-cover-image=ebook/cover.png']) 90 | 91 | # Clean up 92 | os.remove('ebook.md') 93 | 94 | 95 | # Convert all SVG images to PNG for pandoc 96 | print('converting svgs...') 97 | 98 | generatedPngs = [] 99 | 100 | for fn in os.listdir('images'): 101 | parts = fn.split('.') 102 | 103 | if parts[1] == 'svg': 104 | subprocess.check_output(['inkscape', '--export-filename=images/' + 105 | parts[0] + '.png', 'images/' + fn], stderr=subprocess.STDOUT) 106 | generatedPngs.append('images/' + parts[0] + '.png') 107 | 108 | create_ebook('en') 109 | create_ebook('fr') 110 | 111 | for fn in generatedPngs: 112 | os.remove(fn) 113 | -------------------------------------------------------------------------------- /code/00_base_code.cpp: -------------------------------------------------------------------------------- 1 | #define GLFW_INCLUDE_VULKAN 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | const uint32_t WIDTH = 800; 9 | const uint32_t HEIGHT = 600; 10 | 11 | class HelloTriangleApplication { 12 | public: 13 | void run() { 14 | initWindow(); 15 | initVulkan(); 16 | mainLoop(); 17 | cleanup(); 18 | } 19 | 20 | private: 21 | GLFWwindow* window; 22 | 23 | void initWindow() { 24 | glfwInit(); 25 | 26 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 27 | glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); 28 | 29 | window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); 30 | } 31 | 32 | void initVulkan() { 33 | 34 | } 35 | 36 | void mainLoop() { 37 | while (!glfwWindowShouldClose(window)) { 38 | glfwPollEvents(); 39 | } 40 | } 41 | 42 | void cleanup() { 43 | glfwDestroyWindow(window); 44 | 45 | glfwTerminate(); 46 | } 47 | }; 48 | 49 | int main() { 50 | HelloTriangleApplication app; 51 | 52 | try { 53 | app.run(); 54 | } catch (const std::exception& e) { 55 | std::cerr << e.what() << std::endl; 56 | return EXIT_FAILURE; 57 | } 58 | 59 | return EXIT_SUCCESS; 60 | } 61 | -------------------------------------------------------------------------------- /code/01_instance_creation.cpp: -------------------------------------------------------------------------------- 1 | #define GLFW_INCLUDE_VULKAN 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | const uint32_t WIDTH = 800; 9 | const uint32_t HEIGHT = 600; 10 | 11 | class HelloTriangleApplication { 12 | public: 13 | void run() { 14 | initWindow(); 15 | initVulkan(); 16 | mainLoop(); 17 | cleanup(); 18 | } 19 | 20 | private: 21 | GLFWwindow* window; 22 | 23 | VkInstance instance; 24 | 25 | void initWindow() { 26 | glfwInit(); 27 | 28 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 29 | glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); 30 | 31 | window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); 32 | } 33 | 34 | void initVulkan() { 35 | createInstance(); 36 | } 37 | 38 | void mainLoop() { 39 | while (!glfwWindowShouldClose(window)) { 40 | glfwPollEvents(); 41 | } 42 | } 43 | 44 | void cleanup() { 45 | vkDestroyInstance(instance, nullptr); 46 | 47 | glfwDestroyWindow(window); 48 | 49 | glfwTerminate(); 50 | } 51 | 52 | void createInstance() { 53 | VkApplicationInfo appInfo{}; 54 | appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 55 | appInfo.pApplicationName = "Hello Triangle"; 56 | appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); 57 | appInfo.pEngineName = "No Engine"; 58 | appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); 59 | appInfo.apiVersion = VK_API_VERSION_1_0; 60 | 61 | VkInstanceCreateInfo createInfo{}; 62 | createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 63 | createInfo.pApplicationInfo = &appInfo; 64 | 65 | uint32_t glfwExtensionCount = 0; 66 | const char** glfwExtensions; 67 | glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); 68 | 69 | createInfo.enabledExtensionCount = glfwExtensionCount; 70 | createInfo.ppEnabledExtensionNames = glfwExtensions; 71 | 72 | createInfo.enabledLayerCount = 0; 73 | 74 | if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { 75 | throw std::runtime_error("failed to create instance!"); 76 | } 77 | } 78 | }; 79 | 80 | int main() { 81 | HelloTriangleApplication app; 82 | 83 | try { 84 | app.run(); 85 | } catch (const std::exception& e) { 86 | std::cerr << e.what() << std::endl; 87 | return EXIT_FAILURE; 88 | } 89 | 90 | return EXIT_SUCCESS; 91 | } 92 | -------------------------------------------------------------------------------- /code/02_validation_layers.cpp: -------------------------------------------------------------------------------- 1 | #define GLFW_INCLUDE_VULKAN 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | const uint32_t WIDTH = 800; 11 | const uint32_t HEIGHT = 600; 12 | 13 | const std::vector validationLayers = { 14 | "VK_LAYER_KHRONOS_validation" 15 | }; 16 | 17 | #ifdef NDEBUG 18 | const bool enableValidationLayers = false; 19 | #else 20 | const bool enableValidationLayers = true; 21 | #endif 22 | 23 | VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) { 24 | auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); 25 | if (func != nullptr) { 26 | return func(instance, pCreateInfo, pAllocator, pDebugMessenger); 27 | } else { 28 | return VK_ERROR_EXTENSION_NOT_PRESENT; 29 | } 30 | } 31 | 32 | void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { 33 | auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); 34 | if (func != nullptr) { 35 | func(instance, debugMessenger, pAllocator); 36 | } 37 | } 38 | 39 | class HelloTriangleApplication { 40 | public: 41 | void run() { 42 | initWindow(); 43 | initVulkan(); 44 | mainLoop(); 45 | cleanup(); 46 | } 47 | 48 | private: 49 | GLFWwindow* window; 50 | 51 | VkInstance instance; 52 | VkDebugUtilsMessengerEXT debugMessenger; 53 | 54 | void initWindow() { 55 | glfwInit(); 56 | 57 | glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); 58 | glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); 59 | 60 | window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); 61 | } 62 | 63 | void initVulkan() { 64 | createInstance(); 65 | setupDebugMessenger(); 66 | } 67 | 68 | void mainLoop() { 69 | while (!glfwWindowShouldClose(window)) { 70 | glfwPollEvents(); 71 | } 72 | } 73 | 74 | void cleanup() { 75 | if (enableValidationLayers) { 76 | DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); 77 | } 78 | 79 | vkDestroyInstance(instance, nullptr); 80 | 81 | glfwDestroyWindow(window); 82 | 83 | glfwTerminate(); 84 | } 85 | 86 | void createInstance() { 87 | if (enableValidationLayers && !checkValidationLayerSupport()) { 88 | throw std::runtime_error("validation layers requested, but not available!"); 89 | } 90 | 91 | VkApplicationInfo appInfo{}; 92 | appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 93 | appInfo.pApplicationName = "Hello Triangle"; 94 | appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); 95 | appInfo.pEngineName = "No Engine"; 96 | appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); 97 | appInfo.apiVersion = VK_API_VERSION_1_0; 98 | 99 | VkInstanceCreateInfo createInfo{}; 100 | createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 101 | createInfo.pApplicationInfo = &appInfo; 102 | 103 | auto extensions = getRequiredExtensions(); 104 | createInfo.enabledExtensionCount = static_cast(extensions.size()); 105 | createInfo.ppEnabledExtensionNames = extensions.data(); 106 | 107 | VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; 108 | if (enableValidationLayers) { 109 | createInfo.enabledLayerCount = static_cast(validationLayers.size()); 110 | createInfo.ppEnabledLayerNames = validationLayers.data(); 111 | 112 | populateDebugMessengerCreateInfo(debugCreateInfo); 113 | createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo; 114 | } else { 115 | createInfo.enabledLayerCount = 0; 116 | 117 | createInfo.pNext = nullptr; 118 | } 119 | 120 | if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { 121 | throw std::runtime_error("failed to create instance!"); 122 | } 123 | } 124 | 125 | void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { 126 | createInfo = {}; 127 | createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; 128 | createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; 129 | createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; 130 | createInfo.pfnUserCallback = debugCallback; 131 | } 132 | 133 | void setupDebugMessenger() { 134 | if (!enableValidationLayers) return; 135 | 136 | VkDebugUtilsMessengerCreateInfoEXT createInfo; 137 | populateDebugMessengerCreateInfo(createInfo); 138 | 139 | if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) { 140 | throw std::runtime_error("failed to set up debug messenger!"); 141 | } 142 | } 143 | 144 | std::vector getRequiredExtensions() { 145 | uint32_t glfwExtensionCount = 0; 146 | const char** glfwExtensions; 147 | glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); 148 | 149 | std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); 150 | 151 | if (enableValidationLayers) { 152 | extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); 153 | } 154 | 155 | return extensions; 156 | } 157 | 158 | bool checkValidationLayerSupport() { 159 | uint32_t layerCount; 160 | vkEnumerateInstanceLayerProperties(&layerCount, nullptr); 161 | 162 | std::vector availableLayers(layerCount); 163 | vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); 164 | 165 | for (const char* layerName : validationLayers) { 166 | bool layerFound = false; 167 | 168 | for (const auto& layerProperties : availableLayers) { 169 | if (strcmp(layerName, layerProperties.layerName) == 0) { 170 | layerFound = true; 171 | break; 172 | } 173 | } 174 | 175 | if (!layerFound) { 176 | return false; 177 | } 178 | } 179 | 180 | return true; 181 | } 182 | 183 | static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) { 184 | std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; 185 | 186 | return VK_FALSE; 187 | } 188 | }; 189 | 190 | int main() { 191 | HelloTriangleApplication app; 192 | 193 | try { 194 | app.run(); 195 | } catch (const std::exception& e) { 196 | std::cerr << e.what() << std::endl; 197 | return EXIT_FAILURE; 198 | } 199 | 200 | return EXIT_SUCCESS; 201 | } 202 | -------------------------------------------------------------------------------- /code/09_shader_base.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location = 0) in vec3 fragColor; 4 | 5 | layout(location = 0) out vec4 outColor; 6 | 7 | void main() { 8 | outColor = vec4(fragColor, 1.0); 9 | } 10 | -------------------------------------------------------------------------------- /code/09_shader_base.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location = 0) out vec3 fragColor; 4 | 5 | vec2 positions[3] = vec2[]( 6 | vec2(0.0, -0.5), 7 | vec2(0.5, 0.5), 8 | vec2(-0.5, 0.5) 9 | ); 10 | 11 | vec3 colors[3] = vec3[]( 12 | vec3(1.0, 0.0, 0.0), 13 | vec3(0.0, 1.0, 0.0), 14 | vec3(0.0, 0.0, 1.0) 15 | ); 16 | 17 | void main() { 18 | gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); 19 | fragColor = colors[gl_VertexIndex]; 20 | } 21 | -------------------------------------------------------------------------------- /code/17_shader_vertexbuffer.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location = 0) in vec3 fragColor; 4 | 5 | layout(location = 0) out vec4 outColor; 6 | 7 | void main() { 8 | outColor = vec4(fragColor, 1.0); 9 | } 10 | -------------------------------------------------------------------------------- /code/17_shader_vertexbuffer.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location = 0) in vec2 inPosition; 4 | layout(location = 1) in vec3 inColor; 5 | 6 | layout(location = 0) out vec3 fragColor; 7 | 8 | void main() { 9 | gl_Position = vec4(inPosition, 0.0, 1.0); 10 | fragColor = inColor; 11 | } 12 | -------------------------------------------------------------------------------- /code/21_shader_ubo.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location = 0) in vec3 fragColor; 4 | 5 | layout(location = 0) out vec4 outColor; 6 | 7 | void main() { 8 | outColor = vec4(fragColor, 1.0); 9 | } 10 | -------------------------------------------------------------------------------- /code/21_shader_ubo.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(binding = 0) uniform UniformBufferObject { 4 | mat4 model; 5 | mat4 view; 6 | mat4 proj; 7 | } ubo; 8 | 9 | layout(location = 0) in vec2 inPosition; 10 | layout(location = 1) in vec3 inColor; 11 | 12 | layout(location = 0) out vec3 fragColor; 13 | 14 | void main() { 15 | gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); 16 | fragColor = inColor; 17 | } 18 | -------------------------------------------------------------------------------- /code/25_shader_textures.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(binding = 1) uniform sampler2D texSampler; 4 | 5 | layout(location = 0) in vec3 fragColor; 6 | layout(location = 1) in vec2 fragTexCoord; 7 | 8 | layout(location = 0) out vec4 outColor; 9 | 10 | void main() { 11 | outColor = texture(texSampler, fragTexCoord); 12 | } 13 | -------------------------------------------------------------------------------- /code/25_shader_textures.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(binding = 0) uniform UniformBufferObject { 4 | mat4 model; 5 | mat4 view; 6 | mat4 proj; 7 | } ubo; 8 | 9 | layout(location = 0) in vec2 inPosition; 10 | layout(location = 1) in vec3 inColor; 11 | layout(location = 2) in vec2 inTexCoord; 12 | 13 | layout(location = 0) out vec3 fragColor; 14 | layout(location = 1) out vec2 fragTexCoord; 15 | 16 | void main() { 17 | gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); 18 | fragColor = inColor; 19 | fragTexCoord = inTexCoord; 20 | } 21 | -------------------------------------------------------------------------------- /code/26_shader_depth.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(binding = 1) uniform sampler2D texSampler; 4 | 5 | layout(location = 0) in vec3 fragColor; 6 | layout(location = 1) in vec2 fragTexCoord; 7 | 8 | layout(location = 0) out vec4 outColor; 9 | 10 | void main() { 11 | outColor = texture(texSampler, fragTexCoord); 12 | } 13 | -------------------------------------------------------------------------------- /code/26_shader_depth.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(binding = 0) uniform UniformBufferObject { 4 | mat4 model; 5 | mat4 view; 6 | mat4 proj; 7 | } ubo; 8 | 9 | layout(location = 0) in vec3 inPosition; 10 | layout(location = 1) in vec3 inColor; 11 | layout(location = 2) in vec2 inTexCoord; 12 | 13 | layout(location = 0) out vec3 fragColor; 14 | layout(location = 1) out vec2 fragTexCoord; 15 | 16 | void main() { 17 | gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0); 18 | fragColor = inColor; 19 | fragTexCoord = inTexCoord; 20 | } 21 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/.gitignore: -------------------------------------------------------------------------------- 1 | Debug 2 | .vs 3 | x64 4 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/00_base_code/00_base_code.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/00_base_code/00_base_code.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/01_instance_creation/01_instance_creation.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/01_instance_creation/01_instance_creation.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/02_validation_layers/02_validation_layers.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/02_validation_layers/02_validation_layers.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/03_physical_device_selection/03_physical_device_selection.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/03_physical_device_selection/03_physical_device_selection.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/04_logical_device/04_logical_device.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/04_logical_device/04_logical_device.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/05_window_surface/05_window_surface.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/05_window_surface/05_window_surface.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/06_swap_chain_creation/06_swap_chain_creation.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/06_swap_chain_creation/06_swap_chain_creation.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/07_image_views/07_image_views.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/07_image_views/07_image_views.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/08_graphics_pipeline/08_graphics_pipeline.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/08_graphics_pipeline/08_graphics_pipeline.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/09_shader_modules/09_shader_modules.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/09_shader_modules/09_shader_modules.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/10_fixed_functions/10_fixed_functions.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/10_fixed_functions/10_fixed_functions.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/11_render_passes/11_render_passes.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/11_render_passes/11_render_passes.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/12_graphics_pipeline_complete/12_graphics_pipeline_complete.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/12_graphics_pipeline_complete/12_graphics_pipeline_complete.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/13_framebuffers/13_framebuffers.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/13_framebuffers/13_framebuffers.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/14_command_buffers/14_command_buffers.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/14_command_buffers/14_command_buffers.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/15_hello_triangle/15_hello_triangle.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/15_hello_triangle/15_hello_triangle.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/16_swap_chain_recreation/16_swap_chain_recreation.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/16_swap_chain_recreation/16_swap_chain_recreation.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/17_vertex_input/17_vertex_input.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/17_vertex_input/17_vertex_input.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/18_vertex_buffer/18_vertex_buffer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/18_vertex_buffer/18_vertex_buffer.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/19_staging_buffer/19_staging_buffer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/19_staging_buffer/19_staging_buffer.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/20_index_buffer/20_index_buffer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/20_index_buffer/20_index_buffer.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/21_descriptor_layout/21_descriptor_layout.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/21_descriptor_layout/21_descriptor_layout.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/22_descriptor_sets/22_descriptor_sets.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/22_descriptor_sets/22_descriptor_sets.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/23_texture_image/23_texture_image.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/23_texture_image/23_texture_image.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/24_sampler/24_sampler.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/24_sampler/24_sampler.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/25_texture_mapping/25_texture_mapping.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/25_texture_mapping/25_texture_mapping.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/26_depth_buffering/26_depth_buffering.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/26_depth_buffering/26_depth_buffering.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/27_model_loading/27_model_loading.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/27_model_loading/27_model_loading.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/28_mipmapping/28_mipmapping.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/28_mipmapping/28_mipmapping.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/29_multisampling/29_multisampling.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx;frag;vert 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Resource Files 25 | 26 | 27 | Resource Files 28 | 29 | 30 | Resource Files 31 | 32 | 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/29_multisampling/29_multisampling.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(OutDir) 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/README.md: -------------------------------------------------------------------------------- 1 | MS Visual Studio 2019 Solution for x64 (debug+release, no 32 bit). 2 | 3 | Required dependencies (may be installed via [vcpkg tool](https://github.com/microsoft/vcpkg)): 4 | 5 | - stb (2020-09-14) 6 | - tinyobjloader (2.0.0-rc2) 7 | - glfw3 (3.3.4) 8 | - glm (0.9.9.8) 9 | 10 | Version numbers indicate last version that verified ok. 11 | 12 | Of course, we also require the [Vulkan SDK](https://www.lunarg.com/vulkan-sdk/). 13 | It is located via VULKAN_SDK env var set by SDK installer and must be downloaded and 14 | installed manually (last verified ok: 1.2.176.1). 15 | 16 | To start each example via F5 shortcut, set Startup Project in Solution Properties 17 | to "Current selection". 18 | 19 | If you want a working syntax highlighting for the shader sources, this is what worked for me 20 | at the time of writing this: 21 | 22 | - https://github.com/danielscherzer/GLSL for MSVC 2019 (may cause problems with nsight or syntax highlight extensions like "Syntax Highlighting Pack"). 23 | - https://github.com/stef-levesque/vscode-shader/ for *VS Code*. 24 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf x64 Debug */x64 .vs */Debug 4 | -------------------------------------------------------------------------------- /code/build/msvc/VulkanTutorial/create_projects.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # after running this script, use 4 | # https://marketplace.visualstudio.com/items?itemName=MaciejGudanowicz.AddMultipleProjectsToSolution 5 | # to add all generated projects to the solution. 6 | 7 | set -ex 8 | set -o pipefail 9 | 10 | codedir=../../.. 11 | srcproject=29_multisampling 12 | 13 | projects=`find $codedir -maxdepth 1 -type f -name '*.cpp' -printf "%f\n" | while read l; do echo ${l%.cpp}; done |grep -v ^$srcproject | sort` 14 | curfrag="" 15 | curvert="" 16 | 17 | for proj in $projects; do 18 | projnum=${proj%%_*} 19 | if frag=$(ls $codedir/${projnum}_*.frag); then 20 | curfrag=$(basename "$frag") 21 | fi 22 | if vert=$(ls $codedir/${projnum}_*.vert); then 23 | curvert=$(basename "$vert") 24 | fi 25 | rm -rf $proj 26 | cp -ra $srcproject $proj 27 | for suffix in "" .filters .user; do 28 | mv $proj/$srcproject.vcxproj$suffix $proj/$proj.vcxproj$suffix 29 | done 30 | sed -i $proj/$proj.vcxproj -e "s#29_multisampling.cpp#$proj.cpp#" 31 | sed -i $proj/$proj.vcxproj.filters -e "s#29_multisampling.cpp#$proj.cpp#" 32 | if [[ -n "$curvert" ]]; then 33 | sed -i $proj/$proj.vcxproj -e "s#26_shader_depth.vert#$curvert#" 34 | sed -i $proj/$proj.vcxproj.filters -e "s#26_shader_depth.vert#$curvert#" 35 | fi 36 | if [[ -n "$curfrag" ]]; then 37 | sed -i $proj/$proj.vcxproj -e "s#26_shader_depth.frag#$curfrag#" 38 | sed -i $proj/$proj.vcxproj.filters -e "s#26_shader_depth.vert#$curvert#" 39 | fi 40 | done 41 | 42 | 43 | -------------------------------------------------------------------------------- /code/incremental_patch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Check if both a starting file and patch are provided 4 | if [ $# != 2 ]; then 5 | echo "usage: " 6 | echo "specified patch will be applied to first_file.cpp and every code file larger than it (from later chapters)" 7 | exit 1 8 | fi 9 | 10 | # Iterate over code files in order of increasing size 11 | # i.e. in order of chapters (every chapter adds code) 12 | apply_patch=false 13 | 14 | for f in `ls -Sr *.cpp` 15 | do 16 | # Apply patch on every code file including and after initial one 17 | if [ $f = $1 ] || [ $apply_patch = true ]; then 18 | apply_patch=true 19 | 20 | patch -f $f < $2 | grep -q "FAILED" > /dev/null 21 | if [ $? = 0 ]; then 22 | echo "failed to apply patch to $f" 23 | exit 1 24 | fi 25 | 26 | rm -f *.orig 27 | fi 28 | done 29 | 30 | echo "patch successfully applied to all files" 31 | exit 0 32 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Vulkan Tutorial", 3 | "tagline": "A tutorial that teaches you everything it takes to render 3D graphics with the Vulkan API. It covers everything from Windows/Linux setup to rendering and debugging.", 4 | "author": "Alexander Overvoorde", 5 | "live": { 6 | "inherit_index": true, 7 | "clean_urls": true 8 | }, 9 | "html": { 10 | "theme": "vulkan-vulkan", 11 | "auto_landing": false, 12 | "breadcrumbs": true, 13 | "breadcrumb_separator": "Chevrons", 14 | "date_modified": false, 15 | "toggle_code": false, 16 | "float": false, 17 | "auto_toc": true, 18 | 19 | "links": { 20 | "GitHub Repository": "https://github.com/Overv/VulkanTutorial", 21 | "Support the website": "https://www.paypal.me/AOvervoorde", 22 | "Vulkan Specification": "https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/pdf/vkspec.pdf", 23 | "Vulkan Quick Reference": "https://www.khronos.org/files/vulkan10-reference-guide.pdf", 24 | "LunarG Vulkan SDK": "https://lunarg.com/vulkan-sdk/", 25 | "Vulkan Hardware Database": "http://vulkan.gpuinfo.org/", 26 | "Tutorial for Rust": "https://github.com/bwasty/vulkan-tutorial-rs", 27 | "Tutorial for Java": "https://github.com/Naitsirc98/Vulkan-Tutorial-Java", 28 | "Visual Studio 2019 samples": "https://github.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles" 29 | } 30 | }, 31 | "ignore": { 32 | "files": ["README.md", "build_ebook.py","daux.patch",".gitignore"], 33 | "folders": ["ebook"] 34 | }, 35 | "languages": {"en": "English", "fr": "French"}, 36 | "language": "en", 37 | "processor": "VulkanLinkProcessor" 38 | } 39 | -------------------------------------------------------------------------------- /ebook/Vulkan Tutorial en.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/ebook/Vulkan Tutorial en.epub -------------------------------------------------------------------------------- /ebook/Vulkan Tutorial en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/ebook/Vulkan Tutorial en.pdf -------------------------------------------------------------------------------- /ebook/Vulkan Tutorial fr.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/ebook/Vulkan Tutorial fr.epub -------------------------------------------------------------------------------- /ebook/Vulkan Tutorial fr.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/ebook/Vulkan Tutorial fr.pdf -------------------------------------------------------------------------------- /ebook/cover.kra: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/ebook/cover.kra -------------------------------------------------------------------------------- /ebook/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/ebook/cover.png -------------------------------------------------------------------------------- /ebook/listings-setup.tex: -------------------------------------------------------------------------------- 1 | % Contents of listings-setup.tex 2 | \usepackage{xcolor} 3 | 4 | \lstset{ 5 | basicstyle=\ttfamily, 6 | numbers=left, 7 | keywordstyle=\color[rgb]{0.13,0.29,0.53}\bfseries, 8 | stringstyle=\color[rgb]{0.31,0.60,0.02}, 9 | commentstyle=\color[rgb]{0.56,0.35,0.01}\itshape, 10 | numberstyle=\footnotesize, 11 | stepnumber=1, 12 | numbersep=5pt, 13 | backgroundcolor=\color[RGB]{248,248,248}, 14 | showspaces=false, 15 | showstringspaces=false, 16 | showtabs=false, 17 | tabsize=2, 18 | captionpos=b, 19 | breaklines=true, 20 | breakatwhitespace=true, 21 | breakautoindent=true, 22 | escapeinside={\%*}{*)}, 23 | linewidth=\textwidth, 24 | basewidth=0.5em, 25 | } -------------------------------------------------------------------------------- /en/03_Drawing_a_triangle/00_Setup/01_Instance.md: -------------------------------------------------------------------------------- 1 | ## Creating an instance 2 | 3 | The very first thing you need to do is initialize the Vulkan library by creating 4 | an *instance*. The instance is the connection between your application and the 5 | Vulkan library and creating it involves specifying some details about your 6 | application to the driver. 7 | 8 | Start by adding a `createInstance` function and invoking it in the 9 | `initVulkan` function. 10 | 11 | ```c++ 12 | void initVulkan() { 13 | createInstance(); 14 | } 15 | ``` 16 | 17 | Additionally add a data member to hold the handle to the instance: 18 | 19 | ```c++ 20 | private: 21 | VkInstance instance; 22 | ``` 23 | 24 | Now, to create an instance we'll first have to fill in a struct with some 25 | information about our application. This data is technically optional, but it may 26 | provide some useful information to the driver in order to optimize our specific 27 | application (e.g. because it uses a well-known graphics engine with 28 | certain special behavior). This struct is called `VkApplicationInfo`: 29 | 30 | ```c++ 31 | void createInstance() { 32 | VkApplicationInfo appInfo{}; 33 | appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 34 | appInfo.pApplicationName = "Hello Triangle"; 35 | appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); 36 | appInfo.pEngineName = "No Engine"; 37 | appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); 38 | appInfo.apiVersion = VK_API_VERSION_1_0; 39 | } 40 | ``` 41 | 42 | As mentioned before, many structs in Vulkan require you to explicitly specify 43 | the type in the `sType` member. This is also one of the many structs with a 44 | `pNext` member that can point to extension information in the future. We're 45 | using value initialization here to leave it as `nullptr`. 46 | 47 | A lot of information in Vulkan is passed through structs instead of function 48 | parameters and we'll have to fill in one more struct to provide sufficient 49 | information for creating an instance. This next struct is not optional and tells 50 | the Vulkan driver which global extensions and validation layers we want to use. 51 | Global here means that they apply to the entire program and not a specific 52 | device, which will become clear in the next few chapters. 53 | 54 | ```c++ 55 | VkInstanceCreateInfo createInfo{}; 56 | createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 57 | createInfo.pApplicationInfo = &appInfo; 58 | ``` 59 | 60 | The first two parameters are straightforward. The next two layers specify the 61 | desired global extensions. As mentioned in the overview chapter, Vulkan is a 62 | platform agnostic API, which means that you need an extension to interface with 63 | the window system. GLFW has a handy built-in function that returns the 64 | extension(s) it needs to do that which we can pass to the struct: 65 | 66 | ```c++ 67 | uint32_t glfwExtensionCount = 0; 68 | const char** glfwExtensions; 69 | 70 | glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); 71 | 72 | createInfo.enabledExtensionCount = glfwExtensionCount; 73 | createInfo.ppEnabledExtensionNames = glfwExtensions; 74 | ``` 75 | 76 | The last two members of the struct determine the global validation layers to 77 | enable. We'll talk about these more in-depth in the next chapter, so just leave 78 | these empty for now. 79 | 80 | ```c++ 81 | createInfo.enabledLayerCount = 0; 82 | ``` 83 | 84 | We've now specified everything Vulkan needs to create an instance and we can 85 | finally issue the `vkCreateInstance` call: 86 | 87 | ```c++ 88 | VkResult result = vkCreateInstance(&createInfo, nullptr, &instance); 89 | ``` 90 | 91 | As you'll see, the general pattern that object creation function parameters in 92 | Vulkan follow is: 93 | 94 | * Pointer to struct with creation info 95 | * Pointer to custom allocator callbacks, always `nullptr` in this tutorial 96 | * Pointer to the variable that stores the handle to the new object 97 | 98 | If everything went well then the handle to the instance was stored in the 99 | `VkInstance` class member. Nearly all Vulkan functions return a value of type 100 | `VkResult` that is either `VK_SUCCESS` or an error code. To check if the 101 | instance was created successfully, we don't need to store the result and can 102 | just use a check for the success value instead: 103 | 104 | ```c++ 105 | if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { 106 | throw std::runtime_error("failed to create instance!"); 107 | } 108 | ``` 109 | 110 | Now run the program to make sure that the instance is created successfully. 111 | 112 | ## Checking for extension support 113 | 114 | If you look at the `vkCreateInstance` documentation then you'll see that one of 115 | the possible error codes is `VK_ERROR_EXTENSION_NOT_PRESENT`. We could simply 116 | specify the extensions we require and terminate if that error code comes back. 117 | That makes sense for essential extensions like the window system interface, but 118 | what if we want to check for optional functionality? 119 | 120 | To retrieve a list of supported extensions before creating an instance, there's 121 | the `vkEnumerateInstanceExtensionProperties` function. It takes a pointer to a 122 | variable that stores the number of extensions and an array of 123 | `VkExtensionProperties` to store details of the extensions. It also takes an 124 | optional first parameter that allows us to filter extensions by a specific 125 | validation layer, which we'll ignore for now. 126 | 127 | To allocate an array to hold the extension details we first need to know how 128 | many there are. You can request just the number of extensions by leaving the 129 | latter parameter empty: 130 | 131 | ```c++ 132 | uint32_t extensionCount = 0; 133 | vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); 134 | ``` 135 | 136 | Now allocate an array to hold the extension details (`include `): 137 | 138 | ```c++ 139 | std::vector extensions(extensionCount); 140 | ``` 141 | 142 | Finally we can query the extension details: 143 | 144 | ```c++ 145 | vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); 146 | ``` 147 | 148 | Each `VkExtensionProperties` struct contains the name and version of an 149 | extension. We can list them with a simple for loop (`\t` is a tab for 150 | indentation): 151 | 152 | ```c++ 153 | std::cout << "available extensions:\n"; 154 | 155 | for (const auto& extension : extensions) { 156 | std::cout << '\t' << extension.extensionName << '\n'; 157 | } 158 | ``` 159 | 160 | You can add this code to the `createInstance` function if you'd like to provide 161 | some details about the Vulkan support. As a challenge, try to create a function 162 | that checks if all of the extensions returned by 163 | `glfwGetRequiredInstanceExtensions` are included in the supported extensions 164 | list. 165 | 166 | ## Cleaning up 167 | 168 | The `VkInstance` should be only destroyed right before the program exits. It can 169 | be destroyed in `cleanup` with the `vkDestroyInstance` function: 170 | 171 | ```c++ 172 | void cleanup() { 173 | vkDestroyInstance(instance, nullptr); 174 | 175 | glfwDestroyWindow(window); 176 | 177 | glfwTerminate(); 178 | } 179 | ``` 180 | 181 | The parameters for the `vkDestroyInstance` function are straightforward. As 182 | mentioned in the previous chapter, the allocation and deallocation functions 183 | in Vulkan have an optional allocator callback that we'll ignore by passing 184 | `nullptr` to it. All of the other Vulkan resources that we'll create in the 185 | following chapters should be cleaned up before the instance is destroyed. 186 | 187 | Before continuing with the more complex steps after instance creation, it's time 188 | to evaluate our debugging options by checking out [validation layers](!en/Drawing_a_triangle/Setup/Validation_layers). 189 | 190 | [C++ code](/code/01_instance_creation.cpp) 191 | -------------------------------------------------------------------------------- /en/03_Drawing_a_triangle/00_Setup/04_Logical_device_and_queues.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | After selecting a physical device to use we need to set up a *logical device* to 4 | interface with it. The logical device creation process is similar to the 5 | instance creation process and describes the features we want to use. We also 6 | need to specify which queues to create now that we've queried which queue 7 | families are available. You can even create multiple logical devices from the 8 | same physical device if you have varying requirements. 9 | 10 | Start by adding a new class member to store the logical device handle in. 11 | 12 | ```c++ 13 | VkDevice device; 14 | ``` 15 | 16 | Next, add a `createLogicalDevice` function that is called from `initVulkan`. 17 | 18 | ```c++ 19 | void initVulkan() { 20 | createInstance(); 21 | setupDebugMessenger(); 22 | pickPhysicalDevice(); 23 | createLogicalDevice(); 24 | } 25 | 26 | void createLogicalDevice() { 27 | 28 | } 29 | ``` 30 | 31 | ## Specifying the queues to be created 32 | 33 | The creation of a logical device involves specifying a bunch of details in 34 | structs again, of which the first one will be `VkDeviceQueueCreateInfo`. This 35 | structure describes the number of queues we want for a single queue family. 36 | Right now we're only interested in a queue with graphics capabilities. 37 | 38 | ```c++ 39 | QueueFamilyIndices indices = findQueueFamilies(physicalDevice); 40 | 41 | VkDeviceQueueCreateInfo queueCreateInfo{}; 42 | queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 43 | queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value(); 44 | queueCreateInfo.queueCount = 1; 45 | ``` 46 | 47 | The currently available drivers will only allow you to create a small number of 48 | queues for each queue family and you don't really need more than one. That's 49 | because you can create all of the command buffers on multiple threads and then 50 | submit them all at once on the main thread with a single low-overhead call. 51 | 52 | Vulkan lets you assign priorities to queues to influence the scheduling of 53 | command buffer execution using floating point numbers between `0.0` and `1.0`. 54 | This is required even if there is only a single queue: 55 | 56 | ```c++ 57 | float queuePriority = 1.0f; 58 | queueCreateInfo.pQueuePriorities = &queuePriority; 59 | ``` 60 | 61 | ## Specifying used device features 62 | 63 | The next information to specify is the set of device features that we'll be 64 | using. These are the features that we queried support for with 65 | `vkGetPhysicalDeviceFeatures` in the previous chapter, like geometry shaders. 66 | Right now we don't need anything special, so we can simply define it and leave 67 | everything to `VK_FALSE`. We'll come back to this structure once we're about to 68 | start doing more interesting things with Vulkan. 69 | 70 | ```c++ 71 | VkPhysicalDeviceFeatures deviceFeatures{}; 72 | ``` 73 | 74 | ## Creating the logical device 75 | 76 | With the previous two structures in place, we can start filling in the main 77 | `VkDeviceCreateInfo` structure. 78 | 79 | ```c++ 80 | VkDeviceCreateInfo createInfo{}; 81 | createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 82 | ``` 83 | 84 | First add pointers to the queue creation info and device features structs: 85 | 86 | ```c++ 87 | createInfo.pQueueCreateInfos = &queueCreateInfo; 88 | createInfo.queueCreateInfoCount = 1; 89 | 90 | createInfo.pEnabledFeatures = &deviceFeatures; 91 | ``` 92 | 93 | The remainder of the information bears a resemblance to the 94 | `VkInstanceCreateInfo` struct and requires you to specify extensions and 95 | validation layers. The difference is that these are device specific this time. 96 | 97 | An example of a device specific extension is `VK_KHR_swapchain`, which allows 98 | you to present rendered images from that device to windows. It is possible that 99 | there are Vulkan devices in the system that lack this ability, for example 100 | because they only support compute operations. We will come back to this 101 | extension in the swap chain chapter. 102 | 103 | Previous implementations of Vulkan made a distinction between instance and device specific validation layers, but this is [no longer the case](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#extendingvulkan-layers-devicelayerdeprecation). That means that the `enabledLayerCount` and `ppEnabledLayerNames` fields of `VkDeviceCreateInfo` are ignored by up-to-date implementations. However, it is still a good idea to set them anyway to be compatible with older implementations: 104 | 105 | ```c++ 106 | createInfo.enabledExtensionCount = 0; 107 | 108 | if (enableValidationLayers) { 109 | createInfo.enabledLayerCount = static_cast(validationLayers.size()); 110 | createInfo.ppEnabledLayerNames = validationLayers.data(); 111 | } else { 112 | createInfo.enabledLayerCount = 0; 113 | } 114 | ``` 115 | 116 | We won't need any device specific extensions for now. 117 | 118 | That's it, we're now ready to instantiate the logical device with a call to the 119 | appropriately named `vkCreateDevice` function. 120 | 121 | ```c++ 122 | if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { 123 | throw std::runtime_error("failed to create logical device!"); 124 | } 125 | ``` 126 | 127 | The parameters are the physical device to interface with, the queue and usage 128 | info we just specified, the optional allocation callbacks pointer and a pointer 129 | to a variable to store the logical device handle in. Similarly to the instance 130 | creation function, this call can return errors based on enabling non-existent 131 | extensions or specifying the desired usage of unsupported features. 132 | 133 | The device should be destroyed in `cleanup` with the `vkDestroyDevice` function: 134 | 135 | ```c++ 136 | void cleanup() { 137 | vkDestroyDevice(device, nullptr); 138 | ... 139 | } 140 | ``` 141 | 142 | Logical devices don't interact directly with instances, which is why it's not 143 | included as a parameter. 144 | 145 | ## Retrieving queue handles 146 | 147 | The queues are automatically created along with the logical device, but we don't 148 | have a handle to interface with them yet. First add a class member to store a 149 | handle to the graphics queue: 150 | 151 | ```c++ 152 | VkQueue graphicsQueue; 153 | ``` 154 | 155 | Device queues are implicitly cleaned up when the device is destroyed, so we 156 | don't need to do anything in `cleanup`. 157 | 158 | We can use the `vkGetDeviceQueue` function to retrieve queue handles for each 159 | queue family. The parameters are the logical device, queue family, queue index 160 | and a pointer to the variable to store the queue handle in. Because we're only 161 | creating a single queue from this family, we'll simply use index `0`. 162 | 163 | ```c++ 164 | vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue); 165 | ``` 166 | 167 | With the logical device and queue handles we can now actually start using the 168 | graphics card to do things! In the next few chapters we'll set up the resources 169 | to present results to the window system. 170 | 171 | [C++ code](/code/04_logical_device.cpp) 172 | -------------------------------------------------------------------------------- /en/03_Drawing_a_triangle/01_Presentation/02_Image_views.md: -------------------------------------------------------------------------------- 1 | To use any `VkImage`, including those in the swap chain, in the render pipeline 2 | we have to create a `VkImageView` object. An image view is quite literally a 3 | view into an image. It describes how to access the image and which part of the 4 | image to access, for example if it should be treated as a 2D texture depth 5 | texture without any mipmapping levels. 6 | 7 | In this chapter we'll write a `createImageViews` function that creates a basic 8 | image view for every image in the swap chain so that we can use them as color 9 | targets later on. 10 | 11 | First add a class member to store the image views in: 12 | 13 | ```c++ 14 | std::vector swapChainImageViews; 15 | ``` 16 | 17 | Create the `createImageViews` function and call it right after swap chain 18 | creation. 19 | 20 | ```c++ 21 | void initVulkan() { 22 | createInstance(); 23 | setupDebugMessenger(); 24 | createSurface(); 25 | pickPhysicalDevice(); 26 | createLogicalDevice(); 27 | createSwapChain(); 28 | createImageViews(); 29 | } 30 | 31 | void createImageViews() { 32 | 33 | } 34 | ``` 35 | 36 | The first thing we need to do is resize the list to fit all of the image views 37 | we'll be creating: 38 | 39 | ```c++ 40 | void createImageViews() { 41 | swapChainImageViews.resize(swapChainImages.size()); 42 | 43 | } 44 | ``` 45 | 46 | Next, set up the loop that iterates over all of the swap chain images. 47 | 48 | ```c++ 49 | for (size_t i = 0; i < swapChainImages.size(); i++) { 50 | 51 | } 52 | ``` 53 | 54 | The parameters for image view creation are specified in a 55 | `VkImageViewCreateInfo` structure. The first few parameters are straightforward. 56 | 57 | ```c++ 58 | VkImageViewCreateInfo createInfo{}; 59 | createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 60 | createInfo.image = swapChainImages[i]; 61 | ``` 62 | 63 | The `viewType` and `format` fields specify how the image data should be 64 | interpreted. The `viewType` parameter allows you to treat images as 1D textures, 65 | 2D textures, 3D textures and cube maps. 66 | 67 | ```c++ 68 | createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; 69 | createInfo.format = swapChainImageFormat; 70 | ``` 71 | 72 | The `components` field allows you to swizzle the color channels around. For 73 | example, you can map all of the channels to the red channel for a monochrome 74 | texture. You can also map constant values of `0` and `1` to a channel. In our 75 | case we'll stick to the default mapping. 76 | 77 | ```c++ 78 | createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; 79 | createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; 80 | createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; 81 | createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; 82 | ``` 83 | 84 | The `subresourceRange` field describes what the image's purpose is and which 85 | part of the image should be accessed. Our images will be used as color targets 86 | without any mipmapping levels or multiple layers. 87 | 88 | ```c++ 89 | createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 90 | createInfo.subresourceRange.baseMipLevel = 0; 91 | createInfo.subresourceRange.levelCount = 1; 92 | createInfo.subresourceRange.baseArrayLayer = 0; 93 | createInfo.subresourceRange.layerCount = 1; 94 | ``` 95 | 96 | If you were working on a stereographic 3D application, then you would create a 97 | swap chain with multiple layers. You could then create multiple image views for 98 | each image representing the views for the left and right eyes by accessing 99 | different layers. 100 | 101 | Creating the image view is now a matter of calling `vkCreateImageView`: 102 | 103 | ```c++ 104 | if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) { 105 | throw std::runtime_error("failed to create image views!"); 106 | } 107 | ``` 108 | 109 | Unlike images, the image views were explicitly created by us, so we need to add 110 | a similar loop to destroy them again at the end of the program: 111 | 112 | ```c++ 113 | void cleanup() { 114 | for (auto imageView : swapChainImageViews) { 115 | vkDestroyImageView(device, imageView, nullptr); 116 | } 117 | 118 | ... 119 | } 120 | ``` 121 | 122 | An image view is sufficient to start using an image as a texture, but it's not 123 | quite ready to be used as a render target just yet. That requires one more step 124 | of indirection, known as a framebuffer. But first we'll have to set up the 125 | graphics pipeline. 126 | 127 | [C++ code](/code/07_image_views.cpp) 128 | -------------------------------------------------------------------------------- /en/03_Drawing_a_triangle/02_Graphics_pipeline_basics/00_Introduction.md: -------------------------------------------------------------------------------- 1 | Over the course of the next few chapters we'll be setting up a graphics pipeline 2 | that is configured to draw our first triangle. The graphics pipeline is the 3 | sequence of operations that take the vertices and textures of your meshes all 4 | the way to the pixels in the render targets. A simplified overview is displayed 5 | below: 6 | 7 | ![](/images/vulkan_simplified_pipeline.svg) 8 | 9 | The *input assembler* collects the raw vertex data from the buffers you specify 10 | and may also use an index buffer to repeat certain elements without having to 11 | duplicate the vertex data itself. 12 | 13 | The *vertex shader* is run for every vertex and generally applies 14 | transformations to turn vertex positions from model space to screen space. It 15 | also passes per-vertex data down the pipeline. 16 | 17 | The *tessellation shaders* allow you to subdivide geometry based on certain 18 | rules to increase the mesh quality. This is often used to make surfaces like 19 | brick walls and staircases look less flat when they are nearby. 20 | 21 | The *geometry shader* is run on every primitive (triangle, line, point) and can 22 | discard it or output more primitives than came in. This is similar to the 23 | tessellation shader, but much more flexible. However, it is not used much in 24 | today's applications because the performance is not that good on most graphics 25 | cards except for Intel's integrated GPUs. 26 | 27 | The *rasterization* stage discretizes the primitives into *fragments*. These are 28 | the pixel elements that they fill on the framebuffer. Any fragments that fall 29 | outside the screen are discarded and the attributes outputted by the vertex 30 | shader are interpolated across the fragments, as shown in the figure. Usually 31 | the fragments that are behind other primitive fragments are also discarded here 32 | because of depth testing. 33 | 34 | The *fragment shader* is invoked for every fragment that survives and determines 35 | which framebuffer(s) the fragments are written to and with which color and depth 36 | values. It can do this using the interpolated data from the vertex shader, which 37 | can include things like texture coordinates and normals for lighting. 38 | 39 | The *color blending* stage applies operations to mix different fragments that 40 | map to the same pixel in the framebuffer. Fragments can simply overwrite each 41 | other, add up or be mixed based upon transparency. 42 | 43 | Stages with a green color are known as *fixed-function* stages. These stages 44 | allow you to tweak their operations using parameters, but the way they work is 45 | predefined. 46 | 47 | Stages with an orange color on the other hand are `programmable`, which means 48 | that you can upload your own code to the graphics card to apply exactly the 49 | operations you want. This allows you to use fragment shaders, for example, to 50 | implement anything from texturing and lighting to ray tracers. These programs 51 | run on many GPU cores simultaneously to process many objects, like vertices and 52 | fragments in parallel. 53 | 54 | If you've used older APIs like OpenGL and Direct3D before, then you'll be used 55 | to being able to change any pipeline settings at will with calls like 56 | `glBlendFunc` and `OMSetBlendState`. The graphics pipeline in Vulkan is almost 57 | completely immutable, so you must recreate the pipeline from scratch if you want 58 | to change shaders, bind different framebuffers or change the blend function. The 59 | disadvantage is that you'll have to create a number of pipelines that represent 60 | all of the different combinations of states you want to use in your rendering 61 | operations. However, because all of the operations you'll be doing in the 62 | pipeline are known in advance, the driver can optimize for it much better. 63 | 64 | Some of the programmable stages are optional based on what you intend to do. For 65 | example, the tessellation and geometry stages can be disabled if you are just 66 | drawing simple geometry. If you are only interested in depth values then you can 67 | disable the fragment shader stage, which is useful for [shadow map](https://en.wikipedia.org/wiki/Shadow_mapping) 68 | generation. 69 | 70 | In the next chapter we'll first create the two programmable stages required to 71 | put a triangle onto the screen: the vertex shader and fragment shader. The 72 | fixed-function configuration like blending mode, viewport, rasterization will be 73 | set up in the chapter after that. The final part of setting up the graphics 74 | pipeline in Vulkan involves the specification of input and output framebuffers. 75 | 76 | Create a `createGraphicsPipeline` function that is called right after 77 | `createImageViews` in `initVulkan`. We'll work on this function throughout the 78 | following chapters. 79 | 80 | ```c++ 81 | void initVulkan() { 82 | createInstance(); 83 | setupDebugMessenger(); 84 | createSurface(); 85 | pickPhysicalDevice(); 86 | createLogicalDevice(); 87 | createSwapChain(); 88 | createImageViews(); 89 | createGraphicsPipeline(); 90 | } 91 | 92 | ... 93 | 94 | void createGraphicsPipeline() { 95 | 96 | } 97 | ``` 98 | 99 | [C++ code](/code/08_graphics_pipeline.cpp) 100 | -------------------------------------------------------------------------------- /en/03_Drawing_a_triangle/02_Graphics_pipeline_basics/04_Conclusion.md: -------------------------------------------------------------------------------- 1 | We can now combine all of the structures and objects from the previous chapters 2 | to create the graphics pipeline! Here's the types of objects we have now, as a 3 | quick recap: 4 | 5 | * Shader stages: the shader modules that define the functionality of the 6 | programmable stages of the graphics pipeline 7 | * Fixed-function state: all of the structures that define the fixed-function 8 | stages of the pipeline, like input assembly, rasterizer, viewport and color 9 | blending 10 | * Pipeline layout: the uniform and push values referenced by the shader that can 11 | be updated at draw time 12 | * Render pass: the attachments referenced by the pipeline stages and their usage 13 | 14 | All of these combined fully define the functionality of the graphics pipeline, 15 | so we can now begin filling in the `VkGraphicsPipelineCreateInfo` structure at 16 | the end of the `createGraphicsPipeline` function. But before the calls to 17 | `vkDestroyShaderModule` because these are still to be used during the creation. 18 | 19 | ```c++ 20 | VkGraphicsPipelineCreateInfo pipelineInfo{}; 21 | pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 22 | pipelineInfo.stageCount = 2; 23 | pipelineInfo.pStages = shaderStages; 24 | ``` 25 | 26 | We start by referencing the array of `VkPipelineShaderStageCreateInfo` structs. 27 | 28 | ```c++ 29 | pipelineInfo.pVertexInputState = &vertexInputInfo; 30 | pipelineInfo.pInputAssemblyState = &inputAssembly; 31 | pipelineInfo.pViewportState = &viewportState; 32 | pipelineInfo.pRasterizationState = &rasterizer; 33 | pipelineInfo.pMultisampleState = &multisampling; 34 | pipelineInfo.pDepthStencilState = nullptr; // Optional 35 | pipelineInfo.pColorBlendState = &colorBlending; 36 | pipelineInfo.pDynamicState = nullptr; // Optional 37 | ``` 38 | 39 | Then we reference all of the structures describing the fixed-function stage. 40 | 41 | ```c++ 42 | pipelineInfo.layout = pipelineLayout; 43 | ``` 44 | 45 | After that comes the pipeline layout, which is a Vulkan handle rather than a 46 | struct pointer. 47 | 48 | ```c++ 49 | pipelineInfo.renderPass = renderPass; 50 | pipelineInfo.subpass = 0; 51 | ``` 52 | 53 | And finally we have the reference to the render pass and the index of the sub 54 | pass where this graphics pipeline will be used. It is also possible to use other 55 | render passes with this pipeline instead of this specific instance, but they 56 | have to be *compatible* with `renderPass`. The requirements for compatibility 57 | are described [here](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#renderpass-compatibility), 58 | but we won't be using that feature in this tutorial. 59 | 60 | ```c++ 61 | pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optional 62 | pipelineInfo.basePipelineIndex = -1; // Optional 63 | ``` 64 | 65 | There are actually two more parameters: `basePipelineHandle` and 66 | `basePipelineIndex`. Vulkan allows you to create a new graphics pipeline by 67 | deriving from an existing pipeline. The idea of pipeline derivatives is that it 68 | is less expensive to set up pipelines when they have much functionality in 69 | common with an existing pipeline and switching between pipelines from the same 70 | parent can also be done quicker. You can either specify the handle of an 71 | existing pipeline with `basePipelineHandle` or reference another pipeline that 72 | is about to be created by index with `basePipelineIndex`. Right now there is 73 | only a single pipeline, so we'll simply specify a null handle and an invalid 74 | index. These values are only used if the `VK_PIPELINE_CREATE_DERIVATIVE_BIT` 75 | flag is also specified in the `flags` field of `VkGraphicsPipelineCreateInfo`. 76 | 77 | Now prepare for the final step by creating a class member to hold the 78 | `VkPipeline` object: 79 | 80 | ```c++ 81 | VkPipeline graphicsPipeline; 82 | ``` 83 | 84 | And finally create the graphics pipeline: 85 | 86 | ```c++ 87 | if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { 88 | throw std::runtime_error("failed to create graphics pipeline!"); 89 | } 90 | ``` 91 | 92 | The `vkCreateGraphicsPipelines` function actually has more parameters than the 93 | usual object creation functions in Vulkan. It is designed to take multiple 94 | `VkGraphicsPipelineCreateInfo` objects and create multiple `VkPipeline` objects 95 | in a single call. 96 | 97 | The second parameter, for which we've passed the `VK_NULL_HANDLE` argument, 98 | references an optional `VkPipelineCache` object. A pipeline cache can be used to 99 | store and reuse data relevant to pipeline creation across multiple calls to 100 | `vkCreateGraphicsPipelines` and even across program executions if the cache is 101 | stored to a file. This makes it possible to significantly speed up pipeline 102 | creation at a later time. We'll get into this in the pipeline cache chapter. 103 | 104 | The graphics pipeline is required for all common drawing operations, so it 105 | should also only be destroyed at the end of the program: 106 | 107 | ```c++ 108 | void cleanup() { 109 | vkDestroyPipeline(device, graphicsPipeline, nullptr); 110 | vkDestroyPipelineLayout(device, pipelineLayout, nullptr); 111 | ... 112 | } 113 | ``` 114 | 115 | Now run your program to confirm that all this hard work has resulted in a 116 | successful pipeline creation! We are already getting quite close to seeing 117 | something pop up on the screen. In the next couple of chapters we'll set up the 118 | actual framebuffers from the swap chain images and prepare the drawing commands. 119 | 120 | [C++ code](/code/12_graphics_pipeline_complete.cpp) / 121 | [Vertex shader](/code/09_shader_base.vert) / 122 | [Fragment shader](/code/09_shader_base.frag) 123 | -------------------------------------------------------------------------------- /en/03_Drawing_a_triangle/03_Drawing/00_Framebuffers.md: -------------------------------------------------------------------------------- 1 | We've talked a lot about framebuffers in the past few chapters and we've set up 2 | the render pass to expect a single framebuffer with the same format as the swap 3 | chain images, but we haven't actually created any yet. 4 | 5 | The attachments specified during render pass creation are bound by wrapping them 6 | into a `VkFramebuffer` object. A framebuffer object references all of the 7 | `VkImageView` objects that represent the attachments. In our case that will be 8 | only a single one: the color attachment. However, the image that we have to use 9 | for the attachment depends on which image the swap chain returns when we retrieve one 10 | for presentation. That means that we have to create a framebuffer for all of the 11 | images in the swap chain and use the one that corresponds to the retrieved image 12 | at drawing time. 13 | 14 | To that end, create another `std::vector` class member to hold the framebuffers: 15 | 16 | ```c++ 17 | std::vector swapChainFramebuffers; 18 | ``` 19 | 20 | We'll create the objects for this array in a new function `createFramebuffers` 21 | that is called from `initVulkan` right after creating the graphics pipeline: 22 | 23 | ```c++ 24 | void initVulkan() { 25 | createInstance(); 26 | setupDebugMessenger(); 27 | createSurface(); 28 | pickPhysicalDevice(); 29 | createLogicalDevice(); 30 | createSwapChain(); 31 | createImageViews(); 32 | createRenderPass(); 33 | createGraphicsPipeline(); 34 | createFramebuffers(); 35 | } 36 | 37 | ... 38 | 39 | void createFramebuffers() { 40 | 41 | } 42 | ``` 43 | 44 | Start by resizing the container to hold all of the framebuffers: 45 | 46 | ```c++ 47 | void createFramebuffers() { 48 | swapChainFramebuffers.resize(swapChainImageViews.size()); 49 | } 50 | ``` 51 | 52 | We'll then iterate through the image views and create framebuffers from them: 53 | 54 | ```c++ 55 | for (size_t i = 0; i < swapChainImageViews.size(); i++) { 56 | VkImageView attachments[] = { 57 | swapChainImageViews[i] 58 | }; 59 | 60 | VkFramebufferCreateInfo framebufferInfo{}; 61 | framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 62 | framebufferInfo.renderPass = renderPass; 63 | framebufferInfo.attachmentCount = 1; 64 | framebufferInfo.pAttachments = attachments; 65 | framebufferInfo.width = swapChainExtent.width; 66 | framebufferInfo.height = swapChainExtent.height; 67 | framebufferInfo.layers = 1; 68 | 69 | if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) { 70 | throw std::runtime_error("failed to create framebuffer!"); 71 | } 72 | } 73 | ``` 74 | 75 | As you can see, creation of framebuffers is quite straightforward. We first need 76 | to specify with which `renderPass` the framebuffer needs to be compatible. You 77 | can only use a framebuffer with the render passes that it is compatible with, 78 | which roughly means that they use the same number and type of attachments. 79 | 80 | The `attachmentCount` and `pAttachments` parameters specify the `VkImageView` 81 | objects that should be bound to the respective attachment descriptions in 82 | the render pass `pAttachment` array. 83 | 84 | The `width` and `height` parameters are self-explanatory and `layers` refers to 85 | the number of layers in image arrays. Our swap chain images are single images, 86 | so the number of layers is `1`. 87 | 88 | We should delete the framebuffers before the image views and render pass that 89 | they are based on, but only after we've finished rendering: 90 | 91 | ```c++ 92 | void cleanup() { 93 | for (auto framebuffer : swapChainFramebuffers) { 94 | vkDestroyFramebuffer(device, framebuffer, nullptr); 95 | } 96 | 97 | ... 98 | } 99 | ``` 100 | 101 | We've now reached the milestone where we have all of the objects that are 102 | required for rendering. In the next chapter we're going to write the first 103 | actual drawing commands. 104 | 105 | [C++ code](/code/13_framebuffers.cpp) / 106 | [Vertex shader](/code/09_shader_base.vert) / 107 | [Fragment shader](/code/09_shader_base.frag) 108 | -------------------------------------------------------------------------------- /en/04_Vertex_buffers/03_Index_buffer.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | The 3D meshes you'll be rendering in a real world application will often share 4 | vertices between multiple triangles. This already happens even with something 5 | simple like drawing a rectangle: 6 | 7 | ![](/images/vertex_vs_index.svg) 8 | 9 | Drawing a rectangle takes two triangles, which means that we need a vertex 10 | buffer with 6 vertices. The problem is that the data of two vertices needs to be 11 | duplicated resulting in 50% redundancy. It only gets worse with more complex 12 | meshes, where vertices are reused in an average number of 3 triangles. The 13 | solution to this problem is to use an *index buffer*. 14 | 15 | An index buffer is essentially an array of pointers into the vertex buffer. It 16 | allows you to reorder the vertex data, and reuse existing data for multiple 17 | vertices. The illustration above demonstrates what the index buffer would look 18 | like for the rectangle if we have a vertex buffer containing each of the four 19 | unique vertices. The first three indices define the upper-right triangle and the 20 | last three indices define the vertices for the bottom-left triangle. 21 | 22 | ## Index buffer creation 23 | 24 | In this chapter we're going to modify the vertex data and add index data to 25 | draw a rectangle like the one in the illustration. Modify the vertex data to 26 | represent the four corners: 27 | 28 | ```c++ 29 | const std::vector vertices = { 30 | {{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}}, 31 | {{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}}, 32 | {{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}}, 33 | {{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}} 34 | }; 35 | ``` 36 | 37 | The top-left corner is red, top-right is green, bottom-right is blue and the 38 | bottom-left is white. We'll add a new array `indices` to represent the contents 39 | of the index buffer. It should match the indices in the illustration to draw the 40 | upper-right triangle and bottom-left triangle. 41 | 42 | ```c++ 43 | const std::vector indices = { 44 | 0, 1, 2, 2, 3, 0 45 | }; 46 | ``` 47 | 48 | It is possible to use either `uint16_t` or `uint32_t` for your index buffer 49 | depending on the number of entries in `vertices`. We can stick to `uint16_t` for 50 | now because we're using less than 65535 unique vertices. 51 | 52 | Just like the vertex data, the indices need to be uploaded into a `VkBuffer` for 53 | the GPU to be able to access them. Define two new class members to hold the 54 | resources for the index buffer: 55 | 56 | ```c++ 57 | VkBuffer vertexBuffer; 58 | VkDeviceMemory vertexBufferMemory; 59 | VkBuffer indexBuffer; 60 | VkDeviceMemory indexBufferMemory; 61 | ``` 62 | 63 | The `createIndexBuffer` function that we'll add now is almost identical to 64 | `createVertexBuffer`: 65 | 66 | ```c++ 67 | void initVulkan() { 68 | ... 69 | createVertexBuffer(); 70 | createIndexBuffer(); 71 | ... 72 | } 73 | 74 | void createIndexBuffer() { 75 | VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size(); 76 | 77 | VkBuffer stagingBuffer; 78 | VkDeviceMemory stagingBufferMemory; 79 | createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory); 80 | 81 | void* data; 82 | vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data); 83 | memcpy(data, indices.data(), (size_t) bufferSize); 84 | vkUnmapMemory(device, stagingBufferMemory); 85 | 86 | createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory); 87 | 88 | copyBuffer(stagingBuffer, indexBuffer, bufferSize); 89 | 90 | vkDestroyBuffer(device, stagingBuffer, nullptr); 91 | vkFreeMemory(device, stagingBufferMemory, nullptr); 92 | } 93 | ``` 94 | 95 | There are only two notable differences. The `bufferSize` is now equal to the 96 | number of indices times the size of the index type, either `uint16_t` or 97 | `uint32_t`. The usage of the `indexBuffer` should be 98 | `VK_BUFFER_USAGE_INDEX_BUFFER_BIT` instead of 99 | `VK_BUFFER_USAGE_VERTEX_BUFFER_BIT`, which makes sense. Other than that, the 100 | process is exactly the same. We create a staging buffer to copy the contents of 101 | `indices` to and then copy it to the final device local index buffer. 102 | 103 | The index buffer should be cleaned up at the end of the program, just like the 104 | vertex buffer: 105 | 106 | ```c++ 107 | void cleanup() { 108 | cleanupSwapChain(); 109 | 110 | vkDestroyBuffer(device, indexBuffer, nullptr); 111 | vkFreeMemory(device, indexBufferMemory, nullptr); 112 | 113 | vkDestroyBuffer(device, vertexBuffer, nullptr); 114 | vkFreeMemory(device, vertexBufferMemory, nullptr); 115 | 116 | ... 117 | } 118 | ``` 119 | 120 | ## Using an index buffer 121 | 122 | Using an index buffer for drawing involves two changes to 123 | `createCommandBuffers`. We first need to bind the index buffer, just like we did 124 | for the vertex buffer. The difference is that you can only have a single index 125 | buffer. It's unfortunately not possible to use different indices for each vertex 126 | attribute, so we do still have to completely duplicate vertex data even if just 127 | one attribute varies. 128 | 129 | ```c++ 130 | vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets); 131 | 132 | vkCmdBindIndexBuffer(commandBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT16); 133 | ``` 134 | 135 | An index buffer is bound with `vkCmdBindIndexBuffer` which has the index buffer, 136 | a byte offset into it, and the type of index data as parameters. As mentioned 137 | before, the possible types are `VK_INDEX_TYPE_UINT16` and 138 | `VK_INDEX_TYPE_UINT32`. 139 | 140 | Just binding an index buffer doesn't change anything yet, we also need to change 141 | the drawing command to tell Vulkan to use the index buffer. Remove the 142 | `vkCmdDraw` line and replace it with `vkCmdDrawIndexed`: 143 | 144 | ```c++ 145 | vkCmdDrawIndexed(commandBuffers[i], static_cast(indices.size()), 1, 0, 0, 0); 146 | ``` 147 | 148 | A call to this function is very similar to `vkCmdDraw`. The first two parameters 149 | specify the number of indices and the number of instances. We're not using 150 | instancing, so just specify `1` instance. The number of indices represents the 151 | number of vertices that will be passed to the vertex buffer. The next parameter 152 | specifies an offset into the index buffer, using a value of `1` would cause the 153 | graphics card to start reading at the second index. The second to last parameter 154 | specifies an offset to add to the indices in the index buffer. The final 155 | parameter specifies an offset for instancing, which we're not using. 156 | 157 | Now run your program and you should see the following: 158 | 159 | ![](/images/indexed_rectangle.png) 160 | 161 | You now know how to save memory by reusing vertices with index buffers. This 162 | will become especially important in a future chapter where we're going to load 163 | complex 3D models. 164 | 165 | The previous chapter already mentioned that you should allocate multiple 166 | resources like buffers from a single memory allocation, but in fact you should 167 | go a step further. [Driver developers recommend](https://developer.nvidia.com/vulkan-memory-management) 168 | that you also store multiple buffers, like the vertex and index buffer, into a 169 | single `VkBuffer` and use offsets in commands like `vkCmdBindVertexBuffers`. The 170 | advantage is that your data is more cache friendly in that case, because it's 171 | closer together. It is even possible to reuse the same chunk of memory for 172 | multiple resources if they are not used during the same render operations, 173 | provided that their data is refreshed, of course. This is known as *aliasing* 174 | and some Vulkan functions have explicit flags to specify that you want to do 175 | this. 176 | 177 | [C++ code](/code/20_index_buffer.cpp) / 178 | [Vertex shader](/code/17_shader_vertexbuffer.vert) / 179 | [Fragment shader](/code/17_shader_vertexbuffer.frag) 180 | -------------------------------------------------------------------------------- /en/90_FAQ.md: -------------------------------------------------------------------------------- 1 | This page lists solutions to common problems that you may encounter while 2 | developing Vulkan applications. 3 | 4 | * **I get an access violation error in the core validation layer**: Make sure 5 | that MSI Afterburner / RivaTuner Statistics Server is not running, because it 6 | has some compatibility problems with Vulkan. 7 | 8 | * **I don't see any messages from the validation layers / Validation layers are not available**: First make sure that 9 | the validation layers get a chance to print errors by keeping the terminal open 10 | after your program exits. You can do this from Visual Studio by running your 11 | program with Ctrl-F5 instead of F5, and on Linux by executing your program from 12 | a terminal window. If there are still no messages and you are sure that 13 | validation layers are turned on, then you should ensure that your Vulkan SDK is 14 | correctly installed by following the "Verify the Installation" instructions [on this page](https://vulkan.lunarg.com/doc/view/1.2.135.0/windows/getting_started.html). Also ensure that your SDK version is at least 1.1.106.0 to support the `VK_LAYER_KHRONOS_validation` layer. 15 | 16 | * **vkCreateSwapchainKHR triggers an error in SteamOverlayVulkanLayer64.dll**: 17 | This appears to be a compatibility problem in the Steam client beta. There are a 18 | few possible workarounds: 19 | * Opt out of the Steam beta program. 20 | * Set the `DISABLE_VK_LAYER_VALVE_steam_overlay_1` environment variable to `1` 21 | * Delete the Steam overlay Vulkan layer entry in the registry under `HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\ImplicitLayers` 22 | 23 | Example: 24 | 25 | ![](/images/steam_layers_env.png) 26 | -------------------------------------------------------------------------------- /en/95_Privacy_policy.md: -------------------------------------------------------------------------------- 1 | ## General 2 | 3 | This privacy policy applies to the information that is collected when you use vulkan-tutorial.com or any of its subdomains. It describes how the owner of this website, Alexander Overvoorde, collects, uses and shares information about you. 4 | 5 | ## Analytics 6 | 7 | This website collects analytics about visitors using a self-hosted instance of Matomo ([https://matomo.org/](https://matomo.org/)), formerly known as Piwik. It records which pages you visit, what type of device and browser you use, how long you view a given page and where you came from. This information is anonymized by only recording the first two bytes of your IP address (e.g. `123.123.xxx.xxx`). These anonymized logs are stored for an indefinite amount of time. 8 | 9 | These analytics are used for the purpose of tracking how content on the website is consumed, how many people visit the website in general, and which other websites link here. This makes it easier to engage with the community and determine which areas of the website should be improved, for example if extra time should be spent on facilitating mobile reading. 10 | 11 | This data is not shared with third parties. 12 | 13 | ## Advertisement 14 | 15 | This website uses a third-party advertisement server that may use cookies to track activities on the website to measure engagement with advertisements. 16 | 17 | ## Comments 18 | 19 | Each chapter includes a comment section at the end that is provided by the third-party Disqus service. This service collects identity data to facilitate the reading and submission of comments, and aggregate usage information to improve their service. 20 | 21 | The full privacy policy of this third-party service can be found at [https://help.disqus.com/terms-and-policies/disqus-privacy-policy](https://help.disqus.com/terms-and-policies/disqus-privacy-policy). -------------------------------------------------------------------------------- /fr/03_Dessiner_un_triangle/00_Mise_en_place/01_Instance.md: -------------------------------------------------------------------------------- 1 | ## Création d'une instance 2 | 3 | La première chose à faire avec Vulkan est son initialisation au travers d'une *instance*. Cette instance relie 4 | l'application à l'API. Pour la créer vous devrez donner quelques informations au driver. 5 | 6 | Créez une fonction `createInstance` et appelez-la depuis la fonction `initVulkan` : 7 | 8 | ```c++ 9 | void initVulkan() { 10 | createInstance(); 11 | } 12 | ``` 13 | 14 | Ajoutez ensuite un membre donnée représentant cette instance : 15 | 16 | ```c++ 17 | private: 18 | VkInstance instance; 19 | ``` 20 | 21 | Pour créer l'instance, nous allons d'abord remplir une première structure avec des informations sur notre application. 22 | Ces données sont optionnelles, mais elles peuvent fournir des informations utiles au driver pour optimiser ou 23 | dignostiquer les erreurs lors de l'exécution, par exemple en reconnaissant le nom d'un moteur graphique. Cette structure 24 | s'appelle `VkApplicationInfo` : 25 | 26 | ```c++ 27 | void createInstance() { 28 | VkApplicationInfo appInfo{}; 29 | appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 30 | appInfo.pApplicationName = "Hello Triangle"; 31 | appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); 32 | appInfo.pEngineName = "No Engine"; 33 | appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); 34 | appInfo.apiVersion = VK_API_VERSION_1_0; 35 | } 36 | ``` 37 | 38 | Comme mentionné précédemment, la plupart des structures Vulkan vous demandent d'expliciter leur propre type dans le 39 | membre `sType`. Cela permet d'indiquer la version exacte de la structure que nous voulons utiliser : il y aura dans 40 | le futur des extensions à celles-ci. Pour simplifier leur implémentation, les utiliser ne nécessitera que de changer 41 | le type `VK_STRUCTURE_TYPE_XXX` en `VK_STRUCTURE_TYPE_XXX_2` (ou plus de 2) et de fournir une structure complémentaire 42 | à l'aide du pointeur `pNext`. Nous n'utiliserons aucune extension, et donnerons donc toujours `nullptr` à `pNext`. 43 | 44 | Avec Vulkan, nous rencontrerons souvent (TRÈS souvent) des structures à remplir pour passer les informations à Vulkan. 45 | Nous allons maintenant remplir le reste de la structure permettant la création de l'instance. Celle-ci n'est pas 46 | optionnelle. Elle permet d'informer le driver des extensions et des validation layers que nous utiliserons, et ceci 47 | de manière globale. Globale siginifie ici que ces données ne serons pas spécifiques à un périphérique. Nous verrons 48 | la signification de cela dans les chapitres suivants. 49 | 50 | ```c++ 51 | VkInstanceCreateInfo createInfo{}; 52 | createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 53 | createInfo.pApplicationInfo = &appInfo; 54 | ``` 55 | 56 | Les deux premiers paramètres sont simples. Les deux suivants spécifient les extensions dont nous aurons besoin. Comme 57 | nous l'avons vu dans l'introduction, Vulkan ne connaît pas la plateforme sur laquelle il travaille, et nous aurons donc 58 | besoin d'extensions pour utiliser des interfaces avec le gestionnaire de fenêtre. GLFW possède une fonction très 59 | pratique qui nous donne la liste des extensions dont nous aurons besoin pour afficher nos résultats. Remplissez donc la 60 | structure de ces données : 61 | 62 | ```c++ 63 | uint32_t glfwExtensionCount = 0; 64 | const char** glfwExtensions; 65 | 66 | glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); 67 | 68 | createInfo.enabledExtensionCount = glfwExtensionCount; 69 | createInfo.ppEnabledExtensionNames = glfwExtensions; 70 | ``` 71 | 72 | Les deux derniers membres de la structure indiquent les validations layers à activer. Nous verrons cela dans le prochain 73 | chapitre, laissez ces champs vides pour le moment : 74 | 75 | ```c++ 76 | createInfo.enabledLayerCount = 0; 77 | ``` 78 | 79 | Nous avons maintenant indiqué tout ce dont Vulkan a besoin pour créer notre première instance. Nous pouvons enfin 80 | appeler `vkCreateInstance` : 81 | 82 | ```c++ 83 | VkResult result = vkCreateInstance(&createInfo, nullptr, &instance); 84 | ``` 85 | 86 | Comme vous le reverrez, l'appel à une fonction pour la création d'un objet Vulkan a le prototype suivant : 87 | 88 | * Pointeur sur une structure contenant l'information pour la création 89 | * Pointeur sur une fonction d'allocation que nous laisserons toujours `nullptr` 90 | * Pointeur sur une variable stockant une référence au nouvel objet 91 | 92 | Si tout s'est bien passé, la référence à l'instance devrait être contenue dans le membre `VkInstance`. Quasiment toutes 93 | les fonctions Vulkan retournent une valeur de type VkResult, pouvant être soit `VK_SUCCESS` soit un code d'erreur. Afin 94 | de vérifier si la création de l'instance s'est bien déroulée nous pouvons placer l'appel dans un `if` : 95 | 96 | ```c++ 97 | if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { 98 | throw std::runtime_error("Echec de la création de l'instance!"); 99 | } 100 | ``` 101 | 102 | Lancez votre programme pour voir si l'instance s'est créée correctement. 103 | 104 | ## Vérification du support des extensions 105 | 106 | Si vous regardez la documentation pour `vkCreateInstance` vous pourrez voir que l'un des messages d'erreur possible est 107 | `VK_ERROR_EXTENSION_NOT_PRESENT`. Nous pourrions juste interrompre le programme et afficher une erreur si une extension 108 | manque. Ce serait logique pour des fonctionnalités cruciales comme l'affichage, mais pas dans le cas d'extensions 109 | optionnelles. 110 | 111 | La fonction `vkEnumerateInstanceExtensionProperties` permet de récupérer la totalité des extensions supportées par le 112 | système avant la création de l'instance. Elle demande un pointeur vers une variable stockant le nombre d'extensions 113 | supportées et un tableau où stocker des informations sur chacune des extensions. Elle possède également un paramètre 114 | optionnel permettant de filtrer les résultats pour une validation layer spécifique. Nous l'ignorerons pour le moment. 115 | 116 | Pour allouer un tableau contenant les détails des extensions nous devons déjà connaître le nombre de ces extensions. 117 | Vous pouvez ne demander que cette information en laissant le premier paramètre `nullptr` : 118 | 119 | ```c++ 120 | uint32_t extensionCount = 0; 121 | vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); 122 | ``` 123 | 124 | Nous utiliserons souvent cette méthode. Allouez maintenant un tableau pour stocker les détails des extensions (incluez 125 | ) : 126 | 127 | ```c++ 128 | std::vector extensions(extensionCount); 129 | ``` 130 | 131 | Nous pouvons désormais accéder aux détails des extensions : 132 | 133 | ```c++ 134 | vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); 135 | ``` 136 | 137 | Chacune des structure `VkExtensionProperties` contient le nom et la version maximale supportée de l'extension. Nous 138 | pouvons les afficher à l'aide d'une boucle `for` toute simple (`\t` représente une tabulation) : 139 | 140 | ```c++ 141 | std::cout << "Extensions disponibles :\n"; 142 | 143 | for (const auto& extension : extensions) { 144 | std::cout << '\t' << extension.extensionName << '\n'; 145 | } 146 | ``` 147 | 148 | Vous pouvez ajouter ce code dans la fonction `createInstance` si vous voulez indiquer des informations à propos du 149 | support Vulkan sur la machine. Petit challenge : programmez une fonction vérifiant si les extensions dont vous avez 150 | besoin (en particulier celles indiquées par GLFW) sont disponibles. 151 | 152 | ## Libération des ressources 153 | 154 | L'instance contenue dans `VkInstance` ne doit être détruite qu'à la fin du programme. Nous la détruirons dans la 155 | fonction `cleanup` grâce à la fonction `vkDestroyInstance` : 156 | 157 | ```c++ 158 | void cleanup() { 159 | vkDestroyInstance(instance, nullptr); 160 | 161 | glfwDestroyWindow(window); 162 | 163 | glfwTerminate(); 164 | } 165 | ``` 166 | 167 | Les paramètres de cette fonction sont évidents. Nous y retrouvons le paramètre pour un désallocateur que nous laissons 168 | `nullptr`. Toutes les ressources que nous allouerons à partir du prochain chapitre devront être libérées avant la 169 | libération de l'instance. 170 | 171 | Avant d'avancer dans les notions plus complexes, créons un moyen de déboger notre programme avec 172 | [les validations layers.](!fr/Dessiner_un_triangle/Mise_en_place/Validation_layers). 173 | 174 | [Code C++](/code/01_instance_creation.cpp) 175 | -------------------------------------------------------------------------------- /fr/03_Dessiner_un_triangle/00_Mise_en_place/04_Logical_device_et_queues.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | La sélection d'un physical device faite, nous devons générer un *logical device* pour servir d'interface. Le 4 | processus de sa création est similaire à celui de l'instance : nous devons décrire ce dont nous aurons besoin. Nous 5 | devons également spécifier les queues dont nous aurons besoin. Vous pouvez également créer plusieurs logical devices à 6 | partir d'un physical device si vous en avez besoin. 7 | 8 | Commencez par ajouter un nouveau membre donnée pour stocker la référence au logical device. 9 | 10 | ```c++ 11 | VkDevice device; 12 | ``` 13 | 14 | Ajoutez ensuite une fonction `createLogicalDevice` et appelez-la depuis `initVulkan`. 15 | 16 | ```c++ 17 | void initVulkan() { 18 | createInstance(); 19 | setupDebugMessenger(); 20 | pickPhysicalDevice(); 21 | createLogicalDevice(); 22 | } 23 | 24 | void createLogicalDevice() { 25 | 26 | } 27 | ``` 28 | 29 | ## Spécifier les queues à créer 30 | 31 | La création d'un logical device requiert encore que nous remplissions des informations dans des structures. La 32 | première de ces structures s'appelle `VkDeviceQueueCreateInfo`. Elle indique le nombre de queues que nous désirons pour 33 | chaque queue family. Pour le moment nous n'avons besoin que d'une queue originaire d'une unique queue family : la 34 | première avec un support pour les graphismes. 35 | 36 | ```c++ 37 | QueueFamilyIndices indices = findQueueFamilies(physicalDevice); 38 | 39 | VkDeviceQueueCreateInfo queueCreateInfo{}; 40 | queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 41 | queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value(); 42 | queueCreateInfo.queueCount = 1; 43 | ``` 44 | 45 | Actuellement les drivers ne vous permettent que de créer un petit nombre de queues pour chacune des familles, et vous 46 | n'avez en effet pas besoin de plus. Vous pouvez très bien créer les commandes (command buffers) depuis plusieurs 47 | threads et les soumettre à la queue d'un coup sur le thread principal, et ce sans perte de performance. 48 | 49 | Vulkan permet d'assigner des niveaux de priorité aux queues à l'aide de floats compris entre `0.0` et `1.0`. Vous 50 | pouvez ainsi influencer l'exécution des command buffers. Il est nécessaire d'indiquer une priorité même lorsqu'une 51 | seule queue est présente : 52 | 53 | ```c++ 54 | float queuePriority = 1.0f; 55 | queueCreateInfo.pQueuePriorities = &queuePriority; 56 | ``` 57 | 58 | ## Spécifier les fonctionnalités utilisées 59 | 60 | Les prochaines informations à fournir sont les fonctionnalités du physical device que nous souhaitons utiliser. Ce 61 | sont celles dont nous avons vérifié la présence avec `vkGetPhysicalDeviceFeatures` dans le chapitre précédent. Nous 62 | n'avons besoin de rien de spécial pour l'instant, nous pouvons donc nous contenter de créer la structure et de tout 63 | laisser à `VK_FALSE`, valeur par défaut. Nous reviendrons sur cette structure quand nous ferons des choses plus 64 | intéressantes avec Vulkan. 65 | 66 | ```c++ 67 | VkPhysicalDeviceFeatures deviceFeatures{}; 68 | ``` 69 | 70 | ## Créer le logical device 71 | 72 | Avec ces deux structure prêtes, nous pouvons enfin remplir la structure principale appelée `VkDeviceCreateInfo`. 73 | 74 | ```c++ 75 | VkDeviceCreateInfo createInfo{}; 76 | createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 77 | ``` 78 | 79 | Référencez d'abord les structures sur la création des queues et sur les fonctionnalités utilisées : 80 | 81 | ```c++ 82 | createInfo.pQueueCreateInfos = &queueCreateInfo; 83 | createInfo.queueCreateInfoCount = 1; 84 | 85 | createInfo.pEnabledFeatures = &deviceFeatures; 86 | ``` 87 | 88 | Le reste ressemble à la structure `VkInstanceCreateInfo`. Nous devons spécifier les extensions spécifiques de la 89 | carte graphique et les validation layers. 90 | 91 | Un exemple d'extension spécifique au GPU est `VK_KHR_swapchain`. Celle-ci vous permet de présenter à l'écran les images 92 | sur lesquels votre programme a effectué un rendu. Il est en effet possible que certains GPU ne possèdent pas cette 93 | capacité, par exemple parce qu'ils ne supportent que les compute shaders. Nous reviendrons sur cette extension 94 | dans le chapitre dédié à la swap chain. 95 | 96 | Comme dit dans le chapitre sur les validation layers, nous activerons les mêmes que celles que nous avons spécifiées 97 | lors de la création de l'instance. Nous n'avons pour l'instant besoin d'aucune validation layer en particulier. Notez 98 | que le standard ne fait plus la différence entre les extensions de l'instance et celles du device, au point que les 99 | paramètres `enabledLayerCount` et `ppEnabledLayerNames` seront probablement ignorés. Nous les remplissons quand même 100 | pour s'assurer de la bonne compatibilité avec les anciennes implémentations. 101 | 102 | ```c++ 103 | createInfo.enabledExtensionCount = 0; 104 | 105 | if (enableValidationLayers) { 106 | createInfo.enabledLayerCount = static_cast(validationLayers.size()); 107 | createInfo.ppEnabledLayerNames = validationLayers.data(); 108 | } else { 109 | createInfo.enabledLayerCount = 0; 110 | } 111 | ``` 112 | 113 | C'est bon, nous pouvons maintenant instancier le logical device en appelant la fonction `vkCreateDevice`. 114 | 115 | ```c++ 116 | if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { 117 | throw std::runtime_error("échec lors de la création d'un logical device!"); 118 | } 119 | ``` 120 | 121 | Les paramètres sont d'abord le physical device dont on souhaite extraire une interface, ensuite la structure contenant 122 | les informations, puis un pointeur optionnel pour l'allocation et enfin un pointeur sur la référence au logical 123 | device créé. Vérifions également si la création a été un succès ou non, comme lors de la création de l'instance. 124 | 125 | Le logical device doit être explicitement détruit dans la fonction `cleanup` avant le physical device : 126 | 127 | ```c++ 128 | void cleanup() { 129 | vkDestroyDevice(device, nullptr); 130 | ... 131 | } 132 | ``` 133 | 134 | Les logical devices n'interagissent pas directement avec l'instance mais seulement avec le physical device, c'est 135 | pourquoi il n'y a pas de paramètre pour l'instance. 136 | 137 | ## Récupérer des références aux queues 138 | 139 | Les queue families sont automatiquement crées avec le logical device. Cependant nous n'avons aucune interface avec 140 | elles. Ajoutez un membre donnée pour stocker une référence à la queue family supportant les graphismes : 141 | 142 | ```c++ 143 | VkQueue graphicsQueue; 144 | ``` 145 | 146 | Les queues sont implicitement détruites avec le logical device, nous n'avons donc pas à nous en charger dans `cleanup`. 147 | 148 | Nous pourrons ensuite récupérer des références à des queues avec la fonction `vkGetDeviceQueue`. Les paramètres en 149 | sont le logical device, la queue family, l'indice de la queue à récupérer et un pointeur où stocker la référence à la 150 | queue. Nous ne créons qu'une seule queue, nous écrirons donc `0` pour l'indice de la queue. 151 | 152 | ```c++ 153 | vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue); 154 | ``` 155 | 156 | Avec le logical device et les queues nous allons maintenant pouvoir faire travailler la carte graphique! Dans le 157 | prochain chapitre nous mettrons en place les ressources nécessaires à la présentation des images à l'écran. 158 | 159 | [Code C++](/code/04_logical_device.cpp) 160 | -------------------------------------------------------------------------------- /fr/03_Dessiner_un_triangle/01_Présentation/02_Image_views.md: -------------------------------------------------------------------------------- 1 | Quelque soit la `VkImage` que nous voulons utiliser, dont celles de la swap chain, nous devons en créer une 2 | `VkImageView` pour la manipuler. Cette image view correspond assez litéralement à une vue dans l'image. Elle décrit 3 | l'accès à l'image et les parties de l'image à accéder. Par exemple elle indique si elle doit être traitée comme une 4 | texture 2D pour la profondeur sans aucun niveau de mipmapping. 5 | 6 | Dans ce chapitre nous écrirons une fonction `createImageViews` pour créer une image view basique pour chacune des 7 | images dans la swap chain, pour que nous puissions les utiliser comme cibles de couleur. 8 | 9 | Ajoutez d'abord un membre donnée pour y stocker une image view : 10 | 11 | ```c++ 12 | std::vector swapChainImageViews; 13 | ``` 14 | 15 | Créez la fonction `createImageViews` et appelez-la juste après la création de la swap chain. 16 | 17 | ```c++ 18 | void initVulkan() { 19 | createInstance(); 20 | setupDebugMessenger(); 21 | createSurface(); 22 | pickPhysicalDevice(); 23 | createLogicalDevice(); 24 | createSwapChain(); 25 | createImageViews(); 26 | } 27 | 28 | void createImageViews() { 29 | 30 | } 31 | ``` 32 | 33 | Nous devons d'abord redimensionner la liste pour pouvoir y mettre toutes les image views que nous créerons : 34 | 35 | ```c++ 36 | void createImageViews() { 37 | swapChainImageViews.resize(swapChainImages.size()); 38 | 39 | } 40 | ``` 41 | 42 | Créez ensuite la boucle qui parcourra toutes les images de la swap chain. 43 | 44 | ```c++ 45 | for (size_t i = 0; i < swapChainImages.size(); i++) { 46 | 47 | } 48 | ``` 49 | 50 | Les paramètres pour la création d'image views se spécifient dans la structure `VkImageViewCreateInfo`. Les deux 51 | premiers paramètres sont assez simples : 52 | 53 | ```c++ 54 | VkImageViewCreateInfo createInfo{}; 55 | createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 56 | createInfo.image = swapChainImages[i]; 57 | ``` 58 | 59 | Les champs `viewType` et `format` indiquent la manière dont les images doivent être interprétées. Le paramètre 60 | `viewType` permet de traiter les images comme des textures 1D, 2D, 3D ou cube map. 61 | 62 | ```c++ 63 | createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; 64 | createInfo.format = swapChainImageFormat; 65 | ``` 66 | 67 | Le champ `components` vous permet d'altérer les canaux de couleur. Par exemple, vous pouvez envoyer tous les 68 | canaux au canal rouge pour obtenir une texture monochrome. Vous pouvez aussi donner les valeurs constantes `0` ou `1` 69 | à un canal. Dans notre cas nous garderons les paramètres par défaut. 70 | 71 | ```c++ 72 | createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; 73 | createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; 74 | createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; 75 | createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; 76 | ``` 77 | 78 | Le champ `subresourceRange` décrit l'utilisation de l'image et indique quelles parties de l'image devraient être 79 | accédées. Notre image sera utilisée comme cible de couleur et n'aura ni mipmapping ni plusieurs couches. 80 | 81 | ```c++ 82 | createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 83 | createInfo.subresourceRange.baseMipLevel = 0; 84 | createInfo.subresourceRange.levelCount = 1; 85 | createInfo.subresourceRange.baseArrayLayer = 0; 86 | createInfo.subresourceRange.layerCount = 1; 87 | ``` 88 | 89 | Si vous travailliez sur une application 3D stéréoscopique, vous devrez alors créer une swap chain avec plusieurs 90 | couches. Vous pourriez alors créer plusieurs image views pour chaque image. Elles représenteront ce qui sera affiché 91 | pour l'œil gauche et pour l'œil droit. 92 | 93 | Créer l'image view ne se résume plus qu'à appeler `vkCreateImageView` : 94 | 95 | ```c++ 96 | if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) { 97 | throw std::runtime_error("échec de la création d'une image view!"); 98 | } 99 | ``` 100 | 101 | À la différence des images, nous avons créé les image views explicitement et devons donc les détruire de la même 102 | manière, ce que nous faisons à l'aide d'une boucle : 103 | 104 | ```c++ 105 | void cleanup() { 106 | for (auto imageView : swapChainImageViews) { 107 | vkDestroyImageView(device, imageView, nullptr); 108 | } 109 | 110 | ... 111 | } 112 | ``` 113 | 114 | Une image view est suffisante pour commencer à utiliser une image comme une texture, mais pas pour que l'image soit 115 | utilisée comme cible d'affichage. Pour cela nous avons encore une étape, appelée framebuffer. Mais nous devons 116 | d'abord mettre en place le pipeline graphique. 117 | 118 | [Code C++](/code/07_image_views.cpp) 119 | -------------------------------------------------------------------------------- /fr/03_Dessiner_un_triangle/02_Pipeline_graphique_basique/00_Introduction.md: -------------------------------------------------------------------------------- 1 | Dans les chapitres qui viennent nous allons configurer une pipeline graphique pour qu'elle affiche notre premier 2 | triangle. La pipeline graphique est l'ensemble des opérations qui prennent les vertices et les textures de vos 3 | éléments et les utilisent pour en faire des pixels sur les cibles d'affichage. Un résumé simplifié ressemble à ceci : 4 | 5 | ![](/images/vulkan_simplified_pipeline.svg) 6 | 7 | L'_input assembler_ collecte les données des sommets à partir des buffers que vous avez mis en place, et peut aussi 8 | utiliser un _index buffer_ pour répéter certains éléments sans avoir à stocker deux fois les mêmes données dans un 9 | buffer. 10 | 11 | Le _vertex shader_ est exécuté pour chaque sommet et leur applique en général des transformations pour que leurs 12 | coordonnées passent de l'espace du modèle (model space) à l'espace de l'écran (screen space). Il fournit ensuite des 13 | données à la suite de la pipeline. 14 | 15 | Les _tesselation shaders_ permettent de subdiviser la géométrie selon des règles paramétrables afin d'améliorer la 16 | qualité du rendu. Ce procédé est notamment utilisé pour que des surface comme les murs de briques ou les escaliers 17 | aient l'air moins plats lorsque l'on s'en approche. 18 | 19 | Le _geometry shader_ est invoqué pour chaque primitive (triangle, ligne, points...) et peut les détruire ou en créer 20 | de nouvelles, du même type ou non. Ce travail est similaire au tesselation shader tout en étant beaucoup plus 21 | flexible. Il n'est cependant pas beaucoup utilisé à cause de performances assez moyennes sur les cartes graphiques 22 | (avec comme exception les GPUs intégrés d'Intel). 23 | 24 | La _rasterization_ transforme les primitives en _fragments_. Ce sont les pixels auxquels les primitives correspondent 25 | sur le framebuffer. Tout fragment en dehors de l'écran est abandonné. Les attributs sortant du vertex shader 26 | sont interpolés lorsqu'ils sont donnés aux étapes suivantes. Les fragments cachés par d'autres fragments sont aussi 27 | quasiment toujours éliminés grâce au test de profondeur (depth testing). 28 | 29 | Le _fragment shader_ est invoqué pour chaque fragment restant et détermine à quel(s) framebuffer(s) le fragment 30 | est envoyé, et quelles données y sont inscrites. Il réalise ce travail à l'aide des données interpolées émises par le 31 | vertex shader, ce qui inclut souvent des coordonnées de texture et des normales pour réaliser des calculs d'éclairage. 32 | 33 | Le _color blending_ applique des opérations pour mixer différents fragments correspondant à un même pixel sur le 34 | framebuffer. Les fragments peuvent remplacer les valeurs des autres, s'additionner ou se mélanger selon les 35 | paramètres de transparence (ou plus correctement de translucidité, en anglais translucency). 36 | 37 | Les étapes écrites en vert sur le diagramme s'appellent _fixed-function stages_ (étapes à fonction fixée). Il est 38 | possible de modifier des paramètres influençant les calculs, mais pas de modifier les calculs eux-mêmes. 39 | 40 | Les étapes colorées en orange sont programmables, ce qui signifie que vous pouvez charger votre propre code dans la 41 | carte graphique pour y appliquer exactement ce que vous voulez. Cela vous permet par exemple d'utiliser les fragment 42 | shaders pour implémenter n'importe quoi, de l'utilisation de textures et d'éclairage jusqu'au _ray tracing_. Ces 43 | programmes tournent sur de nombreux coeurs simultanément pour y traiter de nombreuses données en parallèle. 44 | 45 | Si vous avez utilisé d'anciens APIs comme OpenGL ou Direct3D, vous êtes habitués à pouvoir changer un quelconque 46 | paramètre de la pipeline à tout moment, avec des fonctions comme `glBlendFunc` ou `OMSSetBlendState`. Cela n'est plus 47 | possible avec Vulkan. La pipeline graphique y est quasiment fixée, et vous devrez en recréer une complètement si 48 | vous voulez changer de shader, y attacher différents framebuffers ou changer le color blending. Devoir créer une 49 | pipeline graphique pour chacune des combinaisons dont vous aurez besoin tout au long du programme représente un gros 50 | travail, mais permet au driver d'optimiser beaucoup mieux l'exécution des tâches car il sait à l'avance ce que la carte 51 | graphique aura à faire. 52 | 53 | Certaines étapes programmables sont optionnelles selon ce que vous voulez faire. Par exemple la tesselation et le 54 | geometry shader peuvent être désactivés. Si vous n'êtes intéressé que par les valeurs de profondeur vous pouvez 55 | désactiver le fragment shader, ce qui est utile pour les [shadow maps](https://en.wikipedia.org/wiki/Shadow_mapping). 56 | 57 | Dans le prochain chapitre nous allons d'abord créer deux étapes nécessaires à l'affichage d'un triangle à l'écran : 58 | le vertex shader et le fragment shader. Les étapes à fonction fixée seront mises en place dans le chapitre suivant. 59 | La dernière préparation nécessaire à la mise en place de la pipeline graphique Vulkan sera de fournir les framebuffers 60 | d'entrée et de sortie. 61 | 62 | Créez la fonction `createGraphicsPipeline` et appelez-la depuis `initVulkan` après `createImageViews`. Nous 63 | travaillerons sur cette fonction dans les chapitres suivants. 64 | 65 | ```c++ 66 | void initVulkan() { 67 | createInstance(); 68 | setupDebugMessenger(); 69 | createSurface(); 70 | pickPhysicalDevice(); 71 | createLogicalDevice(); 72 | createSwapChain(); 73 | createImageViews(); 74 | createGraphicsPipeline(); 75 | } 76 | 77 | ... 78 | 79 | void createGraphicsPipeline() { 80 | 81 | } 82 | ``` 83 | 84 | [Code C++](/code/08_graphics_pipeline.cpp) 85 | -------------------------------------------------------------------------------- /fr/03_Dessiner_un_triangle/02_Pipeline_graphique_basique/04_Conclusion.md: -------------------------------------------------------------------------------- 1 | Nous pouvons maintenant combiner toutes les structures et tous les objets des chapitres précédentes pour créer la 2 | pipeline graphique! Voici un petit récapitulatif des objets que nous avons : 3 | 4 | * Étapes shader : les modules shader définissent le fonctionnement des étapes programmables de la pipeline graphique 5 | * Étapes à fonction fixée : plusieurs structures paramètrent les étapes à fonction fixée comme l'assemblage des 6 | entrées, le rasterizer, le viewport et le mélange des couleurs 7 | * Organisation de la pipeline : les uniformes et push constants utilisées par les shaders, auxquelles on attribue une 8 | valeur pendant l'exécution de la pipeline 9 | * Render pass : les attachements référencés par la pipeline et leurs utilisations 10 | 11 | Tout cela combiné définit le fonctionnement de la pipeline graphique. Nous pouvons maintenant remplir la structure 12 | `VkGraphicsPipelineCreateInfo` à la fin de la fonction `createGraphicsPipeline`, mais avant les appels à la fonction 13 | `vkDestroyShaderModule` pour ne pas invalider les shaders que la pipeline utilisera. 14 | 15 | Commençons par référencer le tableau de `VkPipelineShaderStageCreateInfo`. 16 | 17 | ```c++ 18 | VkGraphicsPipelineCreateInfo pipelineInfo{}; 19 | pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; 20 | pipelineInfo.stageCount = 2; 21 | pipelineInfo.pStages = shaderStages; 22 | ``` 23 | 24 | Puis donnons toutes les structure décrivant les étapes à fonction fixée. 25 | 26 | ```c++ 27 | pipelineInfo.pVertexInputState = &vertexInputInfo; 28 | pipelineInfo.pInputAssemblyState = &inputAssembly; 29 | pipelineInfo.pViewportState = &viewportState; 30 | pipelineInfo.pRasterizationState = &rasterizer; 31 | pipelineInfo.pMultisampleState = &multisampling; 32 | pipelineInfo.pDepthStencilState = nullptr; // Optionnel 33 | pipelineInfo.pColorBlendState = &colorBlending; 34 | pipelineInfo.pDynamicState = nullptr; // Optionnel 35 | ``` 36 | 37 | Après cela vient l'organisation de la pipeline, qui est une référence à un objet Vulkan plutôt qu'une structure. 38 | 39 | ```c++ 40 | pipelineInfo.layout = pipelineLayout; 41 | ``` 42 | 43 | Finalement nous devons fournir les références à la render pass et aux indices des subpasses. Il est aussi possible 44 | d'utiliser d'autres render passes avec cette pipeline mais elles doivent être compatibles avec `renderPass`. La 45 | signification de compatible est donnée 46 | [ici](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#renderpass-compatibility), mais nous 47 | n'utiliserons pas cette possibilité dans ce tutoriel. 48 | 49 | ```c++ 50 | pipelineInfo.renderPass = renderPass; 51 | pipelineInfo.subpass = 0; 52 | ``` 53 | 54 | Il nous reste en fait deux paramètres : `basePipelineHandle` et `basePipelineIndex`. Vulkan vous permet de créer une 55 | nouvelle pipeline en "héritant" d'une pipeline déjà existante. L'idée derrière cette fonctionnalité est qu'il 56 | est moins coûteux de créer une pipeline à partir d'une qui existe déjà, mais surtout que passer d'une pipeline à une 57 | autre est plus rapide si elles ont un même parent. Vous pouvez spécifier une pipeline de deux manières : soit en 58 | fournissant une référence soit en donnant l'indice de la pipeline à hériter. Nous n'utilisons pas cela donc 59 | nous indiquerons une référence nulle et un indice invalide. Ces valeurs ne sont de toute façon utilisées que si le champ 60 | `flags` de la structure `VkGraphicsPipelineCreateInfo` comporte `VK_PIPELINE_CREATE_DERIVATIVE_BIT`. 61 | 62 | ```c++ 63 | pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; // Optionnel 64 | pipelineInfo.basePipelineIndex = -1; // Optionnel 65 | ``` 66 | 67 | Préparons-nous pour l'étape finale en créant un membre donnée où stocker la référence à la `VkPipeline` : 68 | 69 | ```c++ 70 | VkPipeline graphicsPipeline; 71 | ``` 72 | 73 | Et créons enfin la pipeline graphique : 74 | 75 | ```c++ 76 | if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { 77 | throw std::runtime_error("échec de la création de la pipeline graphique!"); 78 | } 79 | ``` 80 | 81 | La fonction `vkCreateGraphicsPipelines` possède en fait plus de paramètres que les fonctions de création d'objet que 82 | nous avons pu voir jusqu'à présent. Elle peut en effet accepter plusieurs structures `VkGraphicsPipelineCreateInfo` 83 | et créer plusieurs `VkPipeline` en un seul appel. 84 | 85 | Le second paramètre que nous n'utilisons pas ici (mais que nous reverrons dans un chapitre qui lui sera dédié) sert à 86 | fournir un objet `VkPipelineCache` optionnel. Un tel objet peut être stocké et réutilisé entre plusieurs appels de la 87 | fonction et même entre plusieurs exécutions du programme si son contenu est correctement stocké dans un fichier. Cela 88 | permet de grandement accélérer la création des pipelines. 89 | 90 | La pipeline graphique est nécessaire à toutes les opérations d'affichage, nous ne devrons donc la supprimer qu'à la fin 91 | du programme dans la fonction `cleanup` : 92 | 93 | ```c++ 94 | void cleanup() { 95 | vkDestroyPipeline(device, graphicsPipeline, nullptr); 96 | vkDestroyPipelineLayout(device, pipelineLayout, nullptr); 97 | ... 98 | } 99 | ``` 100 | 101 | Exécutez votre programme pour vérifier que tout ce travail a enfin résulté dans la création d'une pipeline graphique. 102 | Nous sommes de plus en plus proches d'avoir un dessin à l'écran! Dans les prochains chapitres nous générerons les 103 | framebuffers à partir des images de la swap chain et préparerons les commandes d'affichage. 104 | 105 | [Code C++](/code/12_graphics_pipeline_complete.cpp) / 106 | [Vertex shader](/code/09_shader_base.vert) / 107 | [Fragment shader](/code/09_shader_base.frag) 108 | -------------------------------------------------------------------------------- /fr/03_Dessiner_un_triangle/03_Effectuer_le_rendu/00_Framebuffers.md: -------------------------------------------------------------------------------- 1 | Nous avons beaucoup parlé de framebuffers dans les chapitres précédents, et nous avons mis en place la render pass 2 | pour qu'elle en accepte un du même format que les images de la swap chain. Pourtant nous n'en avons encore créé aucun. 3 | 4 | Les attachements de différents types spécifiés durant la render pass sont liés en les considérant dans des objets de 5 | type `VkFramebuffer`. Un tel objet référence toutes les `VkImageView` utilisées comme attachements par une passe. 6 | Dans notre cas nous n'en aurons qu'un : un attachement de couleur, qui servira de cible d'affichage uniquement. 7 | Cependant l'image utilisée dépendra de l'image fournie par la swap chain lors de la requête pour l'affichage. Nous 8 | devons donc créer un framebuffer pour chacune des images de la swap chain et utiliser le bon au moment de l'affichage. 9 | 10 | Pour cela créez un autre `std::vector` qui contiendra des framebuffers : 11 | 12 | ```c++ 13 | std::vector swapChainFramebuffers; 14 | ``` 15 | 16 | Nous allons remplir ce `vector` depuis une nouvelle fonction `createFramebuffers` que nous appellerons depuis 17 | `initVulkan` juste après la création de la pipeline graphique : 18 | 19 | ```c++ 20 | void initVulkan() { 21 | createInstance(); 22 | setupDebugMessenger(); 23 | createSurface(); 24 | pickPhysicalDevice(); 25 | createLogicalDevice(); 26 | createSwapChain(); 27 | createImageViews(); 28 | createRenderPass(); 29 | createGraphicsPipeline(); 30 | createFramebuffers(); 31 | } 32 | 33 | ... 34 | 35 | void createFramebuffers() { 36 | 37 | } 38 | ``` 39 | 40 | Commencez par redimensionner le conteneur afin qu'il puisse stocker tous les framebuffers : 41 | 42 | ```c++ 43 | void createFramebuffers() { 44 | swapChainFramebuffers.resize(swapChainImageViews.size()); 45 | } 46 | ``` 47 | 48 | Nous allons maintenant itérer à travers toutes les images et créer un framebuffer à partir de chacune d'entre elles : 49 | 50 | ```c++ 51 | for (size_t i = 0; i < swapChainImageViews.size(); i++) { 52 | VkImageView attachments[] = { 53 | swapChainImageViews[i] 54 | }; 55 | 56 | VkFramebufferCreateInfo framebufferInfo{}; 57 | framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 58 | framebufferInfo.renderPass = renderPass; 59 | framebufferInfo.attachmentCount = 1; 60 | framebufferInfo.pAttachments = attachments; 61 | framebufferInfo.width = swapChainExtent.width; 62 | framebufferInfo.height = swapChainExtent.height; 63 | framebufferInfo.layers = 1; 64 | 65 | if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) { 66 | throw std::runtime_error("échec de la création d'un framebuffer!"); 67 | } 68 | } 69 | ``` 70 | 71 | Comme vous le pouvez le voir la création d'un framebuffer est assez simple. Nous devons d'abord indiquer avec quelle 72 | `renderPass` le framebuffer doit être compatible. Sachez que si vous voulez utiliser un framebuffer avec plusieurs 73 | render passes, les render passes spécifiées doivent être compatibles entre elles. La compatibilité signifie ici 74 | approximativement qu'elles utilisent le même nombre d'attachements du même type. Ceci implique qu'il ne faut pas 75 | s'attendre à ce qu'une render pass puisse ignorer certains attachements d'un framebuffer qui en aurait trop. 76 | 77 | Les paramètres `attachementCount` et `pAttachments` doivent donner la taille du tableau contenant les `VkImageViews` 78 | qui servent d'attachements. 79 | 80 | Les paramètres `width` et `height` sont évidents. Le membre `layers` correspond au nombres de couches dans les images 81 | fournies comme attachements. Les images de la swap chain n'ont toujours qu'une seule couche donc nous indiquons `1`. 82 | 83 | Nous devons détruire les framebuffers avant les image views et la render pass dans la fonction `cleanup` : 84 | 85 | ```c++ 86 | void cleanup() { 87 | for (auto framebuffer : swapChainFramebuffers) { 88 | vkDestroyFramebuffer(device, framebuffer, nullptr); 89 | } 90 | 91 | ... 92 | } 93 | ``` 94 | 95 | Nous avons atteint le moment où tous les objets sont prêts pour l'affichage. Dans le prochain chapitre nous allons 96 | écrire les commandes d'affichage. 97 | 98 | [Code C++](/code/13_framebuffers.cpp) / 99 | [Vertex shader](/code/09_shader_base.vert) / 100 | [Fragment shader](/code/09_shader_base.frag) 101 | -------------------------------------------------------------------------------- /fr/04_Vertex_buffers/03_Index_buffer.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | Les modèles 3D que vous serez susceptibles d'utiliser dans des applications réelles partagerons le plus souvent des 4 | vertices communs à plusieurs triangles. Cela est d'ailleurs le cas avec un simple rectangle : 5 | 6 | ![](/images/vertex_vs_index.svg) 7 | 8 | Un rectangle est composé de triangles, ce qui signifie que nous aurions besoin d'un vertex buffer avec 6 vertices. Mais 9 | nous dupliquerions alors des vertices, aboutissant à un gachis de mémoire. Dans des modèles plus complexes, les vertices 10 | sont en moyenne en contact avec 3 triangles, ce qui serait encore pire. La solution consiste à utiliser un index buffer. 11 | 12 | Un index buffer est essentiellement un tableau de références vers le vertex buffer. Il vous permet de réordonner ou de 13 | dupliquer les données de ce buffer. L'image ci-dessus démontre l'utilité de cette méthode. 14 | 15 | ## Création d'un index buffer 16 | 17 | Dans ce chapitre, nous allons ajouter les données nécessaires à l'affichage d'un rectangle. Nous allons ainsi rajouter 18 | une coordonnée dans le vertex buffer et créer un index buffer. Voici les données des sommets au complet : 19 | 20 | ```c++ 21 | const std::vector vertices = { 22 | {{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}}, 23 | {{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}}, 24 | {{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}}, 25 | {{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}} 26 | }; 27 | ``` 28 | 29 | Le coin en haut à gauche est rouge, celui en haut à droite est vert, celui en bas à droite est bleu et celui en bas à 30 | gauche est blanc. Les couleurs seront dégradées par l'interpolation du rasterizer. Nous allons maintenant créer le 31 | tableau `indices` pour représenter l'index buffer. Son contenu correspond à ce qui est présenté dans l'illustration. 32 | 33 | ```c++ 34 | const std::vector indices = { 35 | 0, 1, 2, 2, 3, 0 36 | }; 37 | ``` 38 | 39 | Il est possible d'utiliser `uint16_t` ou `uint32_t` pour les valeurs de l'index buffer, en fonction du nombre d'éléments 40 | dans `vertices`. Nous pouvons nous contenter de `uint16_t` car nous n'utilisons pas plus de 65535 sommets différents. 41 | 42 | Comme les données des sommets, nous devons placer les indices dans un `VkBuffer` pour que le GPU puisse y avoir accès. 43 | Créez deux membres donnée pour référencer les ressources du futur index buffer : 44 | 45 | ```c++ 46 | VkBuffer vertexBuffer; 47 | VkDeviceMemory vertexBufferMemory; 48 | VkBuffer indexBuffer; 49 | VkDeviceMemory indexBufferMemory; 50 | ``` 51 | 52 | La fonction `createIndexBuffer` est quasiment identique à `createVertexBuffer` : 53 | 54 | ```c++ 55 | void initVulkan() { 56 | ... 57 | createVertexBuffer(); 58 | createIndexBuffer(); 59 | ... 60 | } 61 | 62 | void createIndexBuffer() { 63 | VkDeviceSize bufferSize = sizeof(indices[0]) * indices.size(); 64 | 65 | VkBuffer stagingBuffer; 66 | VkDeviceMemory stagingBufferMemory; 67 | createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, stagingBuffer, stagingBufferMemory); 68 | 69 | void* data; 70 | vkMapMemory(device, stagingBufferMemory, 0, bufferSize, 0, &data); 71 | memcpy(data, indices.data(), (size_t) bufferSize); 72 | vkUnmapMemory(device, stagingBufferMemory); 73 | 74 | createBuffer(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexBuffer, indexBufferMemory); 75 | 76 | copyBuffer(stagingBuffer, indexBuffer, bufferSize); 77 | 78 | vkDestroyBuffer(device, stagingBuffer, nullptr); 79 | vkFreeMemory(device, stagingBufferMemory, nullptr); 80 | } 81 | ``` 82 | 83 | Il n'y a que deux différences : `bufferSize` correspond à la taille du tableau multiplié par `sizeof(uint16_t)`, et 84 | `VK_BUFFER_USAGE_VERTEX_BUFFER_BIT` est remplacé par `VK_BUFFER_USAGE_INDEX_BUFFER_BIT`. À part ça tout est 85 | identique : nous créons un buffer intermédiaire puis le copions dans le buffer final local au GPU. 86 | 87 | L'index buffer doit être libéré à la fin du programme depuis `cleanup`. 88 | 89 | ```c++ 90 | void cleanup() { 91 | cleanupSwapChain(); 92 | 93 | vkDestroyBuffer(device, indexBuffer, nullptr); 94 | vkFreeMemory(device, indexBufferMemory, nullptr); 95 | 96 | vkDestroyBuffer(device, vertexBuffer, nullptr); 97 | vkFreeMemory(device, vertexBufferMemory, nullptr); 98 | 99 | ... 100 | } 101 | ``` 102 | 103 | ## Utilisation d'un index buffer 104 | 105 | Pour utiliser l'index buffer lors des opérations de rendu nous devons modifier un petit peu `createCommandBuffers`. Tout 106 | d'abord il nous faut lier l'index buffer. La différence est qu'il n'est pas possible d'avoir plusieurs index buffers. De 107 | plus il n'est pas possible de subdiviser les sommets en leurs coordonnées, ce qui implique que la modification d'une 108 | seule coordonnée nécessite de créer un autre sommet le vertex buffer. 109 | 110 | ```c++ 111 | vkCmdBindVertexBuffers(commandBuffers[i], 0, 1, vertexBuffers, offsets); 112 | 113 | vkCmdBindIndexBuffer(commandBuffers[i], indexBuffer, 0, VK_INDEX_TYPE_UINT16); 114 | ``` 115 | 116 | Un index buffer est lié par la fonction `vkCmdBindIndexBuffer`. Elle prend en paramètres le buffer, le décalage dans ce 117 | buffer et le type de donnée. Pour nous ce dernier sera `VK_INDEX_TYPE_UINT16`. 118 | 119 | Simplement lier le vertex buffer ne change en fait rien. Il nous faut aussi mettre à jour les commandes d'affichage 120 | pour indiquer à Vulkan comment utiliser le buffer. Supprimez l'appel à `vkCmdDraw`, et remplacez-le par 121 | `vkCmdDrawIndexed` : 122 | 123 | ```c++ 124 | vkCmdDrawIndexed(commandBuffers[i], static_cast(indices.size()), 1, 0, 0, 0); 125 | ``` 126 | 127 | Le deuxième paramètre indique le nombre d'indices. Le troisième est le nombre d'instances à invoquer (ici `1` car nous 128 | n'utilisons par cette technique). Le paramètre suivant est un décalage dans l'index buffer, sachant qu'ici il ne 129 | fonctionne pas en octets mais en indices. L'avant-dernier paramètre permet de fournir une valeur qui sera ajoutée à tous 130 | les indices juste avant de les faire correspondre aux vertices. Enfin, le dernier paramètre est un décalage pour le 131 | rendu instancié. 132 | 133 | Lancez le programme et vous devriez avoir ceci : 134 | 135 | ![](/images/indexed_rectangle.png) 136 | 137 | Vous savez maintenant économiser la mémoire en réutilisant les vertices à l'aide d'un index buffer. Cela deviendra 138 | crucial pour les chapitres suivants dans lesquels vous allez apprendre à charger des modèles complexes. 139 | 140 | Nous avons déjà évoqué le fait que le plus de buffers possibles devraient être stockés dans un seul emplacement 141 | mémoire. Il faudrait dans l'idéal allez encore plus loin : 142 | [les développeurs des drivers recommandent](https://developer.nvidia.com/vulkan-memory-management) également que vous 143 | placiez plusieurs buffers dans un seul et même `VkBuffer`, et que vous utilisiez des décalages pour les différencier 144 | dans les fonctions comme `vkCmdBindVertexBuffers`. Cela simplifie la mise des données dans des caches car elles sont 145 | regroupées en un bloc. Il devient même possible d'utiliser la même mémoire pour plusieurs ressources si elles ne sont 146 | pas utilisées en même temps et si elles sont proprement mises à jour. Cette pratique s'appelle d'ailleurs *aliasing*, et 147 | certaines fonctions Vulkan possèdent un paramètre qui permet au développeur d'indiquer s'il veut utiliser la technique. 148 | 149 | [Code C++](/code/20_index_buffer.cpp) / 150 | [Vertex shader](/code/17_shader_vertexbuffer.vert) / 151 | [Fragment shader](/code/17_shader_vertexbuffer.frag) 152 | -------------------------------------------------------------------------------- /fr/90_FAQ.md: -------------------------------------------------------------------------------- 1 | Cette page liste quelques problèmes que vous pourriez rencontrer lors du développement d'une application Vulkan. 2 | 3 | * **J'obtiens un erreur de violation d'accès dans les validations layers** : assurez-vous que MSI Afterburner / 4 | RivaTuner Statistics Server ne tournent pas, car ils possèdent des problèmes de compatibilité avec Vulkan. 5 | 6 | * **Je ne vois aucun message provenant des validation layers / les validation layers ne sont pas disponibles** : 7 | assurez-vous d'abord que les validation layers peuvent écrire leurs message en laissant le terminal ouvert après 8 | l'exécution. Avec Visual Studio, lancez le programme avec Ctrl-F5. Sous Linux, lancez le programme depuis un terminal. 9 | S'il n'y a toujours pas de message, revoyez l'installation du SDK en suivant les instructions de [cette page](https://vulkan.lunarg.com/doc/view/1.2.135.0/windows/getting_started.html) (section "Verify the Installation"). 10 | Assurez-vous également que le SDK est au moins de la version 1.1.106.0 pour le support de `VK_LAYER_KHRONOS_validation`. 11 | 12 | * **vkCreateSwapchainKHR induit une erreur dans SteamOverlayVulkanLayer64.dll** : Il semble qu'il y ait un problème de 13 | compatibilité avec la version beta du client Steam. Il y a quelques moyens de régler le conflit : 14 | * Désinstaller Steam 15 | * Mettre la variable d'environnement `DISABLE_VK_LAYER_VALVE_steam_overlay_1` à `1` 16 | * Supprimer la layer de Steam dans le répertoire sous `HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\ImplicitLayers` 17 | 18 | Exemple pour la variable : 19 | 20 | ![](/images/steam_layers_env.png) -------------------------------------------------------------------------------- /fr/95_Politique_de_confidentialité.md: -------------------------------------------------------------------------------- 1 | ## Généralités 2 | 3 | Cette politique de confidentialité concerne les informations collectées quand vous utilisez vulkan-tutorial.com ou 4 | l'un de ses sous-domaines. Il décrit la manière dont Alexander Overvoorde, propriétaire du site, collecte, utilise et 5 | partage les informations vous concernant. 6 | 7 | ## Renseignements 8 | 9 | Ce site web collecte des informations sur ses visiteurs à l'aide d'une instance Matomo 10 | ([https://matomo.org/](https://matomo.org/)) localement hébergée. Il analyse les pages que vous visitez, le type 11 | d'appareil et le navigateur que vous utilisez, combien de temps vous restez sur une page et comment vous êtes arrivés 12 | sur le site. Ces informations sont anonymisées en ne stockant que les deux premiers octets de votre addresse IP (par 13 | exemple `123.123.xxx.xxx`). Ces données sont stockés pour une durée indéterminée. 14 | 15 | Les données sont utilisées dans déterminer trois données : la manière dont le site est utilisé, le nombre de visiteurs 16 | en général et les sites qui mènent à ce site web. Cela permet de mieux engager un contact avec la communauté, et de 17 | déterminer les zones du site à améliorer. Par exemple cela permet de savoir s'il faut investir plus de temps dans 18 | l'interface mobile. 19 | 20 | Ces données ne sont pas partagées à des tiers. 21 | 22 | ## Publicité 23 | 24 | Ce site utilise des publicités fournies par des serveurs tiers. Elles peuvent utiliser des cookies pour suivre 25 | l'activité du site ou l'engagement avec les publicités. 26 | 27 | ## Commentaires 28 | 29 | Chaque chapitre comporte une section commentaires. Elle utilise le service tier Disqus. Ce service collecte des données 30 | individuelles pour faciliter la lecture et l'émission de commentaires. Il agglomère ces informations pour améliorer son 31 | offre de services. 32 | 33 | La politique de confidentialité complète de ce service tier se trouve à l'addresse suivante : 34 | [https://help.disqus.com/terms-and-policies/disqus-privacy-policy](https://help.disqus.com/terms-and-policies/disqus-privacy-policy). -------------------------------------------------------------------------------- /images/aliasing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/aliasing.png -------------------------------------------------------------------------------- /images/anisotropic_filtering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/anisotropic_filtering.png -------------------------------------------------------------------------------- /images/antialiasing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/antialiasing.png -------------------------------------------------------------------------------- /images/cube_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/cube_demo.png -------------------------------------------------------------------------------- /images/cube_demo_mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/cube_demo_mac.png -------------------------------------------------------------------------------- /images/cube_demo_nowindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/cube_demo_nowindow.png -------------------------------------------------------------------------------- /images/depth_correct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/depth_correct.png -------------------------------------------------------------------------------- /images/depth_issues.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/depth_issues.png -------------------------------------------------------------------------------- /images/drawing_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/drawing_model.png -------------------------------------------------------------------------------- /images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/favicon.png -------------------------------------------------------------------------------- /images/glfw_directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/glfw_directory.png -------------------------------------------------------------------------------- /images/highmipmaps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/highmipmaps.png -------------------------------------------------------------------------------- /images/include_dirs_stb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/include_dirs_stb.png -------------------------------------------------------------------------------- /images/include_dirs_tinyobjloader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/include_dirs_tinyobjloader.png -------------------------------------------------------------------------------- /images/indexed_rectangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/indexed_rectangle.png -------------------------------------------------------------------------------- /images/inverted_texture_coordinates.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/inverted_texture_coordinates.png -------------------------------------------------------------------------------- /images/library_directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/library_directory.png -------------------------------------------------------------------------------- /images/mipmaps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/mipmaps.png -------------------------------------------------------------------------------- /images/mipmaps_comparison.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/mipmaps_comparison.png -------------------------------------------------------------------------------- /images/mipmaps_example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/mipmaps_example.jpg -------------------------------------------------------------------------------- /images/multisampling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/multisampling.png -------------------------------------------------------------------------------- /images/multisampling_comparison.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/multisampling_comparison.png -------------------------------------------------------------------------------- /images/multisampling_comparison2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/multisampling_comparison2.png -------------------------------------------------------------------------------- /images/sample_shading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/sample_shading.png -------------------------------------------------------------------------------- /images/select_develop_branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/select_develop_branch.png -------------------------------------------------------------------------------- /images/semaphore_in_use.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/semaphore_in_use.png -------------------------------------------------------------------------------- /images/spinning_quad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/spinning_quad.png -------------------------------------------------------------------------------- /images/steam_layers_env.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/steam_layers_env.png -------------------------------------------------------------------------------- /images/swap_chain_validation_layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/swap_chain_validation_layer.png -------------------------------------------------------------------------------- /images/texcoord_visualization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/texcoord_visualization.png -------------------------------------------------------------------------------- /images/texture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/texture.jpg -------------------------------------------------------------------------------- /images/texture_addressing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/texture_addressing.png -------------------------------------------------------------------------------- /images/texture_filtering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/texture_filtering.png -------------------------------------------------------------------------------- /images/texture_on_square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/texture_on_square.png -------------------------------------------------------------------------------- /images/texture_on_square_colorized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/texture_on_square_colorized.png -------------------------------------------------------------------------------- /images/texture_on_square_repeated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/texture_on_square_repeated.png -------------------------------------------------------------------------------- /images/triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/triangle.png -------------------------------------------------------------------------------- /images/triangle_coordinates.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 67 | 73 | v0 84 | v1 95 | v2 106 | 107 | 108 | -------------------------------------------------------------------------------- /images/triangle_coordinates_colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/triangle_coordinates_colors.png -------------------------------------------------------------------------------- /images/triangle_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/triangle_white.png -------------------------------------------------------------------------------- /images/unsubmitted_fence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/unsubmitted_fence.png -------------------------------------------------------------------------------- /images/validation_layer_anisotropy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/validation_layer_anisotropy.png -------------------------------------------------------------------------------- /images/validation_layer_test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/validation_layer_test.png -------------------------------------------------------------------------------- /images/viewports_scissors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/viewports_scissors.png -------------------------------------------------------------------------------- /images/vs_all_configs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_all_configs.png -------------------------------------------------------------------------------- /images/vs_application_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_application_settings.png -------------------------------------------------------------------------------- /images/vs_build_mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_build_mode.png -------------------------------------------------------------------------------- /images/vs_cpp17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_cpp17.png -------------------------------------------------------------------------------- /images/vs_cpp_general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_cpp_general.png -------------------------------------------------------------------------------- /images/vs_dependencies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_dependencies.png -------------------------------------------------------------------------------- /images/vs_export_template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_export_template.png -------------------------------------------------------------------------------- /images/vs_include_dirs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_include_dirs.png -------------------------------------------------------------------------------- /images/vs_link_dirs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_link_dirs.png -------------------------------------------------------------------------------- /images/vs_link_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_link_input.png -------------------------------------------------------------------------------- /images/vs_link_settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_link_settings.png -------------------------------------------------------------------------------- /images/vs_new_cpp_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_new_cpp_project.png -------------------------------------------------------------------------------- /images/vs_new_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_new_item.png -------------------------------------------------------------------------------- /images/vs_new_source_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_new_source_file.png -------------------------------------------------------------------------------- /images/vs_open_project_properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_open_project_properties.png -------------------------------------------------------------------------------- /images/vs_template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_template.png -------------------------------------------------------------------------------- /images/vs_test_window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vs_test_window.png -------------------------------------------------------------------------------- /images/vulkan_sdk_download_buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/vulkan_sdk_download_buttons.png -------------------------------------------------------------------------------- /images/xcode_frameworks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/xcode_frameworks.png -------------------------------------------------------------------------------- /images/xcode_new_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/xcode_new_project.png -------------------------------------------------------------------------------- /images/xcode_new_project_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/xcode_new_project_2.png -------------------------------------------------------------------------------- /images/xcode_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/xcode_output.png -------------------------------------------------------------------------------- /images/xcode_paths.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/xcode_paths.png -------------------------------------------------------------------------------- /images/xcode_variables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/images/xcode_variables.png -------------------------------------------------------------------------------- /resources/viking_room.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jjYBdx4IL/VulkanTutorial-VisualStudioProjectFiles/b1abd7cdf2201c60bcff9d8b2b7b4eefdc2d738e/resources/viking_room.png --------------------------------------------------------------------------------