├── .gitignore ├── .prettierignore ├── .prettierrc ├── .stylelintrc.json ├── 404.html ├── CNAME ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── _config.yml ├── _includes ├── comments.html ├── head.html ├── head_custom.html ├── js │ └── custom.js ├── nav.html ├── title.html └── vendor │ └── anchor_headings.html ├── _layouts ├── about.html ├── default.html ├── home.html ├── page.html ├── post.html ├── table_wrappers.html └── vendor │ └── compress.html ├── _posts └── 2020-06-08-post-libraries.md ├── _sass ├── base.scss ├── buttons.scss ├── code.scss ├── color_schemes │ └── dark.scss ├── content.scss ├── custom │ └── custom.scss ├── labels.scss ├── layout.scss ├── navigation.scss ├── overrides.scss ├── search.scss ├── support │ ├── _functions.scss │ ├── _variables.scss │ ├── mixins │ │ ├── _buttons.scss │ │ ├── _layout.scss │ │ ├── _typography.scss │ │ └── mixins.scss │ └── support.scss ├── tables.scss ├── typography.scss ├── utilities │ ├── _colors.scss │ ├── _layout.scss │ ├── _lists.scss │ ├── _spacing.scss │ ├── _typography.scss │ └── utilities.scss └── vendor │ └── normalize.scss │ ├── README.md │ ├── normalize.scss │ └── package.json ├── assets ├── css │ ├── dark-mode-preview.scss │ └── just-the-docs.scss ├── images │ ├── Cmakesetup.png │ ├── Vulkan_170px_Dec16.jpg │ ├── just-the-docs.png │ ├── sdl_dll.png │ ├── search.svg │ └── vs_compile.png └── js │ ├── dark-mode-preview.js │ ├── just-the-docs.js │ ├── search-data.json │ └── vendor │ └── lunr.min.js ├── bin └── just-the-docs ├── debug.log ├── diagrams ├── ColorTri2.png ├── GPU Timeline.drawio ├── IMGUI.png ├── ambientcolor.gif ├── assetarchitecture.drawio ├── chapter0.png ├── chapter1.png ├── chapter2.png ├── chapter3.png ├── chapter4.png ├── chapter5.png ├── cityrender.png ├── colorTriangle.png ├── commandtimeline.png ├── compute_grid.png ├── descriptors.drawio ├── descriptors.png ├── empireTextured.png ├── empireUntextured.png ├── fullscene.png ├── greenTriangle.png ├── indirectarch.drawio ├── indirectperf.png ├── metafor │ ├── bloom.png │ ├── cascades.png │ ├── characters.png │ ├── chardepth.png │ ├── city.png │ ├── deferred_env.png │ ├── deferred_global.png │ ├── deferred_light.png │ ├── desert.png │ ├── fulldraw.png │ ├── lightfx.png │ ├── overdraw.png │ ├── rdc_compute.png │ ├── renderdoc_full_city.png │ ├── rest_forest.png │ ├── rgp_global.png │ ├── rgp_occupancy.png │ ├── shadows.png │ ├── transparent_composite.png │ └── transparents.png ├── monkeyGlitch.png ├── monkeyGood.png ├── novus.png ├── redTriangle.png ├── spinTriangle.gif ├── test.drawio ├── test.png ├── test.svg ├── texmonkey.png ├── vkcommands.drawio ├── vkcommands.png └── vkcommandsync.drawio ├── docs ├── chapter-0 │ ├── building_project.md │ ├── chapter-0.md │ └── code_walkthrough.md ├── chapter-1 │ ├── chapter-1.md │ ├── vulkan_command_flow.md │ ├── vulkan_commands_code.md │ ├── vulkan_init_code.md │ ├── vulkan_init_flow.md │ ├── vulkan_mainloop.md │ ├── vulkan_mainloop_code.md │ ├── vulkan_renderpass.md │ └── vulkan_renderpass_code.md ├── chapter-2 │ ├── chapter-2.md │ ├── cleanup.md │ ├── passing_data.md │ ├── pipeline_walkthrough.md │ ├── toggling_shaders.md │ ├── triangle_walkthrough.md │ └── vulkan_render_pipeline.md ├── chapter-3 │ ├── chapter-3.md │ ├── depth_buffer.md │ ├── obj_loading.md │ ├── push_constants.md │ ├── scene_management.md │ ├── triangle_mesh.md │ └── triangle_mesh_code.md ├── chapter-4 │ ├── chapter-4.md │ ├── descriptors.md │ ├── descriptors_code.md │ ├── descriptors_code_more.md │ ├── double_buffering.md │ └── storage_buffers.md ├── chapter-5 │ ├── chapter-5.md │ ├── drawing_images.md │ ├── loading_images.md │ ├── memory_transfers.md │ └── vulkan_images.md ├── extra-chapter │ ├── abstracting_descriptors.md │ ├── asset_system.md │ ├── cvar_system.md │ ├── extra-chapter.md │ ├── graphics_analysis_metafor.md │ ├── hardware.md │ ├── implementing_imgui.md │ └── multithreading.md ├── gpudriven │ ├── code_architecture.md │ ├── compute_culling.md │ ├── compute_shaders.md │ ├── draw_indirect.md │ ├── gpu_driven_engines.md │ ├── gpudriven.md │ ├── material_system.md │ └── mesh_rendering.md ├── great_resources.md ├── introduction │ ├── introduction.md │ ├── project_libs.md │ ├── vulkan_execution.md │ └── vulkan_overview.md ├── ko │ ├── introduction │ │ ├── introduction.md │ │ ├── project_libs.md │ │ ├── vulkan_execution.md │ │ └── vulkan_overview.md │ ├── korean.md │ ├── new_chapter_0 │ │ ├── building_project.md │ │ ├── chapter-0.md │ │ └── code_walkthrough.md │ ├── new_chapter_1 │ │ ├── chapter-1.md │ │ ├── vulkan_command_flow.md │ │ ├── vulkan_commands_code.md │ │ ├── vulkan_init_code.md │ │ ├── vulkan_init_flow.md │ │ ├── vulkan_mainloop.md │ │ └── vulkan_mainloop_code.md │ ├── new_chapter_2 │ │ ├── chapter-2.md │ │ ├── vulkan_imgui_setup.md │ │ ├── vulkan_new_rendering.md │ │ ├── vulkan_pushconstants.md │ │ ├── vulkan_shader_code.md │ │ └── vulkan_shader_drawing.md │ ├── new_chapter_3 │ │ ├── blending.md │ │ ├── building_pipeline.md │ │ ├── chapter-3.md │ │ ├── loading_meshes.md │ │ ├── mesh_buffers.md │ │ ├── render_pipeline.md │ │ └── resizing_window.md │ ├── new_chapter_4 │ │ ├── chapter-4.md │ │ ├── descriptor_abstractions.md │ │ ├── engine_arch.md │ │ ├── materials.md │ │ ├── new_drawloop.md │ │ └── textures.md │ └── new_chapter_5 │ │ ├── chapter-5.md │ │ ├── faster_draw.md │ │ ├── gltf_nodes.md │ │ ├── gltf_textures.md │ │ └── interactive_camera.md ├── new_chapter_0 │ ├── building_project.md │ ├── chapter-0.md │ └── code_walkthrough.md ├── new_chapter_1 │ ├── chapter-1.md │ ├── vulkan_command_flow.md │ ├── vulkan_commands_code.md │ ├── vulkan_init_code.md │ ├── vulkan_init_flow.md │ ├── vulkan_mainloop.md │ └── vulkan_mainloop_code.md ├── new_chapter_2 │ ├── chapter-2.md │ ├── vulkan_imgui_setup.md │ ├── vulkan_new_rendering.md │ ├── vulkan_pushconstants.md │ ├── vulkan_shader_code.md │ └── vulkan_shader_drawing.md ├── new_chapter_3 │ ├── blending.md │ ├── building_pipeline.md │ ├── chapter-3.md │ ├── loading_meshes.md │ ├── mesh_buffers.md │ ├── render_pipeline.md │ └── resizing_window.md ├── new_chapter_4 │ ├── chapter-4.md │ ├── descriptor_abstractions.md │ ├── engine_arch.md │ ├── materials.md │ ├── new_drawloop.md │ └── textures.md ├── new_chapter_5 │ ├── chapter-5.md │ ├── faster_draw.md │ ├── gltf_nodes.md │ ├── gltf_textures.md │ └── interactive_camera.md └── old_vkguide.md ├── favicon.ico ├── index.md ├── just-the-docs.gemspec ├── lib └── tasks │ └── search.rake ├── package-lock.json ├── package.json ├── script └── build └── vkguide_new_source ├── ko ├── korean.md ├── new_chapter_0 │ ├── building_project.md │ ├── chapter-0.md │ └── code_walkthrough.md ├── new_chapter_1 │ ├── chapter-1.md │ ├── vulkan_command_flow.md │ ├── vulkan_commands_code.md │ ├── vulkan_init_code.md │ ├── vulkan_init_flow.md │ ├── vulkan_mainloop.md │ └── vulkan_mainloop_code.md ├── new_chapter_2 │ ├── chapter-2.md │ ├── vulkan_imgui_setup.md │ ├── vulkan_new_rendering.md │ ├── vulkan_pushconstants.md │ ├── vulkan_shader_code.md │ └── vulkan_shader_drawing.md ├── new_chapter_3 │ ├── blending.md │ ├── building_pipeline.md │ ├── chapter-3.md │ ├── loading_meshes.md │ ├── mesh_buffers.md │ ├── render_pipeline.md │ └── resizing_window.md ├── new_chapter_4 │ ├── chapter-4.md │ ├── descriptor_abstractions.md │ ├── engine_arch.md │ ├── materials.md │ ├── new_drawloop.md │ └── textures.md └── new_chapter_5 │ ├── chapter-5.md │ ├── faster_draw.md │ ├── gltf_nodes.md │ ├── gltf_textures.md │ └── interactive_camera.md ├── new_chapter_0 ├── building_project.md ├── chapter-0.md └── code_walkthrough.md ├── new_chapter_1 ├── chapter-1.md ├── vulkan_command_flow.md ├── vulkan_commands_code.md ├── vulkan_init_code.md ├── vulkan_init_flow.md ├── vulkan_mainloop.md └── vulkan_mainloop_code.md ├── new_chapter_2 ├── chapter-2.md ├── vulkan_imgui_setup.md ├── vulkan_new_rendering.md ├── vulkan_pushconstants.md ├── vulkan_shader_code.md └── vulkan_shader_drawing.md ├── new_chapter_3 ├── blending.md ├── building_pipeline.md ├── chapter-3.md ├── loading_meshes.md ├── mesh_buffers.md ├── render_pipeline.md └── resizing_window.md ├── new_chapter_4 ├── chapter-4.md ├── descriptor_abstractions.md ├── engine_arch.md ├── materials.md ├── new_drawloop.md └── textures.md └── new_chapter_5 ├── chapter-5.md ├── faster_draw.md ├── gltf_nodes.md ├── gltf_textures.md └── interactive_camera.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle 3 | .sass-cache 4 | _site 5 | Gemfile.lock 6 | node_modules 7 | TODO.txt 8 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | package-lock.json 3 | _site 4 | assets/css/dark-mode-preview.scss 5 | assets/css/just-the-docs.scss 6 | assets/js/vendor/lunr.min.js 7 | assets/js/search-data.json 8 | assets/js/just-the-docs.js 9 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } 8 | 9 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "ignoreFiles": [ 3 | "assets/css/just-the-docs.scss", 4 | "assets/css/dark-mode-preview.scss", 5 | "_sass/vendor/**/*.scss" 6 | ], 7 | "extends": ["stylelint-config-primer", "stylelint-config-prettier"], 8 | "plugins": ["stylelint-prettier"], 9 | "rules": { 10 | "prettier/prettier": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Page not found 4 | permalink: /404 5 | nav_exclude: true 6 | search_exclude: true 7 | --- 8 | 9 |

Page not found

10 | 11 |

The page you requested could not be found. Try using the navigation {% if site.search_enabled %}or search {% endif %}to find what you're looking for or go to this site's home page.

12 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | vkguide.dev -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | gemspec 3 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Patrick Marsceill 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Vulkan tutorial guide with a hands on, step by step, approach. -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | Dir.glob('lib/tasks/*.rake').each {|r| import r} 2 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # SITE CONFIGURATION 2 | #baseurl: /vulkan-guide 3 | url: "//www.vkguide.dev" 4 | title: Vulkan Guide # site's title 5 | description: "Practical guide to vulkan graphics programming" # used by search engines 6 | 7 | permalink: pretty 8 | exclude: ["node_modules/", "*.gemspec", "*.gem", "Gemfile", "Gemfile.lock", "package.json", "package-lock.json", "script/", "LICENSE.txt", "lib/", "bin/", "README.md", "Rakefile", vkguide_new_source/] 9 | 10 | # Set a path/url to a logo that will be displayed instead of the title 11 | #logo: "/assets/images/just-the-docs.png" 12 | 13 | # Enable or disable the site search 14 | search_enabled: true 15 | 16 | # Set the search token separator for hyphenated-word search: 17 | search_tokenizer_separator: /[\s/]+/ 18 | 19 | # Enable or disable heading anchors 20 | heading_anchors: true 21 | 22 | # Aux links for the upper right navigation 23 | aux_links: 24 | "Vulkan Spec": 25 | - "https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap2.html#introduction" 26 | "Github Repo": 27 | - "https://github.com/vblanco20-1/vulkan-guide" 28 | "Tutorial code 📖": 29 | - "https://github.com/vblanco20-1/vulkan-guide/tree/all-chapters-2" 30 | # Footer content appears at the bottom of every page's main content 31 | footer_content: "Copyright © 2020 Victor Blanco. Distributed by a MIT license." 32 | 33 | # Color scheme currently only supports "dark" or nil (default) 34 | color_scheme: dark 35 | 36 | # Google Analytics Tracking (optional) 37 | # e.g, UA-1234567-89 38 | ga_tracking: UA-78728905-2 39 | 40 | 41 | plugins: 42 | - jekyll-seo-tag 43 | 44 | compress_html: 45 | clippings: all 46 | comments: all 47 | endings: all 48 | startings: [] 49 | blanklines: false 50 | profile: false -------------------------------------------------------------------------------- /_includes/comments.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% if site.plugins.jekyll-seo == nil %} 6 | {{ page.title }} - {{ site.title }} 7 | 8 | {% if page.description %} 9 | 10 | {% endif %} 11 | {% endif %} 12 | 13 | 14 | 15 | 16 | 17 | {% if site.ga_tracking != nil %} 18 | 19 | 26 | 27 | {% endif %} 28 | 29 | {% if site.search_enabled != false %} 30 | 31 | {% endif %} 32 | 33 | 34 | 35 | 36 | {% seo %} 37 | 38 | {% include head_custom.html %} 39 | 40 | 41 | -------------------------------------------------------------------------------- /_includes/head_custom.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/_includes/head_custom.html -------------------------------------------------------------------------------- /_includes/js/custom.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/_includes/js/custom.js -------------------------------------------------------------------------------- /_includes/nav.html: -------------------------------------------------------------------------------- 1 | 41 | -------------------------------------------------------------------------------- /_includes/title.html: -------------------------------------------------------------------------------- 1 | {% if site.logo %} 2 | 3 | {% else %} 4 | {{ site.title }} 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /_layouts/about.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | {{ content }} 6 | -------------------------------------------------------------------------------- /_layouts/home.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | {{ content }} 6 | -------------------------------------------------------------------------------- /_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | {{ content }} 6 | -------------------------------------------------------------------------------- /_layouts/post.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | {{ content }} 6 | -------------------------------------------------------------------------------- /_layouts/table_wrappers.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: vendor/compress 3 | --- 4 | 5 | {% assign content_ = content | replace: '', '' %} 7 | {{ content_ }} -------------------------------------------------------------------------------- /_layouts/vendor/compress.html: -------------------------------------------------------------------------------- 1 | --- 2 | # Jekyll layout that compresses HTML 3 | # v3.1.0 4 | # http://jch.penibelst.de/ 5 | # © 2014–2015 Anatol Broder 6 | # MIT License 7 | --- 8 | 9 | {% capture _LINE_FEED %} 10 | {% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment or site.compress_html.ignore.envs == "all" %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "" %}{% endif %}{% unless _pre_before contains "" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " ;; ;" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %}
Step Bytes
raw {{ content | size }}{% if _profile_endings %}
endings {{ _profile_endings }}{% endif %}{% if _profile_startings %}
startings {{ _profile_startings }}{% endif %}{% if _profile_comments %}
comments {{ _profile_comments }}{% endif %}{% if _profile_collapse %}
collapse {{ _profile_collapse }}{% endif %}{% if _profile_clippings %}
clippings {{ _profile_clippings }}{% endif %}
{% endif %}{% endif %} 11 | -------------------------------------------------------------------------------- /_posts/2020-06-08-post-libraries.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Code: Space Battle, Huge edition" 4 | excerpt_separator: "" 5 | feature-img: "assets/img/screenshots/hugebattle.jpg" 6 | thumbnail: "assets/img/screenshots/hugebattle.jpg" 7 | categories: 8 | - Code Experiment 9 | tags: 10 | - C++ 11 | - Code 12 | - ECS 13 | - Experiment 14 | - DirectX 15 | --- 16 | 17 | ## Project layout 18 | 19 | For the Vulkan engine, we use a specific folder layout. 20 | 21 | - `/assets` will contain textures and 3d models that we use over the guide 22 | - `/bin` is where the executables will get built. We don't use the normal CMake build folders to simplify the paths to assets and shaders 23 | - `/shaders` will contain all our shaders, and their compiled SPIR-V output 24 | - `/src` contains the source code for the main application and engine 25 | - `/third_party` contains all of the libraries we use, vendored in 26 | 27 | ## Libraries 28 | 29 | On the engine, we use a set of libraries, most stored in `/third_party`. The only library that isn't vendored-in is SDL 30 | 31 | All the libraries in third-party are vendored in, and Cmake will build them automatically. For SDL, it's required to build it separated from the project, and tell Cmake where to find it. 32 | 33 | - [GLM (openGL Mathematics)](https://github.com/g-truc/glm) Mathematics library, Header only. We use this library to use its matrix and vector math functionality. It's a library that contains types that are directly compatible with GLSL types in most cases. For example, a `glm::mat4` has similar operations and is directly compatible with a `mat4` in a shader. It says OpenGL in the name, but it works great with Vulkan too. 34 | - [SDL](https://www.libsdl.org/) Windowing and input library, Separate build. SDL is one of the most used libraries to create a window and have input on a crossplatform way. SDL works in almost every platform, and it's generally very well supported. Used in Unreal Engine, Unity, Source, and others. We use it in the project to have a easy and fast way to open a window, and have detailed keyboard input. 35 | - [dear IMGUI](https://github.com/ocornut/imgui) Easy to use immediate User-Interface library. This library allows us to create editable widgets such as sliders and windows for user interface. It's widely used in the game industry for debug tools. On the project, we use it to create interactive options for the rendering. 36 | 37 | - [STB Image](https://github.com/nothings/stb) Image load library, header only. Small and easy to use library to load image files. It can load a few common formats such as BMP, PNG, JPEG, and others. Part of a set of other similar single-file libraries. 38 | 39 | - [Tiny Obj Loader](https://github.com/tinyobjloader/tinyobjloader) .Obj model loader library, header only. Fast and small library to load the .obj 3d model format that we will use when loading 3d models. 40 | 41 | - [Vk Bootstrap](https://github.com/charles-lunarg/vk-bootstrap/blob/master/src/VkBootstrap.cpp) Abstracts a big amount of boilerplate that Vulkan has when setting up. Most of that code is written once and never touched again, so we will skip most of it using this library. This library simplifies instance creation, swapchain creation, and extension loading. It will be removed from the project eventually in an optional chapter that explains how to initialize that Vulkan boilerplate the "manual" way. 42 | 43 | - [VMA (Vulkan memory allocator)](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) Implements memory allocators for Vulkan, header only. In Vulkan, the user has to deal with the memory allocation of buffers, images, and other resources on their own. This can be very difficult to get right in a performant and safe way. Vulkan Memory Allocator does it for us and allows us to simplify the creation of images and other resources. Widely used in personal Vulkan engines or smaller scale projects like emulators. Very high end projects like Unreal Engine or AAA engines write their own memory allocators. -------------------------------------------------------------------------------- /_sass/base.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Base element style overrides 3 | // 4 | // stylelint-disable selector-no-type, selector-max-type 5 | 6 | * { 7 | box-sizing: border-box; 8 | } 9 | 10 | ::selection { 11 | color: $white; 12 | background: $link-color; 13 | } 14 | 15 | html { 16 | @include fs-4; 17 | } 18 | 19 | body { 20 | font-family: $body-font-family; 21 | font-size: inherit; 22 | line-height: $body-line-height; 23 | color: $body-text-color; 24 | background-color: $body-background-color; 25 | } 26 | 27 | p, 28 | h1, 29 | h2, 30 | h3, 31 | h4, 32 | h5, 33 | h6, 34 | ol, 35 | ul, 36 | pre, 37 | address, 38 | blockquote, 39 | dl, 40 | div, 41 | fieldset, 42 | form, 43 | hr, 44 | noscript, 45 | table { 46 | margin-top: 0; 47 | } 48 | 49 | h1, 50 | h2, 51 | h3, 52 | h4, 53 | h5, 54 | h6 { 55 | margin-top: 1.2em; 56 | margin-bottom: 0.8em; 57 | font-weight: 500; 58 | line-height: $body-heading-line-height; 59 | color: $body-heading-color; 60 | } 61 | 62 | p { 63 | margin-bottom: 1em; 64 | } 65 | 66 | a { 67 | color: $link-color; 68 | text-decoration: none; 69 | } 70 | 71 | a:not([class]) { 72 | text-decoration: none; 73 | background-image: linear-gradient($border-color 0%, $border-color 100%); 74 | background-repeat: repeat-x; 75 | background-position: 0 100%; 76 | background-size: 1px 1px; 77 | 78 | &:hover { 79 | background-image: linear-gradient( 80 | rgba($link-color, 0.45) 0%, 81 | rgba($link-color, 0.45) 100% 82 | ); 83 | background-size: 1px 1px; 84 | } 85 | } 86 | 87 | code { 88 | font-family: $mono-font-family; 89 | font-size: 12px; 90 | line-height: $body-line-height; 91 | } 92 | 93 | figure, 94 | pre { 95 | margin: 0; 96 | } 97 | 98 | li { 99 | margin: 0.25em 0; 100 | } 101 | 102 | img { 103 | max-width: 100%; 104 | height: auto; 105 | } 106 | 107 | hr { 108 | height: 1px; 109 | padding: 0; 110 | margin: $sp-6 0; 111 | background-color: $border-color; 112 | border: 0; 113 | } 114 | -------------------------------------------------------------------------------- /_sass/buttons.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Buttons and things that look like buttons 3 | // 4 | // stylelint-disable color-named 5 | 6 | .btn { 7 | display: inline-block; 8 | box-sizing: border-box; 9 | padding-top: 0.3em; 10 | padding-right: 1em; 11 | padding-bottom: 0.3em; 12 | padding-left: 1em; 13 | margin: 0; 14 | font-family: inherit; 15 | font-size: inherit; 16 | font-weight: 500; 17 | line-height: 1.5; 18 | color: $link-color; 19 | text-decoration: none; 20 | vertical-align: baseline; 21 | cursor: pointer; 22 | background-color: $base-button-color; 23 | border-width: 0; 24 | border-radius: $border-radius; 25 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08); 26 | appearance: none; 27 | 28 | &:focus { 29 | text-decoration: none; 30 | outline: none; 31 | box-shadow: 0 0 0 3px rgba(blue, 0.25); 32 | } 33 | 34 | &:focus:hover, 35 | &.selected:focus { 36 | box-shadow: 0 0 0 3px rgba(blue, 0.25); 37 | } 38 | 39 | &:hover, 40 | &.zeroclipboard-is-hover { 41 | color: darken($link-color, 2%); 42 | } 43 | 44 | &:hover, 45 | &:active, 46 | &.zeroclipboard-is-hover, 47 | &.zeroclipboard-is-active { 48 | text-decoration: none; 49 | background-color: darken($base-button-color, 1%); 50 | } 51 | 52 | &:active, 53 | &.selected, 54 | &.zeroclipboard-is-active { 55 | background-color: darken($base-button-color, 3%); 56 | background-image: none; 57 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15); 58 | } 59 | 60 | &.selected:hover { 61 | background-color: darken(#dcdcdc, 5%); 62 | } 63 | 64 | &:disabled, 65 | &.disabled { 66 | &, 67 | &:hover { 68 | color: rgba(102, 102, 102, 0.5); 69 | cursor: default; 70 | background-color: rgba(229, 229, 229, 0.5); 71 | background-image: none; 72 | box-shadow: none; 73 | } 74 | } 75 | } 76 | 77 | .btn-outline { 78 | color: $link-color; 79 | background: transparent; 80 | box-shadow: inset 0 0 0 2px $grey-lt-300; 81 | 82 | &:hover, 83 | &:active, 84 | &.zeroclipboard-is-hover, 85 | &.zeroclipboard-is-active { 86 | color: darken($link-color, 4%); 87 | text-decoration: none; 88 | background-color: transparent; 89 | box-shadow: inset 0 0 0 3px $grey-lt-300; 90 | } 91 | 92 | &:focus { 93 | text-decoration: none; 94 | outline: none; 95 | box-shadow: inset 0 0 0 2px $grey-dk-100, 0 0 0 3px rgba(blue, 0.25); 96 | } 97 | 98 | &:focus:hover, 99 | &.selected:focus { 100 | box-shadow: inset 0 0 0 2px $grey-dk-100; 101 | } 102 | } 103 | 104 | .btn-primary { 105 | @include btn-color($white, $btn-primary-color); 106 | } 107 | 108 | .btn-purple { 109 | @include btn-color($white, $purple-100); 110 | } 111 | 112 | .btn-blue { 113 | @include btn-color($white, $blue-000); 114 | } 115 | 116 | .btn-green { 117 | @include btn-color($white, $green-100); 118 | } 119 | -------------------------------------------------------------------------------- /_sass/color_schemes/dark.scss: -------------------------------------------------------------------------------- 1 | $body-background-color: $grey-dk-300; 2 | $sidebar-color: $grey-dk-300; 3 | $border-color: $grey-dk-200; 4 | 5 | $body-text-color: $grey-lt-300; 6 | $body-heading-color: $grey-lt-000; 7 | $nav-child-link-color: $grey-dk-000; 8 | $search-result-preview-color: $grey-dk-000; 9 | 10 | $link-color: $blue-000; 11 | $btn-primary-color: $blue-200; 12 | $base-button-color: $grey-dk-250; 13 | 14 | $code-background-color: $grey-dk-250; 15 | $search-background-color: $grey-dk-250; 16 | $table-background-color: $grey-dk-250; 17 | -------------------------------------------------------------------------------- /_sass/content.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | // 4 | // Styles for rendered markdown in the .main-content container 5 | // 6 | // stylelint-disable selector-no-type, max-nesting-depth, selector-max-compound-selectors, selector-max-type 7 | 8 | .page-content { 9 | line-height: $content-line-height; 10 | 11 | a { 12 | overflow: hidden; 13 | text-overflow: ellipsis; 14 | white-space: nowrap; 15 | } 16 | 17 | ul, 18 | ol { 19 | padding-left: 1.5em; 20 | } 21 | 22 | ol { 23 | list-style-type: none; 24 | counter-reset: step-counter; 25 | 26 | > li { 27 | position: relative; 28 | 29 | &::before { 30 | position: absolute; 31 | top: 0.2em; 32 | left: -1.6em; 33 | color: $grey-dk-000; 34 | content: counter(step-counter); 35 | counter-increment: step-counter; 36 | @include fs-3; 37 | 38 | @include mq(sm) { 39 | top: 0.11em; 40 | } 41 | } 42 | 43 | ol { 44 | counter-reset: sub-counter; 45 | 46 | li { 47 | &::before { 48 | content: counter(sub-counter, lower-alpha); 49 | counter-increment: sub-counter; 50 | } 51 | } 52 | } 53 | } 54 | } 55 | 56 | ul { 57 | list-style: none; 58 | 59 | > li { 60 | &::before { 61 | position: absolute; 62 | margin-left: -1.4em; 63 | color: $grey-dk-000; 64 | content: "•"; 65 | } 66 | } 67 | } 68 | 69 | .task-list { 70 | padding-left: 0; 71 | } 72 | 73 | .task-list-item { 74 | display: flex; 75 | align-items: center; 76 | 77 | &::before { 78 | content: ""; 79 | } 80 | } 81 | 82 | .task-list-item-checkbox { 83 | margin-right: 0.6em; 84 | } 85 | 86 | hr + * { 87 | margin-top: 0; 88 | } 89 | 90 | h1:first-of-type { 91 | margin-top: 0.5em; 92 | } 93 | 94 | dl { 95 | display: grid; 96 | grid-template-columns: max-content 1fr; 97 | } 98 | 99 | dt, 100 | dd { 101 | margin: 0.25em 0; 102 | } 103 | 104 | dt { 105 | text-align: right; 106 | 107 | &::after { 108 | content: ":"; 109 | } 110 | } 111 | 112 | dd { 113 | margin-left: 1em; 114 | font-weight: 500; 115 | } 116 | 117 | .anchor-heading { 118 | position: absolute; 119 | right: -$sp-4; 120 | width: $sp-5; 121 | height: 100%; 122 | padding-right: $sp-1; 123 | padding-left: $sp-1; 124 | overflow: visible; 125 | 126 | @include mq(md) { 127 | right: auto; 128 | left: -$sp-5; 129 | } 130 | 131 | svg { 132 | display: inline-block; 133 | width: 100%; 134 | height: 100%; 135 | fill: $link-color; 136 | visibility: hidden; 137 | } 138 | } 139 | 140 | .anchor-heading:hover, 141 | h1:hover > .anchor-heading, 142 | h2:hover > .anchor-heading, 143 | h3:hover > .anchor-heading, 144 | h4:hover > .anchor-heading, 145 | h5:hover > .anchor-heading, 146 | h6:hover > .anchor-heading { 147 | svg { 148 | visibility: visible; 149 | } 150 | } 151 | 152 | h1, 153 | h2, 154 | h3, 155 | h4, 156 | h5, 157 | h6 { 158 | position: relative; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /_sass/custom/custom.scss: -------------------------------------------------------------------------------- 1 | //// 2 | //// Typography 3 | //// 4 | 5 | //$body-font-family: -apple-system, BlinkMacSystemFont, "helvetica neue", helvetica, roboto, noto, "segoe ui", arial, sans-serif; 6 | //$mono-font-family: "SFMono-Regular", Menlo, Consolas, Monospace; 7 | //$root-font-size: 16px; // Base font-size for rems 8 | //$body-line-height: 1.4; 9 | //$content-line-height: 1.5; 10 | //$body-heading-line-height: 1.15; 11 | 12 | //// 13 | //// Colors 14 | //// 15 | 16 | //$white: #fff; 17 | 18 | //$grey-dk-000: #959396; 19 | //$grey-dk-100: #5c5962; 20 | //$grey-dk-200: #44434d; 21 | //$grey-dk-250: #302d36; 22 | //$grey-dk-300: #27262b; 23 | 24 | //$grey-lt-000: #f5f6fa; 25 | //$grey-lt-100: #eeebee; 26 | //$grey-lt-200: #ecebed; 27 | //$grey-lt-300: #e6e1e8; 28 | 29 | //$purple-000: #7253ed; 30 | //$purple-100: #5e41d0; 31 | //$purple-200: #4e26af; 32 | //$purple-300: #381885; 33 | 34 | //$blue-000: #2c84fa; 35 | //$blue-100: #2869e6; 36 | //$blue-200: #264caf; 37 | //$blue-300: #183385; 38 | 39 | //$green-000: #41d693; 40 | //$green-100: #11b584; 41 | //$green-200: #009c7b; 42 | //$green-300: #026e57; 43 | 44 | //$yellow-000: #ffeb82; 45 | //$yellow-100: #fadf50; 46 | //$yellow-200: #f7d12e; 47 | //$yellow-300: #e7af06; 48 | 49 | //$red-000: #f77e7e; 50 | //$red-100: #f96e65; 51 | //$red-200: #e94c4c; 52 | //$red-300: #dd2e2e; 53 | 54 | //$body-background-color: $white; 55 | //$sidebar-color: $grey-lt-000; 56 | //$search-background-color: $white; 57 | //$table-background-color: $white; 58 | //$code-background-color: $grey-lt-000; 59 | 60 | //$body-text-color: $grey-dk-100; 61 | //$body-heading-color: $grey-dk-300; 62 | //$search-result-preview-color: $grey-dk-000; 63 | //$nav-child-link-color: $grey-dk-100; 64 | //$link-color: $purple-000; 65 | //$btn-primary-color: $purple-100; 66 | //$base-button-color: #f7f7f7; 67 | 68 | //// 69 | //// Spacing 70 | //// 71 | 72 | //$spacing-unit: 1rem; // 1rem == 16px 73 | 74 | //$spacers: ( 75 | //sp-0: 0, 76 | //sp-1: $spacing-unit * 0.25, 77 | //sp-2: $spacing-unit * 0.5, 78 | //sp-3: $spacing-unit * 0.75, 79 | //sp-4: $spacing-unit, 80 | //sp-5: $spacing-unit * 1.5, 81 | //sp-6: $spacing-unit * 2, 82 | //sp-7: $spacing-unit * 2.5, 83 | //sp-8: $spacing-unit * 3, 84 | //sp-9: $spacing-unit * 3.5, 85 | //sp-10: $spacing-unit * 4 86 | //); 87 | 88 | //$sp-1: map-get($spacers, sp-1); // 0.25 rem == 4px 89 | //$sp-2: map-get($spacers, sp-2); // 0.5 rem == 8px 90 | //$sp-3: map-get($spacers, sp-3); // 0.75 rem == 12px 91 | //$sp-4: map-get($spacers, sp-4); // 1 rem == 16px 92 | //$sp-5: map-get($spacers, sp-5); // 1.5 rem == 24px 93 | //$sp-6: map-get($spacers, sp-6); // 2 rem == 32px 94 | //$sp-7: map-get($spacers, sp-7); // 2.5 rem == 40px 95 | //$sp-8: map-get($spacers, sp-8); // 3 rem == 48px 96 | //$sp-9: map-get($spacers, sp-9); // 4 rem == 48px 97 | //$sp-10: map-get($spacers, sp-10); // 4.5 rem == 48px 98 | 99 | //// 100 | //// Borders 101 | //// 102 | 103 | //$border: 1px solid; 104 | //$border-radius: 4px; 105 | //$border-color: $grey-lt-100; 106 | 107 | //// 108 | //// Grid system 109 | //// 110 | 111 | //$gutter-spacing: $sp-6; 112 | //$gutter-spacing-sm: $sp-4; 113 | //$nav-width: 264px; 114 | //$nav-width-md: 248px; 115 | //$content-width: 800px; 116 | //$header-height: 60px; 117 | //$search-results-width: 500px; 118 | 119 | //// 120 | //// Media queries in pixels 121 | //// 122 | 123 | //$media-queries: ( 124 | //xs: 320px, 125 | //sm: 500px, 126 | //md: $content-width, 127 | //lg: $content-width + $nav-width, 128 | //xl: 1400px 129 | //); 130 | -------------------------------------------------------------------------------- /_sass/labels.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Labels (not the form kind) 3 | // 4 | 5 | .label, 6 | .label-blue { 7 | display: inline-block; 8 | padding-top: 0.16em; 9 | padding-right: 0.42em; 10 | padding-bottom: 0.16em; 11 | padding-left: 0.42em; 12 | margin-right: $sp-1; 13 | margin-left: $sp-1; 14 | color: $white; 15 | text-transform: uppercase; 16 | vertical-align: middle; 17 | background-color: $blue-100; 18 | @include fs-2; 19 | } 20 | 21 | .label-green { 22 | background-color: $green-200; 23 | } 24 | 25 | .label-purple { 26 | background-color: $purple-100; 27 | } 28 | 29 | .label-red { 30 | background-color: $red-200; 31 | } 32 | 33 | .label-yellow { 34 | color: $grey-dk-200; 35 | background-color: $yellow-200; 36 | } 37 | -------------------------------------------------------------------------------- /_sass/layout.scss: -------------------------------------------------------------------------------- 1 | // 2 | // The basic two column layout 3 | // 4 | 5 | .page-wrap { 6 | @include mq(md) { 7 | position: absolute; 8 | top: 0; 9 | left: 0; 10 | display: flex; 11 | width: 100%; 12 | height: 100%; 13 | overflow-x: hidden; 14 | overflow-y: hidden; 15 | } 16 | } 17 | 18 | .side-bar { 19 | z-index: 100; 20 | display: flex; 21 | flex-wrap: wrap; 22 | background-color: $sidebar-color; 23 | 24 | @include mq(md) { 25 | flex-wrap: nowrap; 26 | position: absolute; 27 | width: $nav-width-md; 28 | height: 100%; 29 | flex-direction: column; 30 | border-right: $border $border-color; 31 | align-items: flex-end; 32 | } 33 | 34 | @include mq(lg) { 35 | width: calc((100% - #{$nav-width + $content-width}) / 2 + #{$nav-width}); 36 | min-width: $nav-width; 37 | } 38 | } 39 | 40 | .main-content-wrap { 41 | @include mq(md) { 42 | position: absolute; 43 | top: 0; 44 | left: 0; 45 | width: 100%; 46 | height: 100%; 47 | -webkit-overflow-scrolling: touch; 48 | overflow-x: hidden; 49 | overflow-y: scroll; 50 | } 51 | } 52 | 53 | .main-content { 54 | @include mq(md) { 55 | position: relative; 56 | max-width: $content-width; 57 | margin-left: $nav-width-md; 58 | } 59 | 60 | @include mq(lg) { 61 | margin-left: calc( 62 | (100% - #{$nav-width + $content-width}) / 2 + #{$nav-width} 63 | ); 64 | } 65 | } 66 | 67 | .js-main-content:focus { 68 | outline: none; 69 | } 70 | 71 | .page { 72 | @include container; 73 | padding-top: $gutter-spacing-sm; 74 | padding-bottom: $gutter-spacing-sm; 75 | 76 | @include mq(md) { 77 | padding-top: $gutter-spacing; 78 | padding-bottom: $gutter-spacing; 79 | } 80 | } 81 | 82 | .page-header { 83 | @include container; 84 | display: none; 85 | padding-top: $gutter-spacing-sm; 86 | padding-bottom: $gutter-spacing-sm; 87 | background-color: $sidebar-color; 88 | 89 | @include mq(md) { 90 | display: flex; 91 | justify-content: flex-end; 92 | height: $header-height; 93 | background-color: $body-background-color; 94 | border-bottom: $border $border-color; 95 | } 96 | 97 | &.nav-open { 98 | display: block; 99 | 100 | @include mq(md) { 101 | display: flex; 102 | } 103 | } 104 | } 105 | 106 | .navigation, 107 | .site-header, 108 | .site-footer { 109 | width: 100%; 110 | 111 | @include mq(lg) { 112 | width: $nav-width; 113 | } 114 | } 115 | 116 | .navigation { 117 | @include container; 118 | 119 | @include mq(md) { 120 | padding-top: $sp-8; 121 | padding-bottom: $gutter-spacing-sm; 122 | overflow-y: auto; 123 | flex: 1 1 auto; 124 | } 125 | } 126 | 127 | .site-header { 128 | display: flex; 129 | min-height: $header-height; 130 | align-items: center; 131 | 132 | @include mq(md) { 133 | z-index: 101; 134 | height: $header-height; 135 | max-height: $header-height; 136 | border-bottom: $border $border-color; 137 | } 138 | } 139 | 140 | .site-title { 141 | @include container; 142 | flex-grow: 1; 143 | display: flex; 144 | height: 100%; 145 | align-items: center; 146 | padding-top: $sp-3; 147 | padding-bottom: $sp-3; 148 | color: $body-heading-color; 149 | @include fs-6; 150 | 151 | @include mq(md) { 152 | padding-top: $sp-2; 153 | padding-bottom: $sp-2; 154 | } 155 | } 156 | 157 | @if variable-exists(logo) { 158 | .site-logo { 159 | width: 100%; 160 | height: 100%; 161 | background-image: url($logo); 162 | background-repeat: no-repeat; 163 | background-position: left center; 164 | background-size: contain; 165 | } 166 | } 167 | 168 | .menu-button { 169 | appearance: none; 170 | display: flex; 171 | height: 100%; 172 | padding: $gutter-spacing-sm; 173 | align-items: center; 174 | color: $link-color; 175 | text-transform: uppercase; 176 | background: transparent; 177 | border: 0; 178 | 179 | @include mq(md) { 180 | display: none; 181 | } 182 | } 183 | 184 | // stylelint-disable selector-max-type 185 | 186 | body { 187 | position: relative; 188 | padding-bottom: $sp-10; 189 | 190 | @include mq(md) { 191 | position: static; 192 | padding-bottom: 0; 193 | } 194 | } 195 | 196 | // stylelint-enable selector-max-type 197 | 198 | .site-footer { 199 | @include container; 200 | position: absolute; 201 | bottom: 0; 202 | left: 0; 203 | padding-top: $sp-4; 204 | padding-bottom: $sp-4; 205 | 206 | @include mq(md) { 207 | position: static; 208 | justify-self: end; 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /_sass/navigation.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Main nav, breadcrumb, etc... 3 | // 4 | .navigation-list { 5 | padding: 0; 6 | margin-top: 0; 7 | margin-bottom: 0; 8 | list-style: none; 9 | } 10 | 11 | .navigation-list-child-list { 12 | padding-left: $sp-3; 13 | list-style: none; 14 | 15 | .navigation-list-link { 16 | color: $nav-child-link-color; 17 | } 18 | 19 | .navigation-list-item { 20 | position: relative; 21 | 22 | &::before { 23 | position: absolute; 24 | margin-top: 0.3em; 25 | margin-left: -0.8em; 26 | color: rgba($body-text-color, 0.3); 27 | content: "- "; 28 | } 29 | 30 | &.active { 31 | &::before { 32 | color: $body-text-color; 33 | } 34 | } 35 | } 36 | } 37 | 38 | .navigation-list-item { 39 | @include fs-4; 40 | margin: 0; 41 | 42 | @include mq(md) { 43 | @include fs-3; 44 | } 45 | 46 | .navigation-list-child-list { 47 | display: none; 48 | } 49 | 50 | &.active { 51 | .navigation-list-child-list { 52 | display: block; 53 | } 54 | } 55 | } 56 | 57 | .navigation-list-link { 58 | display: block; 59 | padding-top: $sp-1; 60 | padding-bottom: $sp-1; 61 | 62 | &.active { 63 | font-weight: 600; 64 | color: $body-heading-color; 65 | text-decoration: none; 66 | } 67 | } 68 | 69 | // Small screen nav 70 | 71 | .main-nav { 72 | display: none; 73 | 74 | &.nav-open { 75 | display: block; 76 | } 77 | @include mq(md) { 78 | display: block; 79 | } 80 | } 81 | 82 | .aux-nav { 83 | align-self: center; 84 | } 85 | 86 | // Breadcrumb nav 87 | .breadcrumb-nav { 88 | @include mq(md) { 89 | margin-top: -$sp-4; 90 | } 91 | } 92 | 93 | .breadcrumb-nav-list { 94 | padding-left: 0; 95 | margin-bottom: $sp-3; 96 | list-style: none; 97 | } 98 | 99 | .breadcrumb-nav-list-item { 100 | display: table-cell; 101 | @include fs-2; 102 | 103 | &::before { 104 | display: none; 105 | } 106 | 107 | &::after { 108 | display: inline-block; 109 | margin-right: $sp-2; 110 | margin-left: $sp-2; 111 | color: $grey-dk-000; 112 | content: "/"; 113 | } 114 | 115 | &:last-child { 116 | &::after { 117 | content: ""; 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /_sass/overrides.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Custom overrides from a user. 3 | // 4 | -------------------------------------------------------------------------------- /_sass/search.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Search input and autocomplete 3 | // 4 | 5 | .search { 6 | position: relative; 7 | z-index: 99; 8 | flex-grow: 1; 9 | height: 100%; 10 | margin-bottom: $sp-3; 11 | 12 | @include mq(md) { 13 | margin-bottom: 0; 14 | } 15 | } 16 | 17 | .search-input-wrap { 18 | display: flex; 19 | height: 100%; 20 | padding: $sp-2; 21 | background-color: $search-background-color; 22 | border-radius: $border-radius; 23 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08); 24 | 25 | @include mq(md) { 26 | padding-top: 0; 27 | padding-right: 0; 28 | padding-bottom: 0; 29 | padding-left: 0; 30 | background-color: $body-background-color; 31 | border-radius: 0; 32 | box-shadow: none; 33 | } 34 | } 35 | 36 | .search-input { 37 | align-self: center; 38 | width: 100%; 39 | padding-top: $sp-1; 40 | padding-bottom: $sp-1; 41 | background-color: $search-background-color; 42 | border-top: 0; 43 | border-right: 0; 44 | border-bottom: 0; 45 | border-left: 0; 46 | order: 2; 47 | @include fs-4; 48 | 49 | &:focus { 50 | outline: 0; 51 | box-shadow: none; 52 | 53 | + .search-icon { 54 | fill: $link-color; 55 | } 56 | } 57 | 58 | @include mq(md) { 59 | background-color: $body-background-color; 60 | @include fs-3; 61 | } 62 | } 63 | 64 | .search-icon { 65 | align-self: center; 66 | margin-right: $sp-2; 67 | fill: $grey-dk-000; 68 | order: 1; 69 | } 70 | 71 | .search-results-wrap { 72 | position: absolute; 73 | z-index: 100; 74 | display: none; 75 | width: 100%; 76 | background: $search-background-color; 77 | border-radius: $border-radius; 78 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08); 79 | 80 | &.active { 81 | display: block; 82 | } 83 | 84 | @include mq(md) { 85 | width: $search-results-width; 86 | } 87 | } 88 | 89 | .search-results-list { 90 | padding-left: 0; 91 | margin-top: $sp-1; 92 | margin-bottom: $sp-1; 93 | list-style: none; 94 | @include fs-4; 95 | 96 | @include mq(md) { 97 | @include fs-3; 98 | } 99 | } 100 | 101 | .search-results-list-item { 102 | padding: 0; 103 | margin: 0; 104 | } 105 | 106 | .search-result { 107 | display: block; 108 | padding-top: $sp-1; 109 | padding-right: $sp-3; 110 | padding-bottom: $sp-1; 111 | padding-left: $sp-3; 112 | 113 | &:hover, 114 | &.active { 115 | background-color: $sidebar-color; 116 | } 117 | 118 | @include mq(md) { 119 | padding-right: $sp-4; 120 | padding-left: $sp-4; 121 | } 122 | } 123 | 124 | .search-result-title { 125 | display: block; 126 | padding-top: $sp-2; 127 | padding-right: $sp-4; 128 | padding-bottom: $sp-2; 129 | 130 | @include mq(sm) { 131 | display: inline-block; 132 | width: 40%; 133 | word-wrap: break-word; 134 | vertical-align: top; 135 | } 136 | } 137 | 138 | .search-result-rel-url { 139 | display: block; 140 | overflow: hidden; 141 | color: $search-result-preview-color; 142 | text-overflow: ellipsis; 143 | white-space: nowrap; 144 | @include fs-1; 145 | } 146 | 147 | .search-result-preview { 148 | display: block; 149 | padding-top: $sp-2; 150 | padding-bottom: $sp-2; 151 | padding-left: $sp-4; 152 | color: $search-result-preview-color; 153 | border-left: $border; 154 | border-left-color: $border-color; 155 | @include fs-2; 156 | 157 | @include mq(sm) { 158 | display: inline-block; 159 | width: 60%; 160 | vertical-align: top; 161 | } 162 | } 163 | 164 | .search-result-highlight { 165 | font-weight: bold; 166 | color: $link-color; 167 | } 168 | -------------------------------------------------------------------------------- /_sass/support/_functions.scss: -------------------------------------------------------------------------------- 1 | @function rem($size, $unit: "") { 2 | $remSize: $size / $root-font-size; 3 | 4 | @if ($unit == false) { 5 | @return #{$remSize}; 6 | } @else { 7 | @return #{$remSize}rem; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /_sass/support/_variables.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Typography 3 | // 4 | 5 | $body-font-family: -apple-system, BlinkMacSystemFont, "helvetica neue", 6 | helvetica, roboto, noto, "segoe ui", arial, sans-serif !default; 7 | $mono-font-family: "SFMono-Regular", Menlo, Consolas, Monospace !default; 8 | $root-font-size: 16px !default; // Base font-size for rems 9 | $body-line-height: 1.4 !default; 10 | $content-line-height: 1.5 !default; 11 | $body-heading-line-height: 1.15 !default !default; 12 | 13 | // 14 | // Colors 15 | // 16 | 17 | $white: #fff !default; 18 | 19 | $grey-dk-000: #959396 !default; 20 | $grey-dk-100: #5c5962 !default; 21 | $grey-dk-200: #44434d !default; 22 | $grey-dk-250: #302d36 !default; 23 | $grey-dk-300: #27262b !default; 24 | 25 | $grey-lt-000: #f5f6fa !default; 26 | $grey-lt-100: #eeebee !default; 27 | $grey-lt-200: #ecebed !default; 28 | $grey-lt-300: #e6e1e8 !default; 29 | 30 | $purple-000: #7253ed !default; 31 | $purple-100: #5e41d0 !default; 32 | $purple-200: #4e26af !default; 33 | $purple-300: #381885 !default; 34 | 35 | $blue-000: #2c84fa !default; 36 | $blue-100: #2869e6 !default; 37 | $blue-200: #264caf !default; 38 | $blue-300: #183385 !default; 39 | 40 | $green-000: #41d693 !default; 41 | $green-100: #11b584 !default; 42 | $green-200: #009c7b !default; 43 | $green-300: #026e57 !default; 44 | 45 | $yellow-000: #ffeb82 !default; 46 | $yellow-100: #fadf50 !default; 47 | $yellow-200: #f7d12e !default; 48 | $yellow-300: #e7af06 !default; 49 | 50 | $red-000: #f77e7e !default; 51 | $red-100: #f96e65 !default; 52 | $red-200: #e94c4c !default; 53 | $red-300: #dd2e2e !default; 54 | 55 | $body-background-color: $white !default; 56 | $sidebar-color: $grey-lt-000 !default; 57 | $search-background-color: $white !default; 58 | $table-background-color: $white !default; 59 | $code-background-color: $grey-lt-000 !default; 60 | 61 | $body-text-color: $grey-dk-100 !default; 62 | $body-heading-color: $grey-dk-300 !default; 63 | $search-result-preview-color: $grey-dk-000 !default; 64 | $nav-child-link-color: $grey-dk-100 !default; 65 | $link-color: $purple-000 !default; 66 | $btn-primary-color: $purple-100 !default; 67 | $base-button-color: #f7f7f7 !default; 68 | 69 | // 70 | // Spacing 71 | // 72 | 73 | $spacing-unit: 1rem; // 1rem == 16px 74 | 75 | $spacers: ( 76 | sp-0: 0, 77 | sp-1: $spacing-unit * 0.25, 78 | sp-2: $spacing-unit * 0.5, 79 | sp-3: $spacing-unit * 0.75, 80 | sp-4: $spacing-unit, 81 | sp-5: $spacing-unit * 1.5, 82 | sp-6: $spacing-unit * 2, 83 | sp-7: $spacing-unit * 2.5, 84 | sp-8: $spacing-unit * 3, 85 | sp-9: $spacing-unit * 3.5, 86 | sp-10: $spacing-unit * 4, 87 | ) !default; 88 | 89 | $sp-1: map-get($spacers, sp-1) !default; // 0.25 rem == 4px 90 | $sp-2: map-get($spacers, sp-2) !default; // 0.5 rem == 8px 91 | $sp-3: map-get($spacers, sp-3) !default; // 0.75 rem == 12px 92 | $sp-4: map-get($spacers, sp-4) !default; // 1 rem == 16px 93 | $sp-5: map-get($spacers, sp-5) !default; // 1.5 rem == 24px 94 | $sp-6: map-get($spacers, sp-6) !default; // 2 rem == 32px 95 | $sp-7: map-get($spacers, sp-7) !default; // 2.5 rem == 40px 96 | $sp-8: map-get($spacers, sp-8) !default; // 3 rem == 48px 97 | $sp-9: map-get($spacers, sp-9) !default; // 4 rem == 48px 98 | $sp-10: map-get($spacers, sp-10) !default; // 4.5 rem == 48px 99 | 100 | // 101 | // Borders 102 | // 103 | 104 | $border: 1px solid !default; 105 | $border-radius: 4px !default; 106 | $border-color: $grey-lt-100 !default; 107 | 108 | // 109 | // Grid system 110 | // 111 | 112 | $gutter-spacing: $sp-6 !default; 113 | $gutter-spacing-sm: $sp-4 !default; 114 | $nav-width: 264px !default; 115 | $nav-width-md: 248px !default; 116 | $content-width: 800px !default; 117 | $header-height: 60px !default; 118 | $search-results-width: 500px !default; 119 | 120 | // 121 | // Media queries in pixels 122 | // 123 | 124 | $media-queries: ( 125 | xs: 320px, 126 | sm: 500px, 127 | md: $content-width, 128 | lg: $content-width + $nav-width, 129 | xl: 1400px, 130 | ) !default; 131 | -------------------------------------------------------------------------------- /_sass/support/mixins/_buttons.scss: -------------------------------------------------------------------------------- 1 | // Colored button 2 | 3 | @mixin btn-color($fg, $bg) { 4 | color: $fg; 5 | background-color: darken($bg, 2%); 6 | background-image: linear-gradient(lighten($bg, 5%), darken($bg, 2%)); 7 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), 0 4px 10px rgba(0, 0, 0, 0.12); 8 | 9 | &:hover, 10 | &.zeroclipboard-is-hover { 11 | color: $fg; 12 | background-color: darken($bg, 4%); 13 | background-image: linear-gradient((lighten($bg, 2%), darken($bg, 4%))); 14 | } 15 | 16 | &:active, 17 | &.selected, 18 | &.zeroclipboard-is-active { 19 | background-color: darken($bg, 5%); 20 | background-image: none; 21 | box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15); 22 | } 23 | 24 | &.selected:hover { 25 | background-color: darken($bg, 10%); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /_sass/support/mixins/_layout.scss: -------------------------------------------------------------------------------- 1 | // Media query 2 | 3 | // Media query mixin 4 | // Usage: 5 | // @include mq(md) { 6 | // ..medium and up styles 7 | // } 8 | @mixin mq($name) { 9 | // Retrieves the value from the key 10 | $value: map-get($media-queries, $name); 11 | 12 | // If the key exists in the map 13 | @if $value != null { 14 | // Prints a media query based on the value 15 | @media (min-width: rem($value)) { 16 | @content; 17 | } 18 | } @else { 19 | @warn "No value could be retrieved from `#{$media-query}`. " 20 | + "Please make sure it is defined in `$media-queries` map."; 21 | } 22 | } 23 | 24 | // Responsive container 25 | 26 | @mixin container { 27 | padding-right: $gutter-spacing-sm; 28 | padding-left: $gutter-spacing-sm; 29 | 30 | @include mq(md) { 31 | padding-right: $gutter-spacing; 32 | padding-left: $gutter-spacing; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /_sass/support/mixins/_typography.scss: -------------------------------------------------------------------------------- 1 | // Font size 2 | 3 | @mixin fs-1 { 4 | font-size: 9px !important; 5 | 6 | @include mq(sm) { 7 | font-size: 10px !important; 8 | } 9 | } 10 | 11 | @mixin fs-2 { 12 | font-size: 11px !important; 13 | 14 | @include mq(sm) { 15 | font-size: 12px !important; 16 | } 17 | } 18 | 19 | @mixin fs-3 { 20 | font-size: 12px !important; 21 | 22 | @include mq(sm) { 23 | font-size: 14px !important; 24 | } 25 | } 26 | 27 | @mixin fs-4 { 28 | font-size: 14px !important; 29 | 30 | @include mq(sm) { 31 | font-size: 16px !important; 32 | } 33 | } 34 | 35 | @mixin fs-5 { 36 | font-size: 16px !important; 37 | 38 | @include mq(sm) { 39 | font-size: 18px !important; 40 | } 41 | } 42 | 43 | @mixin fs-6 { 44 | font-size: 18px !important; 45 | 46 | @include mq(sm) { 47 | font-size: 24px !important; 48 | } 49 | } 50 | 51 | @mixin fs-7 { 52 | font-size: 24px !important; 53 | 54 | @include mq(sm) { 55 | font-size: 32px !important; 56 | } 57 | } 58 | 59 | @mixin fs-8 { 60 | font-size: 32px !important; 61 | 62 | @include mq(sm) { 63 | font-size: 36px !important; 64 | } 65 | } 66 | 67 | @mixin fs-9 { 68 | font-size: 36px !important; 69 | 70 | @include mq(sm) { 71 | font-size: 42px !important; 72 | } 73 | } 74 | 75 | @mixin fs-10 { 76 | font-size: 42px !important; 77 | 78 | @include mq(sm) { 79 | font-size: 48px !important; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /_sass/support/mixins/mixins.scss: -------------------------------------------------------------------------------- 1 | @import "./layout"; 2 | @import "./buttons"; 3 | @import "./typography"; 4 | -------------------------------------------------------------------------------- /_sass/support/support.scss: -------------------------------------------------------------------------------- 1 | @import "./variables"; 2 | @import "./functions"; 3 | @import "./mixins/mixins"; 4 | -------------------------------------------------------------------------------- /_sass/tables.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Tables 3 | // 4 | // stylelint-disable max-nesting-depth, selector-no-type, selector-max-type 5 | 6 | .table-wrapper { 7 | display: block; 8 | width: 100%; 9 | max-width: 100%; 10 | margin-bottom: $sp-5; 11 | overflow-x: auto; 12 | border-radius: $border-radius; 13 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 3px 10px rgba(0, 0, 0, 0.08); 14 | } 15 | 16 | table { 17 | display: table; 18 | min-width: 100%; 19 | border-collapse: separate; 20 | } 21 | 22 | th, 23 | td { 24 | @include fs-3; 25 | min-width: 120px; 26 | padding-top: $sp-2; 27 | padding-right: $sp-3; 28 | padding-bottom: $sp-2; 29 | padding-left: $sp-3; 30 | background-color: $table-background-color; 31 | border-bottom: $border rgba($border-color, 0.5); 32 | border-left: $border $border-color; 33 | 34 | &:first-of-type { 35 | border-left: 0; 36 | } 37 | } 38 | 39 | tbody { 40 | tr { 41 | &:last-of-type { 42 | th, 43 | td { 44 | border-bottom: 0; 45 | } 46 | 47 | td { 48 | padding-bottom: $sp-3; 49 | } 50 | } 51 | } 52 | } 53 | 54 | thead { 55 | th { 56 | border-bottom: $border $border-color; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /_sass/typography.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Typography 3 | // 4 | // stylelint-disable primer/selector-no-utility, primer/no-override, selector-no-type, selector-max-type 5 | 6 | h1, 7 | .text-alpha { 8 | @include fs-8; 9 | font-weight: 300; 10 | } 11 | 12 | h2, 13 | .text-beta { 14 | @include fs-6; 15 | } 16 | 17 | h3, 18 | .text-gamma { 19 | @include fs-5; 20 | } 21 | 22 | h4, 23 | .text-delta { 24 | @include fs-2; 25 | font-weight: 300; 26 | text-transform: uppercase; 27 | letter-spacing: 0.1em; 28 | } 29 | 30 | h5, 31 | .text-epsilon { 32 | @include fs-3; 33 | color: $grey-dk-200; 34 | } 35 | 36 | h6, 37 | .text-zeta { 38 | @include fs-2; 39 | color: $grey-dk-200; 40 | } 41 | 42 | li { 43 | .highlight { 44 | margin-top: $sp-2; 45 | } 46 | } 47 | 48 | .text-small { 49 | @include fs-2; 50 | } 51 | 52 | .text-mono { 53 | font-family: $mono-font-family !important; 54 | } 55 | 56 | .text-center { 57 | text-align: center !important; 58 | } 59 | -------------------------------------------------------------------------------- /_sass/utilities/_layout.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable primer/selector-no-utility, primer/no-override 2 | // 3 | // Utility classes for layout 4 | // 5 | 6 | // Display 7 | 8 | .d-block { 9 | display: block !important; 10 | } 11 | .d-flex { 12 | display: flex !important; 13 | } 14 | .d-inline { 15 | display: inline !important; 16 | } 17 | .d-inline-block { 18 | display: inline-block !important; 19 | } 20 | .d-none { 21 | display: none !important; 22 | } 23 | 24 | @each $media-query in map-keys($media-queries) { 25 | @for $i from 1 through length($spacers) { 26 | @include mq($media-query) { 27 | $size: #{map-get($spacers, sp-#{$i - 1})}; 28 | $scale: #{$i - 1}; 29 | 30 | // .d-sm-block, .d-md-none, .d-lg-inline 31 | .d-#{$media-query}-block { 32 | display: block !important; 33 | } 34 | .d-#{$media-query}-flex { 35 | display: flex !important; 36 | } 37 | .d-#{$media-query}-inline { 38 | display: inline !important; 39 | } 40 | .d-#{$media-query}-inline-block { 41 | display: inline-block !important; 42 | } 43 | .d-#{$media-query}-none { 44 | display: none !important; 45 | } 46 | } 47 | } 48 | } 49 | 50 | // Vertical alignment 51 | 52 | .v-align-baseline { 53 | vertical-align: baseline !important; 54 | } 55 | .v-align-bottom { 56 | vertical-align: bottom !important; 57 | } 58 | .v-align-middle { 59 | vertical-align: middle !important; 60 | } 61 | .v-align-text-bottom { 62 | vertical-align: text-bottom !important; 63 | } 64 | .v-align-text-top { 65 | vertical-align: text-top !important; 66 | } 67 | .v-align-top { 68 | vertical-align: top !important; 69 | } 70 | -------------------------------------------------------------------------------- /_sass/utilities/_lists.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Utility classes for lists 3 | // 4 | 5 | // stylelint-disable primer/selector-no-utility, primer/no-override, selector-max-type 6 | 7 | .list-style-none { 8 | padding: 0 !important; 9 | margin: 0 !important; 10 | list-style: none !important; 11 | 12 | li { 13 | &::before { 14 | display: none !important; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /_sass/utilities/_spacing.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Utility classes for margins and padding 3 | // 4 | 5 | // scss-lint:disable SpaceAfterPropertyName 6 | // stylelint-disable block-opening-brace-space-after, block-opening-brace-space-before, primer/selector-no-utility, primer/no-override 7 | 8 | // Margin spacer utilities 9 | 10 | @for $i from 1 through length($spacers) { 11 | $size: #{map-get($spacers, sp-#{$i - 1})}; 12 | $scale: #{$i - 1}; 13 | 14 | // .m-0, .m-1, .m-2... 15 | .m-#{$scale} { 16 | margin: #{$size} !important; 17 | } 18 | .mt-#{$scale} { 19 | margin-top: #{$size} !important; 20 | } 21 | .mr-#{$scale} { 22 | margin-right: #{$size} !important; 23 | } 24 | .mb-#{$scale} { 25 | margin-bottom: #{$size} !important; 26 | } 27 | .ml-#{$scale} { 28 | margin-left: #{$size} !important; 29 | } 30 | 31 | .mx-#{$scale} { 32 | margin-right: #{$size} !important; 33 | margin-left: #{$size} !important; 34 | } 35 | 36 | .my-#{$scale} { 37 | margin-top: #{$size} !important; 38 | margin-bottom: #{$size} !important; 39 | } 40 | 41 | .mxn-#{$scale} { 42 | margin-right: -#{$size} !important; 43 | margin-left: -#{$size} !important; 44 | } 45 | } 46 | 47 | .mx-auto { 48 | margin-right: auto !important; 49 | margin-left: auto !important; 50 | } 51 | 52 | @each $media-query in map-keys($media-queries) { 53 | @for $i from 1 through length($spacers) { 54 | @include mq($media-query) { 55 | $size: #{map-get($spacers, sp-#{$i - 1})}; 56 | $scale: #{$i - 1}; 57 | 58 | // .m-sm-0, .m-md-1, .m-lg-2... 59 | .m-#{$media-query}-#{$scale} { 60 | margin: #{$size} !important; 61 | } 62 | .mt-#{$media-query}-#{$scale} { 63 | margin-top: #{$size} !important; 64 | } 65 | .mr-#{$media-query}-#{$scale} { 66 | margin-right: #{$size} !important; 67 | } 68 | .mb-#{$media-query}-#{$scale} { 69 | margin-bottom: #{$size} !important; 70 | } 71 | .ml-#{$media-query}-#{$scale} { 72 | margin-left: #{$size} !important; 73 | } 74 | 75 | .mx-#{$media-query}-#{$scale} { 76 | margin-right: #{$size} !important; 77 | margin-left: #{$size} !important; 78 | } 79 | 80 | .my-#{$media-query}-#{$scale} { 81 | margin-top: #{$size} !important; 82 | margin-bottom: #{$size} !important; 83 | } 84 | 85 | .mxn-#{$media-query}-#{$scale} { 86 | margin-right: -#{$size} !important; 87 | margin-left: -#{$size} !important; 88 | } 89 | } 90 | } 91 | } 92 | 93 | // Padding spacer utilities 94 | 95 | @for $i from 1 through length($spacers) { 96 | $size: #{map-get($spacers, sp-#{$i - 1})}; 97 | $scale: #{$i - 1}; 98 | 99 | // .p-0, .p-1, .p-2... 100 | .p-#{$scale} { 101 | padding: #{$size} !important; 102 | } 103 | .pt-#{$scale} { 104 | padding-top: #{$size} !important; 105 | } 106 | .pr-#{$scale} { 107 | padding-right: #{$size} !important; 108 | } 109 | .pb-#{$scale} { 110 | padding-bottom: #{$size} !important; 111 | } 112 | .pl-#{$scale} { 113 | padding-left: #{$size} !important; 114 | } 115 | 116 | .px-#{$scale} { 117 | padding-right: #{$size} !important; 118 | padding-left: #{$size} !important; 119 | } 120 | 121 | .py-#{$scale} { 122 | padding-top: #{$size} !important; 123 | padding-bottom: #{$size} !important; 124 | } 125 | } 126 | 127 | @each $media-query in map-keys($media-queries) { 128 | @include mq($media-query) { 129 | @for $i from 1 through length($spacers) { 130 | $size: #{map-get($spacers, sp-#{$i - 1})}; 131 | $scale: #{$i - 1}; 132 | 133 | // .p-sm-0, .p-md-1, .p-lg-2... 134 | .p-#{$media-query}-#{$scale} { 135 | padding: #{$size} !important; 136 | } 137 | .pt-#{$media-query}-#{$scale} { 138 | padding-top: #{$size} !important; 139 | } 140 | .pr-#{$media-query}-#{$scale} { 141 | padding-right: #{$size} !important; 142 | } 143 | .pb-#{$media-query}-#{$scale} { 144 | padding-bottom: #{$size} !important; 145 | } 146 | .pl-#{$media-query}-#{$scale} { 147 | padding-left: #{$size} !important; 148 | } 149 | 150 | .px-#{$media-query}-#{$scale} { 151 | padding-right: #{$size} !important; 152 | padding-left: #{$size} !important; 153 | } 154 | 155 | .py-#{$media-query}-#{$scale} { 156 | padding-top: #{$size} !important; 157 | padding-bottom: #{$size} !important; 158 | } 159 | } 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /_sass/utilities/_typography.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Utility classes for typography 3 | // 4 | 5 | // stylelint-disable primer/selector-no-utility, primer/no-override 6 | 7 | .fs-1 { 8 | @include fs-1; 9 | } 10 | 11 | .fs-2 { 12 | @include fs-2; 13 | } 14 | 15 | .fs-3 { 16 | @include fs-3; 17 | } 18 | 19 | .fs-4 { 20 | @include fs-4; 21 | } 22 | 23 | .fs-5 { 24 | @include fs-5; 25 | } 26 | 27 | .fs-6 { 28 | @include fs-6; 29 | } 30 | 31 | .fs-7 { 32 | @include fs-7; 33 | } 34 | 35 | .fs-8 { 36 | @include fs-8; 37 | } 38 | 39 | .fs-9 { 40 | @include fs-9; 41 | } 42 | 43 | .fs-10 { 44 | @include fs-10; 45 | } 46 | 47 | .fw-300 { 48 | font-weight: 300 !important; 49 | } 50 | 51 | .fw-400 { 52 | font-weight: 400 !important; 53 | } 54 | 55 | .fw-500 { 56 | font-weight: 500 !important; 57 | } 58 | 59 | .fw-700 { 60 | font-weight: 700 !important; 61 | } 62 | 63 | .lh-0 { 64 | line-height: 0 !important; 65 | } 66 | 67 | .lh-default { 68 | line-height: $body-line-height; 69 | } 70 | 71 | .lh-tight { 72 | line-height: $body-heading-line-height; 73 | } 74 | 75 | .ls-5 { 76 | letter-spacing: 0.05em !important; 77 | } 78 | 79 | .ls-10 { 80 | letter-spacing: 0.1em !important; 81 | } 82 | 83 | .ls-0 { 84 | letter-spacing: 0 !important; 85 | } 86 | 87 | .text-uppercase { 88 | text-transform: uppercase !important; 89 | } 90 | 91 | // stylelint-enable primer/selector-no-utility 92 | -------------------------------------------------------------------------------- /_sass/utilities/utilities.scss: -------------------------------------------------------------------------------- 1 | @import "./colors"; 2 | @import "./layout"; 3 | @import "./typography"; 4 | @import "./lists"; 5 | @import "./spacing"; 6 | -------------------------------------------------------------------------------- /_sass/vendor/normalize.scss/README.md: -------------------------------------------------------------------------------- 1 | # normalize.scss v0.1.0 2 | 3 | Normalize.scss is the SCSS version of [normalize.css](http://necolas.github.io/normalize.css), a customisable CSS file that makes browsers render all elements more consistently and in line with modern standards. 4 | 5 | [View the normalize.css test file](http://necolas.github.io/normalize.css/latest/test.html) 6 | 7 | ## Install 8 | 9 | * [npm](http://npmjs.org/): `npm install --save normalize.scss` 10 | * [Component(1)](https://github.com/component/component/): `component install guerrero/normalize.scss` 11 | * [Bower](http://bower.io/): `bower install --save normalize.scss` 12 | * Download: Go to [this link](https://raw.githubusercontent.com/guerrero/normalize.scss/master/normalize.scss), press right-click on the page and choose "Save as..." 13 | 14 | No other styles should come before Normalize.scss. 15 | 16 | It's recommendable to modify `normalize.scss` to suit it to your project 17 | 18 | ## What does it do? 19 | 20 | * Preserves useful defaults, unlike many CSS resets. 21 | * Normalizes styles for a wide range of elements. 22 | * Corrects bugs and common browser inconsistencies. 23 | * Improves usability with subtle improvements. 24 | * Explains what code does using detailed comments. 25 | 26 | ## Browser support 27 | 28 | * Google Chrome (latest) 29 | * Mozilla Firefox (latest) 30 | * Mozilla Firefox 4 31 | * Opera (latest) 32 | * Apple Safari 6+ 33 | * Internet Explorer 8+ 34 | 35 | [Normalize.css v1 provides legacy browser 36 | support](https://github.com/necolas/normalize.css/tree/v1) (IE 6+, Safari 4+), 37 | but is no longer actively developed. 38 | 39 | ## Extended details 40 | 41 | Additional detail and explanation of the esoteric parts of normalize.css. 42 | 43 | #### `pre, code, kbd, samp` 44 | 45 | The `font-family: monospace, monospace` hack fixes the inheritance and scaling 46 | of font-size for preformated text. The duplication of `monospace` is 47 | intentional. [Source](http://en.wikipedia.org/wiki/User:Davidgothberg/Test59). 48 | 49 | #### `sub, sup` 50 | 51 | Normally, using `sub` or `sup` affects the line-box height of text in all 52 | browsers. [Source](http://gist.github.com/413930). 53 | 54 | #### `svg:not(:root)` 55 | 56 | Adding `overflow: hidden` fixes IE9's SVG rendering. Earlier versions of IE 57 | don't support SVG, so we can safely use the `:not()` and `:root` selectors that 58 | modern browsers use in the default UA stylesheets to apply this style. [SVG 59 | Mailing List discussion](http://lists.w3.org/Archives/Public/public-svg-wg/2008JulSep/0339.html) 60 | 61 | #### `input[type="search"]` 62 | 63 | The search input is not fully stylable by default. In Chrome and Safari on 64 | OSX/iOS you can't control `font`, `padding`, `border`, or `background`. In 65 | Chrome and Safari on Windows you can't control `border` properly. It will apply 66 | `border-width` but will only show a border color (which cannot be controlled) 67 | for the outer 1px of that border. Applying `-webkit-appearance: textfield` 68 | addresses these issues without removing the benefits of search inputs (e.g. 69 | showing past searches). 70 | 71 | #### `legend` 72 | 73 | Adding `border: 0` corrects an IE 8–11 bug where `color` (yes, `color`) is not 74 | inherited by `legend`. 75 | 76 | ## Acknowledgements 77 | 78 | Normalize.scss is a project by [Alex Guerrero](https://github.com/guerrero) based on [normalize.css](http://necolas.github.io/normalize.css) from [Nicolas Gallagher](https://github.com/necolas), co-created with [Jonathan Neal](https://github.com/jonathantneal). 79 | -------------------------------------------------------------------------------- /_sass/vendor/normalize.scss/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_args": [ 3 | [ 4 | "normalize.scss", 5 | "/Users/pmarsceill/_projects/just-the-docs" 6 | ] 7 | ], 8 | "_from": "normalize.scss@*", 9 | "_id": "normalize.scss@0.1.0", 10 | "_inCache": true, 11 | "_installable": true, 12 | "_location": "/normalize.scss", 13 | "_nodeVersion": "0.10.32", 14 | "_npmUser": { 15 | "email": "alexguerrero1092@gmail.com", 16 | "name": "alexguerrero" 17 | }, 18 | "_npmVersion": "2.0.2", 19 | "_phantomChildren": {}, 20 | "_requested": { 21 | "name": "normalize.scss", 22 | "raw": "normalize.scss", 23 | "rawSpec": "", 24 | "scope": null, 25 | "spec": "*", 26 | "type": "range" 27 | }, 28 | "_requiredBy": [ 29 | "#DEV:/" 30 | ], 31 | "_resolved": "https://registry.npmjs.org/normalize.scss/-/normalize.scss-0.1.0.tgz", 32 | "_shasum": "4a21dc25bd4c019c857785f829b658aba2a8f9ab", 33 | "_shrinkwrap": null, 34 | "_spec": "normalize.scss", 35 | "_where": "/Users/pmarsceill/_projects/just-the-docs", 36 | "author": "", 37 | "bugs": { 38 | "url": "https://github.com/guerrero/normalize.scss/issues" 39 | }, 40 | "dependencies": {}, 41 | "description": "Normalize.scss as a node packaged module", 42 | "devDependencies": {}, 43 | "directories": {}, 44 | "dist": { 45 | "shasum": "4a21dc25bd4c019c857785f829b658aba2a8f9ab", 46 | "tarball": "https://registry.npmjs.org/normalize.scss/-/normalize.scss-0.1.0.tgz" 47 | }, 48 | "files": [ 49 | "normalize.scss" 50 | ], 51 | "gitHead": "d67d517e28615a873066438af1d4845c157c9baf", 52 | "homepage": "https://github.com/guerrero/normalize.scss", 53 | "license": "MIT", 54 | "maintainers": [ 55 | { 56 | "name": "alexguerrero", 57 | "email": "alexguerrero1092@gmail.com" 58 | } 59 | ], 60 | "name": "normalize.scss", 61 | "optionalDependencies": {}, 62 | "readme": "ERROR: No README data found!", 63 | "repository": { 64 | "type": "git", 65 | "url": "git://github.com/guerrero/normalize.scss.git" 66 | }, 67 | "scripts": {}, 68 | "style": "normalize.scss", 69 | "version": "0.1.0" 70 | } 71 | -------------------------------------------------------------------------------- /assets/css/dark-mode-preview.scss: -------------------------------------------------------------------------------- 1 | --- 2 | # this ensures Jekyll reads the file to be transformed into CSS later 3 | # only Main files contain this front matter, not partials. 4 | --- 5 | 6 | {% if site.logo %} 7 | $logo: "{{ site.logo | absolute_url }}"; 8 | {% endif %} 9 | 10 | // 11 | // Import external dependencies 12 | // 13 | 14 | @import "./vendor/normalize.scss/normalize.scss"; 15 | 16 | // 17 | // Import Just the Docs scss 18 | // 19 | 20 | // Support 21 | @import "./support/support"; 22 | 23 | // 24 | // Import custom color scheme scss 25 | // 26 | 27 | @import "./color_schemes/dark.scss"; 28 | 29 | // Modules 30 | @import "./base"; 31 | @import "./layout"; 32 | @import "./content"; 33 | @import "./navigation"; 34 | @import "./typography"; 35 | @import "./labels"; 36 | @import "./buttons"; 37 | @import "./search"; 38 | @import "./tables"; 39 | @import "./code"; 40 | @import "./utilities/utilities"; 41 | 42 | // 43 | // Import custom overrides 44 | // 45 | @import "./custom/custom"; 46 | -------------------------------------------------------------------------------- /assets/css/just-the-docs.scss: -------------------------------------------------------------------------------- 1 | --- 2 | # this ensures Jekyll reads the file to be transformed into CSS later 3 | # only Main files contain this front matter, not partials. 4 | --- 5 | 6 | {% if site.logo %} 7 | $logo: "{{ site.logo | absolute_url }}"; 8 | {% endif %} 9 | 10 | // 11 | // Import external dependencies 12 | // 13 | 14 | @import "./vendor/normalize.scss/normalize.scss"; 15 | 16 | // 17 | // Import Just the Docs scss 18 | // 19 | 20 | // Support 21 | @import "./support/support"; 22 | 23 | // 24 | // Import custom overrides 25 | // 26 | 27 | @import "./custom/custom"; 28 | 29 | // 30 | // Import custom color scheme scss 31 | // 32 | 33 | {% if site.color_scheme == "dark" %} 34 | @import "./color_schemes/dark.scss"; 35 | {% endif %} 36 | 37 | // Modules 38 | @import "./base"; 39 | @import "./layout"; 40 | @import "./content"; 41 | @import "./navigation"; 42 | @import "./typography"; 43 | @import "./labels"; 44 | @import "./buttons"; 45 | @import "./search"; 46 | @import "./tables"; 47 | @import "./code"; 48 | @import "./utilities/utilities"; 49 | @import "./overrides"; 50 | -------------------------------------------------------------------------------- /assets/images/Cmakesetup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/assets/images/Cmakesetup.png -------------------------------------------------------------------------------- /assets/images/Vulkan_170px_Dec16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/assets/images/Vulkan_170px_Dec16.jpg -------------------------------------------------------------------------------- /assets/images/just-the-docs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/assets/images/just-the-docs.png -------------------------------------------------------------------------------- /assets/images/sdl_dll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/assets/images/sdl_dll.png -------------------------------------------------------------------------------- /assets/images/search.svg: -------------------------------------------------------------------------------- 1 | Search 2 | -------------------------------------------------------------------------------- /assets/images/vs_compile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/assets/images/vs_compile.png -------------------------------------------------------------------------------- /assets/js/dark-mode-preview.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", function () { 2 | const toggleDarkMode = document.querySelector(".js-toggle-dark-mode") 3 | const cssFile = document.querySelector('[rel="stylesheet"]') 4 | const originalCssRef = cssFile.getAttribute("href") 5 | const darkModeCssRef = originalCssRef.replace( 6 | "just-the-docs.css", 7 | "dark-mode-preview.css" 8 | ) 9 | const buttonCopy = ["Return to the light side", "Preview dark color scheme"] 10 | const updateButtonText = function (toggleDarkMode) { 11 | toggleDarkMode.textContent === buttonCopy[0] 12 | ? (toggleDarkMode.textContent = buttonCopy[1]) 13 | : (toggleDarkMode.textContent = buttonCopy[0]) 14 | } 15 | 16 | jtd.addEvent(toggleDarkMode, "click", function () { 17 | if (cssFile.getAttribute("href") === originalCssRef) { 18 | cssFile.setAttribute("href", darkModeCssRef) 19 | updateButtonText(toggleDarkMode) 20 | } else { 21 | cssFile.setAttribute("href", originalCssRef) 22 | updateButtonText(toggleDarkMode) 23 | } 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /assets/js/search-data.json: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | { 4 | {% assign comma = false %} 5 | {% for page in site.html_pages %}{% if page.search_exclude != true %}{% if comma == true%},{% endif %}"{{ forloop.index0 }}": { 6 | "title": "{{ page.title | replace: '&', '&' }}", 7 | "content": "{{ page.content | markdownify | replace: '7Zlbb5swGIZ/DZedsDk1l03SwzpNa5VJba8qBxzwBJgZp4H++plgTiZV2igpiVapUu3XR97viT+TaMYkyq4ZSoKf1MOhBnUv04ypBiEwIdSKP93LS8WxpeAz4slOjTAjr1iKulSXxMNppyOnNOQk6YoujWPs8o6GGKOrbrcFDburJsjHPWHmorCvPhCPB6V6Dp1Gv8HED6qVgT0qWyJUdZZPkgbIo6uWZFxqxoRRystSlE1wWJhX+VKOu3qjtd4YwzF/z4Dr5P7u9c+tecdvHmB+b39frBZncpYXFC7lA2vQDsV843mxZZ5LH+y/y2Kf4wWN+Vm6jtKF6ACcJGsaRcmX/8Oq8+6zXKQp5iGZ1xti6vx9RTx9uWhPnjca7OwJMrqMPVyYpIvmVUA4niXILVpXgmmhBTwKRQ3Uo18w4zh7Mw6gjq74WGAaYc5y0UUOMAwJhPxEAEfWVw1fwJRa0GLLlhqSSPv11E3URUEG/gMQwOOF4DL2SYxPO+Bg1A24YQ0dcPN4Az6h8dpsdtoxN61ji7m1IeaKSSJDJUVxEeLsosidwgsce7I4dUOUpsTteiX8YPlj4es3q6o+SZvXlWnWqeWyVi6OvV72VRwW6R4xH/Ntx1c/Ei2nrQ1GVxrDIeLkpbuNTe7LFe4oWfNdnea21Qk0NJQApnTJXCxHtdOzMpFpKsSoJJQ+9CZaw1A/9u582AfiIyO8xMOxZPWp1dTQUVTyNioHhaqMyvaL0Vb4zCHhM2GXGejsCp+jTATfB58IPcpb3ZKiQ3oIPJ0enuJ+SKJk8JPeVrJ7fQC0T3r4mSf9ec+q3yTOf41vj84rAw7t1ajn1dX4UQiz6Y+jc8sEQ7tVbaBlV8rnzyQqXqKPzS5LH9yuTS9W+8yprYQqM+X2lAo6CbXJr4dPqc4ppFRDPaLAnu5zPcwOfJ8Dxhd8/aT4Bd/nwLfpG4b/F77RKcBnWW/kz4/CZ+vKvcX6ZPgO9VXHDvDtESKgD0qH8oZomTvSYaln3Pm+6BDV5teUsnvzm5Rx+Q8= -------------------------------------------------------------------------------- /diagrams/chapter0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/chapter0.png -------------------------------------------------------------------------------- /diagrams/chapter1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/chapter1.png -------------------------------------------------------------------------------- /diagrams/chapter2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/chapter2.png -------------------------------------------------------------------------------- /diagrams/chapter3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/chapter3.png -------------------------------------------------------------------------------- /diagrams/chapter4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/chapter4.png -------------------------------------------------------------------------------- /diagrams/chapter5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/chapter5.png -------------------------------------------------------------------------------- /diagrams/cityrender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/cityrender.png -------------------------------------------------------------------------------- /diagrams/colorTriangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/colorTriangle.png -------------------------------------------------------------------------------- /diagrams/commandtimeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/commandtimeline.png -------------------------------------------------------------------------------- /diagrams/compute_grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/compute_grid.png -------------------------------------------------------------------------------- /diagrams/descriptors.drawio: -------------------------------------------------------------------------------- 1 | 7Vpdk5owFP01PG4HCCA+6qptZ7Yzne706zFKRLrR0BBX6a9vAkEgQdc6wLRs9UFyE0hyzj03N0ED3G+PbymMNx9IgLBhm8HRADPDti0bjPiPsKS5xfNAbghpFMhGpeEx+oWk0ZTWfRSgpNaQEYJZFNeNK7LboRWr2SCl5FBvtia43msMQ6QZHlcQ69avUcA2udW3R6X9HYrCTdGz5Y3zmiVcPYWU7HeyP8MGzkx88+otLJ4lJ5psYEAOlU7B3AD3lBCWX22P9wgLbAvY8vsWZ2pP46Zox665AXhyHCwt5o4CDoUsEso2JCQ7iOeldZrND4knmLxUtnkgJOZGixt/IMZSySvcM8JNG7bFsnZNduyeYEKzHsHcE19uTxglT6hSMxuLL6/R5yWnmpA9XcmRS3bEBFREuaciskWMprwBRRiy6LnONZQuE57anW79SCLeq21K93ZdSZ50bsc0649gkIaIybtK8CeUwrTSLBYNkgv9mM39LG5rzy/yERSlCialKfOPZl+R8D5DvJfQfXmaoWRFo5gR+oiY5kqlowjWD5uIoccYZnQdeOBQnCLCuEI9tE3TdpucwluY/KO70Tr7XHKWZ0QZOl70DVkLnDqWYCTLhzIcWIWIN5VQ4Cm+UHWnChMXgbZvESWPJLGoXWN0nIgQ2IZQOYA0/Sbuf+MWxe/ycVlhdqyVUlnqSOC+XAoyfXWk+atJ8jU5TDAmK8iQYXuYD2+6pDUSvZ97EdYzcO6SDPIJb2D58TEDoKjnVyE7QaI4wQNc8rW2RhLEUbjj1ysOHeK4ToWbR3wxm8iKbRQEeeBGvFu4zJ4naJIRiD/cnRruTI5NeoPlN9JSOKempdNqLDso1p6zGrsz3wBzbNV0dmfnxVtDdNGErNcJYhqffxbwdIarAe8jT0gGHPFO0a2PiAf8AaUhwO4nD/HGdcY0JlrKQ0ZKXgHcy3mI2r4YV1t5SIFvRZdmHkqn+/UaiaBbqnRACnU9hQfnSoXaLSi06GsYCgX9KNT3blPoLaIAmiisVymKaxP1VkRhaUj+w6JwehKFun12uhOFo4nCzkXxfitOgGwPboVz75aJ+HkVAjmdVvQiEDAkgbj9CGQE6oy5oDuBuJpAwGtcNRzQoyiAfpD2juAg0fDlk2HdbfWFbhK51W9XNNfz4Izc+urt6zy4XdEw1miYfl4s5p+qxzdnTmJe8PUWkNE2dw0eCrqCxtF3WO8/TN7O/wpkfHAmf6gg4zUA08Y5haMnFH+Rz2gLR9MGsQkadYG5CRpPg2aZirNQkW+8CM7wQ93IUgTdsFHpTM/6ijPNuXH/s5MHldHL7DQppw123CElyY48ye06SQbq0YrbWZLsXH4PkL34VCX0AFOy11+IvrAGqCJigss23NtSgo81vjLftVRYbwo/eqalHNgOZmNhmeO6W/a5sSi4On8GOByc1dXU6xNnS8O5fqw0XJivjRutwKzvQsArcWdw7cvXVnDWNzXZsolo8j83NPSteNMhRUu5IS+W//3LU5XyD5Zg/hs= -------------------------------------------------------------------------------- /diagrams/descriptors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/descriptors.png -------------------------------------------------------------------------------- /diagrams/empireTextured.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/empireTextured.png -------------------------------------------------------------------------------- /diagrams/empireUntextured.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/empireUntextured.png -------------------------------------------------------------------------------- /diagrams/fullscene.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/fullscene.png -------------------------------------------------------------------------------- /diagrams/greenTriangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/greenTriangle.png -------------------------------------------------------------------------------- /diagrams/indirectperf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/indirectperf.png -------------------------------------------------------------------------------- /diagrams/metafor/bloom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/bloom.png -------------------------------------------------------------------------------- /diagrams/metafor/cascades.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/cascades.png -------------------------------------------------------------------------------- /diagrams/metafor/characters.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/characters.png -------------------------------------------------------------------------------- /diagrams/metafor/chardepth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/chardepth.png -------------------------------------------------------------------------------- /diagrams/metafor/city.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/city.png -------------------------------------------------------------------------------- /diagrams/metafor/deferred_env.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/deferred_env.png -------------------------------------------------------------------------------- /diagrams/metafor/deferred_global.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/deferred_global.png -------------------------------------------------------------------------------- /diagrams/metafor/deferred_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/deferred_light.png -------------------------------------------------------------------------------- /diagrams/metafor/desert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/desert.png -------------------------------------------------------------------------------- /diagrams/metafor/fulldraw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/fulldraw.png -------------------------------------------------------------------------------- /diagrams/metafor/lightfx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/lightfx.png -------------------------------------------------------------------------------- /diagrams/metafor/overdraw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/overdraw.png -------------------------------------------------------------------------------- /diagrams/metafor/rdc_compute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/rdc_compute.png -------------------------------------------------------------------------------- /diagrams/metafor/renderdoc_full_city.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/renderdoc_full_city.png -------------------------------------------------------------------------------- /diagrams/metafor/rest_forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/rest_forest.png -------------------------------------------------------------------------------- /diagrams/metafor/rgp_global.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/rgp_global.png -------------------------------------------------------------------------------- /diagrams/metafor/rgp_occupancy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/rgp_occupancy.png -------------------------------------------------------------------------------- /diagrams/metafor/shadows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/shadows.png -------------------------------------------------------------------------------- /diagrams/metafor/transparent_composite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/transparent_composite.png -------------------------------------------------------------------------------- /diagrams/metafor/transparents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/metafor/transparents.png -------------------------------------------------------------------------------- /diagrams/monkeyGlitch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/monkeyGlitch.png -------------------------------------------------------------------------------- /diagrams/monkeyGood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/monkeyGood.png -------------------------------------------------------------------------------- /diagrams/novus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/novus.png -------------------------------------------------------------------------------- /diagrams/redTriangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/redTriangle.png -------------------------------------------------------------------------------- /diagrams/spinTriangle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/spinTriangle.gif -------------------------------------------------------------------------------- /diagrams/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/test.png -------------------------------------------------------------------------------- /diagrams/texmonkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/texmonkey.png -------------------------------------------------------------------------------- /diagrams/vkcommands.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /diagrams/vkcommands.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/diagrams/vkcommands.png -------------------------------------------------------------------------------- /diagrams/vkcommandsync.drawio: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /docs/chapter-0/building_project.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Building Project 4 | parent: "0. Initial Setup" 5 | grand_parent: Legacy VkGuide, Vulkan 1.1 6 | nav_order: 2 7 | auto_comments: 0. Comments 8 | --- 9 | 10 | # Building the project 11 | 12 | Start by syncing the Git project at . 13 | The all-chapters branch contains the example code for the entire project, and the starting-point branch contains the initial empty project setup. I recommend you sync both branches to different folders, and if at one point you get stuck, check how the code works in the all-chapters code. 14 | If you want a direct download to the code without using Git just download from these direct links. 15 | 16 | [All Chapters](https://github.com/vblanco20-1/vulkan-guide/archive/all-chapters.zip) 17 | 18 | [Starting Point](https://github.com/vblanco20-1/vulkan-guide/archive/starting-point.zip) 19 | 20 | 21 | You will need Visual Studio to build the project. The code in the project should work cross-platform, but this guide is windows-centric. 22 | 23 | First, install the Vulkan SDK . This will contain the development headers and libraries needed to create Vulkan applications. It is put in a global location, so you don't need to worry about where it gets installed. 24 | 25 | Then grab CMake, as it's the build system we are going to use. . 26 | 27 | Once CMake is installed, use CMake-gui to open the project root CMakeLists. Press the Configure button. 28 | At this point, it should give you an error about missing SDL2. 29 | 30 | SDL2 is a library dependency that we need to get separately from the rest. 31 | 32 | You can grab it here . I recommend you just take the development libraries. 33 | Once you have unzipped SDL somewhere, put the root path in the SDL2_dir variable of CMake. 34 | Note, this is not the /libs or similar folder, but the root folder of SDL itself. 35 | 36 | If at this point it complains about not finding Vulkan_INCLUDE_DIR or Vulkan_LIBRARY, make sure you've finished installing the Vulkan SDK, then close and open CMake-Gui and try configuring again. 37 | 38 | Now that the dependencies are set, you can proceed with CMake and Configure then Generate the project files for Visual Studio (or your IDE of choice). 39 | 40 | Cmake should look like this: 41 | 42 | ![cmake]({{site.baseurl}}/assets/images/Cmakesetup.png) 43 | 44 | From Visual Studio, select the vulkan-guide target, set as Startup Project, and you can now compile and execute it by just hitting F5 (start debugging) 45 | 46 | ![vs]({{site.baseurl}}/assets/images/vs_compile.png) 47 | 48 | If you get the message of SDL2 dll missing, go to your sdl folder, lib directory, and grab the dlls from there. Paste them on vulkan_guide/bin/Debug/ folder. (Or Release) . The dll has to be by the side of the vulkan_guide.exe 49 | 50 | ![dll]({{site.baseurl}}/assets/images/sdl_dll.png) 51 | 52 | 53 | Next: [Chapter 0 code walkthrough]({{ site.baseurl }}{% link docs/chapter-0/code_walkthrough.md %}) 54 | 55 | 56 | -------------------------------------------------------------------------------- /docs/chapter-0/chapter-0.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "0. Initial Setup" 4 | nav_order: 102 5 | has_children: true 6 | parent: Legacy VkGuide, Vulkan 1.1 7 | permalink: /docs/chapter_0 8 | auto_comments: 0. Comments 9 | --- 10 | ![chapter0]({{site.baseurl}}/diagrams/chapter0.png) 11 | 12 | 13 | # Chapter 0 index 14 | 15 | 16 | In this chapter, we setup the build toolchain to compile the project 17 | 18 | {: .fs-6 .fw-300 } 19 | 20 | -------------------------------------------------------------------------------- /docs/chapter-1/chapter-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "1. Initialization and Render Loop" 4 | nav_order: 103 5 | has_children: true 6 | parent: Legacy VkGuide, Vulkan 1.1 7 | permalink: /docs/chapter_1 8 | 9 | auto_comments: 1. Comments 10 | --- 11 | ![chapter1]({{site.baseurl}}/diagrams/chapter1.png) 12 | # Chapter 1 : Initialization and render Loop 13 | 14 | In this chapter, we are going to start the tutorial code, and configure the initial Vulkan structures needed to support rendering. 15 | We will also be writing the initial render loop, including command buffer and renderpass management. 16 | {: .fs-6 .fw-300 } 17 | -------------------------------------------------------------------------------- /docs/chapter-1/vulkan_renderpass.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Renderpasses 4 | parent: "1. Initialization and Render Loop" 5 | grand_parent: Legacy VkGuide, Vulkan 1.1 6 | nav_order: 30 7 | --- 8 | 9 | 10 | # Renderpasses 11 | In Vulkan, all of the rendering happens inside a VkRenderPass. It is not possible to do rendering commands outside of a renderpass, but it is possible to do Compute commands without them. 12 | 13 | A VkRenderPass is a Vulkan object that encapsulates the state needed to setup the "target" for rendering, and the state of the images you will be rendering to. 14 | 15 | The renderpass is a concept that only exists in Vulkan. It's there because it allows the driver to know more about the state of the images you render. 16 | 17 | A Renderpass will render into a Framebuffer. The framebuffer links to the images you will render to, and it's used when starting a renderpass to set the target images for rendering. 18 | 19 | The general use of a renderpass when encoding commands is like this: 20 | 21 | ```cpp 22 | vkBeginCommandBuffer(cmd, ...); 23 | 24 | vkCmdBeginRenderPass(cmd, ...); 25 | 26 | //rendering commands go here 27 | 28 | vkCmdEndRenderPass(cmd); 29 | 30 | vkEndCommandBuffer(cmd) 31 | ``` 32 | 33 | When beginning a renderpass, you set the target framebuffer, and the clear color (if available). In this first chapter, we will change the clear color dynamically over time. 34 | 35 | ## Subpasses 36 | A renderpass also contains subpasses, which are a bit like the rendering "steps". They can be very useful in mobile GPUs, as they allow the driver to optimize things quite a lot. 37 | In desktop GPUs, they are less important, so we aren't going to use them. When creating the renderpass, it will only have 1 subpass which is the minimum required for rendering. 38 | 39 | ## Image Layouts 40 | A very important thing that the renderpass does, is that it performs image layout changes when entering and exiting the renderpass. 41 | 42 | Images in the GPU aren't necessarily in the format you would expect. For optimization purposes, the GPUs perform a lot of transformation and reshuffling of them into internal opaque formats. For example, some GPUs will compress textures whenever they can, and will reorder the way the pixels are arranged so that they mipmap better. 43 | In Vulkan, you don't have control of that, but there is control over the layout for the image, which lets the driver transform the image to those optimized internal formats. 44 | 45 | In this first chapter, we are only going to use a few image layouts 46 | 47 | - `VK_IMAGE_LAYOUT_UNDEFINED` : Don't care of what the layout is, can be whatever. 48 | - `VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL` : Image is on a layout optimal to be written into by rendering commands. 49 | - `VK_IMAGE_LAYOUT_PRESENT_SRC_KHR` : Image is on a layout that allows displaying the image on the screen. 50 | - `VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL` : (Used later) Image is on a format optimized to be read from shaders. 51 | 52 | Next: [Setting up render passes]({{ site.baseurl }}{% link docs/chapter-1/vulkan_renderpass_code.md %}) 53 | 54 | {% include comments.html term="1. Comments" %} 55 | -------------------------------------------------------------------------------- /docs/chapter-2/chapter-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "2. The graphics pipeline, Hello Triangle" 4 | nav_order: 104 5 | has_children: true 6 | parent: Legacy VkGuide, Vulkan 1.1 7 | permalink: /docs/chapter_2 8 | 9 | auto_comments: Chapter 2 Comments 10 | --- 11 | ![chapter2]({{site.baseurl}}/diagrams/chapter2.png) 12 | # Chapter 2 : The Graphics Pipeline, Rendering first triangle 13 | 14 | In this chapter, we are going to start rendering triangles. We will setup a render pipeline and use it to draw a hardcoded triangle. 15 | {: .fs-6 .fw-300 } -------------------------------------------------------------------------------- /docs/chapter-2/vulkan_render_pipeline.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: The render pipeline 4 | parent: "2. The graphics pipeline, Hello Triangle" 5 | grand_parent: Legacy VkGuide, Vulkan 1.1 6 | nav_order: 10 7 | --- 8 | 9 | At this point, we managed to setup the main render loop, so it's the time to start rendering things. 10 | 11 | To render things, we have to understand how the Vulkan rendering pipeline works. 12 | 13 | ## The render pipeline 14 | The GPU has a lot of functionality used for rendering objects. This is not only the shaders (programs that run on the GPU), but also functionality for the hardware itself. 15 | 16 | Think of a GPU as an assembly line. It has a lot of different parts doing different things, and the output is pixels rendered on a Framebuffer. This "assembly line" is what we call the graphics pipeline. 17 | 18 | In the graphics pipeline, data and programs come in, and pixels come out. The job of a graphics programmer is to make sure to customize this to get the desired result. 19 | 20 | The full-scale Vulkan graphics pipeline is very complex, so we are going to view a simplified version of it. 21 | 22 | Data -> Vertex Shader -> Rasterization -> Fragment Shader -> Render Output. 23 | 24 | The 2 shader stages will run custom programs that will do anything we want to. The Rasterization, and Render Output are Fixed stages, and we can only tweak their parameters and configuration. 25 | 26 | To begin, we need Data. The Data can be anything we want, and will be our textures, 3d models, material parameters, anything. Everything revolves around data being transformed by the stages until it becomes pixels on the screen. 27 | 28 | The vertex shader is a little program that will run once for every vertex we draw. Its job is to output vertex locations and vertex parameters in the way the GPU understands it for the Rasterization stage. 29 | 30 | The rasterization stage will grab the vertices generated by the Vertex shader, and it will find what pixels are covered by the triangle. These pixels will be sent to the fragment shader. 31 | 32 | The fragment shader takes care of turning those pixels into real colored pixels for the output, running the shader once per pixel that the rasterization stage sends to it. 33 | 34 | With the final colored pixels, we put them on the output framebuffer with the Render Output stage. If we have transparent pixels, this stage will blend them, but if it's opaque rendering, it will just overwrite. 35 | 36 | 37 | ## Shaders 38 | To program the GPU, we use shaders. Shaders are a restricted programming model, with their own language and functionality, that is designed for the parallelism of GPUs, and to mesh with the graphics pipeline well. 39 | 40 | GPUs, unlike CPUs, have a lot of cores, and those cores are very wide cores, executing a lot of things at once. The amount of data a GPU can crunch at once is staggering, so normal CPU style programming models don't work of it. 41 | 42 | On this tutorial, we are focusing on the minimum we need to render, which is Fragment Shaders and Vertex Shaders 43 | 44 | 45 | 46 | Next: [Setting up triangle shaders]({{ site.baseurl }}{% link docs/chapter-2/triangle_walkthrough.md %}) 47 | 48 | {% include comments.html term="Chapter 2 Comments" %} 49 | 50 | -------------------------------------------------------------------------------- /docs/chapter-3/chapter-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "3. Drawing meshes" 4 | nav_order: 105 5 | has_children: true 6 | parent: Legacy VkGuide, Vulkan 1.1 7 | permalink: /docs/chapter_3 8 | 9 | auto_comments: Chapter 3 Comments 10 | --- 11 | ![chapter3]({{site.baseurl}}/diagrams/chapter3.png) 12 | # Chapter 3 : Drawing meshes 13 | 14 | In this chapter, we iterate on the code to turn a hardcoded triangle into real meshes loaded from .obj format. 15 | 16 | 17 | {: .fs-6 .fw-300 } 18 | 19 | -------------------------------------------------------------------------------- /docs/chapter-3/triangle_mesh.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Vertex buffers 4 | parent: "3. Drawing meshes" 5 | grand_parent: Legacy VkGuide, Vulkan 1.1 6 | nav_order: 10 7 | --- 8 | 9 | Right now, we are rendering triangles by hardcoding the vertex arrays in the shader. We are now going to change the code to render the triangles in the same way, but without hardcoding the vertices, using CPU arrays for them, and vertex input layouts. 10 | 11 | ## Vertex buffers 12 | In Vulkan, you can allocate memory visible to the GPU, and read it from the shaders. You can allocate memory for two purposes, for images and buffers. 13 | We have already been using images a bit as part of the render pass and the swapchain, but using them in the shaders can be complicated so we leave it for a later chapter. Images are used mostly for 2d or 3d data, like textures, where you want to access any part of it from the shaders. 14 | 15 | The other type is buffers, which are just a bunch of memory that the GPU can see and write/read to. There are multiple types of buffers, and they can be used in different ways. In here, we are going to create a buffer and use it as a vertex buffer, which will allow the GPU to read the data from the buffer and send it to our vertex shader. 16 | 17 | To read a vertex buffer from a shader, you need to set the vertex input state on the pipeline. This will let Vulkan know how to interpret a given buffer as vertex data. Once this is set up, we will be able to get vertex information into the vertex shader, like vertex colors or vertex positions, automatically. 18 | 19 | This type of buffers work more or less the same as they do on OpenGL and DirectX, if you are familiar with those. 20 | 21 | ## Memory allocation 22 | All buffers and images need to be created on top of a memory allocation. As we don't want to implement a memory allocator in this tutorial, we will be using the library Vulkan Memory Allocator (VMA), created by AMD, which will abstract this for us. 23 | 24 | The number of total allocations is fixed by the driver, and can be a number as low as 1024. This minimum number can be easily exceeded if each buffer or image are placed in their own memory allocation, so a typical strategy is to allocate big chunks of memory from the driver, and then sub-allocate your buffers and images into it, using a library like Vulkan Memory Allocator (VMA) or by implementing the allocator yourself. 25 | 26 | If you look at a desktop computer, you will see that the GPU has separate memory (VRAM) from the main system memory (RAM). These different domains are called heaps. Within these heaps, the driver can expose memory regions optimized for specific use cases, called memory types. Even on integrated GPUs (without dedicated VRAM), multiple memory types might be available from a single heap. Vulkan gives complete control over where to allocate your data, be it on native GPU VRAM, or on the CPU RAM. The VMA library abstracts this slightly for us, but it's still very important to know. 27 | 28 | For now, we are going to be allocating our buffers all on CPU RAM, as it is significantly easier to implement, and at the moment we don't need the performance. 29 | 30 | ## Vertex Input Layout 31 | If you come from OpenGL, you may know about vertex attributes, where you let OpenGL know how should vertex data be read on your vertex shader, and then OpenGL fetches the data for you. 32 | In Vulkan, it works in a very similar way. When you create the pipeline, one of the editable objects is the vertex input layout, which we have left empty for now. We can fill it out to let Vulkan know how to interpret the vertex data for your shader. 33 | 34 | Let's go ahead and implement what we need to turn our hardcoded triangle into a non-hardcoded one! 35 | 36 | Next: [Implementing vertex buffers]({{ site.baseurl }}{% link docs/chapter-3/triangle_mesh_code.md %}) 37 | 38 | 39 | 40 | {% include comments.html term="Chapter 3 Comments" %} -------------------------------------------------------------------------------- /docs/chapter-4/chapter-4.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "4. Buffers, Shader input/output" 4 | nav_order: 106 5 | has_children: true 6 | parent: Legacy VkGuide, Vulkan 1.1 7 | permalink: /docs/chapter_4 8 | 9 | auto_comments: Chapter 4 Comments 10 | --- 11 | ![chapter4]({{site.baseurl}}/diagrams/chapter4.png) 12 | # Chapter 4 : Shader input/output 13 | 14 | In this chapter, we explain how to send data into shaders using Descriptor sets, and how to setup the different types of buffers offered by Vulkan. 15 | We will create descriptor sets to use uniform buffers for our camera data, and we will also set dynamic uniforms and storage-buffers to render a full scene in an efficient way. 16 | 17 | {: .fs-6 .fw-300 } 18 | -------------------------------------------------------------------------------- /docs/chapter-5/chapter-5.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "5. Textures" 4 | nav_order: 107 5 | has_children: true 6 | parent: Legacy VkGuide, Vulkan 1.1 7 | permalink: /docs/chapter_5 8 | 9 | auto_comments: Chapter 5 Comments 10 | --- 11 | ![chapter5]({{site.baseurl}}/diagrams/chapter5.png) 12 | # Chapter 5 : Textures 13 | 14 | In this chapter, we load textures from files and upload them to Vulkan, to then be used when rendering objects. 15 | 16 | {: .fs-6 .fw-300 } 17 | 18 | -------------------------------------------------------------------------------- /docs/extra-chapter/extra-chapter.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Extra Chapter 4 | nav_order: 30 5 | has_children: true 6 | permalink: /docs/extra_chapter 7 | --- 8 | 9 | # Extra chapter 10 | In this chapter, there are general articles that don't fit in the main track. All here is optional, and can be of interest even if it's outside of the tutorial. 11 | 12 | {: .fs-6 .fw-300 } 13 | -------------------------------------------------------------------------------- /docs/gpudriven/gpudriven.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: GPU Driven Rendering 4 | nav_order: 58 5 | has_children: true 6 | permalink: /docs/gpudriven 7 | auto_comments: GPU Driven Rendering 8 | --- 9 | 10 | # GPU Driven Rendering 11 | In this chapter, we are going to continue the evolution of the engine after the 5 core chapters by implementing high performance rendering techniques. 12 | 13 | {: .fs-6 .fw-300 } -------------------------------------------------------------------------------- /docs/introduction/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: introduction 4 | nav_order: 1 5 | has_children: true 6 | permalink: /docs/introduction 7 | 8 | auto_comments: Introduction Comments 9 | --- 10 | 11 | # INTRODUCTION INDEX 12 | 13 | 14 | {: .fs-6 .fw-300 } 15 | -------------------------------------------------------------------------------- /docs/introduction/project_libs.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Project layout and libraries 4 | parent: introduction 5 | nav_order: 99 6 | --- 7 | 8 | ## Project layout 9 | 10 | For the Vulkan engine, we use a specific folder layout. 11 | 12 | - `/assets` will contain textures and 3d models that we use over the guide 13 | - `/bin` is where the executables will get built. We don't use the normal CMake build folders to simplify the paths to assets and shaders 14 | - `/shaders` will contain all our shaders, and their compiled output 15 | - `/chapter-N` folders contain the code for each of the chapters of the guide 16 | - `/third_party` contains all of the libraries we use, vendored in, so all of the source code is readily available 17 | 18 | ## Libraries 19 | 20 | On the engine, we use a set of libraries, most stored in `/third_party`. The only library that isn't vendored-in is SDL 21 | 22 | All the libraries in third-party are vendored-in, and CMake will build them automatically. For SDL, it's required to build it separately from the project, and tell CMake where to find it. 23 | 24 | The Libraries we are using: 25 | - [GLM (openGL Mathematics)](https://github.com/g-truc/glm) Mathematics library, Header only. We use this for its matrix and vector math functionality. It's a library that contains types that are directly compatible with GLSL types in most cases. For example, a `glm::mat4` has similar operations and is directly compatible with a `mat4` in a shader. While it says OpenGL in the name, it works great with Vulkan. 26 | 27 | - [SDL](https://www.libsdl.org/) Windowing and input library, Separately built. SDL is one of the most used libraries to create a window and access input devices in a crossplatform way. SDL works on almost every platform, and is very well supported. Used in Unreal Engine, Unity, Source, and others. We use it in the project to have a easy and fast way to open a window, and have detailed keyboard input. 28 | 29 | - [dear IMGUI](https://github.com/ocornut/imgui) Easy to use immediate Graphical-User-Interface (GUI) library. This allows us to create editable widgets such as sliders and windows for the user interface. It's widely used in the game industry for debug tools. In the project, we use it to create interactive options for rendering. 30 | 31 | - [STB Image](https://github.com/nothings/stb) Image loading library, header only. Small and easy to use library to load image files. It can load common image formats such as BMP, PNG, JPEG, and others. It is part of a set of other similar single-file libraries. 32 | 33 | - [Tiny Obj Loader](https://github.com/tinyobjloader/tinyobjloader) .Obj model loader library, header only. Fast and small library to load the .obj 3d model format that we will use when loading 3d models. 34 | 35 | - [Vk Bootstrap](https://github.com/charles-lunarg/vk-bootstrap/blob/master/src/VkBootstrap.cpp) Abstracts a big amount of boilerplate that Vulkan has when setting up. Most of that code is written once and never touched again, so we will skip most of it using this library. This library simplifies instance creation, swapchain creation, and extension loading. It will be removed from the project eventually in an optional chapter that explains how to initialize that Vulkan boilerplate the "manual" way. 36 | 37 | - [VMA (vulkan memory allocator)](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) Implements memory allocators for Vulkan, header only. In Vulkan, the user has to deal with the memory allocation of buffers, images, and other resources on their own. This can be very difficult to get right in a performant and safe way. Vulkan Memory Allocator does it for us and allows us to simplify the creation of images and other resources. Widely used in personal Vulkan engines or smaller scale projects like emulators. Very high end projects like Unreal Engine or AAA engines write their own memory allocators. 38 | 39 | Next: [Building Project]({{ site.baseurl }}{% link docs/new_chapter_0/building_project.md %}) 40 | 41 | 42 | {% include comments.html term="Introduction Comments" %} 43 | -------------------------------------------------------------------------------- /docs/ko/introduction/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "introduction - ko" 4 | nav_order: 1 5 | has_children: true 6 | permalink: /docs/ko/introduction 7 | parent : "Korean VKGuide" 8 | auto_comments: Introduction Comments 9 | --- 10 | 11 | # INTRODUCTION INDEX 12 | 13 | 14 | {: .fs-6 .fw-300 } 15 | 16 | {% include comments.html term="Vkguide 2 Korean Comments" %} 17 | 18 | -------------------------------------------------------------------------------- /docs/ko/introduction/project_libs.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Project layout and libraries - KO 4 | parent: "introduction - ko" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 99 7 | --- 8 | 9 | ## 프로젝트 레이아웃 10 | 11 | Vulkan 엔진에서는 다음과 같은 폴더 레이아웃을 사용할 것입니다. 12 | 13 | - `/assets`에는 이 가이드에서 사용할 텍스쳐와 3D 모델이 들어있습니다. 14 | - `/bin`은 실행 가능한 파일이 빌드될 곳입니다. 에셋과 셰이더의 경로를 단순하게 하기 위해 일반적인 CMake 빌드 폴더를 사용하지 않습니다. 15 | - `/shaders`는 셰이더와 컴파일된 셰이더가 출력될 곳입니다. 16 | - `/chapter-N`에는 이 가이드의 각 챕터의 코드가 들어있습니다. 17 | - `/third_party`에는 우리가 사용할 모든 라이브러리가 들어있으며, 소스코드에서 바로 사용가능할 수 있습니다. 18 | 19 | ## 라이브러리 20 | 21 | 엔진에서 대부분의 라이브러리는 `/third_part`에 들어가 있습니다. 유일하게 내장되지 않는 예외는 SDL입니다. 22 | 23 | 모든 써드파티 라이브러리가 내장되어 있으며, CMake가 자동으로 빌드합니다. SDL은 프로젝트와 별도로 빌드해야 하며, CMake에게 그 위치를 알려주어야 합니다. 24 | 25 | 사용할 라이브러리의 목록은 다음과 같습니다. 26 | - [GLM (openGL Mathematics)](https://github.com/g-truc/glm) Header only 수학 라이브러리입니다. GLM을 사용해 행렬과 벡터 연산을 수행할 것입니다. 대부분의 상황에서 GLSL 타입과 직접적으로 호환되는 타입들을 갖고 있습니다. 예를 들어, `glm::mat4`는 셰이더에서의 `mat4`와 직접적으로 호환되며 유사한 연산을 할 수 있습니다. 이름에 OpenGL이 들어가 있지만 Vulkan에서도 잘 작동합니다. 27 | 28 | - [SDL](https://www.libsdl.org/) 창(window)와 입력을 받는 라이브러리입니다. 개별적으로 빌드해야 합니다. SDL은 창을 만들어 입력 장치에 접근하는 가장 널리 쓰이는 것 중 하나입니다. SDL은 대부분의 플랫폼을 지원하며 작동합니다. 언리얼 엔진, 유니티, 소스, 그 이외의 다양한 곳에서 사용됩니다. 이 프로젝트에서는 창을 만들고 키보드 입력과 같은 세부사항을 쉽고 빠르게 관리하는 방법으로 SDL을 사용할 것입니다. 29 | 30 | - [dear IMGUI](https://github.com/ocornut/imgui) 사용하기 쉬운 GUI 라이브러리입니다. 이는 슬라이더와 창과 같은 편집 가능한 위젯을 생성할 수 있게 해줍니다. 게임 산업에서 디버그 툴로 널리 사용됩니다. 이 프로젝트에서는 렌더링에 상호작용할 옵션들을 만드는 데 사용됩니다. 31 | 32 | - [STB Image](https://github.com/nothings/stb) 이미지를 로딩하는 header only 라이브러리입니다. 이미지 파일을 로딩하는 데 사용되는 작고 빠른 라이브러리입니다. BMP, JPEG, 그리고 기타 다른 흔한 이미지 포맷들을 로딩할 수 있습니다. 이는 다른 유사한 단일 파일 라이브러리 집합의 일부입니다. 33 | 34 | - [Tiny Obj Loader](https://github.com/tinyobjloader/tinyobjloader) .Obj 모델을 로딩하는 header only 라이브러리입니다. 3D 모델을 불러오는 데 사용할 작고 빠른 라이브러리입니다. 35 | 36 | - [Vk Bootstrap](https://github.com/charles-lunarg/vk-bootstrap/blob/master/src/VkBootstrap.cpp) Vulkan을 초기화할 때 필요한 많은 양의 보일러플레이트(boilerplate)를 추상화해줍니다. 대부분의 코드는 한번만 작성되고 이후 수정할 일이 없기 때문에 이 라이브러리를 사용해 대부분의 과정을 생략할 것입니다. 이 라이브러리는 인스턴스 생성, 스왑체인 생성, 그리고 확장 로딩과 같은 작업을 단순하게 만들어줍니다. 이후 Vulkan을 수동적으로 초기화하는 방법을 설명하는 부록에서는 제거될 것입니다. 37 | 38 | - [VMA (vulkan memory allocator)](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) Vulkan을 위한 메모리 할당자가 구현되어있는 header only 라이브러리입니다. Vulkan에서는 버퍼, 이미지, 그리고 다른 자원들의 메모리 관리를 사용자가 직접 다뤄야 합니다. 이는 성능과 안정성을 동시에 고려하면서 처리하기 매우 어려울 수 있습니다. Vulkan Memory Allocator는 이를 대신 처리하여 이미지나 다른 자원의 생성을 쉽게 수행할 수 있습니다. 개인 Vulkan 엔진이나 에뮬레이터와 같은 소규모 프로젝트에서 널리 사용됩니다. 언리얼 엔진이나 기타 AAA 엔진과 같은 대규모 프로젝트에서는 각자의 메모리 할당자가 구현되어있습니다. 39 | 40 | Next: [Building Project]({{ site.baseurl }}{% link docs/ko/new_chapter_0/building_project.md %}) 41 | 42 | 43 | {% include comments.html term="Vkguide 2 Korean Comments" %} 44 | 45 | -------------------------------------------------------------------------------- /docs/ko/introduction/vulkan_execution.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Vulkan Usage - KO 4 | nav_order: 2 5 | parent: "introduction - ko" 6 | grand_parent: "Korean VKGuide" 7 | --- 8 | 9 | # Vulkan 핵심 객체와 활용 방법 10 | 11 | - `VkInstance` : Vulkan 문맥(context)으로, GPU 드라이버에 접근하는 데 사용됩니다. 12 | - `VkPhysicalDevice` : GPU 그 자체입니다. 기능, 호환성, 메모리 크기, 그 이외의 여러 GPU 세부 사항을 조회하는 데 사용됩니다. 13 | - `VkDevice` : GPU를 실제로 실행하는데 사용할 "논리적인" GPU 문맥입니다. 14 | - `VkBuffer` : GPU가 접근할 수 있는 메모리 묶음입니다. 15 | - `VkImage` : 읽고 쓸 수 있는 텍스쳐입니다. 16 | - `VkPipeline` : 그리기에 필요한 GPU 상태를 담고 있는 개겣입니다.(ex. 셰이더, 래스터화, 깊이 설정) 17 | - `VkRenderPass` : 렌더링할 이미지의 정보를 담고있습니다. 모든 그리기 명령은 렌더패스(renderpass) 내부에서 수행됩니다. 18 | - `VkFrameBuffer` : 렌더패스의 타겟 이미지를 담습니다. 구버전 vkguide에서만 사용됩니다. 19 | - `VkCommandBuffer` : GPU 명령을 기록합니다. (드라이버가 아닌)GPU에서 실행되는 모든 명령은 `VkCommandBuffer`에 기록됩니다. 20 | - `VkQueue` : 명령의 실행 지점입니다. GPU는 다른 속성의 큐 모음을 갖습니다. 어떤 큐는 그래픽 명령만 받으며, 다른 어떤 큐는 메모리 명령만 받습니다. 예를 들어 커맨드 버퍼는 큐에 제출되어 실행되는데, 이는 GPU로 렌더링 명령을 전달합니다. 21 | - `VkDescriptorSet` : `VkBuffer`자원이나 `VkImage`텍스쳐와 같은 데이터를 셰이더로 연결하는 데 필요한 정보를 담습니다. GPU에서의 포인터라고 생각해도 좋습니다. 22 | - `VkSwapchainKHR` : 화면의 이미지를 담는데 사용됩니다. 렌더링 한 것을 시각적으로 볼 수 있는 창에 렌더링 할 수 있게 합니다. `KHR`접미사는 Vulkan 확장의 객체임을 나타냅니다. 여기서는 `Vk_KHR_swapchain`입니다. 23 | - `VkSemaphore` : GPU간 명령 동기화에 사용됩니다. 여러 커맨드 버퍼가 있을 때 하나가 실행되고 그 다음 것이 실행하는 것을 보장하기 위해 사용됩니다. 24 | - `VkFence` : GPU와 CPU를 동기화하는 데 사용됩니다. 커맨드 버퍼가 GPU에서 실행이 완료되었는지를 확인할 때 사용합니다. 25 | 26 | # 고수준 Vulkan 애플리케이션 흐름 27 | 28 | ## 엔진 초기화 29 | 먼저, 모든 것을 초기화합니다. Vulkan을 초기화하기 위해선 `VkInstance`를 생성하는 것부터 시작합니다. `VkInstance`로부터 컴퓨터의 사용 가능한 `VkPhysicalDevice` 핸들의 목록을 조회합니다. 예를 들어, 컴퓨터가 전용 GPU와 통합 그래픽스를 갖는다면, 각각 `VkPhysicalDevice`가 될 수 있습니다. `VkPhysicalDevice`로부터 사용 가능한 기능과 제한 사항을 조회한 후 `VkDevice`를 생성합니다. `VkDevice`에서는 커맨드를 실행하게 해주는 `VkQueue` 핸들을 얻을 수 있습니다. 그 후, `VkSwapchainKHR`을 초기화합니다. `VkQueue` 핸들로 커맨드 버퍼를 할당할 수 있는 객체인 `VkCommandPool`을 생성할 수 있습니다. 30 | 31 | ## 에셋 초기화 32 | 핵심 구조체들이 초기화 되고 나면, 렌더링할 대상에 필요한 자원을 초기화해야합니다. 머테리얼(Material)이 로딩되면 `VkPipeline`의 집합을 생성합니다. 이는 머테리얼을 렌더링하는 데 필요한 셰이더 조합과 파라미터를 담습니다. 메시(Mesh)를 렌더링 하기 위해 메시의 정점 데이터를 `VkBuffer` 자원으로, 그리고 메시의 텍스쳐를 `VkImage` 자원으로 업로드해야 합니다. 이 때 이미지가 "읽을 수 있는" 레이아웃임을 분명히 해야합니다. 또한 주요 렌더링 패스에 대해 `VkRenderPass` 객체를 만들어야 합니다. 예를 들어, 주요 렌더링하는데 사용할 `VkRenderPass`가 있을 수 있고, 그림자 패스에 사용할 `VkRenderPass`가 있을 수 있습니다. 특히 파이프라인 생성은 꽤 비싼 편이기 때문에, 실제 엔진에서는 이러한 작업은 백그라운드 쓰레드에서 병렬화 되어 처리될 수 있습니다. 33 | 34 | ## 렌더링 루프 35 | 이제 렌더링할 준비가 끝났습니다. 먼저 `VkSwapchainKHR`에 렌더링할 이미지를 요청해야 합니다. 그리고 `VkCommandPool`로부터 `VkCommandBuffer`를 할당하거나 이미 할당된 커맨드 버퍼를 재사용해 커맨드를 작성합니다. 다음으로는 `VkRenderPass`를 시작해서 렌더링을 시작합니다. 이는 일반적인 `VkRenderPass` 혹은 동적 렌더링을 사용해 수행할 수 있습니다. 렌더패스는 스왑체인으로부터 받아온 이미지에 렌더링을 수행하도록 지정합니다. 그리고 `VkPipeline`, (셰이더 파라미터에 필요한)`VkDescriptorSet`, 정점 버퍼를 바인딩하고 그리기 호출을 실행할 루프를 만듭니다. 렌더패스에서 그리기가 끝났으면 `VkRenderPass`를 끝냅니다. 렌더링 할 것이 남아있지 않다면 `VkCommandBuffer`도 끝냅니다. 마지막으로 렌더링하기 위해 커맨드 버퍼를 큐로 제출합니다. 그러면 GPU에서 커맨드 버퍼의 명령들의 실행이 시작될 것입니다. 만약 렌더링한 결과를 화면에 표시하고 싶다면, 렌더링한 이미지를 화면에 "표시(present)"해야합니다. 아직 렌더링이 끝나지 않았을 수 있기 때문에, 세마포어(semaphore)를 사용해 렌더링이 끝날 때 까지 화면에 이미지를 표시하는 작업을 대기시켜야 합니다. 36 | 37 | Vulkan에서의 렌더링 루프 의사코드입니다. 38 | 39 | ```cpp 40 | // 스왑체인에 렌더링할 이미지의 인덱스를 요청합니다. 41 | int image_index = request_image(mySwapchain); 42 | 43 | // 커맨드 버퍼를 생성합니다. 44 | VkCommandBuffer cmd = allocate_command_buffer(); 45 | 46 | // 커맨드 버퍼를 초기화합니다. 47 | vkBeginCommandBuffer(cmd, ... ); 48 | 49 | // 스왑체인으로부터 받아온 이미지 인덱스로 새로운 렌더패스를 시작합니다. 50 | // 각 프레임 버퍼는 스왑체인의 이미지를 참조합니다. 51 | vkCmdBeginRenderPass(cmd, main_render_pass, framebuffers[image_index] ); 52 | 53 | // 모든 객체를 렌더링합니다. 54 | for(object in PassObjects){ 55 | 56 | // 객체를 렌더링하는 데 사용되는 구성과 셰이더를 바인딩합니다. 57 | vkCmdBindPipeline(cmd, object.pipeline); 58 | 59 | // 객체를 렌더링하는 데 사용되는 정점과 인덱스 버퍼를 바인딩합니다. 60 | vkCmdBindVertexBuffers(cmd, object.VertexBuffer,...); 61 | vkCmdBindIndexBuffer(cmd, object.IndexBuffer,...); 62 | 63 | // 셰이더 입력으로 사용되는 객체의 디스크립터 셋을 바인딩합니다. 64 | vkCmdBindDescriptorSets(cmd, object.textureDescriptorSet); 65 | vkCmdBindDescriptorSets(cmd, object.parametersDescriptorSet); 66 | 67 | // 그립니다. 68 | vkCmdDraw(cmd,...); 69 | } 70 | 71 | // 렌더패스와 커맨드 버퍼를 끝냅니다. 72 | vkCmdEndRenderPass(cmd); 73 | vkEndCommandBuffer(cmd); 74 | 75 | 76 | // 커맨드 버퍼를 제출하고 GPU에서 실행합니다. 77 | vkQueueSubmit(graphicsQueue, cmd, ...); 78 | 79 | // 렌더링한 이미지를 화면에 표시합니다. 80 | // renderSemaphore는 `cmd`가 실행될 때 까지 이미지를 표시하지 않는 것을 보장합니다. 81 | vkQueuePresent(graphicsQueue, renderSemaphore); 82 | ``` 83 | 84 | Next: [Project files and libraries]({{ site.baseurl }}{% link docs/ko/introduction/project_libs.md %}) 85 | 86 | {% include comments.html term="Vkguide 2 Korean Comments" %} 87 | -------------------------------------------------------------------------------- /docs/ko/introduction/vulkan_overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Vulkan API - KO 4 | nav_order: 1 5 | parent: "introduction - ko" 6 | grand_parent: "Korean VKGuide" 7 | --- 8 | 9 | ![VulkanLogo](/assets/images/Vulkan_170px_Dec16.jpg) 10 | 11 | ## Vulkan 소개 12 | 13 | Vulkan은 크로노스 그룹이 개발한 크로스 플랫폼 그래픽스 API(Application Program Interface)입니다. Vulkan API는 표준 규격이므로 다양한 디바이스, 플랫폼, 그리고 여러 프로그래밍 언어로 구현될 수 있습니다. 14 | 15 | Vulkan은 고성능 멀티쓰레딩 애플리케이션에 사용되도록 설계되었습니다.특히 Vulkan은 명시적인 설계 방식을 채택하여 그래픽 드라이버의 작업을 줄이는 이점을 갖습니다. Vulkan을 올바르게 사용하는 것은 고성능, 저지연, 그리고 일관된 프레임을 얻을 수 있습니다. 16 | 17 | ## Vulkan API 개요 18 | 19 | Vulkan API는 함수 목록, 전달할 인자, 그리고 반환 타입을 제공합니다. 이는 C 언어로 작성되었으며, 대부분의 언어와 호환 될 수 있습니다. 20 | 21 | 이 튜토리얼은 C++로 작성되었지만 Rust 혹은 순수 C와 같은 저수준 언어로 포팅하는 것은 간단할 것입니다. 22 | 23 | ## Vulkan이 필요한 상황 24 | 25 | 만약 주요 병목이 GPU에서 일어난다면, Vulkan을 구현하는 것만으로는 성능이 충분히 향상되지 않아 그만한 가치가 없을 수 있습니다. Vulkan이 OpenGL과 비교하여 상당히 어렵고 종종 개발하는 데 더 오랜 시간이 걸립니다. 26 | 27 | 만약 애플리케이션이 커다란 맵, 동적 월드, 혹은 많은 양의 오브젝트를 담는 CAD 씬을 포함한다면, Vulkan의 멀티쓰레딩을 통해 성능 향상을 기대할 수 있습니다. 28 | 29 | 모바일 환경에서는 파편화 문제가 있을 수 있습니다. 모든 스마트폰이 Vulkan을 지원하는 것은 아니며(특히 구형 기기), 지원하더라도 드라이버 품질에 문제가 있을 수 있습니다. 특히 Vulkan을 지원하는 드라이버가 탑재된 폰은 더 적은 배터리로 더 적은 CPU 오버헤드와 높은 성능을 기대할 수 있습니다. 30 | 31 | ## 크로스 플랫폼 32 | 33 | 모바일과 데스크탑을 모두 지원하는 API라는 점에서 Vulkan의 설계는 다른 그래픽스 API와 비교해 특수한 면이 있습니다. Vulkan의 많은 기능이 선택적이며 사용하려면 명시적으로 활성화해야 합니다. 대부분의 데스크탑 GPU에서는 지원하지만 모바일에서는 지원하지 않는 기능이 있는 것도 흔한 일입니다. 34 | 35 | Vulkan을 모바일과 데스크탑에서 실행할 때, 하나 또는 두 개의 핵심 렌더링 경로를 사용할 수 있습니다. 일반적으로 2개의 렌더링 경로를 사용하는 것이 권장되며, 그렇지 않으면 최적의 성능을 얻기 어려울 수 있습니다. API가 통합되어 있기 때문에 두 렌더링 경로 간 코드를 공유할 수 있다는 것을 의미합니다. 36 | 37 | 이 튜토리얼에서는 데스크탑을 위한 Vulkan을 작성하는 것에 집중할 것이지만, 두 GPU의 차이에 대해서도 다룰 것입니다. 38 | 39 | ## 검증 레이어 40 | 41 | Vulkan API는 방대하고 실수하기 쉽지만, 검증 레이어로 이를 해결할 수 있습니다. 42 | 43 | 검증 레이어는 API의 올바르지 않은 사용을 감지하고 기록하는 선택적 기능입니다. 44 | 45 | 검증 레이어는 함수 호출을 가로채 데이터를 검증하는 방식으로 작동합니다. 만약 모든 데이터가 올바르게 검증되었다면 드라이버에 대한 호출이 정상적으로 수행될 것입니다. 이 과정에서 함수 가로채기와 검증 실행이 성능 하락을 일으킬 수 있다는 점을 유의해야합니다. 46 | 47 | 검증 레이어는 올바르지 않은 구현이나 올바르지 않은 열거형 사용, 동기화 문제, 객체 생성주기와 같은 에러를 잡는 데 유용합니다. 작성한 코드가 요구사항을 준수했는지를 보장하기 위해 개발 도중 검증 레이어를 활성화 하는 것을 추천합니다. 애플리케이션을 실행했을 때 검증 레이어의 오류가 없는 것은 좋은 신호이지만, 이것만으로 다른 하드웨어에서 잘 실행될 것이라고 판단할 수 없습니다. 애플리케이션을 가능한 많은 디바이스에서 실행해보는 것을 권장합니다. 48 | 49 | 중요한 점은 검증 레이어가 초기화되지 않은 메모리와 올바르지 않은 포인터와 같은 버그를 잡아주지는 않는다는 점입니다. 이러한 버그를 잡기 위해서는 Address Sanitizer와 Vanlgrind를 사용하는 편을 추천합니다. 이러한 도구를 사용할 때 그래픽 드라이버는 종종 잘못된 탐지로 출력에 잡음이 생길 수 있습니다. 50 | 51 | ## 사용법과 일반적인 접근 방식 52 | 53 | Vulkan API에서는 대부분의 요소가 직접 생성하고 사용하도록 설계되어있습니다. 이는 이미지, 텍스쳐, 버퍼(정점 데이터와 같은 메모리) 같은 실제 GPU 자원 뿐만 아니라 매우 많은 양의 내부 설정 구조체도 포함합니다. 54 | 55 | 예를 들어, 래스터라이저(rasterizer)와 같은 GPU 고정 함수는 파이프라인 객체에 저장되며, 이 객체는 셰이더와 다른 설정들을 포함합니다. OpenGL과 DX11에서는 이를 렌더링 중 즉석에서 계산합니다. Vulkan에서 이를 사용할 때에는 객체들을 캐싱할 지, 혹은 렌더링 중 즉석에서 만들 지를 생각해야 합니다. 파이프라인과 같은 몇몇 객체들은 생성하는 비용이 비싼 편입니다. 따라서 이를 화면 로딩 시 혹은 백그라운드 쓰레드에서 생성하는 것이 최적입니다. 디스크립터 셋(DescriptorSet)과 같은 다른 객체들은 비용이 낮아 렌더링 중 필요할 때 생성해도 무방합니다. 56 | 57 | Vulkan의 모든 것들은 기본적으로 사전빌드되므로, GPU의 대부분의 상태 검사는 객체를 생성할 때 이루어집니다. 따라서 렌더링 자체의 작업량이 줄어들어 성능이 향상됩니다. 이러한 객체들이 어떻게 만들어지고 사용되는지 잘 이해하면 전체 실행 흐름을 효과적으로 제어하여 프레임을 부드럽게 만들 수 있습니다. 58 | 59 | 실제 GPU 명령을 실행할 때, GPU의 모든 작업은 커맨드 버퍼(CommandBuffer)에 기록되어 큐(Queue)로 제출됩니다. 먼저 커맨드 버퍼를 할당하고, 이를 작성해 큐에 제출하는 것으로 실행할 수 있습니다. 커맨드 버퍼를 큐에 제출하면 GPU에서 해당 명령의 실행이 시작됩니다. 언제 실행이 끝날지를 제어하는 도구도 있습니다. 만약 여러 커맨드 버퍼를 서로 다른 큐에 제출한다면, 병렬로 실행하는 것도 가능합니다. 60 | 61 | Vulkan에는 프레임이라는 개념이 없습니다. 이는 렌더링 방식이 전적으로 개발자에게 맡겨졌다는 의미죠. 중요한 것은 언제 프레임을 화면에 표시할 것인지 이며, 이는 스왑체인(swapchain)을 통해 이루어집니다. 하지만 렌더링한 이미지를 네트워크를 통해 전송하거나, 파일로 이미지를 저장하거나, 스왑체인을 통해 스크린에 이를 표시하는 것에는 근본적인 차이는 없습니다. 62 | 63 | 이는 Vulkan이 완전히 헤드리스(headless)모드로 사용할 수 있다는 것을 의미합니다. 즉, 화면에 아무것도 표시하지 않고 이미지를 렌더링한 후 이미지를 디스크에 저장할 수 있습니다(테스트 하기에 매우 유용하죠!). 혹은 Vulkan을 레이트레이싱과 같은 GPU 연산이나 다른 컴퓨팅 작업을 수행하는 도구로도 사용할 수 있습니다. 64 | 65 | Next: [Vulkan Render flow]({{ site.baseurl }}{% link docs/ko/introduction/vulkan_execution.md %}) 66 | 67 | 68 | {% include comments.html term="Vkguide 2 Korean Comments" %} 69 | -------------------------------------------------------------------------------- /docs/ko/korean.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Korean VKGuide 4 | nav_order: 99 5 | has_children: true 6 | permalink: /docs/ko 7 | auto_comments: Korean VKGuide 8 | --- 9 | 10 | ![scene]({{site.baseurl}}/diagrams/fullscene.png) 11 | 튜토리얼 이후의 예시 사진 12 | 13 | ## VulkanGuide에 오신 것을 환영합니다. 14 | 15 | 새롭게 작성중인 Vulkan Guide에 오신 것을 환영합니다. 이 가이드의 목적은 Vulkan을 올바르게 이해하고 프로젝트에서 일할 수 있는 디딤돌 역할을 하는 것입니다. 렌더링 루프를 하드코딩한 대부분의 예제와 다른 Vulkan 가이드와는 달리 여기서는 동적 렌더링에 집중할 것입니다. 게임 엔진으로서 더 나은 기반으로 작동하도록 하는 것입니다. 16 | 17 | 이 가이드는 게임 렌더링에 집중되었지만, 개념은 CAD와 시각화에도 적용될 수 있습니다. 18 | 19 | 여기서는 C++20을 사용할 것이지만, 복잡한 C++ 기능을 사용하지는 않을 것이기 때문에 C 혹은 Rust도 사용할 수 있습니다. 20 | 21 | OpenGL 혹은 DirectX에 대해 익숙해 3D 그래픽스에 대해 어느정도 알고 있는 사람이 읽는다고 가정합니다. 이 가이드는 선형 대수학과 같은 3D 렌더링 기초를 가르치지는 않을 것입니다. 22 | 23 | 저자에게 연락하려면 `contact@vkguide.dev`로 이메일을 보내주세요. 24 | 25 | 이 코드는 Vulkan 1.3의 기능들을 사용해 엔진 아키텍처와 튜토리얼을 단순화합니다. 만약 구버전을 확인하고 싶다면 [여기]({{ site.baseurl }}{% link docs/old_vkguide.md %})서 확인할 수 있습니다. 26 | 27 | 이 가이드는 코드 정리를 위해 여러 장으로 나뉘어 있습니다. 28 | 29 | - **소개** : Vulkan API와 프로젝트에 사용되는 라이브러리에 대해 설명합니다. 30 | - **0장** : 초기화 코드를 설정합니다. 31 | - **1장** : Vulkan 초기화와 렌더링 루프를 설정합니다.(번쩍이는 색상을 그립니다.) 32 | - **2장** : Vulkan 컴퓨트 셰이더와 그리기를 수행합니다.(컴퓨트 셰이더를 사용해 그리기를 수행합니다.) 33 | - **3장** : Vulkan 메시 드로잉을 수행합니다.(그래픽스 파이프라인을 사용해 메시를 그립니다.) 34 | - **4장** : 텍스쳐와 더 나은 디스크립터 셋 관리를 설명합니다. 35 | - **5장** : 전체 GLTF 씬을 로드하고 고성능의 렌더링을 수행하는 방법을 설명합니다. 36 | 37 | 이 책의 부록은 본 책에는 담지 않는 더 많은 정보를 포함합니다. 그 중 일부는 vkguide의 이전 버전도 있으며, 최신 버전을 사용하는 경우 구식일 수 있으며 해당 글에는 상단에 표시가 있습니다. 38 | 39 | - **GPU 기반 렌더링** : 컴퓨트 셰이더를 사용해 수십만 개의 메시 렌더링하는 법에 대해 설명합니다. 40 | - **부록** : 튜토리얼에서 구현한 엔진의 성능을 올리는 다양한 내용이 있습니다. 41 | 42 | 43 | Next: [Introduction to vulkan]({{ site.baseurl }}{% link docs/ko/introduction/vulkan_overview.md %}) 44 | {% include comments.html term="Index Comments" %} 45 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_0/building_project.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "Building Project - KO" 4 | parent: "0. Project Setup - KO" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 2 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | 10 | # 프로젝트 빌드하기 11 | 12 | 에 있는 Git 프로젝트를 가져오는 것으로 시작합니다. all-chapters 브랜치는 전체 프로젝트의 예시 코드를 포함하며, starting-point 브랜치는 초기 빈 프로젝트를 포함합니다. 두 브랜치를 다른 폴더로 가져와 작업하면서 막힐 때 마다 all-chapters 브랜치의 코드를 확인해보는 방법을 권장합니다. 만약 Git을 사용하지 않고 직접 다운로드 받기를 원한다면 아래 링크를 통해 다운로드 할 수 있습니다. 13 | 14 | [All Chapters](https://github.com/vblanco20-1/vulkan-guide/archive/all-chapters-2.zip) 15 | 16 | [Starting Point](https://github.com/vblanco20-1/vulkan-guide/archive/starting-point-2.zip) 17 | 18 | 프로젝트를 빌드하기 위해 Visual Studio가 필요합니다. 프로젝트의 코드는 크로스 플랫폼으로 작동하지만 이 가이드에서는 Window 중심으로 설명할 것입니다. 19 | 20 | 먼저, Vulkan SDK 를 설치합니다. 이는 Vulkan 애플리케이션을 만드는 데 필요한 헤더와 라이브러리를 담고 있습니다. 이는 전역 위치에 설치되므로 설치위치를 걱정할 필요는 없습니다. 21 | 22 | 그 다음, CMake를 설정합니다. 이는 우리가 사용할 빌드 시스템입니다.. 23 | 24 | CMake가 설치되면 CMake-gui를 사용해 프로젝트 루트 경로의 CMakeLists를 엽니다. 그 후, Configure 버튼을 누릅니다. 25 | 26 | 만약 이 지점에서 Vulkan_INCLUDE_DIR 혹은 Vulkan_LIBRARY를 찾지 못했다는 에러가 발생한다면, Vulkan SDK 설치가 완료되기를 기다리세요. 그리고 CMake-Gui를 재시작 한 후 다시 Configure 버튼을 눌러보세요. 27 | 28 | 이제 의존성이 설정되었습니다. CMake에서 Configure이 되고 나서 Generate를 눌러 Visual Studio(혹은 다른 IDE)에 맞는 프로젝트 파일을 만들 수 있습니다. 29 | 30 | Visual Studio에서 엔진을 시작 프로젝트로 설정한 후, 이제 F5(디버깅 시작)을 눌러 컴파일하고 이를 실행할 수 있습니다. 31 | 32 | ![vs]({{site.baseurl}}/assets/images/vs_compile.png) 33 | 34 | 35 | # Third party 라이브러리 36 | third_party 폴더 하위에는 튜토리얼에서 사용할 여러 다양한 라이브러리가 있습니다. 이 라이브러리들은 소스 코드 형태로 폴더에 포함되어 있습니다. 이 중 일부는 공개 저장소의 코드와 다르게 수정되었거나 추가된 부분이 있습니다. 37 | 38 | 아래는 사용할 라이브러리의 목록입니다. 39 | 40 | - vulkan SDK: third_party 폴더에 없는 것이지만 필수적인 것으로, 위에서 설명한대로 설치해야 합니다. 41 | - vkbootstrap: Vulkan 초기화를 단순하게 만들어주는 라이브러리입니다. 우리가 사용할 GPU를 선택하거나 초기화 구조체를 설정하는 것과 같은 작업을 수행해줍니다. 42 | - VMA: Vulkan Memory Allocator입니다. 이는 GPU 구조체를 위한 고성능 메모리 할당기를 구현합니다. 할당자를 우리가 직접 구현하는 것 대신 이를 사용할 것입니다. 이 라이브러리가 우리의 GPU 메모리를 관리해줄 것입니다. 43 | - SDL: 창을 만들고 입력, 오디오, 기타 다양한 것을 수행할 수 있는 고성능 멀티플랫폼 라이브러리입니다. 이 튜토리얼에서는 SDL의 창 생성과 입력 처리 부분을 사용할 것입니다. 44 | - GLM : 수학 라이브러리입니다. 벡터, 행렬 등을 지원합니다. 45 | - {fmt} : 문자열 포맷팅과 콘솔 출력 라이브러리입니다. 성능이 뛰어나며 문자열 출력과 다양한 포맷팅 옵션을 제공하기 때문에 std::cout 대신 사용할 것입니다. 46 | - stb_image: PNG 혹은 jpeg 이미지를 불러오는 데 사용할 라이브러리입니다. 47 | - dear imgui: 디버깅 인터페이스를 위한 매우 유용한 UI 라이브러리입니다. 타이머나 기타 UI 창을 만들 때 사용할 것입니다. 48 | - fastgltf: 고성능 GLTF 로딩 라이브러리입니다. 49 | 50 | 51 | Next: [ "Code Walkthrough - KO"]({{ site.baseurl }}{% link docs/ko/new_chapter_0/code_walkthrough.md %}) 52 | 53 | {% include comments.html term="Vkguide 2 Korean Comments" %} 54 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_0/chapter-0.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "0. Project Setup - KO" 4 | parent: "Korean VKGuide" 5 | nav_order: 11 6 | has_children: true 7 | permalink: /docs/ko/new_vkguide/chapter_0 8 | auto_comments: Vkguide 2 Beta Comments 9 | --- 10 | ![chapter0]({{site.baseurl}}/diagrams/chapter0.png) 11 | 12 | 13 | 14 | # 0장 15 | 16 | 17 | 이 챕터에서는 프로젝트를 컴파일 하기 위해 필요한 도구들을 빌드할 것입니다. 18 | 19 | {: .fs-6 .fw-300 } 20 | 21 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_1/chapter-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "1. Initializing Vulkan - KO" 4 | parent: "Korean VKGuide" 5 | nav_order: 13 6 | has_children: true 7 | permalink: /docs/ko/new_vkguide/chapter_1 8 | auto_comments: Vkguide 2 Beta Comments 9 | --- 10 | ![chapter1]({{site.baseurl}}/diagrams/chapter1.png) 11 | # 1장 : 초기화와 렌더링 루프 12 | 13 | 이 장에서는 튜토리얼 코드로 시작해 렌더링을 하기 위한 Vulkan 구조체를 초기화합니다. 또한 커맨드 버퍼와 렌더 이미지 관리를 포함한 초기 렌더링 루프를 작성할 것입니다. 14 | {: .fs-6 .fw-300 } 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_1/vulkan_command_flow.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Executing Vulkan Commands 4 | parent: "1. Initializing Vulkan - KO" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 20 7 | --- 8 | 9 | 10 | ![cmake]({{site.baseurl}}/diagrams/vkcommands.png) 11 | 12 | ## Vulkan 명령 실행 13 | OpenGL이나 DirectX11 이전 버전과는 달리 Vulkan에서는 모든 GPU 명령이 커맨드 버퍼(Command buffer)를 통해 전달되며, 큐(Queue)를 통해 실행됩니다. 14 | 15 | 명령을 실행하는 일반적인 흐름은 다음과 같습니다.: 16 | - `VkCommandPool`로부터 `VkCommandBuffer`를 할당합니다. 17 | - `VkCmdXXXXX` 함수를 사용하여 명령을 커맨드 버퍼에 기록합니다. 18 | - `VkQueue`로 커맨드 버퍼를 제출해 명령을 실행을 시작합니다. 19 | 20 | 같은 커맨드 버퍼를 여러 번 제출하는 것도 가능합니다. 많은 튜토리얼과 예제에서는 흔히 커맨드 버퍼를 한번만 작성하여 렌더링 루프에서 매 프레임마다 제출하는 방식을 사용합니다. 하지만 이 튜토리얼에서는 매 프레임마다 명령을 작성할 것이며, 이는 실제 렌더링 엔진의 동작 방식과 더 유사하기 때문입니다. 21 | 22 | Vulkan에서 명령을 기록하는 것은 상대적으로 비용이 적게 듭니다. 일반적으로 비용이 많이 드는 작업은 VkQueueSubmit 호출로, 이 과정에서 드라이버가 커맨드 버퍼의 유효성을 검사하고 GPU에서 실행하기 때문입니다. 23 | 24 | 커맨드 버퍼에서 매우 중요한 점은 병렬로 기록할 수 있다는 것입니다. 여러 쓰레드에서 서로 다른 커맨드 버퍼를 안전하게 기록할 수 있습니다. 이를 위해 각 쓰레드는 최소한 하나의 `VkCommandPool`과 하나의 `VkCommandBuffer`를 가져야 하며, 각 쓰레드가 자신만의 고유한 커맨드 버퍼와 커맨드 풀(Command Pool)을 사용해야 합니다. 올바르게 설정하면 각 쓰레드에서 커맨드 버퍼를 제출할 수 있습니다. `vkQueueSubmit`이 쓰레드 안전(thread-safe)하지 않기 때문에, 하나의 큐에는 한번에 하나의 쓰레드만 명령을 제출할 수 있습니다. 대규모 엔진에서는 흔히 백그라운드 쓰레드에서 제출을 처리하며, 메인 렌더링 루프 쓰레드가 실행될 수 있도록 합니다. 25 | 26 | ## VkQueue 27 | Vulkan에서의 큐는 GPU의 실행 포트입니다. 모든 GPU는 사용가능한 여러 큐를 가지며, 서로 다른 명령을 동시에 실행할 수도 있습니다. 서로 다른 큐에 제출된 명령들은 동시에 실행될 수 있습니다. 이는 메인 프레임 루프와 직접적으로 연관되지 않는 백그라운드 작업을 수행할 때 매우 유용합니다. 이를 위해 백그라운드 작업 전용 `VkQueue`를 생성하여 일반적인 렌더링 작업과 분리할 수 있습니다. 28 | 29 | Vulkan의 모든 큐는 큐 패밀리로부터 파생됩니다. 큐 패밀리는 특정 유형의 큐 그룹이며, 지원하는 명령의 종류가 각기 다릅니다. 30 | 31 | GPU는 각기 다른 큐 패밀리를 지원합니다. 예를 들어 NVIDIA GT 750TI의 경우, 이 [링크](https://vulkan.gpuinfo.org/displayreport.php?id=8859#queuefamilies)에서 확인할 수 있습니다. 이 GPU에는 2개의 큐 패밀리가 있으며, 하나는 모든 기능을 지원하는 16개의 큐로 이루어져 있으며, 다른 하나는 전송(Transfer)만을 지원하는 1개의 큐로 이루어진 큐 패밀리가 있습니다. 반면, 고성능 AMD GPU는 [여기](https://vulkan.gpuinfo.org/displayreport.php?id=24407#queuefamilies)를 참고할 수 있습니다.이 GPU에는 5개의 큐 패밀리가 있으며, 각 유형별로 최대 2개의 큐만 존재합니다. 1개의 큐는 모든 기능을 지원하고, 계산(Compute) 및 전송(Transfer) 작업을 지원하는 2개의 큐, 2개의 전송 전용 큐, 2개의 표시(Present) 전용 큐가 있습니다. 이처럼, 각 GPU가 지원하는 큐 패밀리는 상당히 다를 수 있습니다. 32 | 33 | 대부분의 엔진에서는 3개의 큐 패밀리를 사용하는 것이 일반적입니다. 하나는 프레임을 그리는 데 사용하고, 다른 하나는 비동기 계산(compute), 그리고 다른 하나는 데이터 전송입니다. 이 튜토리얼에서는 단순화를 위해 하나의 큐에서 모든 명령을 실행하겠습니다. 34 | 35 | ## VkCommandPool 36 | `VkCommandPool`은 `VkDevice`를 기반으로 생성되며, 해당 커맨드 풀이 명령을 생성할 큐 패밀리의 인덱스가 필요합니다. 37 | 38 | `VkCommandPool`을 `VkCommandBuffer`의 할당기라고 생각할 수 있습니다. 하나의 풀에서 원하는 만큼 `VkCommandBuffer`를 할당할 수 있지만, 한 번에 하나의 쓰레드만 명령을 기록할 수 있습니다. 만약 멀티쓰레드 환경에서 명령을 기록하고자 한다면 추가적인 `VkCommandPool` 객체가 필요합니다. 이러한 이유로, 해당 커맨드 풀과 쌍으로 구성할 것입니다. 39 | 40 | ## VkCommandBuffer 41 | 42 | GPU의 모든 명령은 `VkCommandBuffer`에 기록됩니다. GPU의 작업을 수행하는 모든 함수는 커맨드 버퍼가 `VkQueueSubmit`을 통해 GPU로 제출될 때까지 실행되지 않습니다. 43 | 44 | 커맨드 버퍼는 준비(Ready) 상태에서부터 시작합니다. 준비 상태에서는 `vkBeginCommandBuffer()`를 호출해 기록(Recording) 상태로 변경할 수 있습니다. 이 상태에서 `vkCmdXXXXX`함수를 호출해 명령을 기록할 수 있습니다. 모든 명령을 기록하고 나면 `vkEndCommandBuffer()`를 호출하여 실행가능한(Executable) 상태로 변경하면 해당 커맨드 버퍼를 GPU에 제출할 수 있습니다. 45 | 46 | 커맨드 버퍼를 제출하려면 제출할 명령과 큐를 지정하여 `vkQueueSubmit()`를 호출합니다. 또한, `vkQueueSubmit`은 여러 개의 커맨드 버퍼를 한 번에 제출할 수도 있습니다. 제출한 모든 커맨드 버퍼는 보류(Pending) 상태로 변환됩니다. 47 | 48 | 커맨드 버퍼가 제출되면 여전히 "유효(alive)"하며 GPU에서 처리되고 있습니다. 이 시점에서는 커맨드 버퍼를 리셋하는 것이 안전하지 않습니다. 커맨드 버퍼를 재설정하고 재사용 하기 전에, GPU가 해당 커맨드 버퍼의 모든 명령을 완료했는 지 확인해야 합니다. 49 | 50 | 커맨드 버퍼를 리셋하기 위해서 `vkResetCommandBuffer()`를 사용합니다. 51 | 52 | 커맨드 버퍼가 실행중인 동안 다음 프레임을 계속 그릴 수 있도록 더블 버퍼링을 수행할 것입니다. 이렇게 하면 GPU가 한 버퍼에서 렌더링 및 처리를 수행하는 동안, 다른 버퍼에서 명령을 기록할 수 있습니다. 53 | 54 | 커맨드 버퍼의 생명주기에 대한 더 자세한 정보는 다음 Vulkan 사양의 관련 글을 참고하세요. 55 | 56 | . 57 | 58 | 59 | Next: [ Setting up Vulkan commands]({{ site.baseurl }}{% link docs/ko/new_chapter_1/vulkan_commands_code.md %}) 60 | 61 | {% include comments.html term="Vkguide 2 Korean Comments" %} 62 | 63 | 64 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_1/vulkan_init_flow.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Vulkan Initialization 4 | parent: "1. Initializing Vulkan - KO" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 1 7 | --- 8 | 9 | 10 | ## Vulkan 초기화 11 | OpenGL과는 달리, Vulkan은 그래픽 명령을 즉시 실행하는 대신 매우 긴 초기화 단계를 거칩니다. 이 초기화 과정을 단축하기 위해 `VkBootstrap` 라이브러리를 사용할 것입니다. 이 라이브러리는 많은 양의 작업을 간소화해줍니다. 12 | 13 | Vulkan은 매우 "직접적인" 제어를 제공하는 매우 명시적인 API입니다. 확장을 불러오거나, 사용할 GPU(들)을 선택하거나, Vulkan 명령에 사용할 초기 `VkInstance`와 `VkDevice` 구조체를 생성해야 합니다. 14 | 15 | Vulkan은 OpenGL과는 달리 전역 상태(global state)가 없습니다. 따라서 모든 API 호출에서 `VkDevice`와 `VkInstance`를 직접 전달해야합니다. 이 가이드에서는 `vulkan-1.dll`을 직접 링크하지만 이는 유일한 방법이 아닙니다. 함수 포인터를 "수동으로" 불러올 수도 있습니다. `vulkan-1.dll`을 링킹하는 것은 확장 함수도 불러오는 것은 아니므로, 별도로 불러와야 합니다. 프로젝트 코드에서는 이러한 확장 함수를 불러올 수 있도록 `Volk` 라이브러리가 제공합니다. 주요 튜토리얼 챕터에서는 이를 사용하지 않을 것이지만 이후 활용할 가능성이 높기 때문에 포함되어 있습니다. 16 | 17 | ## VkInstance 18 | 모든 것의 핵심인 `VkInstance`입니다. 이는 Vulkan API 문맥(Context)을 나타냅니다. `VkInstance`를 생성할 때, 원한다면 검증 레이어를 활성화 할 수 있으며, `VK_KHR_surface`와 같은 필요한 확장도 설정할 수 있습니다. 또한, Vulkan 드라이버에서 오류가 발생하거나 로그를 남겨야 할 때 사용할 로거를 연결할 수도 있습니다. `VkInstance`를 생성할 때 가장 중요한 것은 검증 레이어와 확장을 활성화하는 것입니다. 19 | 20 | 일반적으로 애플리케이션은 전체 실행 동안 단 하나의 `VkInstance`만 생성하면 됩니다. 이는 애플리케이션의 전역 Vulkan 문맥 역할을 하기 때문입니다. 21 | 22 | ## VkPhysicalDevice 23 | `VkInstance`를 생성한 후, 시스템에서 사용가능한 GPU를 조회할 수 있습니다. 24 | 25 | Vulkan에서는 시스템에 존재하는 GPU와 해당 GPU 기능 목록을 가져올 수 있습니다. 이 모든 정보들은 GPU를 나타내는 `VkPhysicalDevice`를 통해 나타납니다. 예를 들어, 게이밍 전용 GPU가 장착된 게이밍 전용 PC의 경우 단 하나의 `VkPhysicalDevice`만을 존재할 가능성이 높습니다. 이 경우 여러 GPU들 중 고를 필요 없이 하나만 선택하면 됩니다. 26 | 27 | 더 흥미로운 상황은 랩탑에서 발생합니다. 랩탑은 보통 2개의 GPU를 갖는 경우가 있습니다. 하나는 저전력의 CPU 내장 GPU이고, 다른 하나는 고성능의 전용 GPU입니다. 이 경우 애플리케이션은 렌더링에 사용할 GPU를 선택해야 하며, 최적의 방법은 사용자가 직접 선택할 수 있도록 하는 것입니다. 사용자는 배터리 수명을 유지하기 위해 저전력 GPU를 사용하고 싶을 수 있습니다. 28 | 29 | GPU를 선택하는 것 외에도, `VkPhysicalDevice`를 통해 GPU의 기능, 메모리 크기, 그리고 지원하는 확장을 조회할 수 있습니다. 이는 사용 가능한 VRAM의 크기와 GPU가 고급 기능을 지원하는 지를 정확히 알아야 하는 고급 애플리케이션에서 매우 중요합니다. 30 | 31 | ## VkDevice 32 | `VkPhysicalDevice`로 `VkDevice`를 생성할 수 있습니다. `VkDevice`는 GPU 하드웨어의 실제 드라이버이며, GPU에게 소통하는 수단입니다. 디버깅 기능과 초기화를 제외한 대부분의 Vulkan 명령은 `VkDevice`를 필요로 합니다. 장치(device)를 생성할 때는 활성화할 확장 목록을 지정해야 합니다. 필요하지 않은 확장은 활성화하지 않는 것이 좋습니다. 불필요한 기능을 확인하는 과정에서 드라이버가 성능이 저하될 수 있기 때문입니다. 33 | 34 | 엔진이 여러 `VkDevice`를 동시에 다룰 수도 있으며, 이를 통해 하나의 프로그램에서 여러 GPU를 사용할 수 있습니다. 이 튜토리얼에서는 다루지 않지만, 여러 GPU간 컴퓨트 셰이더를 작동할 때 알아두면 유용한 내용입니다. 35 | 36 | ## 스왑체인(Swapchain) 37 | GPU가 올바르게 초기화했지만, 화면에 실제로 렌더링을 수행해야 합니다. 이를 위해 스왑체인(swapchain)을 사용합니다. 스왑체인은 OS 또는 창 시스템이 제공하는 구조로, 이미지를 그린 후 화면에 표시할 수 있도록 합니다. 스왑체인은 Vulkan의 핵심 사양은 아닙니다. 선택적 기능이며 플랫폼마다 차이가 있을 수 있습니다. 만약 Vulkan을 컴퓨트 셰이더 계산 혹은 오프라인 렌더링에 사용한다면, 스왑체인을 설정할 필요는 없습니다. 38 | 39 | 스왑체인은 주어진 크기로 생성되며, 창 크기가 변경된다면 스왑체인을 다시 만들어야 합니다. 40 | 41 | 스왑체인 이미지의 포맷은 플랫폼과 GPU에 따라 달라질 수 있습니다. 따라서 스왑체인에서 요구하는 포맷의 이미지를 저장해야 합니다. 다른 포맷의 이미지를 렌더링하면 그래픽 이상이나 크래시가 일어날 수 있기 때문입니다. 42 | 43 | 스왑체인은 화면에 표시하기 위해 운영체제에서 접근할 수 있는 이미지와 이미지뷰(image-view)의 목록을 포함합니다. 스왑체인을 더 적거나 더 많은 이미지로 생성할 수도 있지만, 일반적으로 더블 버퍼링 혹은 트리플 버퍼링을 수행하기 위해 2,3개의 이미지만을 사용합니다. 44 | 45 | 스왑체인을 만들 때 가장 중요한 것은 표시 모드(Present Mode)를 선택하는 것입니다. 이는 스왑체인이 화면 표시와 어떻게 동기화할지를 제어합니다. 46 | 47 | 모든 표시 모드의 자세한 설명은 아래 Vulkan 사양 페이지에서 확인할 수 있습니다. [Vulkan Spec: VkPresentModeKHR](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap34.html#VkPresentModeKHR) 48 | 49 | 50 | - `VK_PRESENT_MODE_IMMEDIATE_KHR` 스왑체인을 아무것도 기다리지 않고 이미지를 받는 즉시 표시하도록 합니다. 이는 화면 찢어짐(tearing)이 발생할 수 있으며 일반적으로 권장되지 않습니다. 51 | - `VK_PRESENT_MODE_FIFO_KHR` 새로고침 주기에 따라 표시할 이미지 큐(queue)를 사용합니다. 큐가 가득 차면 이미지가 표시되어 빈 공간이 생길 때 까지 애플리케이션이 대기합니다. 이는 "강한 VSync" 표시 모드이며, 애플리케이션의 FPS가 화면의 주사율에 고정됩니다. 52 | - `VK_PRESENT_MODE_FIFO_RELAXED_KHR` . Fifo VSync과 거의 같지만 VSync VSync가 유연하게 작동합니다. 만약 애플리케이션의 FPS가 화면의 최적 FPS보다 낮다면, 이미지를 즉시 표시하여 찢어짐(tearing) 현상이 발생할 수 있습니다. 예를 들어, 화면이 60Hz를 지원하는데 렌더링이 55Hz로 이루어진다면, 일반적인 Fifo에서는 다음 VSync주기 까지 대기해야 하므로 30FPS까지 떨어질 수 있지만, 이 모드는 그대로 55FPS로 표시합니다. 다만 이 과정에서 화면 찢어짐이 발생할 수 있습니다. 53 | - `VK_PRESENT_MODE_MAILBOX_KHR` . 이 모드는 이미지 목록을 유지하며, 한 이미지가 화면에 표시되는 동안 나머지 이미지에 계속해서 렌더링할 수 있습니다. 이미지를 표시할 시점이 되면 가장 최근에 렌더링 된 이미지를 선택합니다. 엄격한 VSync 없이 트리플 버퍼링을 사용하고 싶을 때 적합한 방식입니다. 54 | 55 | `VK_PRESENT_MODE_IMMEDIATE_KHR`은 찢어짐 현상 거의 사용되지 않습니다. 극도로 낮은 지연이 필요한 경우, 찢어짐 현상을 감수하고 사용할 수도 있습니다. 56 | 57 | 일반적인 애플리케이션은 MAILBOX 혹은 FIFO중 하나를 사용합니다. 이는 엄격한 VSync를 원하는 지, 혹은 트리플 버퍼링을 선호하는 지에 따라 달라집니다. 58 | 59 | 이 가이드에서는 `FIFO_RELAXED` 모드를 사용하겠습니다. 렌더링 속도의 상한을 설정해주며, 많은 객체를 렌더링하지 않으므로 프레임 속도가 5000FPS까지 올라가 과열 등의 문제가 발생하는 것을 방지하는 데 적합합니다. 하지만 실제 애플리케이션에서 작업 부하가 있다면 `MAILBOX`가 더 적절할 수 있습니다. 60 | 61 | Next: [ Vulkan Initialization Code]({{ site.baseurl }}{% link docs/ko/new_chapter_1/vulkan_init_code.md %}) 62 | 63 | {% include comments.html term="Vkguide 2 Korean Comments" %} 64 | 65 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_2/chapter-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "2. Drawing with Compute - KO" 4 | nav_order: 14 5 | parent: "Korean VKGuide" 6 | has_children: true 7 | permalink: /docs/ko/new_vkguide/chapter_2 8 | auto_comments: Vkguide 2 Beta Comments 9 | --- 10 | # 2장 : 컴퓨트 셰이더 그리기 11 | 12 | 이 장에서는 컴퓨트 셰이더를 사용해 그리기를 시작할 것입니다. 사용자 인터페이스를 추가하기 위해 DearImgui 라이브러리도 함께 설정하겠습니다. 13 | 14 | {: .fs-6 .fw-300 } 15 | 16 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_3/blending.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Blending 4 | grand_parent: "Korean VKGuide" 5 | parent: "3. Graphics Pipelines - KO" 6 | nav_order: 20 7 | --- 8 | 9 | 파이프라인 빌더를 생성할 때, 블렌딩 로직은 완전히 생략했었습니다. 블렌딩은 투명한 객체나 몇몇 그래픽 효과에 필수적으로 사용되기 때문에 중요한 기능입니다. 따라서 이번에는 지난 글에서 렌더링한 사각형을 투명하게 만들겠습니다. 10 | 11 | ## 파이프라인 블렌딩 12 | 셰이더에서 블렌딩을 제어할 수는 없으며, 이는 파이프라인의 속성입니다. GPU 하드웨어 자체가 블렌딩 연산을 처리하며, 다양한 옵션을 제공합니다. PipelineBuilder에 2가지 새로운 블렌딩 모드를 추가해 보겠습니다. 하나는 단순히 색상을 더하는 addtive blending, 다른 하나는 색상과 알파 값을 섞는 alpha blending 입니다. 13 | 14 | PipelineBuilder에 다음 두 함수를 추가합니다. 15 | 16 | 17 | ```cpp 18 | void PipelineBuilder::enable_blending_additive() 19 | { 20 | _colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 21 | _colorBlendAttachment.blendEnable = VK_TRUE; 22 | _colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; 23 | _colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; 24 | _colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; 25 | _colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; 26 | _colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 27 | _colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; 28 | } 29 | 30 | void PipelineBuilder::enable_blending_alphablend() 31 | { 32 | _colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 33 | _colorBlendAttachment.blendEnable = VK_TRUE; 34 | _colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; 35 | _colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 36 | _colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; 37 | _colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; 38 | _colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 39 | _colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; 40 | } 41 | ``` 42 | 43 | Vulkan에서 블렌딩 옵션을 설정할 때 색상과 알파값에 각각에 대해 블렌딩 식을 지정해주어야 합니다. 색상과 알파에 매개변수는 동일하게 동작하며, 블렌딩 식은 다음과 같은 방식으로 작동합니다. 44 | 45 | ``` 46 | outColor = srcColor * srcColorBlendFactor dstColor * dstColorBlendFactor; 47 | ``` 48 | 블렌딩에는 여러 연산자가 있지만, 대부분은 가장 기본적이고 안정적으로 작동하는 `VK_BLEND_OP_ADD`를 사용합니다. 그 외에도 다양한 고급 연산자들이 있지만, 대부분 확장이 필요하며 여기서는 다루지 않겠습니다. Source는 파이프라인에서 현재 처리중인 색상을 의미하고, Destination은 우리가 렌더링 중인 이미지의 현재 픽셀 값입니다. 49 | 50 | 위의 식을 바탕으로 덧셈 블렌딩이 어떻게 작동하는지 설명하겠습니다. 51 | 52 | `VK_BLEND_FACTOR_ONE`은 blend factor를 1.0으로 설정하므로, 곱셈 연산 없이 그대로 더해지게 됩니다. `VK_BLEND_FACTOR_SRC_ALPHA`은 반면 Source의 alpha 값을 곱합니다. 이 경우 우리의 블렌딩 공식은 다음과 같은 형태가 됩니다. 53 | ```c 54 | outColor = srcColor.rgb * srcColor.a + dstColor.rgb * 1.0 55 | ``` 56 | 57 | 알파 블렌딩을 사용할 경우 대신 다음과 같은 모습이 될 것입니다. 58 | 59 | ```c 60 | outColor = srcColor.rgb * srcColor.a + dstColor.rgb * (1.0 - srcColor.a) 61 | ``` 62 | 본질적으로 srcColor의 alpha값에 의해 제어되는 보간을 수행하는 셈이며, 이 alpha 값은 셰이더에서 전달됩니다. 63 | 64 | 이걸 사용해 어떤 결과가 나오는지 확인해 봅시다. 셰이더에서는 알파 값을 따로 설정하지 않았으니, addtive를 사용해 봅시다. `init_mesh_pipeline()`함수에서 블렌딩 설정을 변경해 주세요.` 65 | 66 | ```cpp 67 | //pipelineBuilder.disable_blending(); 68 | pipelineBuilder.enable_blending_additive(); 69 | ``` 70 | 71 | 이제 원숭이 메시가 반투명해진 것을 볼 수 있습니다. 다양한 블렌딩 모드를 시도해보면서 각각이 어떤 효과를 주는지 확인해 보세요. 72 | 73 | 4장으로 넘어가기 전에 창 크기 조정 기능을 구현해봅시다. 74 | 75 | Next: [ Window Resizing]({{ site.baseurl }}{% link docs/ko/new_chapter_3/resizing_window.md %}) 76 | 77 | {% include comments.html term="Vkguide 2 Korean Comments" %} 78 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_3/chapter-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "3. Graphics Pipelines - KO" 4 | nav_order: 16 5 | parent: "Korean VKGuide" 6 | has_children: true 7 | auto_comments: Vkguide 2 Beta Comments 8 | permalink: /docs/ko/new_vkguide/chapter_3 9 | --- 10 | # 3장 : 그래픽스 파이프라인 11 | 12 | 지금까지 컴퓨트 셰이더로 그리기를 수행해왔지만, 이번 장에서는 GPU의 본격적인 렌더링 기능을 활용하여 일반적인 그래픽스 파이프라인과 래스터화 시스템을 통해 메시를 그려보겠습니다. 13 | 14 | {: .fs-6 .fw-300 } 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_3/render_pipeline.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: The graphics pipeline 4 | parent: "3. Graphics Pipelines - KO" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 2 7 | --- 8 | 9 | 지금까지는 렌더링 루프를 구성하고 컴퓨트 셰이더를 사용해 이미지를 그릴 수 있는 방법을 마련했습니다. 하지만 아직은 실제 도형(geometry)을 그리지는 못합니다. 도형을 렌더링하려면 GPU 내부의 특수 하드웨어를 활용해 렌더링을 수행하기 위한 다양한 설정을 담고 있는 그래픽스 파이프라인을 설정해야 합니다. 이러한 작업을 제대로 수행하려면, 어떻게 Vulkan 렌더링 파이프라인이 작동하는지 이해해야 합니다. 10 | 11 | ## 렌더링 파이프라인 12 | GPU는 도형을 그릴 때 사용되는 다양한 기능을 갖고 있습니다. GPU는 범용 컴퓨팅 유닛과 별개로 렌더링을 위한 전용 하드웨어가 별도로 존재합니다. 이 전용 하드웨어들은 삼각형 혹은 다른 프리미티브를 빠르고 효율적으로 그릴 수 있게 해줍니다. 13 | 14 | GPU를 하나의 어셈블리 라인이라고 생각해도 좋습니다. 각 단계에서 서로 다른 작업을 수행하는 여러 구성요소가 있으며, 최종 결과물은 이미지에 렌더링된 픽셀입니다. 이 "어셈블리 라인"을 그래픽스 파이프라인이라 부릅니다. 15 | 16 | 그래픽스 파이프라인에서는 데이터와 프로그램이 입력되어 픽셀이 출력됩니다. 그래픽스 프로그래머의 일은 이를 요구사항에 맞게 적절히 구성하는 것입니다. 17 | 18 | 전체 Vulkan 그래픽스 파이프라인은 매우 복잡하므로, 우선 단순한 버전을 살펴볼 것입니다. 렌더링에 사용할 파이프라인을 구성해 나가면서 각 단계에 세부 내용도 함께 다뤄볼 것입니다. 19 | 20 | 그래픽스 파이프라인은 데이터 입력 → 정점 셰이더 → 래스터화 → 프래그먼트 셰이더 → 렌더링 출력 순으로 이뤄집니다. 21 | 22 | 두 셰이더 단계에서는 우리가 원하는 작업을 수행하도록 작성된 프로그램이 실행됩니다. 반면 래스터화와 렌더링 출력 단계는 고정된 기능을 수행하며, 이들에 대해서는 매개변수나 설정만 조정할 수 있습니다. 23 | 24 | 우선 데이터를 준비해야 합니다 이 데이터는 텍스쳐, 3D 모델, 머테리얼 등 우리가 원하는 어떤 것이든 될 수 있습니다. 이러한 데이터는 파이프라인의 각 단계를 거치며 변환되어 결국 화면에 픽셀로 나타나게 됩니다. 25 | 26 | 정점 셰이더는 모든 정점마다 한 번씩 실행되며, 정점의 위치와 그 외 속성들을 GPU가 이해할 수 있는 형태로 변환해 래스터화 단계에 전달하는 역할을 합니다. 27 | 28 | 래스터화 단계는 정점 셰이더에서 생성된 정점들을 받아와 삼각형이 화면에서 차지하는 픽셀을 계산합니다. 이렇게 계산된 픽셀들은 프래그먼트 셰이더로 전달됩니다. 이 과정은 그래픽스 파이프라인을 구성할 때 다양한 설정이 필요한 부분입니다. 29 | 30 | 프래그먼트 셰이더는 이러한 픽셀들을 실제 색상 픽셀로 출력하며, 래스터화 과정으로부터 받은 픽셀마다 한 번씩 실행됩니다. 31 | 32 | 렌더링 출력 단계에서는 최종 색상 픽셀을 출력 프레임 버퍼에 기록합니다. 이 단계에는 고정 기능 하드웨어 설정들이 포함되어 있으며, 블렌딩이나 깊이 테스트와 같은 작업이 수행됩니다. 33 | 34 | 다음 글에서는 지금까지 설명한 내용을 바탕으로 실제로 삼각형을 그려보겠습니다. 35 | 36 | Next: [ Setting up render pipeline]({{ site.baseurl }}{% link docs/ko/new_chapter_3/building_pipeline.md %}) 37 | 38 | {% include comments.html term="Vkguide 2 Korean Comments" %} 39 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_4/chapter-4.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "4. Textures and Engine Architecture- KO" 4 | has_children: true 5 | nav_order: 17 6 | parent: "Korean VKGuide" 7 | permalink: /docs/ko/new_vkguide/chapter_4 8 | auto_comments: Vkguide 2 Beta Comments 9 | --- 10 | # 4장 : 텍스쳐와 엔진 아키텍처 11 | 12 | 이제 메시를 그릴 수 있지만, 몇 가지 작업할 일이 남았습니다. 이 장에서는 셰이더에 사용할 이미지를 불러오는 방법을 설정하고 성능과 확장성을 위한 렌더링 아키텍처를 설정하겠습니다. 13 | 14 | {: .fs-6 .fw-300 } 15 | 16 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_4/engine_arch.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Engine Architecture 4 | parent: "4. Textures and Engine Architecture- KO" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 10 7 | --- 8 | 9 | # 엔진 아키텍처 10 | 엔진을 구성하는 데 필요한 로우 레벨 기법은 이미 갖춰졌습니다. 임의의 메시를 그릴 수 있고, 버퍼나 텍스쳐 같은 데이터를 셰이더에 전달할 수 있습니다. 이제 필요한 것은 객체를 렌더링하기 위한 제대로된 아키텍처를 구축하고 VulkanEngine 클래스에 하드코딩된 구조체 사용을 지양하는 것입니다. 11 | 12 | 다음 장에서 GLTF 파일로부터 동적으로 전체 씬을 불러올 것이므로, 여기서의 아키텍쳐는 GLTF를 어느 정도 모방하게 됩니다. 우리는 GLTF의 PBR 사양을 기반으로 기본적인 GLTF 파이프라인을 만들고, 첫 번째 메시 클래스를 정의할 것입니다. 13 | 14 | 이 아키텍처는 두 단계의 구조체를 중심으로 구성됩니다. 그 중 하나는 RenderObject 구조체입니다. 15 | 16 | ```cpp 17 | struct RenderObject { 18 | uint32_t indexCount; 19 | uint32_t firstIndex; 20 | VkBuffer indexBuffer; 21 | 22 | MaterialInstance* material; 23 | 24 | glm::mat4 transform; 25 | VkDeviceAddress vertexBufferAddress; 26 | }; 27 | ``` 28 | 29 | 이 구조체는 VkCmdDrawIndexed 호출에 필요한 모든 파라미터를 평탄화한 추상화 구조입니다. 인덱싱에 필요한 정보와 함께, 특정 머테리얼에 해당하는 파이프라인과 디스크립터 셋을 가리키는 MaterialInstance 포인터를 포함합니다. 이어서 3D 렌더링에 필요한 행렬과 정점 버퍼의 포인터가 있으며, 이 두 요소는 객체마다 바뀌는 동적 데이터이므로 푸시 상수를 통해 전달됩니다. 30 | 31 | 이 구조체는 매 프레임 동적으로 작성되며, 렌더링 로직은 RenderObject 구조체 배열을 순회하면서 그리기 명령을 직접 기록하게 됩니다. 32 | 33 | MaterialInstance 구조체는 다음과 같습니다. 34 | ```cpp 35 | struct MaterialPipeline { 36 | VkPipeline pipeline; 37 | VkPipelineLayout layout; 38 | }; 39 | 40 | struct MaterialInstance { 41 | MaterialPipeline* pipeline; 42 | VkDescriptorSet materialSet; 43 | MaterialPass passType; 44 | }; 45 | ``` 46 | 47 | 머테리얼 시스템에는 두 개의 파이프라인, 즉 GLTF PBR 불투명용과 투명용으로 하드코딩될 것입니다. 두 파이프라인은 동일한 정점 및 프래그먼트 셰이더 쌍을 공유하며, 디스크립터 셋은 총 2개만 사용할 예정입니다. 슬롯 0번은 카메라 및 환경 정보와 같은 전역 데이터를 담는 디스크립터 셋으로, 한번 바인딩된 후 모든 드로우 콜에서 재사용됩니다. 이후 조명 정보 등도 추가할 예정입니다. 슬롯 1번은 머테리얼별 디스크립터 셋으로, 텍스쳐 및 머테리얼 파라미터를 바인딩하는 역할을 합니다. GLTF 사양을 그대로 반영하여, PBR GLTF 머테리얼이 요구하는 텍스쳐 외에도 객체 색상 등의 색상 상수를 포함하는 유니폼 버퍼를 사용할 것입니다. GLTF PBR 머테리얼은 특정 텍스쳐가 없어도 유효하지만, 이 경우 용도에 따라 기본 흰색 혹은 검은색 텍스쳐를 바인딩하게 됩니다. MaterialInstance 구조체는 MaterialPass 열거형을 갖는데 이는 불투명 객체와 투명 객체를 구분하는 데 사용됩니다. 48 | 49 | 2개의 파이프라인만 사용하는 이유는 파이프라인 수를 가능한 적게 유지하기 위함입니다. 파이프라인 수가 적으면 시작 시 사전 로딩이 가능하고, 특히 바인드리스 렌더링이나 draw-indirect 렌더링 로직을 도입했을 때 렌더링 속도가 향상됩니다. 우리의 목표는 GLTF PBR 머테리얼과 같은 각 머테리얼 타입에 대해 소수의 파이프라인만을 사용하는 것입니다. 렌더링 엔진이 필요로 하는 파이프라인 수는 성능에 큰 영향을 미칩니다. 예를 들어 둠 이터널 엔진과 같은 경우는 게임에 약 200여개의 파이프라인만 사용하지만, 언리얼 엔진 기반의 프로젝트인 경우 종종 10만 개 이상의 파이프라인을 사용합니다. 이처럼 지나치게 많은 파이프라인을 컴파일 하는 것은 렌더링 중 스터터링을 유발하고, 많은 저장 공간을 차지하며, draw-indirect와 같은 고급 기능의 구현에도 제약을 줍니다. 50 | 51 | RenderObject는 매우 로우 레벨의 구조이므로, 이를 생성하고 관리하기 위한 구조가 필요합니다. 여기에는 씬 그래프를 도입하겠습니다. 이렇게 하면 메시 간의 부모-자식 관계를 표현할 수 있으며, 메시가 없는 빈 노드도 가질 수 있습니다. 이는 게임 엔진에서 레벨을 구성하기 위한 전형적인 방식입니다. 52 | 53 | 이번에 설계할 씬 그래프는 중간 또는 다소 낮은 성능 구조이지만, 추후에 개선할 예정이며 매우 유연하고 확장성이 뛰어납니다. 현재 설계만으로도 수만 개의 객체 렌더링에는 충분한 성능을 제공합니다. 54 | 55 | ```cpp 56 | // base class for a renderable dynamic object 57 | class IRenderable { 58 | 59 | virtual void Draw(const glm::mat4& topMatrix, DrawContext& ctx) = 0; 60 | }; 61 | ``` 62 | 63 | 단일 Draw() 함수만을 정의하는 IRenderable 인터페이스가 있습니다. 이 함수는 부모로 사용할 행렬과 RenderContext를 인자로 받습니다. RenderContext는 현재로서는 렌더링할 객체들의 배열일 뿐입니다. 이 구조의 아이디어는 Draw() 함수가 호출될 때, 해당 객체가 이번 프레임에 렌더링할 항목에 Renderables을 추가하는 것입니다. 이 방식은 흔히 Immediate Design이라 불리며, 가장 큰 장점은 동일한 객체를 여러 번 다른 행렬을 사용하여 한 프레임 안에서 중복 렌더링할 수 있다는 점입니다. 또한 특정 로직에 따라 어떤 프레임에서는 Draw()를 호출하지 않음으로써 해당 객체를 렌더링하지 않을 수도 있습니다. 이 접근법은 자원 관리 및 객체 수명 관리가 훨씬 단순해지기 때문에 동적인 객체를 다룰 때 매우 유용하며, 코드 작성 또한 비교적 간단합니다. 단점으로는, 프레임마다 여러 객체를 순회하며 가상 함수를 호출하게 되는데, 객체 수가 많아질수록 이러한 호출 비용이 누적된다는 점입니다. 64 | 65 | Node 클래스는 IRenderable을 상속받을 것이며, 고유의 변환 행렬과 자식 노드의 배열을 가질 것입니다. Draw()가 호출될 때 자식 노드들의 Draw()도 호출하게 됩니다. 66 | 67 | MeshNode 클래스를 만들 것이며, 이는 Node를 상속받을 것입니다. 이 클래스는 렌더링에 필요한 자원들을 보유하고 있으며, Draw()가 호출되면 RenderObject를 생성해 DrawContext에 추가하게 됩니다. 68 | 69 | 조명과 같은 다른 렌더링 요소를 추가할 때도 동일한 구조로 동작합니다. DrawContext는 조명들의 목록을 유지하고, LightNode는 조명이 활성화되어 있을 경우 자신의 파라미터를 해당 목록에 추가합니다. 지형, 파티클 등 다른 렌더링 객체도 동일한 방식으로 처리할 수 있습니다. 70 | 71 | 우리가 사용할 한 가지 트릭은 GLTF를 추가할 때 LoadedGLTF라는 클래스를 만드는 것입니다. 이 클래스는 Node가 아닌 IRenderable을 직접 상속하며, 특정 GLTF 파일에 포함된 전체 상태와 텍스쳐, 메시같은 모든 자원을 포함합니다. 그리고 Draw()가 호출되면 해당 GLTF의 내용을 렌더링합니다. 비슷한 방식으로 OBJ와 같은 다른 포맷도 처리할 수 있어 유용합니다. 72 | 73 | 74 | GLTF를 불러오는 것은 다음 장에서 할 예정이지만, 지금은 RenderObject와 GLTF 머테리얼 처리 방식을 준비할 것입니다. 75 | 76 | Next: [ Setting up Materials]({{ site.baseurl }}{% link docs/ko/new_chapter_4/materials.md %}) 77 | 78 | {% include comments.html term="Vkguide 2 Korean Comments" %} 79 | -------------------------------------------------------------------------------- /docs/ko/new_chapter_5/chapter-5.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "5. GLTF loading - KO" 4 | nav_order: 18 5 | has_children: true 6 | parent: "Korean VKGuide" 7 | permalink: /docs/ko/new_vkguide/chapter_5 8 | auto_comments: Vkguide 2 Beta Comments 9 | --- 10 | # 5장 : GLTF 불러오기 11 | 12 | 기본적인 엔진 구성이 끝났습니다. 이번에는 GLTF 파일을 불러오고, 보다 고급 렌더링 기법을 설정하는 데 집중하겠습니다. 13 | 14 | {: .fs-6 .fw-300 } 15 | 16 | -------------------------------------------------------------------------------- /docs/new_chapter_0/building_project.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Building Project 4 | parent: "0. Project Setup" 5 | nav_order: 2 6 | auto_comments: Vkguide 2 Beta Comments 7 | --- 8 | 9 | # Building the project 10 | 11 | Start by syncing the Git project at . 12 | The all-chapters branch contains the example code for the entire project, and the starting-point branch contains the initial empty project setup. I recommend you sync both branches to different folders, and if at one point you get stuck, check how the code works in the all-chapters code. 13 | If you want a direct download to the code without using Git just download from these direct links. 14 | 15 | [All Chapters](https://github.com/vblanco20-1/vulkan-guide/archive/all-chapters-2.zip) 16 | 17 | [Starting Point](https://github.com/vblanco20-1/vulkan-guide/archive/starting-point-2.zip) 18 | 19 | 20 | You will need Visual Studio to build the project. The code in the project should work cross-platform, but this guide is windows-centric. 21 | 22 | First, install the Vulkan SDK . This will contain the development headers and libraries needed to create Vulkan applications. It is put in a global location, so you don't need to worry about where it gets installed. 23 | 24 | Then grab CMake, as it's the build system we are going to use. . 25 | 26 | Once CMake is installed, use CMake-gui to open the project root CMakeLists. Press the Configure button. 27 | 28 | If at this point it complains about not finding Vulkan_INCLUDE_DIR or Vulkan_LIBRARY, make sure you've finished installing the Vulkan SDK, then close and open CMake-Gui and try configuring again. 29 | 30 | Now that the dependencies are set, you can proceed with CMake and Configure then Generate the project files for Visual Studio (or your IDE of choice). 31 | 32 | From Visual Studio, select the engine target, set as Startup Project, and you can now compile and execute it by just hitting F5 (start debugging) 33 | 34 | ![vs]({{site.baseurl}}/assets/images/vs_compile.png) 35 | 36 | # Third party libraries 37 | Under the third_party folder, we have several different libraries that we are going to use across the tutorial. Those libraries are all embedded as sourcecode into the folder. Some of them have source code edits or are different from what is on their public repo 38 | 39 | This is the list of libraries we are using. 40 | 41 | - vulkan SDK: This one is not in the third_party folder, but its a dependency we have. You should have it installed from the explanation above 42 | - vkbootstrap: We will be using this to simplify the vulkan initialization logic. It will do things like select what gpu to use for us, and setup some initial structures. 43 | - VMA: Vulkan Memory Allocator. This is a library that implements high performance memory allocators for GPU structures. We will use that instead of trying to write the allocators ourselves. It will manage our GPU memory 44 | - SDL: Highly multiplatform library for windowing, input, audio, and a few other things. We will be using its windowing and input parts on the tutorial. 45 | - GLM : Math library. Will provide vectors, matrices, and so on. 46 | - {fmt} : String formatting and console output library. We will use it instead of std::cout as it runs significantly faster and gives us great utilities to display strings and other formatting options. 47 | - stb_image: for loading PNG or jpeg images. 48 | - dear imgui: Great UI library very useful for debug interfaces. Will lets us display some timings or add some UI windows. 49 | - fastgltf: High performance GLTF loading library. 50 | 51 | 52 | Next: [ Code Walkthrough]({{ site.baseurl }}{% link docs/new_chapter_0/code_walkthrough.md %}) 53 | -------------------------------------------------------------------------------- /docs/new_chapter_0/chapter-0.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "0. Project Setup" 4 | nav_order: 11 5 | has_children: true 6 | permalink: /docs/new_vkguide/chapter_0 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | ![chapter0]({{site.baseurl}}/diagrams/chapter0.png) 10 | 11 | 12 | # Chapter 0 index 13 | 14 | 15 | In this chapter, we setup the build toolchain to compile the project 16 | 17 | {: .fs-6 .fw-300 } 18 | 19 | -------------------------------------------------------------------------------- /docs/new_chapter_1/chapter-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "1. Initializing Vulkan" 4 | nav_order: 13 5 | has_children: true 6 | permalink: /docs/new_vkguide/chapter_1 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | ![chapter1]({{site.baseurl}}/diagrams/chapter1.png) 10 | # Chapter 1 : Initialization and render Loop 11 | 12 | In this chapter, we are going to start the tutorial code, and configure the initial Vulkan structures needed to support rendering. 13 | We will also be writing the initial render loop, including command buffer and render image management. 14 | {: .fs-6 .fw-300 } 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/new_chapter_2/chapter-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "2. Drawing with Compute" 4 | nav_order: 14 5 | has_children: true 6 | permalink: /docs/new_vkguide/chapter_2 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | # Chapter 2 : Drawing with compute 10 | 11 | In this chapter, we are going to begin drawing using compute shaders. As part of the chapter, we will also setup DearImgui library to get some user interface. 12 | 13 | {: .fs-6 .fw-300 } 14 | 15 | -------------------------------------------------------------------------------- /docs/new_chapter_3/blending.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Blending 4 | parent: "3. Graphics Pipelines" 5 | nav_order: 20 6 | --- 7 | 8 | When we created the pipeline builder, we completely skipped over the blending logic, setting it as no blending. Blending is used for transparent objects and some graphical effects, so its important to have it. for that reason, we will make the rectangle we rendered last article transparent. 9 | 10 | ## Blending in the pipeline 11 | We cant really control blending from shaders, thats property of the pipeline. The gpu hardware itself does the blending mathematics for us, and has a bunch of options. We will be adding 2 new blending modes into the pipeline builder, one will be additive blending, where it just adds the colors, and the other alpha-blend, where it would mix the colors. 12 | 13 | Lets add these 2 functions into the pipeline builder 14 | 15 | 16 | ```cpp 17 | void PipelineBuilder::enable_blending_additive() 18 | { 19 | _colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 20 | _colorBlendAttachment.blendEnable = VK_TRUE; 21 | _colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; 22 | _colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE; 23 | _colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; 24 | _colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; 25 | _colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 26 | _colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; 27 | } 28 | 29 | void PipelineBuilder::enable_blending_alphablend() 30 | { 31 | _colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 32 | _colorBlendAttachment.blendEnable = VK_TRUE; 33 | _colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; 34 | _colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; 35 | _colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; 36 | _colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; 37 | _colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; 38 | _colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; 39 | } 40 | ``` 41 | 42 | When setting blending options in vulkan, we need to fill the formula on both color and alpha. The parameters work the same on both color and alpha. The formula works like this 43 | 44 | ``` 45 | outColor = srcColor * srcColorBlendFactor dstColor * dstColorBlendFactor; 46 | ``` 47 | There are a few possible operators, but for the most part we will be doing `VK_BLEND_OP_ADD`, as its the most basic and guaranteed to work. There are many other much more advanced operators, but those come with extensions and we wont use them. Source (from srcColor and blend factor) refers to the color we are processing on our pipeline, and Destination (dstColor and blend factor) is the current value of the image we are rendering into. 48 | 49 | With the formula above, lets explain what the addition blending does. 50 | 51 | `VK_BLEND_FACTOR_ONE` sets the blend factor to just 1.0, so no multiplying. `VK_BLEND_FACTOR_SRC_ALPHA` on the other hand multiplies it by the alpha of the source. Our blending ends up as this formula 52 | ```c 53 | outColor = srcColor.rgb * srcColor.a + dstColor.rgb * 1.0 54 | ``` 55 | 56 | The alpha-blend one will look like this instead. 57 | 58 | ```c 59 | outColor = srcColor.rgb * srcColor.a + dstColor.rgb * (1.0 - srcColor.a) 60 | ``` 61 | Essentially making it into a lerp controlled by srcColor alpha, which will be from our shader. 62 | 63 | Lets try to use it to see what it does. We dont have alpha set in our shaders, so lets just try the additive one. Change the blending on the `init_mesh_pipeline()` function. 64 | 65 | ```cpp 66 | //pipelineBuilder.disable_blending(); 67 | pipelineBuilder.enable_blending_additive(); 68 | ``` 69 | 70 | You should now see the monkey mesh as semi-transparent, letting the color below it show.Play around with the blending modes to see what effects they result on. 71 | 72 | Before we move to chapter 4, lets implement window resizing. 73 | 74 | Next: [ Window Resizing]({{ site.baseurl }}{% link docs/new_chapter_3/resizing_window.md %}) 75 | 76 | {% include comments.html term="Vkguide 2 Beta Comments" %} 77 | -------------------------------------------------------------------------------- /docs/new_chapter_3/chapter-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "3. Graphics Pipelines" 4 | nav_order: 16 5 | has_children: true 6 | auto_comments: Vkguide 2 Beta Comments 7 | permalink: /docs/new_vkguide/chapter_3 8 | --- 9 | # Chapter 3 : Graphics Pipelines 10 | 11 | We have already drawn with compute shaders, but in this chapter, we will use the real capabilities of a GPU to draw meshes using the rasterizer systems and the normal graphics pipeline. 12 | 13 | {: .fs-6 .fw-300 } 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/new_chapter_3/render_pipeline.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: The graphics pipeline 4 | parent: "3. Graphics Pipelines" 5 | nav_order: 2 6 | --- 7 | 8 | At this point, we have a draw loop and we have a way to draw into image using compute shader, but we cant render geometry yet. To render geometry, we need to setup a graphics pipeline that will contain all of the configuration options needed to draw geometry using the special hardware inside a GPU. 9 | To render things, we have to understand how the Vulkan rendering pipeline works. 10 | 11 | ## The render pipeline 12 | The GPU has a lot of functionality used for rendering geometry. They have a lot of extra hardware apart from the normal generic compute units. This extra hardware allows them to draw triangles or other primitives at great speed and efficiency. 13 | 14 | Think of a GPU as an assembly line. It has a lot of different parts doing different things, and the output is pixels rendered on a image. This "assembly line" is what we call the graphics pipeline. 15 | 16 | In the graphics pipeline, data and programs come in, and pixels come out. The job of a graphics programmer is to make sure to customize this to get the desired result. 17 | 18 | The full-scale Vulkan graphics pipeline is very complex, so we are going to view a simplified version of it. As we write the configuration for building our pipeline for rendering, we will go more into detail about the stages. 19 | 20 | Data -> Vertex Shader -> Rasterization -> Fragment Shader -> Render Output. 21 | 22 | The 2 shader stages will run custom programs that will do anything we want to. The Rasterization, and Render Output are Fixed stages, and we can only tweak their parameters and configuration. 23 | 24 | To begin, we need Data. The Data can be anything we want, and will be our textures, 3d models, material parameters, anything. Everything revolves around data being transformed by the stages until it becomes pixels on the screen. 25 | 26 | The vertex shader is a shader that will run once for every vertex we draw. Its job is to output vertex locations and vertex parameters in the way the GPU understands it for the Rasterization stage. 27 | 28 | The rasterization stage will grab the vertices generated by the Vertex shader, and it will find what pixels are covered by the triangle. These pixels will be sent to the fragment shader. This part has a lot of configuration options we will need to fill while building our graphics pipeline. 29 | 30 | The fragment shader takes care of turning those pixels into real colored pixels for the output, running the shader once per pixel that the rasterization stage sends to it. 31 | 32 | With the final colored pixels, we put them on the output framebuffer with the Render Output stage. There are multiple fixed-function hardware configuration steps here, that let us do things like blending pixels or depth-testing. 33 | 34 | Next article we will draw a triangle using all this. 35 | 36 | Next: [ Setting up render pipeline]({{ site.baseurl }}{% link docs/new_chapter_3/building_pipeline.md %}) 37 | 38 | {% include comments.html term="Vkguide 2 Beta Comments" %} 39 | -------------------------------------------------------------------------------- /docs/new_chapter_4/chapter-4.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "4. Textures and Engine Architecture" 4 | has_children: true 5 | nav_order: 17 6 | permalink: /docs/new_vkguide/chapter_4 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | # Chapter 4 : Textures and engine architecture 10 | 11 | We are able to draw meshes now, but there are still some things that need doing. This chapter sets up image loading from files to use in shaders, and sets up a rendering architecture that is fast and extensible. 12 | 13 | {: .fs-6 .fw-300 } 14 | 15 | -------------------------------------------------------------------------------- /docs/new_chapter_5/chapter-5.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "5. GLTF loading" 4 | nav_order: 18 5 | has_children: true 6 | permalink: /docs/new_vkguide/chapter_5 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | # Chapter 5 : GLTF Loading 10 | 11 | With the basics of the engine done, this chapter focuses on loading GLTF files and setting up more advanced rendering features. 12 | 13 | {: .fs-6 .fw-300 } 14 | 15 | -------------------------------------------------------------------------------- /docs/old_vkguide.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Legacy VkGuide, Vulkan 1.1 4 | nav_order: 100 5 | has_children: true 6 | --- 7 | 8 | ## Legacy Vkguide 9 | This is an older version of vkguide, focused on vulkan 1.1 and having wider support. Its deprecated and should only be followed if you want to learn about render passes and other features that the newer version of the guide skips. 10 | 11 | {: .fs-6 .fw-300 } 12 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vblanco20-1/vulkan-guide/620d9d083f2e5abb2818fc89fadbf06e83164cc8/favicon.ico -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Home 4 | nav_order: 1 5 | description: "Guide to the Vulkan API" 6 | permalink: / 7 | --- 8 | 9 | 10 | ![scene]({{site.baseurl}}/diagrams/fullscene.png) 11 | End stage after the tutorial 12 | 13 | ## Welcome to VulkanGuide 14 | 15 | Welcome to a new work-in-progress Vulkan guide. The focus of this guide is to understand Vulkan correctly, and act as a stepping stone for then working in your own projects. Unlike most samples and other Vulkan guides, which like to hardcode rendering loops, in here we will have a focus around dynamic rendering, so that it can act as a better base code for a game engine. 16 | 17 | While the guide is focused around game rendering, its concepts can be used in CAD and visualization just fine. 18 | 19 | We will be using C++20, but we aren't doing complex C++ unique features, so following this guide on C or Rust can be doable. 20 | 21 | This guide is meant for the people who already know the basics about 3d graphics, and have worked with either OpenGL or DirectX in the past. This guide will not explain 3d rendering basics such as linear algebra math. 22 | 23 | To contact the authors, email `contact@vkguide.dev` 24 | 25 | The code uses vulkan 1.3, and directly uses those new features to simplify the tutorial and engine architecture. If you need support for an older standard, the older version of the guide can be found here [Legacy VKGuide]({{ site.baseurl }}{% link docs/old_vkguide.md %}) 26 | 27 | The guide is separated into multiple chapters for code organization. 28 | 29 | - **Introduction**: Overview about Vulkan API and the libraries used by this project 30 | - **Chapter 0**: Setting up the guide initial code 31 | - **Chapter 1**: Vulkan initialization and render loop setup. (Draws a flashing clear color) 32 | - **Chapter 2**: Vulkan compute shaders and drawing (Uses a compute shader to draw) 33 | - **Chapter 3**: Vulkan mesh drawing (Draws meshes using the graphics pipeline) 34 | - **Chapter 4**: Textures and better descriptor set management 35 | - **Chapter 5**: Full GLTF scene loading and high performance rendering. 36 | 37 | Some extra sections of the guide contain more information that is not part of the main tutorial. Some of them are meant for the Legacy version of vkguide, and will be outdated if you are going with the current version. Outdated articles are flagged at the top. 38 | 39 | - **GPU Driven Rendering**: Using compute shaders to handle rendering for maximum scalability and hundreds of thousands of meshes 40 | - **Extra chapter**: Extra articles for various improvements to the engine shown in the tutorial. 41 | 42 | 43 | Next: [Introduction to vulkan]({{ site.baseurl }}{% link docs/introduction/vulkan_overview.md %}) 44 | {% include comments.html term="Index Comments" %} -------------------------------------------------------------------------------- /just-the-docs.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | Gem::Specification.new do |spec| 4 | spec.name = "just-the-docs" 5 | spec.version = "0.2.8" 6 | spec.authors = ["Patrick Marsceill"] 7 | spec.email = ["patrick.marsceill@gmail.com"] 8 | 9 | spec.summary = %q{A modern, highly customizable, and responsive Jekyll theme for documention with built-in search.} 10 | spec.homepage = "https://github.com/pmarsceill/just-the-docs" 11 | spec.license = "MIT" 12 | 13 | spec.files = `git ls-files -z`.split("\x0").select { |f| f.match(%r{^(assets|bin|_layouts|_includes|lib|Rakefile|_sass|LICENSE|README)}i) } 14 | spec.executables << 'just-the-docs' 15 | 16 | spec.add_runtime_dependency "bundler", "~> 2.1.4" 17 | spec.add_runtime_dependency "jekyll", ">= 3.8.5", "< 4.1.0" 18 | spec.add_runtime_dependency "jekyll-seo-tag", "~> 2.0" 19 | spec.add_runtime_dependency "rake", ">= 12.3.1", "< 13.1.0" 20 | 21 | end 22 | -------------------------------------------------------------------------------- /lib/tasks/search.rake: -------------------------------------------------------------------------------- 1 | namespace :search do 2 | desc 'Generate the files needed for search functionality' 3 | task :init do 4 | puts 'Creating search data json file...' 5 | mkdir_p 'assets/js' 6 | touch 'assets/js/search-data.json' 7 | content = %Q[{{ page.content | markdownify | replace: '에 있는 Git 프로젝트를 가져오는 것으로 시작합니다. all-chapters 브랜치는 전체 프로젝트의 예시 코드를 포함하며, starting-point 브랜치는 초기 빈 프로젝트를 포함합니다. 두 브랜치를 다른 폴더로 가져와 작업하면서 막힐 때 마다 all-chapters 브랜치의 코드를 확인해보는 방법을 권장합니다. 만약 Git을 사용하지 않고 직접 다운로드 받기를 원한다면 아래 링크를 통해 다운로드 할 수 있습니다. 13 | 14 | [All Chapters](https://github.com/vblanco20-1/vulkan-guide/archive/all-chapters-2.zip) 15 | 16 | [Starting Point](https://github.com/vblanco20-1/vulkan-guide/archive/starting-point-2.zip) 17 | 18 | 프로젝트를 빌드하기 위해 Visual Studio가 필요합니다. 프로젝트의 코드는 크로스 플랫폼으로 작동하지만 이 가이드에서는 Window 중심으로 설명할 것입니다. 19 | 20 | 먼저, Vulkan SDK 를 설치합니다. 이는 Vulkan 애플리케이션을 만드는 데 필요한 헤더와 라이브러리를 담고 있습니다. 이는 전역 위치에 설치되므로 설치위치를 걱정할 필요는 없습니다. 21 | 22 | 그 다음, CMake를 설정합니다. 이는 우리가 사용할 빌드 시스템입니다.. 23 | 24 | CMake가 설치되면 CMake-gui를 사용해 프로젝트 루트 경로의 CMakeLists를 엽니다. 그 후, Configure 버튼을 누릅니다. 25 | 26 | 만약 이 지점에서 Vulkan_INCLUDE_DIR 혹은 Vulkan_LIBRARY를 찾지 못했다는 에러가 발생한다면, Vulkan SDK 설치가 완료되기를 기다리세요. 그리고 CMake-Gui를 재시작 한 후 다시 Configure 버튼을 눌러보세요. 27 | 28 | 이제 의존성이 설정되었습니다. CMake에서 Configure이 되고 나서 Generate를 눌러 Visual Studio(혹은 다른 IDE)에 맞는 프로젝트 파일을 만들 수 있습니다. 29 | 30 | Visual Studio에서 엔진을 시작 프로젝트로 설정한 후, 이제 F5(디버깅 시작)을 눌러 컴파일하고 이를 실행할 수 있습니다. 31 | 32 | ![vs]({{site.baseurl}}/assets/images/vs_compile.png) 33 | 34 | 35 | # Third party 라이브러리 36 | third_party 폴더 하위에는 튜토리얼에서 사용할 여러 다양한 라이브러리가 있습니다. 이 라이브러리들은 소스 코드 형태로 폴더에 포함되어 있습니다. 이 중 일부는 공개 저장소의 코드와 다르게 수정되었거나 추가된 부분이 있습니다. 37 | 38 | 아래는 사용할 라이브러리의 목록입니다. 39 | 40 | - vulkan SDK: third_party 폴더에 없는 것이지만 필수적인 것으로, 위에서 설명한대로 설치해야 합니다. 41 | - vkbootstrap: Vulkan 초기화를 단순하게 만들어주는 라이브러리입니다. 우리가 사용할 GPU를 선택하거나 초기화 구조체를 설정하는 것과 같은 작업을 수행해줍니다. 42 | - VMA: Vulkan Memory Allocator입니다. 이는 GPU 구조체를 위한 고성능 메모리 할당기를 구현합니다. 할당자를 우리가 직접 구현하는 것 대신 이를 사용할 것입니다. 이 라이브러리가 우리의 GPU 메모리를 관리해줄 것입니다. 43 | - SDL: 창을 만들고 입력, 오디오, 기타 다양한 것을 수행할 수 있는 고성능 멀티플랫폼 라이브러리입니다. 이 튜토리얼에서는 SDL의 창 생성과 입력 처리 부분을 사용할 것입니다. 44 | - GLM : 수학 라이브러리입니다. 벡터, 행렬 등을 지원합니다. 45 | - {fmt} : 문자열 포맷팅과 콘솔 출력 라이브러리입니다. 성능이 뛰어나며 문자열 출력과 다양한 포맷팅 옵션을 제공하기 때문에 std::cout 대신 사용할 것입니다. 46 | - stb_image: PNG 혹은 jpeg 이미지를 불러오는 데 사용할 라이브러리입니다. 47 | - dear imgui: 디버깅 인터페이스를 위한 매우 유용한 UI 라이브러리입니다. 타이머나 기타 UI 창을 만들 때 사용할 것입니다. 48 | - fastgltf: 고성능 GLTF 로딩 라이브러리입니다. 49 | 50 | 51 | ^nextlink 52 | 53 | {% include comments.html term="Vkguide 2 Korean Comments" %} -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_0/chapter-0.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "0. Project Setup - KO" 4 | parent: "Korean VKGuide" 5 | nav_order: 11 6 | has_children: true 7 | permalink: /docs/ko/new_vkguide/chapter_0 8 | auto_comments: Vkguide 2 Beta Comments 9 | --- 10 | ![chapter0]({{site.baseurl}}/diagrams/chapter0.png) 11 | 12 | 13 | 14 | # 0장 15 | 16 | 17 | 이 챕터에서는 프로젝트를 컴파일 하기 위해 필요한 도구들을 빌드할 것입니다. 18 | 19 | {: .fs-6 .fw-300 } 20 | -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_1/chapter-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "1. Initializing Vulkan - KO" 4 | parent: "Korean VKGuide" 5 | nav_order: 13 6 | has_children: true 7 | permalink: /docs/ko/new_vkguide/chapter_1 8 | auto_comments: Vkguide 2 Beta Comments 9 | --- 10 | ![chapter1]({{site.baseurl}}/diagrams/chapter1.png) 11 | # 1장 : 초기화와 렌더링 루프 12 | 13 | 이 장에서는 튜토리얼 코드로 시작해 렌더링을 하기 위한 Vulkan 구조체를 초기화합니다. 또한 커맨드 버퍼와 렌더 이미지 관리를 포함한 초기 렌더링 루프를 작성할 것입니다. 14 | {: .fs-6 .fw-300 } 15 | 16 | -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_1/vulkan_command_flow.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Executing Vulkan Commands 4 | parent: "1. Initializing Vulkan - KO" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 20 7 | --- 8 | 9 | 10 | ![cmake]({{site.baseurl}}/diagrams/vkcommands.png) 11 | 12 | ## Vulkan 명령 실행 13 | OpenGL이나 DirectX11 이전 버전과는 달리 Vulkan에서는 모든 GPU 명령이 커맨드 버퍼(Command buffer)를 통해 전달되며, 큐(Queue)를 통해 실행됩니다. 14 | 15 | 명령을 실행하는 일반적인 흐름은 다음과 같습니다.: 16 | - `VkCommandPool`로부터 `VkCommandBuffer`를 할당합니다. 17 | - `VkCmdXXXXX` 함수를 사용하여 명령을 커맨드 버퍼에 기록합니다. 18 | - `VkQueue`로 커맨드 버퍼를 제출해 명령을 실행을 시작합니다. 19 | 20 | 같은 커맨드 버퍼를 여러 번 제출하는 것도 가능합니다. 많은 튜토리얼과 예제에서는 흔히 커맨드 버퍼를 한번만 작성하여 렌더링 루프에서 매 프레임마다 제출하는 방식을 사용합니다. 하지만 이 튜토리얼에서는 매 프레임마다 명령을 작성할 것이며, 이는 실제 렌더링 엔진의 동작 방식과 더 유사하기 때문입니다. 21 | 22 | Vulkan에서 명령을 기록하는 것은 상대적으로 비용이 적게 듭니다. 일반적으로 비용이 많이 드는 작업은 VkQueueSubmit 호출로, 이 과정에서 드라이버가 커맨드 버퍼의 유효성을 검사하고 GPU에서 실행하기 때문입니다. 23 | 24 | 커맨드 버퍼에서 매우 중요한 점은 병렬로 기록할 수 있다는 것입니다. 여러 쓰레드에서 서로 다른 커맨드 버퍼를 안전하게 기록할 수 있습니다. 이를 위해 각 쓰레드는 최소한 하나의 `VkCommandPool`과 하나의 `VkCommandBuffer`를 가져야 하며, 각 쓰레드가 자신만의 고유한 커맨드 버퍼와 커맨드 풀(Command Pool)을 사용해야 합니다. 올바르게 설정하면 각 쓰레드에서 커맨드 버퍼를 제출할 수 있습니다. `vkQueueSubmit`이 쓰레드 안전(thread-safe)하지 않기 때문에, 하나의 큐에는 한번에 하나의 쓰레드만 명령을 제출할 수 있습니다. 대규모 엔진에서는 흔히 백그라운드 쓰레드에서 제출을 처리하며, 메인 렌더링 루프 쓰레드가 실행될 수 있도록 합니다. 25 | 26 | ## VkQueue 27 | Vulkan에서의 큐는 GPU의 실행 포트입니다. 모든 GPU는 사용가능한 여러 큐를 가지며, 서로 다른 명령을 동시에 실행할 수도 있습니다. 서로 다른 큐에 제출된 명령들은 동시에 실행될 수 있습니다. 이는 메인 프레임 루프와 직접적으로 연관되지 않는 백그라운드 작업을 수행할 때 매우 유용합니다. 이를 위해 백그라운드 작업 전용 `VkQueue`를 생성하여 일반적인 렌더링 작업과 분리할 수 있습니다. 28 | 29 | Vulkan의 모든 큐는 큐 패밀리로부터 파생됩니다. 큐 패밀리는 특정 유형의 큐 그룹이며, 지원하는 명령의 종류가 각기 다릅니다. 30 | 31 | GPU는 각기 다른 큐 패밀리를 지원합니다. 예를 들어 NVIDIA GT 750TI의 경우, 이 [링크](https://vulkan.gpuinfo.org/displayreport.php?id=8859#queuefamilies)에서 확인할 수 있습니다. 이 GPU에는 2개의 큐 패밀리가 있으며, 하나는 모든 기능을 지원하는 16개의 큐로 이루어져 있으며, 다른 하나는 전송(Transfer)만을 지원하는 1개의 큐로 이루어진 큐 패밀리가 있습니다. 반면, 고성능 AMD GPU는 [여기](https://vulkan.gpuinfo.org/displayreport.php?id=24407#queuefamilies)를 참고할 수 있습니다.이 GPU에는 5개의 큐 패밀리가 있으며, 각 유형별로 최대 2개의 큐만 존재합니다. 1개의 큐는 모든 기능을 지원하고, 계산(Compute) 및 전송(Transfer) 작업을 지원하는 2개의 큐, 2개의 전송 전용 큐, 2개의 표시(Present) 전용 큐가 있습니다. 이처럼, 각 GPU가 지원하는 큐 패밀리는 상당히 다를 수 있습니다. 32 | 33 | 대부분의 엔진에서는 3개의 큐 패밀리를 사용하는 것이 일반적입니다. 하나는 프레임을 그리는 데 사용하고, 다른 하나는 비동기 계산(compute), 그리고 다른 하나는 데이터 전송입니다. 이 튜토리얼에서는 단순화를 위해 하나의 큐에서 모든 명령을 실행하겠습니다. 34 | 35 | ## VkCommandPool 36 | `VkCommandPool`은 `VkDevice`를 기반으로 생성되며, 해당 커맨드 풀이 명령을 생성할 큐 패밀리의 인덱스가 필요합니다. 37 | 38 | `VkCommandPool`을 `VkCommandBuffer`의 할당기라고 생각할 수 있습니다. 하나의 풀에서 원하는 만큼 `VkCommandBuffer`를 할당할 수 있지만, 한 번에 하나의 쓰레드만 명령을 기록할 수 있습니다. 만약 멀티쓰레드 환경에서 명령을 기록하고자 한다면 추가적인 `VkCommandPool` 객체가 필요합니다. 이러한 이유로, 해당 커맨드 풀과 쌍으로 구성할 것입니다. 39 | 40 | ## VkCommandBuffer 41 | 42 | GPU의 모든 명령은 `VkCommandBuffer`에 기록됩니다. GPU의 작업을 수행하는 모든 함수는 커맨드 버퍼가 `VkQueueSubmit`을 통해 GPU로 제출될 때까지 실행되지 않습니다. 43 | 44 | 커맨드 버퍼는 준비(Ready) 상태에서부터 시작합니다. 준비 상태에서는 `vkBeginCommandBuffer()`를 호출해 기록(Recording) 상태로 변경할 수 있습니다. 이 상태에서 `vkCmdXXXXX`함수를 호출해 명령을 기록할 수 있습니다. 모든 명령을 기록하고 나면 `vkEndCommandBuffer()`를 호출하여 실행가능한(Executable) 상태로 변경하면 해당 커맨드 버퍼를 GPU에 제출할 수 있습니다. 45 | 46 | 커맨드 버퍼를 제출하려면 제출할 명령과 큐를 지정하여 `vkQueueSubmit()`를 호출합니다. 또한, `vkQueueSubmit`은 여러 개의 커맨드 버퍼를 한 번에 제출할 수도 있습니다. 제출한 모든 커맨드 버퍼는 보류(Pending) 상태로 변환됩니다. 47 | 48 | 커맨드 버퍼가 제출되면 여전히 "유효(alive)"하며 GPU에서 처리되고 있습니다. 이 시점에서는 커맨드 버퍼를 리셋하는 것이 안전하지 않습니다. 커맨드 버퍼를 재설정하고 재사용 하기 전에, GPU가 해당 커맨드 버퍼의 모든 명령을 완료했는 지 확인해야 합니다. 49 | 50 | 커맨드 버퍼를 리셋하기 위해서 `vkResetCommandBuffer()`를 사용합니다. 51 | 52 | 커맨드 버퍼가 실행중인 동안 다음 프레임을 계속 그릴 수 있도록 더블 버퍼링을 수행할 것입니다. 이렇게 하면 GPU가 한 버퍼에서 렌더링 및 처리를 수행하는 동안, 다른 버퍼에서 명령을 기록할 수 있습니다. 53 | 54 | 커맨드 버퍼의 생명주기에 대한 더 자세한 정보는 다음 Vulkan 사양의 관련 글을 참고하세요. 55 | 56 | . 57 | 58 | 59 | ^nextlink 60 | 61 | {% include comments.html term="Vkguide 2 Korean Comments" %} 62 | 63 | -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_1/vulkan_init_flow.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Vulkan Initialization 4 | parent: "1. Initializing Vulkan - KO" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 1 7 | --- 8 | 9 | 10 | ## Vulkan 초기화 11 | OpenGL과는 달리, Vulkan은 그래픽 명령을 즉시 실행하는 대신 매우 긴 초기화 단계를 거칩니다. 이 초기화 과정을 단축하기 위해 `VkBootstrap` 라이브러리를 사용할 것입니다. 이 라이브러리는 많은 양의 작업을 간소화해줍니다. 12 | 13 | Vulkan은 매우 "직접적인" 제어를 제공하는 매우 명시적인 API입니다. 확장을 불러오거나, 사용할 GPU(들)을 선택하거나, Vulkan 명령에 사용할 초기 `VkInstance`와 `VkDevice` 구조체를 생성해야 합니다. 14 | 15 | Vulkan은 OpenGL과는 달리 전역 상태(global state)가 없습니다. 따라서 모든 API 호출에서 `VkDevice`와 `VkInstance`를 직접 전달해야합니다. 이 가이드에서는 `vulkan-1.dll`을 직접 링크하지만 이는 유일한 방법이 아닙니다. 함수 포인터를 "수동으로" 불러올 수도 있습니다. `vulkan-1.dll`을 링킹하는 것은 확장 함수도 불러오는 것은 아니므로, 별도로 불러와야 합니다. 프로젝트 코드에서는 이러한 확장 함수를 불러올 수 있도록 `Volk` 라이브러리가 제공합니다. 주요 튜토리얼 챕터에서는 이를 사용하지 않을 것이지만 이후 활용할 가능성이 높기 때문에 포함되어 있습니다. 16 | 17 | ## VkInstance 18 | 모든 것의 핵심인 `VkInstance`입니다. 이는 Vulkan API 문맥(Context)을 나타냅니다. `VkInstance`를 생성할 때, 원한다면 검증 레이어를 활성화 할 수 있으며, `VK_KHR_surface`와 같은 필요한 확장도 설정할 수 있습니다. 또한, Vulkan 드라이버에서 오류가 발생하거나 로그를 남겨야 할 때 사용할 로거를 연결할 수도 있습니다. `VkInstance`를 생성할 때 가장 중요한 것은 검증 레이어와 확장을 활성화하는 것입니다. 19 | 20 | 일반적으로 애플리케이션은 전체 실행 동안 단 하나의 `VkInstance`만 생성하면 됩니다. 이는 애플리케이션의 전역 Vulkan 문맥 역할을 하기 때문입니다. 21 | 22 | ## VkPhysicalDevice 23 | `VkInstance`를 생성한 후, 시스템에서 사용가능한 GPU를 조회할 수 있습니다. 24 | 25 | Vulkan에서는 시스템에 존재하는 GPU와 해당 GPU 기능 목록을 가져올 수 있습니다. 이 모든 정보들은 GPU를 나타내는 `VkPhysicalDevice`를 통해 나타납니다. 예를 들어, 게이밍 전용 GPU가 장착된 게이밍 전용 PC의 경우 단 하나의 `VkPhysicalDevice`만을 존재할 가능성이 높습니다. 이 경우 여러 GPU들 중 고를 필요 없이 하나만 선택하면 됩니다. 26 | 27 | 더 흥미로운 상황은 랩탑에서 발생합니다. 랩탑은 보통 2개의 GPU를 갖는 경우가 있습니다. 하나는 저전력의 CPU 내장 GPU이고, 다른 하나는 고성능의 전용 GPU입니다. 이 경우 애플리케이션은 렌더링에 사용할 GPU를 선택해야 하며, 최적의 방법은 사용자가 직접 선택할 수 있도록 하는 것입니다. 사용자는 배터리 수명을 유지하기 위해 저전력 GPU를 사용하고 싶을 수 있습니다. 28 | 29 | GPU를 선택하는 것 외에도, `VkPhysicalDevice`를 통해 GPU의 기능, 메모리 크기, 그리고 지원하는 확장을 조회할 수 있습니다. 이는 사용 가능한 VRAM의 크기와 GPU가 고급 기능을 지원하는 지를 정확히 알아야 하는 고급 애플리케이션에서 매우 중요합니다. 30 | 31 | ## VkDevice 32 | `VkPhysicalDevice`로 `VkDevice`를 생성할 수 있습니다. `VkDevice`는 GPU 하드웨어의 실제 드라이버이며, GPU에게 소통하는 수단입니다. 디버깅 기능과 초기화를 제외한 대부분의 Vulkan 명령은 `VkDevice`를 필요로 합니다. 장치(device)를 생성할 때는 활성화할 확장 목록을 지정해야 합니다. 필요하지 않은 확장은 활성화하지 않는 것이 좋습니다. 불필요한 기능을 확인하는 과정에서 드라이버가 성능이 저하될 수 있기 때문입니다. 33 | 34 | 엔진이 여러 `VkDevice`를 동시에 다룰 수도 있으며, 이를 통해 하나의 프로그램에서 여러 GPU를 사용할 수 있습니다. 이 튜토리얼에서는 다루지 않지만, 여러 GPU간 컴퓨트 셰이더를 작동할 때 알아두면 유용한 내용입니다. 35 | 36 | ## 스왑체인(Swapchain) 37 | GPU가 올바르게 초기화했지만, 화면에 실제로 렌더링을 수행해야 합니다. 이를 위해 스왑체인(swapchain)을 사용합니다. 스왑체인은 OS 또는 창 시스템이 제공하는 구조로, 이미지를 그린 후 화면에 표시할 수 있도록 합니다. 스왑체인은 Vulkan의 핵심 사양은 아닙니다. 선택적 기능이며 플랫폼마다 차이가 있을 수 있습니다. 만약 Vulkan을 컴퓨트 셰이더 계산 혹은 오프라인 렌더링에 사용한다면, 스왑체인을 설정할 필요는 없습니다. 38 | 39 | 스왑체인은 주어진 크기로 생성되며, 창 크기가 변경된다면 스왑체인을 다시 만들어야 합니다. 40 | 41 | 스왑체인 이미지의 포맷은 플랫폼과 GPU에 따라 달라질 수 있습니다. 따라서 스왑체인에서 요구하는 포맷의 이미지를 저장해야 합니다. 다른 포맷의 이미지를 렌더링하면 그래픽 이상이나 크래시가 일어날 수 있기 때문입니다. 42 | 43 | 스왑체인은 화면에 표시하기 위해 운영체제에서 접근할 수 있는 이미지와 이미지뷰(image-view)의 목록을 포함합니다. 스왑체인을 더 적거나 더 많은 이미지로 생성할 수도 있지만, 일반적으로 더블 버퍼링 혹은 트리플 버퍼링을 수행하기 위해 2,3개의 이미지만을 사용합니다. 44 | 45 | 스왑체인을 만들 때 가장 중요한 것은 표시 모드(Present Mode)를 선택하는 것입니다. 이는 스왑체인이 화면 표시와 어떻게 동기화할지를 제어합니다. 46 | 47 | 모든 표시 모드의 자세한 설명은 아래 Vulkan 사양 페이지에서 확인할 수 있습니다. [Vulkan Spec: VkPresentModeKHR](https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap34.html#VkPresentModeKHR) 48 | 49 | 50 | - `VK_PRESENT_MODE_IMMEDIATE_KHR` 스왑체인을 아무것도 기다리지 않고 이미지를 받는 즉시 표시하도록 합니다. 이는 화면 찢어짐(tearing)이 발생할 수 있으며 일반적으로 권장되지 않습니다. 51 | - `VK_PRESENT_MODE_FIFO_KHR` 새로고침 주기에 따라 표시할 이미지 큐(queue)를 사용합니다. 큐가 가득 차면 이미지가 표시되어 빈 공간이 생길 때 까지 애플리케이션이 대기합니다. 이는 "강한 VSync" 표시 모드이며, 애플리케이션의 FPS가 화면의 주사율에 고정됩니다. 52 | - `VK_PRESENT_MODE_FIFO_RELAXED_KHR` . Fifo VSync과 거의 같지만 VSync VSync가 유연하게 작동합니다. 만약 애플리케이션의 FPS가 화면의 최적 FPS보다 낮다면, 이미지를 즉시 표시하여 찢어짐(tearing) 현상이 발생할 수 있습니다. 예를 들어, 화면이 60Hz를 지원하는데 렌더링이 55Hz로 이루어진다면, 일반적인 Fifo에서는 다음 VSync주기 까지 대기해야 하므로 30FPS까지 떨어질 수 있지만, 이 모드는 그대로 55FPS로 표시합니다. 다만 이 과정에서 화면 찢어짐이 발생할 수 있습니다. 53 | - `VK_PRESENT_MODE_MAILBOX_KHR` . 이 모드는 이미지 목록을 유지하며, 한 이미지가 화면에 표시되는 동안 나머지 이미지에 계속해서 렌더링할 수 있습니다. 이미지를 표시할 시점이 되면 가장 최근에 렌더링 된 이미지를 선택합니다. 엄격한 VSync 없이 트리플 버퍼링을 사용하고 싶을 때 적합한 방식입니다. 54 | 55 | `VK_PRESENT_MODE_IMMEDIATE_KHR`은 찢어짐 현상 거의 사용되지 않습니다. 극도로 낮은 지연이 필요한 경우, 찢어짐 현상을 감수하고 사용할 수도 있습니다. 56 | 57 | 일반적인 애플리케이션은 MAILBOX 혹은 FIFO중 하나를 사용합니다. 이는 엄격한 VSync를 원하는 지, 혹은 트리플 버퍼링을 선호하는 지에 따라 달라집니다. 58 | 59 | 이 가이드에서는 `FIFO_RELAXED` 모드를 사용하겠습니다. 렌더링 속도의 상한을 설정해주며, 많은 객체를 렌더링하지 않으므로 프레임 속도가 5000FPS까지 올라가 과열 등의 문제가 발생하는 것을 방지하는 데 적합합니다. 하지만 실제 애플리케이션에서 작업 부하가 있다면 `MAILBOX`가 더 적절할 수 있습니다. 60 | 61 | ^nextlink 62 | 63 | {% include comments.html term="Vkguide 2 Korean Comments" %} 64 | -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_2/chapter-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "2. Drawing with Compute - KO" 4 | nav_order: 14 5 | parent: "Korean VKGuide" 6 | has_children: true 7 | permalink: /docs/ko/new_vkguide/chapter_2 8 | auto_comments: Vkguide 2 Beta Comments 9 | --- 10 | # 2장 : 컴퓨트 셰이더 그리기 11 | 12 | 이 장에서는 컴퓨트 셰이더를 사용해 그리기를 시작할 것입니다. 사용자 인터페이스를 추가하기 위해 DearImgui 라이브러리도 함께 설정하겠습니다. 13 | 14 | {: .fs-6 .fw-300 } 15 | -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_3/blending.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Blending 4 | grand_parent: "Korean VKGuide" 5 | parent: "3. Graphics Pipelines - KO" 6 | nav_order: 20 7 | --- 8 | 9 | 파이프라인 빌더를 생성할 때, 블렌딩 로직은 완전히 생략했었습니다. 블렌딩은 투명한 객체나 몇몇 그래픽 효과에 필수적으로 사용되기 때문에 중요한 기능입니다. 따라서 이번에는 지난 글에서 렌더링한 사각형을 투명하게 만들겠습니다. 10 | 11 | ## 파이프라인 블렌딩 12 | 셰이더에서 블렌딩을 제어할 수는 없으며, 이는 파이프라인의 속성입니다. GPU 하드웨어 자체가 블렌딩 연산을 처리하며, 다양한 옵션을 제공합니다. PipelineBuilder에 2가지 새로운 블렌딩 모드를 추가해 보겠습니다. 하나는 단순히 색상을 더하는 addtive blending, 다른 하나는 색상과 알파 값을 섞는 alpha blending 입니다. 13 | 14 | PipelineBuilder에 다음 두 함수를 추가합니다. 15 | 16 | ^code alphablend shared/vk_pipelines.cpp 17 | 18 | Vulkan에서 블렌딩 옵션을 설정할 때 색상과 알파값에 각각에 대해 블렌딩 식을 지정해주어야 합니다. 색상과 알파에 매개변수는 동일하게 동작하며, 블렌딩 식은 다음과 같은 방식으로 작동합니다. 19 | 20 | ``` 21 | outColor = srcColor * srcColorBlendFactor dstColor * dstColorBlendFactor; 22 | ``` 23 | 블렌딩에는 여러 연산자가 있지만, 대부분은 가장 기본적이고 안정적으로 작동하는 `VK_BLEND_OP_ADD`를 사용합니다. 그 외에도 다양한 고급 연산자들이 있지만, 대부분 확장이 필요하며 여기서는 다루지 않겠습니다. Source는 파이프라인에서 현재 처리중인 색상을 의미하고, Destination은 우리가 렌더링 중인 이미지의 현재 픽셀 값입니다. 24 | 25 | 위의 식을 바탕으로 덧셈 블렌딩이 어떻게 작동하는지 설명하겠습니다. 26 | 27 | `VK_BLEND_FACTOR_ONE`은 blend factor를 1.0으로 설정하므로, 곱셈 연산 없이 그대로 더해지게 됩니다. `VK_BLEND_FACTOR_SRC_ALPHA`은 반면 Source의 alpha 값을 곱합니다. 이 경우 우리의 블렌딩 공식은 다음과 같은 형태가 됩니다. 28 | ```c 29 | outColor = srcColor.rgb * srcColor.a + dstColor.rgb * 1.0 30 | ``` 31 | 32 | 알파 블렌딩을 사용할 경우 대신 다음과 같은 모습이 될 것입니다. 33 | 34 | ```c 35 | outColor = srcColor.rgb * srcColor.a + dstColor.rgb * (1.0 - srcColor.a) 36 | ``` 37 | 본질적으로 srcColor의 alpha값에 의해 제어되는 보간을 수행하는 셈이며, 이 alpha 값은 셰이더에서 전달됩니다. 38 | 39 | 이걸 사용해 어떤 결과가 나오는지 확인해 봅시다. 셰이더에서는 알파 값을 따로 설정하지 않았으니, addtive를 사용해 봅시다. `init_mesh_pipeline()`함수에서 블렌딩 설정을 변경해 주세요.` 40 | 41 | ```cpp 42 | //pipelineBuilder.disable_blending(); 43 | pipelineBuilder.enable_blending_additive(); 44 | ``` 45 | 46 | 이제 원숭이 메시가 반투명해진 것을 볼 수 있습니다. 다양한 블렌딩 모드를 시도해보면서 각각이 어떤 효과를 주는지 확인해 보세요. 47 | 48 | 4장으로 넘어가기 전에 창 크기 조정 기능을 구현해봅시다. 49 | 50 | ^nextlink 51 | 52 | {% include comments.html term="Vkguide 2 Korean Comments" %} -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_3/chapter-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "3. Graphics Pipelines - KO" 4 | nav_order: 16 5 | parent: "Korean VKGuide" 6 | has_children: true 7 | auto_comments: Vkguide 2 Beta Comments 8 | permalink: /docs/ko/new_vkguide/chapter_3 9 | --- 10 | # 3장 : 그래픽스 파이프라인 11 | 12 | 지금까지 컴퓨트 셰이더로 그리기를 수행해왔지만, 이번 장에서는 GPU의 본격적인 렌더링 기능을 활용하여 일반적인 그래픽스 파이프라인과 래스터화 시스템을 통해 메시를 그려보겠습니다. 13 | 14 | {: .fs-6 .fw-300 } 15 | 16 | -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_3/render_pipeline.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: The graphics pipeline 4 | parent: "3. Graphics Pipelines - KO" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 2 7 | --- 8 | 9 | 지금까지는 렌더링 루프를 구성하고 컴퓨트 셰이더를 사용해 이미지를 그릴 수 있는 방법을 마련했습니다. 하지만 아직은 실제 도형(geometry)을 그리지는 못합니다. 도형을 렌더링하려면 GPU 내부의 특수 하드웨어를 활용해 렌더링을 수행하기 위한 다양한 설정을 담고 있는 그래픽스 파이프라인을 설정해야 합니다. 이러한 작업을 제대로 수행하려면, 어떻게 Vulkan 렌더링 파이프라인이 작동하는지 이해해야 합니다. 10 | 11 | ## 렌더링 파이프라인 12 | GPU는 도형을 그릴 때 사용되는 다양한 기능을 갖고 있습니다. GPU는 범용 컴퓨팅 유닛과 별개로 렌더링을 위한 전용 하드웨어가 별도로 존재합니다. 이 전용 하드웨어들은 삼각형 혹은 다른 프리미티브를 빠르고 효율적으로 그릴 수 있게 해줍니다. 13 | 14 | GPU를 하나의 어셈블리 라인이라고 생각해도 좋습니다. 각 단계에서 서로 다른 작업을 수행하는 여러 구성요소가 있으며, 최종 결과물은 이미지에 렌더링된 픽셀입니다. 이 "어셈블리 라인"을 그래픽스 파이프라인이라 부릅니다. 15 | 16 | 그래픽스 파이프라인에서는 데이터와 프로그램이 입력되어 픽셀이 출력됩니다. 그래픽스 프로그래머의 일은 이를 요구사항에 맞게 적절히 구성하는 것입니다. 17 | 18 | 전체 Vulkan 그래픽스 파이프라인은 매우 복잡하므로, 우선 단순한 버전을 살펴볼 것입니다. 렌더링에 사용할 파이프라인을 구성해 나가면서 각 단계에 세부 내용도 함께 다뤄볼 것입니다. 19 | 20 | 그래픽스 파이프라인은 데이터 입력 → 정점 셰이더 → 래스터화 → 프래그먼트 셰이더 → 렌더링 출력 순으로 이뤄집니다. 21 | 22 | 두 셰이더 단계에서는 우리가 원하는 작업을 수행하도록 작성된 프로그램이 실행됩니다. 반면 래스터화와 렌더링 출력 단계는 고정된 기능을 수행하며, 이들에 대해서는 매개변수나 설정만 조정할 수 있습니다. 23 | 24 | 우선 데이터를 준비해야 합니다 이 데이터는 텍스쳐, 3D 모델, 머테리얼 등 우리가 원하는 어떤 것이든 될 수 있습니다. 이러한 데이터는 파이프라인의 각 단계를 거치며 변환되어 결국 화면에 픽셀로 나타나게 됩니다. 25 | 26 | 정점 셰이더는 모든 정점마다 한 번씩 실행되며, 정점의 위치와 그 외 속성들을 GPU가 이해할 수 있는 형태로 변환해 래스터화 단계에 전달하는 역할을 합니다. 27 | 28 | 래스터화 단계는 정점 셰이더에서 생성된 정점들을 받아와 삼각형이 화면에서 차지하는 픽셀을 계산합니다. 이렇게 계산된 픽셀들은 프래그먼트 셰이더로 전달됩니다. 이 과정은 그래픽스 파이프라인을 구성할 때 다양한 설정이 필요한 부분입니다. 29 | 30 | 프래그먼트 셰이더는 이러한 픽셀들을 실제 색상 픽셀로 출력하며, 래스터화 과정으로부터 받은 픽셀마다 한 번씩 실행됩니다. 31 | 32 | 렌더링 출력 단계에서는 최종 색상 픽셀을 출력 프레임 버퍼에 기록합니다. 이 단계에는 고정 기능 하드웨어 설정들이 포함되어 있으며, 블렌딩이나 깊이 테스트와 같은 작업이 수행됩니다. 33 | 34 | 다음 글에서는 지금까지 설명한 내용을 바탕으로 실제로 삼각형을 그려보겠습니다. 35 | 36 | ^nextlink 37 | 38 | {% include comments.html term="Vkguide 2 Korean Comments" %} -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_3/resizing_window.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Window Resizing 4 | parent: "3. Graphics Pipelines - KO" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 25 7 | --- 8 | 9 | ## 창 크기 재조정하기 10 | Vulkan에서는 창 크기 조정을 직접 처리해 주어야 합니다. 0장에서 이미 창이 최소화되었을 때를 처리하는 코드를 작성했지만, 창 크기 조정은 훨씬 더 복잡한 작업입니다. 11 | 12 | 창 크기가 조정될 때 스왑체인은 더 이상 유효하지 않게 되며, `vkAcquireNextImageKHR`, `vkQueuePresentKHR`과 같은 Vulkan의 스왑체인 명령은 `VK_ERROR_OUT_OF_DATE_KHR` 오류를 반환할 수 있습니다. 이를 올바르게 처리하여 스왑체인을 새로운 크기로 재생성하게 해야 합니다. 13 | 14 | 효율성을 위해 drawImage를 재할당하지는 않을 것입니다. 지금 당장은 drawImage와 depthImage만을 갖지만 조금 더 고도화된 엔진에서는 상당히 많은 이미지가 있을 것이며 이 모든 것을 재생성하는 것은 번거롭고 비용이 큽니다. 대신, drawImage와 depthImage를 시작 시 프리셋된 크기로 생성해 창이 작을 경우 해당 이미지의 일부분에 렌더링하고, 창이 커지면 더 넓은 영역에 렌더링하도록 합니다. 이미지를 재할당하지 않고 구석에만 렌더링하기 때문에 이 로직은 동적 해상도 구현에도 응용할 수 있습니다. 동적 해상도는 성능을 유연하게 조정할 수 있는 좋은 방법이며, 디버깅 시에도 유용하게 활용할 수 있습니다. 현재 drawImage에서 스왑체인 이미지로 VkCmdBlit을 사용해 복사하고 있으며, 이 연산은 확대 축소를 수행하기 때문에 이러한 방식에서도 잘 작동할 것입니다. 물론 이러한 방식의 확대 축소는 최고 품질은 아닙니다. 일반적으로는 확대 시 sharpening같은 추가 필터를 적요하거나, 안티앨리어싱 효과를 흉내내는 등의 복잡한 처리가 더해져야 좋은 품질을 얻을 수 있습니다. ImGui UI는 여전히 스왑체인 이미지에 직접 그릴 것이므로, 항상 네이티브 해상도로 렌더링할 것입니다. 15 | 16 | 이제 창 생성 시 창 크기 조정 가능(resizable) 플래그를 활성화해봅시다. 그후 실제로 창 크기를 조정해 보면 어떤 일이 일어나는지 확인해볼 수 있습니다. 17 | 18 | `VulkanEngine::init`의 상단에 window_flags를 바꾸어 resizable 플래그를 갖도록 합니다. 19 | 20 | ```cpp 21 | SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE); 22 | ``` 23 | SDL은 창 크기 조정과 관련된 운영체제 레벨의 처리를 담당하므로, 지금 당장 창 크기 조정을 시도해볼 수 있습니다. 엔진을 실행해 창을 재조정해봅시다. 24 | 25 | 이 작업을 하면 `vkAcquireNextImageKHR` 혹은 `vkQueuePresentKHR` 중 하나에서 VK_CHECK 매크로가 에러를 감지하고 크래시가 발생할 것입니다. 발생하는 에러는 `VK_ERROR_OUT_OF_DATE_KHR`일 가능성이 큽니다. 따라서 이 에러를 제대로 처리하려면, 해당 에러가 발생했을 때 렌더링을 중단하고 스왑체인을 다시 생성해 주어야 합니다. 26 | 27 | 먼저, VulkanEngine 클래스에 `resize_requested`라는 이름의 bool 변수를 추가합니다. 28 | 29 | draw()함수에 `vkAcquireNextImageKHR` 호출을 에러 코드를 확인하는 코드로 대체합니다. 30 | 31 | ```cpp 32 | VkResult e = vkAcquireNextImageKHR(_device, _swapchain, 1000000000, get_current_frame()._swapchainSemaphore, nullptr, &swapchainImageIndex); 33 | if (e == VK_ERROR_OUT_OF_DATE_KHR) { 34 | resize_requested = true; 35 | return ; 36 | } 37 | ``` 38 | 39 | 또한 `vkQueuePresentKHR`도 동일하게 대체합니다. 하지만 이미 함수의 끝이기 때문에 `return`은 하지 않습니다. 40 | ```cpp 41 | VkResult presentResult = vkQueuePresentKHR(_graphicsQueue, &presentInfo); 42 | if (presentResult == VK_ERROR_OUT_OF_DATE_KHR) { 43 | resize_requested = true; 44 | } 45 | ``` 46 | 47 | 이제 해당 에러가 발생하면 렌더링을 중단하게 되므로, 창 크기를 조정해도 크래시는 발생하지 않겠지만, 화면이 다시 그려지지 않고 이미지가 멈춘 상태로 유지될 것입니다. 48 | 49 | `resize_swapchain()`함수를 추가하여 VulkanEngine이 스왑체인을 재생성하도록 합시다. 50 | 51 | ^code resize_swap chapter-3/vk_engine.cpp 52 | 53 | 스왑체인을 재생성하기 위해 GPU가 모든 렌더링 작업을 완료할 때 까지 대기해야 합니다. GPU가 여전히 이미지와 이미지 뷰를 사용중일 수 있기 때문에, 그 상태에서 변경해서는 안됩니다. 그후 스왑체인을 파괴하고 SDL로부터 창크기를 조회하여 그에 맞게 새로 생성합니다. 54 | 55 | 이제 run() 반복문에서 이미지가 재조정될 때 이 함수를 호출해야 합니다. 56 | 57 | SDL 이벤트 루프와 freeze_rendering 확인 이후, 새로운 ImGui 프레임을 시작하는 함수들보다 먼저 이 함수를 호출하도록 코드를 추가합니다. 58 | ```cpp 59 | if (resize_requested) { 60 | resize_swapchain(); 61 | } 62 | ``` 63 | 64 | 이제 재조정 기능이 구현되었으니 한번 시도해보세요. 이제 에러 없이 이미지 축소가 가능합니다. 하지만 창을 더 크게 만든다면 실패할 것입니다. drawImage 영역 밖으로 렌더링하려고 시도했기 때문입니다. 이 문제는 _drawExtent 변수를 도입하고 해당 변수가 drawImage 크기를 초과하지 않도록 설정함으로써 해결할 수 있습니다. 65 | 66 | `_drawExtent`와 동적 해상도 조절을 위해 사용할 `renderScale` float를 VulkanEngine 클래스에 추가해줍니다. 67 | 68 | ```cpp 69 | VkExtent2D _drawExtent; 70 | float renderScale = 1.f; 71 | ``` 72 | 73 | draw() 함수로 돌아와 시작할 때 기존에 drawImage Extent를 사용하는 부분 대신 drawExtent를 계산하도록 합니다. 74 | 75 | ```cpp 76 | _drawExtent.height = std::min(_swapchainExtent.height, _drawImage.imageExtent.height) * renderScale; 77 | _drawExtent.width= std::min(_swapchainExtent.width, _drawImage.imageExtent.width) * renderScale; 78 | ``` 79 | 80 | 이제 ImGui에 슬라이더를 추가해 drawScale 파라미터를 제어할 수 있도록 하겠습니다. 81 | 82 | `run()`함수에서 배경 관련 파라미터를 설정하는 ImGui 창 내부의 상단에 이 슬라이더 코드를 추가해주세요. 83 | 84 | ```cpp 85 | if (ImGui::Begin("background")) { 86 | ImGui::SliderFloat("Render Scale",&renderScale, 0.3f, 1.f); 87 | //other code 88 | } 89 | ``` 90 | 91 | 이는 0.3에서 1.0까지의 렌더링 배율을 조정할 수 있는 슬라이더입니다. 1을 초과하면 해상도를 깨트릴 수 있기 때문에 제한합니다. 92 | 93 | 프로그램을 실행해 창 크기를 재조정하고 렌더링 배율을 조정해보세요. 이제 동적으로 해상도를 변경하고 창을 최대화하거나 이동할 수 있습니다. 94 | 95 | 현재 drawImage를 다소 작은 크기로 설정했지만 원한다면 init_swapchain()에서 생성되는 drawImage의 크기를 키워볼 수도 있습니다. _windowExntent 대신 모니터 해상도를 `drawImageExtent`에 직접 지정해보세요. 96 | 97 | 이것으로 3장이 끝났습니다. 이제 다음 장으로 넘어가겠습니다. 98 | 99 | Next: [Chapter 4: New Descriptor Abstractions]({{ site.baseurl }}{% link docs/ko/new_chapter_4/descriptor_abstractions.md %}) 100 | 101 | {% include comments.html term="Vkguide 2 Korean Comments" %} -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_4/chapter-4.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "4. Textures and Engine Architecture- KO" 4 | has_children: true 5 | nav_order: 17 6 | parent: "Korean VKGuide" 7 | permalink: /docs/ko/new_vkguide/chapter_4 8 | auto_comments: Vkguide 2 Beta Comments 9 | --- 10 | # 4장 : 텍스쳐와 엔진 아키텍처 11 | 12 | 이제 메시를 그릴 수 있지만, 몇 가지 작업할 일이 남았습니다. 이 장에서는 셰이더에 사용할 이미지를 불러오는 방법을 설정하고 성능과 확장성을 위한 렌더링 아키텍처를 설정하겠습니다. 13 | 14 | {: .fs-6 .fw-300 } 15 | -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_4/engine_arch.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Engine Architecture 4 | parent: "4. Textures and Engine Architecture- KO" 5 | grand_parent: "Korean VKGuide" 6 | nav_order: 10 7 | --- 8 | 9 | # 엔진 아키텍처 10 | 엔진을 구성하는 데 필요한 로우 레벨 기법은 이미 갖춰졌습니다. 임의의 메시를 그릴 수 있고, 버퍼나 텍스쳐 같은 데이터를 셰이더에 전달할 수 있습니다. 이제 필요한 것은 객체를 렌더링하기 위한 제대로된 아키텍처를 구축하고 VulkanEngine 클래스에 하드코딩된 구조체 사용을 지양하는 것입니다. 11 | 12 | 다음 장에서 GLTF 파일로부터 동적으로 전체 씬을 불러올 것이므로, 여기서의 아키텍쳐는 GLTF를 어느 정도 모방하게 됩니다. 우리는 GLTF의 PBR 사양을 기반으로 기본적인 GLTF 파이프라인을 만들고, 첫 번째 메시 클래스를 정의할 것입니다. 13 | 14 | 이 아키텍처는 두 단계의 구조체를 중심으로 구성됩니다. 그 중 하나는 RenderObject 구조체입니다. 15 | 16 | ```cpp 17 | struct RenderObject { 18 | uint32_t indexCount; 19 | uint32_t firstIndex; 20 | VkBuffer indexBuffer; 21 | 22 | MaterialInstance* material; 23 | 24 | glm::mat4 transform; 25 | VkDeviceAddress vertexBufferAddress; 26 | }; 27 | ``` 28 | 29 | 이 구조체는 VkCmdDrawIndexed 호출에 필요한 모든 파라미터를 평탄화한 추상화 구조입니다. 인덱싱에 필요한 정보와 함께, 특정 머테리얼에 해당하는 파이프라인과 디스크립터 셋을 가리키는 MaterialInstance 포인터를 포함합니다. 이어서 3D 렌더링에 필요한 행렬과 정점 버퍼의 포인터가 있으며, 이 두 요소는 객체마다 바뀌는 동적 데이터이므로 푸시 상수를 통해 전달됩니다. 30 | 31 | 이 구조체는 매 프레임 동적으로 작성되며, 렌더링 로직은 RenderObject 구조체 배열을 순회하면서 그리기 명령을 직접 기록하게 됩니다. 32 | 33 | MaterialInstance 구조체는 다음과 같습니다. 34 | ```cpp 35 | struct MaterialPipeline { 36 | VkPipeline pipeline; 37 | VkPipelineLayout layout; 38 | }; 39 | 40 | struct MaterialInstance { 41 | MaterialPipeline* pipeline; 42 | VkDescriptorSet materialSet; 43 | MaterialPass passType; 44 | }; 45 | ``` 46 | 47 | 머테리얼 시스템에는 두 개의 파이프라인, 즉 GLTF PBR 불투명용과 투명용으로 하드코딩될 것입니다. 두 파이프라인은 동일한 정점 및 프래그먼트 셰이더 쌍을 공유하며, 디스크립터 셋은 총 2개만 사용할 예정입니다. 슬롯 0번은 카메라 및 환경 정보와 같은 전역 데이터를 담는 디스크립터 셋으로, 한번 바인딩된 후 모든 드로우 콜에서 재사용됩니다. 이후 조명 정보 등도 추가할 예정입니다. 슬롯 1번은 머테리얼별 디스크립터 셋으로, 텍스쳐 및 머테리얼 파라미터를 바인딩하는 역할을 합니다. GLTF 사양을 그대로 반영하여, PBR GLTF 머테리얼이 요구하는 텍스쳐 외에도 객체 색상 등의 색상 상수를 포함하는 유니폼 버퍼를 사용할 것입니다. GLTF PBR 머테리얼은 특정 텍스쳐가 없어도 유효하지만, 이 경우 용도에 따라 기본 흰색 혹은 검은색 텍스쳐를 바인딩하게 됩니다. MaterialInstance 구조체는 MaterialPass 열거형을 갖는데 이는 불투명 객체와 투명 객체를 구분하는 데 사용됩니다. 48 | 49 | 2개의 파이프라인만 사용하는 이유는 파이프라인 수를 가능한 적게 유지하기 위함입니다. 파이프라인 수가 적으면 시작 시 사전 로딩이 가능하고, 특히 바인드리스 렌더링이나 draw-indirect 렌더링 로직을 도입했을 때 렌더링 속도가 향상됩니다. 우리의 목표는 GLTF PBR 머테리얼과 같은 각 머테리얼 타입에 대해 소수의 파이프라인만을 사용하는 것입니다. 렌더링 엔진이 필요로 하는 파이프라인 수는 성능에 큰 영향을 미칩니다. 예를 들어 둠 이터널 엔진과 같은 경우는 게임에 약 200여개의 파이프라인만 사용하지만, 언리얼 엔진 기반의 프로젝트인 경우 종종 10만 개 이상의 파이프라인을 사용합니다. 이처럼 지나치게 많은 파이프라인을 컴파일 하는 것은 렌더링 중 스터터링을 유발하고, 많은 저장 공간을 차지하며, draw-indirect와 같은 고급 기능의 구현에도 제약을 줍니다. 50 | 51 | RenderObject는 매우 로우 레벨의 구조이므로, 이를 생성하고 관리하기 위한 구조가 필요합니다. 여기에는 씬 그래프를 도입하겠습니다. 이렇게 하면 메시 간의 부모-자식 관계를 표현할 수 있으며, 메시가 없는 빈 노드도 가질 수 있습니다. 이는 게임 엔진에서 레벨을 구성하기 위한 전형적인 방식입니다. 52 | 53 | 이번에 설계할 씬 그래프는 중간 또는 다소 낮은 성능 구조이지만, 추후에 개선할 예정이며 매우 유연하고 확장성이 뛰어납니다. 현재 설계만으로도 수만 개의 객체 렌더링에는 충분한 성능을 제공합니다. 54 | 55 | ```cpp 56 | // base class for a renderable dynamic object 57 | class IRenderable { 58 | 59 | virtual void Draw(const glm::mat4& topMatrix, DrawContext& ctx) = 0; 60 | }; 61 | ``` 62 | 63 | 단일 Draw() 함수만을 정의하는 IRenderable 인터페이스가 있습니다. 이 함수는 부모로 사용할 행렬과 RenderContext를 인자로 받습니다. RenderContext는 현재로서는 렌더링할 객체들의 배열일 뿐입니다. 이 구조의 아이디어는 Draw() 함수가 호출될 때, 해당 객체가 이번 프레임에 렌더링할 항목에 Renderables을 추가하는 것입니다. 이 방식은 흔히 Immediate Design이라 불리며, 가장 큰 장점은 동일한 객체를 여러 번 다른 행렬을 사용하여 한 프레임 안에서 중복 렌더링할 수 있다는 점입니다. 또한 특정 로직에 따라 어떤 프레임에서는 Draw()를 호출하지 않음으로써 해당 객체를 렌더링하지 않을 수도 있습니다. 이 접근법은 자원 관리 및 객체 수명 관리가 훨씬 단순해지기 때문에 동적인 객체를 다룰 때 매우 유용하며, 코드 작성 또한 비교적 간단합니다. 단점으로는, 프레임마다 여러 객체를 순회하며 가상 함수를 호출하게 되는데, 객체 수가 많아질수록 이러한 호출 비용이 누적된다는 점입니다. 64 | 65 | Node 클래스는 IRenderable을 상속받을 것이며, 고유의 변환 행렬과 자식 노드의 배열을 가질 것입니다. Draw()가 호출될 때 자식 노드들의 Draw()도 호출하게 됩니다. 66 | 67 | MeshNode 클래스를 만들 것이며, 이는 Node를 상속받을 것입니다. 이 클래스는 렌더링에 필요한 자원들을 보유하고 있으며, Draw()가 호출되면 RenderObject를 생성해 DrawContext에 추가하게 됩니다. 68 | 69 | 조명과 같은 다른 렌더링 요소를 추가할 때도 동일한 구조로 동작합니다. DrawContext는 조명들의 목록을 유지하고, LightNode는 조명이 활성화되어 있을 경우 자신의 파라미터를 해당 목록에 추가합니다. 지형, 파티클 등 다른 렌더링 객체도 동일한 방식으로 처리할 수 있습니다. 70 | 71 | 우리가 사용할 한 가지 트릭은 GLTF를 추가할 때 LoadedGLTF라는 클래스를 만드는 것입니다. 이 클래스는 Node가 아닌 IRenderable을 직접 상속하며, 특정 GLTF 파일에 포함된 전체 상태와 텍스쳐, 메시같은 모든 자원을 포함합니다. 그리고 Draw()가 호출되면 해당 GLTF의 내용을 렌더링합니다. 비슷한 방식으로 OBJ와 같은 다른 포맷도 처리할 수 있어 유용합니다. 72 | 73 | 74 | GLTF를 불러오는 것은 다음 장에서 할 예정이지만, 지금은 RenderObject와 GLTF 머테리얼 처리 방식을 준비할 것입니다. 75 | 76 | ^nextlink 77 | 78 | {% include comments.html term="Vkguide 2 Korean Comments" %} -------------------------------------------------------------------------------- /vkguide_new_source/ko/new_chapter_5/chapter-5.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "5. GLTF loading - KO" 4 | nav_order: 18 5 | has_children: true 6 | parent: "Korean VKGuide" 7 | permalink: /docs/ko/new_vkguide/chapter_5 8 | auto_comments: Vkguide 2 Beta Comments 9 | --- 10 | # 5장 : GLTF 불러오기 11 | 12 | 기본적인 엔진 구성이 끝났습니다. 이번에는 GLTF 파일을 불러오고, 보다 고급 렌더링 기법을 설정하는 데 집중하겠습니다. 13 | 14 | {: .fs-6 .fw-300 } 15 | -------------------------------------------------------------------------------- /vkguide_new_source/new_chapter_0/building_project.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Building Project 4 | parent: "0. Project Setup" 5 | nav_order: 2 6 | auto_comments: Vkguide 2 Beta Comments 7 | --- 8 | 9 | # Building the project 10 | 11 | Start by syncing the Git project at . 12 | The all-chapters branch contains the example code for the entire project, and the starting-point branch contains the initial empty project setup. I recommend you sync both branches to different folders, and if at one point you get stuck, check how the code works in the all-chapters code. 13 | If you want a direct download to the code without using Git just download from these direct links. 14 | 15 | [All Chapters](https://github.com/vblanco20-1/vulkan-guide/archive/all-chapters-2.zip) 16 | 17 | [Starting Point](https://github.com/vblanco20-1/vulkan-guide/archive/starting-point-2.zip) 18 | 19 | 20 | You will need Visual Studio to build the project. The code in the project should work cross-platform, but this guide is windows-centric. 21 | 22 | First, install the Vulkan SDK . This will contain the development headers and libraries needed to create Vulkan applications. It is put in a global location, so you don't need to worry about where it gets installed. 23 | 24 | Then grab CMake, as it's the build system we are going to use. . 25 | 26 | Once CMake is installed, use CMake-gui to open the project root CMakeLists. Press the Configure button. 27 | 28 | If at this point it complains about not finding Vulkan_INCLUDE_DIR or Vulkan_LIBRARY, make sure you've finished installing the Vulkan SDK, then close and open CMake-Gui and try configuring again. 29 | 30 | Now that the dependencies are set, you can proceed with CMake and Configure then Generate the project files for Visual Studio (or your IDE of choice). 31 | 32 | From Visual Studio, select the engine target, set as Startup Project, and you can now compile and execute it by just hitting F5 (start debugging) 33 | 34 | ![vs]({{site.baseurl}}/assets/images/vs_compile.png) 35 | 36 | # Third party libraries 37 | Under the third_party folder, we have several different libraries that we are going to use across the tutorial. Those libraries are all embedded as sourcecode into the folder. Some of them have source code edits or are different from what is on their public repo 38 | 39 | This is the list of libraries we are using. 40 | 41 | - vulkan SDK: This one is not in the third_party folder, but its a dependency we have. You should have it installed from the explanation above 42 | - vkbootstrap: We will be using this to simplify the vulkan initialization logic. It will do things like select what gpu to use for us, and setup some initial structures. 43 | - VMA: Vulkan Memory Allocator. This is a library that implements high performance memory allocators for GPU structures. We will use that instead of trying to write the allocators ourselves. It will manage our GPU memory 44 | - SDL: Highly multiplatform library for windowing, input, audio, and a few other things. We will be using its windowing and input parts on the tutorial. 45 | - GLM : Math library. Will provide vectors, matrices, and so on. 46 | - {fmt} : String formatting and console output library. We will use it instead of std::cout as it runs significantly faster and gives us great utilities to display strings and other formatting options. 47 | - stb_image: for loading PNG or jpeg images. 48 | - dear imgui: Great UI library very useful for debug interfaces. Will lets us display some timings or add some UI windows. 49 | - fastgltf: High performance GLTF loading library. 50 | 51 | 52 | ^nextlink -------------------------------------------------------------------------------- /vkguide_new_source/new_chapter_0/chapter-0.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "0. Project Setup" 4 | nav_order: 11 5 | has_children: true 6 | permalink: /docs/new_vkguide/chapter_0 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | ![chapter0]({{site.baseurl}}/diagrams/chapter0.png) 10 | 11 | 12 | # Chapter 0 index 13 | 14 | 15 | In this chapter, we setup the build toolchain to compile the project 16 | 17 | {: .fs-6 .fw-300 } 18 | -------------------------------------------------------------------------------- /vkguide_new_source/new_chapter_1/chapter-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "1. Initializing Vulkan" 4 | nav_order: 13 5 | has_children: true 6 | permalink: /docs/new_vkguide/chapter_1 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | ![chapter1]({{site.baseurl}}/diagrams/chapter1.png) 10 | # Chapter 1 : Initialization and render Loop 11 | 12 | In this chapter, we are going to start the tutorial code, and configure the initial Vulkan structures needed to support rendering. 13 | We will also be writing the initial render loop, including command buffer and render image management. 14 | {: .fs-6 .fw-300 } 15 | 16 | -------------------------------------------------------------------------------- /vkguide_new_source/new_chapter_2/chapter-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "2. Drawing with Compute" 4 | nav_order: 14 5 | has_children: true 6 | permalink: /docs/new_vkguide/chapter_2 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | # Chapter 2 : Drawing with compute 10 | 11 | In this chapter, we are going to begin drawing using compute shaders. As part of the chapter, we will also setup DearImgui library to get some user interface. 12 | 13 | {: .fs-6 .fw-300 } 14 | -------------------------------------------------------------------------------- /vkguide_new_source/new_chapter_3/blending.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Blending 4 | parent: "3. Graphics Pipelines" 5 | nav_order: 20 6 | --- 7 | 8 | When we created the pipeline builder, we completely skipped over the blending logic, setting it as no blending. Blending is used for transparent objects and some graphical effects, so its important to have it. for that reason, we will make the rectangle we rendered last article transparent. 9 | 10 | ## Blending in the pipeline 11 | We cant really control blending from shaders, thats property of the pipeline. The gpu hardware itself does the blending mathematics for us, and has a bunch of options. We will be adding 2 new blending modes into the pipeline builder, one will be additive blending, where it just adds the colors, and the other alpha-blend, where it would mix the colors. 12 | 13 | Lets add these 2 functions into the pipeline builder 14 | 15 | ^code alphablend shared/vk_pipelines.cpp 16 | 17 | When setting blending options in vulkan, we need to fill the formula on both color and alpha. The parameters work the same on both color and alpha. The formula works like this 18 | 19 | ``` 20 | outColor = srcColor * srcColorBlendFactor dstColor * dstColorBlendFactor; 21 | ``` 22 | There are a few possible operators, but for the most part we will be doing `VK_BLEND_OP_ADD`, as its the most basic and guaranteed to work. There are many other much more advanced operators, but those come with extensions and we wont use them. Source (from srcColor and blend factor) refers to the color we are processing on our pipeline, and Destination (dstColor and blend factor) is the current value of the image we are rendering into. 23 | 24 | With the formula above, lets explain what the addition blending does. 25 | 26 | `VK_BLEND_FACTOR_ONE` sets the blend factor to just 1.0, so no multiplying. `VK_BLEND_FACTOR_SRC_ALPHA` on the other hand multiplies it by the alpha of the source. Our blending ends up as this formula 27 | ```c 28 | outColor = srcColor.rgb * srcColor.a + dstColor.rgb * 1.0 29 | ``` 30 | 31 | The alpha-blend one will look like this instead. 32 | 33 | ```c 34 | outColor = srcColor.rgb * srcColor.a + dstColor.rgb * (1.0 - srcColor.a) 35 | ``` 36 | Essentially making it into a lerp controlled by srcColor alpha, which will be from our shader. 37 | 38 | Lets try to use it to see what it does. We dont have alpha set in our shaders, so lets just try the additive one. Change the blending on the `init_mesh_pipeline()` function. 39 | 40 | ```cpp 41 | //pipelineBuilder.disable_blending(); 42 | pipelineBuilder.enable_blending_additive(); 43 | ``` 44 | 45 | You should now see the monkey mesh as semi-transparent, letting the color below it show.Play around with the blending modes to see what effects they result on. 46 | 47 | Before we move to chapter 4, lets implement window resizing. 48 | 49 | ^nextlink 50 | 51 | {% include comments.html term="Vkguide 2 Beta Comments" %} -------------------------------------------------------------------------------- /vkguide_new_source/new_chapter_3/chapter-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "3. Graphics Pipelines" 4 | nav_order: 16 5 | has_children: true 6 | auto_comments: Vkguide 2 Beta Comments 7 | permalink: /docs/new_vkguide/chapter_3 8 | --- 9 | # Chapter 3 : Graphics Pipelines 10 | 11 | We have already drawn with compute shaders, but in this chapter, we will use the real capabilities of a GPU to draw meshes using the rasterizer systems and the normal graphics pipeline. 12 | 13 | {: .fs-6 .fw-300 } 14 | 15 | -------------------------------------------------------------------------------- /vkguide_new_source/new_chapter_3/render_pipeline.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: The graphics pipeline 4 | parent: "3. Graphics Pipelines" 5 | nav_order: 2 6 | --- 7 | 8 | At this point, we have a draw loop and we have a way to draw into image using compute shader, but we cant render geometry yet. To render geometry, we need to setup a graphics pipeline that will contain all of the configuration options needed to draw geometry using the special hardware inside a GPU. 9 | To render things, we have to understand how the Vulkan rendering pipeline works. 10 | 11 | ## The render pipeline 12 | The GPU has a lot of functionality used for rendering geometry. They have a lot of extra hardware apart from the normal generic compute units. This extra hardware allows them to draw triangles or other primitives at great speed and efficiency. 13 | 14 | Think of a GPU as an assembly line. It has a lot of different parts doing different things, and the output is pixels rendered on a image. This "assembly line" is what we call the graphics pipeline. 15 | 16 | In the graphics pipeline, data and programs come in, and pixels come out. The job of a graphics programmer is to make sure to customize this to get the desired result. 17 | 18 | The full-scale Vulkan graphics pipeline is very complex, so we are going to view a simplified version of it. As we write the configuration for building our pipeline for rendering, we will go more into detail about the stages. 19 | 20 | Data -> Vertex Shader -> Rasterization -> Fragment Shader -> Render Output. 21 | 22 | The 2 shader stages will run custom programs that will do anything we want to. The Rasterization, and Render Output are Fixed stages, and we can only tweak their parameters and configuration. 23 | 24 | To begin, we need Data. The Data can be anything we want, and will be our textures, 3d models, material parameters, anything. Everything revolves around data being transformed by the stages until it becomes pixels on the screen. 25 | 26 | The vertex shader is a shader that will run once for every vertex we draw. Its job is to output vertex locations and vertex parameters in the way the GPU understands it for the Rasterization stage. 27 | 28 | The rasterization stage will grab the vertices generated by the Vertex shader, and it will find what pixels are covered by the triangle. These pixels will be sent to the fragment shader. This part has a lot of configuration options we will need to fill while building our graphics pipeline. 29 | 30 | The fragment shader takes care of turning those pixels into real colored pixels for the output, running the shader once per pixel that the rasterization stage sends to it. 31 | 32 | With the final colored pixels, we put them on the output framebuffer with the Render Output stage. There are multiple fixed-function hardware configuration steps here, that let us do things like blending pixels or depth-testing. 33 | 34 | Next article we will draw a triangle using all this. 35 | 36 | ^nextlink 37 | 38 | {% include comments.html term="Vkguide 2 Beta Comments" %} -------------------------------------------------------------------------------- /vkguide_new_source/new_chapter_4/chapter-4.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "4. Textures and Engine Architecture" 4 | has_children: true 5 | nav_order: 17 6 | permalink: /docs/new_vkguide/chapter_4 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | # Chapter 4 : Textures and engine architecture 10 | 11 | We are able to draw meshes now, but there are still some things that need doing. This chapter sets up image loading from files to use in shaders, and sets up a rendering architecture that is fast and extensible. 12 | 13 | {: .fs-6 .fw-300 } 14 | -------------------------------------------------------------------------------- /vkguide_new_source/new_chapter_5/chapter-5.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "5. GLTF loading" 4 | nav_order: 18 5 | has_children: true 6 | permalink: /docs/new_vkguide/chapter_5 7 | auto_comments: Vkguide 2 Beta Comments 8 | --- 9 | # Chapter 5 : GLTF Loading 10 | 11 | With the basics of the engine done, this chapter focuses on loading GLTF files and setting up more advanced rendering features. 12 | 13 | {: .fs-6 .fw-300 } 14 | --------------------------------------------------------------------------------