├── .clang-format ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── config ├── meson.build ├── vkBasalt.conf └── vkBasalt.json.in ├── format.sh ├── meson.build ├── meson_options.txt └── src ├── AreaTex.h ├── SearchTex.h ├── basalt.cpp ├── buffer.cpp ├── buffer.hpp ├── command_buffer.cpp ├── command_buffer.hpp ├── config.cpp ├── config.hpp ├── descriptor_set.cpp ├── descriptor_set.hpp ├── effect.cpp ├── effect.hpp ├── effect_cas.cpp ├── effect_cas.hpp ├── effect_deband.cpp ├── effect_deband.hpp ├── effect_dls.cpp ├── effect_dls.hpp ├── effect_fxaa.cpp ├── effect_fxaa.hpp ├── effect_lut.cpp ├── effect_lut.hpp ├── effect_reshade.cpp ├── effect_reshade.hpp ├── effect_simple.cpp ├── effect_simple.hpp ├── effect_smaa.cpp ├── effect_smaa.hpp ├── effect_transfer.cpp ├── effect_transfer.hpp ├── fake_swapchain.cpp ├── fake_swapchain.hpp ├── format.cpp ├── format.hpp ├── framebuffer.cpp ├── framebuffer.hpp ├── graphics_pipeline.cpp ├── graphics_pipeline.hpp ├── image.cpp ├── image.hpp ├── image_view.cpp ├── image_view.hpp ├── keyboard_input.cpp ├── keyboard_input.hpp ├── keyboard_input_x11.cpp ├── keyboard_input_x11.hpp ├── logger.cpp ├── logger.hpp ├── logical_device.hpp ├── logical_swapchain.cpp ├── logical_swapchain.hpp ├── lut_cube.cpp ├── lut_cube.hpp ├── memory.cpp ├── memory.hpp ├── meson.build ├── renderpass.cpp ├── renderpass.hpp ├── reshade ├── GLSL.std.450.h ├── LICENSE.md ├── effect_codegen.hpp ├── effect_codegen_spirv.cpp ├── effect_expression.cpp ├── effect_expression.hpp ├── effect_lexer.cpp ├── effect_lexer.hpp ├── effect_module.hpp ├── effect_parser.cpp ├── effect_parser.hpp ├── effect_preprocessor.cpp ├── effect_preprocessor.hpp ├── effect_symbol_table.cpp ├── effect_symbol_table.hpp ├── effect_symbol_table_intrinsics.inl ├── effect_token.hpp ├── meson.build └── spirv.hpp ├── reshade_uniforms.cpp ├── reshade_uniforms.hpp ├── sampler.cpp ├── sampler.hpp ├── shader.cpp ├── shader.hpp ├── shader ├── cas.frag.glsl ├── deband.frag.glsl ├── dls.frag.glsl ├── full_screen_triangle.vert.glsl ├── fxaa.frag.glsl ├── fxaa3_11.h ├── lut.frag.glsl ├── meson.build ├── smaa.h ├── smaa_blend.frag.glsl ├── smaa_blend.vert.glsl ├── smaa_edge.vert.glsl ├── smaa_edge_color.frag.glsl ├── smaa_edge_luma.frag.glsl ├── smaa_neighbor.frag.glsl ├── smaa_neighbor.vert.glsl └── smaa_settings.h ├── shader_sources.hpp ├── stb_image.c ├── stb_image.h ├── stb_image_dds.h ├── stb_image_resize.c ├── stb_image_resize.h ├── util.cpp ├── util.hpp ├── vkdispatch.cpp ├── vkdispatch.hpp ├── vkfuncs.hpp └── vulkan_include.hpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -4 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveMacros: true 7 | AlignConsecutiveAssignments: true 8 | AlignConsecutiveDeclarations: true 9 | AlignEscapedNewlines: DontAlign 10 | AlignOperands: true 11 | AlignTrailingComments: true 12 | AllowAllArgumentsOnNextLine: true 13 | AllowAllConstructorInitializersOnNextLine: true 14 | AllowAllParametersOfDeclarationOnNextLine: true 15 | AllowShortBlocksOnASingleLine: false 16 | AllowShortCaseLabelsOnASingleLine: true 17 | AllowShortFunctionsOnASingleLine: None 18 | AllowShortLambdasOnASingleLine: All 19 | AllowShortIfStatementsOnASingleLine: Never 20 | AllowShortLoopsOnASingleLine: false 21 | AlwaysBreakAfterReturnType: None 22 | AlwaysBreakBeforeMultilineStrings: false 23 | AlwaysBreakTemplateDeclarations: Yes 24 | BinPackArguments: false 25 | BinPackParameters: false 26 | BreakBeforeBraces: Custom 27 | BraceWrapping: 28 | AfterCaseLabel: true 29 | AfterClass: true 30 | AfterControlStatement: true 31 | AfterEnum: true 32 | AfterFunction: true 33 | AfterNamespace: true 34 | AfterObjCDeclaration: true 35 | AfterStruct: true 36 | AfterUnion: true 37 | AfterExternBlock: true 38 | BeforeCatch: true 39 | BeforeElse: true 40 | IndentBraces: false 41 | SplitEmptyFunction: true 42 | SplitEmptyRecord: true 43 | SplitEmptyNamespace: true 44 | BreakBeforeBinaryOperators: NonAssignment 45 | BreakBeforeInheritanceComma: false 46 | BreakInheritanceList: AfterColon 47 | BreakBeforeTernaryOperators: true 48 | BreakConstructorInitializersBeforeComma: false 49 | BreakConstructorInitializers: AfterColon 50 | BreakStringLiterals: true 51 | ColumnLimit: 150 52 | CompactNamespaces: false 53 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 54 | ConstructorInitializerIndentWidth: 4 55 | ContinuationIndentWidth: 4 56 | Cpp11BracedListStyle: true 57 | DerivePointerAlignment: false 58 | DisableFormat: false 59 | ExperimentalAutoDetectBinPacking: false 60 | FixNamespaceComments: true 61 | IncludeBlocks: Preserve 62 | IncludeIsMainRegex: '(Test)?$' 63 | IndentCaseLabels: true 64 | IndentPPDirectives: None 65 | IndentWidth: 4 66 | IndentWrappedFunctionNames: false 67 | JavaScriptQuotes: Leave 68 | JavaScriptWrapImports: true 69 | KeepEmptyLinesAtTheStartOfBlocks: true 70 | MacroBlockBegin: '' 71 | MacroBlockEnd: '' 72 | MaxEmptyLinesToKeep: 1 73 | NamespaceIndentation: All 74 | ObjCBinPackProtocolList: Auto 75 | ObjCBlockIndentWidth: 2 76 | ObjCSpaceAfterProperty: false 77 | ObjCSpaceBeforeProtocolList: true 78 | PenaltyBreakAssignment: 2 79 | PenaltyBreakBeforeFirstCallParameter: 19 80 | PenaltyBreakComment: 300 81 | PenaltyBreakFirstLessLess: 120 82 | PenaltyBreakString: 1000 83 | PenaltyBreakTemplateDeclaration: 10 84 | PenaltyExcessCharacter: 1000000 85 | PenaltyReturnTypeOnItsOwnLine: 60 86 | PointerAlignment: Left 87 | ReflowComments: true 88 | SortIncludes: false 89 | SortUsingDeclarations: false 90 | SpaceAfterCStyleCast: true 91 | SpaceAfterLogicalNot: false 92 | SpaceAfterTemplateKeyword: false 93 | SpaceBeforeAssignmentOperators: true 94 | SpaceBeforeCpp11BracedList: false 95 | SpaceBeforeCtorInitializerColon: true 96 | SpaceBeforeInheritanceColon: true 97 | SpaceBeforeParens: ControlStatements 98 | SpaceBeforeRangeBasedForLoopColon: true 99 | SpaceInEmptyParentheses: false 100 | SpacesBeforeTrailingComments: 1 101 | SpacesInAngles: false 102 | SpacesInContainerLiterals: false 103 | SpacesInCStyleCastParentheses: false 104 | SpacesInParentheses: false 105 | SpacesInSquareBrackets: false 106 | Standard: Auto 107 | TabWidth: 4 108 | UseTab: Never 109 | ... 110 | 111 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | src/stb_image.h linguist-vendored 2 | src/stb_image_resize.h linguist-vendored 3 | src/stb_image_dds.h linguist-vendored 4 | src/AreaTex.h linguist-generated 5 | src/SearchTex.h linguist-generated 6 | 7 | src/reshade/* linguist-vendored 8 | 9 | src/shader/smaa.h linguist-vendored 10 | src/shader/fxaa3_11.h linguist-vendored 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.spv 2 | *.old 3 | *.so 4 | *.o 5 | build*/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 - 2022 Georg Lehmann 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 19 | 3. This notice may not be removed or altered from any source distribution. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vkBasalt 2 | vkBasalt is a Vulkan post processing layer to enhance the visual graphics of games. 3 | 4 | Currently, the build in effects are: 5 | - Contrast Adaptive Sharpening 6 | - Denoised Luma Sharpening 7 | - Fast Approximate Anti-Aliasing 8 | - Enhanced Subpixel Morphological Anti-Aliasing 9 | - 3D color LookUp Table 10 | 11 | It is also possible to use Reshade Fx shaders. 12 | 13 | ## Disclaimer 14 | This is one of my first projects ever, so expect it to have bugs. Use it at your own risk. 15 | 16 | ## Building from Source 17 | 18 | ### Dependencies 19 | Before building, you will need: 20 | - GCC >= 9 21 | - X11 development files 22 | - glslang 23 | - SPIR-V Headers 24 | - Vulkan Headers 25 | 26 | ### Building 27 | 28 | **These instructions use `--prefix=/usr`, which is generally not recommened since vkBasalt will be installed in directories that are meant for the package manager. The alternative is not setting the prefix, it will then be installed in `/usr/local`. But you need to make sure that `ld` finds the library since /usr/local is very likely not in the default path.** 29 | 30 | In general, prefer using distro provided packages. 31 | 32 | ``` 33 | git clone https://github.com/DadSchoorse/vkBasalt.git 34 | cd vkBasalt 35 | ``` 36 | 37 | #### 64bit 38 | 39 | ``` 40 | meson setup --buildtype=release --prefix=/usr builddir 41 | ninja -C builddir install 42 | ``` 43 | #### 32bit 44 | 45 | Make sure that `PKG_CONFIG_PATH=/usr/lib32/pkgconfig` and `--libdir=lib32` are correct for your distro and change them if needed. On Debian based distros you need to replace `lib32` with `lib/i386-linux-gnu`, for example. 46 | ``` 47 | ASFLAGS=--32 CFLAGS=-m32 CXXFLAGS=-m32 PKG_CONFIG_PATH=/usr/lib32/pkgconfig meson setup --prefix=/usr --buildtype=release --libdir=lib32 -Dwith_json=false builddir.32 48 | ninja -C builddir.32 install 49 | ``` 50 | 51 | ## Packaging status 52 | 53 | [Debian](https://tracker.debian.org/pkg/vkbasalt) `sudo apt install vkbasalt` 54 | 55 | [Fedora](https://src.fedoraproject.org/rpms/vkBasalt) `sudo dnf install vkBasalt` 56 | 57 | [Void Linux](https://github.com/void-linux/void-packages/blob/master/srcpkgs/vkBasalt/template) `sudo xbps-install vkBasalt` 58 | 59 | ## Usage 60 | Enable the layer with the environment variable. 61 | 62 | ### Standard 63 | When using the terminal or an application (.desktop) file, execute: 64 | ```ini 65 | ENABLE_VKBASALT=1 yourgame 66 | ``` 67 | 68 | ### Lutris 69 | With Lutris, follow these steps below: 70 | 1. Right click on a game, and press `configure`. 71 | 2. Go to the `System options` tab and scroll down to `Environment variables`. 72 | 3. Press on `Add`, and add `ENABLE_VKBASALT` under `Key`, and add `1` under `Value`. 73 | 74 | ### Steam 75 | With Steam, edit your launch options and add: 76 | ```ini 77 | ENABLE_VKBASALT=1 %command% 78 | ``` 79 | 80 | ## Configure 81 | 82 | Settings like the CAS sharpening strength can be changed in the config file. 83 | The config file will be searched for in the following locations: 84 | * a file set with the environment variable`VKBASALT_CONFIG_FILE=/path/to/vkBasalt.conf` 85 | * `vkBasalt.conf` in the working directory of the game 86 | * `$XDG_CONFIG_HOME/vkBasalt/vkBasalt.conf` or `~/.config/vkBasalt/vkBasalt.conf` if `XDG_CONFIG_HOME` is not set 87 | * `$XDG_DATA_HOME/vkBasalt/vkBasalt.conf` or `~/.local/share/vkBasalt/vkBasalt.conf` if `XDG_DATA_HOME` is not set 88 | * `/etc/vkBasalt.conf` 89 | * `/etc/vkBasalt/vkBasalt.conf` 90 | * `/usr/share/vkBasalt/vkBasalt.conf` 91 | 92 | If you want to make changes for one game only, you can create a file named `vkBasalt.conf` in the working directory of the game and change the values there. 93 | 94 | #### Reshade Fx shaders 95 | 96 | To run reshade fx shaders e.g. shaders from the [reshade repo](https://github.com/crosire/reshade-shaders), you have to set `reshadeTexturePath` and `reshadeIncludePath` to the matching dirctories from the repo. To then use a specific shader you need to set a custom effect name to the shader path and then add that effect name to `effects` like every other effect. 97 | 98 | ```ini 99 | effects = colorfulness:denoise 100 | 101 | colorfulness = /home/user/reshade-shaders/Shaders/Colourfulness.fx 102 | denoise = /home/user/reshade-shaders/Shaders/Denoise.fx 103 | reshadeTexturePath = /home/user/reshade-shaders/Textures 104 | reshadeIncludePath = /home/user/reshade-shaders/Shaders 105 | ``` 106 | 107 | #### Ingame Input 108 | 109 | The [HOME key](https://en.wikipedia.org/wiki/Home_key) can be used to disable and re-enable the applied effects, the key can also be changed in the config file. This is based on X11 so it won't work on pure wayland. It **should** however at least not crash without X11. 110 | 111 | 112 | #### Debug Output 113 | 114 | The amount of debug output can be set with the `VKBASALT_LOG_LEVEL` env var, e.g. `VKBASALT_LOG_LEVEL=debug`. Possible values are: `trace, debug, info, warn, error, none`. 115 | 116 | By default the logger outputs to stderr, a file as output location can be set with the `VKBASALT_LOG_FILE` env var, e.g. `VKBASALT_LOG_FILE="vkBasalt.log"`. 117 | 118 | 119 | ## FAQ 120 | 121 | #### Why is it called vkBasalt? 122 | It's a joke: vulkan post processing → after vulcan → basalt 123 | #### Does vkBasalt work with dxvk and vkd3d? 124 | Yes. 125 | #### Will vkBasalt get me banned? 126 | Maybe. To my knowledge this hasn't happened yet but don't blame me if your frog dies. 127 | #### Will there be a openGl version? 128 | No. I don't know anything about openGl and I don't want to either. Also openGl has no layer system like vulkan. 129 | #### Will there be a GUI in the future? 130 | Maybe, but not soon. 131 | #### So is vkBasalt just a reshade port for linux? 132 | Not really, most of the code was written from scratch. vkBasalt directly uses reshade source code for the shader compiler (thanks [@crosire](https://github.com/crosire)), but that's about it. 133 | #### Does every reshade shader work? 134 | No. Shaders that need multiple techniques do not work, there might still be problems with stencil and blending and depth buffer access isn't ready yet. 135 | #### You said that "depth buffer access isn't ready yet", what does this mean? 136 | There is a wip version that you can enable with `depthCapture = on`. It will lead to many problems especially on non nvidia hardware. Also the selected depth buffer isn't always the one you would want. 137 | #### Is there a way to change settings for reshade shaders? 138 | There is some support for it [#46](https://github.com/DadSchoorse/vkBasalt/pull/46). One easy way so to simply edit the shader file. 139 | -------------------------------------------------------------------------------- /config/meson.build: -------------------------------------------------------------------------------- 1 | data_dir = get_option('datadir') 2 | 3 | vulkan_layer_dir = join_paths(data_dir, 'vulkan', 'implicit_layer.d') 4 | 5 | configure_file( 6 | input : 'vkBasalt.json.in', 7 | output : 'vkBasalt.json', 8 | configuration : {'ld_lib_dir_vkbasalt' : ld_lib_dir_vkbasalt}, 9 | install : true, 10 | install_dir : vulkan_layer_dir, 11 | ) 12 | -------------------------------------------------------------------------------- /config/vkBasalt.conf: -------------------------------------------------------------------------------- 1 | #effects is a colon seperated list of effect to use 2 | #e.g.: effects = fxaa:cas 3 | #effects will be run in order from left to right 4 | #one effect can be run multiple times e.g. smaa:smaa:cas 5 | #cas - Contrast Adaptive Sharpening 6 | #dls - Denoised Luma Sharpening 7 | #fxaa - Fast Approximate Anti-Aliasing 8 | #smaa - Enhanced Subpixel Morphological Antialiasing 9 | #lut - Color LookUp Table 10 | effects = cas 11 | 12 | reshadeTexturePath = "/path/to/reshade-shaders/Textures" 13 | reshadeIncludePath = "/path/to/reshade-shaders/Shaders" 14 | depthCapture = off 15 | 16 | #toggleKey toggles the effects on/off 17 | toggleKey = Home 18 | 19 | #enableOnLaunch sets if the effects are enabled when started 20 | enableOnLaunch = True 21 | 22 | #casSharpness specifies the amount of sharpning in the CAS shader. 23 | #0.0 less sharp, less artefacts, but not off 24 | #1.0 maximum sharp more artefacts 25 | #Everything in between is possible 26 | #negative values sharpen even less, up to -1.0 make a visible difference 27 | casSharpness = 0.4 28 | 29 | #dlsSharpness specifies the amount of sharpening in the Denoised Luma Sharpening shader. 30 | #Increase to sharpen details within the image. 31 | #0.0 less sharp, less artefacts, but not off 32 | #1.0 maximum sharp more artefacts 33 | dlsSharpness = 0.5 34 | 35 | #dlsDenoise specifies the amount of denoising in the Denoised Luma Sharpening shader. 36 | #Increase to limit how intensely film grain within the image gets sharpened. 37 | #0.0 min 38 | #1.0 max 39 | dlsDenoise = 0.17 40 | 41 | #fxaaQualitySubpix can effect sharpness. 42 | #1.00 - upper limit (softer) 43 | #0.75 - default amount of filtering 44 | #0.50 - lower limit (sharper, less sub-pixel aliasing removal) 45 | #0.25 - almost off 46 | #0.00 - completely off 47 | fxaaQualitySubpix = 0.75 48 | 49 | #fxaaQualityEdgeThreshold is the minimum amount of local contrast required to apply algorithm. 50 | #0.333 - too little (faster) 51 | #0.250 - low quality 52 | #0.166 - default 53 | #0.125 - high quality 54 | #0.063 - overkill (slower) 55 | fxaaQualityEdgeThreshold = 0.125 56 | 57 | #fxaaQualityEdgeThresholdMin trims the algorithm from processing darks. 58 | #0.0833 - upper limit (default, the start of visible unfiltered edges) 59 | #0.0625 - high quality (faster) 60 | #0.0312 - visible limit (slower) 61 | #Special notes: due to the current implementation you 62 | #Likely want to set this to zero. 63 | #As colors that are mostly not-green 64 | #will appear very dark in the green channel! 65 | #Tune by looking at mostly non-green content, 66 | #then start at zero and increase until aliasing is a problem. 67 | fxaaQualityEdgeThresholdMin = 0.0312 68 | 69 | #smaaEdgeDetection changes the edge detection shader 70 | #luma - default 71 | #color - might catch more edges, but is more expensive 72 | smaaEdgeDetection = luma 73 | 74 | #smaaThreshold specifies the threshold or sensitivity to edges 75 | #Lowering this value you will be able to detect more edges at the expense of performance. 76 | #Range: [0, 0.5] 77 | #0.1 is a reasonable value, and allows to catch most visible edges. 78 | #0.05 is a rather overkill value, that allows to catch 'em all. 79 | smaaThreshold = 0.05 80 | 81 | #smaaMaxSearchSteps specifies the maximum steps performed in the horizontal/vertical pattern searches 82 | #Range: [0, 112] 83 | #4 - low 84 | #8 - medium 85 | #16 - high 86 | #32 - ultra 87 | smaaMaxSearchSteps = 32 88 | 89 | #smaaMaxSearchStepsDiag specifies the maximum steps performed in the diagonal pattern searches 90 | #Range: [0, 20] 91 | #0 - low, medium 92 | #8 - high 93 | #16 - ultra 94 | smaaMaxSearchStepsDiag = 16 95 | 96 | #smaaCornerRounding specifies how much sharp corners will be rounded 97 | #Range: [0, 100] 98 | #25 is a reasonable value 99 | smaaCornerRounding = 25 100 | 101 | #lutFile is the path to the LUT file that will be used 102 | #supported are .CUBE files and .png with width == height * height 103 | lutFile = "/path/to/lut" 104 | -------------------------------------------------------------------------------- /config/vkBasalt.json.in: -------------------------------------------------------------------------------- 1 | { 2 | "file_format_version" : "1.0.0", 3 | "layer" : { 4 | "name": "VK_LAYER_VKBASALT_post_processing", 5 | "type": "GLOBAL", 6 | "library_path": "@ld_lib_dir_vkbasalt@libvkbasalt.so", 7 | "api_version": "1.3.223", 8 | "implementation_version": "1", 9 | "description": "a post processing layer", 10 | "functions": { 11 | "vkGetInstanceProcAddr": "vkBasalt_GetInstanceProcAddr", 12 | "vkGetDeviceProcAddr": "vkBasalt_GetDeviceProcAddr" 13 | }, 14 | "enable_environment": { 15 | "ENABLE_VKBASALT": "1" 16 | }, 17 | "disable_environment": { 18 | "DISABLE_VKBASALT": "1" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SOURCE="${BASH_SOURCE[0]}" 4 | while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink 5 | DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" 6 | SOURCE="$(readlink "$SOURCE")" 7 | [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located 8 | done 9 | DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" 10 | 11 | shopt -s expand_aliases 12 | if [ -f ~/.bash_aliases ]; then 13 | source ~/.bash_aliases 14 | fi 15 | 16 | clang-format -i $DIR/src/*cpp $DIR/src/*hpp 17 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('vkBasalt', ['c', 'cpp'], default_options: ['c_std=c11', 'cpp_std=c++2a']) 2 | 3 | cpp = meson.get_compiler('cpp') 4 | 5 | vkBasalt_include_path = '' 6 | 7 | lib_dir = get_option('libdir') 8 | ld_lib_dir_vkbasalt = '' 9 | 10 | if get_option('append_libdir_vkbasalt') 11 | lib_dir = join_paths(lib_dir, 'vkbasalt') 12 | ld_lib_dir_vkbasalt = get_option('prefix') + '/$LIB/vkbasalt/' 13 | endif 14 | 15 | if get_option('with_so') 16 | subdir('src') 17 | endif 18 | 19 | if get_option('with_json') 20 | subdir('config') 21 | endif 22 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('with_so', type : 'boolean', value : true, description : 'install the library') 2 | option('with_json', type : 'boolean', value : true, description : 'install the json') 3 | option('append_libdir_vkbasalt', type : 'boolean', value : false, description: 'Append "vkbasalt" to libdir path or not.') 4 | -------------------------------------------------------------------------------- /src/SearchTex.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2013 Jorge Jimenez (jorge@iryoku.com) 3 | * Copyright (C) 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com) 4 | * Copyright (C) 2013 Belen Masia (bmasia@unizar.es) 5 | * Copyright (C) 2013 Fernando Navarro (fernandn@microsoft.com) 6 | * Copyright (C) 2013 Diego Gutierrez (diegog@unizar.es) 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * this software and associated documentation files (the "Software"), to deal in 10 | * the Software without restriction, including without limitation the rights to 11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | * of the Software, and to permit persons to whom the Software is furnished to 13 | * do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. As clarification, there 17 | * is no requirement that the copyright notice and permission be included in 18 | * binary distributions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifndef SEARCHTEX_H 30 | #define SEARCHTEX_H 31 | 32 | #define SEARCHTEX_WIDTH 64 33 | #define SEARCHTEX_HEIGHT 16 34 | #define SEARCHTEX_PITCH SEARCHTEX_WIDTH 35 | #define SEARCHTEX_SIZE (SEARCHTEX_HEIGHT * SEARCHTEX_PITCH) 36 | 37 | /** 38 | * Stored in R8 format. Load it in the following format: 39 | * - DX9: D3DFMT_L8 40 | * - DX10: DXGI_FORMAT_R8_UNORM 41 | */ 42 | static const unsigned char searchTexBytes[] = { 43 | 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 44 | 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 46 | 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 47 | 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 48 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 52 | 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 54 | 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 55 | 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 56 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 57 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 58 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 62 | 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 63 | 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 66 | 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 68 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 70 | 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 71 | 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 73 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 74 | 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 78 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 79 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 80 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 81 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 82 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 83 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 84 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 85 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 86 | }; 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "buffer.hpp" 2 | #include "memory.hpp" 3 | 4 | namespace vkBasalt 5 | { 6 | void createBuffer(LogicalDevice* pLogicalDevice, 7 | VkDeviceSize size, 8 | VkBufferUsageFlags usage, 9 | VkMemoryPropertyFlags properties, 10 | VkBuffer& buffer, 11 | VkDeviceMemory& bufferMemory) 12 | { 13 | VkBufferCreateInfo bufferInfo = {}; 14 | 15 | bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 16 | bufferInfo.size = size; 17 | bufferInfo.usage = usage; 18 | bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 19 | 20 | VkResult result = pLogicalDevice->vkd.CreateBuffer(pLogicalDevice->device, &bufferInfo, nullptr, &buffer); 21 | ASSERT_VULKAN(result); 22 | 23 | VkMemoryRequirements memRequirements; 24 | pLogicalDevice->vkd.GetBufferMemoryRequirements(pLogicalDevice->device, buffer, &memRequirements); 25 | 26 | VkMemoryAllocateInfo allocInfo = {}; 27 | 28 | allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 29 | allocInfo.allocationSize = memRequirements.size; 30 | allocInfo.memoryTypeIndex = findMemoryTypeIndex(pLogicalDevice, memRequirements.memoryTypeBits, properties); 31 | 32 | result = pLogicalDevice->vkd.AllocateMemory(pLogicalDevice->device, &allocInfo, nullptr, &bufferMemory); 33 | ASSERT_VULKAN(result); 34 | 35 | result = pLogicalDevice->vkd.BindBufferMemory(pLogicalDevice->device, buffer, bufferMemory, 0); 36 | ASSERT_VULKAN(result); 37 | } 38 | 39 | } // namespace vkBasalt 40 | -------------------------------------------------------------------------------- /src/buffer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BUFFER_HPP_INCLUDED 2 | #define BUFFER_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | namespace vkBasalt 15 | { 16 | void createBuffer(LogicalDevice* pLogicalDevice, 17 | VkDeviceSize size, 18 | VkBufferUsageFlags usage, 19 | VkMemoryPropertyFlags properties, 20 | VkBuffer& buffer, 21 | VkDeviceMemory& bufferMemory); 22 | } 23 | 24 | #endif // BUFFER_HPP_INCLUDED 25 | -------------------------------------------------------------------------------- /src/command_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "command_buffer.hpp" 2 | 3 | #include "format.hpp" 4 | #include "util.hpp" 5 | 6 | namespace vkBasalt 7 | { 8 | std::vector allocateCommandBuffer(LogicalDevice* pLogicalDevice, uint32_t count) 9 | { 10 | std::vector commandBuffers(count); 11 | 12 | VkCommandBufferAllocateInfo allocInfo; 13 | allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; 14 | allocInfo.pNext = nullptr; 15 | allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; 16 | allocInfo.commandPool = pLogicalDevice->commandPool; 17 | allocInfo.commandBufferCount = count; 18 | 19 | VkResult result = pLogicalDevice->vkd.AllocateCommandBuffers(pLogicalDevice->device, &allocInfo, commandBuffers.data()); 20 | ASSERT_VULKAN(result); 21 | for (uint32_t i = 0; i < count; i++) 22 | { 23 | // initialize dispatch tables for commandBuffers since the are dispatchable objects 24 | initializeDispatchTable(commandBuffers[i], pLogicalDevice->device); 25 | } 26 | 27 | return commandBuffers; 28 | } 29 | void writeCommandBuffers(LogicalDevice* pLogicalDevice, 30 | std::vector> effects, 31 | VkImage depthImage, 32 | VkImageView depthImageView, 33 | VkFormat depthFormat, 34 | std::vector commandBuffers) 35 | { 36 | VkCommandBufferBeginInfo beginInfo = {}; 37 | 38 | beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; 39 | beginInfo.pNext = nullptr; 40 | beginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT; 41 | beginInfo.pInheritanceInfo = nullptr; 42 | 43 | for (auto& effect : effects) 44 | { 45 | effect->useDepthImage(depthImageView); 46 | } 47 | 48 | for (uint32_t i = 0; i < commandBuffers.size(); i++) 49 | { 50 | 51 | VkResult result = pLogicalDevice->vkd.BeginCommandBuffer(commandBuffers[i], &beginInfo); 52 | ASSERT_VULKAN(result); 53 | 54 | VkImageMemoryBarrier memoryBarrier; 55 | memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 56 | memoryBarrier.pNext = nullptr; 57 | memoryBarrier.image = depthImage; 58 | memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 59 | memoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 60 | memoryBarrier.srcAccessMask = 0; 61 | memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 62 | memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 63 | memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 64 | memoryBarrier.subresourceRange.aspectMask = 65 | isStencilFormat(depthFormat) ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; 66 | memoryBarrier.subresourceRange.baseMipLevel = 0; 67 | memoryBarrier.subresourceRange.levelCount = 1; 68 | memoryBarrier.subresourceRange.baseArrayLayer = 0; 69 | memoryBarrier.subresourceRange.layerCount = 1; 70 | 71 | if (depthImageView) 72 | { 73 | pLogicalDevice->vkd.CmdPipelineBarrier(commandBuffers[i], 74 | VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 75 | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 76 | 0, 77 | 0, 78 | nullptr, 79 | 0, 80 | nullptr, 81 | 1, 82 | &memoryBarrier); 83 | } 84 | 85 | for (uint32_t j = 0; j < effects.size(); j++) 86 | { 87 | Logger::debug("before applying effect " + convertToString(effects[j])); 88 | effects[j]->applyEffect(i, commandBuffers[i]); 89 | } 90 | 91 | memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 92 | memoryBarrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; 93 | memoryBarrier.dstAccessMask = 0; 94 | if (depthImageView) 95 | { 96 | pLogicalDevice->vkd.CmdPipelineBarrier(commandBuffers[i], 97 | VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 98 | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 99 | 0, 100 | 0, 101 | nullptr, 102 | 0, 103 | nullptr, 104 | 1, 105 | &memoryBarrier); 106 | } 107 | 108 | result = pLogicalDevice->vkd.EndCommandBuffer(commandBuffers[i]); 109 | ASSERT_VULKAN(result); 110 | } 111 | } 112 | 113 | std::vector createSemaphores(LogicalDevice* pLogicalDevice, uint32_t count) 114 | { 115 | std::vector semaphores(count); 116 | VkSemaphoreCreateInfo info; 117 | info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; 118 | info.pNext = nullptr; 119 | info.flags = 0; 120 | 121 | for (uint32_t i = 0; i < count; i++) 122 | { 123 | pLogicalDevice->vkd.CreateSemaphore(pLogicalDevice->device, &info, nullptr, &semaphores[i]); 124 | } 125 | return semaphores; 126 | } 127 | 128 | } // namespace vkBasalt 129 | -------------------------------------------------------------------------------- /src/command_buffer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COMMAND_BUFFER_HPP_INCLUDED 2 | #define COMMAND_BUFFER_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | #include "effect.hpp" 15 | namespace vkBasalt 16 | { 17 | 18 | std::vector allocateCommandBuffer(LogicalDevice* pLogicalDevice, uint32_t count); 19 | 20 | void writeCommandBuffers(LogicalDevice* pLogicalDevice, 21 | std::vector> effects, 22 | VkImage depthImage, 23 | VkImageView depthImageView, 24 | VkFormat depthFormat, 25 | std::vector commandBuffers); 26 | 27 | std::vector createSemaphores(LogicalDevice* pLogicalDevice, uint32_t count); 28 | } // namespace vkBasalt 29 | 30 | #endif // COMMAND_BUFFER_HPP_INCLUDED 31 | -------------------------------------------------------------------------------- /src/config.cpp: -------------------------------------------------------------------------------- 1 | #include "config.hpp" 2 | #include "config_paths.hpp" 3 | 4 | #include 5 | #include 6 | 7 | namespace vkBasalt 8 | { 9 | Config::Config() 10 | { 11 | // Custom config file path 12 | const char* tmpConfEnv = std::getenv("VKBASALT_CONFIG_FILE"); 13 | std::string customConfigFile = tmpConfEnv ? std::string(tmpConfEnv) : ""; 14 | 15 | // User config file path 16 | const char* tmpHomeEnv = std::getenv("XDG_DATA_HOME"); 17 | std::string userConfigFile = tmpHomeEnv ? std::string(tmpHomeEnv) + "/vkBasalt/vkBasalt.conf" 18 | : std::string(std::getenv("HOME")) + "/.local/share/vkBasalt/vkBasalt.conf"; 19 | 20 | const char* tmpConfigEnv = std::getenv("XDG_CONFIG_HOME"); 21 | std::string userXdgConfigFile = tmpConfigEnv ? std::string(tmpConfigEnv) + "/vkBasalt/vkBasalt.conf" 22 | : std::string(std::getenv("HOME")) + "/.config/vkBasalt/vkBasalt.conf"; 23 | 24 | // Allowed config paths 25 | const std::array configPath = { 26 | customConfigFile, // custom config (VKBASALT_CONFIG_FILE=/path/to/vkBasalt.conf) 27 | "vkBasalt.conf", // per game config 28 | userXdgConfigFile, // user-global config 29 | userConfigFile, // legacy default config 30 | std::string(SYSCONFDIR) + "/vkBasalt.conf", // system-wide config 31 | std::string(SYSCONFDIR) + "/vkBasalt/vkBasalt.conf", // system-wide config (alternative) 32 | std::string(DATADIR) + "/vkBasalt/vkBasalt.conf", // legacy system-wide config 33 | }; 34 | 35 | for (const auto& cFile : configPath) 36 | { 37 | std::ifstream configFile(cFile); 38 | if (!configFile.good()) 39 | continue; 40 | 41 | Logger::info("config file: " + cFile); 42 | readConfigFile(configFile); 43 | return; 44 | } 45 | 46 | Logger::err("no good config file"); 47 | } 48 | 49 | Config::Config(const Config& other) 50 | { 51 | this->options = other.options; 52 | } 53 | 54 | void Config::readConfigFile(std::ifstream& stream) 55 | { 56 | std::string line; 57 | 58 | while (std::getline(stream, line)) 59 | { 60 | readConfigLine(line); 61 | } 62 | } 63 | 64 | void Config::readConfigLine(std::string line) 65 | { 66 | std::string key; 67 | std::string value; 68 | 69 | bool inQuotes = false; 70 | bool foundEquals = false; 71 | 72 | auto appendChar = [&key, &value, &foundEquals](const char& newChar) { 73 | if (foundEquals) 74 | value += newChar; 75 | else 76 | key += newChar; 77 | }; 78 | 79 | for (const char& nextChar : line) 80 | { 81 | if (inQuotes) 82 | { 83 | if (nextChar == '"') 84 | inQuotes = false; 85 | else 86 | appendChar(nextChar); 87 | continue; 88 | } 89 | switch (nextChar) 90 | { 91 | case '#': goto BREAK; 92 | case '"': inQuotes = true; break; 93 | case '\t': 94 | case ' ': break; 95 | case '=': foundEquals = true; break; 96 | default: appendChar(nextChar); break; 97 | } 98 | } 99 | 100 | BREAK: 101 | 102 | if (!key.empty() && !value.empty()) 103 | { 104 | Logger::info(key + " = " + value); 105 | options[key] = value; 106 | } 107 | } 108 | 109 | void Config::parseOption(const std::string& option, int32_t& result) 110 | { 111 | auto found = options.find(option); 112 | if (found != options.end()) 113 | { 114 | try 115 | { 116 | result = std::stoi(found->second); 117 | } 118 | catch (...) 119 | { 120 | Logger::warn("invalid int32_t value for: " + option); 121 | } 122 | } 123 | } 124 | 125 | void Config::parseOption(const std::string& option, float& result) 126 | { 127 | auto found = options.find(option); 128 | if (found != options.end()) 129 | { 130 | // TODO find a better float parsing way, std::stof has locale issues 131 | std::stringstream ss(found->second); 132 | ss.imbue(std::locale("C")); 133 | float value; 134 | ss >> value; 135 | 136 | bool failed = ss.fail(); 137 | 138 | std::string rest; 139 | ss >> rest; 140 | if (failed || (!rest.empty() && rest != "f")) 141 | { 142 | Logger::warn("invalid float value for: " + option); 143 | } 144 | else 145 | { 146 | result = value; 147 | } 148 | } 149 | } 150 | 151 | void Config::parseOption(const std::string& option, bool& result) 152 | { 153 | auto found = options.find(option); 154 | if (found != options.end()) 155 | { 156 | if (found->second == "True" || found->second == "true" || found->second == "1") 157 | { 158 | result = true; 159 | } 160 | else if (found->second == "False" || found->second == "false" || found->second == "0") 161 | { 162 | result = false; 163 | } 164 | else 165 | { 166 | Logger::warn("invalid bool value for: " + option); 167 | } 168 | } 169 | } 170 | 171 | void Config::parseOption(const std::string& option, std::string& result) 172 | { 173 | auto found = options.find(option); 174 | if (found != options.end()) 175 | { 176 | result = found->second; 177 | } 178 | } 179 | 180 | void Config::parseOption(const std::string& option, std::vector& result) 181 | { 182 | auto found = options.find(option); 183 | if (found != options.end()) 184 | { 185 | result = {}; 186 | std::stringstream stringStream(found->second); 187 | std::string newString; 188 | while (getline(stringStream, newString, ':')) 189 | { 190 | result.push_back(newString); 191 | } 192 | } 193 | } 194 | } // namespace vkBasalt 195 | -------------------------------------------------------------------------------- /src/config.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_HPP_INCLUDED 2 | #define CONFIG_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | namespace vkBasalt 14 | { 15 | class Config 16 | { 17 | public: 18 | Config(); 19 | Config(const Config& other); 20 | 21 | template 22 | T getOption(const std::string& option, const T& defaultValue = {}) 23 | { 24 | T result = defaultValue; 25 | parseOption(option, result); 26 | return result; 27 | } 28 | 29 | private: 30 | std::unordered_map options; 31 | 32 | void readConfigLine(std::string line); 33 | void readConfigFile(std::ifstream& stream); 34 | 35 | void parseOption(const std::string& option, int32_t& result); 36 | void parseOption(const std::string& option, float& result); 37 | void parseOption(const std::string& option, bool& result); 38 | void parseOption(const std::string& option, std::string& result); 39 | void parseOption(const std::string& option, std::vector& result); 40 | }; 41 | } // namespace vkBasalt 42 | 43 | #endif // CONFIG_HPP_INCLUDED 44 | -------------------------------------------------------------------------------- /src/descriptor_set.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DESCRIPTOR_SET_HPP_INCLUDED 2 | #define DESCRIPTOR_SET_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | namespace vkBasalt 15 | { 16 | VkDescriptorPool createDescriptorPool(LogicalDevice* pLogicalDevice, const std::vector& poolSizes); 17 | 18 | VkDescriptorSetLayout createUniformBufferDescriptorSetLayout(LogicalDevice* pLogicalDevice); 19 | 20 | VkDescriptorSet writeBufferDescriptorSet(LogicalDevice* pLogicalDevice, 21 | VkDescriptorPool descriptorPool, 22 | VkDescriptorSetLayout descriptorSetLayout, 23 | VkBuffer buffer); 24 | 25 | VkDescriptorSetLayout createImageSamplerDescriptorSetLayout(LogicalDevice* pLogicalDevice, uint32_t count); 26 | 27 | std::vector allocateAndWriteImageSamplerDescriptorSets(LogicalDevice* pLogicalDevice, 28 | VkDescriptorPool descriptorPool, 29 | VkDescriptorSetLayout descriptorSetLayout, 30 | std::vector samplers, 31 | std::vector> imageViewsVectors); 32 | } // namespace vkBasalt 33 | 34 | #endif // DESCRIPTOR_SET_HPP_INCLUDED 35 | -------------------------------------------------------------------------------- /src/effect.cpp: -------------------------------------------------------------------------------- 1 | #include "effect.hpp" 2 | 3 | namespace vkBasalt 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/effect.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EFFECT_HPP_INCLUDED 2 | #define EFFECT_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | namespace vkBasalt 13 | { 14 | class Effect 15 | { 16 | public: 17 | void virtual applyEffect(uint32_t imageIndex, VkCommandBuffer commandBuffer) = 0; 18 | void virtual updateEffect(){}; 19 | void virtual useDepthImage(VkImageView depthImageView){}; 20 | virtual ~Effect(){}; 21 | 22 | private: 23 | }; 24 | } // namespace vkBasalt 25 | 26 | #endif // EFFECT_HPP_INCLUDED 27 | -------------------------------------------------------------------------------- /src/effect_cas.cpp: -------------------------------------------------------------------------------- 1 | #include "effect_cas.hpp" 2 | 3 | #include 4 | 5 | #include "image_view.hpp" 6 | #include "descriptor_set.hpp" 7 | #include "buffer.hpp" 8 | #include "renderpass.hpp" 9 | #include "graphics_pipeline.hpp" 10 | #include "framebuffer.hpp" 11 | #include "shader.hpp" 12 | #include "sampler.hpp" 13 | 14 | #include "shader_sources.hpp" 15 | 16 | namespace vkBasalt 17 | { 18 | CasEffect::CasEffect(LogicalDevice* pLogicalDevice, 19 | VkFormat format, 20 | VkExtent2D imageExtent, 21 | std::vector inputImages, 22 | std::vector outputImages, 23 | Config* pConfig) 24 | { 25 | 26 | float sharpness = pConfig->getOption("casSharpness", 0.4f); 27 | 28 | vertexCode = full_screen_triangle_vert; 29 | fragmentCode = cas_frag; 30 | 31 | VkSpecializationMapEntry sharpnessMapEntry; 32 | sharpnessMapEntry.constantID = 0; 33 | sharpnessMapEntry.offset = 0; 34 | sharpnessMapEntry.size = sizeof(float); 35 | 36 | VkSpecializationInfo fragmentSpecializationInfo; 37 | fragmentSpecializationInfo.mapEntryCount = 1; 38 | fragmentSpecializationInfo.pMapEntries = &sharpnessMapEntry; 39 | fragmentSpecializationInfo.dataSize = sizeof(float); 40 | fragmentSpecializationInfo.pData = &sharpness; 41 | 42 | pVertexSpecInfo = nullptr; 43 | pFragmentSpecInfo = &fragmentSpecializationInfo; 44 | 45 | init(pLogicalDevice, format, imageExtent, inputImages, outputImages, pConfig); 46 | } 47 | CasEffect::~CasEffect() 48 | { 49 | } 50 | } // namespace vkBasalt 51 | -------------------------------------------------------------------------------- /src/effect_cas.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EFFECT_CAS_HPP_INCLUDED 2 | #define EFFECT_CAS_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "effect_simple.hpp" 14 | #include "config.hpp" 15 | 16 | namespace vkBasalt 17 | { 18 | class CasEffect : public SimpleEffect 19 | { 20 | public: 21 | CasEffect(LogicalDevice* pLogicalDevice, 22 | VkFormat format, 23 | VkExtent2D imageExtent, 24 | std::vector inputImages, 25 | std::vector outputImages, 26 | Config* pConfig); 27 | ~CasEffect(); 28 | }; 29 | } // namespace vkBasalt 30 | 31 | #endif // EFFECT_CAS_HPP_INCLUDED 32 | -------------------------------------------------------------------------------- /src/effect_deband.cpp: -------------------------------------------------------------------------------- 1 | #include "effect_deband.hpp" 2 | 3 | #include 4 | 5 | #include "image_view.hpp" 6 | #include "descriptor_set.hpp" 7 | #include "buffer.hpp" 8 | #include "renderpass.hpp" 9 | #include "graphics_pipeline.hpp" 10 | #include "framebuffer.hpp" 11 | #include "shader.hpp" 12 | #include "sampler.hpp" 13 | 14 | #include "shader_sources.hpp" 15 | 16 | namespace vkBasalt 17 | { 18 | DebandEffect::DebandEffect(LogicalDevice* pLogicalDevice, 19 | VkFormat format, 20 | VkExtent2D imageExtent, 21 | std::vector inputImages, 22 | std::vector outputImages, 23 | Config* pConfig) 24 | { 25 | vertexCode = full_screen_triangle_vert; 26 | fragmentCode = deband_frag; 27 | 28 | struct 29 | { 30 | float screenWidth; 31 | float screenHeight; 32 | float reverseScreenWidth; 33 | float reverseScreenHeight; 34 | float debandAvgdiff; 35 | float debandMaxdiff; 36 | float debandMiddiff; 37 | float range; 38 | int32_t iterations; 39 | } debandOptions{}; 40 | 41 | debandOptions.screenWidth = (float) imageExtent.width; 42 | debandOptions.screenHeight = (float) imageExtent.height; 43 | debandOptions.reverseScreenWidth = 1.0f / imageExtent.width; 44 | debandOptions.reverseScreenHeight = 1.0f / imageExtent.height; 45 | 46 | // get Options 47 | debandOptions.debandAvgdiff = pConfig->getOption("debandAvgdiff", 3.4f); 48 | debandOptions.debandMaxdiff = pConfig->getOption("debandMaxdiff", 6.8f); 49 | debandOptions.debandMiddiff = pConfig->getOption("debandMiddiff", 3.3f); 50 | debandOptions.range = pConfig->getOption("debandRange", 16.0f); 51 | debandOptions.iterations = pConfig->getOption("debandIterations", 4); 52 | 53 | std::vector specMapEntrys(9); 54 | for (uint32_t i = 0; i < specMapEntrys.size(); i++) 55 | { 56 | specMapEntrys[i].constantID = i; 57 | specMapEntrys[i].offset = sizeof(float) * i; // TODO not clean to assume that sizeof(int32_t) == sizeof(float) 58 | specMapEntrys[i].size = sizeof(float); 59 | } 60 | 61 | VkSpecializationInfo specializationInfo; 62 | specializationInfo.mapEntryCount = specMapEntrys.size(); 63 | specializationInfo.pMapEntries = specMapEntrys.data(); 64 | specializationInfo.dataSize = sizeof(debandOptions); 65 | specializationInfo.pData = &debandOptions; 66 | 67 | pVertexSpecInfo = nullptr; 68 | pFragmentSpecInfo = &specializationInfo; 69 | 70 | init(pLogicalDevice, format, imageExtent, inputImages, outputImages, pConfig); 71 | } 72 | DebandEffect::~DebandEffect() 73 | { 74 | } 75 | } // namespace vkBasalt 76 | -------------------------------------------------------------------------------- /src/effect_deband.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EFFECT_DEBAND_HPP_INCLUDED 2 | #define EFFECT_DEBAND_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "effect_simple.hpp" 14 | #include "config.hpp" 15 | 16 | namespace vkBasalt 17 | { 18 | class DebandEffect : public SimpleEffect 19 | { 20 | public: 21 | DebandEffect(LogicalDevice* pLogicalDevice, 22 | VkFormat format, 23 | VkExtent2D imageExtent, 24 | std::vector inputImages, 25 | std::vector outputImages, 26 | Config* pConfig); 27 | ~DebandEffect(); 28 | }; 29 | } // namespace vkBasalt 30 | 31 | #endif // EFFECT_DEBAND_HPP_INCLUDED 32 | -------------------------------------------------------------------------------- /src/effect_dls.cpp: -------------------------------------------------------------------------------- 1 | #include "effect_dls.hpp" 2 | 3 | #include 4 | 5 | #include "image_view.hpp" 6 | #include "descriptor_set.hpp" 7 | #include "buffer.hpp" 8 | #include "renderpass.hpp" 9 | #include "graphics_pipeline.hpp" 10 | #include "framebuffer.hpp" 11 | #include "shader.hpp" 12 | #include "sampler.hpp" 13 | 14 | #include "shader_sources.hpp" 15 | 16 | namespace vkBasalt 17 | { 18 | DlsEffect::DlsEffect(LogicalDevice* pLogicalDevice, 19 | VkFormat format, 20 | VkExtent2D imageExtent, 21 | std::vector inputImages, 22 | std::vector outputImages, 23 | Config* pConfig) 24 | { 25 | float sharpness = pConfig->getOption("dlsSharpness", 0.5f); 26 | float denoise = pConfig->getOption("dlsDenoise", 0.17f); 27 | 28 | float specData[2] = {sharpness, denoise}; 29 | 30 | vertexCode = full_screen_triangle_vert; 31 | fragmentCode = dls_frag; 32 | 33 | VkSpecializationMapEntry mapEntries[2]; 34 | mapEntries[0].constantID = 0; 35 | mapEntries[0].offset = 0; 36 | mapEntries[0].size = sizeof(float); 37 | mapEntries[1].constantID = 1; 38 | mapEntries[1].offset = sizeof(float); 39 | mapEntries[1].size = sizeof(float); 40 | 41 | VkSpecializationInfo fragmentSpecializationInfo; 42 | fragmentSpecializationInfo.mapEntryCount = 1; 43 | fragmentSpecializationInfo.pMapEntries = mapEntries; 44 | fragmentSpecializationInfo.dataSize = sizeof(float) * 2; 45 | fragmentSpecializationInfo.pData = specData; 46 | 47 | pVertexSpecInfo = nullptr; 48 | pFragmentSpecInfo = &fragmentSpecializationInfo; 49 | 50 | init(pLogicalDevice, format, imageExtent, inputImages, outputImages, pConfig); 51 | } 52 | DlsEffect::~DlsEffect() 53 | { 54 | } 55 | } // namespace vkBasalt 56 | -------------------------------------------------------------------------------- /src/effect_dls.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "effect_simple.hpp" 13 | #include "config.hpp" 14 | 15 | namespace vkBasalt 16 | { 17 | class DlsEffect : public SimpleEffect 18 | { 19 | public: 20 | DlsEffect(LogicalDevice* pLogicalDevice, 21 | VkFormat format, 22 | VkExtent2D imageExtent, 23 | std::vector inputImages, 24 | std::vector outputImages, 25 | Config* pConfig); 26 | ~DlsEffect(); 27 | }; 28 | } // namespace vkBasalt 29 | -------------------------------------------------------------------------------- /src/effect_fxaa.cpp: -------------------------------------------------------------------------------- 1 | #include "effect_fxaa.hpp" 2 | 3 | #include 4 | 5 | #include "image_view.hpp" 6 | #include "descriptor_set.hpp" 7 | #include "buffer.hpp" 8 | #include "renderpass.hpp" 9 | #include "graphics_pipeline.hpp" 10 | #include "framebuffer.hpp" 11 | #include "shader.hpp" 12 | #include "sampler.hpp" 13 | 14 | #include "shader_sources.hpp" 15 | 16 | namespace vkBasalt 17 | { 18 | FxaaEffect::FxaaEffect(LogicalDevice* pLogicalDevice, 19 | VkFormat format, 20 | VkExtent2D imageExtent, 21 | std::vector inputImages, 22 | std::vector outputImages, 23 | Config* pConfig) 24 | { 25 | float fxaaQualitySubpix = pConfig->getOption("fxaaQualitySubpix", 0.75f); 26 | float fxaaQualityEdgeThreshold = pConfig->getOption("fxaaQualityEdgeThreshold", 0.125f); 27 | float fxaaQualityEdgeThresholdMin = pConfig->getOption("fxaaQualityEdgeThresholdMin", 0.0312f); 28 | 29 | vertexCode = full_screen_triangle_vert; 30 | fragmentCode = fxaa_frag; 31 | 32 | std::vector specMapEntrys(5); 33 | 34 | for (uint32_t i = 0; i < specMapEntrys.size(); i++) 35 | { 36 | specMapEntrys[i].constantID = i; 37 | specMapEntrys[i].offset = sizeof(float) * i; 38 | specMapEntrys[i].size = sizeof(float); 39 | } 40 | std::vector specData = { 41 | fxaaQualitySubpix, fxaaQualityEdgeThreshold, fxaaQualityEdgeThresholdMin, (float) imageExtent.width, (float) imageExtent.height}; 42 | 43 | VkSpecializationInfo fragmentSpecializationInfo; 44 | fragmentSpecializationInfo.mapEntryCount = specMapEntrys.size(); 45 | fragmentSpecializationInfo.pMapEntries = specMapEntrys.data(); 46 | fragmentSpecializationInfo.dataSize = sizeof(float) * specData.size(); 47 | fragmentSpecializationInfo.pData = specData.data(); 48 | 49 | pVertexSpecInfo = nullptr; 50 | pFragmentSpecInfo = &fragmentSpecializationInfo; 51 | 52 | init(pLogicalDevice, format, imageExtent, inputImages, outputImages, pConfig); 53 | } 54 | FxaaEffect::~FxaaEffect() 55 | { 56 | } 57 | } // namespace vkBasalt 58 | -------------------------------------------------------------------------------- /src/effect_fxaa.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EFFECT_FXAA_HPP_INCLUDED 2 | #define EFFECT_FXAA_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "effect_simple.hpp" 14 | #include "config.hpp" 15 | 16 | namespace vkBasalt 17 | { 18 | class FxaaEffect : public SimpleEffect 19 | { 20 | public: 21 | FxaaEffect(LogicalDevice* pLogicalDevice, 22 | VkFormat format, 23 | VkExtent2D imageExtent, 24 | std::vector inputImages, 25 | std::vector outputImages, 26 | Config* pConfig); 27 | ~FxaaEffect(); 28 | }; 29 | } // namespace vkBasalt 30 | 31 | #endif // EFFECT_FXAA_HPP_INCLUDED 32 | -------------------------------------------------------------------------------- /src/effect_lut.cpp: -------------------------------------------------------------------------------- 1 | #include "effect_lut.hpp" 2 | 3 | #include 4 | 5 | #include "image_view.hpp" 6 | #include "descriptor_set.hpp" 7 | #include "buffer.hpp" 8 | #include "renderpass.hpp" 9 | #include "graphics_pipeline.hpp" 10 | #include "framebuffer.hpp" 11 | #include "shader.hpp" 12 | #include "sampler.hpp" 13 | #include "image.hpp" 14 | #include "lut_cube.hpp" 15 | 16 | #include "stb_image.h" 17 | 18 | #include "shader_sources.hpp" 19 | 20 | namespace vkBasalt 21 | { 22 | LutEffect::LutEffect(LogicalDevice* pLogicalDevice, 23 | VkFormat format, 24 | VkExtent2D imageExtent, 25 | std::vector inputImages, 26 | std::vector outputImages, 27 | Config* pConfig) 28 | { 29 | vertexCode = full_screen_triangle_vert; 30 | fragmentCode = lut_frag; 31 | 32 | std::string lutFile = pConfig->getOption("lutFile"); 33 | 34 | int height; 35 | LutCube lutCube; 36 | stbi_uc* pixels; 37 | int32_t usingPNG = (int32_t)(lutFile.find(".cube") == std::string::npos && lutFile.find(".CUBE") == std::string::npos); 38 | if (!usingPNG) 39 | { 40 | lutCube = LutCube(lutFile); 41 | pixels = lutCube.colorCube.data(); 42 | height = lutCube.size; 43 | } 44 | else 45 | { 46 | int channels, width; 47 | pixels = stbi_load(lutFile.c_str(), &width, &height, &channels, STBI_rgb_alpha); 48 | if (width != height * height) 49 | { 50 | Logger::err("bad lut"); 51 | } 52 | } 53 | 54 | std::vector specMapEntrys(2); 55 | for (uint32_t i = 0; i < specMapEntrys.size(); i++) 56 | { 57 | specMapEntrys[i].constantID = i; 58 | specMapEntrys[i].offset = sizeof(int32_t) * i; 59 | specMapEntrys[i].size = sizeof(int32_t); 60 | } 61 | std::vector specData = {height, usingPNG}; 62 | 63 | VkSpecializationInfo fragmentSpecializationInfo; 64 | fragmentSpecializationInfo.mapEntryCount = specMapEntrys.size(); 65 | fragmentSpecializationInfo.pMapEntries = specMapEntrys.data(); 66 | fragmentSpecializationInfo.dataSize = specMapEntrys.size() * sizeof(int32_t); 67 | fragmentSpecializationInfo.pData = specData.data(); 68 | 69 | pVertexSpecInfo = nullptr; 70 | pFragmentSpecInfo = &fragmentSpecializationInfo; 71 | 72 | VkExtent3D lutImageExtent = {(uint32_t) height, (uint32_t) height, (uint32_t) height}; 73 | 74 | lutImage = createImages(pLogicalDevice, 75 | 1, 76 | lutImageExtent, 77 | VK_FORMAT_R8G8B8A8_UNORM, // TODO search for format and save it 78 | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 79 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 80 | lutMemory)[0]; 81 | 82 | uploadToImage(pLogicalDevice, lutImage, lutImageExtent, height * height * height * 4, pixels); 83 | 84 | if (usingPNG) 85 | { 86 | stbi_image_free(pixels); 87 | } 88 | 89 | lutImageView = createImageViews(pLogicalDevice, VK_FORMAT_R8G8B8A8_UNORM, std::vector(1, lutImage), VK_IMAGE_VIEW_TYPE_3D)[0]; 90 | 91 | lutDescriptorSetLayout = createImageSamplerDescriptorSetLayout(pLogicalDevice, 1); 92 | descriptorSetLayouts.push_back(lutDescriptorSetLayout); 93 | 94 | VkDescriptorPoolSize imagePoolSize; 95 | imagePoolSize.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 96 | imagePoolSize.descriptorCount = 1; 97 | 98 | std::vector poolSizes = {imagePoolSize}; 99 | 100 | lutDescriptorPool = createDescriptorPool(pLogicalDevice, poolSizes); 101 | 102 | init(pLogicalDevice, format, imageExtent, inputImages, outputImages, pConfig); 103 | 104 | lutDescriptorSet = 105 | allocateAndWriteImageSamplerDescriptorSets(pLogicalDevice, 106 | lutDescriptorPool, 107 | lutDescriptorSetLayout, 108 | {sampler}, 109 | std::vector>(1, std::vector(1, lutImageView)))[0]; 110 | } 111 | LutEffect::~LutEffect() 112 | { 113 | pLogicalDevice->vkd.DestroyImageView(pLogicalDevice->device, lutImageView, nullptr); 114 | pLogicalDevice->vkd.DestroyImage(pLogicalDevice->device, lutImage, nullptr); 115 | pLogicalDevice->vkd.DestroyDescriptorSetLayout(pLogicalDevice->device, lutDescriptorSetLayout, nullptr); 116 | pLogicalDevice->vkd.DestroyDescriptorPool(pLogicalDevice->device, lutDescriptorPool, nullptr); 117 | pLogicalDevice->vkd.FreeMemory(pLogicalDevice->device, lutMemory, nullptr); 118 | } 119 | void LutEffect::applyEffect(uint32_t imageIndex, VkCommandBuffer commandBuffer) 120 | { 121 | pLogicalDevice->vkd.CmdBindDescriptorSets( 122 | commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &(lutDescriptorSet), 0, nullptr); 123 | SimpleEffect::applyEffect(imageIndex, commandBuffer); 124 | } 125 | } // namespace vkBasalt 126 | -------------------------------------------------------------------------------- /src/effect_lut.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EFFECT_LUT_HPP_INCLUDED 2 | #define EFFECT_LUT_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "effect_simple.hpp" 14 | #include "config.hpp" 15 | 16 | namespace vkBasalt 17 | { 18 | class LutEffect : public SimpleEffect 19 | { 20 | public: 21 | LutEffect(LogicalDevice* pLogicalDevice, 22 | VkFormat format, 23 | VkExtent2D imageExtent, 24 | std::vector inputImages, 25 | std::vector outputImages, 26 | Config* pConfig); 27 | ~LutEffect(); 28 | void applyEffect(uint32_t imageIndex, VkCommandBuffer commandBuffer) override; 29 | 30 | private: 31 | VkImage lutImage; 32 | VkDeviceMemory lutMemory; 33 | VkImageView lutImageView; 34 | VkDescriptorSetLayout lutDescriptorSetLayout; 35 | VkDescriptorPool lutDescriptorPool; 36 | VkDescriptorSet lutDescriptorSet; 37 | }; 38 | } // namespace vkBasalt 39 | 40 | #endif // EFFECT_LUT_HPP_INCLUDED 41 | -------------------------------------------------------------------------------- /src/effect_reshade.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EFFECT_RESHADE_HPP_INCLUDED 2 | #define EFFECT_RESHADE_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "effect.hpp" 14 | #include "config.hpp" 15 | #include "reshade_uniforms.hpp" 16 | 17 | #include "logical_device.hpp" 18 | 19 | #include "reshade/effect_parser.hpp" 20 | #include "reshade/effect_codegen.hpp" 21 | #include "reshade/effect_preprocessor.hpp" 22 | 23 | namespace vkBasalt 24 | { 25 | class ReshadeEffect : public Effect 26 | { 27 | public: 28 | ReshadeEffect(LogicalDevice* pLogicalDevice, 29 | VkFormat format, 30 | VkExtent2D imageExtent, 31 | std::vector inputImages, 32 | std::vector outputImages, 33 | Config* pConfig, 34 | std::string effectName); 35 | void virtual applyEffect(uint32_t imageIndex, VkCommandBuffer commandBuffer) override; 36 | void virtual updateEffect() override; 37 | void virtual useDepthImage(VkImageView depthImageView) override; 38 | virtual ~ReshadeEffect(); 39 | 40 | private: 41 | LogicalDevice* pLogicalDevice; 42 | std::vector inputImages; 43 | std::vector outputImages; 44 | std::vector inputImageViewsSRGB; 45 | std::vector inputImageViewsUNORM; 46 | std::vector outputImageViewsSRGB; 47 | std::vector outputImageViewsUNORM; 48 | 49 | std::unordered_map> textureImages; 50 | std::unordered_map> textureImageViewsUNORM; 51 | std::unordered_map> textureImageViewsSRGB; 52 | std::unordered_map> renderImageViewsSRGB; 53 | std::unordered_map> renderImageViewsUNORM; 54 | 55 | std::unordered_map textureFormatsUNORM; 56 | std::unordered_map textureFormatsSRGB; 57 | std::unordered_map textureMipLevels; 58 | std::unordered_map textureExtents; 59 | 60 | std::vector inputDescriptorSets; 61 | std::vector outputDescriptorSets; 62 | std::vector backBufferDescriptorSets; 63 | 64 | std::vector> framebuffers; 65 | 66 | VkDescriptorSetLayout uniformDescriptorSetLayout; 67 | VkDescriptorSetLayout imageSamplerDescriptorSetLayout; 68 | VkShaderModule shaderModule; 69 | VkDescriptorPool descriptorPool; 70 | std::vector renderPasses; 71 | std::vector> renderTargets; 72 | std::vector renderPassBeginInfos; 73 | VkPipelineLayout pipelineLayout; 74 | std::vector graphicsPipelines; 75 | std::vector switchSamplers; 76 | VkExtent2D imageExtent; 77 | std::vector samplers; 78 | Config* pConfig; 79 | std::string effectName; 80 | reshadefx::module module; 81 | std::vector textureMemory; 82 | 83 | VkFormat inputOutputFormatUNORM; 84 | VkFormat inputOutputFormatSRGB; 85 | VkFormat stencilFormat; 86 | VkImage stencilImage; 87 | VkImageView stencilImageView; 88 | // how often the shader writes to the reshade back buffer 89 | // we need to flip the "backbuffer" after each write if there is a next one 90 | int outputWrites = 0; 91 | std::vector backBufferImages; 92 | std::vector backBufferImageViewsUNORM; 93 | std::vector backBufferImageViewsSRGB; 94 | VkBuffer stagingBuffer; 95 | VkDeviceMemory stagingBufferMemory; 96 | uint32_t bufferSize; 97 | VkDescriptorSet bufferDescriptorSet; 98 | 99 | std::vector> uniforms; 100 | 101 | void createReshadeModule(); 102 | VkFormat convertReshadeFormat(reshadefx::texture_format texFormat); 103 | VkCompareOp convertReshadeCompareOp(reshadefx::pass_stencil_func compareOp); 104 | VkStencilOp convertReshadeStencilOp(reshadefx::pass_stencil_op stencilOp); 105 | VkBlendOp convertReshadeBlendOp(reshadefx::pass_blend_op blendOp); 106 | VkBlendFactor convertReshadeBlendFactor(reshadefx::pass_blend_func blendFactor); 107 | }; 108 | } // namespace vkBasalt 109 | 110 | #endif // EFFECT_RESHADE_HPP_INCLUDED 111 | -------------------------------------------------------------------------------- /src/effect_simple.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EFFECT_SIMPLE_HPP_INCLUDED 2 | #define EFFECT_SIMPLE_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "effect.hpp" 14 | #include "config.hpp" 15 | 16 | #include "logical_device.hpp" 17 | 18 | namespace vkBasalt 19 | { 20 | class SimpleEffect : public Effect 21 | { 22 | public: 23 | SimpleEffect(); 24 | void virtual applyEffect(uint32_t imageIndex, VkCommandBuffer commandBuffer) override; 25 | virtual ~SimpleEffect(); 26 | 27 | protected: 28 | LogicalDevice* pLogicalDevice; 29 | std::vector inputImages; 30 | std::vector outputImages; 31 | std::vector inputImageViews; 32 | std::vector outputImageViews; 33 | std::vector imageDescriptorSets; 34 | std::vector framebuffers; 35 | VkDescriptorSetLayout imageSamplerDescriptorSetLayout; 36 | VkDescriptorPool descriptorPool; 37 | VkShaderModule vertexModule; 38 | VkShaderModule fragmentModule; 39 | VkRenderPass renderPass; 40 | VkPipelineLayout pipelineLayout; 41 | VkPipeline graphicsPipeline; 42 | VkExtent2D imageExtent; 43 | VkFormat format; 44 | VkSampler sampler; 45 | Config* pConfig; 46 | std::vector vertexCode; 47 | std::vector fragmentCode; 48 | VkSpecializationInfo* pVertexSpecInfo; 49 | VkSpecializationInfo* pFragmentSpecInfo; 50 | 51 | // subclasses can put DescriptorSets in here, but the first one will be the input image descriptorSet 52 | std::vector descriptorSetLayouts; 53 | 54 | void init(LogicalDevice* pLogicalDevice, 55 | VkFormat format, 56 | VkExtent2D imageExtent, 57 | std::vector inputImages, 58 | std::vector outputImages, 59 | Config* pConfig); 60 | }; 61 | } // namespace vkBasalt 62 | 63 | #endif // EFFECT_SIMPLE_HPP_INCLUDED 64 | -------------------------------------------------------------------------------- /src/effect_smaa.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EFFECT_SMAA_HPP_INCLUDED 2 | #define EFFECT_SMAA_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "effect.hpp" 14 | #include "config.hpp" 15 | 16 | #include "logical_device.hpp" 17 | 18 | namespace vkBasalt 19 | { 20 | class SmaaEffect : public Effect 21 | { 22 | public: 23 | SmaaEffect(LogicalDevice* pLogicalDevice, 24 | VkFormat format, 25 | VkExtent2D imageExtent, 26 | std::vector inputImages, 27 | std::vector outputImages, 28 | Config* pConfig); 29 | void applyEffect(uint32_t imageIndex, VkCommandBuffer commandBuffer) override; 30 | ~SmaaEffect(); 31 | 32 | private: 33 | LogicalDevice* pLogicalDevice; 34 | std::vector inputImages; 35 | std::vector edgeImages; 36 | std::vector blendImages; 37 | std::vector outputImages; 38 | std::vector inputImageViews; 39 | std::vector edgeImageViews; 40 | std::vector blendImageViews; 41 | std::vector outputImageViews; 42 | std::vector imageDescriptorSets; 43 | std::vector edgeFramebuffers; 44 | std::vector blendFramebuffers; 45 | std::vector neignborFramebuffers; 46 | VkImage areaImage; 47 | VkImage searchImage; 48 | VkImageView areaImageView; 49 | VkImageView searchImageView; 50 | VkDescriptorSetLayout imageSamplerDescriptorSetLayout; 51 | VkDescriptorPool descriptorPool; 52 | VkShaderModule edgeVertexModule; 53 | VkShaderModule edgeFragmentModule; 54 | VkShaderModule blendVertexModule; 55 | VkShaderModule blendFragmentModule; 56 | VkShaderModule neighborVertexModule; 57 | VkShaderModule neignborFragmentModule; 58 | VkRenderPass renderPass; 59 | VkRenderPass unormRenderPass; 60 | VkPipelineLayout pipelineLayout; 61 | VkPipeline edgePipeline; 62 | VkPipeline blendPipeline; 63 | VkPipeline neighborPipeline; 64 | VkExtent2D imageExtent; 65 | VkFormat format; 66 | VkDeviceMemory imageMemory; 67 | VkDeviceMemory areaMemory; 68 | VkDeviceMemory searchMemory; 69 | VkSampler sampler; 70 | 71 | Config* pConfig; 72 | }; 73 | } // namespace vkBasalt 74 | 75 | #endif // EFFECT_SMAA_HPP_INCLUDED 76 | -------------------------------------------------------------------------------- /src/effect_transfer.cpp: -------------------------------------------------------------------------------- 1 | #include "effect_transfer.hpp" 2 | 3 | namespace vkBasalt 4 | { 5 | TransferEffect::TransferEffect(LogicalDevice* pLogicalDevice, 6 | VkFormat format, 7 | VkExtent2D imageExtent, 8 | std::vector inputImages, 9 | std::vector outputImages, 10 | Config* pConfig) 11 | { 12 | this->pLogicalDevice = pLogicalDevice; 13 | this->format = format; 14 | this->imageExtent = imageExtent; 15 | this->inputImages = inputImages; 16 | this->outputImages = outputImages; 17 | this->pConfig = pConfig; 18 | } 19 | 20 | void TransferEffect::applyEffect(uint32_t imageIndex, VkCommandBuffer commandBuffer) 21 | { 22 | VkImageCopy imageCopy; 23 | imageCopy.srcSubresource = {}; 24 | imageCopy.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 25 | imageCopy.srcSubresource.layerCount = 1; 26 | imageCopy.srcOffset = {}; 27 | imageCopy.dstSubresource = {}; 28 | imageCopy.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 29 | imageCopy.dstSubresource.layerCount = 1; 30 | imageCopy.dstOffset = {}; 31 | imageCopy.extent = {imageExtent.width, imageExtent.height, 1}; 32 | 33 | VkImageMemoryBarrier memoryBarrier; 34 | memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; 35 | memoryBarrier.pNext = nullptr; 36 | memoryBarrier.srcAccessMask = 0; 37 | memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 38 | memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 39 | memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; 40 | memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 41 | memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 42 | memoryBarrier.image = inputImages[imageIndex]; 43 | 44 | memoryBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 45 | memoryBarrier.subresourceRange.baseMipLevel = 0; 46 | memoryBarrier.subresourceRange.levelCount = 1; 47 | memoryBarrier.subresourceRange.baseArrayLayer = 0; 48 | memoryBarrier.subresourceRange.layerCount = 1; 49 | 50 | pLogicalDevice->vkd.CmdPipelineBarrier( 51 | commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &memoryBarrier); 52 | 53 | memoryBarrier.image = outputImages[imageIndex]; 54 | memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; 55 | memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 56 | memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 57 | pLogicalDevice->vkd.CmdPipelineBarrier( 58 | commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &memoryBarrier); 59 | 60 | pLogicalDevice->vkd.CmdCopyImage(commandBuffer, 61 | inputImages[imageIndex], 62 | VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 63 | outputImages[imageIndex], 64 | VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 65 | 1, 66 | &imageCopy); 67 | 68 | memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 69 | memoryBarrier.dstAccessMask = 0; 70 | memoryBarrier.image = outputImages[imageIndex]; 71 | memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 72 | memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 73 | pLogicalDevice->vkd.CmdPipelineBarrier( 74 | commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &memoryBarrier); 75 | 76 | memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; 77 | memoryBarrier.image = inputImages[imageIndex]; 78 | memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; 79 | memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 80 | pLogicalDevice->vkd.CmdPipelineBarrier( 81 | commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &memoryBarrier); 82 | } 83 | 84 | TransferEffect::~TransferEffect() 85 | { 86 | } 87 | 88 | } // namespace vkBasalt 89 | -------------------------------------------------------------------------------- /src/effect_transfer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EFFECT_TRANSFER_HPP_INCLUDED 2 | #define EFFECT_TRANSFER_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "effect.hpp" 14 | #include "config.hpp" 15 | 16 | #include "logical_device.hpp" 17 | 18 | namespace vkBasalt 19 | { 20 | class TransferEffect : public Effect 21 | { 22 | public: 23 | TransferEffect(LogicalDevice* pLogicalDevice, 24 | VkFormat format, 25 | VkExtent2D imageExtent, 26 | std::vector inputImages, 27 | std::vector outputImages, 28 | Config* pConfig); 29 | void virtual applyEffect(uint32_t imageIndex, VkCommandBuffer commandBuffer) override; 30 | virtual ~TransferEffect(); 31 | 32 | private: 33 | LogicalDevice* pLogicalDevice; 34 | std::vector inputImages; 35 | std::vector outputImages; 36 | VkExtent2D imageExtent; 37 | VkFormat format; 38 | Config* pConfig; 39 | }; 40 | } // namespace vkBasalt 41 | #endif // EFFECT_TRANSFER_HPP_INCLUDED 42 | -------------------------------------------------------------------------------- /src/fake_swapchain.cpp: -------------------------------------------------------------------------------- 1 | #include "fake_swapchain.hpp" 2 | #include "memory.hpp" 3 | #include "format.hpp" 4 | 5 | namespace vkBasalt 6 | { 7 | std::vector createFakeSwapchainImages(LogicalDevice* pLogicalDevice, 8 | VkSwapchainCreateInfoKHR swapchainCreateInfo, 9 | uint32_t count, 10 | VkDeviceMemory& deviceMemory) 11 | { 12 | std::vector fakeImages(count); 13 | 14 | VkFormat srgbFormat = 15 | isSRGB(swapchainCreateInfo.imageFormat) ? swapchainCreateInfo.imageFormat : convertToSRGB(swapchainCreateInfo.imageFormat); 16 | VkFormat unormFormat = 17 | isSRGB(swapchainCreateInfo.imageFormat) ? convertToUNORM(swapchainCreateInfo.imageFormat) : swapchainCreateInfo.imageFormat; 18 | 19 | VkFormat formats[] = {unormFormat, srgbFormat}; 20 | 21 | VkImageFormatListCreateInfoKHR imageFormatListCreateInfo; 22 | imageFormatListCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO_KHR; 23 | imageFormatListCreateInfo.pNext = nullptr; 24 | imageFormatListCreateInfo.viewFormatCount = 2; 25 | imageFormatListCreateInfo.pViewFormats = formats; 26 | 27 | VkImageCreateInfo imageCreateInfo; 28 | imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 29 | imageCreateInfo.pNext = (unormFormat == srgbFormat) ? nullptr : &imageFormatListCreateInfo; 30 | imageCreateInfo.flags = (unormFormat == srgbFormat) ? 0 : VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; 31 | imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; 32 | imageCreateInfo.format = swapchainCreateInfo.imageFormat; 33 | imageCreateInfo.extent.width = swapchainCreateInfo.imageExtent.width; 34 | imageCreateInfo.extent.height = swapchainCreateInfo.imageExtent.height; 35 | imageCreateInfo.extent.depth = 1; 36 | imageCreateInfo.mipLevels = 1; 37 | imageCreateInfo.arrayLayers = swapchainCreateInfo.imageArrayLayers; 38 | imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; 39 | imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; 40 | imageCreateInfo.usage = swapchainCreateInfo.imageUsage | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT 41 | | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; // TODO what usage do we need? 42 | imageCreateInfo.sharingMode = swapchainCreateInfo.imageSharingMode; 43 | imageCreateInfo.queueFamilyIndexCount = swapchainCreateInfo.queueFamilyIndexCount; 44 | imageCreateInfo.pQueueFamilyIndices = swapchainCreateInfo.pQueueFamilyIndices; 45 | imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 46 | 47 | VkResult result; 48 | for (uint32_t i = 0; i < count; i++) 49 | { 50 | result = pLogicalDevice->vkd.CreateImage(pLogicalDevice->device, &imageCreateInfo, nullptr, &(fakeImages[i])); 51 | ASSERT_VULKAN(result); 52 | } 53 | 54 | // Allocate a bunch of memory for all images at one 55 | VkMemoryRequirements memoryRequirements; 56 | pLogicalDevice->vkd.GetImageMemoryRequirements(pLogicalDevice->device, fakeImages[0], &memoryRequirements); 57 | 58 | Logger::debug("fake image size: " + std::to_string(memoryRequirements.size)); 59 | Logger::debug("fake image alignment: " + std::to_string(memoryRequirements.alignment)); 60 | 61 | if (memoryRequirements.size % memoryRequirements.alignment != 0) 62 | { 63 | memoryRequirements.size = (memoryRequirements.size / memoryRequirements.alignment + 1) * memoryRequirements.alignment; 64 | } 65 | 66 | VkMemoryAllocateInfo memoryAllocateInfo; 67 | memoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; 68 | memoryAllocateInfo.pNext = nullptr; 69 | memoryAllocateInfo.allocationSize = memoryRequirements.size * count; 70 | memoryAllocateInfo.memoryTypeIndex = 71 | findMemoryTypeIndex(pLogicalDevice, memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 72 | 73 | result = pLogicalDevice->vkd.AllocateMemory(pLogicalDevice->device, &memoryAllocateInfo, nullptr, &deviceMemory); 74 | ASSERT_VULKAN(result); 75 | 76 | for (uint32_t i = 0; i < count; i++) 77 | { 78 | result = pLogicalDevice->vkd.BindImageMemory(pLogicalDevice->device, fakeImages[i], deviceMemory, memoryRequirements.size * i); 79 | ASSERT_VULKAN(result); 80 | } 81 | return fakeImages; 82 | } 83 | } // namespace vkBasalt 84 | -------------------------------------------------------------------------------- /src/fake_swapchain.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_SWAPCHAIN_HPP_INCLUDED 2 | #define FAKE_SWAPCHAIN_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | namespace vkBasalt 15 | { 16 | std::vector createFakeSwapchainImages(LogicalDevice* pLogicalDevice, 17 | VkSwapchainCreateInfoKHR swapchainCreateInfo, 18 | uint32_t count, 19 | VkDeviceMemory& deviceMemory); 20 | } 21 | 22 | #endif // FAKE_SWAPCHAIN_HPP_INCLUDED 23 | -------------------------------------------------------------------------------- /src/format.cpp: -------------------------------------------------------------------------------- 1 | #include "format.hpp" 2 | 3 | namespace vkBasalt 4 | { 5 | VkFormat convertToSRGB(VkFormat format) 6 | { 7 | switch (format) 8 | { 9 | /*case VK_FORMAT_R8_UNORM: 10 | return VK_FORMAT_R8_SRGB; 11 | case VK_FORMAT_R8G8_UNORM: 12 | return VK_FORMAT_R8G8_SRGB;*/ 13 | case VK_FORMAT_B8G8R8_UNORM: return VK_FORMAT_B8G8R8_SRGB; 14 | case VK_FORMAT_R8G8B8A8_UNORM: return VK_FORMAT_R8G8B8A8_SRGB; 15 | case VK_FORMAT_B8G8R8A8_UNORM: return VK_FORMAT_B8G8R8A8_SRGB; 16 | case VK_FORMAT_A8B8G8R8_UNORM_PACK32: return VK_FORMAT_A8B8G8R8_SRGB_PACK32; 17 | case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return VK_FORMAT_BC1_RGB_SRGB_BLOCK; 18 | case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return VK_FORMAT_BC1_RGBA_SRGB_BLOCK; 19 | case VK_FORMAT_BC2_UNORM_BLOCK: return VK_FORMAT_BC2_SRGB_BLOCK; 20 | case VK_FORMAT_BC3_UNORM_BLOCK: return VK_FORMAT_BC3_SRGB_BLOCK; 21 | case VK_FORMAT_BC7_UNORM_BLOCK: return VK_FORMAT_BC7_SRGB_BLOCK; 22 | case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; 23 | case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: return VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; 24 | case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: return VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; 25 | case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: return VK_FORMAT_ASTC_4x4_SRGB_BLOCK; 26 | case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: return VK_FORMAT_ASTC_5x4_SRGB_BLOCK; 27 | case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: return VK_FORMAT_ASTC_5x5_SRGB_BLOCK; 28 | case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: return VK_FORMAT_ASTC_6x5_SRGB_BLOCK; 29 | case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: return VK_FORMAT_ASTC_6x6_SRGB_BLOCK; 30 | case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: return VK_FORMAT_ASTC_8x5_SRGB_BLOCK; 31 | case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: return VK_FORMAT_ASTC_8x6_SRGB_BLOCK; 32 | case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: return VK_FORMAT_ASTC_8x8_SRGB_BLOCK; 33 | case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: return VK_FORMAT_ASTC_10x5_SRGB_BLOCK; 34 | case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: return VK_FORMAT_ASTC_10x6_SRGB_BLOCK; 35 | case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: return VK_FORMAT_ASTC_10x8_SRGB_BLOCK; 36 | case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: return VK_FORMAT_ASTC_10x10_SRGB_BLOCK; 37 | case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: return VK_FORMAT_ASTC_12x10_SRGB_BLOCK; 38 | case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: return VK_FORMAT_ASTC_12x12_SRGB_BLOCK; 39 | case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: return VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG; 40 | case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: return VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG; 41 | case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: return VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG; 42 | case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: return VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG; 43 | default: return format; 44 | } 45 | } 46 | 47 | VkFormat convertToUNORM(VkFormat format) 48 | { 49 | switch (format) 50 | { 51 | case VK_FORMAT_R8_SRGB: return VK_FORMAT_R8_UNORM; 52 | case VK_FORMAT_R8G8_SRGB: return VK_FORMAT_R8G8_UNORM; 53 | case VK_FORMAT_B8G8R8_SRGB: return VK_FORMAT_B8G8R8_UNORM; 54 | case VK_FORMAT_R8G8B8A8_SRGB: return VK_FORMAT_R8G8B8A8_UNORM; 55 | case VK_FORMAT_B8G8R8A8_SRGB: return VK_FORMAT_B8G8R8A8_UNORM; 56 | case VK_FORMAT_A8B8G8R8_SRGB_PACK32: return VK_FORMAT_A8B8G8R8_UNORM_PACK32; 57 | case VK_FORMAT_BC1_RGB_SRGB_BLOCK: return VK_FORMAT_BC1_RGB_UNORM_BLOCK; 58 | case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; 59 | case VK_FORMAT_BC2_SRGB_BLOCK: return VK_FORMAT_BC2_UNORM_BLOCK; 60 | case VK_FORMAT_BC3_SRGB_BLOCK: return VK_FORMAT_BC3_UNORM_BLOCK; 61 | case VK_FORMAT_BC7_SRGB_BLOCK: return VK_FORMAT_BC7_UNORM_BLOCK; 62 | case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; 63 | case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; 64 | case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; 65 | case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: return VK_FORMAT_ASTC_4x4_UNORM_BLOCK; 66 | case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: return VK_FORMAT_ASTC_5x4_UNORM_BLOCK; 67 | case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: return VK_FORMAT_ASTC_5x5_UNORM_BLOCK; 68 | case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: return VK_FORMAT_ASTC_6x5_UNORM_BLOCK; 69 | case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: return VK_FORMAT_ASTC_6x6_UNORM_BLOCK; 70 | case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: return VK_FORMAT_ASTC_8x5_UNORM_BLOCK; 71 | case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: return VK_FORMAT_ASTC_8x6_UNORM_BLOCK; 72 | case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: return VK_FORMAT_ASTC_8x8_UNORM_BLOCK; 73 | case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: return VK_FORMAT_ASTC_10x5_UNORM_BLOCK; 74 | case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: return VK_FORMAT_ASTC_10x6_UNORM_BLOCK; 75 | case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: return VK_FORMAT_ASTC_10x8_UNORM_BLOCK; 76 | case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: return VK_FORMAT_ASTC_10x10_UNORM_BLOCK; 77 | case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: return VK_FORMAT_ASTC_12x10_UNORM_BLOCK; 78 | case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: return VK_FORMAT_ASTC_12x12_UNORM_BLOCK; 79 | case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: return VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; 80 | case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: return VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; 81 | case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: return VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG; 82 | case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: return VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG; 83 | default: return format; 84 | } 85 | } 86 | 87 | bool isSRGB(VkFormat format) 88 | { 89 | return convertToUNORM(format) != format; 90 | } 91 | 92 | bool isUNORM(VkFormat format) 93 | { 94 | return convertToSRGB(format) != format; 95 | } 96 | 97 | VkFormat getSupportedFormat(LogicalDevice* pLogicalDevice, std::vector formats, VkFormatFeatureFlags features, VkImageTiling tiling) 98 | { 99 | for (auto& format : formats) 100 | { 101 | VkFormatProperties properties; 102 | pLogicalDevice->vki.GetPhysicalDeviceFormatProperties(pLogicalDevice->physicalDevice, format, &properties); 103 | if ((properties.optimalTilingFeatures & features) == features && tiling == VK_IMAGE_TILING_OPTIMAL) 104 | { 105 | return format; 106 | } 107 | if ((properties.linearTilingFeatures & features) == features && tiling == VK_IMAGE_TILING_LINEAR) 108 | { 109 | return format; 110 | } 111 | } 112 | Logger::err("No requested format supported"); 113 | return VK_FORMAT_UNDEFINED; 114 | } 115 | 116 | VkFormat getStencilFormat(LogicalDevice* pLogicalDevice) 117 | { 118 | std::vector stencilFormats = {VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT}; 119 | return getSupportedFormat(pLogicalDevice, stencilFormats, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); 120 | } 121 | 122 | bool isDepthFormat(VkFormat format) 123 | { 124 | switch (format) 125 | { 126 | case VK_FORMAT_D16_UNORM: return true; 127 | case VK_FORMAT_X8_D24_UNORM_PACK32: return true; 128 | case VK_FORMAT_D32_SFLOAT: return true; 129 | case VK_FORMAT_D16_UNORM_S8_UINT: return true; 130 | case VK_FORMAT_D24_UNORM_S8_UINT: return true; 131 | case VK_FORMAT_D32_SFLOAT_S8_UINT: return true; 132 | default: return false; 133 | } 134 | } 135 | 136 | bool isStencilFormat(VkFormat format) 137 | { 138 | switch (format) 139 | { 140 | case VK_FORMAT_S8_UINT: return true; 141 | case VK_FORMAT_D16_UNORM_S8_UINT: return true; 142 | case VK_FORMAT_D24_UNORM_S8_UINT: return true; 143 | case VK_FORMAT_D32_SFLOAT_S8_UINT: return true; 144 | default: return false; 145 | } 146 | } 147 | } // namespace vkBasalt 148 | -------------------------------------------------------------------------------- /src/format.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FORMAT_HPP_INCLUDED 2 | #define FORMAT_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | namespace vkBasalt 15 | { 16 | // Returns a matching sRGB format to a UNORM format if it exist, else returns format 17 | VkFormat convertToSRGB(VkFormat format); 18 | // Returns a matching UNORM format to a sRGB format if it exist, else returns format 19 | VkFormat convertToUNORM(VkFormat format); 20 | // Returns true if format is SRGB 21 | bool isSRGB(VkFormat format); 22 | // Returns true if format is UNORM 23 | // TODO currently return false if format is UNORM and no matching sRGB format exist 24 | bool isUNORM(VkFormat format); 25 | 26 | VkFormat getSupportedFormat(LogicalDevice* pLogicalDevice, 27 | std::vector formats, 28 | VkFormatFeatureFlags features, 29 | VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL); 30 | 31 | VkFormat getStencilFormat(LogicalDevice* pLogicalDevice); 32 | 33 | bool isDepthFormat(VkFormat format); 34 | 35 | bool isStencilFormat(VkFormat format); 36 | } // namespace vkBasalt 37 | 38 | #endif // FORMAT_HPP_INCLUDED 39 | -------------------------------------------------------------------------------- /src/framebuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "framebuffer.hpp" 2 | 3 | namespace vkBasalt 4 | { 5 | std::vector 6 | createFramebuffers(LogicalDevice* pLogicalDevice, VkRenderPass renderPass, VkExtent2D& extent, std::vector> imageViews) 7 | { 8 | std::vector framebuffers(imageViews[0].size()); 9 | std::vector perFrameImageViews; 10 | for (uint32_t i = 0; i < imageViews[0].size(); i++) 11 | { 12 | for (auto& iv : imageViews) 13 | { 14 | perFrameImageViews.push_back(iv[i]); 15 | } 16 | 17 | VkFramebufferCreateInfo framebufferCreateInfo; 18 | framebufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; 19 | framebufferCreateInfo.pNext = nullptr; 20 | framebufferCreateInfo.flags = 0; 21 | framebufferCreateInfo.renderPass = renderPass; 22 | framebufferCreateInfo.attachmentCount = perFrameImageViews.size(); 23 | framebufferCreateInfo.pAttachments = perFrameImageViews.data(); 24 | framebufferCreateInfo.width = extent.width; 25 | framebufferCreateInfo.height = extent.height; 26 | framebufferCreateInfo.layers = 1; 27 | 28 | VkResult result = pLogicalDevice->vkd.CreateFramebuffer(pLogicalDevice->device, &framebufferCreateInfo, nullptr, &(framebuffers[i])); 29 | ASSERT_VULKAN(result); 30 | perFrameImageViews.clear(); 31 | } 32 | return framebuffers; 33 | } 34 | } // namespace vkBasalt 35 | -------------------------------------------------------------------------------- /src/framebuffer.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FRAMEBUFFER_HPP_INCLUDED 2 | #define FRAMEBUFFER_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | namespace vkBasalt 15 | { 16 | std::vector 17 | createFramebuffers(LogicalDevice* pLogicalDevice, VkRenderPass renderPass, VkExtent2D& extent, std::vector> imageViews); 18 | } 19 | 20 | #endif // FRAMEBUFFER_HPP_INCLUDED 21 | -------------------------------------------------------------------------------- /src/graphics_pipeline.hpp: -------------------------------------------------------------------------------- 1 | #ifndef GRAPHICS_PIPELINE_HPP_INCLUDED 2 | #define GRAPHICS_PIPELINE_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | namespace vkBasalt 15 | { 16 | VkPipelineLayout createGraphicsPipelineLayout(LogicalDevice* pLogicalDevice, std::vector descriptorSetLayouts); 17 | 18 | VkPipeline createGraphicsPipeline(LogicalDevice* pLogicalDevice, 19 | VkShaderModule vertexModule, 20 | VkSpecializationInfo* vertexSpecializationInfo, 21 | std::string vertexEntryPoint, 22 | VkShaderModule fragmentModule, 23 | VkSpecializationInfo* fragmentSpecializationInfo, 24 | std::string fragmentEntryPoint, 25 | VkExtent2D extent, 26 | VkRenderPass renderPass, 27 | VkPipelineLayout pipelineLayout, 28 | bool flip = false); 29 | 30 | } // namespace vkBasalt 31 | 32 | #endif // GRAPHICS_PIPELINE_HPP_INCLUDED 33 | -------------------------------------------------------------------------------- /src/image.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_HPP_INCLUDED 2 | #define IMAGE_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "logical_device.hpp" 14 | 15 | namespace vkBasalt 16 | { 17 | std::vector createImages(LogicalDevice* pLogicalDevice, 18 | uint32_t count, 19 | VkExtent3D extent, 20 | VkFormat format, 21 | VkImageUsageFlags usage, 22 | VkMemoryPropertyFlags properties, 23 | VkDeviceMemory& imageMemory, 24 | uint32_t mipLevels = 1); 25 | 26 | void uploadToImage( 27 | LogicalDevice* pLogicalDevice, VkImage image, VkExtent3D extent, uint32_t size, const unsigned char* writeData, uint32_t mipLevels = 1); 28 | 29 | void changeImageLayout(LogicalDevice* pLogicalDevice, std::vector images, uint32_t mipLevels = 1); 30 | 31 | void generateMipMaps(LogicalDevice* pLogicalDevice, VkCommandBuffer commandBuffer, VkImage image, VkExtent3D extent, uint32_t mipLevels); 32 | } // namespace vkBasalt 33 | 34 | #endif // IMAGE_HPP_INCLUDED 35 | -------------------------------------------------------------------------------- /src/image_view.cpp: -------------------------------------------------------------------------------- 1 | #include "image_view.hpp" 2 | 3 | namespace vkBasalt 4 | { 5 | std::vector createImageViews(LogicalDevice* pLogicalDevice, 6 | VkFormat format, 7 | std::vector images, 8 | VkImageViewType viewType, 9 | VkImageAspectFlags aspectMask, 10 | uint32_t mipLevels) 11 | { 12 | std::vector imageViews(images.size()); 13 | 14 | VkImageViewCreateInfo imageViewCreateInfo; 15 | 16 | imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; 17 | imageViewCreateInfo.pNext = nullptr; 18 | imageViewCreateInfo.flags = 0; 19 | imageViewCreateInfo.image = VK_NULL_HANDLE; 20 | imageViewCreateInfo.viewType = viewType; 21 | imageViewCreateInfo.format = format; 22 | imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; 23 | imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; 24 | imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; 25 | imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; 26 | 27 | imageViewCreateInfo.subresourceRange.aspectMask = aspectMask; 28 | imageViewCreateInfo.subresourceRange.baseMipLevel = 0; 29 | imageViewCreateInfo.subresourceRange.levelCount = mipLevels; 30 | imageViewCreateInfo.subresourceRange.baseArrayLayer = 0; 31 | imageViewCreateInfo.subresourceRange.layerCount = 1; 32 | 33 | for (uint32_t i = 0; i < images.size(); i++) 34 | { 35 | imageViewCreateInfo.image = images[i]; 36 | VkResult result = pLogicalDevice->vkd.CreateImageView(pLogicalDevice->device, &imageViewCreateInfo, nullptr, &(imageViews[i])); 37 | ASSERT_VULKAN(result); 38 | } 39 | 40 | return imageViews; 41 | } 42 | 43 | } // namespace vkBasalt 44 | -------------------------------------------------------------------------------- /src/image_view.hpp: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_VIEW_HPP_INCLUDED 2 | #define IMAGE_VIEW_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | namespace vkBasalt 15 | { 16 | std::vector createImageViews(LogicalDevice* pLogicalDevice, 17 | VkFormat format, 18 | std::vector images, 19 | VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D, 20 | VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 21 | uint32_t mipLevels = 1); 22 | } 23 | 24 | #endif // IMAGE_VIEW_HPP_INCLUDED 25 | -------------------------------------------------------------------------------- /src/keyboard_input.cpp: -------------------------------------------------------------------------------- 1 | #include "keyboard_input.hpp" 2 | 3 | #include "logger.hpp" 4 | 5 | // TODO build without X11 6 | #ifndef VKBASALT_X11 7 | #define VKBASALT_X11 1 8 | #endif 9 | 10 | #if VKBASALT_X11 11 | #include "keyboard_input_x11.hpp" 12 | #endif 13 | 14 | namespace vkBasalt 15 | { 16 | uint32_t convertToKeySym(std::string key) 17 | { 18 | #if VKBASALT_X11 19 | return convertToKeySymX11(key); 20 | #endif 21 | return 0u; 22 | } 23 | 24 | bool isKeyPressed(uint32_t ks) 25 | { 26 | #if VKBASALT_X11 27 | return isKeyPressedX11(ks); 28 | #endif 29 | return false; 30 | } 31 | } // namespace vkBasalt 32 | -------------------------------------------------------------------------------- /src/keyboard_input.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace vkBasalt 7 | { 8 | uint32_t convertToKeySym(std::string key); 9 | bool isKeyPressed(uint32_t ks); 10 | } // namespace vkBasalt 11 | -------------------------------------------------------------------------------- /src/keyboard_input_x11.cpp: -------------------------------------------------------------------------------- 1 | #include "keyboard_input_x11.hpp" 2 | 3 | #include "logger.hpp" 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace vkBasalt 15 | { 16 | uint32_t convertToKeySymX11(std::string key) 17 | { 18 | // TODO what if X11 isn't loaded? 19 | uint32_t result = (uint32_t) XStringToKeysym(key.c_str()); 20 | if (!result) 21 | { 22 | Logger::err("invalid key"); 23 | } 24 | return result; 25 | } 26 | 27 | bool isKeyPressedX11(uint32_t ks) 28 | { 29 | static int usesX11 = -1; 30 | 31 | static std::unique_ptr> display; 32 | 33 | if (usesX11 < 0) 34 | { 35 | const char* disVar = getenv("DISPLAY"); 36 | if (!disVar || !std::strcmp(disVar, "")) 37 | { 38 | usesX11 = 0; 39 | Logger::debug("no X11 support"); 40 | } 41 | else 42 | { 43 | display = std::unique_ptr>(XOpenDisplay(disVar), [](Display* d) { XCloseDisplay(d); }); 44 | usesX11 = 1; 45 | Logger::debug("X11 support"); 46 | } 47 | } 48 | 49 | if (!usesX11) 50 | { 51 | return false; 52 | } 53 | 54 | char keys_return[32]; 55 | 56 | XQueryKeymap(display.get(), keys_return); 57 | 58 | KeyCode kc2 = XKeysymToKeycode(display.get(), (KeySym) ks); 59 | 60 | return !!(keys_return[kc2 >> 3] & (1 << (kc2 & 7))); 61 | } 62 | 63 | } // namespace vkBasalt 64 | -------------------------------------------------------------------------------- /src/keyboard_input_x11.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace vkBasalt 7 | { 8 | uint32_t convertToKeySymX11(std::string key); 9 | bool isKeyPressedX11(uint32_t ks); 10 | } // namespace vkBasalt 11 | -------------------------------------------------------------------------------- /src/logger.cpp: -------------------------------------------------------------------------------- 1 | #include "logger.hpp" 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace vkBasalt 8 | { 9 | 10 | Logger::Logger() : m_minLevel(getMinLogLevel()) 11 | { 12 | if (m_minLevel != LogLevel::None) 13 | { 14 | std::string filename = getFileName(); 15 | if (filename == "stderr") 16 | { 17 | m_outStream = std::unique_ptr>(&std::cerr, [](std::ostream*) {}); 18 | } 19 | else if (filename == "stdout") 20 | { 21 | m_outStream = std::unique_ptr>(&std::cout, [](std::ostream*) {}); 22 | } 23 | else 24 | { 25 | m_outStream = std::unique_ptr>(new std::ofstream(filename), 26 | [](std::ostream* os) { delete os; }); 27 | } 28 | } 29 | } 30 | 31 | Logger::~Logger() 32 | { 33 | } 34 | 35 | void Logger::trace(const std::string& message) 36 | { 37 | s_instance.emitMsg(LogLevel::Trace, message); 38 | } 39 | 40 | void Logger::debug(const std::string& message) 41 | { 42 | s_instance.emitMsg(LogLevel::Debug, message); 43 | } 44 | 45 | void Logger::info(const std::string& message) 46 | { 47 | s_instance.emitMsg(LogLevel::Info, message); 48 | } 49 | 50 | void Logger::warn(const std::string& message) 51 | { 52 | s_instance.emitMsg(LogLevel::Warn, message); 53 | } 54 | 55 | void Logger::err(const std::string& message) 56 | { 57 | s_instance.emitMsg(LogLevel::Error, message); 58 | } 59 | 60 | void Logger::log(LogLevel level, const std::string& message) 61 | { 62 | s_instance.emitMsg(level, message); 63 | } 64 | 65 | void Logger::emitMsg(LogLevel level, const std::string& message) 66 | { 67 | if (level >= m_minLevel) 68 | { 69 | std::lock_guard lock(m_mutex); 70 | 71 | static std::array s_prefixes = { 72 | {"vkBasalt trace: ", "vkBasalt debug: ", "vkBasalt info: ", "vkBasalt warn: ", "vkBasalt err: "}}; 73 | 74 | const char* prefix = s_prefixes.at(static_cast(level)); 75 | 76 | std::stringstream stream(message); 77 | std::string line; 78 | 79 | while (std::getline(stream, line, '\n')) 80 | { 81 | *m_outStream << prefix << line << std::endl; 82 | } 83 | } 84 | } 85 | 86 | LogLevel Logger::getMinLogLevel() 87 | { 88 | const std::array, 6> logLevels = {{ 89 | {"trace", LogLevel::Trace}, 90 | {"debug", LogLevel::Debug}, 91 | {"info", LogLevel::Info}, 92 | {"warn", LogLevel::Warn}, 93 | {"error", LogLevel::Error}, 94 | {"none", LogLevel::None}, 95 | }}; 96 | 97 | const char* envVar = getenv("VKBASALT_LOG_LEVEL"); 98 | 99 | const std::string logLevelStr = envVar ? envVar : ""; 100 | 101 | for (const auto& pair : logLevels) 102 | { 103 | if (logLevelStr == pair.first) 104 | return pair.second; 105 | } 106 | 107 | return LogLevel::Info; 108 | } 109 | 110 | std::string Logger::getFileName() 111 | { 112 | const char* envVar = getenv("VKBASALT_LOG_FILE"); 113 | 114 | std::string filename = envVar ? envVar : ""; 115 | 116 | if (filename.empty()) 117 | { 118 | filename = "stderr"; 119 | } 120 | 121 | return filename; 122 | } 123 | 124 | } // namespace vkBasalt 125 | -------------------------------------------------------------------------------- /src/logger.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LOGGER_HPP_INCLUDED 2 | #define LOGGER_HPP_INCLUDED 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace vkBasalt 13 | { 14 | 15 | enum class LogLevel : uint32_t 16 | { 17 | Trace = 0, 18 | Debug = 1, 19 | Info = 2, 20 | Warn = 3, 21 | Error = 4, 22 | None = 5, 23 | }; 24 | 25 | class Logger 26 | { 27 | 28 | public: 29 | Logger(); 30 | ~Logger(); 31 | 32 | static void trace(const std::string& message); 33 | static void debug(const std::string& message); 34 | static void info(const std::string& message); 35 | static void warn(const std::string& message); 36 | static void err(const std::string& message); 37 | static void log(LogLevel level, const std::string& message); 38 | 39 | static LogLevel logLevel() 40 | { 41 | return s_instance.m_minLevel; 42 | } 43 | 44 | private: 45 | static Logger s_instance; 46 | 47 | const LogLevel m_minLevel; 48 | 49 | std::mutex m_mutex; 50 | 51 | std::unique_ptr> m_outStream; 52 | 53 | void emitMsg(LogLevel level, const std::string& message); 54 | 55 | static LogLevel getMinLogLevel(); 56 | 57 | static std::string getFileName(); 58 | }; 59 | 60 | } // namespace vkBasalt 61 | 62 | #endif // LOGGER_HPP_INCLUDED 63 | -------------------------------------------------------------------------------- /src/logical_device.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LOGICAL_DEVICE_HPP_INCLUDED 2 | #define LOGICAL_DEVICE_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "vulkan_include.hpp" 10 | #include "vkdispatch.hpp" 11 | 12 | namespace vkBasalt 13 | { 14 | struct LogicalDevice 15 | { 16 | DeviceDispatch vkd; 17 | InstanceDispatch vki; 18 | VkDevice device; 19 | VkPhysicalDevice physicalDevice; 20 | VkInstance instance; 21 | VkQueue queue; 22 | uint32_t queueFamilyIndex; 23 | VkCommandPool commandPool; 24 | bool supportsMutableFormat; 25 | std::vector depthImages; 26 | std::vector depthFormats; 27 | std::vector depthImageViews; 28 | }; 29 | } // namespace vkBasalt 30 | 31 | #endif // LOGICAL_DEVICE_HPP_INCLUDED 32 | -------------------------------------------------------------------------------- /src/logical_swapchain.cpp: -------------------------------------------------------------------------------- 1 | #include "logical_swapchain.hpp" 2 | 3 | namespace vkBasalt 4 | { 5 | void LogicalSwapchain::destroy() 6 | { 7 | if (imageCount > 0) 8 | { 9 | effects.clear(); 10 | defaultTransfer.reset(); 11 | 12 | pLogicalDevice->vkd.FreeCommandBuffers( 13 | pLogicalDevice->device, pLogicalDevice->commandPool, commandBuffersEffect.size(), commandBuffersEffect.data()); 14 | pLogicalDevice->vkd.FreeCommandBuffers( 15 | pLogicalDevice->device, pLogicalDevice->commandPool, commandBuffersNoEffect.size(), commandBuffersNoEffect.data()); 16 | Logger::debug("after free commandbuffer"); 17 | 18 | pLogicalDevice->vkd.FreeMemory(pLogicalDevice->device, fakeImageMemory, nullptr); 19 | 20 | for (uint32_t i = 0; i < fakeImages.size(); i++) 21 | { 22 | pLogicalDevice->vkd.DestroyImage(pLogicalDevice->device, fakeImages[i], nullptr); 23 | } 24 | 25 | for (unsigned int i = 0; i < imageCount; i++) 26 | { 27 | pLogicalDevice->vkd.DestroySemaphore(pLogicalDevice->device, semaphores[i], nullptr); 28 | } 29 | Logger::debug("after DestroySemaphore"); 30 | } 31 | } 32 | } // namespace vkBasalt 33 | -------------------------------------------------------------------------------- /src/logical_swapchain.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LOGICAL_SWAPCHAIN_HPP_INCLUDED 2 | #define LOGICAL_SWAPCHAIN_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "effect.hpp" 11 | 12 | #include "vulkan_include.hpp" 13 | 14 | #include "logical_device.hpp" 15 | 16 | namespace vkBasalt 17 | { 18 | // for each swapchain, we have the Images and the other stuff we need to execute the compute shader 19 | struct LogicalSwapchain 20 | { 21 | LogicalDevice* pLogicalDevice; 22 | VkSwapchainCreateInfoKHR swapchainCreateInfo; 23 | VkExtent2D imageExtent; 24 | VkFormat format; 25 | uint32_t imageCount; 26 | std::vector images; 27 | std::vector fakeImages; 28 | std::vector commandBuffersEffect; 29 | std::vector commandBuffersNoEffect; 30 | std::vector semaphores; 31 | std::vector> effects; 32 | std::shared_ptr defaultTransfer; 33 | VkDeviceMemory fakeImageMemory; 34 | 35 | void destroy(); 36 | }; 37 | } // namespace vkBasalt 38 | 39 | #endif // LOGICAL_SWAPCHAIN_HPP_INCLUDED 40 | -------------------------------------------------------------------------------- /src/lut_cube.cpp: -------------------------------------------------------------------------------- 1 | #include "lut_cube.hpp" 2 | 3 | #include "logger.hpp" 4 | 5 | namespace vkBasalt 6 | { 7 | LutCube::LutCube() 8 | { 9 | } 10 | LutCube::LutCube(const std::string& file) 11 | { 12 | std::ifstream cubeStream(file); 13 | if (!cubeStream.good()) 14 | { 15 | Logger::err("lut cube file does not exist"); 16 | } 17 | 18 | std::string line; 19 | 20 | while (std::getline(cubeStream, line)) 21 | { 22 | parseLine(line); 23 | } 24 | } 25 | void LutCube::parseLine(std::string line) 26 | { 27 | if (line.length() == 0) 28 | { 29 | return; 30 | } 31 | if (line[0] == '#') 32 | { 33 | return; 34 | } 35 | if (line.find("LUT_3D_SIZE") != std::string::npos) 36 | { 37 | line = line.substr(line.find("LUT_3D_SIZE") + 11); 38 | line = skipWhiteSpace(line); 39 | size = std::stoi(line); 40 | 41 | colorCube = std::vector(size * size * size * 4, 255); 42 | return; 43 | } 44 | if (line.find("DOMAIN_MIN") != std::string::npos) 45 | { 46 | line = line.substr(line.find("DOMAIN_MIN") + 10); 47 | splitTripel(line, minX, minY, minZ); 48 | return; 49 | } 50 | if (line.find("DOMAIN_MAX") != std::string::npos) 51 | { 52 | line = line.substr(line.find("DOMAIN_MAX") + 10); 53 | splitTripel(line, maxX, maxY, maxZ); 54 | return; 55 | } 56 | if (line.find_first_of("0123456789") == 0) 57 | { 58 | float x, y, z; 59 | unsigned char outX, outY, outZ; 60 | splitTripel(line, x, y, z); 61 | clampTripel(x, y, z, outX, outY, outZ); 62 | writeColor(currentX, currentY, currentZ, outX, outY, outZ); 63 | if (currentX != size - 1) 64 | { 65 | currentX++; 66 | } 67 | else if (currentY != size - 1) 68 | { 69 | currentY++; 70 | currentX = 0; 71 | } 72 | else if (currentZ != size - 1) 73 | { 74 | currentZ++; 75 | currentX = 0; 76 | currentY = 0; 77 | } 78 | return; 79 | } 80 | } 81 | 82 | std::string LutCube::skipWhiteSpace(std::string text) 83 | { 84 | while (text.size() > 0 && (text[0] == ' ' || text[0] == '\t')) 85 | { 86 | text = text.substr(1); 87 | } 88 | return text; 89 | } 90 | 91 | void LutCube::splitTripel(std::string tripel, float& x, float& y, float& z) 92 | { 93 | tripel = skipWhiteSpace(tripel); 94 | size_t after = tripel.find_first_of(" \n"); 95 | x = std::stof(tripel.substr(0, after)); 96 | tripel = tripel.substr(after); 97 | 98 | tripel = skipWhiteSpace(tripel); 99 | after = tripel.find_first_of(" \n"); 100 | y = std::stof(tripel.substr(0, after)); 101 | tripel = tripel.substr(after); 102 | 103 | tripel = skipWhiteSpace(tripel); 104 | z = std::stof(tripel); 105 | } 106 | 107 | void LutCube::clampTripel(float x, float y, float z, unsigned char& outX, unsigned char& outY, unsigned char& outZ) 108 | { 109 | outX = (unsigned char) 255 * (x / (maxX - minX)); 110 | outY = (unsigned char) 255 * (y / (maxY - minY)); 111 | outZ = (unsigned char) 255 * (z / (maxZ - minZ)); 112 | } 113 | 114 | void LutCube::writeColor(int x, int y, int z, unsigned char r, unsigned char g, unsigned char b) 115 | { 116 | static const int colorSize = 4; // 4 bytes per point in the cube, rgba 117 | 118 | int locationR = (((z * size) + y) * size + x) * colorSize; 119 | 120 | colorCube[locationR + 0] = r; 121 | colorCube[locationR + 1] = g; 122 | colorCube[locationR + 2] = b; 123 | } 124 | } // namespace vkBasalt 125 | -------------------------------------------------------------------------------- /src/lut_cube.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LUT_CUBE_HPP_INCLUDED 2 | #define LUT_CUBE_HPP_INCLUDED 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace vkBasalt 13 | { 14 | /* 15 | reads .cube files 16 | returns a vector of bytes 17 | one byte is one color value 18 | 4 bytes stand for rgba 19 | the alpha value is always 255 20 | 21 | size will be set according to the size in the file, which can be in [2,256] 22 | the cube will have the dimentions size * size * size 23 | 24 | so the vector will have a length of size*size*size*4 25 | 26 | See: https://wwwimages2.adobe.com/content/dam/acom/en/products/speedgrade/cc/pdfs/cube-lut-specification-1.0.pdf 27 | */ 28 | class LutCube 29 | { 30 | public: 31 | std::vector colorCube; 32 | int size; 33 | 34 | LutCube(const std::string& file); 35 | LutCube(); 36 | 37 | private: 38 | float minX = 0.0f; 39 | float minY = 0.0f; 40 | float minZ = 0.0f; 41 | 42 | float maxX = 1.0f; 43 | float maxY = 1.0f; 44 | float maxZ = 1.0f; 45 | 46 | int currentX = 0; 47 | int currentY = 0; 48 | int currentZ = 0; 49 | 50 | void writeColor(int x, int y, int z, unsigned char r, unsigned char g, unsigned char b); 51 | 52 | void parseLine(std::string line); 53 | 54 | // splits a tripel of floats 55 | void splitTripel(std::string tripel, float& x, float& y, float& z); 56 | 57 | void clampTripel(float x, float y, float z, unsigned char& outX, unsigned char& outY, unsigned char& outZ); 58 | 59 | // returns the text without leading whitespace 60 | std::string skipWhiteSpace(std::string text); 61 | }; 62 | 63 | } // namespace vkBasalt 64 | #endif // LUT_CUBE_HPP_INCLUDED 65 | -------------------------------------------------------------------------------- /src/memory.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.hpp" 2 | 3 | namespace vkBasalt 4 | { 5 | uint32_t findMemoryTypeIndex(LogicalDevice* pLogicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties) 6 | { 7 | VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties; 8 | pLogicalDevice->vki.GetPhysicalDeviceMemoryProperties(pLogicalDevice->physicalDevice, &physicalDeviceMemoryProperties); 9 | for (uint32_t i = 0; i < physicalDeviceMemoryProperties.memoryTypeCount; i++) 10 | { 11 | if ((typeFilter & (1 << i)) && (physicalDeviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties) 12 | { 13 | return i; 14 | } 15 | } 16 | 17 | Logger::err("Found no correct memory type"); 18 | return 0x70AD; 19 | } 20 | } // namespace vkBasalt 21 | -------------------------------------------------------------------------------- /src/memory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MEMORY_HPP_INCLUDED 2 | #define MEMORY_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | namespace vkBasalt 15 | { 16 | uint32_t findMemoryTypeIndex(LogicalDevice* pLogicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties); 17 | } 18 | 19 | #endif // MEMORY_HPP_INCLUDED 20 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | subdir('shader') 2 | subdir('reshade') 3 | 4 | vkBasalt_src = [ 5 | 'basalt.cpp', 6 | 'buffer.cpp', 7 | 'command_buffer.cpp', 8 | 'config.cpp', 9 | 'descriptor_set.cpp', 10 | 'effect_cas.cpp', 11 | 'effect.cpp', 12 | 'effect_deband.cpp', 13 | 'effect_dls.cpp', 14 | 'effect_fxaa.cpp', 15 | 'effect_lut.cpp', 16 | 'effect_reshade.cpp', 17 | 'effect_simple.cpp', 18 | 'effect_smaa.cpp', 19 | 'effect_transfer.cpp', 20 | 'fake_swapchain.cpp', 21 | 'format.cpp', 22 | 'framebuffer.cpp', 23 | 'graphics_pipeline.cpp', 24 | 'image.cpp', 25 | 'image_view.cpp', 26 | 'keyboard_input.cpp', 27 | 'logger.cpp', 28 | 'logical_swapchain.cpp', 29 | 'lut_cube.cpp', 30 | 'memory.cpp', 31 | 'renderpass.cpp', 32 | 'reshade_uniforms.cpp', 33 | 'sampler.cpp', 34 | 'shader.cpp', 35 | 'stb_image.c', 36 | 'stb_image_resize.c', 37 | 'util.cpp', 38 | 'vkdispatch.cpp', 39 | ] 40 | 41 | x11_dep = dependency('x11') 42 | 43 | conf_paths = configuration_data() 44 | conf_paths.set_quoted('SYSCONFDIR', join_paths(get_option('prefix'), get_option('sysconfdir'))) 45 | conf_paths.set_quoted('DATADIR', join_paths(get_option('prefix'), get_option('datadir'))) 46 | 47 | configure_file(output: 'config_paths.hpp', 48 | configuration : conf_paths) 49 | 50 | # X11/X.h library contains many definitions (e.g. None) 51 | # which conflicts with the rest codebase with with Meson --unity=on option 52 | keyboard_input_x11_lib = static_library('keyboard_input_x11', 'keyboard_input_x11.cpp') 53 | 54 | shared_library(meson.project_name().to_lower(), 55 | vkBasalt_src, shader_include, 56 | link_with: [keyboard_input_x11_lib], 57 | include_directories : vkBasalt_include_path, 58 | dependencies : [x11_dep, reshade_dep], 59 | gnu_symbol_visibility: 'hidden', 60 | install : true, 61 | install_dir : lib_dir) 62 | -------------------------------------------------------------------------------- /src/renderpass.cpp: -------------------------------------------------------------------------------- 1 | #include "renderpass.hpp" 2 | 3 | namespace vkBasalt 4 | { 5 | VkRenderPass createRenderPass(LogicalDevice* pLogicalDevice, VkFormat format) 6 | { 7 | VkRenderPass renderPass; 8 | 9 | VkAttachmentDescription attachmentDescription; 10 | attachmentDescription.flags = 0; 11 | attachmentDescription.format = format; 12 | attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT; 13 | attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; 14 | attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE; 15 | attachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 16 | attachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 17 | attachmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 18 | attachmentDescription.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; 19 | 20 | VkAttachmentReference attachmentReference; 21 | attachmentReference.attachment = 0; 22 | attachmentReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 23 | 24 | VkSubpassDescription subpassDescription; 25 | subpassDescription.flags = 0; 26 | subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 27 | subpassDescription.inputAttachmentCount = 0; 28 | subpassDescription.pInputAttachments = nullptr; 29 | subpassDescription.colorAttachmentCount = 1; 30 | subpassDescription.pColorAttachments = &attachmentReference; 31 | subpassDescription.pResolveAttachments = nullptr; 32 | subpassDescription.pDepthStencilAttachment = nullptr; 33 | subpassDescription.preserveAttachmentCount = 0; 34 | subpassDescription.pPreserveAttachments = nullptr; 35 | 36 | VkSubpassDependency subpassDependency; 37 | subpassDependency.srcSubpass = VK_SUBPASS_EXTERNAL; 38 | subpassDependency.dstSubpass = 0; 39 | subpassDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 40 | subpassDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 41 | subpassDependency.srcAccessMask = 0; 42 | subpassDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 43 | subpassDependency.dependencyFlags = 0; 44 | 45 | VkRenderPassCreateInfo renderPassCreateInfo; 46 | renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; 47 | renderPassCreateInfo.pNext = nullptr; 48 | renderPassCreateInfo.flags = 0; 49 | renderPassCreateInfo.attachmentCount = 1; 50 | renderPassCreateInfo.pAttachments = &attachmentDescription; 51 | renderPassCreateInfo.subpassCount = 1; 52 | renderPassCreateInfo.pSubpasses = &subpassDescription; 53 | renderPassCreateInfo.dependencyCount = 1; 54 | renderPassCreateInfo.pDependencies = &subpassDependency; 55 | 56 | VkResult result = pLogicalDevice->vkd.CreateRenderPass(pLogicalDevice->device, &renderPassCreateInfo, nullptr, &renderPass); 57 | ASSERT_VULKAN(result); 58 | 59 | return renderPass; 60 | } 61 | } // namespace vkBasalt 62 | -------------------------------------------------------------------------------- /src/renderpass.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RENDERPASS_HPP_INCLUDED 2 | #define RENDERPASS_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | namespace vkBasalt 15 | { 16 | VkRenderPass createRenderPass(LogicalDevice* pLogicalDevice, VkFormat format); 17 | } 18 | 19 | #endif // RENDERPASS_HPP_INCLUDED 20 | -------------------------------------------------------------------------------- /src/reshade/GLSL.std.450.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /src/reshade/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2014 Patrick Mours. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 7 | * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /src/reshade/effect_lexer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "effect_token.hpp" 9 | 10 | namespace reshadefx 11 | { 12 | /// 13 | /// A lexical analyzer for C-like languages. 14 | /// 15 | class lexer 16 | { 17 | public: 18 | explicit lexer( 19 | std::string input, 20 | bool ignore_comments = true, 21 | bool ignore_whitespace = true, 22 | bool ignore_pp_directives = true, 23 | bool ignore_line_directives = false, 24 | bool ignore_keywords = false, 25 | bool escape_string_literals = true, 26 | const location &start_location = location()) : 27 | _input(std::move(input)), 28 | _cur_location(start_location), 29 | _ignore_comments(ignore_comments), 30 | _ignore_whitespace(ignore_whitespace), 31 | _ignore_pp_directives(ignore_pp_directives), 32 | _ignore_line_directives(ignore_line_directives), 33 | _ignore_keywords(ignore_keywords), 34 | _escape_string_literals(escape_string_literals) 35 | { 36 | _cur = _input.data(); 37 | _end = _cur + _input.size(); 38 | } 39 | 40 | lexer(const lexer &lexer) { operator=(lexer); } 41 | lexer &operator=(const lexer &lexer) 42 | { 43 | _input = lexer._input; 44 | _cur_location = lexer._cur_location; 45 | _cur = _input.data() + (lexer._cur - lexer._input.data()); 46 | _end = _input.data() + _input.size(); 47 | _ignore_comments = lexer._ignore_comments; 48 | _ignore_whitespace = lexer._ignore_whitespace; 49 | _ignore_pp_directives = lexer._ignore_pp_directives; 50 | _ignore_keywords = lexer._ignore_keywords; 51 | _escape_string_literals = lexer._escape_string_literals; 52 | _ignore_line_directives = lexer._ignore_line_directives; 53 | 54 | return *this; 55 | } 56 | 57 | /// 58 | /// Get the input string this lexical analyzer works on. 59 | /// 60 | /// A constant reference to the input string. 61 | const std::string &input_string() const { return _input; } 62 | 63 | /// 64 | /// Perform lexical analysis on the input string and return the next token in sequence. 65 | /// 66 | /// The next token from the input string. 67 | token lex(); 68 | 69 | /// 70 | /// Advances to the next token that is not whitespace. 71 | /// 72 | void skip_space(); 73 | /// 74 | /// Advances to the next new line, ignoring all tokens. 75 | /// 76 | void skip_to_next_line(); 77 | 78 | private: 79 | /// 80 | /// Skips an arbitrary amount of characters in the input string. 81 | /// 82 | /// The number of input characters to skip. 83 | void skip(size_t length); 84 | 85 | void parse_identifier(token &tok) const; 86 | bool parse_pp_directive(token &tok); 87 | void parse_string_literal(token &tok, bool escape); 88 | void parse_numeric_literal(token &tok) const; 89 | 90 | std::string _input; 91 | location _cur_location; 92 | const std::string::value_type *_cur, *_end; 93 | bool _ignore_comments; 94 | bool _ignore_whitespace; 95 | bool _ignore_pp_directives; 96 | bool _ignore_line_directives; 97 | bool _ignore_keywords; 98 | bool _escape_string_literals; 99 | }; 100 | } 101 | -------------------------------------------------------------------------------- /src/reshade/effect_module.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "effect_expression.hpp" 9 | 10 | namespace reshadefx 11 | { 12 | /// 13 | /// A list of supported image formats. 14 | /// 15 | enum class texture_format 16 | { 17 | unknown, 18 | 19 | r8, 20 | r16f, 21 | r32f, 22 | rg8, 23 | rg16, 24 | rg16f, 25 | rg32f, 26 | rgba8, 27 | rgba16, 28 | rgba16f, 29 | rgba32f, 30 | rgb10a2, 31 | }; 32 | 33 | /// 34 | /// A filtering type used for texture lookups. 35 | /// 36 | enum class texture_filter 37 | { 38 | min_mag_mip_point = 0, 39 | min_mag_point_mip_linear = 0x1, 40 | min_point_mag_linear_mip_point = 0x4, 41 | min_point_mag_mip_linear = 0x5, 42 | min_linear_mag_mip_point = 0x10, 43 | min_linear_mag_point_mip_linear = 0x11, 44 | min_mag_linear_mip_point = 0x14, 45 | min_mag_mip_linear = 0x15 46 | }; 47 | 48 | /// 49 | /// Specifies behavior of sampling with texture coordinates outside an image. 50 | /// 51 | enum class texture_address_mode 52 | { 53 | wrap = 1, 54 | mirror = 2, 55 | clamp = 3, 56 | border = 4 57 | }; 58 | 59 | /// 60 | /// Specifies RGB or alpha blending operations. 61 | /// 62 | enum class pass_blend_op : uint8_t 63 | { 64 | add = 1, 65 | subtract, 66 | rev_subtract, 67 | min, 68 | max, 69 | }; 70 | 71 | /// 72 | /// Specifies blend factors, which modulate values between the pixel shader output and render target. 73 | /// 74 | enum class pass_blend_func : uint8_t 75 | { 76 | zero = 0, 77 | one = 1, 78 | src_color, 79 | src_alpha, 80 | inv_src_color, 81 | inv_src_alpha, 82 | dst_color, 83 | dst_alpha, 84 | inv_dst_color, 85 | inv_dst_alpha, 86 | }; 87 | 88 | /// 89 | /// Specifies the stencil operations that can be performed during depth-stencil testing. 90 | /// 91 | enum class pass_stencil_op : uint8_t 92 | { 93 | zero, 94 | keep, 95 | invert, 96 | replace, 97 | incr, 98 | incr_sat, 99 | decr, 100 | decr_sat, 101 | }; 102 | 103 | /// 104 | /// Specifies comparison options for depth-stencil testing. 105 | /// 106 | enum class pass_stencil_func : uint8_t 107 | { 108 | never, 109 | equal, 110 | not_equal, 111 | less, 112 | less_equal, 113 | greater, 114 | greater_equal, 115 | always, 116 | }; 117 | 118 | /// 119 | /// Specifies the possible primitives. 120 | /// 121 | enum class primitive_topology : uint8_t 122 | { 123 | point_list = 1, 124 | line_list, 125 | line_strip, 126 | triangle_list, 127 | triangle_strip, 128 | }; 129 | 130 | /// 131 | /// A struct type defined in the shader code. 132 | /// 133 | struct struct_info 134 | { 135 | std::string name; 136 | std::string unique_name; 137 | std::vector member_list; 138 | uint32_t definition = 0; 139 | }; 140 | 141 | /// 142 | /// A struct field defined in the shader code. 143 | /// 144 | struct struct_member_info 145 | { 146 | reshadefx::type type; 147 | std::string name; 148 | std::string semantic; 149 | reshadefx::location location; 150 | uint32_t definition = 0; 151 | }; 152 | 153 | /// 154 | /// An annotation attached to a variable. 155 | /// 156 | struct annotation 157 | { 158 | reshadefx::type type; 159 | std::string name; 160 | reshadefx::constant value; 161 | }; 162 | 163 | /// 164 | /// A texture defined in the shader code. 165 | /// 166 | struct texture_info 167 | { 168 | uint32_t id = 0; 169 | uint32_t binding = 0; 170 | std::string semantic; 171 | std::string unique_name; 172 | std::vector annotations; 173 | uint32_t width = 1; 174 | uint32_t height = 1; 175 | uint32_t levels = 1; 176 | texture_format format = texture_format::rgba8; 177 | }; 178 | 179 | /// 180 | /// A texture sampler defined in the shader code. 181 | /// 182 | struct sampler_info 183 | { 184 | uint32_t id = 0; 185 | uint32_t binding = 0; 186 | uint32_t texture_binding = 0; 187 | std::string unique_name; 188 | std::string texture_name; 189 | std::vector annotations; 190 | texture_filter filter = texture_filter::min_mag_mip_linear; 191 | texture_address_mode address_u = texture_address_mode::clamp; 192 | texture_address_mode address_v = texture_address_mode::clamp; 193 | texture_address_mode address_w = texture_address_mode::clamp; 194 | float min_lod = -3.402823466e+38f; // FLT_MAX 195 | float max_lod = +3.402823466e+38f; 196 | float lod_bias = 0.0f; 197 | uint8_t srgb = false; 198 | }; 199 | 200 | /// 201 | /// An uniform variable defined in the shader code. 202 | /// 203 | struct uniform_info 204 | { 205 | std::string name; 206 | reshadefx::type type; 207 | uint32_t size = 0; 208 | uint32_t offset = 0; 209 | std::vector annotations; 210 | bool has_initializer_value = false; 211 | reshadefx::constant initializer_value; 212 | }; 213 | 214 | /// 215 | /// A shader entry point function. 216 | /// 217 | struct entry_point 218 | { 219 | std::string name; 220 | bool is_pixel_shader; 221 | }; 222 | 223 | /// 224 | /// A function defined in the shader code. 225 | /// 226 | struct function_info 227 | { 228 | uint32_t definition; 229 | std::string name; 230 | std::string unique_name; 231 | reshadefx::type return_type; 232 | std::string return_semantic; 233 | std::vector parameter_list; 234 | }; 235 | 236 | /// 237 | /// A render pass with all its state info. 238 | /// 239 | struct pass_info 240 | { 241 | std::string render_target_names[8] = {}; 242 | std::string vs_entry_point; 243 | std::string ps_entry_point; 244 | uint8_t clear_render_targets = false; 245 | uint8_t srgb_write_enable = false; 246 | uint8_t blend_enable = false; 247 | uint8_t stencil_enable = false; 248 | uint8_t color_write_mask = 0xF; 249 | uint8_t stencil_read_mask = 0xFF; 250 | uint8_t stencil_write_mask = 0xFF; 251 | pass_blend_op blend_op = pass_blend_op::add; 252 | pass_blend_op blend_op_alpha = pass_blend_op::add; 253 | pass_blend_func src_blend = pass_blend_func::one; 254 | pass_blend_func dest_blend = pass_blend_func::zero; 255 | pass_blend_func src_blend_alpha = pass_blend_func::one; 256 | pass_blend_func dest_blend_alpha = pass_blend_func::zero; 257 | pass_stencil_func stencil_comparison_func = pass_stencil_func::always; 258 | uint32_t stencil_reference_value = 0; 259 | pass_stencil_op stencil_op_pass = pass_stencil_op::keep; 260 | pass_stencil_op stencil_op_fail = pass_stencil_op::keep; 261 | pass_stencil_op stencil_op_depth_fail = pass_stencil_op::keep; 262 | uint32_t num_vertices = 3; 263 | primitive_topology topology = primitive_topology::triangle_list; 264 | uint32_t viewport_width = 0; 265 | uint32_t viewport_height = 0; 266 | }; 267 | 268 | /// 269 | /// A collection of passes that make up an effect. 270 | /// 271 | struct technique_info 272 | { 273 | std::string name; 274 | std::vector passes; 275 | std::vector annotations; 276 | }; 277 | 278 | /// 279 | /// In-memory representation of an effect file. 280 | /// 281 | struct module 282 | { 283 | std::string hlsl; 284 | std::vector spirv; 285 | 286 | std::vector entry_points; 287 | std::vector textures; 288 | std::vector samplers; 289 | std::vector uniforms, spec_constants; 290 | std::vector techniques; 291 | 292 | uint32_t total_uniform_size = 0; 293 | uint32_t num_sampler_bindings = 0; 294 | uint32_t num_texture_bindings = 0; 295 | }; 296 | } 297 | -------------------------------------------------------------------------------- /src/reshade/effect_parser.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "effect_symbol_table.hpp" 9 | #include // std::unique_ptr 10 | 11 | namespace reshadefx 12 | { 13 | /// 14 | /// A parser for the ReShade FX shader language. 15 | /// 16 | class parser : symbol_table 17 | { 18 | public: 19 | // Define constructor explicitly because lexer class is not included here 20 | parser(); 21 | ~parser(); 22 | 23 | /// 24 | /// Parse the provided input string. 25 | /// 26 | /// The string to analyze. 27 | /// The code generation implementation to use. 28 | /// A boolean value indicating whether parsing was successful or not. 29 | bool parse(std::string source, class codegen *backend); 30 | 31 | /// 32 | /// Get the list of error messages. 33 | /// 34 | std::string &errors() { return _errors; } 35 | const std::string &errors() const { return _errors; } 36 | 37 | private: 38 | void error(const location &location, unsigned int code, const std::string &message); 39 | void warning(const location &location, unsigned int code, const std::string &message); 40 | 41 | void backup(); 42 | void restore(); 43 | 44 | bool peek(char tok) const { return _token_next.id == static_cast(tok); } 45 | bool peek(tokenid tokid) const { return _token_next.id == tokid; } 46 | void consume(); 47 | void consume_until(char tok) { return consume_until(static_cast(tok)); } 48 | void consume_until(tokenid tokid); 49 | bool accept(char tok) { return accept(static_cast(tok)); } 50 | bool accept(tokenid tokid); 51 | bool expect(char tok) { return expect(static_cast(tok)); } 52 | bool expect(tokenid tokid); 53 | 54 | bool accept_symbol(std::string &identifier, scope &scope, symbol &symbol); 55 | bool accept_type_class(type &type); 56 | bool accept_type_qualifiers(type &type); 57 | bool accept_unary_op(); 58 | bool accept_postfix_op(); 59 | bool peek_multary_op(unsigned int &precedence) const; 60 | bool accept_assignment_op(); 61 | 62 | bool parse_top(); 63 | bool parse_struct(); 64 | bool parse_function(type type, std::string name); 65 | bool parse_variable(type type, std::string name, bool global = false); 66 | bool parse_technique(); 67 | bool parse_technique_pass(pass_info &info); 68 | bool parse_type(type &type); 69 | bool parse_array_size(type &type); 70 | bool parse_expression(expression &expression); 71 | bool parse_expression_unary(expression &expression); 72 | bool parse_expression_multary(expression &expression, unsigned int precedence = 0); 73 | bool parse_expression_assignment(expression &expression); 74 | bool parse_annotations(std::vector &annotations); 75 | bool parse_statement(bool scoped); 76 | bool parse_statement_block(bool scoped); 77 | 78 | codegen *_codegen = nullptr; 79 | std::string _errors; 80 | token _token, _token_next, _token_backup; 81 | std::unique_ptr _lexer, _lexer_backup; 82 | reshadefx::type _current_return_type; 83 | std::vector _loop_break_target_stack; 84 | std::vector _loop_continue_target_stack; 85 | }; 86 | } 87 | -------------------------------------------------------------------------------- /src/reshade/effect_preprocessor.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "effect_token.hpp" 9 | #include // std::unique_ptr 10 | #include 11 | #include 12 | #include 13 | 14 | namespace reshadefx 15 | { 16 | /// 17 | /// A C-style preprocessor implementation. 18 | /// 19 | class preprocessor 20 | { 21 | public: 22 | struct macro 23 | { 24 | std::string replacement_list; 25 | std::vector parameters; 26 | bool is_variadic = false; 27 | bool is_function_like = false; 28 | }; 29 | 30 | // Define constructor explicitly because lexer class is not included here 31 | preprocessor(); 32 | ~preprocessor(); 33 | 34 | /// 35 | /// Add an include directory to the list of search paths used when resolving #include directives. 36 | /// 37 | /// The path to the directory to add. 38 | void add_include_path(const std::filesystem::path &path); 39 | 40 | /// 41 | /// Add a new macro definition. This is equal to appending '#define name macro' to this preprocessor instance. 42 | /// 43 | /// The name of the macro to define. 44 | /// The definition of the macro function or value. 45 | /// 46 | bool add_macro_definition(const std::string &name, const macro ¯o); 47 | /// 48 | /// Add a new macro value definition. This is equal to appending '#define name macro' to this preprocessor instance. 49 | /// 50 | /// The name of the macro to define. 51 | /// The value to define that macro to. 52 | /// 53 | bool add_macro_definition(const std::string &name, std::string value = "1") { return add_macro_definition(name, macro { std::move(value), {} }); } 54 | 55 | /// 56 | /// Open the specified file, parse its contents and append them to the output. 57 | /// 58 | /// The path to the file to parse. 59 | /// A boolean value indicating whether parsing was successful or not. 60 | bool append_file(const std::filesystem::path &path); 61 | /// 62 | /// Parse the specified string and append it to the output. 63 | /// 64 | /// The string to parse. 65 | /// A boolean value indicating whether parsing was successful or not. 66 | bool append_string(const std::string &source_code); 67 | 68 | /// 69 | /// Get the list of error messages. 70 | /// 71 | std::string &errors() { return _errors; } 72 | const std::string &errors() const { return _errors; } 73 | /// 74 | /// Get the current pre-processed output string. 75 | /// 76 | std::string &output() { return _output; } 77 | const std::string &output() const { return _output; } 78 | 79 | /// 80 | /// Get a list of all included files. 81 | /// 82 | std::vector included_files() const; 83 | 84 | /// 85 | /// Get a list of all defines that were used in #ifdef and #ifndef lines 86 | /// 87 | /// 88 | std::vector> used_macro_definitions() const; 89 | 90 | private: 91 | struct if_level 92 | { 93 | bool value; 94 | bool skipping; 95 | token pp_token; 96 | size_t input_index; 97 | }; 98 | struct input_level 99 | { 100 | std::string name; 101 | std::unique_ptr lexer; 102 | token next_token; 103 | std::unordered_set hidden_macros; 104 | }; 105 | 106 | void error(const location &location, const std::string &message); 107 | void warning(const location &location, const std::string &message); 108 | 109 | void push(std::string input, const std::string &name = std::string()); 110 | 111 | bool peek(tokenid token) const; 112 | bool consume(); 113 | void consume_until(tokenid token); 114 | bool accept(tokenid token); 115 | bool expect(tokenid token); 116 | 117 | void parse(); 118 | void parse_def(); 119 | void parse_undef(); 120 | void parse_if(); 121 | void parse_ifdef(); 122 | void parse_ifndef(); 123 | void parse_elif(); 124 | void parse_else(); 125 | void parse_endif(); 126 | void parse_error(); 127 | void parse_warning(); 128 | void parse_pragma(); 129 | void parse_include(); 130 | 131 | bool evaluate_expression(); 132 | bool evaluate_identifier_as_macro(); 133 | 134 | void expand_macro(const std::string &name, const macro ¯o, const std::vector &arguments, std::string &out); 135 | void create_macro_replacement_list(macro ¯o); 136 | 137 | bool _success = true; 138 | std::string _output, _errors; 139 | std::string _current_token_raw_data; 140 | reshadefx::token _token; 141 | std::vector _if_stack; 142 | std::vector _input_stack; 143 | size_t _next_input_index = 0; 144 | size_t _current_input_index = 0; 145 | unsigned short _recursion_count = 0; 146 | location _output_location; 147 | std::unordered_set _used_macros; 148 | std::unordered_map _macros; 149 | std::vector _include_paths; 150 | std::unordered_map _file_cache; 151 | }; 152 | } 153 | -------------------------------------------------------------------------------- /src/reshade/effect_symbol_table.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include "effect_module.hpp" 9 | #include // Used for symbol lookup table 10 | 11 | namespace reshadefx 12 | { 13 | /// 14 | /// A scope encapsulating symbols 15 | /// 16 | struct scope 17 | { 18 | std::string name; 19 | unsigned int level, namespace_level; 20 | }; 21 | 22 | /// 23 | /// Enumeration of all possible symbol types 24 | /// 25 | enum class symbol_type 26 | { 27 | invalid, 28 | variable, 29 | constant, 30 | function, 31 | intrinsic, 32 | structure, 33 | }; 34 | 35 | /// 36 | /// A single symbol in the symbol table 37 | /// 38 | struct symbol 39 | { 40 | symbol_type op = symbol_type::invalid; 41 | uint32_t id = 0; 42 | reshadefx::type type = {}; 43 | reshadefx::constant constant = {}; 44 | const reshadefx::function_info *function = nullptr; 45 | }; 46 | 47 | /// 48 | /// A symbol table managing a list of scopes and symbols 49 | /// 50 | class symbol_table 51 | { 52 | public: 53 | symbol_table(); 54 | 55 | /// 56 | /// Enter a new scope as child of the current one. 57 | /// 58 | void enter_scope(); 59 | /// 60 | /// Enter a new namespace as child of the current one. 61 | /// 62 | void enter_namespace(const std::string &name); 63 | /// 64 | /// Leave the current scope and enter the parent one. 65 | /// 66 | void leave_scope(); 67 | /// 68 | /// Leave the current namespace and enter the parent one. 69 | /// 70 | void leave_namespace(); 71 | 72 | /// 73 | /// Get the current scope the symbol table operates in. 74 | /// 75 | /// 76 | const scope ¤t_scope() const { return _current_scope; } 77 | 78 | /// 79 | /// Insert an new symbol in the symbol table. Returns false if a symbol by that name and type already exists. 80 | /// 81 | bool insert_symbol(const std::string &name, const symbol &symbol, bool global = false); 82 | 83 | /// 84 | /// Look for an existing symbol with the specified . 85 | /// 86 | symbol find_symbol(const std::string &name) const; 87 | symbol find_symbol(const std::string &name, const scope &scope, bool exclusive) const; 88 | 89 | /// 90 | /// Search for the best function or intrinsic overload matching the argument list. 91 | /// 92 | bool resolve_function_call(const std::string &name, const std::vector &args, const scope &scope, symbol &data, bool &ambiguous) const; 93 | 94 | private: 95 | struct scoped_symbol : symbol { 96 | struct scope scope; // Store scope with symbol data 97 | }; 98 | 99 | scope _current_scope; 100 | std::unordered_map> _symbol_stack; 102 | }; 103 | } 104 | -------------------------------------------------------------------------------- /src/reshade/effect_token.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Patrick Mours. All rights reserved. 3 | * License: https://github.com/crosire/reshade#license 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | namespace reshadefx 12 | { 13 | /// 14 | /// Structure which keeps track of a code location 15 | /// 16 | struct location 17 | { 18 | location() : line(1), column(1) { } 19 | explicit location(unsigned int line, unsigned int column = 1) : line(line), column(column) { } 20 | explicit location(std::string source, unsigned int line, unsigned int column = 1) : source(std::move(source)), line(line), column(column) { } 21 | 22 | std::string source; 23 | unsigned int line, column; 24 | }; 25 | 26 | /// 27 | /// A collection of identifiers for various possible tokens. 28 | /// 29 | enum class tokenid 30 | { 31 | unknown = -1, 32 | end_of_file = 0, 33 | end_of_line = '\n', 34 | 35 | // operators 36 | space = ' ', 37 | exclaim = '!', 38 | hash = '#', 39 | dollar = '$', 40 | percent = '%', 41 | ampersand = '&', 42 | parenthesis_open = '(', 43 | parenthesis_close = ')', 44 | star = '*', 45 | plus = '+', 46 | comma = ',', 47 | minus = '-', 48 | dot = '.', 49 | slash = '/', 50 | colon = ':', 51 | semicolon = ';', 52 | less = '<', 53 | equal = '=', 54 | greater = '>', 55 | question = '?', 56 | at = '@', 57 | bracket_open = '[', 58 | backslash = '\\', 59 | bracket_close = ']', 60 | caret = '^', 61 | brace_open = '{', 62 | pipe = '|', 63 | brace_close = '}', 64 | tilde = '~', 65 | exclaim_equal = 256 /* != */, 66 | percent_equal /* %= */, 67 | ampersand_ampersand /* && */, 68 | ampersand_equal /* &= */, 69 | star_equal /* *= */, 70 | plus_plus /* ++*/, 71 | plus_equal /* += */, 72 | minus_minus /* -- */, 73 | minus_equal /* -= */, 74 | arrow /* -> */, 75 | ellipsis /* ... */, 76 | slash_equal /* /= */, 77 | colon_colon /* :: */, 78 | less_less_equal /* <<= */, 79 | less_less /* << */, 80 | less_equal /* <= */, 81 | equal_equal /* == */, 82 | greater_greater_equal /* >>= */, 83 | greater_greater /* >> */, 84 | greater_equal /* >= */, 85 | caret_equal /* ^= */, 86 | pipe_equal /* |= */, 87 | pipe_pipe /* || */, 88 | 89 | // identifiers 90 | reserved, 91 | identifier, 92 | 93 | // literals 94 | true_literal, 95 | false_literal, 96 | int_literal, 97 | uint_literal, 98 | float_literal, 99 | double_literal, 100 | string_literal, 101 | 102 | // keywords 103 | namespace_, 104 | struct_, 105 | technique, 106 | pass, 107 | for_, 108 | while_, 109 | do_, 110 | if_, 111 | else_, 112 | switch_, 113 | case_, 114 | default_, 115 | break_, 116 | continue_, 117 | return_, 118 | discard_, 119 | extern_, 120 | static_, 121 | uniform_, 122 | volatile_, 123 | precise, 124 | in, 125 | out, 126 | inout, 127 | const_, 128 | linear, 129 | noperspective, 130 | centroid, 131 | nointerpolation, 132 | 133 | void_, 134 | bool_, 135 | bool2, 136 | bool3, 137 | bool4, 138 | bool2x2, 139 | bool3x3, 140 | bool4x4, 141 | int_, 142 | int2, 143 | int3, 144 | int4, 145 | int2x2, 146 | int3x3, 147 | int4x4, 148 | uint_, 149 | uint2, 150 | uint3, 151 | uint4, 152 | uint2x2, 153 | uint3x3, 154 | uint4x4, 155 | float_, 156 | float2, 157 | float3, 158 | float4, 159 | float2x2, 160 | float3x3, 161 | float4x4, 162 | vector, 163 | matrix, 164 | string_, 165 | texture, 166 | sampler, 167 | 168 | // preprocessor directives 169 | hash_def, 170 | hash_undef, 171 | hash_if, 172 | hash_ifdef, 173 | hash_ifndef, 174 | hash_else, 175 | hash_elif, 176 | hash_endif, 177 | hash_error, 178 | hash_warning, 179 | hash_pragma, 180 | hash_include, 181 | hash_unknown, 182 | 183 | single_line_comment, 184 | multi_line_comment, 185 | }; 186 | 187 | /// 188 | /// A structure describing a single token in the input string. 189 | /// 190 | struct token 191 | { 192 | tokenid id; 193 | reshadefx::location location; 194 | size_t offset, length; 195 | union 196 | { 197 | int literal_as_int; 198 | unsigned int literal_as_uint; 199 | float literal_as_float; 200 | double literal_as_double; 201 | }; 202 | std::string literal_as_string; 203 | 204 | inline operator tokenid() const { return id; } 205 | 206 | static std::string id_to_name(tokenid id); 207 | }; 208 | } 209 | -------------------------------------------------------------------------------- /src/reshade/meson.build: -------------------------------------------------------------------------------- 1 | reshade_src = [ 2 | 'effect_codegen_spirv.cpp', 3 | 'effect_expression.cpp', 4 | 'effect_lexer.cpp', 5 | 'effect_parser.cpp', 6 | 'effect_preprocessor.cpp', 7 | 'effect_symbol_table.cpp', 8 | ] 9 | 10 | 11 | cpp_args_reshade = cpp.get_supported_arguments(['-Wno-unknown-pragmas']) 12 | 13 | 14 | reshade_lib = static_library('reshade', reshade_src, 15 | include_directories : vkBasalt_include_path, 16 | cpp_args : cpp_args_reshade, 17 | ) 18 | 19 | reshade_dep = declare_dependency( 20 | link_with : [ reshade_lib ]) -------------------------------------------------------------------------------- /src/reshade/spirv.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /src/reshade_uniforms.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RESHADE_UNIFORMS_HPP_INCLUDED 2 | #define RESHADE_UNIFORMS_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "reshade/effect_module.hpp" 14 | 15 | namespace vkBasalt 16 | { 17 | void enumerateReshadeUniforms(reshadefx::module module); 18 | 19 | class ReshadeUniform 20 | { 21 | public: 22 | void virtual update(void* mapedBuffer) = 0; 23 | virtual ~ReshadeUniform(){}; 24 | 25 | protected: 26 | uint32_t offset; 27 | uint32_t size; 28 | }; 29 | 30 | std::vector> createReshadeUniforms(reshadefx::module module); 31 | 32 | class FrameTimeUniform : public ReshadeUniform 33 | { 34 | public: 35 | FrameTimeUniform(reshadefx::uniform_info uniformInfo); 36 | void virtual update(void* mapedBuffer) override; 37 | virtual ~FrameTimeUniform(); 38 | 39 | private: 40 | std::chrono::time_point lastFrame; 41 | }; 42 | 43 | class FrameCountUniform : public ReshadeUniform 44 | { 45 | public: 46 | FrameCountUniform(reshadefx::uniform_info uniformInfo); 47 | void virtual update(void* mapedBuffer) override; 48 | virtual ~FrameCountUniform(); 49 | 50 | private: 51 | int32_t count = 0; 52 | }; 53 | 54 | class DateUniform : public ReshadeUniform 55 | { 56 | public: 57 | DateUniform(reshadefx::uniform_info uniformInfo); 58 | void virtual update(void* mapedBuffer) override; 59 | virtual ~DateUniform(); 60 | }; 61 | 62 | class TimerUniform : public ReshadeUniform 63 | { 64 | public: 65 | TimerUniform(reshadefx::uniform_info uniformInfo); 66 | void virtual update(void* mapedBuffer) override; 67 | virtual ~TimerUniform(); 68 | 69 | private: 70 | std::chrono::time_point start; 71 | }; 72 | 73 | class PingPongUniform : public ReshadeUniform 74 | { 75 | public: 76 | PingPongUniform(reshadefx::uniform_info uniformInfo); 77 | void virtual update(void* mapedBuffer) override; 78 | virtual ~PingPongUniform(); 79 | 80 | private: 81 | std::chrono::time_point lastFrame; 82 | 83 | float min = 0.0f; 84 | float max = 0.0f; 85 | float stepMin = 0.0f; 86 | float stepMax = 0.0f; 87 | float smoothing = 0.0f; 88 | float currentValue[2] = {0.0f, 1.0f}; 89 | }; 90 | 91 | class RandomUniform : public ReshadeUniform 92 | { 93 | public: 94 | RandomUniform(reshadefx::uniform_info uniformInfo); 95 | void virtual update(void* mapedBuffer) override; 96 | virtual ~RandomUniform(); 97 | 98 | private: 99 | int max = 0; 100 | int min = 0; 101 | }; 102 | 103 | class KeyUniform : public ReshadeUniform 104 | { 105 | public: 106 | KeyUniform(reshadefx::uniform_info uniformInfo); 107 | void virtual update(void* mapedBuffer) override; 108 | virtual ~KeyUniform(); 109 | }; 110 | 111 | class MouseButtonUniform : public ReshadeUniform 112 | { 113 | public: 114 | MouseButtonUniform(reshadefx::uniform_info uniformInfo); 115 | void virtual update(void* mapedBuffer) override; 116 | virtual ~MouseButtonUniform(); 117 | }; 118 | 119 | class MousePointUniform : public ReshadeUniform 120 | { 121 | public: 122 | MousePointUniform(reshadefx::uniform_info uniformInfo); 123 | void virtual update(void* mapedBuffer) override; 124 | virtual ~MousePointUniform(); 125 | }; 126 | 127 | class MouseDeltaUniform : public ReshadeUniform 128 | { 129 | public: 130 | MouseDeltaUniform(reshadefx::uniform_info uniformInfo); 131 | void virtual update(void* mapedBuffer) override; 132 | virtual ~MouseDeltaUniform(); 133 | }; 134 | 135 | class DepthUniform : public ReshadeUniform 136 | { 137 | public: 138 | DepthUniform(reshadefx::uniform_info uniformInfo); 139 | void virtual update(void* mapedBuffer) override; 140 | virtual ~DepthUniform(); 141 | }; 142 | } // namespace vkBasalt 143 | 144 | #endif // RESHADE_UNIFORMS_HPP_INCLUDED 145 | -------------------------------------------------------------------------------- /src/sampler.cpp: -------------------------------------------------------------------------------- 1 | #include "sampler.hpp" 2 | 3 | namespace vkBasalt 4 | { 5 | VkSampler createSampler(LogicalDevice* pLogicalDevice) 6 | { 7 | VkSampler sampler; 8 | 9 | VkSamplerCreateInfo samplerCreateInfo; 10 | samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 11 | samplerCreateInfo.pNext = nullptr; 12 | samplerCreateInfo.flags = 0; 13 | samplerCreateInfo.magFilter = VK_FILTER_LINEAR; 14 | samplerCreateInfo.minFilter = VK_FILTER_LINEAR; 15 | samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 16 | samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; 17 | samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; 18 | samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; 19 | samplerCreateInfo.mipLodBias = 0.0f; 20 | samplerCreateInfo.anisotropyEnable = VK_FALSE; 21 | samplerCreateInfo.maxAnisotropy = 16; 22 | samplerCreateInfo.compareEnable = VK_FALSE; 23 | samplerCreateInfo.compareOp = VK_COMPARE_OP_ALWAYS; 24 | samplerCreateInfo.minLod = 0.0f; 25 | samplerCreateInfo.maxLod = 0.0f; 26 | samplerCreateInfo.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK; 27 | samplerCreateInfo.unnormalizedCoordinates = VK_FALSE; 28 | 29 | VkResult result = pLogicalDevice->vkd.CreateSampler(pLogicalDevice->device, &samplerCreateInfo, nullptr, &sampler); 30 | ASSERT_VULKAN(result); 31 | return sampler; 32 | } 33 | 34 | VkSampler createReshadeSampler(LogicalDevice* pLogicalDevice, const reshadefx::sampler_info& samplerInfo) 35 | { 36 | VkSampler sampler; 37 | 38 | VkFilter minFilter; 39 | VkFilter magFilter; 40 | VkSamplerMipmapMode mipmapMode; 41 | convertReshadeFilter(samplerInfo.filter, minFilter, magFilter, mipmapMode); 42 | 43 | VkSamplerCreateInfo samplerCreateInfo; 44 | samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; 45 | samplerCreateInfo.pNext = nullptr; 46 | samplerCreateInfo.flags = 0; 47 | samplerCreateInfo.magFilter = magFilter; 48 | samplerCreateInfo.minFilter = minFilter; 49 | samplerCreateInfo.mipmapMode = mipmapMode; 50 | samplerCreateInfo.addressModeU = convertReshadeAddressMode(samplerInfo.address_u); 51 | samplerCreateInfo.addressModeV = convertReshadeAddressMode(samplerInfo.address_v); 52 | samplerCreateInfo.addressModeW = convertReshadeAddressMode(samplerInfo.address_w); 53 | samplerCreateInfo.mipLodBias = samplerInfo.lod_bias; 54 | samplerCreateInfo.anisotropyEnable = VK_FALSE; 55 | samplerCreateInfo.maxAnisotropy = 16; 56 | samplerCreateInfo.compareEnable = VK_FALSE; 57 | samplerCreateInfo.compareOp = VK_COMPARE_OP_ALWAYS; 58 | samplerCreateInfo.minLod = samplerInfo.min_lod; 59 | samplerCreateInfo.maxLod = samplerInfo.max_lod; 60 | samplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; 61 | samplerCreateInfo.unnormalizedCoordinates = VK_FALSE; 62 | 63 | VkResult result = pLogicalDevice->vkd.CreateSampler(pLogicalDevice->device, &samplerCreateInfo, nullptr, &sampler); 64 | ASSERT_VULKAN(result); 65 | return sampler; 66 | } 67 | 68 | VkSamplerAddressMode convertReshadeAddressMode(const reshadefx::texture_address_mode& addressMode) 69 | { 70 | switch (addressMode) 71 | { 72 | case reshadefx::texture_address_mode::wrap: return VK_SAMPLER_ADDRESS_MODE_REPEAT; 73 | case reshadefx::texture_address_mode::mirror: return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; 74 | case reshadefx::texture_address_mode::clamp: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; 75 | case reshadefx::texture_address_mode::border: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; 76 | } 77 | return VK_SAMPLER_ADDRESS_MODE_REPEAT; 78 | } 79 | 80 | void 81 | convertReshadeFilter(const reshadefx::texture_filter& textureFilter, VkFilter& minFilter, VkFilter& magFilter, VkSamplerMipmapMode& mipmapMode) 82 | { 83 | switch (textureFilter) 84 | { 85 | case reshadefx::texture_filter::min_mag_mip_point: 86 | minFilter = VK_FILTER_NEAREST; 87 | magFilter = VK_FILTER_NEAREST; 88 | mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; 89 | return; 90 | case reshadefx::texture_filter::min_mag_point_mip_linear: 91 | minFilter = VK_FILTER_NEAREST; 92 | magFilter = VK_FILTER_NEAREST; 93 | mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 94 | return; 95 | case reshadefx::texture_filter::min_point_mag_linear_mip_point: 96 | minFilter = VK_FILTER_NEAREST; 97 | magFilter = VK_FILTER_LINEAR; 98 | mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; 99 | return; 100 | case reshadefx::texture_filter::min_point_mag_mip_linear: 101 | minFilter = VK_FILTER_NEAREST; 102 | magFilter = VK_FILTER_LINEAR; 103 | mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 104 | return; 105 | case reshadefx::texture_filter::min_linear_mag_mip_point: 106 | minFilter = VK_FILTER_LINEAR; 107 | magFilter = VK_FILTER_NEAREST; 108 | mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; 109 | return; 110 | case reshadefx::texture_filter::min_linear_mag_point_mip_linear: 111 | minFilter = VK_FILTER_LINEAR; 112 | magFilter = VK_FILTER_NEAREST; 113 | mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 114 | return; 115 | case reshadefx::texture_filter::min_mag_linear_mip_point: 116 | minFilter = VK_FILTER_LINEAR; 117 | magFilter = VK_FILTER_LINEAR; 118 | mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; 119 | return; 120 | case reshadefx::texture_filter::min_mag_mip_linear: 121 | minFilter = VK_FILTER_LINEAR; 122 | magFilter = VK_FILTER_LINEAR; 123 | mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; 124 | return; 125 | } 126 | } 127 | } // namespace vkBasalt 128 | -------------------------------------------------------------------------------- /src/sampler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SAMPLER_HPP_INCLUDED 2 | #define SAMPLER_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "vulkan_include.hpp" 11 | 12 | #include "logical_device.hpp" 13 | 14 | #include "reshade/effect_module.hpp" 15 | namespace vkBasalt 16 | { 17 | VkSampler createSampler(LogicalDevice* pLogicalDevice); 18 | 19 | VkSampler createReshadeSampler(LogicalDevice* pLogicalDevice, const reshadefx::sampler_info& samplerInfo); 20 | 21 | VkSamplerAddressMode convertReshadeAddressMode(const reshadefx::texture_address_mode& addressMode); 22 | 23 | void 24 | convertReshadeFilter(const reshadefx::texture_filter& textureFilter, VkFilter& minFilter, VkFilter& magFilter, VkSamplerMipmapMode& mipmapMode); 25 | } // namespace vkBasalt 26 | 27 | #endif // SAMPLER_HPP_INCLUDED 28 | -------------------------------------------------------------------------------- /src/shader.cpp: -------------------------------------------------------------------------------- 1 | #include "shader.hpp" 2 | 3 | #include 4 | #include 5 | 6 | namespace vkBasalt 7 | { 8 | void createShaderModule(LogicalDevice* pLogicalDevice, const std::vector& code, VkShaderModule* shaderModule) 9 | { 10 | VkShaderModuleCreateInfo shaderCreateInfo; 11 | 12 | shaderCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 13 | shaderCreateInfo.pNext = nullptr; 14 | shaderCreateInfo.flags = 0; 15 | shaderCreateInfo.codeSize = code.size(); 16 | shaderCreateInfo.pCode = (uint32_t*) code.data(); 17 | 18 | VkResult result = pLogicalDevice->vkd.CreateShaderModule(pLogicalDevice->device, &shaderCreateInfo, nullptr, shaderModule); 19 | ASSERT_VULKAN(result); 20 | } 21 | 22 | void createShaderModule(LogicalDevice* pLogicalDevice, const std::vector& code, VkShaderModule* shaderModule) 23 | { 24 | VkShaderModuleCreateInfo shaderCreateInfo; 25 | 26 | shaderCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; 27 | shaderCreateInfo.pNext = nullptr; 28 | shaderCreateInfo.flags = 0; 29 | shaderCreateInfo.codeSize = code.size() * sizeof(uint32_t); 30 | shaderCreateInfo.pCode = code.data(); 31 | 32 | VkResult result = pLogicalDevice->vkd.CreateShaderModule(pLogicalDevice->device, &shaderCreateInfo, nullptr, shaderModule); 33 | ASSERT_VULKAN(result); 34 | } 35 | } // namespace vkBasalt 36 | -------------------------------------------------------------------------------- /src/shader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SHADER_HPP_INCLUDED 2 | #define SHADER_HPP_INCLUDED 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "vulkan_include.hpp" 12 | 13 | #include "logical_device.hpp" 14 | 15 | namespace vkBasalt 16 | { 17 | void createShaderModule(LogicalDevice* pLogicalDevice, const std::vector& code, VkShaderModule* shaderModule); 18 | void createShaderModule(LogicalDevice* pLogicalDevice, const std::vector& code, VkShaderModule* shaderModule); 19 | } // namespace vkBasalt 20 | 21 | #endif // SHADER_HPP_INCLUDED 22 | -------------------------------------------------------------------------------- /src/shader/cas.frag.glsl: -------------------------------------------------------------------------------- 1 | // LICENSE 2 | // ======= 3 | // Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved. 4 | // ------- 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 6 | // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 7 | // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 8 | // Software is furnished to do so, subject to the following conditions: 9 | // ------- 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 11 | // Software. 12 | // ------- 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 14 | // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 16 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 17 | #version 450 18 | 19 | layout(set=0, binding=0) uniform sampler2D img; 20 | 21 | layout (constant_id = 0) const float sharpness = 0.4; 22 | 23 | layout(location = 0) in vec2 textureCoord; 24 | layout(location = 0) out vec4 fragColor; 25 | 26 | #define textureLod0Offset(img, coord, offset) textureLodOffset(img, coord, 0.0f, offset) 27 | #define textureLod0(img, coord) textureLod(img, coord, 0.0f) 28 | 29 | void main() 30 | { 31 | // fetch a 3x3 neighborhood around the pixel 'e', 32 | // a b c 33 | // d(e)f 34 | // g h i 35 | vec4 inputColor = textureLod0(img,textureCoord); 36 | float alpha = inputColor.a; 37 | 38 | vec3 a = textureLod0Offset(img, textureCoord, ivec2(-1,-1)).rgb; 39 | vec3 b = textureLod0Offset(img, textureCoord, ivec2( 0,-1)).rgb; 40 | vec3 c = textureLod0Offset(img, textureCoord, ivec2( 1,-1)).rgb; 41 | vec3 d = textureLod0Offset(img, textureCoord, ivec2(-1, 0)).rgb; 42 | vec3 e = inputColor.rgb; 43 | vec3 f = textureLod0Offset(img, textureCoord, ivec2( 1, 0)).rgb; 44 | vec3 g = textureLod0Offset(img, textureCoord, ivec2(-1, 1)).rgb; 45 | vec3 h = textureLod0Offset(img, textureCoord, ivec2( 0, 1)).rgb; 46 | vec3 i = textureLod0Offset(img, textureCoord, ivec2( 1, 1)).rgb; 47 | 48 | // Soft min and max. 49 | // a b c b 50 | // d e f * 0.5 + d e f * 0.5 51 | // g h i h 52 | // These are 2.0x bigger (factored out the extra multiply). 53 | 54 | vec3 mnRGB = min(min(min(d,e),min(f,b)),h); 55 | vec3 mnRGB2 = min(min(min(mnRGB,a),min(g,c)),i); 56 | mnRGB += mnRGB2; 57 | 58 | vec3 mxRGB = max(max(max(d,e),max(f,b)),h); 59 | vec3 mxRGB2 = max(max(max(mxRGB,a),max(g,c)),i); 60 | mxRGB += mxRGB2; 61 | 62 | // Smooth minimum distance to signal limit divided by smooth max. 63 | 64 | vec3 rcpMxRGB = vec3(1)/mxRGB; 65 | vec3 ampRGB = clamp((min(mnRGB,2.0-mxRGB) * rcpMxRGB),0,1); 66 | 67 | // Shaping amount of sharpening. 68 | ampRGB = inversesqrt(ampRGB); 69 | float peak = 8.0 - 3.0 * sharpness; 70 | vec3 wRGB = -vec3(1)/(ampRGB * peak); 71 | vec3 rcpWeightRGB = vec3(1)/(1.0 + 4.0 * wRGB); 72 | 73 | // 0 w 0 74 | // Filter shape: w 1 w 75 | // 0 w 0 76 | 77 | vec3 window = (b + d) + (f + h); 78 | vec3 outColor = clamp((window * wRGB + e) * rcpWeightRGB,0,1); 79 | 80 | fragColor = vec4(outColor,alpha); 81 | } 82 | -------------------------------------------------------------------------------- /src/shader/deband.frag.glsl: -------------------------------------------------------------------------------- 1 | /** 2 | * Deband shader by haasn 3 | * https://github.com/haasn/gentoo-conf/blob/xor/home/nand/.mpv/shaders/deband-pre.glsl 4 | * 5 | * Copyright (c) 2015 Niklas Haas 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #version 450 26 | 27 | layout(set=0, binding=0) uniform sampler2D img; 28 | 29 | layout(constant_id = 0) const float screenWidth = 1920; 30 | layout(constant_id = 1) const float screenHeight = 1080; 31 | layout(constant_id = 2) const float reverseScreenWidth = 1.0/1920.0; 32 | layout(constant_id = 3) const float reverseScreenHeight = 1.0/1080.0; 33 | layout(constant_id = 4) const float debandAvgdiff = 3.4; 34 | layout(constant_id = 5) const float debandMaxdiff = 6.8; 35 | layout(constant_id = 6) const float debandMiddiff = 3.3; 36 | layout(constant_id = 7) const float range = 16.0; 37 | layout(constant_id = 8) const int iterations = 4; 38 | 39 | layout(location = 0) in vec2 texcoord; 40 | layout(location = 0) out vec4 fragColor; 41 | 42 | #define textureLod0Offset(img, coord, offset) textureLodOffset(img, coord, 0.0f, offset) 43 | #define textureLod0(img, coord) textureLod(img, coord, 0.0f) 44 | 45 | float rand(float x) 46 | { 47 | return fract(x / 41.0); 48 | } 49 | 50 | float permute(float x) 51 | { 52 | return mod(((34.0 * x + 1.0) * x), 289.0); 53 | } 54 | 55 | void analyze_pixels(vec3 ori, sampler2D tex, vec2 texcoord, vec2 _range, vec2 dir, out vec3 ref_avg, out vec3 ref_avg_diff, out vec3 ref_max_diff, out vec3 ref_mid_diff1, out vec3 ref_mid_diff2) 56 | { 57 | // Sample at quarter-turn intervals around the source pixel 58 | 59 | // South-east 60 | vec3 ref = textureLod0(tex, texcoord + _range * dir).rgb; 61 | vec3 diff = abs(ori - ref); 62 | ref_max_diff = diff; 63 | ref_avg = ref; 64 | ref_mid_diff1 = ref; 65 | 66 | // North-west 67 | ref = textureLod0(tex, texcoord + _range * -dir).rgb; 68 | diff = abs(ori - ref); 69 | ref_max_diff = max(ref_max_diff, diff); 70 | ref_avg += ref; 71 | ref_mid_diff1 = abs(((ref_mid_diff1 + ref) * 0.5) - ori); 72 | 73 | // North-east 74 | ref = textureLod0(tex, texcoord + _range * vec2(-dir.y, dir.x)).rgb; 75 | diff = abs(ori - ref); 76 | ref_max_diff = max(ref_max_diff, diff); 77 | ref_avg += ref; 78 | ref_mid_diff2 = ref; 79 | 80 | // South-west 81 | ref = textureLod0(tex, texcoord + _range * vec2( dir.y, -dir.x)).rgb; 82 | diff = abs(ori - ref); 83 | ref_max_diff = max(ref_max_diff, diff); 84 | ref_avg += ref; 85 | ref_mid_diff2 = abs(((ref_mid_diff2 + ref) * 0.5) - ori); 86 | 87 | ref_avg *= 0.25; // Normalize avg 88 | ref_avg_diff = abs(ori - ref_avg); 89 | } 90 | 91 | void main() 92 | { 93 | // Normalize 94 | float avgdiff = debandAvgdiff / 255.0; 95 | float maxdiff = debandMaxdiff / 55.0; 96 | float middiff = debandMiddiff / 255.0; 97 | 98 | const int drandom = 436;//TODO very random 99 | 100 | // Initialize the PRNG by hashing the position + a random uniform 101 | float h = permute(permute(permute(texcoord.x) + texcoord.y) + drandom / 32767.0); 102 | 103 | vec3 ref_avg; // Average of 4 reference pixels 104 | vec3 ref_avg_diff; // The difference between the average of 4 reference pixels and the original pixel 105 | vec3 ref_max_diff; // The maximum difference between one of the 4 reference pixels and the original pixel 106 | vec3 ref_mid_diff1; // The difference between the average of SE and NW reference pixels and the original pixel 107 | vec3 ref_mid_diff2; // The difference between the average of NE and SW reference pixels and the original pixel 108 | 109 | vec4 ori_alpha = textureLod0(img, texcoord); // Original pixel 110 | vec3 ori = ori_alpha.rgb; 111 | vec3 res; // Final pixel 112 | 113 | // Compute a random angle 114 | float dir = rand(permute(h)) * 6.2831853; 115 | vec2 o = vec2(cos(dir), sin(dir)); 116 | 117 | for (int i = 1; i <= iterations; ++i) { 118 | // Compute a random distance 119 | float dist = rand(h) * range * i; 120 | vec2 pt = dist * vec2(reverseScreenWidth, reverseScreenHeight); 121 | 122 | analyze_pixels(ori, img, texcoord, pt, o, 123 | ref_avg, 124 | ref_avg_diff, 125 | ref_max_diff, 126 | ref_mid_diff1, 127 | ref_mid_diff2); 128 | 129 | vec3 ref_avg_diff_threshold = vec3(avgdiff * i); 130 | vec3 ref_max_diff_threshold = vec3(maxdiff * i); 131 | vec3 ref_mid_diff_threshold = vec3(middiff * i); 132 | 133 | 134 | // Fuzzy logic based pixel selection 135 | vec3 factor = pow(clamp(3.0 * (1.0 - ref_avg_diff / ref_avg_diff_threshold), 0, 1) * 136 | clamp(3.0 * (1.0 - ref_max_diff / ref_max_diff_threshold), 0, 1) * 137 | clamp(3.0 * (1.0 - ref_mid_diff1 / ref_mid_diff_threshold), 0, 1) * 138 | clamp(3.0 * (1.0 - ref_mid_diff2 / ref_mid_diff_threshold), 0, 1), vec3(0.1)); 139 | 140 | res = mix(ori, ref_avg, factor); 141 | 142 | h = permute(h); 143 | } 144 | 145 | const float dither_bit = 8.0; //Number of bits per channel. Should be 8 for most monitors. 146 | 147 | /*------------------------. 148 | | :: Ordered Dithering :: | 149 | '------------------------*/ 150 | //Calculate grid position 151 | float grid_position = fract(dot(texcoord, (vec2(screenWidth, screenHeight) * vec2(1.0 / 16.0, 10.0 / 36.0)) + 0.25)); 152 | 153 | //Calculate how big the shift should be 154 | float dither_shift = 0.25 * (1.0 / (pow(2, dither_bit) - 1.0)); 155 | 156 | //Shift the individual colors differently, thus making it even harder to see the dithering pattern 157 | vec3 dither_shift_RGB = vec3(dither_shift, -dither_shift, dither_shift); //subpixel dithering 158 | 159 | //modify shift acording to grid position. 160 | dither_shift_RGB = mix(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position); //shift acording to grid position. 161 | 162 | //shift the color by dither_shift 163 | res += dither_shift_RGB; 164 | 165 | fragColor = vec4(res,ori_alpha.a); 166 | } 167 | -------------------------------------------------------------------------------- /src/shader/dls.frag.glsl: -------------------------------------------------------------------------------- 1 | /* 2 | Image sharpening filter from GeForce Experience. Provided by NVIDIA Corporation. 3 | 4 | Copyright 2019 Suketu J. Shah. All rights reserved. 5 | Redistribution and use in source and binary forms, with or without modification, are permitted provided 6 | that the following conditions are met: 7 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions 8 | and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions 10 | and the following disclaimer in the documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse 12 | or promote products derived from this software without specific prior written permission. 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 14 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 15 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 16 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 17 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 18 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 19 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 20 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 21 | */ 22 | 23 | #version 450 24 | 25 | layout(set=0, binding=0) uniform sampler2D img; 26 | 27 | layout (constant_id = 0) const float sharpen = 0.5; 28 | layout (constant_id = 1) const float denoise = 0.17; 29 | 30 | layout(location = 0) in vec2 textureCoord; 31 | layout(location = 0) out vec4 fragColor; 32 | 33 | #define textureLod0Offset(img, coord, offset) textureLodOffset(img, coord, 0.0f, offset) 34 | #define textureLod0(img, coord) textureLod(img, coord, 0.0f) 35 | 36 | float GetLumaComponents(float r, float g, float b) 37 | { 38 | // Y from JPEG spec 39 | return 0.299 * r + 0.587 * g + 0.114 * b; 40 | } 41 | 42 | float GetLuma(vec4 p) 43 | { 44 | return GetLumaComponents(p.x, p.y, p.z); 45 | } 46 | 47 | float Square(float v) 48 | { 49 | return v * v; 50 | } 51 | 52 | // highlight fall-off start (prevents halos and noise in bright areas) 53 | #define kHighBlock 0.65 54 | // offset reducing sharpening in the shadows 55 | #define kLowBlock (1.0 / 256.0) 56 | #define kSharpnessMin (-1.0 / 14.0) 57 | #define kSharpnessMax (-1.0 / 6.5) 58 | #define kDenoiseMin (0.001) 59 | #define kDenoiseMax (-0.1) 60 | 61 | void main() 62 | { 63 | // e d h 64 | // a (x) b 65 | // g c f 66 | 67 | vec4 x = textureLod0(img, textureCoord); 68 | 69 | vec4 a = textureLod0Offset(img, textureCoord, ivec2(-1, 0)); 70 | vec4 b = textureLod0Offset(img, textureCoord, ivec2( 1, 0)); 71 | vec4 c = textureLod0Offset(img, textureCoord, ivec2( 0, 1)); 72 | vec4 d = textureLod0Offset(img, textureCoord, ivec2( 0, -1)); 73 | 74 | vec4 e = textureLod0Offset(img, textureCoord, ivec2(-1, -1)); 75 | vec4 f = textureLod0Offset(img, textureCoord, ivec2( 1, 1)); 76 | vec4 g = textureLod0Offset(img, textureCoord, ivec2(-1, 1)); 77 | vec4 h = textureLod0Offset(img, textureCoord, ivec2( 1, -1)); 78 | 79 | float lx = GetLuma(x); 80 | 81 | float la = GetLuma(a); 82 | float lb = GetLuma(b); 83 | float lc = GetLuma(c); 84 | float ld = GetLuma(d); 85 | 86 | float le = GetLuma(e); 87 | float lf = GetLuma(f); 88 | float lg = GetLuma(g); 89 | float lh = GetLuma(h); 90 | 91 | // cross min/max 92 | const float ncmin = min(min(le, lf), min(lg, lh)); 93 | const float ncmax = max(max(le, lf), max(lg, lh)); 94 | 95 | // plus min/max 96 | float npmin = min(min(min(la, lb), min(lc, ld)), lx); 97 | float npmax = max(max(max(la, lb), max(lc, ld)), lx); 98 | 99 | // compute "soft" local dynamic range -- average of 3x3 and plus shape 100 | float lmin = 0.5 * min(ncmin, npmin) + 0.5 * npmin; 101 | float lmax = 0.5 * max(ncmax, npmax) + 0.5 * npmax; 102 | 103 | // compute local contrast enhancement kernel 104 | float lw = lmin / (lmax + kLowBlock); 105 | float hw = Square(1.0 - Square(max(lmax - kHighBlock, 0.0) / ((1.0 - kHighBlock)))); 106 | 107 | // noise suppression 108 | // Note: Ensure that the denoiseFactor is in the range of (10, 1000) on the CPU-side prior to launching this shader. 109 | // For example, you can do so by adding these lines 110 | // const float kDenoiseMin = 0.001f; 111 | // const float kDenoiseMax = 0.1f; 112 | // float kernelDenoise = 1.0 / (kDenoiseMin + (kDenoiseMax - kDenoiseMin) * min(max(denoise, 0.0), 1.0)); 113 | // where kernelDenoise is the value to be passed in to this shader (the amount of noise suppression is inversely proportional to this value), 114 | // denoise is the value chosen by the user, in the range (0, 1) 115 | const float kernelDenoise = 1.0 / (kDenoiseMin + (kDenoiseMax - kDenoiseMin) * denoise); 116 | const float nw = Square((lmax - lmin) * kernelDenoise); 117 | 118 | // pick conservative boost 119 | const float boost = min(min(lw, hw), nw); 120 | 121 | // run variable-sigma 3x3 sharpening convolution 122 | // Note: Ensure that the sharpenFactor is in the range of (-1.0/14.0, -1.0/6.5f) on the CPU-side prior to launching this shader. 123 | // For example, you can do so by adding these lines 124 | // const float kSharpnessMin = -1.0 / 14.0; 125 | // const float kSharpnessMax = -1.0 / 6.5f; 126 | // float kernelSharpness = kSharpnessMin + (kSharpnessMax - kSharpnessMin) * min(max(sharpen, 0.0), 1.0); 127 | // where kernelSharpness is the value to be passed in to this shader, 128 | // sharpen is the value chosen by the user, in the range (0, 1) 129 | const float kernelSharpness = kSharpnessMin + (kSharpnessMax - kSharpnessMin) * sharpen; 130 | const float k = boost * kernelSharpness; 131 | 132 | float accum = lx; 133 | accum += la * k; 134 | accum += lb * k; 135 | accum += lc * k; 136 | accum += ld * k; 137 | accum += le * (k * 0.5); 138 | accum += lf * (k * 0.5); 139 | accum += lg * (k * 0.5); 140 | accum += lh * (k * 0.5); 141 | 142 | // normalize (divide the accumulator by the sum of convolution weights) 143 | accum /= 1.0 + 6.0 * k; 144 | 145 | // accumulator is in linear light space 146 | float delta = accum - lx; 147 | x.x += delta; 148 | x.y += delta; 149 | x.z += delta; 150 | 151 | fragColor = x; 152 | } 153 | -------------------------------------------------------------------------------- /src/shader/full_screen_triangle.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location = 0) out vec2 textureCoord; 4 | 5 | void main() { 6 | gl_Position = vec4(gl_VertexIndex == 1 ? 3.0 : -1.0, 7 | gl_VertexIndex == 2 ? 3.0 : -1.0, 8 | 0.0, 9 | 1.0); 10 | 11 | textureCoord = vec2(gl_VertexIndex == 1 ? 2.0 : 0.0, 12 | gl_VertexIndex == 2 ? 2.0 : 0.0); 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/shader/fxaa.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_GOOGLE_include_directive : require 3 | 4 | #define FXAA_QUALITY_PRESET 39 5 | #define FXAA_GLSL_130 1 6 | #define FXAA_PC 1 7 | #define FXAA_GREEN_AS_LUMA 1 8 | #include "fxaa3_11.h" 9 | 10 | layout(set=0, binding=0) uniform sampler2D img; 11 | 12 | layout (constant_id = 0) const float fxaaQualitySubpix = 0.75; 13 | layout (constant_id = 1) const float fxaaQualityEdgeThreshold = 0.125; 14 | layout (constant_id = 2) const float fxaaQualityEdgeThresholdMin = 0.0312; 15 | layout (constant_id = 3) const float screenWidth = 1920; 16 | layout (constant_id = 4) const float screenHeight = 1080; 17 | 18 | layout(location = 0) in vec2 textureCoord; 19 | layout(location = 0) out vec4 fragColor; 20 | 21 | void main() 22 | { 23 | vec2 size = vec2(screenWidth,screenHeight); 24 | vec2 fxaaQualityRcpFrame = vec2(1.0)/size; 25 | 26 | vec4 zero = vec4(0.0); 27 | 28 | fragColor = FxaaPixelShader(textureCoord, zero, img, img, img, fxaaQualityRcpFrame, zero, zero, zero, fxaaQualitySubpix, fxaaQualityEdgeThreshold, fxaaQualityEdgeThresholdMin, 8.0, 0.125, 0.05, zero); 29 | } 30 | -------------------------------------------------------------------------------- /src/shader/lut.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(set=0, binding=0) uniform sampler2D img; 4 | layout(set=1, binding=0) uniform sampler3D lut; 5 | 6 | //Only works with cubes not with cuboids 7 | layout(constant_id = 0) const int lutSize = 32; 8 | layout(constant_id = 1) const int flipGB = 0; 9 | 10 | layout(location = 0) in vec2 textureCoord; 11 | layout(location = 0) out vec4 fragColor; 12 | 13 | #define textureLod0Offset(img, coord, offset) textureLodOffset(img, coord, 0.0f, offset) 14 | #define textureLod0(img, coord) textureLod(img, coord, 0.0f) 15 | 16 | void main() 17 | { 18 | vec4 color; 19 | if(flipGB != 0) 20 | { 21 | color = textureLod0(img,textureCoord).rbga; 22 | } 23 | else 24 | { 25 | color = textureLod0(img,textureCoord); 26 | } 27 | 28 | //see https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter24.html 29 | vec3 scale = (vec3(lutSize) - 1.0) / vec3(lutSize); 30 | vec3 offset = 1.0 / (2.0 * vec3(lutSize)); 31 | 32 | fragColor = vec4(textureLod0(lut, scale * color.rgb + offset).rgb, color.a); 33 | } 34 | -------------------------------------------------------------------------------- /src/shader/meson.build: -------------------------------------------------------------------------------- 1 | shader_src = [ 2 | 'cas.frag.glsl', 3 | 'deband.frag.glsl', 4 | 'dls.frag.glsl', 5 | 'full_screen_triangle.vert.glsl', 6 | 'fxaa.frag.glsl', 7 | 'lut.frag.glsl', 8 | 'smaa_blend.frag.glsl', 9 | 'smaa_blend.vert.glsl', 10 | 'smaa_edge_color.frag.glsl', 11 | 'smaa_edge_luma.frag.glsl', 12 | 'smaa_edge.vert.glsl', 13 | 'smaa_neighbor.frag.glsl', 14 | 'smaa_neighbor.vert.glsl', 15 | ] 16 | 17 | glsl_compiler = find_program('glslangValidator') 18 | glsl_generator = generator(glsl_compiler, 19 | output : [ '@BASENAME@.h' ], 20 | arguments : [ '-V', '-x', '@INPUT@', '-o', '@OUTPUT@' ]) 21 | 22 | shader_include = glsl_generator.process(shader_src) 23 | -------------------------------------------------------------------------------- /src/shader/smaa.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DadSchoorse/vkBasalt/4f97f09ffe91900e6ca136cc26cf7966f8f6970d/src/shader/smaa.h -------------------------------------------------------------------------------- /src/shader/smaa_blend.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_GOOGLE_include_directive : require 3 | 4 | layout(set = 0, binding = 1) uniform sampler2D edgesTex; 5 | layout(set = 0, binding = 2) uniform sampler2D areaTex; 6 | layout(set = 0, binding = 3) uniform sampler2D searchTex; 7 | 8 | layout(location = 0) out vec4 fragColor; 9 | layout(location = 0) in vec2 textureCoord; 10 | layout(location = 1) in vec2 pixelCoord; 11 | layout(location = 2) in vec4[3] offsets; 12 | 13 | #include "smaa_settings.h" 14 | 15 | #define SMAA_INCLUDE_VS 0 16 | #define SMAA_INCLUDE_PS 1 17 | #include "smaa.h" 18 | 19 | void main() 20 | { 21 | fragColor = SMAABlendingWeightCalculationPS(textureCoord, pixelCoord, offsets, edgesTex, areaTex, searchTex, vec4(0.0)); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/shader/smaa_blend.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_GOOGLE_include_directive : require 3 | 4 | vec2 positions[3] = vec2[]( 5 | vec2(-1.0,-1.0), 6 | vec2( 3.0,-1.0), 7 | vec2(-1.0, 3.0) 8 | ); 9 | 10 | vec2 texture_coordinates[3] = vec2[]( 11 | vec2( 0.0, 0.0), 12 | vec2( 2.0, 0.0), 13 | vec2( 0.0, 2.0) 14 | ); 15 | 16 | layout(location=0) out vec2 textureCoord; 17 | layout(location=1) out vec2 pixelCoord; 18 | layout(location=2) out vec4[3] offsets; 19 | 20 | #include "smaa_settings.h" 21 | #define SMAA_INCLUDE_VS 1 22 | #define SMAA_INCLUDE_PS 0 23 | #include "smaa.h" 24 | 25 | void main() 26 | { 27 | textureCoord = texture_coordinates[gl_VertexIndex]; 28 | SMAABlendingWeightCalculationVS(textureCoord, pixelCoord, offsets); 29 | gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/shader/smaa_edge.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_GOOGLE_include_directive : require 3 | 4 | vec2 positions[3] = vec2[]( 5 | vec2(-1.0,-1.0), 6 | vec2( 3.0,-1.0), 7 | vec2(-1.0, 3.0) 8 | ); 9 | 10 | vec2 texture_coordinates[3] = vec2[]( 11 | vec2( 0.0, 0.0), 12 | vec2( 2.0, 0.0), 13 | vec2( 0.0, 2.0) 14 | ); 15 | 16 | layout(location=0) out vec2 textureCoord; 17 | layout(location=1) out vec4[3] offsets; 18 | 19 | #include "smaa_settings.h" 20 | #define SMAA_INCLUDE_VS 1 21 | #define SMAA_INCLUDE_PS 0 22 | #include "smaa.h" 23 | 24 | void main() 25 | { 26 | textureCoord = texture_coordinates[gl_VertexIndex]; 27 | SMAAEdgeDetectionVS(textureCoord, offsets); 28 | gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/shader/smaa_edge_color.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_GOOGLE_include_directive : require 3 | 4 | layout(set = 0, binding = 0) uniform sampler2D colorImg; 5 | 6 | layout(location = 0) out vec4 fragColor; 7 | layout(location = 0) in vec2 textureCoord; 8 | layout(location = 1) in vec4[3] offsets; 9 | 10 | #include "smaa_settings.h" 11 | #define SMAA_INCLUDE_VS 0 12 | #define SMAA_INCLUDE_PS 1 13 | #include "smaa.h" 14 | 15 | void main() 16 | { 17 | fragColor = vec4(SMAAColorEdgeDetectionPS(textureCoord, offsets, colorImg), 0.0, 0.0); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/shader/smaa_edge_luma.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_GOOGLE_include_directive : require 3 | 4 | layout(set = 0, binding = 0) uniform sampler2D colorImg; 5 | 6 | layout(location = 0) out vec4 fragColor; 7 | layout(location = 0) in vec2 textureCoord; 8 | layout(location = 1) in vec4[3] offsets; 9 | 10 | #include "smaa_settings.h" 11 | #define SMAA_INCLUDE_VS 0 12 | #define SMAA_INCLUDE_PS 1 13 | #include "smaa.h" 14 | 15 | void main() 16 | { 17 | fragColor = vec4(SMAALumaEdgeDetectionPS(textureCoord, offsets, colorImg), 0.0, 0.0); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/shader/smaa_neighbor.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_GOOGLE_include_directive : require 3 | 4 | layout(set = 0, binding = 0) uniform sampler2D colorImg; 5 | layout(set = 0, binding = 4) uniform sampler2D blendTex; 6 | 7 | layout(location = 0) out vec4 fragColor; 8 | layout(location = 0) in vec2 textureCoord; 9 | layout(location = 1) in vec4 offset; 10 | 11 | #include "smaa_settings.h" 12 | #define SMAA_INCLUDE_VS 0 13 | #define SMAA_INCLUDE_PS 1 14 | #include "smaa.h" 15 | 16 | void main() 17 | { 18 | fragColor = SMAANeighborhoodBlendingPS(textureCoord, offset, colorImg, blendTex); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/shader/smaa_neighbor.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_GOOGLE_include_directive : require 3 | 4 | layout(location=0) out vec2 textureCoord; 5 | layout(location=1) out vec4 offset; 6 | 7 | #include "smaa_settings.h" 8 | #define SMAA_INCLUDE_VS 1 9 | #define SMAA_INCLUDE_PS 0 10 | #include "smaa.h" 11 | 12 | void main() 13 | { 14 | gl_Position = vec4(gl_VertexIndex == 1 ? 3.0 : -1.0, 15 | gl_VertexIndex == 2 ? 3.0 : -1.0, 16 | 0.0, 17 | 1.0); 18 | 19 | textureCoord = vec2(gl_VertexIndex == 1 ? 2.0 : 0.0, 20 | gl_VertexIndex == 2 ? 2.0 : 0.0); 21 | 22 | SMAANeighborhoodBlendingVS(textureCoord, offset); 23 | } 24 | -------------------------------------------------------------------------------- /src/shader/smaa_settings.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | layout(constant_id = 0) const float screenWidth = 1920; 4 | layout(constant_id = 1) const float screenHeight = 1080; 5 | layout(constant_id = 2) const float reverseScreenWidth = 1.0/1920.0; 6 | layout(constant_id = 3) const float reverseScreenHeight = 1.0/1080.0; 7 | layout(constant_id = 4) const float threshold = 0.05; 8 | layout(constant_id = 5) const int maxSearchSteps = 32; 9 | layout(constant_id = 6) const int maxSearchStepsDiag = 16; 10 | layout(constant_id = 7) const int cornerRounding = 25; 11 | 12 | #define SMAA_RT_METRICS vec4(reverseScreenWidth, reverseScreenHeight, screenWidth, screenHeight) 13 | #define SMAA_GLSL_4 1 14 | #define SMAA_THRESHOLD threshold 15 | #define SMAA_MAX_SEARCH_STEPS maxSearchSteps 16 | #define SMAA_MAX_SEARCH_STEPS_DIAG maxSearchStepsDiag 17 | #define SMAA_CORNER_ROUNDING cornerRounding 18 | 19 | -------------------------------------------------------------------------------- /src/shader_sources.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace vkBasalt 7 | { 8 | const std::vector cas_frag = { 9 | #include "cas.frag.h" 10 | }; 11 | 12 | const std::vector deband_frag = { 13 | #include "deband.frag.h" 14 | }; 15 | 16 | const std::vector dls_frag = { 17 | #include "dls.frag.h" 18 | }; 19 | 20 | const std::vector full_screen_triangle_vert = { 21 | #include "full_screen_triangle.vert.h" 22 | }; 23 | 24 | const std::vector fxaa_frag = { 25 | #include "fxaa.frag.h" 26 | }; 27 | 28 | const std::vector lut_frag = { 29 | #include "lut.frag.h" 30 | }; 31 | 32 | const std::vector smaa_blend_frag = { 33 | #include "smaa_blend.frag.h" 34 | }; 35 | 36 | const std::vector smaa_blend_vert = { 37 | #include "smaa_blend.vert.h" 38 | }; 39 | 40 | const std::vector smaa_edge_color_frag = { 41 | #include "smaa_edge_color.frag.h" 42 | }; 43 | 44 | const std::vector smaa_edge_luma_frag = { 45 | #include "smaa_edge_luma.frag.h" 46 | }; 47 | 48 | const std::vector smaa_edge_vert = { 49 | #include "smaa_edge.vert.h" 50 | }; 51 | 52 | const std::vector smaa_neighbor_frag = { 53 | #include "smaa_neighbor.frag.h" 54 | }; 55 | 56 | const std::vector smaa_neighbor_vert = { 57 | #include "smaa_neighbor.vert.h" 58 | }; 59 | } // namespace vkBasalt 60 | -------------------------------------------------------------------------------- /src/stb_image.c: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #define STB_IMAGE_DDS_IMPLEMENTATION 3 | #include "stb_image.h" 4 | #include "stb_image_dds.h" 5 | 6 | #undef STB_IMAGE_IMPLEMENTATION 7 | #undef STB_IMAGE_DDS_IMPLEMENTATION 8 | -------------------------------------------------------------------------------- /src/stb_image_resize.c: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_RESIZE_IMPLEMENTATION 2 | #include "stb_image_resize.h" 3 | 4 | #undef STB_IMAGE_RESIZE_IMPLEMENTATION 5 | -------------------------------------------------------------------------------- /src/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.hpp" 2 | 3 | #include 4 | #include 5 | 6 | namespace vkBasalt 7 | { 8 | void addUniqueCString(std::vector& stringVector, const char* addString) 9 | { 10 | for (const char* other : stringVector) 11 | { 12 | if (other == std::string(addString)) 13 | { 14 | return; 15 | } 16 | } 17 | stringVector.push_back(addString); 18 | } 19 | 20 | void outputInColor(std::string output, Color foreground, Color background) 21 | { 22 | std::vector magicNumbers; 23 | switch (foreground) 24 | { 25 | case Color::black: magicNumbers.push_back("30"); break; 26 | case Color::red: magicNumbers.push_back("31"); break; 27 | case Color::green: magicNumbers.push_back("32"); break; 28 | case Color::yellow: magicNumbers.push_back("33"); break; 29 | case Color::blue: magicNumbers.push_back("34"); break; 30 | case Color::magenta: magicNumbers.push_back("35"); break; 31 | case Color::cyan: magicNumbers.push_back("36"); break; 32 | case Color::white: magicNumbers.push_back("37"); break; 33 | default: break; 34 | } 35 | switch (background) 36 | { 37 | case Color::black: magicNumbers.push_back("40"); break; 38 | case Color::red: magicNumbers.push_back("41"); break; 39 | case Color::green: magicNumbers.push_back("42"); break; 40 | case Color::yellow: magicNumbers.push_back("43"); break; 41 | case Color::blue: magicNumbers.push_back("44"); break; 42 | case Color::magenta: magicNumbers.push_back("45"); break; 43 | case Color::cyan: magicNumbers.push_back("46"); break; 44 | case Color::white: magicNumbers.push_back("47"); break; 45 | default: break; 46 | } 47 | std::string magicString = ""; 48 | for (bool first = true; auto& magicNumber : magicNumbers) 49 | { 50 | if (!first) 51 | { 52 | magicString += ";"; 53 | } 54 | magicString += magicNumber; 55 | first = false; 56 | } 57 | if (magicString.size() == 0 || !isatty(fileno(stdout))) 58 | { 59 | std::cout << output << std::endl; 60 | } 61 | else 62 | { 63 | std::cout << "\033[" << magicString << "m" << output << "\033[0m" << std::endl; 64 | } 65 | } 66 | } // namespace vkBasalt 67 | -------------------------------------------------------------------------------- /src/util.hpp: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_HPP_INCLUDED 2 | #define UTIL_HPP_INCLUDED 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace vkBasalt 9 | { 10 | void addUniqueCString(std::vector& stringVector, const char* addString); 11 | 12 | enum class Color 13 | { 14 | defaultColor, 15 | 16 | black, 17 | red, 18 | green, 19 | yellow, 20 | blue, 21 | magenta, 22 | cyan, 23 | white 24 | }; 25 | 26 | void outputInColor(std::string output, Color foreground = Color::defaultColor, Color background = Color::defaultColor); 27 | 28 | template 29 | std::string convertToString(T object) 30 | { 31 | std::stringstream ss; 32 | ss << object; 33 | return ss.str(); 34 | } 35 | } // namespace vkBasalt 36 | 37 | #endif // UTIL_HPP_INCLUDED 38 | -------------------------------------------------------------------------------- /src/vkdispatch.cpp: -------------------------------------------------------------------------------- 1 | #include "vkdispatch.hpp" 2 | 3 | #include "vkfuncs.hpp" 4 | 5 | namespace vkBasalt 6 | { 7 | 8 | void fillDispatchTableInstance(VkInstance instance, PFN_vkGetInstanceProcAddr gipa, InstanceDispatch* table) 9 | { 10 | table->GetInstanceProcAddr = gipa; 11 | #define FORVKFUNC(func) \ 12 | do \ 13 | { \ 14 | if (!table->func) \ 15 | table->func = (PFN_vk##func) gipa(instance, "vk" #func); \ 16 | } while (false); 17 | VK_INSTANCE_FUNCS 18 | #undef FORVKFUNC 19 | } 20 | 21 | void fillDispatchTableDevice(VkDevice device, PFN_vkGetDeviceProcAddr gdpa, DeviceDispatch* table) 22 | { 23 | table->GetDeviceProcAddr = gdpa; 24 | #define FORVKFUNC(func) \ 25 | do \ 26 | { \ 27 | if (!table->func) \ 28 | table->func = (PFN_vk##func) gdpa(device, "vk" #func); \ 29 | } while (false); 30 | VK_DEVICE_FUNCS 31 | #undef FORVKFUNC 32 | } 33 | 34 | } // namespace vkBasalt 35 | 36 | #undef VK_INSTANCE_FUNCS 37 | #undef VK_DEVICE_FUNCS 38 | -------------------------------------------------------------------------------- /src/vkdispatch.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "vulkan_include.hpp" 4 | 5 | #include "vkfuncs.hpp" 6 | 7 | #define FORVKFUNC(func) PFN_vk##func func = nullptr; 8 | 9 | namespace vkBasalt 10 | { 11 | 12 | struct InstanceDispatch 13 | { 14 | VK_INSTANCE_FUNCS 15 | }; 16 | 17 | struct DeviceDispatch 18 | { 19 | VK_DEVICE_FUNCS 20 | }; 21 | 22 | void fillDispatchTableInstance(VkInstance instance, PFN_vkGetInstanceProcAddr gipa, InstanceDispatch* table); 23 | void fillDispatchTableDevice(VkDevice device, PFN_vkGetDeviceProcAddr gdpa, DeviceDispatch* table); 24 | 25 | } // namespace vkBasalt 26 | 27 | #undef FORVKFUNC 28 | #undef VK_INSTANCE_FUNCS 29 | #undef VK_DEVICE_FUNCS 30 | -------------------------------------------------------------------------------- /src/vkfuncs.hpp: -------------------------------------------------------------------------------- 1 | 2 | #define VK_INSTANCE_FUNCS \ 3 | FORVKFUNC(DestroyInstance) \ 4 | FORVKFUNC(EnumerateDeviceExtensionProperties) \ 5 | FORVKFUNC(GetInstanceProcAddr) \ 6 | FORVKFUNC(GetPhysicalDeviceFormatProperties) \ 7 | FORVKFUNC(GetPhysicalDeviceMemoryProperties) \ 8 | FORVKFUNC(GetPhysicalDeviceQueueFamilyProperties) \ 9 | FORVKFUNC(GetPhysicalDeviceProperties) 10 | 11 | #define VK_DEVICE_FUNCS \ 12 | FORVKFUNC(AllocateCommandBuffers) \ 13 | FORVKFUNC(AllocateDescriptorSets) \ 14 | FORVKFUNC(AllocateMemory) \ 15 | FORVKFUNC(BeginCommandBuffer) \ 16 | FORVKFUNC(BindBufferMemory) \ 17 | FORVKFUNC(BindImageMemory) \ 18 | FORVKFUNC(CmdBeginRenderPass) \ 19 | FORVKFUNC(CmdBindDescriptorSets) \ 20 | FORVKFUNC(CmdBindPipeline) \ 21 | FORVKFUNC(CmdBlitImage) \ 22 | FORVKFUNC(CmdCopyBufferToImage) \ 23 | FORVKFUNC(CmdCopyImage) \ 24 | FORVKFUNC(CmdDraw) \ 25 | FORVKFUNC(CmdEndRenderPass) \ 26 | FORVKFUNC(CmdPipelineBarrier) \ 27 | FORVKFUNC(CreateBuffer) \ 28 | FORVKFUNC(CreateCommandPool) \ 29 | FORVKFUNC(CreateDescriptorPool) \ 30 | FORVKFUNC(CreateDescriptorSetLayout) \ 31 | FORVKFUNC(CreateFramebuffer) \ 32 | FORVKFUNC(CreateGraphicsPipelines) \ 33 | FORVKFUNC(CreateImage) \ 34 | FORVKFUNC(CreateImageView) \ 35 | FORVKFUNC(CreatePipelineLayout) \ 36 | FORVKFUNC(CreateRenderPass) \ 37 | FORVKFUNC(CreateSampler) \ 38 | FORVKFUNC(CreateSemaphore) \ 39 | FORVKFUNC(CreateShaderModule) \ 40 | FORVKFUNC(CreateSwapchainKHR) \ 41 | FORVKFUNC(DestroyBuffer) \ 42 | FORVKFUNC(DestroyCommandPool) \ 43 | FORVKFUNC(DestroyDescriptorPool) \ 44 | FORVKFUNC(DestroyDescriptorSetLayout) \ 45 | FORVKFUNC(DestroyDevice) \ 46 | FORVKFUNC(DestroyFramebuffer) \ 47 | FORVKFUNC(DestroyImage) \ 48 | FORVKFUNC(DestroyImageView) \ 49 | FORVKFUNC(DestroyPipeline) \ 50 | FORVKFUNC(DestroyPipelineLayout) \ 51 | FORVKFUNC(DestroyRenderPass) \ 52 | FORVKFUNC(DestroySampler) \ 53 | FORVKFUNC(DestroySemaphore) \ 54 | FORVKFUNC(DestroyShaderModule) \ 55 | FORVKFUNC(DestroySwapchainKHR) \ 56 | FORVKFUNC(EndCommandBuffer) \ 57 | FORVKFUNC(FreeCommandBuffers) \ 58 | FORVKFUNC(FreeMemory) \ 59 | FORVKFUNC(GetBufferMemoryRequirements) \ 60 | FORVKFUNC(GetDeviceProcAddr) \ 61 | FORVKFUNC(GetDeviceQueue) \ 62 | FORVKFUNC(GetDeviceQueue2) \ 63 | FORVKFUNC(GetImageMemoryRequirements) \ 64 | FORVKFUNC(GetSwapchainImagesKHR) \ 65 | FORVKFUNC(MapMemory) \ 66 | FORVKFUNC(QueuePresentKHR) \ 67 | FORVKFUNC(QueueSubmit) \ 68 | FORVKFUNC(QueueWaitIdle) \ 69 | FORVKFUNC(UnmapMemory) \ 70 | FORVKFUNC(UpdateDescriptorSets) 71 | -------------------------------------------------------------------------------- /src/vulkan_include.hpp: -------------------------------------------------------------------------------- 1 | #ifndef VULKAN_INCLUDE_HPP_INCLUDED 2 | #define VULKAN_INCLUDE_HPP_INCLUDED 3 | 4 | #define VK_NO_PROTOTYPES 5 | 6 | #pragma GCC system_header 7 | #include "vulkan/vulkan.h" 8 | #include "vulkan/vk_layer.h" 9 | 10 | #include 11 | 12 | #include "logger.hpp" 13 | 14 | #ifndef ASSERT_VULKAN 15 | #define ASSERT_VULKAN(val) \ 16 | if (val != VK_SUCCESS) \ 17 | { \ 18 | Logger::err("ASSERT_VULKAN failed in " + std::string(__FILE__) + " : " + std::to_string(__LINE__) + "; " + std::to_string(val)); \ 19 | } 20 | #endif 21 | namespace vkBasalt 22 | { 23 | template 24 | inline void initializeDispatchTable(DispatchableType dispatchableObject, SuperDispatchableType source) 25 | { 26 | *reinterpret_cast(dispatchableObject) = *reinterpret_cast(source); 27 | } 28 | } // namespace vkBasalt 29 | 30 | #endif // VULKAN_INCLUDE_HPP_INCLUDED 31 | --------------------------------------------------------------------------------