├── .gitattributes ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .gitmodules ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── TGEngine ├── CMakeLists.txt ├── CMakeSettings.json ├── private │ ├── Error.cpp │ ├── IO │ │ └── IOModule.cpp │ ├── TGEngine.cpp │ ├── Util.cpp │ └── graphics │ │ ├── GUIModule.cpp │ │ ├── GameGraphicsModule.cpp │ │ ├── GameShaderModule.cpp │ │ ├── Material.cpp │ │ ├── Vulkan │ │ ├── VulkanGraphicsModule.cpp │ │ └── VulkanShaderModule.cpp │ │ └── WindowModule.cpp ├── public │ ├── Error.hpp │ ├── IO │ │ └── IOModule.hpp │ ├── Module.hpp │ ├── TGEngine.hpp │ ├── Util.hpp │ ├── graphics │ │ ├── APILayer.hpp │ │ ├── GUIModule.hpp │ │ ├── GameGraphicsModule.hpp │ │ ├── GameShaderModule.hpp │ │ ├── Material.hpp │ │ ├── WindowModule.hpp │ │ └── vulkan │ │ │ ├── VulkanGraphicsModule.hpp │ │ │ ├── VulkanModuleDef.hpp │ │ │ ├── VulkanShaderModule.hpp │ │ │ └── VulkanShaderPipe.hpp │ └── headerlibs │ │ ├── json.hpp │ │ ├── stb_image.h │ │ ├── stb_image_write.h │ │ └── tiny_gltf.h ├── renderTest │ └── TGRenderTest.cpp └── test │ ├── TGTest.cpp │ └── assets │ ├── Test │ ├── apple.png │ ├── cup.png │ ├── plate.png │ ├── table.png │ ├── teapot.png │ ├── test.bin │ └── test.gltf │ ├── Triangle.gltf │ ├── avocado.vert │ ├── lightPass.frag │ ├── lightPass.vert │ ├── simpleTriangle.bin │ ├── test.frag │ ├── test.png │ ├── test.vert │ ├── test3c.png │ ├── testLight.frag │ ├── testLight.vert │ ├── testTexture.frag │ ├── testUV.vert │ └── testvec4.vert ├── install.bat ├── setup.bat └── setup.py /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: MrTroble 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | dependencies\\/ 5 | *.spv 6 | 7 | # User-specific files 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | ./TGEngine/out 33 | 34 | # MSTest test Results 35 | [Tt]est[Rr]esult*/ 36 | [Bb]uild[Ll]og.* 37 | 38 | # NUNIT 39 | *.VisualState.xml 40 | TestResult.xml 41 | 42 | # Build Results of an ATL Project 43 | [Dd]ebugPS/ 44 | [Rr]eleasePS/ 45 | dlldata.c 46 | 47 | # DNX 48 | project.lock.json 49 | project.fragment.lock.json 50 | artifacts/ 51 | 52 | *_i.c 53 | *_p.c 54 | *_i.h 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.tmp_proj 69 | *.log 70 | *.vspscc 71 | *.vssscc 72 | .builds 73 | *.pidb 74 | *.svclog 75 | *.scc 76 | 77 | # Chutzpah Test files 78 | _Chutzpah* 79 | 80 | # Visual C++ cache files 81 | ipch/ 82 | *.aps 83 | *.ncb 84 | *.opendb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | *.VC.db 89 | *.VC.VC.opendb 90 | 91 | # Visual Studio profiler 92 | *.psess 93 | *.vsp 94 | *.vspx 95 | *.sap 96 | 97 | # TFS 2012 Local Workspace 98 | $tf/ 99 | 100 | # Guidance Automation Toolkit 101 | *.gpState 102 | 103 | # ReSharper is a .NET coding add-in 104 | _ReSharper*/ 105 | *.[Rr]e[Ss]harper 106 | *.DotSettings.user 107 | 108 | # JustCode is a .NET coding add-in 109 | .JustCode 110 | 111 | # TeamCity is a build add-in 112 | _TeamCity* 113 | 114 | # DotCover is a Code Coverage Tool 115 | *.dotCover 116 | 117 | # NCrunch 118 | _NCrunch_* 119 | .*crunch*.local.xml 120 | nCrunchTemp_* 121 | 122 | # MightyMoose 123 | *.mm.* 124 | AutoTest.Net/ 125 | 126 | # Web workbench (sass) 127 | .sass-cache/ 128 | 129 | # Installshield output folder 130 | [Ee]xpress/ 131 | 132 | # DocProject is a documentation generator add-in 133 | DocProject/buildhelp/ 134 | DocProject/Help/*.HxT 135 | DocProject/Help/*.HxC 136 | DocProject/Help/*.hhc 137 | DocProject/Help/*.hhk 138 | DocProject/Help/*.hhp 139 | DocProject/Help/Html2 140 | DocProject/Help/html 141 | 142 | # Click-Once directory 143 | publish/ 144 | 145 | # Publish Web Output 146 | *.[Pp]ublish.xml 147 | *.azurePubxml 148 | # TODO: Comment the next line if you want to checkin your web deploy settings 149 | # but database connection strings (with potential passwords) will be unencrypted 150 | #*.pubxml 151 | *.publishproj 152 | 153 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 154 | # checkin your Azure Web App publish settings, but sensitive information contained 155 | # in these scripts will be unencrypted 156 | PublishScripts/ 157 | 158 | # NuGet Packages 159 | *.nupkg 160 | # The packages folder can be ignored because of Package Restore 161 | **/packages/* 162 | # except build/, which is used as an MSBuild target. 163 | !**/packages/build/ 164 | # Uncomment if necessary however generally it will be regenerated when needed 165 | #!**/packages/repositories.config 166 | # NuGet v3's project.json files produces more ignoreable files 167 | *.nuget.props 168 | *.nuget.targets 169 | 170 | # Microsoft Azure Build Output 171 | csx/ 172 | *.build.csdef 173 | 174 | # Microsoft Azure Emulator 175 | ecf/ 176 | rcf/ 177 | 178 | # Windows Store app package directories and files 179 | AppPackages/ 180 | BundleArtifacts/ 181 | Package.StoreAssociation.xml 182 | _pkginfo.txt 183 | 184 | # Visual Studio cache files 185 | # files ending in .cache can be ignored 186 | *.[Cc]ache 187 | # but keep track of directories ending in .cache 188 | !*.[Cc]ache/ 189 | 190 | # Others 191 | ClientBin/ 192 | ~$* 193 | *~ 194 | *.dbmdl 195 | *.dbproj.schemaview 196 | *.jfm 197 | *.pfx 198 | *.publishsettings 199 | node_modules/ 200 | orleans.codegen.cs 201 | 202 | # Since there are multiple workflows, uncomment next line to ignore bower_components 203 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 204 | #bower_components/ 205 | 206 | # RIA/Silverlight projects 207 | Generated_Code/ 208 | 209 | # Backup & report files from converting an old project file 210 | # to a newer Visual Studio version. Backup files are not needed, 211 | # because we have git ;-) 212 | _UpgradeReport_Files/ 213 | Backup*/ 214 | UpgradeLog*.XML 215 | UpgradeLog*.htm 216 | 217 | # SQL Server files 218 | *.mdf 219 | *.ldf 220 | 221 | # Business Intelligence projects 222 | *.rdl.data 223 | *.bim.layout 224 | *.bim_*.settings 225 | 226 | # Microsoft Fakes 227 | FakesAssemblies/ 228 | 229 | # GhostDoc plugin setting file 230 | *.GhostDoc.xml 231 | 232 | # Node.js Tools for Visual Studio 233 | .ntvs_analysis.dat 234 | 235 | # Visual Studio 6 build log 236 | *.plg 237 | 238 | # Visual Studio 6 workspace options file 239 | *.opt 240 | 241 | # Visual Studio LightSwitch build output 242 | **/*.HTMLClient/GeneratedArtifacts 243 | **/*.DesktopClient/GeneratedArtifacts 244 | **/*.DesktopClient/ModelManifest.xml 245 | **/*.Server/GeneratedArtifacts 246 | **/*.Server/ModelManifest.xml 247 | _Pvt_Extensions 248 | 249 | # Paket dependency manager 250 | .paket/paket.exe 251 | paket-files/ 252 | 253 | # FAKE - F# Make 254 | .fake/ 255 | 256 | # JetBrains Rider 257 | .idea/ 258 | *.sln.iml 259 | 260 | # CodeRush 261 | .cr/ 262 | 263 | # Python Tools for Visual Studio (PTVS) 264 | __pycache__/ 265 | *.pyc 266 | /TGEditor/Vraag.png 267 | /TGEngine/run/TGEngine-0.0.3.zip 268 | /TGEngine/run 269 | /TGEngine/out 270 | dependencies/deps.zip 271 | /dependencies/deps/Deps 272 | /TGEditor/helmet.blend 273 | /dependencies 274 | /TGEngine/TGEngine.layout 275 | /TGEngine/TGEngine.depend 276 | /TGEngine/TGEngine.cbp 277 | /TGEditor/TGEditor.layout 278 | /TGEditor/TGEditor.cbp 279 | /TGEditor/resource/loop.fbx 280 | /TGEditor/resource/Helmet.fbx 281 | /fbx/include 282 | /Dependencies.zip 283 | /TGEditor/resource 284 | /Chess 285 | /test 286 | /Release.zip 287 | /ShaderTool/Test/Resources 288 | /ShaderTool/bin 289 | /ShaderTool/obj 290 | /TGEditor/TGEditor.exe 291 | /TGEditor/start.py 292 | /TGEditor/report.txt 293 | /TGEditor/report_fixed.txt 294 | /ShaderToolUI/build-ShaderTool-Desktop_Qt_5_13_0_MSVC2015_64bit-Debug 295 | /ShaderToolUI/build-ShaderTool-Desktop_Qt_5_13_0_MSVC2017_64bit-Debug 296 | /ShaderToolUI/build-ShaderTool-Qt_5_13_0_for_UWP_64bit_MSVC_2017-Debug 297 | /ShaderToolUI/build-ShaderTool-Desktop_Qt_5_13_0_MinGW_32_bit-Debug 298 | /TGEngine/resources/Resources.json 299 | /TGEngine/resources/Resources.tgr 300 | *.spv 301 | /TGEngine/out 302 | /TGEngine/test/assets/glslangValidator.exe 303 | /TGEngine/graph_info.json 304 | /TGEngine/conaninfo.txt 305 | /TGEngine/conanbuildinfo.txt 306 | /TGEngine/conan.lock 307 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "TGEngine/test/assets/glTF-Sample-Models"] 2 | path = TGEngine/test/assets/glTF-Sample-Models 3 | url = https://github.com/KhronosGroup/glTF-Sample-Models 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at nifroh56@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 |

Contribute?

2 | 3 | Everyone can contribute unless he is banned of contributing.
4 | Only the owner Nico "MrTroble" can ban someone.
5 | Every commit needs to be confirmed by the owner.
6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | TRADEMARK: 179 | 180 | The names 'MrTroble', 'Troblecodings', 'TrobleGameEngine' and 'TGEngine' have 181 | not been registered by the Licensor as a trademark in any jurisdiction. 182 | However, because 'MrTroble', 'Troblecodings', 'TrobleGameEngine' and 'TGEngine' 183 | have been distributed and maintained world-wide, continually since 2015, 184 | the Licensor claims "common-law trademark protection" in any 185 | jurisdiction where common-law trademark is recognized. 186 | 187 | APPENDIX: How to apply the Apache License to your work. 188 | 189 | To apply the Apache License to your work, attach the following 190 | boilerplate notice, with the fields enclosed by brackets "{}" 191 | replaced with your own identifying information. (Don't include 192 | the brackets!) The text should be enclosed in the appropriate 193 | comment syntax for the file format. We also recommend that a 194 | file or class name and description of purpose be included on the 195 | same "printed page" as the copyright notice for easier 196 | identification within third-party archives. 197 | 198 | Copyright 2017 Nico Fröhlich 199 | 200 | Nico Fröhlich is also known as 'MrTroble'. 201 | 202 | Licensed under the Apache License, Version 2.0 (the "License"); 203 | you may not use this file except in compliance with the License. 204 | You may obtain a copy of the License at 205 | 206 | http://www.apache.org/licenses/LICENSE-2.0 207 | 208 | Unless required by applicable law or agreed to in writing, software 209 | distributed under the License is distributed on an "AS IS" BASIS, 210 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 211 | See the License for the specific language governing permissions and 212 | limitations under the License. 213 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

TGEngine

2 | 3 |

What is the TGEngine?

4 | 5 | It should be or better to say it will be a Game Engine, hopefully... 6 | 7 |

Status

8 | 9 | Visit our [Roadmap](https://trello.com/b/CvHhdjVN) 10 | 11 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/463ead5524004360a3c1b7acb98e238b)](https://app.codacy.com/app/MrTroble_2/TGEngine?utm_source=github.com&utm_medium=referral&utm_content=Troblecodings/TGEngine&utm_campaign=Badge_Grade_Dashboard) 12 | 13 | still working on it...
14 | For updates please follow the [official twitter account of Troblecodings](https://twitter.com/Troblecodings) 15 | 16 | To run the app your build you need to install the Lunarg Vulkan SDK. A mirrow can be found [here](https://drive.google.com/drive/folders/18_ucs58vY9T3xB5lfVoYFKtjZm3DqF4v?usp=sharing) 17 | 18 |

Build your own

19 | 20 | To compile your own build you have to install the dependencies.
21 | To do so you need tu run python setup.py.
22 | There you have to select 1 Get dependencies
23 | Now you can open the VisualStudios Project file and compile the Engine. 24 | 25 |

Build Status

26 | 27 | | Platform | Build Status | 28 | |:--------:|:------------:| 29 | | Windows (Visual Studio 2017) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/xkqlankoj873h3xh?svg=true)](https://ci.appveyor.com/project/MrTroble/tgengine) | 30 | | Linux | ![Linux Build Status](https://img.shields.io/badge/build-not%20passing-red.svg) | 31 | 32 |

Libraries

33 | 34 | I am using [LunarG's Vulkan-SDK](https://vulkan.lunarg.com/sdk/home).
35 | Current built version: 1.1.101
36 | Current Vulkan API version: 1.1 37 |
38 |
39 | and Autodesk [FBX SDK](https://www.autodesk.com/developer-network/platform-technologies/fbx-sdk-2019-2)
40 | Current built version: 2019.2 41 |
42 |
43 | For image loading and font loading is [STB](https://github.com/nothings/stb) currently being used.
44 | This is planned to be replaced in the future.
45 | *SIDE NOTE: The file library [TGVL](https://github.com/Troblecodings/TGVertex) maybe needed in the future to compile newer versions of the TGEngine 46 | but currently it is not supported!* 47 | 48 |

License

49 | 50 | Can be found in the [License File](https://github.com/MrTroble/TGEngine/blob/master/LICENSE) 51 |
52 |

Library

53 | 54 | Every library used is Open-Source or free to use.
55 |
56 | STB is published under a [Public domain](https://github.com/nothings/stb) License (or MIT)
57 | LunarG's Vulkan-SDK is published under [Creative Commons](https://creativecommons.org/licenses/by-nd/4.0/), see [LunarG.com](https://vulkan.lunarg.com/doc/sdk/1.1.82.0/windows/getting_started.html)
58 | Vulkan itself is distributed under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0), see Vulkan.h
59 | The FBX Model loader library SDK from Autodesk is [Licensed](http://download.autodesk.com/us/fbx/2019/2019.0/FBX%20SDK%202019%20About%20Box%20Final.pdf) under there owne license. 60 | 61 | All other brand names, product names or trademarks belong to their respective holders. 62 | 63 |

Wanna contribute?

64 | 65 | Everyone is welcome to help in development!
66 | I am thankful for every improvment, addition or fix. 67 | 68 | ***Please review the [Code of Conduct](https://github.com/MrTroble/TGEngine/blob/master/CODE_OF_CONDUCT.md) before contributing in anyway to the repository!*** 69 | 70 | Additional information can be found [here](https://github.com/MrTroble/TGEngine/blob/master/CONTRIBUTING.md) 71 | -------------------------------------------------------------------------------- /TGEngine/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.8) 2 | 3 | project ("TGEngine") 4 | set(CMAKE_CXX_STANDARD 23) 5 | set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded") 6 | 7 | add_compile_definitions(ENGINE_NAME="TGEngine" ENGINE_VERSION=8388608 APPLICATION_NAME="TGEngineTest" DEBUG) 8 | 9 | 10 | #add_compile_options("/D_ITERATOR_DEBUG_LEVEL=0" "/MD" "/EHa" "-Wno-deprecated-volatile") 11 | #add_link_options("/ignore:4099") 12 | 13 | include(FetchContent) 14 | FETCHCONTENT_DECLARE( 15 | googletest 16 | URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip 17 | ) 18 | message("Downloading vulkansdk") 19 | FETCHCONTENT_DECLARE( 20 | vulkansdk 21 | URL https://seafile.media-dienste.de/f/85da9d3e98b347a490f6/?dl=1 22 | 23 | BUILD_COMMAND "" 24 | ) 25 | 26 | FETCHCONTENT_DECLARE( 27 | imgui 28 | URL https://github.com/ocornut/imgui/archive/refs/tags/v1.83.zip 29 | ) 30 | FETCHCONTENT_DECLARE( 31 | permute 32 | URL https://github.com/MrTroble/ShaderPermute/archive/refs/heads/master.zip 33 | ) 34 | 35 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 36 | FETCHCONTENT_MAKEAVAILABLE(googletest) 37 | FETCHCONTENT_MAKEAVAILABLE(vulkansdk) 38 | FETCHCONTENT_MAKEAVAILABLE(imgui) 39 | FETCHCONTENT_MAKEAVAILABLE(permute) 40 | include_directories("${vulkansdk_SOURCE_DIR}/Include" "${vulkansdk_SOURCE_DIR}/Third-Party/Include" "${imgui_SOURCE_DIR}") 41 | link_directories("${vulkansdk_SOURCE_DIR}/Lib") 42 | 43 | add_library (TGEngine STATIC 44 | # public 45 | "public/TGEngine.hpp" 46 | "public/graphics/vulkan/VulkanGraphicsModule.hpp" 47 | "public/Module.hpp" 48 | "public/Error.hpp" 49 | "public/graphics/GameGraphicsModule.hpp" 50 | "public/Util.hpp" 51 | # private 52 | "private/TGEngine.cpp" 53 | "private/Error.cpp" 54 | "private/graphics/Vulkan/VulkanGraphicsModule.cpp" 55 | "private/graphics/GameGraphicsModule.cpp" 56 | "private/Util.cpp" 57 | "private/graphics/WindowModule.cpp" 58 | "private/graphics/Vulkan/VulkanShaderModule.cpp" 59 | "public/graphics/vulkan/VulkanShaderModule.hpp" 60 | "public/graphics/vulkan/VulkanShaderPipe.hpp" 61 | "public/graphics/GameShaderModule.hpp" 62 | "private/graphics/GUIModule.cpp" 63 | "public/graphics/GUIModule.hpp" 64 | "public/graphics/vulkan/VulkanModuleDef.hpp" 65 | "${imgui_SOURCE_DIR}/imconfig.h" 66 | "${imgui_SOURCE_DIR}/imgui.cpp" 67 | "${imgui_SOURCE_DIR}/imgui.h" 68 | "${imgui_SOURCE_DIR}/imgui_demo.cpp" 69 | "${imgui_SOURCE_DIR}/imgui_draw.cpp" 70 | "${imgui_SOURCE_DIR}/imgui_internal.h" 71 | "${imgui_SOURCE_DIR}/imgui_tables.cpp" 72 | "${imgui_SOURCE_DIR}/imgui_widgets.cpp" 73 | "${imgui_SOURCE_DIR}/imstb_rectpack.h" 74 | "${imgui_SOURCE_DIR}/imstb_textedit.h" 75 | "${imgui_SOURCE_DIR}/imstb_truetype.h" 76 | "${imgui_SOURCE_DIR}/backends/imgui_impl_win32.cpp" 77 | "${imgui_SOURCE_DIR}/backends/imgui_impl_win32.h" 78 | "${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.cpp" 79 | "${imgui_SOURCE_DIR}/backends/imgui_impl_vulkan.h" 80 | "public/graphics/Material.hpp" "public/graphics/APILayer.hpp" "private/graphics/Material.cpp" "public/IO/IOModule.hpp" "private/IO/IOModule.cpp") 81 | target_link_libraries(TGEngine PRIVATE glslang SPIRV vulkan-1) 82 | target_include_directories(TGEngine PUBLIC ${permute_SOURCE_DIR}/ShaderPermute ${glslang_SOURCE_DIR}) 83 | 84 | add_executable(TGEngineTest "test/TGTest.cpp") 85 | target_include_directories(TGEngineTest PUBLIC "public") 86 | add_custom_command(TARGET TGEngineTest PRE_BUILD 87 | COMMAND ${CMAKE_COMMAND} -E copy_directory 88 | ${CMAKE_SOURCE_DIR}/test/assets/ $/assets) 89 | target_link_libraries(TGEngineTest PUBLIC TGEngine gtest_main) 90 | add_test(NAME TGEngineTest COMMAND TGEngineTest) 91 | 92 | add_executable(TGRenderTest "renderTest/TGRenderTest.cpp") 93 | target_include_directories(TGRenderTest PUBLIC "public") 94 | target_link_libraries(TGRenderTest PUBLIC TGEngine) -------------------------------------------------------------------------------- /TGEngine/CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "x64-Debug", 5 | "generator": "Ninja", 6 | "configurationType": "Debug", 7 | "inheritEnvironments": [ "msvc_x64_x64" ], 8 | "buildRoot": "${projectDir}\\out\\build\\${name}", 9 | "installRoot": "${projectDir}\\out\\install\\${name}", 10 | "buildCommandArgs": "", 11 | "ctestCommandArgs": "" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /TGEngine/private/Error.cpp: -------------------------------------------------------------------------------- 1 | #include "../public/Error.hpp" 2 | 3 | namespace tge::main { 4 | 5 | Error error = Error::NONE; 6 | 7 | } -------------------------------------------------------------------------------- /TGEngine/private/IO/IOModule.cpp: -------------------------------------------------------------------------------- 1 | #include "../../public/IO/IOModule.hpp" 2 | #include "../../public/TGEngine.hpp" 3 | #include 4 | #include 5 | #include 6 | 7 | namespace tge::io { 8 | 9 | std::vector ios; 10 | 11 | #ifdef WIN32 12 | LRESULT CALLBACK callback(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { 13 | switch (Msg) { 14 | case WM_MOUSEMOVE: { 15 | const auto xParam = GET_X_LPARAM(lParam); 16 | const auto yParam = GET_Y_LPARAM(lParam); 17 | for (const auto io : ios) 18 | io->mouseEvent({xParam, yParam, 0}); 19 | } break; 20 | case WM_KEYDOWN: { 21 | for (const auto io : ios) 22 | io->keyboardEvent({(uint32_t)wParam}); 23 | } break; 24 | default: 25 | break; 26 | } 27 | return DefWindowProc(hWnd, Msg, wParam, lParam); 28 | } 29 | #endif 30 | 31 | bool funcAdded = false; 32 | 33 | main::Error IOModule::init() { 34 | if (!funcAdded) { 35 | auto win = main::getGameGraphicsModule()->getWindowModule(); 36 | win->customFn.push_back((void *)callback); 37 | funcAdded = true; 38 | } 39 | ios.push_back(this); 40 | return main::Error::NONE; 41 | } 42 | 43 | }; // namespace tge::io 44 | -------------------------------------------------------------------------------- /TGEngine/private/TGEngine.cpp: -------------------------------------------------------------------------------- 1 | #include "../public/TGEngine.hpp" 2 | #include "../public/graphics/vulkan/VulkanGraphicsModule.hpp" 3 | #include "../public/graphics/GUIModule.hpp" 4 | #include "../public/Util.hpp" 5 | 6 | namespace tge::main { 7 | 8 | std::vector modules; 9 | std::vector lateModules; 10 | bool isRunning = false; 11 | bool isInitialized = false; 12 | 13 | graphics::APILayer *usedApiLayer = nullptr; 14 | graphics::GameGraphicsModule *gameModule = nullptr; 15 | graphics::WindowModule *winModule = nullptr; 16 | 17 | Error init() { 18 | if (isInitialized) 19 | return error = Error::ALREADY_INITIALIZED; 20 | winModule = new graphics::WindowModule(); 21 | modules.push_back(winModule); 22 | usedApiLayer = graphics::getNewVulkanModule(); 23 | modules.push_back(usedApiLayer); 24 | gameModule = new graphics::GameGraphicsModule(usedApiLayer, winModule); 25 | usedApiLayer->setGameGraphicsModule(gameModule); 26 | modules.push_back(gameModule); 27 | 28 | for (const auto m : lateModules) { 29 | modules.push_back(m); 30 | } 31 | lateModules.clear(); 32 | 33 | for (auto mod : modules) { 34 | error = mod->init(); 35 | if (error != Error::NONE) 36 | return error; 37 | } 38 | isInitialized = true; 39 | return error = Error::NONE; 40 | } 41 | 42 | Error start() { 43 | if (!isInitialized) 44 | return error = Error::NOT_INITIALIZED; 45 | if (isRunning) 46 | return error = Error::ALREADY_RUNNING; 47 | 48 | using namespace std::chrono; 49 | auto startpoint = steady_clock::now(); 50 | double deltatime = 0; 51 | isRunning = true; 52 | for (;;) { 53 | if (util::exitRequest || winModule->closeRequest) 54 | break; 55 | for (auto mod : modules) 56 | mod->tick(deltatime); 57 | 58 | auto endpoint = steady_clock::now(); 59 | deltatime = duration_cast>(endpoint - startpoint).count(); 60 | startpoint = endpoint; 61 | } 62 | for (auto bItr = modules.rbegin(); bItr < modules.rend(); bItr++) { 63 | (*bItr)->destroy(); 64 | delete *bItr; 65 | } 66 | modules.clear(); 67 | usedApiLayer = nullptr; 68 | gameModule = nullptr; 69 | winModule = nullptr; 70 | isRunning = false; 71 | isInitialized = false; 72 | util::exitRequest = false; 73 | return error = Error::NONE; 74 | } 75 | 76 | Error lastError() { return error; } 77 | 78 | graphics::APILayer *getAPILayer() { return usedApiLayer; } 79 | 80 | graphics::GameGraphicsModule *getGameGraphicsModule() { return gameModule; } 81 | 82 | } // namespace tge::main -------------------------------------------------------------------------------- /TGEngine/private/Util.cpp: -------------------------------------------------------------------------------- 1 | #include "../public/Util.hpp" 2 | #include 3 | 4 | namespace tge::util { 5 | 6 | bool exitRequest = false; 7 | 8 | std::vector wholeFile(const fs::path &path) { 9 | std::ifstream inputstream(path, 10 | std::ios::ate | std::ios::in | std::ios::binary); 11 | if (!inputstream) { 12 | #ifdef DEBUG 13 | printf("Error couldn't find file: %s!", path.generic_string().c_str()); 14 | #endif // DEBUG 15 | 16 | throw std::runtime_error(std::string("File not found: ") + 17 | path.generic_string()); 18 | } 19 | const size_t size = (size_t)inputstream.tellg(); 20 | inputstream.seekg(0, SEEK_SET); 21 | std::vector fileData(size + 1); 22 | inputstream.read((char *)fileData.data(), size); 23 | fileData[size] = 0; 24 | return fileData; 25 | } 26 | 27 | void requestExit() { exitRequest = true; } 28 | 29 | } // namespace tge::util -------------------------------------------------------------------------------- /TGEngine/private/graphics/GUIModule.cpp: -------------------------------------------------------------------------------- 1 | #include "../../public/graphics/GUIModule.hpp" 2 | #include "../../public/graphics/WindowModule.hpp" 3 | 4 | #include "../../public/graphics/vulkan/VulkanModuleDef.hpp" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "../../public/TGEngine.hpp" 11 | 12 | namespace tge::gui { 13 | 14 | using namespace vk; 15 | 16 | inline void render(gui::GUIModule* gmod) { 17 | const CommandBuffer buffer = (VkCommandBuffer)gmod->buffer; 18 | const RenderPass pass = (VkRenderPass)gmod->renderpass; 19 | auto vgm = (graphics::VulkanGraphicsModule *)main::getAPILayer(); 20 | const Framebuffer frame = ((Framebuffer *)gmod->framebuffer)[vgm->nextImage]; 21 | 22 | ImGui_ImplVulkan_NewFrame(); 23 | ImGui_ImplWin32_NewFrame(); 24 | ImGui::NewFrame(); 25 | 26 | gmod->renderGUI(); 27 | 28 | ImGui::Render(); 29 | ImDrawData *draw_data = ImGui::GetDrawData(); 30 | 31 | const CommandBufferBeginInfo beginInfo; 32 | buffer.begin(beginInfo); 33 | 34 | constexpr std::array clearColor = {1.0f, 1.0f, 1.0f, 1.0f}; 35 | 36 | const std::array clearValue = {ClearValue(clearColor), 37 | ClearValue(ClearDepthStencilValue(0.0f, 0))}; 38 | 39 | const RenderPassBeginInfo renderPassBeginInfo( 40 | pass, frame, 41 | {{0, 0}, {(uint32_t)vgm->viewport.width, (uint32_t)vgm->viewport.height}}, 42 | clearValue); 43 | buffer.beginRenderPass(renderPassBeginInfo, {}); 44 | ImGui_ImplVulkan_RenderDrawData(draw_data, buffer); 45 | buffer.endRenderPass(); 46 | buffer.end(); 47 | } 48 | 49 | main::Error GUIModule::init() { 50 | 51 | auto winModule = main::getGameGraphicsModule()->getWindowModule(); 52 | auto api = main::getAPILayer(); 53 | IMGUI_CHECKVERSION(); 54 | ImGui::CreateContext(); 55 | ImGuiIO &io = ImGui::GetIO(); 56 | (void)io; 57 | ImGui::StyleColorsDark(); 58 | winModule->customFn.push_back((void *)ImGui_ImplWin32_WndProcHandler); 59 | const bool winInit = ImGui_ImplWin32_Init(winModule->hWnd); 60 | if (!winInit) 61 | return main::Error::COULD_NOT_CREATE_WINDOW; 62 | 63 | const auto vmod = (graphics::VulkanGraphicsModule *)api; 64 | 65 | const std::array attachments = { 66 | AttachmentDescription( 67 | {}, vmod->format.format, SampleCountFlagBits::e1, 68 | AttachmentLoadOp::eLoad, AttachmentStoreOp::eStore, 69 | AttachmentLoadOp::eDontCare, AttachmentStoreOp::eDontCare, 70 | ImageLayout::eUndefined, ImageLayout::ePresentSrcKHR)}; 71 | 72 | constexpr std::array colorAttachments = { 73 | AttachmentReference(0, ImageLayout::eColorAttachmentOptimal)}; 74 | 75 | const std::array subpassDescriptions = { 76 | SubpassDescription({}, PipelineBindPoint::eGraphics, {}, colorAttachments)}; 77 | 78 | const std::array subpassDependencies = { 79 | SubpassDependency(VK_SUBPASS_EXTERNAL, 0, 80 | PipelineStageFlagBits::eColorAttachmentOutput | 81 | PipelineStageFlagBits::eEarlyFragmentTests, 82 | PipelineStageFlagBits::eColorAttachmentOutput | 83 | PipelineStageFlagBits::eEarlyFragmentTests, 84 | (AccessFlagBits)0, 85 | AccessFlagBits::eColorAttachmentWrite | 86 | AccessFlagBits::eColorAttachmentRead | 87 | AccessFlagBits::eDepthStencilAttachmentRead | 88 | AccessFlagBits::eDepthStencilAttachmentWrite)}; 89 | 90 | const RenderPassCreateInfo renderPassCreateInfo( 91 | {}, attachments, subpassDescriptions, subpassDependencies); 92 | this->renderpass = vmod->device.createRenderPass(renderPassCreateInfo); 93 | 94 | framebuffer = new Framebuffer[vmod->swapchainImageviews.size()]; 95 | 96 | for (size_t i = 0; i < vmod->swapchainImageviews.size(); i++) { 97 | const auto imview = vmod->swapchainImageviews[i]; 98 | const FramebufferCreateInfo framebufferCreateInfo( 99 | {}, (VkRenderPass)renderpass, imview, vmod->viewport.width, 100 | vmod->viewport.height, 1); 101 | ((Framebuffer *)framebuffer)[i] = 102 | vmod->device.createFramebuffer(framebufferCreateInfo); 103 | } 104 | 105 | VkDescriptorPoolSize pool_sizes[] = { 106 | {VK_DESCRIPTOR_TYPE_SAMPLER, 1000}, 107 | {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000}, 108 | {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000}, 109 | {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000}, 110 | {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000}, 111 | {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000}, 112 | {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000}, 113 | {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000}, 114 | {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000}, 115 | {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000}, 116 | {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000}}; 117 | VkDescriptorPoolCreateInfo pool_info = {}; 118 | pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; 119 | pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; 120 | pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes); 121 | pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes); 122 | pool_info.pPoolSizes = pool_sizes; 123 | const auto result = vkCreateDescriptorPool(vmod->device, &pool_info, nullptr, 124 | ((VkDescriptorPool *)&pool)); 125 | if (result != VK_SUCCESS) 126 | return main::Error::VULKAN_ERROR; 127 | 128 | ImGui_ImplVulkan_InitInfo instinfo = {vmod->instance, 129 | vmod->physicalDevice, 130 | vmod->device, 131 | vmod->queueFamilyIndex, 132 | vmod->queue, 133 | VK_NULL_HANDLE, 134 | (VkDescriptorPool)pool, 135 | 0, 136 | 3, 137 | 3, 138 | VK_SAMPLE_COUNT_1_BIT, 139 | nullptr, 140 | [](VkResult rslt) { 141 | if (rslt != VK_SUCCESS) 142 | printf("ERROR IN VK"); 143 | }}; 144 | ImGui_ImplVulkan_Init(&instinfo, (VkRenderPass)this->renderpass); 145 | 146 | const auto sCmd = vmod->cmdbuffer.back(); 147 | const auto beginInfo = 148 | CommandBufferBeginInfo(CommandBufferUsageFlagBits::eOneTimeSubmit); 149 | sCmd.begin(beginInfo); 150 | ImGui_ImplVulkan_CreateFontsTexture(sCmd); 151 | sCmd.end(); 152 | 153 | const auto submitInfo = SubmitInfo({}, {}, sCmd, {}); 154 | vmod->queue.submit(submitInfo); 155 | 156 | vmod->device.waitIdle(); 157 | ImGui_ImplVulkan_DestroyFontUploadObjects(); 158 | 159 | const auto allocInfo = 160 | CommandBufferAllocateInfo(vmod->pool, CommandBufferLevel::ePrimary, 1); 161 | buffer = vmod->device.allocateCommandBuffers(allocInfo).back(); 162 | 163 | render(this); 164 | 165 | vmod->primary.push_back((VkCommandBuffer)buffer); 166 | 167 | return main::Error::NONE; 168 | } 169 | 170 | void GUIModule::tick(double deltatime) { 171 | render(this); 172 | } 173 | 174 | void GUIModule::destroy() { 175 | const auto vmod = (graphics::VulkanGraphicsModule *)main::getAPILayer(); 176 | vmod->device.waitIdle(); 177 | ImGui_ImplVulkan_Shutdown(); 178 | vmod->device.destroyDescriptorPool(((VkDescriptorPool)pool)); 179 | vmod->device.destroyRenderPass((VkRenderPass)this->renderpass); 180 | for (size_t i = 0; i < vmod->swapchainImageviews.size(); i++) { 181 | vmod->device.destroyFramebuffer(((Framebuffer *)framebuffer)[i]); 182 | } 183 | delete[](Framebuffer *) framebuffer; 184 | ImGui_ImplWin32_Shutdown(); 185 | } 186 | 187 | } // namespace tge::gui 188 | -------------------------------------------------------------------------------- /TGEngine/private/graphics/GameGraphicsModule.cpp: -------------------------------------------------------------------------------- 1 | #include "../../public/graphics/GameGraphicsModule.hpp" 2 | 3 | #define TINYGLTF_IMPLEMENTATION 4 | #define STB_IMAGE_IMPLEMENTATION 5 | #define STB_IMAGE_WRITE_IMPLEMENTATION 6 | #include "../../public/Util.hpp" 7 | #include "../../public/graphics/GameShaderModule.hpp" 8 | #include "../../public/graphics/vulkan/VulkanShaderPipe.hpp" 9 | #include "../../public/headerlibs/tiny_gltf.h" 10 | #include 11 | #include 12 | #include 13 | 14 | namespace tge::graphics { 15 | 16 | using namespace tinygltf; 17 | 18 | inline AddressMode gltfToAPI(int in, AddressMode def) { 19 | switch (in) { 20 | case TINYGLTF_TEXTURE_WRAP_REPEAT: 21 | return AddressMode::REPEAT; 22 | case TINYGLTF_TEXTURE_WRAP_CLAMP_TO_EDGE: 23 | return AddressMode::CLAMP_TO_EDGE; 24 | case TINYGLTF_TEXTURE_WRAP_MIRRORED_REPEAT: 25 | return AddressMode::MIRROR_REPEAT; 26 | } 27 | return def; 28 | } 29 | 30 | inline FilterSetting gltfToAPI(int in, FilterSetting def) { 31 | switch (in) { 32 | case TINYGLTF_TEXTURE_FILTER_LINEAR: 33 | return FilterSetting::LINEAR; 34 | case TINYGLTF_TEXTURE_FILTER_NEAREST: 35 | return FilterSetting::NEAREST; 36 | default: 37 | return def; 38 | } 39 | } 40 | 41 | inline vk::Format getFormatFromStride(uint32_t stride) { 42 | switch (stride) { 43 | case 4: 44 | return vk::Format::eR32Sfloat; 45 | case 8: 46 | return vk::Format::eR32G32Sfloat; 47 | case 12: 48 | return vk::Format::eR32G32B32Sfloat; 49 | case 16: 50 | return vk::Format::eR32G32B32A32Sfloat; 51 | default: 52 | throw std::runtime_error("Couldn't find format"); 53 | } 54 | } 55 | 56 | inline size_t loadSampler(const Model &model, APILayer *apiLayer) { 57 | size_t samplerIndex = -1; 58 | for (const auto &smplr : model.samplers) { 59 | const SamplerInfo samplerInfo = { 60 | gltfToAPI(smplr.minFilter, FilterSetting::LINEAR), 61 | gltfToAPI(smplr.minFilter, FilterSetting::LINEAR), 62 | gltfToAPI(smplr.wrapS, AddressMode::REPEAT), 63 | gltfToAPI(smplr.wrapT, AddressMode::REPEAT)}; 64 | samplerIndex = apiLayer->pushSampler(samplerInfo); 65 | } 66 | samplerIndex -= model.samplers.size() - 1; 67 | 68 | if (!model.images.empty()) { 69 | if (model.samplers.empty()) { // default sampler 70 | const SamplerInfo samplerInfo = { 71 | FilterSetting::LINEAR, FilterSetting::LINEAR, AddressMode::REPEAT, 72 | AddressMode::REPEAT}; 73 | samplerIndex = apiLayer->pushSampler(samplerInfo); 74 | } 75 | } 76 | return samplerIndex; 77 | } 78 | 79 | inline size_t loadTexturesFM(const Model &model, APILayer *apiLayer) { 80 | std::vector textureInfos; 81 | textureInfos.reserve(model.images.size()); 82 | for (const auto &img : model.images) { 83 | if (!img.image.empty()) [[likely]] { 84 | const TextureInfo info{(uint8_t *)img.image.data(), 85 | (uint32_t)img.image.size(), (uint32_t)img.width, 86 | (uint32_t)img.height, (uint32_t)img.component}; 87 | textureInfos.push_back(info); 88 | } else { 89 | throw std::runtime_error("Not implemented!"); 90 | } 91 | } 92 | if (!textureInfos.empty()) 93 | return apiLayer->pushTexture(textureInfos.size(), textureInfos.data()); 94 | return -1; 95 | } 96 | 97 | inline size_t loadMaterials(const Model &model, APILayer *apiLayer, 98 | const size_t sampler, const size_t texture, 99 | std::vector &created) { 100 | std::vector materials; 101 | materials.reserve(model.materials.size()); 102 | std::vector roughnessMetallicFactors; 103 | for (const auto &mat : model.materials) { 104 | const auto &pbr = mat.pbrMetallicRoughness; 105 | const auto &diffuseTexture = pbr.baseColorTexture; 106 | 107 | Material nmMat; 108 | if (diffuseTexture.index != -1) [[likely]] { 109 | nmMat.type = MaterialType::TextureOnly; 110 | const auto nextSampler = model.textures[diffuseTexture.index].sampler; 111 | nmMat.data.textureMaterial.samplerIndex = 112 | nextSampler < 0 ? sampler : (nextSampler + sampler); 113 | nmMat.data.textureMaterial.textureIndex = diffuseTexture.index + texture; 114 | } else { 115 | nmMat.type = MaterialType::None; 116 | } 117 | roughnessMetallicFactors.push_back(glm::vec2(pbr.roughnessFactor, pbr.metallicFactor)); 118 | 119 | nmMat.doubleSided = mat.doubleSided; 120 | materials.push_back(nmMat); 121 | } 122 | 123 | namespace s = shader; 124 | for (const auto &mesh : model.meshes) { 125 | const auto &prim = mesh.primitives[0]; 126 | s::ShaderCreateInfo createInfo[2]; 127 | apiLayer->getShaderAPI()->createShaderPipe(createInfo, 2); 128 | } 129 | 130 | return apiLayer->pushMaterials(materials.size(), materials.data()); 131 | } 132 | 133 | inline size_t loadDataBuffers(const Model &model, APILayer *apiLayer) { 134 | std::vector ptr; 135 | ptr.reserve(model.buffers.size()); 136 | std::vector sizes; 137 | sizes.reserve(ptr.capacity()); 138 | for (const auto &buffer : model.buffers) { 139 | const auto ptrto = (uint8_t *)buffer.data.data(); 140 | ptr.push_back(ptrto); 141 | sizes.push_back(buffer.data.size()); 142 | } 143 | 144 | return apiLayer->pushData(ptr.size(), ptr.data(), 145 | sizes.data(), DataType::VertexIndexData); 146 | } 147 | 148 | inline void pushRender(const Model &model, APILayer *apiLayer, 149 | const size_t dataId, const size_t materialId, 150 | const size_t nodeID, 151 | const std::vector bindings) { 152 | std::vector renderInfos; 153 | renderInfos.reserve(1000); 154 | for (size_t i = 0; i < model.meshes.size(); i++) { 155 | const auto &mesh = model.meshes[i]; 156 | const auto bItr = model.nodes.begin(); 157 | const auto eItr = model.nodes.end(); 158 | const auto oItr = std::find_if( 159 | bItr, eItr, [idx = i](const Node &node) { return node.mesh == idx; }); 160 | const auto nID = 161 | oItr != eItr ? std::distance(bItr, oItr) + nodeID : UINT64_MAX; 162 | const auto bID = bindings[nID]; 163 | for (const auto &prim : mesh.primitives) { 164 | std::vector> strides; 165 | strides.reserve(prim.attributes.size()); 166 | 167 | for (const auto &attr : prim.attributes) { 168 | const auto &vertAccesor = model.accessors[attr.second]; 169 | const auto &vertView = model.bufferViews[vertAccesor.bufferView]; 170 | const auto bufferID = vertView.buffer + dataId; 171 | const auto vertOffset = vertView.byteOffset + vertAccesor.byteOffset; 172 | strides.push_back( 173 | std::make_tuple(vertAccesor.type, bufferID, vertOffset)); 174 | } 175 | 176 | std::sort(strides.rbegin(), strides.rend(), 177 | [](auto x, auto y) { return std::get<0>(x) < std::get<0>(y); }); 178 | std::vector bufferIndicies; 179 | bufferIndicies.reserve(strides.size()); 180 | std::vector bufferOffsets; 181 | bufferOffsets.reserve(bufferIndicies.capacity()); 182 | for (auto &stride : strides) { 183 | bufferIndicies.push_back(std::get<1>(stride)); 184 | bufferOffsets.push_back(std::get<2>(stride)); 185 | } 186 | 187 | if (prim.indices >= 0) [[likely]] { 188 | const auto &indexAccesor = model.accessors[prim.indices]; 189 | const auto &indexView = model.bufferViews[indexAccesor.bufferView]; 190 | const auto indexOffset = indexView.byteOffset + indexAccesor.byteOffset; 191 | const IndexSize indextype = 192 | indexView.byteStride == 4 ? IndexSize::UINT32 : IndexSize::UINT16; 193 | const RenderInfo renderInfo = { 194 | bufferIndicies, 195 | indexView.buffer + dataId, 196 | prim.material == -1 ? materialId : prim.material + materialId, 197 | indexAccesor.count, 198 | 1, 199 | indexOffset, 200 | indextype, 201 | bufferOffsets, 202 | bID}; 203 | renderInfos.push_back(renderInfo); 204 | } else { 205 | const auto accessorID = prim.attributes.begin()->second; 206 | const auto &vertAccesor = model.accessors[accessorID]; 207 | const RenderInfo renderInfo = { 208 | bufferIndicies, 209 | 0, 210 | prim.material == -1 ? materialId : prim.material + materialId, 211 | 0, 212 | 1, 213 | vertAccesor.count, 214 | IndexSize::NONE, 215 | bufferOffsets, 216 | bID}; 217 | renderInfos.push_back(renderInfo); 218 | } 219 | } 220 | } 221 | 222 | apiLayer->pushRender(renderInfos.size(), renderInfos.data()); 223 | } 224 | 225 | inline size_t loadNodes(const Model &model, APILayer *apiLayer, 226 | const size_t nextNodeID, GameGraphicsModule *ggm, 227 | const std::vector &created) { 228 | std::vector nodeInfos = {}; 229 | const auto amount = model.nodes.size(); 230 | nodeInfos.resize(amount + 1); 231 | if (amount != 0) [[likely]] { 232 | for (size_t i = 0; i < amount; i++) { 233 | const auto &node = model.nodes[i]; 234 | const auto infoID = i + 1; 235 | auto &info = nodeInfos[infoID]; 236 | if (!node.translation.empty()) { 237 | info.transforms.translation.x = (float)node.translation[0]; 238 | info.transforms.translation.y = (float)node.translation[1]; 239 | info.transforms.translation.z = (float)node.translation[2]; 240 | } 241 | if (!node.scale.empty()) { 242 | info.transforms.scale.x = (float)node.scale[0]; 243 | info.transforms.scale.y = (float)node.scale[1]; 244 | info.transforms.scale.z = (float)node.scale[2]; 245 | } 246 | if (!node.rotation.empty()) { 247 | info.transforms.rotation = 248 | glm::quat((float)node.rotation[3], (float)node.rotation[0], 249 | (float)node.rotation[1], (float)node.rotation[2]); 250 | } 251 | for (const auto id : node.children) { 252 | nodeInfos[id + 1].parent = nextNodeID + infoID; 253 | } 254 | if (node.mesh >= 0 && created.size() > node.mesh) [[likely]] { 255 | info.bindingID = 256 | apiLayer->getShaderAPI()->createBindings(created[node.mesh]); 257 | } else { 258 | info.bindingID = 259 | apiLayer->getShaderAPI()->createBindings(ggm->defaultPipe); 260 | } 261 | } 262 | for (auto &nInfo : nodeInfos) { 263 | if (nInfo.parent == UINT64_MAX) { 264 | nInfo.parent = nextNodeID; 265 | } 266 | } 267 | } else { 268 | const auto startID = 269 | apiLayer->getShaderAPI()->createBindings(ggm->defaultPipe); 270 | nodeInfos[0].bindingID = startID; 271 | } 272 | return ggm->addNode(nodeInfos.data(), nodeInfos.size()); 273 | } 274 | 275 | GameGraphicsModule::GameGraphicsModule(APILayer *apiLayer, 276 | WindowModule *winModule) { 277 | const auto prop = winModule->getWindowProperties(); 278 | this->apiLayer = apiLayer; 279 | this->windowModule = winModule; 280 | // TODO Cleanup 281 | this->projectionMatrix = 282 | glm::perspective(glm::radians(45.0f), 283 | (float)prop.width / (float)prop.height, 0.1f, 100.0f); 284 | this->projectionMatrix[1][1] *= -1; 285 | this->viewMatrix = glm::lookAt(glm::vec3(0, 0.5f, 1), glm::vec3(0, 0, 0), 286 | glm::vec3(0, 1, 0)); 287 | } 288 | 289 | size_t GameGraphicsModule::loadModel(const std::vector &data, 290 | const bool binary, 291 | const std::string &baseDir, 292 | void *shaderPipe) { 293 | TinyGLTF loader; 294 | std::string error; 295 | std::string warning; 296 | Model model; 297 | 298 | const bool rst = 299 | binary ? loader.LoadBinaryFromMemory(&model, &error, &warning, 300 | (const uint8_t *)data.data(), 301 | data.size(), baseDir) 302 | : loader.LoadASCIIFromString(&model, &error, &warning, data.data(), 303 | data.size(), baseDir); 304 | if (!rst) { 305 | printf("[GLTF][ERR]: Loading failed\n[GLTF][ERR]: %s\n[GLTF][WARN]: %s\n", 306 | error.c_str(), warning.c_str()); 307 | return UINT64_MAX; 308 | } 309 | 310 | if (!warning.empty()) { 311 | printf("[GLTF][WARN]: %s\n", warning.c_str()); 312 | } 313 | 314 | const auto samplerId = loadSampler(model, apiLayer); 315 | 316 | const auto textureId = loadTexturesFM(model, apiLayer); 317 | 318 | const auto dataId = loadDataBuffers(model, apiLayer); 319 | 320 | std::vector createdShader; 321 | const auto materials = 322 | model.materials.empty() 323 | ? defaultMaterial 324 | : loadMaterials(model, apiLayer, samplerId, textureId, createdShader); 325 | 326 | const auto nId = loadNodes(model, apiLayer, node.size(), this, createdShader); 327 | 328 | pushRender(model, apiLayer, dataId, materials, nId + 1, this->bindingID); 329 | 330 | return nId; 331 | } 332 | 333 | main::Error GameGraphicsModule::init() { 334 | const auto size = this->node.size(); 335 | glm::mat4 projView = this->projectionMatrix * this->viewMatrix; 336 | modelMatrices.reserve(UINT16_MAX); 337 | for (size_t i = 0; i < size; i++) { 338 | const auto &transform = this->node[i]; 339 | const auto parantID = this->parents[i]; 340 | const auto mMatrix = glm::translate(transform.translation) * 341 | glm::scale(transform.scale) * 342 | glm::toMat4(transform.rotation); 343 | if (parantID < size) { 344 | modelMatrices[i] = modelMatrices[parantID] * mMatrix; 345 | } else { 346 | modelMatrices[i] = mMatrix; 347 | } 348 | } 349 | 350 | std::array mvpsPtr = {(const uint8_t *)modelMatrices.data(), 351 | (const uint8_t *)&projView}; 352 | std::array arrSize = {UINT16_MAX * sizeof(glm::mat4), sizeof(glm::mat4)}; 353 | dataID = apiLayer->pushData(mvpsPtr.size(), mvpsPtr.data(), arrSize.data(), 354 | DataType::Uniform); 355 | const Material defMat(defaultPipe = apiLayer->loadShader(MaterialType::None)); 356 | defaultMaterial = apiLayer->pushMaterials(1, &defMat); 357 | return main::Error::NONE; 358 | } 359 | 360 | void GameGraphicsModule::tick(double time) { 361 | const auto size = this->node.size(); 362 | const auto projView = this->projectionMatrix * this->viewMatrix; 363 | apiLayer->changeData(dataID + 1, (const uint8_t *)&projView, 364 | sizeof(glm::mat4)); 365 | for (size_t i = 0; i < size; i++) { 366 | const auto parantID = this->parents[i]; 367 | if (this->status[i] == 1 || (parantID < size && this->status[parantID])) { 368 | const auto &transform = this->node[i]; 369 | const auto mMatrix = glm::translate(transform.translation) * 370 | glm::scale(transform.scale) * 371 | glm::toMat4(transform.rotation); 372 | if (parantID < size) { 373 | modelMatrices[i] = modelMatrices[parantID] * mMatrix; 374 | } else { 375 | modelMatrices[i] = mMatrix; 376 | } 377 | apiLayer->changeData(dataID, (const uint8_t *)&modelMatrices[i], 378 | sizeof(glm::mat4), i * sizeof(glm::mat4)); 379 | } 380 | } 381 | std::fill(begin(this->status), end(this->status), 0); 382 | } 383 | 384 | void GameGraphicsModule::destroy() {} 385 | 386 | uint32_t 387 | GameGraphicsModule::loadTextures(const std::vector> &data) { 388 | std::vector textureInfos; 389 | 390 | util::OnExit onExit([tinfos = &textureInfos] { 391 | for (const auto &tex : *tinfos) 392 | if (tex.data != nullptr) 393 | free(tex.data); 394 | }); 395 | 396 | for (const auto &dataIn : data) { 397 | TextureInfo info; 398 | info.data = stbi_load_from_memory((stbi_uc *)dataIn.data(), dataIn.size(), 399 | (int *)&info.width, (int *)&info.height, 400 | (int *)&info.channel, 0); 401 | info.size = info.width * info.height * info.channel; 402 | textureInfos.push_back(info); 403 | if (info.channel == 3) 404 | throw std::runtime_error("Texture with 3 channels not supported!"); 405 | } 406 | return apiLayer->pushTexture(textureInfos.size(), textureInfos.data()); 407 | } 408 | 409 | uint32_t 410 | GameGraphicsModule::loadTextures(const std::vector &names) { 411 | std::vector> data; 412 | data.reserve(names.size()); 413 | for (const auto &name : names) { 414 | data.push_back(util::wholeFile(name)); 415 | } 416 | return loadTextures(data); 417 | } 418 | 419 | size_t GameGraphicsModule::addNode(const NodeInfo *nodeInfos, 420 | const size_t count) { 421 | const auto nodeID = node.size(); 422 | node.reserve(nodeID + count); 423 | std::vector bindings; 424 | bindings.reserve(count); 425 | for (size_t i = 0; i < count; i++) { 426 | const auto nodeI = nodeInfos[i]; 427 | const auto nodeIndex = (nodeID + i); 428 | node.push_back(nodeI.transforms); 429 | 430 | const auto mMatrix = glm::translate(nodeI.transforms.translation) * 431 | glm::scale(nodeI.transforms.scale) * 432 | glm::toMat4(nodeI.transforms.rotation); 433 | if (nodeI.parent < nodeIndex) { 434 | modelMatrices.push_back(modelMatrices[nodeI.parent] * mMatrix); 435 | parents.push_back(nodeI.parent); 436 | } else { 437 | modelMatrices.push_back(mMatrix); 438 | parents.push_back(UINT64_MAX); 439 | } 440 | status.push_back(0); 441 | if (nodeI.bindingID != UINT64_MAX) [[likely]] { 442 | const auto mvp = modelMatrices[nodeID]; 443 | const auto off = sizeof(mvp) * (nodeID + i); 444 | apiLayer->changeData(dataID, (const uint8_t *)&mvp, sizeof(mvp), off); 445 | bindings.push_back({2, 446 | nodeI.bindingID, 447 | shader::BindingType::UniformBuffer, 448 | {dataID, sizeof(mvp), off}}); 449 | bindings.push_back({3, 450 | nodeI.bindingID, 451 | shader::BindingType::UniformBuffer, 452 | {dataID + 1, sizeof(mvp), 0}}); 453 | } 454 | bindingID.push_back(nodeI.bindingID); 455 | } 456 | apiLayer->getShaderAPI()->bindData(bindings.data(), bindings.size()); 457 | return nodeID; 458 | } 459 | 460 | void GameGraphicsModule::updateTransform(const size_t nodeID, 461 | const NodeTransform &transform) { 462 | this->node[nodeID] = transform; 463 | this->status[nodeID] = 1; 464 | } 465 | 466 | } // namespace tge::graphics -------------------------------------------------------------------------------- /TGEngine/private/graphics/GameShaderModule.cpp: -------------------------------------------------------------------------------- 1 | #include "../../public/graphics/GameShaderModule.hpp" 2 | 3 | namespace tge::shader { 4 | 5 | 6 | 7 | } // namespace tge::shader -------------------------------------------------------------------------------- /TGEngine/private/graphics/Material.cpp: -------------------------------------------------------------------------------- 1 | #include "../../public/graphics/Material.hpp" 2 | #include "../../public/graphics/APILayer.hpp" 3 | 4 | namespace tge::graphics { 5 | tge::graphics::Material::Material(const TextureMaterial texture, 6 | APILayer *layer) 7 | : type(MaterialType::TextureOnly), data({texture}) { 8 | costumShaderData = layer->loadShader(type); 9 | } 10 | } // namespace tge::graphics -------------------------------------------------------------------------------- /TGEngine/private/graphics/Vulkan/VulkanGraphicsModule.cpp: -------------------------------------------------------------------------------- 1 | #include "../../../public/graphics/vulkan/VulkanGraphicsModule.hpp" 2 | #include "../../../public/Error.hpp" 3 | #include "../../../public/Util.hpp" 4 | #include "../../../public/graphics/WindowModule.hpp" 5 | #include 6 | #include 7 | #include 8 | #define VULKAN_HPP_HAS_SPACESHIP_OPERATOR 9 | #include "../../../public/graphics/vulkan/VulkanModuleDef.hpp" 10 | #include 11 | 12 | namespace tge::graphics { 13 | 14 | using namespace tge::shader; 15 | 16 | constexpr std::array layerToEnable = {"VK_LAYER_KHRONOS_validation", 17 | "VK_LAYER_VALVE_steam_overlay", 18 | "VK_LAYER_NV_optimus"}; 19 | 20 | constexpr std::array extensionToEnable = {VK_KHR_SURFACE_EXTENSION_NAME 21 | #ifdef WIN32 22 | , 23 | VK_KHR_WIN32_SURFACE_EXTENSION_NAME 24 | #endif // WIN32 25 | #ifdef DEBUG 26 | , 27 | VK_EXT_DEBUG_UTILS_EXTENSION_NAME 28 | #endif 29 | 30 | }; 31 | 32 | using namespace vk; 33 | 34 | Result verror = Result::eSuccess; 35 | 36 | #define VERROR(rslt) \ 37 | if (rslt != Result::eSuccess) { \ 38 | verror = rslt; \ 39 | main::error = main::Error::VULKAN_ERROR; \ 40 | std::string s = to_string(verror); \ 41 | const auto file = __FILE__; \ 42 | const auto line = __LINE__; \ 43 | printf("Vulkan error %s in %s L%d!\n", s.c_str(), file, line); \ 44 | } // namespace tge::graphics 45 | 46 | struct InternalImageInfo { 47 | Format format; 48 | Extent2D ex; 49 | ImageUsageFlags usage = ImageUsageFlagBits::eColorAttachment; 50 | SampleCountFlagBits sampleCount = SampleCountFlagBits::e1; 51 | }; 52 | 53 | inline void waitForImageTransition( 54 | const CommandBuffer &curBuffer, const ImageLayout oldLayout, 55 | const ImageLayout newLayout, const Image image, 56 | const ImageSubresourceRange &subresource, 57 | const PipelineStageFlags srcFlags = PipelineStageFlagBits::eTopOfPipe, 58 | const AccessFlags srcAccess = AccessFlagBits::eNoneKHR, 59 | const PipelineStageFlags dstFlags = PipelineStageFlagBits::eAllGraphics, 60 | const AccessFlags dstAccess = AccessFlagBits::eNoneKHR) { 61 | const ImageMemoryBarrier imageMemoryBarrier( 62 | srcAccess, dstAccess, oldLayout, newLayout, VK_QUEUE_FAMILY_IGNORED, 63 | VK_QUEUE_FAMILY_IGNORED, image, subresource); 64 | curBuffer.pipelineBarrier(srcFlags, dstFlags, DependencyFlagBits::eByRegion, 65 | {}, {}, imageMemoryBarrier); 66 | } 67 | 68 | constexpr PipelineInputAssemblyStateCreateInfo 69 | inputAssemblyCreateInfo({}, PrimitiveTopology::eTriangleList, 70 | false); // For now constexpr 71 | 72 | #define EXPECT(assertion) \ 73 | if (!this->isInitialiazed || !(assertion)) { \ 74 | throw std::runtime_error(std::string("Debug assertion failed! ") + \ 75 | __FILE__ + " L" + std::to_string(__LINE__)); \ 76 | } 77 | 78 | void *VulkanGraphicsModule::loadShader(const MaterialType type) { 79 | EXPECT(((size_t)type) <= (size_t)MAX_TYPE); 80 | const auto idx = (size_t)type; 81 | auto &vert = shaderNames[idx]; 82 | const auto ptr = shaderAPI->loadShaderPipeAndCompile(vert); 83 | return ptr; 84 | } 85 | 86 | inline void submitAndWait(const Device &device, const Queue &queue, 87 | const CommandBuffer &cmdBuf) { 88 | const FenceCreateInfo fenceCreateInfo; 89 | const auto fence = device.createFence(fenceCreateInfo); 90 | 91 | const SubmitInfo submitInfo({}, {}, cmdBuf, {}); 92 | queue.submit(submitInfo, fence); 93 | 94 | const Result result = device.waitForFences(fence, true, UINT64_MAX); 95 | VERROR(result); 96 | 97 | device.destroyFence(fence); 98 | } 99 | 100 | size_t VulkanGraphicsModule::pushMaterials(const size_t materialcount, 101 | const Material *materials) { 102 | EXPECT(materialcount != 0 && materials != nullptr); 103 | 104 | const Rect2D scissor({0, 0}, 105 | {(uint32_t)viewport.width, (uint32_t)viewport.height}); 106 | const PipelineViewportStateCreateInfo pipelineViewportCreateInfo({}, viewport, 107 | scissor); 108 | 109 | const PipelineMultisampleStateCreateInfo multisampleCreateInfo( 110 | {}, SampleCountFlagBits::e1, false, 1); 111 | 112 | const auto pDefaultState = PipelineColorBlendAttachmentState( 113 | true, BlendFactor::eSrcAlpha, BlendFactor::eOneMinusSrcAlpha, 114 | BlendOp::eAdd, BlendFactor::eOne, BlendFactor::eZero, BlendOp::eAdd, 115 | (ColorComponentFlags)FlagTraits::allFlags); 116 | 117 | const std::array blendAttachment = {pDefaultState, pDefaultState, 118 | pDefaultState, pDefaultState}; 119 | 120 | const PipelineColorBlendStateCreateInfo colorBlendState( 121 | {}, false, LogicOp::eClear, blendAttachment); 122 | 123 | const PipelineDepthStencilStateCreateInfo pipeDepthState( 124 | {}, true, true, CompareOp::eLess, false, false, {}, {}, 0, 1); 125 | 126 | std::vector pipelineCreateInfos; 127 | pipelineCreateInfos.reserve(materialcount); 128 | 129 | for (size_t i = 0; i < materialcount; i++) { 130 | const auto &material = materials[i]; 131 | 132 | const auto shaderPipe = (VulkanShaderPipe *)material.costumShaderData; 133 | 134 | shaderPipe->pipelineShaderStage.clear(); 135 | shaderPipe->pipelineShaderStage.reserve(shaderPipe->shader.size()); 136 | 137 | for (const auto &shaderPair : shaderPipe->shader) { 138 | const auto &shaderData = shaderPair.first; 139 | 140 | const ShaderModuleCreateInfo shaderModuleCreateInfo( 141 | {}, shaderData.size() * sizeof(uint32_t), shaderData.data()); 142 | const auto shaderModule = 143 | device.createShaderModule(shaderModuleCreateInfo); 144 | shaderModules.push_back(shaderModule); 145 | shaderPipe->pipelineShaderStage.push_back(PipelineShaderStageCreateInfo( 146 | {}, shaderPair.second, shaderModule, "main")); 147 | } 148 | 149 | shaderPipe->rasterization.frontFace = FrontFace::eCounterClockwise; 150 | shaderPipe->rasterization.lineWidth = 1; 151 | shaderPipe->rasterization.depthBiasEnable = false; 152 | shaderPipe->rasterization.depthClampEnable = false; 153 | shaderPipe->rasterization.rasterizerDiscardEnable = false; 154 | shaderPipe->rasterization.cullMode = material.doubleSided 155 | ? CullModeFlagBits::eNone 156 | : CullModeFlagBits::eFront; 157 | 158 | GraphicsPipelineCreateInfo gpipeCreateInfo( 159 | {}, shaderPipe->pipelineShaderStage, &shaderPipe->inputStateCreateInfo, 160 | &inputAssemblyCreateInfo, {}, &pipelineViewportCreateInfo, 161 | &shaderPipe->rasterization, &multisampleCreateInfo, &pipeDepthState, 162 | &colorBlendState, {}, {}, renderpass, 0); 163 | shaderAPI->addToMaterial(&material, &gpipeCreateInfo); 164 | pipelineCreateInfos.push_back(gpipeCreateInfo); 165 | shaderPipes.push_back(shaderPipe); 166 | } 167 | 168 | const auto indexOffset = pipelines.size(); 169 | const auto piperesult = 170 | device.createGraphicsPipelines({}, pipelineCreateInfos); 171 | VERROR(piperesult.result); 172 | pipelines.resize(indexOffset + piperesult.value.size()); 173 | std::copy(piperesult.value.cbegin(), piperesult.value.cend(), 174 | pipelines.begin() + indexOffset); 175 | 176 | for (auto &pInfo : pipelineCreateInfos) { 177 | pInfo.renderPass = lightRenderpass; 178 | } 179 | 180 | const auto piperesult2 = 181 | device.createGraphicsPipelines({}, pipelineCreateInfos); 182 | VERROR(piperesult2.result); 183 | lightMapPipelines.resize(indexOffset + piperesult.value.size()); 184 | std::copy(piperesult2.value.cbegin(), piperesult2.value.cend(), 185 | lightMapPipelines.begin() + indexOffset); 186 | 187 | return indexOffset; 188 | } 189 | 190 | template 191 | void __pushRender(VulkanGraphicsModule *vgm, const size_t renderInfoCount, 192 | const RenderInfo *renderInfos) { 193 | const CommandBufferAllocateInfo commandBufferAllocate( 194 | vgm->pool, CommandBufferLevel::eSecondary, 1); 195 | 196 | const auto cmdBuf = 197 | vgm->device.allocateCommandBuffers(commandBufferAllocate).back(); 198 | const auto passes = ([&]() { 199 | if constexpr (lightMaps) { 200 | return vgm->lightRenderpass; 201 | } else { 202 | return vgm->renderpass; 203 | } 204 | })(); 205 | 206 | const CommandBufferInheritanceInfo inheritance(passes, 0); 207 | const CommandBufferBeginInfo beginInfo( 208 | CommandBufferUsageFlagBits::eRenderPassContinue, &inheritance); 209 | cmdBuf.begin(beginInfo); 210 | for (size_t i = 0; i < renderInfoCount; i++) { 211 | auto &info = renderInfos[i]; 212 | 213 | std::vector vertexBuffer; 214 | vertexBuffer.reserve(info.vertexBuffer.size()); 215 | 216 | for (auto vertId : info.vertexBuffer) { 217 | vertexBuffer.push_back(vgm->bufferList[vertId]); 218 | } 219 | 220 | if (info.vertexOffsets.size() == 0) { 221 | std::vector offsets(vertexBuffer.size()); 222 | std::fill(offsets.begin(), offsets.end(), 0); 223 | cmdBuf.bindVertexBuffers(0, vertexBuffer, offsets); 224 | } else { 225 | cmdBuf.bindVertexBuffers(0, vertexBuffer, info.vertexOffsets); 226 | } 227 | 228 | if (info.bindingID != UINT64_MAX) { 229 | vgm->shaderAPI->addToRender(&info.bindingID, 1, (void *)&cmdBuf); 230 | } else { 231 | const auto binding = 232 | vgm->shaderAPI->createBindings(vgm->shaderPipes[info.materialId]); 233 | vgm->shaderAPI->addToRender(&binding, 1, (void *)&cmdBuf); 234 | } 235 | 236 | if constexpr (lightMaps) { 237 | cmdBuf.bindPipeline(PipelineBindPoint::eGraphics, 238 | vgm->lightMapPipelines[info.materialId]); 239 | } else { 240 | cmdBuf.bindPipeline(PipelineBindPoint::eGraphics, 241 | vgm->pipelines[info.materialId]); 242 | } 243 | 244 | if (info.indexSize != IndexSize::NONE) [[likely]] { 245 | cmdBuf.bindIndexBuffer(vgm->bufferList[info.indexBuffer], 246 | info.indexOffset, (IndexType)info.indexSize); 247 | 248 | cmdBuf.drawIndexed(info.indexCount, info.instanceCount, 0, 0, 0); 249 | } else { 250 | cmdBuf.draw(info.indexCount, info.instanceCount, 0, 0); 251 | } 252 | } 253 | cmdBuf.end(); 254 | const std::lock_guard onExitUnlock(vgm->commandBufferRecording); 255 | 256 | if constexpr (lightMaps) { 257 | vgm->lightCommandBuffer.push_back(cmdBuf); 258 | } else { 259 | vgm->secondaryCommandBuffer.push_back(cmdBuf); 260 | } 261 | } 262 | 263 | void VulkanGraphicsModule::pushRender(const size_t renderInfoCount, 264 | const RenderInfo *renderInfos) { 265 | EXPECT(renderInfoCount != 0 && renderInfos != nullptr); 266 | for (size_t i = 0; i < renderInfoCount; i++) { 267 | this->renderInfos.push_back(renderInfos[i]); 268 | } 269 | __pushRender(this, renderInfoCount, renderInfos); 270 | __pushRender(this, renderInfoCount, renderInfos); 271 | } 272 | 273 | inline BufferUsageFlags getUsageFlagsFromDataType(const DataType type) { 274 | switch (type) { 275 | case DataType::VertexIndexData: 276 | return BufferUsageFlagBits::eVertexBuffer | 277 | BufferUsageFlagBits::eIndexBuffer; 278 | case DataType::Uniform: 279 | return BufferUsageFlagBits::eUniformBuffer; 280 | case DataType::VertexData: 281 | return BufferUsageFlagBits::eVertexBuffer; 282 | case DataType::IndexData: 283 | return BufferUsageFlagBits::eIndexBuffer; 284 | default: 285 | throw std::runtime_error("Couldn't find usage flag"); 286 | } 287 | } 288 | 289 | size_t VulkanGraphicsModule::pushData(const size_t dataCount, void *data, 290 | const size_t *dataSizes, 291 | const DataType type) { 292 | EXPECT(dataCount != 0 && data != nullptr && dataSizes != nullptr); 293 | 294 | std::vector tempMemory; 295 | tempMemory.reserve(dataCount); 296 | std::vector tempBuffer; 297 | tempBuffer.reserve(dataCount); 298 | 299 | const auto firstIndex = bufferList.size(); 300 | bufferList.reserve(firstIndex + dataCount); 301 | const auto firstMemIndex = bufferMemoryList.size(); 302 | bufferMemoryList.reserve(firstMemIndex + dataCount); 303 | 304 | const auto cmdBuf = cmdbuffer.back(); 305 | 306 | const CommandBufferBeginInfo beginInfo( 307 | CommandBufferUsageFlagBits::eOneTimeSubmit); 308 | cmdBuf.begin(beginInfo); 309 | 310 | const BufferUsageFlags bufferUsage = getUsageFlagsFromDataType(type); 311 | 312 | for (size_t i = 0; i < dataCount; i++) { 313 | const auto size = dataSizes[i]; 314 | const auto dataptr = ((const uint8_t **)data)[i]; 315 | 316 | const BufferCreateInfo bufferCreateInfo( 317 | {}, size, BufferUsageFlagBits::eTransferSrc, SharingMode::eExclusive); 318 | const auto intermBuffer = device.createBuffer(bufferCreateInfo); 319 | tempBuffer.push_back(intermBuffer); 320 | const auto memRequ = device.getBufferMemoryRequirements(intermBuffer); 321 | 322 | const MemoryAllocateInfo allocInfo(memRequ.size, 323 | memoryTypeHostVisibleCoherent); 324 | const auto hostVisibleMemory = device.allocateMemory(allocInfo); 325 | tempMemory.push_back(hostVisibleMemory); 326 | device.bindBufferMemory(intermBuffer, hostVisibleMemory, 0); 327 | const auto mappedHandle = 328 | device.mapMemory(hostVisibleMemory, 0, VK_WHOLE_SIZE); 329 | memcpy(mappedHandle, dataptr, size); 330 | device.unmapMemory(hostVisibleMemory); 331 | 332 | const BufferCreateInfo bufferLocalCreateInfo( 333 | {}, size, 334 | BufferUsageFlagBits::eTransferDst | BufferUsageFlagBits::eTransferSrc | 335 | bufferUsage, 336 | SharingMode::eExclusive); 337 | const auto localBuffer = device.createBuffer(bufferLocalCreateInfo); 338 | bufferList.push_back(localBuffer); 339 | const auto memRequLocal = device.getBufferMemoryRequirements(localBuffer); 340 | const MemoryAllocateInfo allocLocalInfo(memRequLocal.size, 341 | memoryTypeDeviceLocal); 342 | const auto localMem = device.allocateMemory(allocLocalInfo); 343 | device.bindBufferMemory(localBuffer, localMem, 0); 344 | bufferMemoryList.push_back(localMem); 345 | bufferSizeList.push_back(size); 346 | 347 | const BufferCopy copyInfo(0, 0, size); 348 | cmdBuf.copyBuffer(intermBuffer, localBuffer, copyInfo); 349 | } 350 | 351 | cmdBuf.end(); 352 | 353 | submitAndWait(device, queue, cmdBuf); 354 | 355 | for (const auto mem : tempMemory) 356 | device.freeMemory(mem); 357 | for (const auto buf : tempBuffer) 358 | device.destroyBuffer(buf); 359 | 360 | return firstIndex; 361 | } 362 | 363 | void VulkanGraphicsModule::changeData(const size_t bufferIndex, 364 | const void *data, const size_t dataSizes, 365 | const size_t offset) { 366 | EXPECT(bufferIndex >= 0 && bufferIndex < this->bufferList.size() && 367 | data != nullptr && dataSizes != 0); 368 | 369 | const BufferCreateInfo bufferCreateInfo({}, dataSizes, 370 | BufferUsageFlagBits::eTransferSrc, 371 | SharingMode::eExclusive); 372 | const auto intermBuffer = device.createBuffer(bufferCreateInfo); 373 | const auto memRequ = device.getBufferMemoryRequirements(intermBuffer); 374 | 375 | const MemoryAllocateInfo allocInfo(memRequ.size, 376 | memoryTypeHostVisibleCoherent); 377 | const auto hostVisibleMemory = device.allocateMemory(allocInfo); 378 | device.bindBufferMemory(intermBuffer, hostVisibleMemory, 0); 379 | const auto mappedHandle = 380 | device.mapMemory(hostVisibleMemory, 0, VK_WHOLE_SIZE); 381 | 382 | memcpy(mappedHandle, data, dataSizes); 383 | 384 | device.unmapMemory(hostVisibleMemory); 385 | 386 | const auto cmdBuf = cmdbuffer.back(); 387 | 388 | const CommandBufferBeginInfo beginInfo( 389 | CommandBufferUsageFlagBits::eOneTimeSubmit); 390 | cmdBuf.begin(beginInfo); 391 | 392 | const BufferCopy copyRegion(0, offset, dataSizes); 393 | 394 | cmdBuf.copyBuffer(intermBuffer, this->bufferList[bufferIndex], copyRegion); 395 | 396 | cmdBuf.end(); 397 | 398 | submitAndWait(device, queue, cmdBuf); 399 | device.freeMemory(hostVisibleMemory); 400 | device.destroyBuffer(intermBuffer); 401 | } 402 | 403 | size_t VulkanGraphicsModule::pushSampler(const SamplerInfo &sampler) { 404 | const auto position = this->sampler.size(); 405 | const SamplerCreateInfo samplerCreateInfo( 406 | {}, (Filter)sampler.minFilter, (Filter)sampler.magFilter, 407 | SamplerMipmapMode::eLinear, (SamplerAddressMode)sampler.uMode, 408 | (SamplerAddressMode)sampler.vMode, (SamplerAddressMode)sampler.vMode, 0, 409 | sampler.anisotropy, sampler.anisotropy); 410 | const auto smplr = device.createSampler(samplerCreateInfo); 411 | this->sampler.push_back(smplr); 412 | return position; 413 | } 414 | 415 | inline size_t 416 | createInternalImages(VulkanGraphicsModule *vgm, 417 | const std::vector &imagesIn) { 418 | std::vector> memorys; 419 | size_t wholeSize = 0; 420 | 421 | const auto firstIndex = vgm->textureImages.size(); 422 | 423 | for (const auto &img : imagesIn) { 424 | const ImageCreateInfo depthImageCreateInfo( 425 | {}, ImageType::e2D, img.format, {img.ex.width, img.ex.height, 1}, 1, 1, 426 | img.sampleCount, ImageTiling::eOptimal, img.usage); 427 | const auto depthImage = vgm->device.createImage(depthImageCreateInfo); 428 | 429 | const MemoryRequirements imageMemReq = 430 | vgm->device.getImageMemoryRequirements(depthImage); 431 | 432 | const ImageAspectFlags aspect = 433 | (img.usage & ImageUsageFlagBits::eDepthStencilAttachment 434 | ? ImageAspectFlagBits::eDepth 435 | : (((img.usage & ImageUsageFlagBits::eColorAttachment || 436 | img.usage & ImageUsageFlagBits::eSampled) 437 | ? ImageAspectFlagBits::eColor 438 | : (ImageAspectFlagBits)0))); 439 | const ImageSubresourceRange subresourceRange(aspect, 0, 1, 0, 1); 440 | 441 | const ImageViewCreateInfo depthImageViewCreateInfo( 442 | {}, depthImage, ImageViewType::e2D, img.format, {}, subresourceRange); 443 | vgm->textureImages.push_back(depthImage); 444 | 445 | const auto rest = wholeSize % imageMemReq.alignment; 446 | if (rest != 0) { 447 | wholeSize += imageMemReq.alignment - rest; 448 | } 449 | 450 | memorys.push_back(std::make_tuple(depthImageViewCreateInfo, wholeSize)); 451 | wholeSize += imageMemReq.size; 452 | } 453 | 454 | const MemoryAllocateInfo memAllocInfo(wholeSize, vgm->memoryTypeDeviceLocal); 455 | const auto depthImageMemory = vgm->device.allocateMemory(memAllocInfo); 456 | 457 | for (const auto &[image, offset] : memorys) { 458 | vgm->device.bindImageMemory(image.image, depthImageMemory, offset); 459 | vgm->textureMemorys.push_back(std::make_tuple(depthImageMemory, offset)); 460 | 461 | const auto depthImageView = vgm->device.createImageView(image); 462 | vgm->textureImageViews.push_back(depthImageView); 463 | } 464 | 465 | return firstIndex; 466 | } 467 | 468 | size_t VulkanGraphicsModule::pushTexture(const size_t textureCount, 469 | const TextureInfo *textures) { 470 | EXPECT(textureCount != 0 && textures != nullptr); 471 | 472 | const size_t firstIndex = textureImages.size(); 473 | 474 | std::vector intermBuffers; 475 | std::vector intermMemorys; 476 | std::vector intermCopys; 477 | intermBuffers.reserve(textureCount); 478 | intermMemorys.reserve(textureCount); 479 | intermCopys.reserve(textureCount); 480 | 481 | util::OnExit exitHandle([&] { 482 | for (auto mem : intermMemorys) 483 | device.freeMemory(mem); 484 | for (auto img : intermBuffers) 485 | device.destroyBuffer(img); 486 | }); 487 | 488 | textureImages.reserve(firstIndex + textureCount); 489 | textureMemorys.reserve(firstIndex + textureCount); 490 | textureImageViews.reserve(firstIndex + textureCount); 491 | 492 | const auto cmd = this->cmdbuffer.back(); 493 | 494 | const CommandBufferBeginInfo beginInfo( 495 | CommandBufferUsageFlagBits::eOneTimeSubmit, {}); 496 | cmd.begin(beginInfo); 497 | 498 | constexpr ImageSubresourceRange range = {ImageAspectFlagBits::eColor, 0, 1, 0, 499 | 1}; 500 | const Format format = Format::eR8G8B8A8Unorm; 501 | 502 | std::vector imagesIn(textureCount); 503 | for (size_t i = 0; i < textureCount; i++) { 504 | const TextureInfo &tex = textures[i]; 505 | const Extent2D ext = {tex.width, tex.height}; 506 | imagesIn[i] = {format, ext, 507 | ImageUsageFlagBits::eTransferDst | 508 | ImageUsageFlagBits::eSampled}; 509 | } 510 | 511 | const auto internalImageIndex = createInternalImages(this, imagesIn); 512 | 513 | for (size_t i = 0; i < textureCount; i++) { 514 | const TextureInfo &tex = textures[i]; 515 | const Extent3D ext = {tex.width, tex.height, 1}; 516 | 517 | const BufferCreateInfo intermBufferCreate({}, tex.size, 518 | BufferUsageFlagBits::eTransferSrc, 519 | SharingMode::eExclusive, {}); 520 | const auto intermBuffer = device.createBuffer(intermBufferCreate); 521 | intermBuffers.push_back(intermBuffer); 522 | const auto memRequIntern = device.getBufferMemoryRequirements(intermBuffer); 523 | const MemoryAllocateInfo intermMemAllocInfo(memRequIntern.size, 524 | memoryTypeHostVisibleCoherent); 525 | const auto intermMemory = device.allocateMemory(intermMemAllocInfo); 526 | intermMemorys.push_back(intermMemory); 527 | device.bindBufferMemory(intermBuffer, intermMemory, 0); 528 | const auto handle = device.mapMemory(intermMemory, 0, VK_WHOLE_SIZE, {}); 529 | std::memcpy(handle, tex.data, tex.size); 530 | device.unmapMemory(intermMemory); 531 | 532 | intermCopys.push_back({0, 533 | tex.width, 534 | tex.height, 535 | {ImageAspectFlagBits::eColor, 0, 0, 1}, 536 | {}, 537 | ext}); 538 | 539 | const auto curentImg = textureImages[i + internalImageIndex]; 540 | 541 | waitForImageTransition( 542 | cmd, ImageLayout::eUndefined, ImageLayout::eTransferDstOptimal, 543 | curentImg, range, PipelineStageFlagBits::eTopOfPipe, 544 | AccessFlagBits::eNoneKHR, PipelineStageFlagBits::eTransfer, 545 | AccessFlagBits::eTransferWrite); 546 | 547 | cmd.copyBufferToImage(intermBuffer, curentImg, 548 | ImageLayout::eTransferDstOptimal, intermCopys.back()); 549 | 550 | waitForImageTransition( 551 | cmd, ImageLayout::eTransferDstOptimal, 552 | ImageLayout::eShaderReadOnlyOptimal, curentImg, range, 553 | PipelineStageFlagBits::eTransfer, AccessFlagBits::eTransferWrite, 554 | PipelineStageFlagBits::eFragmentShader, AccessFlagBits::eShaderRead); 555 | } 556 | 557 | cmd.end(); 558 | 559 | const SubmitInfo submitInfo({}, {}, cmd, {}); 560 | queue.submit(submitInfo, commandBufferFence); 561 | const Result result = 562 | device.waitForFences(commandBufferFence, true, UINT64_MAX); 563 | VERROR(result); 564 | device.resetFences(commandBufferFence); 565 | 566 | return firstIndex; 567 | } 568 | 569 | size_t VulkanGraphicsModule::pushLights(const size_t lightCount, 570 | const Light *lights, 571 | const size_t offset) { 572 | EXPECT(lightCount + offset < 50 && lights != nullptr); 573 | this->lights.lightCount = offset + lightCount; 574 | std::copy(lights, lights + lightCount, this->lights.lights + offset); 575 | changeData(lightData, &this->lights, sizeof(this->lights)); 576 | return this->lights.lightCount; 577 | } 578 | 579 | #ifdef DEBUG 580 | VkBool32 debugMessage(DebugUtilsMessageSeverityFlagBitsEXT messageSeverity, 581 | DebugUtilsMessageTypeFlagsEXT messageTypes, 582 | const DebugUtilsMessengerCallbackDataEXT *pCallbackData, 583 | void *pUserData) { 584 | if (messageSeverity == DebugUtilsMessageSeverityFlagBitsEXT::eVerbose) { 585 | return VK_TRUE; 586 | } 587 | std::string severity = to_string(messageSeverity); 588 | std::string type = to_string(messageTypes); 589 | 590 | printf("[%s][%s]: %s\n", severity.c_str(), type.c_str(), 591 | pCallbackData->pMessage); 592 | return !(bool)(messageSeverity | 593 | DebugUtilsMessageSeverityFlagBitsEXT::eError); 594 | } 595 | #endif 596 | 597 | inline void createLightPass(VulkanGraphicsModule *vgm) { 598 | 599 | const auto sapi = vgm->getShaderAPI(); 600 | 601 | const auto pipe = (VulkanShaderPipe *)sapi->loadShaderPipeAndCompile( 602 | {"assets/lightPass.vert", "assets/lightPass.frag"}); 603 | vgm->shaderPipes.push_back(pipe); 604 | vgm->lightBindings = sapi->createBindings(pipe, 1); 605 | 606 | auto ptr = &vgm->lights; 607 | auto sizeOfLight = sizeof(vgm->lights); 608 | vgm->lightData = vgm->pushData(1, &ptr, &sizeOfLight, DataType::Uniform); 609 | 610 | const std::array bindingInfos = { 611 | BindingInfo{0, 612 | vgm->lightBindings, 613 | BindingType::InputAttachment, 614 | {vgm->albedoImage, UINT64_MAX}}, 615 | BindingInfo{1, 616 | vgm->lightBindings, 617 | BindingType::InputAttachment, 618 | {vgm->normalImage, UINT64_MAX}}, 619 | BindingInfo{2, 620 | vgm->lightBindings, 621 | BindingType::InputAttachment, 622 | {vgm->roughnessMetallicImage, UINT64_MAX}}, 623 | BindingInfo{3, 624 | vgm->lightBindings, 625 | BindingType::InputAttachment, 626 | {vgm->position, UINT64_MAX}}, 627 | BindingInfo{4, 628 | vgm->lightBindings, 629 | BindingType::UniformBuffer, 630 | {vgm->lightData, VK_WHOLE_SIZE, 0}}}; 631 | 632 | sapi->bindData(bindingInfos.data(), bindingInfos.size()); 633 | 634 | for (const auto &shaderPair : pipe->shader) { 635 | const auto &shaderData = shaderPair.first; 636 | 637 | const ShaderModuleCreateInfo shaderModuleCreateInfo( 638 | {}, shaderData.size() * sizeof(uint32_t), shaderData.data()); 639 | const auto shaderModule = 640 | vgm->device.createShaderModule(shaderModuleCreateInfo); 641 | vgm->shaderModules.push_back(shaderModule); 642 | pipe->pipelineShaderStage.push_back(PipelineShaderStageCreateInfo( 643 | {}, shaderPair.second, shaderModule, "main")); 644 | } 645 | 646 | const Rect2D sic = { 647 | {0, 0}, {(uint32_t)vgm->viewport.width, (uint32_t)vgm->viewport.height}}; 648 | 649 | const PipelineVertexInputStateCreateInfo visci; 650 | const PipelineViewportStateCreateInfo vsci({}, vgm->viewport, sic); 651 | const PipelineRasterizationStateCreateInfo rsci( 652 | {}, false, false, {}, {}, {}, false, 0.0f, 0.0f, 0.0f, 1.0f); 653 | 654 | const PipelineMultisampleStateCreateInfo msci; 655 | 656 | constexpr std::array blendAttachment = {PipelineColorBlendAttachmentState( 657 | true, BlendFactor::eSrcAlpha, BlendFactor::eOneMinusSrcAlpha, 658 | BlendOp::eAdd, BlendFactor::eOne, BlendFactor::eZero, BlendOp::eAdd, 659 | (ColorComponentFlags)FlagTraits::allFlags)}; 660 | 661 | const PipelineColorBlendStateCreateInfo colorBlendState( 662 | {}, false, LogicOp::eOr, blendAttachment); 663 | 664 | GraphicsPipelineCreateInfo graphicsPipeline( 665 | {}, pipe->pipelineShaderStage, &visci, &inputAssemblyCreateInfo, {}, 666 | &vsci, &rsci, &msci, {}, &colorBlendState, nullptr, nullptr, 667 | vgm->renderpass, 1); 668 | vgm->lightMat = Material(pipe); 669 | sapi->addToMaterial(&vgm->lightMat, &graphicsPipeline); 670 | 671 | const auto gp = vgm->device.createGraphicsPipeline({}, graphicsPipeline); 672 | VERROR(gp.result) 673 | vgm->lightPipe = vgm->pipelines.size(); 674 | vgm->pipelines.push_back(gp.value); 675 | } 676 | 677 | size_t VulkanGraphicsModule::generateLightMaps(const size_t count, 678 | const LightMap *lightMaps) { 679 | std::vector imageInfos; 680 | imageInfos.resize(count); 681 | 682 | const Extent2D extent(500, 500); 683 | for (size_t i = 0; i < count; i++) { 684 | imageInfos[i].ex = extent; 685 | imageInfos[i].format = this->depthFormat; 686 | imageInfos[i].sampleCount = SampleCountFlagBits::e1; 687 | imageInfos[i].usage = ImageUsageFlagBits::eDepthStencilAttachment | 688 | ImageUsageFlagBits::eSampled; 689 | } 690 | const auto images = createInternalImages(this, imageInfos); 691 | 692 | const auto cmd = cmdbuffer.back(); 693 | 694 | std::vector cFrameBuffers; 695 | for (size_t i = 0; i < count; i++) { 696 | const auto &lightMap = lightMaps[i]; 697 | 698 | const auto projView = 699 | glm::perspective(glm::radians(70.0f), 1.0f, 0.1f, 100.0f) * 700 | glm::lookAt(lightMap.lightPos, lightMap.lightPos - lightMap.direction, 701 | glm::vec3(0, 1, 0)); 702 | 703 | this->changeData(this->getGraphicsModule()->dataID + 1, (const uint8_t *)&projView, sizeof(glm::mat4)); 704 | 705 | const CommandBufferBeginInfo beginInfo( 706 | CommandBufferUsageFlagBits::eOneTimeSubmit); 707 | cmd.begin(beginInfo); 708 | 709 | const std::array views = {this->textureImageViews[images + i], 710 | this->textureImageViews[albedoImage]}; 711 | const FramebufferCreateInfo cFrameBufferCI({}, lightRenderpass, views, 712 | extent.width, extent.height, 1); 713 | const auto cFrameBuffer = device.createFramebuffer(cFrameBufferCI); 714 | cFrameBuffers.push_back(cFrameBuffer); 715 | 716 | const std::array cValue = {ClearValue(ClearDepthStencilValue(1.0f, 0)), 717 | ClearValue()}; 718 | const RenderPassBeginInfo renderpassBegin(lightRenderpass, cFrameBuffer, 719 | {{0, 0}, extent}, cValue); 720 | cmd.beginRenderPass(renderpassBegin, 721 | SubpassContents::eSecondaryCommandBuffers); 722 | 723 | cmd.executeCommands(lightCommandBuffer); 724 | 725 | cmd.endRenderPass(); 726 | 727 | constexpr ImageSubresourceRange range(ImageAspectFlagBits::eDepth, 0, 1, 0, 728 | 1); 729 | 730 | waitForImageTransition(cmd, ImageLayout::eDepthAttachmentOptimal, 731 | ImageLayout::eShaderReadOnlyOptimal, 732 | this->textureImages[images + i], range); 733 | cmd.end(); 734 | 735 | submitAndWait(device, queue, cmd); 736 | } 737 | 738 | this->shaderAPI->updateAllTextures(); 739 | this->secondaryCommandBuffer.clear(); 740 | __pushRender(this, this->renderInfos.size(), this->renderInfos.data()); 741 | 742 | return 0; 743 | } 744 | 745 | main::Error VulkanGraphicsModule::init() { 746 | this->shaderAPI = new VulkanShaderModule(this); 747 | #pragma region Instance 748 | const ApplicationInfo applicationInfo(APPLICATION_NAME, APPLICATION_VERSION, 749 | ENGINE_NAME, ENGINE_VERSION, 750 | VK_API_VERSION_1_0); 751 | 752 | const auto layerInfos = enumerateInstanceLayerProperties(); 753 | std::vector layerEnabled; 754 | for (const auto &layer : layerInfos) { 755 | const auto lname = layer.layerName.data(); 756 | const auto enditr = layerToEnable.end(); 757 | if (std::find_if(layerToEnable.begin(), enditr, 758 | [&](auto in) { return strcmp(lname, in) == 0; }) != enditr) 759 | layerEnabled.push_back(lname); 760 | } 761 | 762 | const auto extensionInfos = enumerateInstanceExtensionProperties(); 763 | std::vector extensionEnabled; 764 | for (const auto &extension : extensionInfos) { 765 | const auto lname = extension.extensionName.data(); 766 | const auto enditr = extensionToEnable.end(); 767 | if (std::find_if(extensionToEnable.begin(), enditr, 768 | [&](auto in) { return strcmp(lname, in) == 0; }) != enditr) 769 | extensionEnabled.push_back(lname); 770 | } 771 | 772 | const InstanceCreateInfo createInfo( 773 | {}, &applicationInfo, (uint32_t)layerEnabled.size(), layerEnabled.data(), 774 | (uint32_t)extensionEnabled.size(), extensionEnabled.data()); 775 | this->instance = createInstance(createInfo); 776 | 777 | #ifdef DEBUG 778 | if (std::find_if(begin(extensionEnabled), end(extensionEnabled), [](auto x) { 779 | return strcmp(x, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0; 780 | }) != end(extensionEnabled)) { 781 | DispatchLoaderDynamic stat; 782 | stat.vkCreateDebugUtilsMessengerEXT = 783 | (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr( 784 | instance, "vkCreateDebugUtilsMessengerEXT"); 785 | const DebugUtilsMessengerCreateInfoEXT debugUtilsMsgCreateInfo( 786 | {}, 787 | (DebugUtilsMessageSeverityFlagsEXT) 788 | FlagTraits::allFlags, 789 | (DebugUtilsMessageTypeFlagsEXT) 790 | FlagTraits::allFlags, 791 | (PFN_vkDebugUtilsMessengerCallbackEXT)debugMessage); 792 | debugMessenger = instance.createDebugUtilsMessengerEXT( 793 | debugUtilsMsgCreateInfo, nullptr, stat); 794 | } 795 | #endif 796 | #pragma endregion 797 | 798 | #pragma region Device 799 | constexpr auto getScore = [](auto physDevice) { 800 | const auto properties = physDevice.getProperties(); 801 | return properties.limits.maxImageDimension2D + 802 | (properties.deviceType == PhysicalDeviceType::eDiscreteGpu ? 1000 803 | : 0); 804 | }; 805 | 806 | const auto physicalDevices = this->instance.enumeratePhysicalDevices(); 807 | this->physicalDevice = *std::max_element( 808 | physicalDevices.begin(), physicalDevices.end(), 809 | [&](auto p1, auto p2) { return getScore(p1) < getScore(p2); }); 810 | 811 | // just one queue for now 812 | const auto queueFamilys = this->physicalDevice.getQueueFamilyProperties(); 813 | const auto bgnitr = queueFamilys.begin(); 814 | const auto enditr = queueFamilys.end(); 815 | const auto queueFamilyItr = std::find_if(bgnitr, enditr, [](auto queue) { 816 | return queue.queueFlags & QueueFlagBits::eGraphics; 817 | }); 818 | if (queueFamilyItr == enditr) 819 | return main::Error::NO_GRAPHIC_QUEUE_FOUND; 820 | 821 | queueFamilyIndex = (uint32_t)std::distance(bgnitr, queueFamilyItr); 822 | const auto &queueFamily = *queueFamilyItr; 823 | std::vector priorities(queueFamily.queueCount); 824 | std::fill(priorities.begin(), priorities.end(), 0.0f); 825 | 826 | queueIndex = (uint32_t)std::distance(bgnitr, queueFamilyItr); 827 | const DeviceQueueCreateInfo queueCreateInfo( 828 | {}, queueIndex, queueFamily.queueCount, priorities.data()); 829 | 830 | const auto devextensions = 831 | physicalDevice.enumerateDeviceExtensionProperties(); 832 | const auto devextEndItr = devextensions.end(); 833 | const auto fndDevExtItr = std::find_if( 834 | devextensions.begin(), devextEndItr, [](ExtensionProperties prop) { 835 | return strcmp(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0; 836 | }); 837 | if (fndDevExtItr == devextEndItr) 838 | return main::Error::SWAPCHAIN_EXT_NOT_FOUND; 839 | 840 | const char *name = VK_KHR_SWAPCHAIN_EXTENSION_NAME; 841 | const DeviceCreateInfo deviceCreateInfo({}, 1, &queueCreateInfo, 0, {}, 1, 842 | &name); 843 | this->device = this->physicalDevice.createDevice(deviceCreateInfo); 844 | 845 | const auto c4Props = 846 | this->physicalDevice.getFormatProperties(Format::eR8G8B8A8Unorm); 847 | if (!(c4Props.optimalTilingFeatures & 848 | FormatFeatureFlagBits::eColorAttachment)) 849 | return main::Error::FORMAT_NOT_SUPPORTED; 850 | 851 | #pragma endregion 852 | 853 | #pragma region Queue, Surface, Prepipe, MemTypes 854 | queue = device.getQueue(queueFamilyIndex, queueIndex); 855 | 856 | const auto winM = graphicsModule->getWindowModule(); 857 | #ifdef WIN32 858 | Win32SurfaceCreateInfoKHR surfaceCreateInfo({}, (HINSTANCE)winM->hInstance, 859 | (HWND)winM->hWnd); 860 | surface = instance.createWin32SurfaceKHR(surfaceCreateInfo); 861 | #endif // WIN32 862 | 863 | if (!physicalDevice.getSurfaceSupportKHR(queueIndex, surface)) 864 | return main::Error::NO_SURFACE_SUPPORT; 865 | 866 | const auto surfaceFormat = physicalDevice.getSurfaceFormatsKHR(surface); 867 | const auto surfEndItr = surfaceFormat.end(); 868 | const auto surfBeginItr = surfaceFormat.begin(); 869 | const auto fitr = 870 | std::find_if(surfBeginItr, surfEndItr, [](SurfaceFormatKHR format) { 871 | return format.format == Format::eB8G8R8A8Unorm; 872 | }); 873 | if (fitr == surfEndItr) 874 | return main::Error::FORMAT_NOT_FOUND; 875 | format = *fitr; 876 | 877 | const auto memoryProperties = physicalDevice.getMemoryProperties(); 878 | const auto memBeginItr = memoryProperties.memoryTypes.begin(); 879 | const auto memEndItr = memoryProperties.memoryTypes.end(); 880 | 881 | const auto findMemoryIndex = [&](auto prop) { 882 | const auto findItr = std::find_if(memBeginItr, memEndItr, [&](auto &type) { 883 | return type.propertyFlags & (prop); 884 | }); 885 | return std::distance(memBeginItr, findItr); 886 | }; 887 | 888 | memoryTypeDeviceLocal = findMemoryIndex(MemoryPropertyFlagBits::eDeviceLocal); 889 | memoryTypeHostVisibleCoherent = 890 | findMemoryIndex(MemoryPropertyFlagBits::eHostVisible | 891 | MemoryPropertyFlagBits::eHostCoherent); 892 | 893 | const auto capabilities = physicalDevice.getSurfaceCapabilitiesKHR(surface); 894 | viewport = Viewport(0, 0, capabilities.currentExtent.width, 895 | capabilities.currentExtent.height, 0, 1.0f); 896 | 897 | const auto presentModes = physicalDevice.getSurfacePresentModesKHR(surface); 898 | const auto presentModesEndItr = presentModes.end(); 899 | const auto presentModesBeginItr = presentModes.begin(); 900 | auto fndPresentMode = std::find(presentModesBeginItr, presentModesEndItr, 901 | PresentModeKHR::eMailbox); 902 | if (fndPresentMode == presentModesEndItr) { 903 | fndPresentMode = std::find(presentModesBeginItr, presentModesEndItr, 904 | PresentModeKHR::eImmediate); 905 | if (fndPresentMode == presentModesEndItr) 906 | fndPresentMode = presentModesBeginItr; 907 | } 908 | const auto presentMode = *fndPresentMode; 909 | #pragma endregion 910 | 911 | #pragma region Swapchain 912 | const SwapchainCreateInfoKHR swapchainCreateInfo( 913 | {}, surface, 3, format.format, format.colorSpace, 914 | capabilities.currentExtent, 1, ImageUsageFlagBits::eColorAttachment, 915 | SharingMode::eExclusive, 0, nullptr, 916 | SurfaceTransformFlagBitsKHR::eIdentity, 917 | CompositeAlphaFlagBitsKHR::eOpaque, presentMode, true, nullptr); 918 | 919 | swapchain = device.createSwapchainKHR(swapchainCreateInfo); 920 | 921 | swapchainImages = device.getSwapchainImagesKHR(swapchain); 922 | #pragma endregion 923 | 924 | #pragma region Depth and Output Attachments 925 | constexpr std::array potentialDepthFormat = { 926 | Format::eD32Sfloat, Format::eD32SfloatS8Uint, Format::eD24UnormS8Uint, 927 | Format::eD16Unorm, Format::eD16UnormS8Uint}; 928 | for (const Format pDF : potentialDepthFormat) { 929 | const FormatProperties fProp = physicalDevice.getFormatProperties(pDF); 930 | if (fProp.optimalTilingFeatures & 931 | FormatFeatureFlagBits::eDepthStencilAttachment) { 932 | depthFormat = pDF; 933 | break; 934 | } 935 | } 936 | if (depthFormat == Format::eUndefined) 937 | return main::Error::FORMAT_NOT_FOUND; 938 | const Extent2D ext = {(uint32_t)viewport.width, (uint32_t)viewport.height}; 939 | const std::vector intImageInfo = { 940 | {depthFormat, ext, ImageUsageFlagBits::eDepthStencilAttachment}, 941 | {format.format, ext, 942 | ImageUsageFlagBits::eColorAttachment | 943 | ImageUsageFlagBits::eInputAttachment}, 944 | {Format::eR8G8B8A8Snorm, ext, 945 | ImageUsageFlagBits::eColorAttachment | 946 | ImageUsageFlagBits::eInputAttachment}, 947 | {Format::eR8G8B8A8Snorm, ext, 948 | ImageUsageFlagBits::eColorAttachment | 949 | ImageUsageFlagBits::eInputAttachment}, 950 | {Format::eR8G8B8A8Snorm, ext, 951 | ImageUsageFlagBits::eColorAttachment | 952 | ImageUsageFlagBits::eInputAttachment}}; 953 | 954 | const auto imageFirstIndex = createInternalImages(this, intImageInfo); 955 | depthImage = imageFirstIndex; 956 | albedoImage = imageFirstIndex + 1; 957 | normalImage = imageFirstIndex + 2; 958 | roughnessMetallicImage = imageFirstIndex + 3; 959 | position = imageFirstIndex + 4; 960 | #pragma endregion 961 | 962 | #pragma region Renderpass 963 | 964 | const std::array attachments = { 965 | AttachmentDescription( 966 | {}, depthFormat, SampleCountFlagBits::e1, AttachmentLoadOp::eClear, 967 | AttachmentStoreOp::eDontCare, AttachmentLoadOp::eDontCare, 968 | AttachmentStoreOp::eDontCare, ImageLayout::eUndefined, 969 | ImageLayout::eDepthStencilAttachmentOptimal), 970 | AttachmentDescription( 971 | {}, format.format, SampleCountFlagBits::e1, AttachmentLoadOp::eClear, 972 | AttachmentStoreOp::eStore, AttachmentLoadOp::eDontCare, 973 | AttachmentStoreOp::eDontCare, ImageLayout::eUndefined, 974 | ImageLayout::eSharedPresentKHR), 975 | AttachmentDescription( 976 | {}, intImageInfo[2].format, SampleCountFlagBits::e1, 977 | AttachmentLoadOp::eClear, AttachmentStoreOp::eDontCare, 978 | AttachmentLoadOp::eDontCare, AttachmentStoreOp::eDontCare, 979 | ImageLayout::eUndefined, ImageLayout::eSharedPresentKHR), 980 | AttachmentDescription( 981 | {}, intImageInfo[3].format, SampleCountFlagBits::e1, 982 | AttachmentLoadOp::eClear, AttachmentStoreOp::eDontCare, 983 | AttachmentLoadOp::eDontCare, AttachmentStoreOp::eDontCare, 984 | ImageLayout::eUndefined, ImageLayout::eSharedPresentKHR), 985 | AttachmentDescription( 986 | {}, intImageInfo[4].format, SampleCountFlagBits::e1, 987 | AttachmentLoadOp::eClear, AttachmentStoreOp::eDontCare, 988 | AttachmentLoadOp::eDontCare, AttachmentStoreOp::eDontCare, 989 | ImageLayout::eUndefined, ImageLayout::eSharedPresentKHR), 990 | AttachmentDescription( 991 | {}, format.format, SampleCountFlagBits::e1, AttachmentLoadOp::eClear, 992 | AttachmentStoreOp::eStore, AttachmentLoadOp::eDontCare, 993 | AttachmentStoreOp::eDontCare, ImageLayout::eUndefined, 994 | ImageLayout::ePresentSrcKHR)}; 995 | 996 | constexpr std::array colorAttachments = { 997 | AttachmentReference(1, ImageLayout::eColorAttachmentOptimal), 998 | AttachmentReference(2, ImageLayout::eColorAttachmentOptimal), 999 | AttachmentReference(3, ImageLayout::eColorAttachmentOptimal), 1000 | AttachmentReference(4, ImageLayout::eColorAttachmentOptimal)}; 1001 | 1002 | constexpr std::array inputAttachments = { 1003 | AttachmentReference(1, ImageLayout::eShaderReadOnlyOptimal), 1004 | AttachmentReference(2, ImageLayout::eShaderReadOnlyOptimal), 1005 | AttachmentReference(3, ImageLayout::eShaderReadOnlyOptimal), 1006 | AttachmentReference(4, ImageLayout::eShaderReadOnlyOptimal)}; 1007 | 1008 | constexpr std::array colorAttachmentsSubpass1 = { 1009 | AttachmentReference(5, ImageLayout::eColorAttachmentOptimal)}; 1010 | 1011 | constexpr AttachmentReference depthAttachment( 1012 | 0, ImageLayout::eDepthStencilAttachmentOptimal); 1013 | 1014 | const std::array subpassDescriptions = { 1015 | SubpassDescription({}, PipelineBindPoint::eGraphics, {}, colorAttachments, 1016 | {}, &depthAttachment), 1017 | SubpassDescription({}, PipelineBindPoint::eGraphics, inputAttachments, 1018 | colorAttachmentsSubpass1)}; 1019 | 1020 | const auto frag1 = PipelineStageFlagBits::eColorAttachmentOutput | 1021 | PipelineStageFlagBits::eEarlyFragmentTests; 1022 | 1023 | const auto frag2 = AccessFlagBits::eColorAttachmentWrite | 1024 | AccessFlagBits::eColorAttachmentRead | 1025 | AccessFlagBits::eDepthStencilAttachmentRead | 1026 | AccessFlagBits::eDepthStencilAttachmentWrite; 1027 | 1028 | const std::array subpassDependencies = { 1029 | SubpassDependency(0, 1, frag1, frag1, frag2, frag2), 1030 | SubpassDependency(1, VK_SUBPASS_EXTERNAL, frag1, frag1, frag2, frag2)}; 1031 | 1032 | const SubpassDescription lightMapsSubpass({}, PipelineBindPoint::eGraphics, 1033 | {}, colorAttachments[0], {}, 1034 | &depthAttachment); 1035 | 1036 | const SubpassDependency lightMapsDep(0, VK_SUBPASS_EXTERNAL, frag1, frag1, 1037 | frag2, frag2); 1038 | 1039 | const RenderPassCreateInfo lightMapPassCreateInfo( 1040 | {}, 2, attachments.data(), 1, &lightMapsSubpass, 1, &lightMapsDep); 1041 | lightRenderpass = device.createRenderPass(lightMapPassCreateInfo); 1042 | 1043 | const RenderPassCreateInfo renderPassCreateInfo( 1044 | {}, attachments, subpassDescriptions, subpassDependencies); 1045 | renderpass = device.createRenderPass(renderPassCreateInfo); 1046 | #pragma endregion 1047 | 1048 | #pragma region CommandBuffer 1049 | swapchainImageviews.reserve(swapchainImages.size()); 1050 | 1051 | const CommandPoolCreateInfo commandPoolCreateInfo( 1052 | CommandPoolCreateFlagBits::eResetCommandBuffer, queueIndex); 1053 | pool = device.createCommandPool(commandPoolCreateInfo); 1054 | 1055 | const CommandBufferAllocateInfo cmdBufferAllocInfo( 1056 | pool, CommandBufferLevel::ePrimary, (uint32_t)swapchainImages.size() + 1); 1057 | cmdbuffer = device.allocateCommandBuffers(cmdBufferAllocInfo); 1058 | #pragma endregion 1059 | 1060 | #pragma region ImageViews and Framebuffer 1061 | for (auto im : swapchainImages) { 1062 | const ImageViewCreateInfo imageviewCreateInfo( 1063 | {}, im, ImageViewType::e2D, format.format, ComponentMapping(), 1064 | ImageSubresourceRange(ImageAspectFlagBits::eColor, 0, 1, 0, 1)); 1065 | 1066 | const auto imview = device.createImageView(imageviewCreateInfo); 1067 | swapchainImageviews.push_back(imview); 1068 | 1069 | std::array images; 1070 | std::copy(textureImageViews.begin() + imageFirstIndex, 1071 | textureImageViews.begin() + imageFirstIndex + intImageInfo.size(), 1072 | images.begin()); 1073 | images.back() = imview; 1074 | 1075 | const FramebufferCreateInfo framebufferCreateInfo( 1076 | {}, renderpass, images, viewport.width, viewport.height, 1); 1077 | framebuffer.push_back(device.createFramebuffer(framebufferCreateInfo)); 1078 | } 1079 | #pragma endregion 1080 | 1081 | #pragma region Vulkan Mutex 1082 | const FenceCreateInfo fenceCreateInfo; 1083 | commandBufferFence = device.createFence(fenceCreateInfo); 1084 | 1085 | const SemaphoreCreateInfo semaphoreCreateInfo; 1086 | waitSemaphore = device.createSemaphore(semaphoreCreateInfo); 1087 | signalSemaphore = device.createSemaphore(semaphoreCreateInfo); 1088 | #pragma endregion 1089 | 1090 | this->isInitialiazed = true; 1091 | this->shaderAPI->init(); 1092 | device.waitIdle(); 1093 | 1094 | createLightPass(this); 1095 | 1096 | auto nextimage = 1097 | device.acquireNextImageKHR(swapchain, UINT64_MAX, waitSemaphore, {}); 1098 | VERROR(nextimage.result); 1099 | this->nextImage = nextimage.value; 1100 | 1101 | return main::Error::NONE; 1102 | } 1103 | 1104 | void VulkanGraphicsModule::tick(double time) { 1105 | if (exitFailed) 1106 | return; 1107 | 1108 | const auto currentBuffer = cmdbuffer[this->nextImage]; 1109 | if (1) { // For now rerecord every tick 1110 | constexpr std::array clearColor = {1.0f, 1.0f, 1.0f, 1.0f}; 1111 | const std::array clearValue = {ClearValue(ClearDepthStencilValue(1.0f, 0)), 1112 | ClearValue(clearColor), 1113 | ClearValue(clearColor), 1114 | ClearValue(clearColor), 1115 | ClearValue(clearColor), 1116 | ClearValue(clearColor)}; 1117 | 1118 | const CommandBufferBeginInfo cmdBufferBeginInfo({}, nullptr); 1119 | currentBuffer.begin(cmdBufferBeginInfo); 1120 | 1121 | const RenderPassBeginInfo renderPassBeginInfo( 1122 | renderpass, framebuffer[this->nextImage], 1123 | {{0, 0}, {(uint32_t)viewport.width, (uint32_t)viewport.height}}, 1124 | clearValue); 1125 | currentBuffer.beginRenderPass(renderPassBeginInfo, 1126 | SubpassContents::eSecondaryCommandBuffers); 1127 | const std::lock_guard onExitUnlock(commandBufferRecording); 1128 | currentBuffer.executeCommands(secondaryCommandBuffer); 1129 | 1130 | currentBuffer.nextSubpass(SubpassContents::eInline); 1131 | 1132 | currentBuffer.bindPipeline(PipelineBindPoint::eGraphics, 1133 | pipelines[lightPipe]); 1134 | 1135 | const std::array lights = {lightBindings}; 1136 | getShaderAPI()->addToRender(lights.data(), lights.size(), 1137 | (CommandBuffer *)¤tBuffer); 1138 | 1139 | currentBuffer.draw(3, 1, 0, 0); 1140 | 1141 | currentBuffer.endRenderPass(); 1142 | currentBuffer.end(); 1143 | } 1144 | 1145 | primary[0] = currentBuffer; 1146 | 1147 | const PipelineStageFlags stageFlag = 1148 | PipelineStageFlagBits::eColorAttachmentOutput | 1149 | PipelineStageFlagBits::eLateFragmentTests; 1150 | const SubmitInfo submitInfo(waitSemaphore, stageFlag, primary, 1151 | signalSemaphore); 1152 | 1153 | queue.submit(submitInfo, commandBufferFence); 1154 | 1155 | const PresentInfoKHR presentInfo(signalSemaphore, swapchain, this->nextImage, 1156 | nullptr); 1157 | const Result result = queue.presentKHR(&presentInfo); 1158 | if (result == Result::eErrorOutOfDateKHR) { 1159 | exitFailed = true; 1160 | return; 1161 | } 1162 | if (result == Result::eErrorInitializationFailed) { 1163 | printf("For some reasone NV drivers seem to be hitting this error!"); 1164 | } 1165 | VERROR(result); 1166 | 1167 | const Result waitresult = 1168 | device.waitForFences(commandBufferFence, true, UINT64_MAX); 1169 | VERROR(waitresult); 1170 | 1171 | currentBuffer.reset(); 1172 | device.resetFences(commandBufferFence); 1173 | 1174 | auto nextimage = 1175 | device.acquireNextImageKHR(swapchain, UINT64_MAX, waitSemaphore, {}); 1176 | VERROR(nextimage.result); 1177 | this->nextImage = nextimage.value; 1178 | } 1179 | 1180 | void VulkanGraphicsModule::destroy() { 1181 | this->isInitialiazed = false; 1182 | device.waitIdle(); 1183 | this->shaderAPI->destroy(); 1184 | for (const auto pipe : this->lightMapPipelines) 1185 | device.destroyPipeline(pipe); 1186 | device.destroySemaphore(waitSemaphore); 1187 | device.destroySemaphore(signalSemaphore); 1188 | device.freeCommandBuffers(pool, secondaryCommandBuffer); 1189 | for (const auto imag : textureImages) 1190 | device.destroyImage(imag); 1191 | const auto eItr = std::unique( 1192 | textureMemorys.begin(), textureMemorys.end(), 1193 | [](auto t1, auto t2) { return std::get<0>(t1) == std::get<0>(t2); }); 1194 | for (auto itr = textureMemorys.begin(); itr != eItr; itr++) 1195 | device.freeMemory(std::get<0>(*itr)); 1196 | for (const auto imView : textureImageViews) 1197 | device.destroyImageView(imView); 1198 | for (const auto samp : sampler) 1199 | device.destroySampler(samp); 1200 | for (const auto mem : bufferMemoryList) 1201 | device.freeMemory(mem); 1202 | for (const auto buf : bufferList) 1203 | device.destroyBuffer(buf); 1204 | for (const auto pipe : pipelines) 1205 | device.destroyPipeline(pipe); 1206 | for (const auto shader : shaderModules) 1207 | device.destroyShaderModule(shader); 1208 | device.freeCommandBuffers(pool, cmdbuffer); 1209 | device.destroyCommandPool(pool); 1210 | for (const auto framebuff : framebuffer) 1211 | device.destroyFramebuffer(framebuff); 1212 | for (const auto imv : swapchainImageviews) 1213 | device.destroyImageView(imv); 1214 | device.destroyRenderPass(renderpass); 1215 | device.destroySwapchainKHR(swapchain); 1216 | device.destroy(); 1217 | instance.destroySurfaceKHR(surface); 1218 | #ifdef DEBUG 1219 | if (debugMessenger) { 1220 | DispatchLoaderDynamic stat; 1221 | stat.vkDestroyDebugUtilsMessengerEXT = 1222 | (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr( 1223 | instance, "vkDestroyDebugUtilsMessengerEXT"); 1224 | instance.destroyDebugUtilsMessengerEXT(debugMessenger, nullptr, stat); 1225 | } 1226 | #endif 1227 | instance.destroy(); 1228 | delete shaderAPI; 1229 | } 1230 | 1231 | APILayer *getNewVulkanModule() { return new VulkanGraphicsModule(); } 1232 | 1233 | } // namespace tge::graphics 1234 | -------------------------------------------------------------------------------- /TGEngine/private/graphics/Vulkan/VulkanShaderModule.cpp: -------------------------------------------------------------------------------- 1 | #include "../../../public/graphics/vulkan/VulkanShaderModule.hpp" 2 | #include "../../../public/Error.hpp" 3 | #include "../../../public/Util.hpp" 4 | #include "../../../public/graphics/vulkan/VulkanModuleDef.hpp" 5 | #include "../../../public/graphics/vulkan/VulkanShaderPipe.hpp" 6 | #define ENABLE_OPT 1 7 | #include 8 | #include 9 | #include 10 | 11 | namespace tge::shader { 12 | 13 | using namespace vk; 14 | 15 | #define NO_BINDING_GIVEN 65535 16 | #define NO_LAYOUT_GIVEN 4095 17 | 18 | inline Format getFormatFromElf(const glslang::TType &format) { 19 | if (format.isVector() && 20 | format.getBasicType() == glslang::TBasicType::EbtFloat) { 21 | switch (format.getVectorSize()) { 22 | case 2: 23 | return Format::eR32G32Sfloat; 24 | case 3: 25 | return Format::eR32G32B32Sfloat; 26 | case 4: 27 | return Format::eR32G32B32A32Sfloat; 28 | } 29 | } 30 | throw std::runtime_error(std::string("Couldn't find Format for TType" + 31 | format.getCompleteString())); 32 | } 33 | 34 | inline uint32_t getSizeFromFormat(const Format format) { 35 | switch (format) { 36 | case Format::eR32G32Sfloat: 37 | return 8; 38 | case Format::eR32G32B32Sfloat: 39 | return 12; 40 | case Format::eR32G32B32A32Sfloat: 41 | return 16; 42 | default: 43 | throw std::runtime_error(std::string("Couldn't find size for Format ") + 44 | to_string(format)); 45 | } 46 | } 47 | 48 | struct VertexShaderAnalizer : public permute::ShaderTraverser { 49 | 50 | VulkanShaderPipe *shaderPipe; 51 | std::unordered_set ioVars; 52 | 53 | VertexShaderAnalizer(VulkanShaderPipe *pipe) 54 | : shaderPipe(pipe) { 55 | ioVars.reserve(10); 56 | } 57 | 58 | void visitSymbol(glslang::TIntermSymbol *symbol) { 59 | const auto &qualifier = symbol->getQualifier(); 60 | if (ioVars.contains(symbol->getId())) 61 | return; 62 | ioVars.emplace(symbol->getId()); 63 | if (qualifier.layoutLocation < NO_LAYOUT_GIVEN) { 64 | if (qualifier.storage == glslang::TStorageQualifier::EvqVaryingIn) { 65 | const auto bind = qualifier.layoutBinding == NO_BINDING_GIVEN 66 | ? 0 67 | : qualifier.layoutBinding; 68 | shaderPipe->vertexInputAttributes.push_back( 69 | VertexInputAttributeDescription( 70 | qualifier.layoutLocation, bind, 71 | getFormatFromElf(symbol->getType()))); 72 | } 73 | } 74 | } 75 | 76 | void postProcess() { 77 | const auto beginItr = shaderPipe->vertexInputAttributes.begin(); 78 | const auto endItr = shaderPipe->vertexInputAttributes.end(); 79 | 80 | for (auto &vert : shaderPipe->vertexInputAttributes) { 81 | for (auto itr = beginItr; itr != endItr; itr++) { 82 | if (itr->location < vert.location && itr->binding == vert.binding) 83 | vert.offset += getSizeFromFormat(itr->format); 84 | } 85 | 86 | auto beginItrBinding = shaderPipe->vertexInputBindings.begin(); 87 | auto endItrBinding = shaderPipe->vertexInputBindings.end(); 88 | auto fitr = std::find_if( 89 | beginItrBinding, endItrBinding, 90 | [bind = vert.binding](auto c) { return c.binding == bind; }); 91 | if (fitr == endItrBinding) { 92 | const auto index = shaderPipe->vertexInputBindings.size(); 93 | shaderPipe->vertexInputBindings.push_back( 94 | VertexInputBindingDescription(vert.binding, 0)); 95 | fitr = shaderPipe->vertexInputBindings.begin() + index; 96 | } 97 | fitr->stride += getSizeFromFormat(vert.format); 98 | } 99 | 100 | shaderPipe->inputStateCreateInfo = PipelineVertexInputStateCreateInfo( 101 | {}, shaderPipe->vertexInputBindings.size(), 102 | shaderPipe->vertexInputBindings.data(), 103 | shaderPipe->vertexInputAttributes.size(), 104 | shaderPipe->vertexInputAttributes.data()); 105 | } 106 | 107 | bool isValid(const permute::GlslSettings &settings) { 108 | return settings.shaderType == EShLanguage::EShLangVertex; 109 | } 110 | }; 111 | 112 | inline std::pair 113 | getDescTypeFromELF(const glslang::TType &type) { 114 | const auto count = type.isArray() ? type.getOuterArraySize() : 1; 115 | if (type.getBasicType() == glslang::TBasicType::EbtSampler) { 116 | const auto sampler = type.getSampler(); 117 | if (sampler.isImageClass() && sampler.isSubpass()) 118 | return std::pair(DescriptorType::eInputAttachment, count); 119 | if (sampler.isPureSampler() || sampler.isCombined()) 120 | return std::pair(DescriptorType::eSampler, count); 121 | return std::pair(DescriptorType::eSampledImage, count); 122 | } else if (type.getBasicType() == glslang::TBasicType::EbtBlock) { 123 | return std::pair(DescriptorType::eUniformBuffer, count); 124 | } 125 | std::cout << type.getQualifier().layoutAttachment << " <- Attachment"; 126 | throw std::runtime_error("Descriptor could not be found for: " + 127 | std::string(type.getCompleteString())); 128 | } 129 | 130 | struct GeneralShaderAnalizer : public permute::ShaderTraverser { 131 | 132 | VulkanShaderPipe *shaderPipe; 133 | ShaderStageFlagBits flags; 134 | std::unordered_set uset; 135 | 136 | GeneralShaderAnalizer(VulkanShaderPipe *pipe) 137 | : shaderPipe(pipe), flags(ShaderStageFlagBits::eVertex) { 138 | shaderPipe->descriptorLayoutBindings.reserve(10); 139 | uset.reserve(10); 140 | } 141 | 142 | void visitSymbol(glslang::TIntermSymbol *symbol) { 143 | const auto &type = symbol->getType(); 144 | std::cout << type.getCompleteString() << std::endl; 145 | const auto &quali = type.getQualifier(); 146 | if (quali.layoutBinding < NO_BINDING_GIVEN) { 147 | if (uset.contains(quali.layoutBinding)) 148 | return; 149 | uset.insert(quali.layoutBinding); 150 | const auto desc = getDescTypeFromELF(type); 151 | const DescriptorSetLayoutBinding descBinding( 152 | quali.layoutBinding, desc.first, desc.second, flags); 153 | shaderPipe->descriptorLayoutBindings.push_back(descBinding); 154 | } 155 | } 156 | 157 | void postProcess() {}; 158 | 159 | bool isValid(const permute::GlslSettings &settings) { 160 | this->flags = (ShaderStageFlagBits)settings.shaderType; 161 | return true; 162 | }; 163 | }; 164 | 165 | struct ShaderInfo { 166 | EShLanguage language; 167 | std::vector code; 168 | std::vector additionalCode; 169 | }; 170 | 171 | ShaderPipe VulkanShaderModule::loadShaderPipeAndCompile( 172 | const std::vector &shadernames, 173 | const std::vector &dependencies) { 174 | std::vector shaderInfos; 175 | for (const auto &name : shadernames) { 176 | const auto glsl = permute::fromFile(name); 177 | shaderInfos.push_back(glsl); 178 | } 179 | return createShaderPipe(shaderInfos.data(), shaderInfos.size(), dependencies); 180 | } 181 | 182 | void __implCreateDescSets(VulkanShaderPipe *shaderPipe, 183 | VulkanShaderModule *vsm) { 184 | graphics::VulkanGraphicsModule *vgm = 185 | (graphics::VulkanGraphicsModule *)vsm->vgm; 186 | 187 | if (!shaderPipe->descriptorLayoutBindings.empty()) { 188 | const DescriptorSetLayoutCreateInfo layoutCreate( 189 | {}, shaderPipe->descriptorLayoutBindings); 190 | const auto descLayout = vgm->device.createDescriptorSetLayout(layoutCreate); 191 | vsm->setLayouts.push_back(descLayout); 192 | std::vector descPoolSizes; 193 | for (const auto &binding : shaderPipe->descriptorLayoutBindings) { 194 | descPoolSizes.push_back( 195 | {binding.descriptorType, binding.descriptorCount}); 196 | } 197 | const DescriptorPoolCreateInfo descPoolCreateInfo({}, 1000, descPoolSizes); 198 | const auto descPool = vgm->device.createDescriptorPool(descPoolCreateInfo); 199 | vsm->descPools.push_back(descPool); 200 | 201 | const auto layoutCreateInfo = PipelineLayoutCreateInfo({}, descLayout); 202 | const auto pipeLayout = vgm->device.createPipelineLayout(layoutCreateInfo); 203 | vsm->pipeLayouts.push_back(pipeLayout); 204 | shaderPipe->layoutID = vsm->pipeLayouts.size() - 1; 205 | } else { 206 | shaderPipe->layoutID = UINT64_MAX; 207 | } 208 | } 209 | 210 | ShaderPipe VulkanShaderModule::createShaderPipe( 211 | ShaderCreateInfo *shaderCreateInfo, const size_t shaderCount, 212 | const std::vector &dependencies) { 213 | VulkanShaderPipe *shaderPipe = new VulkanShaderPipe(); 214 | shaderPipe->shader.reserve(shaderCount); 215 | 216 | GeneralShaderAnalizer gsa(shaderPipe); 217 | VertexShaderAnalizer vsa(shaderPipe); 218 | permute::traverser.push_back(&gsa); 219 | permute::traverser.push_back(&vsa); 220 | 221 | util::OnExit e([p = &permute::traverser]() { p->clear(); }); 222 | 223 | for (size_t i = 0; i < shaderCount; i++) { 224 | auto &perm = shaderCreateInfo[i]; 225 | 226 | if (perm.generate(dependencies)) { 227 | const auto &bin = perm.getBinary(); 228 | shaderPipe->shader.push_back({bin, gsa.flags}); 229 | } 230 | } 231 | return shaderPipe; 232 | } 233 | 234 | void VulkanShaderModule::updateAllTextures() { 235 | std::vector bInfo; 236 | graphics::VulkanGraphicsModule *vgm = 237 | (graphics::VulkanGraphicsModule *)this->vgm; 238 | for (auto nID : textureDesc) { 239 | for (size_t i = 0; i < 5; i++) { 240 | bInfo.push_back({1, nID, BindingType::Texture, {5, UINT64_MAX}, i}); 241 | } 242 | for (size_t i = 5; i < vgm->textureImages.size(); i++) { 243 | bInfo.push_back({1, nID, BindingType::Texture, {i, UINT64_MAX}, i}); 244 | } 245 | for (size_t i = vgm->textureImages.size(); i < 255; i++) { 246 | bInfo.push_back({1, nID, BindingType::Texture, {5, UINT64_MAX}, i}); 247 | } 248 | } 249 | this->bindData(bInfo.data(), bInfo.size()); 250 | } 251 | 252 | size_t VulkanShaderModule::createBindings(ShaderPipe pipe, const size_t count) { 253 | VulkanShaderPipe *shaderPipe = (VulkanShaderPipe *)pipe; 254 | const auto layout = shaderPipe->layoutID; 255 | if (layout == UINT64_MAX) 256 | return UINT64_MAX; 257 | std::vector layouts(count); 258 | std::fill(layouts.begin(), layouts.end(), this->setLayouts[layout]); 259 | const DescriptorSetAllocateInfo allocInfo(this->descPools[layout], count, 260 | layouts.data()); 261 | graphics::VulkanGraphicsModule *vgm = 262 | (graphics::VulkanGraphicsModule *)this->vgm; 263 | const auto sets = vgm->device.allocateDescriptorSets(allocInfo); 264 | const auto nextID = this->descSets.size(); 265 | this->descSets.resize(nextID + count); 266 | std::copy(sets.begin(), sets.end(), this->descSets.begin() + nextID); 267 | 268 | for (size_t i = 0; i < count; i++) { 269 | pipeInfos.push_back({nextID + i, layout}); 270 | } 271 | 272 | std::vector bInfo; 273 | if (defaultbindings.size() > layout) { 274 | auto &bindings = defaultbindings[layout]; 275 | if (!bindings.empty()) { 276 | for (size_t i = 0; i < count; i++) { 277 | const auto nID = nextID + i; 278 | for (auto &b : bindings) { 279 | b.bindingSet = nID; 280 | bInfo.push_back(b); 281 | } 282 | } 283 | for (size_t i = 0; i < count; i++) { 284 | const auto nID = nextID + i; 285 | textureDesc.push_back(nID); 286 | for (size_t i = 0; i < 5; i++) { 287 | bInfo.push_back({1, nID, BindingType::Texture, {5, UINT64_MAX}, i}); 288 | } 289 | for (size_t i = 5; i < vgm->textureImages.size(); i++) { 290 | bInfo.push_back({1, nID, BindingType::Texture, {i, UINT64_MAX}, i}); 291 | } 292 | for (size_t i = vgm->textureImages.size(); i < 255; i++) { 293 | bInfo.push_back({1, nID, BindingType::Texture, {5, UINT64_MAX}, i}); 294 | } 295 | } 296 | 297 | this->bindData(bInfo.data(), bInfo.size()); 298 | } 299 | } 300 | return nextID; 301 | } 302 | 303 | void VulkanShaderModule::changeInputBindings(const ShaderPipe pipe, 304 | const size_t bindingID, 305 | const size_t buffer) {} 306 | 307 | void VulkanShaderModule::bindData(const BindingInfo *info, const size_t count) { 308 | graphics::VulkanGraphicsModule *vgm = 309 | (graphics::VulkanGraphicsModule *)this->vgm; 310 | 311 | std::vector set; 312 | set.reserve(count); 313 | std::vector bufferInfo; 314 | bufferInfo.resize(count); 315 | std::vector imgInfo; 316 | imgInfo.resize(count); 317 | for (size_t i = 0; i < count; i++) { 318 | const auto &cinfo = info[i]; 319 | switch (cinfo.type) { 320 | case BindingType::UniformBuffer: { 321 | const auto &buffI = cinfo.data.buffer; 322 | bufferInfo[i] = (DescriptorBufferInfo(vgm->bufferList[buffI.dataID], 323 | buffI.offset, buffI.size)); 324 | set.push_back(WriteDescriptorSet( 325 | descSets[cinfo.bindingSet], cinfo.binding, 0, 1, 326 | DescriptorType::eUniformBuffer, nullptr, bufferInfo.data() + i)); 327 | } break; 328 | case BindingType::Texture: 329 | case BindingType::Sampler: 330 | case BindingType::InputAttachment: { 331 | const auto &tex = cinfo.data.texture; 332 | imgInfo[i] = DescriptorImageInfo( 333 | tex.sampler == UINT64_MAX ? vk::Sampler() : vgm->sampler[tex.sampler], 334 | tex.texture == UINT64_MAX ? vk::ImageView() 335 | : vgm->textureImageViews[tex.texture], 336 | ImageLayout::eShaderReadOnlyOptimal); 337 | set.push_back(WriteDescriptorSet( 338 | descSets[cinfo.bindingSet], cinfo.binding, cinfo.arrayID, 1, 339 | cinfo.type == BindingType::Texture ? DescriptorType::eSampledImage 340 | : (cinfo.type == BindingType::InputAttachment) 341 | ? DescriptorType::eInputAttachment 342 | : DescriptorType::eSampler, 343 | imgInfo.data() + i)); 344 | } break; 345 | default: 346 | throw std::runtime_error("Can not find descriptor type in bind data!"); 347 | } 348 | } 349 | vgm->device.updateDescriptorSets(set, {}); 350 | } 351 | 352 | void VulkanShaderModule::addToRender(const size_t *bids, const size_t size, 353 | void *customData) { 354 | std::vector sets; 355 | PipelineLayout pipeLayout; 356 | for (size_t i = 0; i < size; i++) { 357 | const auto bindingID = bids[i]; 358 | if (this->pipeInfos.size() > bindingID && bindingID >= 0) { 359 | const auto &bInfo = pipeInfos[bindingID]; 360 | const auto descSet = descSets[bInfo.descSet]; 361 | pipeLayout = pipeLayouts[bInfo.pipeline]; 362 | sets.push_back(descSet); 363 | } 364 | } 365 | ((CommandBuffer *)customData) 366 | ->bindDescriptorSets(PipelineBindPoint::eGraphics, pipeLayout, 0, sets, 367 | {}); 368 | } 369 | 370 | void VulkanShaderModule::addToMaterial(const graphics::Material *material, 371 | void *customData) { 372 | using namespace tge::graphics; 373 | const auto vkPipe = ((VulkanShaderPipe *)material->costumShaderData); 374 | const auto layOut = vkPipe->layoutID; 375 | if (layOut != UINT64_MAX) [[likely]] { 376 | ((GraphicsPipelineCreateInfo *)customData)->setLayout(pipeLayouts[layOut]); 377 | } else { 378 | ((GraphicsPipelineCreateInfo *)customData)->setLayout(defaultLayout); 379 | } 380 | 381 | // LEGACY 382 | if (material->type == MaterialType::TextureOnly) { // Legacy support 383 | const auto texMat = material->data.textureMaterial; 384 | if (layOut == UINT64_MAX) 385 | return; 386 | if (defaultbindings.size() <= layOut) { 387 | defaultbindings.resize(layOut + 1); 388 | } 389 | defaultbindings[layOut] = {{0, 390 | UINT64_MAX, 391 | BindingType::Sampler, 392 | {texMat.textureIndex, texMat.samplerIndex}}}; 393 | } 394 | } 395 | 396 | void VulkanShaderModule::init() { 397 | glslang::InitializeProcess(); 398 | 399 | graphics::VulkanGraphicsModule *vgm = 400 | (graphics::VulkanGraphicsModule *)this->vgm; 401 | if (!vgm->isInitialiazed) 402 | throw std::runtime_error( 403 | "Vulkan module not initalized, Vulkan Shader Module cannot be used!"); 404 | 405 | const DescriptorSetLayoutCreateInfo layoutCreate({}, {}); 406 | defaultDescLayout = vgm->device.createDescriptorSetLayout(layoutCreate); 407 | 408 | const auto layoutCreateInfo = PipelineLayoutCreateInfo({}, defaultDescLayout); 409 | defaultLayout = vgm->device.createPipelineLayout(layoutCreateInfo); 410 | } 411 | 412 | void VulkanShaderModule::destroy() { 413 | glslang::FinalizeProcess(); 414 | graphics::VulkanGraphicsModule *vgm = 415 | (graphics::VulkanGraphicsModule *)this->vgm; 416 | vgm->device.destroyDescriptorSetLayout(defaultDescLayout); 417 | vgm->device.destroyPipelineLayout(defaultLayout); 418 | for (auto pool : descPools) 419 | vgm->device.destroyDescriptorPool(pool); 420 | for (auto dscLayout : setLayouts) 421 | vgm->device.destroyDescriptorSetLayout(dscLayout); 422 | for (auto pipeLayout : pipeLayouts) 423 | vgm->device.destroyPipelineLayout(pipeLayout); 424 | } 425 | 426 | } // namespace tge::shader 427 | -------------------------------------------------------------------------------- /TGEngine/private/graphics/WindowModule.cpp: -------------------------------------------------------------------------------- 1 | #include "..\..\public\graphics\WindowModule.hpp" 2 | #include 3 | #include 4 | #include "..\..\public\Util.hpp" 5 | 6 | #ifdef WIN32 7 | #include 8 | #endif 9 | 10 | namespace tge::graphics { 11 | 12 | #ifdef WIN32 13 | LRESULT CALLBACK callback(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { 14 | if (Msg == WM_CLOSE) { 15 | util::requestExit(); 16 | return 0; 17 | } 18 | return DefWindowProc(hWnd, Msg, wParam, lParam); 19 | } 20 | 21 | main::Error windowsInit(WindowModule *winModule) { 22 | HMODULE systemHandle = GetModuleHandle(nullptr); 23 | if (!systemHandle) 24 | return main::Error::NO_MODULE_HANDLE; 25 | winModule->hInstance = systemHandle; 26 | 27 | const auto windowProperties = winModule->getWindowProperties(); 28 | 29 | WNDCLASSEX wndclass; 30 | FillMemory(&wndclass, sizeof(WNDCLASSEX), 0); 31 | wndclass.cbSize = sizeof(WNDCLASSEX); 32 | wndclass.style = CS_ENABLE | CS_OWNDC | CS_HREDRAW; 33 | wndclass.lpfnWndProc = callback; 34 | wndclass.hInstance = systemHandle; 35 | wndclass.lpszClassName = ENGINE_NAME; 36 | 37 | auto regWndClass = RegisterClassEx(&wndclass); 38 | if (!regWndClass) { 39 | if (GetLastError() != ERROR_CLASS_ALREADY_EXISTS) 40 | return main::Error::COULD_NOT_CREATE_WINDOW_CLASS; 41 | } 42 | 43 | auto window = CreateWindowEx( 44 | WS_EX_APPWINDOW, ENGINE_NAME, APPLICATION_NAME, 45 | WS_CLIPSIBLINGS | WS_CAPTION | WS_SIZEBOX | WS_SYSMENU, 46 | windowProperties.x, windowProperties.y, windowProperties.width, 47 | windowProperties.height, NULL, NULL, systemHandle, NULL); 48 | if (!window) 49 | return main::Error::COULD_NOT_CREATE_WINDOW; 50 | winModule->hWnd = window; 51 | ShowWindow(window, SW_SHOW); 52 | UpdateWindow(window); 53 | return main::Error::NONE; 54 | } 55 | 56 | void windowsPoolMessages(WindowModule *winModule) { 57 | MSG msg; 58 | const HWND wnd = (HWND)winModule->hWnd; 59 | while (PeekMessage(&msg, wnd, 0, 0, PM_REMOVE)) { 60 | TranslateMessage(&msg); 61 | DispatchMessage(&msg); 62 | for(const auto fun : winModule->customFn) 63 | ((WNDPROC)fun)(wnd, msg.message, msg.wParam, msg.lParam); 64 | } 65 | } 66 | 67 | void windowsDestroy(WindowModule *winModule) { 68 | DestroyWindow((HWND)winModule->hWnd); 69 | } 70 | 71 | #endif // WIN32 72 | 73 | main::Error WindowModule::init() { 74 | #ifdef WIN32 75 | osThread = std::thread([winM = this] { 76 | winM->osMutex.lock(); 77 | windowsInit(winM); 78 | winM->osMutex.unlock(); 79 | std::lock_guard lg2(winM->exitMutex); 80 | while (!winM->closing) { 81 | windowsPoolMessages(winM); 82 | } 83 | windowsDestroy(winM); 84 | }); 85 | osThread.detach(); 86 | std::lock_guard lg(this->osMutex); 87 | #endif // WIN32 88 | return main::Error::NONE; 89 | } 90 | 91 | void WindowModule::tick(double deltatime) {} 92 | 93 | void WindowModule::destroy() { 94 | this->closing = true; 95 | std::lock_guard lg(this->exitMutex); 96 | } 97 | 98 | WindowProperties WindowModule::getWindowProperties() { 99 | return WindowProperties(); 100 | } 101 | 102 | } // namespace tge::graphics 103 | -------------------------------------------------------------------------------- /TGEngine/public/Error.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace tge::main { 4 | 5 | enum class Error { 6 | NONE, 7 | ALREADY_RUNNING, 8 | ALREADY_INITIALIZED, 9 | NOT_INITIALIZED, 10 | NO_GRAPHIC_QUEUE_FOUND, 11 | SURFACECREATION_FAILED, 12 | COULD_NOT_CREATE_WINDOW, 13 | COULD_NOT_CREATE_WINDOW_CLASS, 14 | NO_MODULE_HANDLE, 15 | FORMAT_NOT_FOUND, 16 | SWAPCHAIN_EXT_NOT_FOUND, 17 | NO_SURFACE_SUPPORT, 18 | VULKAN_ERROR, 19 | GLTF_LOADER_ERROR, 20 | FORMAT_NOT_SUPPORTED 21 | }; 22 | 23 | extern Error error; 24 | 25 | } // namespace tge::main 26 | -------------------------------------------------------------------------------- /TGEngine/public/IO/IOModule.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Module.hpp" 4 | 5 | namespace tge::io { 6 | 7 | struct KeyboardEvent { 8 | unsigned int signal; 9 | }; 10 | 11 | struct MouseEvent { 12 | int x; 13 | int y; 14 | int pressed; 15 | }; 16 | 17 | class IOModule : public tge::main::Module { 18 | 19 | main::Error init() override; 20 | 21 | public: 22 | virtual void mouseEvent(const MouseEvent event) = 0; 23 | 24 | virtual void keyboardEvent(const KeyboardEvent event) = 0; 25 | }; 26 | 27 | constexpr auto KC_LBUTTON = 0x01; 28 | constexpr auto KC_RBUTTON = 0x02; 29 | constexpr auto KC_CANCEL = 0x03; 30 | constexpr auto KC_MBUTTON = 0x04; /* NOT contiguous with L & RBUTTON */ 31 | constexpr auto KC_XBUTTON1 = 0x05; /* NOT contiguous with L & RBUTTON */ 32 | constexpr auto KC_XBUTTON2 = 0x06; /* NOT contiguous with L & RBUTTON */ 33 | constexpr auto KC_BACK = 0x08; 34 | constexpr auto KC_TAB = 0x09; 35 | constexpr auto KC_CLEAR = 0x0C; 36 | constexpr auto KC_RETURN = 0x0D; 37 | constexpr auto KC_SHIFT = 0x10; 38 | constexpr auto KC_CONTROL = 0x11; 39 | constexpr auto KC_MENU = 0x12; 40 | constexpr auto KC_PAUSE = 0x13; 41 | constexpr auto KC_CAPITAL = 0x14; 42 | constexpr auto KC_KANA = 0x15; 43 | constexpr auto KC_HANGEUL = 0x15; /* old name - should be here for compatibility */ 44 | constexpr auto KC_HANGUL = 0x15; 45 | constexpr auto KC_IME_ON = 0x16; 46 | constexpr auto KC_JUNJA = 0x17; 47 | constexpr auto KC_FINAL = 0x18; 48 | constexpr auto KC_HANJA = 0x19; 49 | constexpr auto KC_KANJI = 0x19; 50 | constexpr auto KC_IME_OFF = 0x1A; 51 | constexpr auto KC_ESCAPE = 0x1B; 52 | constexpr auto KC_CONVERT = 0x1C; 53 | constexpr auto KC_NONCONVERT = 0x1D; 54 | constexpr auto KC_ACCEPT = 0x1E; 55 | constexpr auto KC_MODECHANGE = 0x1F; 56 | constexpr auto KC_SPACE = 0x20; 57 | constexpr auto KC_PRIOR = 0x21; 58 | constexpr auto KC_NEXT = 0x22; 59 | constexpr auto KC_END = 0x23; 60 | constexpr auto KC_HOME = 0x24; 61 | constexpr auto KC_LEFT = 0x25; 62 | constexpr auto KC_UP = 0x26; 63 | constexpr auto KC_RIGHT = 0x27; 64 | constexpr auto KC_DOWN = 0x28; 65 | constexpr auto KC_SELECT = 0x29; 66 | constexpr auto KC_PRINT = 0x2A; 67 | constexpr auto KC_EXECUTE = 0x2B; 68 | constexpr auto KC_SNAPSHOT = 0x2C; 69 | constexpr auto KC_INSERT = 0x2D; 70 | constexpr auto KC_DELETE = 0x2E; 71 | constexpr auto KC_HELP = 0x2F; 72 | 73 | /* 74 | * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39) 75 | * 0x3A - 0x40 : unassigned 76 | * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A) 77 | */ 78 | 79 | constexpr auto KC_LWIN = 0x5B; 80 | constexpr auto KC_RWIN = 0x5C; 81 | constexpr auto KC_APPS = 0x5D; 82 | constexpr auto KC_SLEEP = 0x5F; 83 | constexpr auto KC_NUMPAD0 = 0x60; 84 | constexpr auto KC_NUMPAD1 = 0x61; 85 | constexpr auto KC_NUMPAD2 = 0x62; 86 | constexpr auto KC_NUMPAD3 = 0x63; 87 | constexpr auto KC_NUMPAD4 = 0x64; 88 | constexpr auto KC_NUMPAD5 = 0x65; 89 | constexpr auto KC_NUMPAD6 = 0x66; 90 | constexpr auto KC_NUMPAD7 = 0x67; 91 | constexpr auto KC_NUMPAD8 = 0x68; 92 | constexpr auto KC_NUMPAD9 = 0x69; 93 | constexpr auto KC_MULTIPLY = 0x6A; 94 | constexpr auto KC_ADD = 0x6B; 95 | constexpr auto KC_SEPARATOR = 0x6C; 96 | constexpr auto KC_SUBTRACT = 0x6D; 97 | constexpr auto KC_DECIMAL = 0x6E; 98 | constexpr auto KC_DIVIDE = 0x6F; 99 | constexpr auto KC_F1 = 0x70; 100 | constexpr auto KC_F2 = 0x71; 101 | constexpr auto KC_F3 = 0x72; 102 | constexpr auto KC_F4 = 0x73; 103 | constexpr auto KC_F5 = 0x74; 104 | constexpr auto KC_F6 = 0x75; 105 | constexpr auto KC_F7 = 0x76; 106 | constexpr auto KC_F8 = 0x77; 107 | constexpr auto KC_F9 = 0x78; 108 | constexpr auto KC_F10 = 0x79; 109 | constexpr auto KC_F11 = 0x7A; 110 | constexpr auto KC_F12 = 0x7B; 111 | constexpr auto KC_F13 = 0x7C; 112 | constexpr auto KC_F14 = 0x7D; 113 | constexpr auto KC_F15 = 0x7E; 114 | constexpr auto KC_F16 = 0x7F; 115 | constexpr auto KC_F17 = 0x80; 116 | constexpr auto KC_F18 = 0x81; 117 | constexpr auto KC_F19 = 0x82; 118 | constexpr auto KC_F20 = 0x83; 119 | constexpr auto KC_F21 = 0x84; 120 | constexpr auto KC_F22 = 0x85; 121 | constexpr auto KC_F23 = 0x86; 122 | constexpr auto KC_F24 = 0x87; 123 | constexpr auto KC_NAVIGATION_VIEW = 0x88; // reserved 124 | constexpr auto KC_NAVIGATION_MENU = 0x89; // reserved 125 | constexpr auto KC_NAVIGATION_UP = 0x8A; // reserved 126 | constexpr auto KC_NAVIGATION_DOWN = 0x8B; // reserved 127 | constexpr auto KC_NAVIGATION_LEFT = 0x8C; // reserved 128 | constexpr auto KC_NAVIGATION_RIGHT = 0x8D; // reserved 129 | constexpr auto KC_NAVIGATION_ACCEPT = 0x8E; // reserved 130 | constexpr auto KC_NAVIGATION_CANCEL = 0x8F; // reserved 131 | constexpr auto KC_NUMLOCK = 0x90; 132 | constexpr auto KC_SCROLL = 0x91; 133 | constexpr auto KC_OEM_NEC_EQUAL = 0x92; // '=' key on numpad 134 | constexpr auto KC_OEM_FJ_JISHO = 0x92; // 'Dictionary' key 135 | constexpr auto KC_OEM_FJ_MASSHOU = 0x93; // 'Unregister word' key 136 | constexpr auto KC_OEM_FJ_TOUROKU = 0x94; // 'Register word' key 137 | constexpr auto KC_OEM_FJ_LOYA = 0x95; // 'Left OYAYUBI' key 138 | constexpr auto KC_OEM_FJ_ROYA = 0x96; // 'Right OYAYUBI' key 139 | constexpr auto KC_LSHIFT = 0xA0; 140 | constexpr auto KC_RSHIFT = 0xA1; 141 | constexpr auto KC_LCONTROL = 0xA2; 142 | constexpr auto KC_RCONTROL = 0xA3; 143 | constexpr auto KC_LMENU = 0xA4; 144 | constexpr auto KC_RMENU = 0xA5; 145 | constexpr auto KC_BROWSER_BACK = 0xA6; 146 | constexpr auto KC_BROWSER_FORWARD = 0xA7; 147 | constexpr auto KC_BROWSER_REFRESH = 0xA8; 148 | constexpr auto KC_BROWSER_STOP = 0xA9; 149 | constexpr auto KC_BROWSER_SEARCH = 0xAA; 150 | constexpr auto KC_BROWSER_FAVORITES = 0xAB; 151 | constexpr auto KC_BROWSER_HOME = 0xAC; 152 | constexpr auto KC_VOLUME_MUTE = 0xAD; 153 | constexpr auto KC_VOLUME_DOWN = 0xAE; 154 | constexpr auto KC_VOLUME_UP = 0xAF; 155 | constexpr auto KC_MEDIA_NEXT_TRACK = 0xB0; 156 | constexpr auto KC_MEDIA_PREV_TRACK = 0xB1; 157 | constexpr auto KC_MEDIA_STOP = 0xB2; 158 | constexpr auto KC_MEDIA_PLAY_PAUSE = 0xB3; 159 | constexpr auto KC_LAUNCH_MAIL = 0xB4; 160 | constexpr auto KC_LAUNCH_MEDIA_SELECT = 0xB5; 161 | constexpr auto KC_LAUNCH_APP1 = 0xB6; 162 | constexpr auto KC_LAUNCH_APP2 = 0xB7; 163 | constexpr auto KC_OEM_1 = 0xBA; // ';:' for US 164 | constexpr auto KC_OEM_PLUS = 0xBB; // '+' any country 165 | constexpr auto KC_OEM_COMMA = 0xBC; // ',' any country 166 | constexpr auto KC_OEM_MINUS = 0xBD; // '-' any country 167 | constexpr auto KC_OEM_PERIOD = 0xBE; // '.' any country 168 | constexpr auto KC_OEM_2 = 0xBF; // '/?' for US 169 | constexpr auto KC_OEM_3 = 0xC0; // '`~' for US 170 | constexpr auto KC_GAMEPAD_A = 0xC3; // reserved 171 | constexpr auto KC_GAMEPAD_B = 0xC4; // reserved 172 | constexpr auto KC_GAMEPAD_X = 0xC5; // reserved 173 | constexpr auto KC_GAMEPAD_Y = 0xC6; // reserved 174 | constexpr auto KC_GAMEPAD_RIGHT_SHOULDER = 0xC7; // reserved 175 | constexpr auto KC_GAMEPAD_LEFT_SHOULDER = 0xC8; // reserved 176 | constexpr auto KC_GAMEPAD_LEFT_TRIGGER = 0xC9; // reserved 177 | constexpr auto KC_GAMEPAD_RIGHT_TRIGGER = 0xCA; // reserved 178 | constexpr auto KC_GAMEPAD_DPAD_UP = 0xCB; // reserved 179 | constexpr auto KC_GAMEPAD_DPAD_DOWN = 0xCC; // reserved 180 | constexpr auto KC_GAMEPAD_DPAD_LEFT = 0xCD; // reserved 181 | constexpr auto KC_GAMEPAD_DPAD_RIGHT = 0xCE; // reserved 182 | constexpr auto KC_GAMEPAD_MENU = 0xCF; // reserved 183 | constexpr auto KC_GAMEPAD_VIEW = 0xD0; // reserved 184 | constexpr auto KC_GAMEPAD_LEFT_THUMBSTICK_BUTTON = 0xD1; // reserved 185 | constexpr auto KC_GAMEPAD_RIGHT_THUMBSTICK_BUTTON = 0xD2; // reserved 186 | constexpr auto KC_GAMEPAD_LEFT_THUMBSTICK_UP = 0xD3; // reserved 187 | constexpr auto KC_GAMEPAD_LEFT_THUMBSTICK_DOWN = 0xD4; // reserved 188 | constexpr auto KC_GAMEPAD_LEFT_THUMBSTICK_RIGHT = 0xD5; // reserved 189 | constexpr auto KC_GAMEPAD_LEFT_THUMBSTICK_LEFT = 0xD6; // reserved 190 | constexpr auto KC_GAMEPAD_RIGHT_THUMBSTICK_UP = 0xD7; // reserved 191 | constexpr auto KC_GAMEPAD_RIGHT_THUMBSTICK_DOWN = 0xD8; // reserved 192 | constexpr auto KC_GAMEPAD_RIGHT_THUMBSTICK_RIGHT = 0xD9; // reserved 193 | constexpr auto KC_GAMEPAD_RIGHT_THUMBSTICK_LEFT = 0xDA; // reserved 194 | constexpr auto KC_OEM_4 = 0xDB; // '[{' for US 195 | constexpr auto KC_OEM_5 = 0xDC; // '\|' for US 196 | constexpr auto KC_OEM_6 = 0xDD; // ']}' for US 197 | constexpr auto KC_OEM_7 = 0xDE; // ''"' for US 198 | constexpr auto KC_OEM_8 = 0xDF; 199 | constexpr auto KC_OEM_AX = 0xE1; // 'AX' key on Japanese AX kbd 200 | constexpr auto KC_OEM_102 = 0xE2; // "<>" or "\|" on RT 102-key kbd. 201 | constexpr auto KC_ICO_HELP = 0xE3; // Help key on ICO 202 | constexpr auto KC_ICO_00 = 0xE4; // 00 key on ICO 203 | constexpr auto KC_PROCESSKEY = 0xE5; 204 | constexpr auto KC_ICO_CLEAR = 0xE6; 205 | constexpr auto KC_PACKET = 0xE7; 206 | constexpr auto KC_OEM_RESET = 0xE9; 207 | constexpr auto KC_OEM_JUMP = 0xEA; 208 | constexpr auto KC_OEM_PA1 = 0xEB; 209 | constexpr auto KC_OEM_PA2 = 0xEC; 210 | constexpr auto KC_OEM_PA3 = 0xED; 211 | constexpr auto KC_OEM_WSCTRL = 0xEE; 212 | constexpr auto KC_OEM_CUSEL = 0xEF; 213 | constexpr auto KC_OEM_ATTN = 0xF0; 214 | constexpr auto KC_OEM_FINISH = 0xF1; 215 | constexpr auto KC_OEM_COPY = 0xF2; 216 | constexpr auto KC_OEM_AUTO = 0xF3; 217 | constexpr auto KC_OEM_ENLW = 0xF4; 218 | constexpr auto KC_OEM_BACKTAB = 0xF5; 219 | constexpr auto KC_ATTN = 0xF6; 220 | constexpr auto KC_CRSEL = 0xF7; 221 | constexpr auto KC_EXSEL = 0xF8; 222 | constexpr auto KC_EREOF = 0xF9; 223 | constexpr auto KC_PLAY = 0xFA; 224 | constexpr auto KC_ZOOM = 0xFB; 225 | constexpr auto KC_NONAME = 0xFC; 226 | constexpr auto KC_PA1 = 0xFD; 227 | constexpr auto KC_OEM_CLEAR = 0xFE; 228 | 229 | } // namespace tge::io 230 | -------------------------------------------------------------------------------- /TGEngine/public/Module.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Error.hpp" 4 | 5 | namespace tge::main { 6 | 7 | class Module { 8 | public: 9 | virtual ~Module() {} 10 | 11 | virtual Error init() { return Error::NONE; } 12 | 13 | virtual void tick(double deltatime) {} 14 | 15 | virtual void destroy() {} 16 | }; 17 | 18 | } // namespace tge::main -------------------------------------------------------------------------------- /TGEngine/public/TGEngine.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Error.hpp" 4 | #include "Module.hpp" 5 | #include "graphics/GameGraphicsModule.hpp" 6 | #include 7 | #include 8 | 9 | namespace tge::main { 10 | 11 | extern std::vector lateModules; 12 | 13 | Error init(); 14 | 15 | Error start(); 16 | 17 | Error lastError(); 18 | 19 | graphics::APILayer *getAPILayer(); 20 | 21 | graphics::GameGraphicsModule *getGameGraphicsModule(); 22 | 23 | } // namespace tge::main 24 | -------------------------------------------------------------------------------- /TGEngine/public/Util.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace fs = std::filesystem; 9 | 10 | namespace tge::util { 11 | 12 | template concept Callable = std::is_invocable_v; 13 | template class OnExit { 14 | 15 | const C call; 16 | 17 | public: 18 | constexpr OnExit(const C cin) : call(cin) {} 19 | constexpr ~OnExit() { call(); } 20 | }; 21 | 22 | std::vector wholeFile(const fs::path &path); 23 | 24 | extern bool exitRequest; 25 | 26 | void requestExit(); 27 | 28 | } // namespace tge::util -------------------------------------------------------------------------------- /TGEngine/public/graphics/APILayer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Module.hpp" 4 | #include "Material.hpp" 5 | #include 6 | #include 7 | #include 8 | 9 | namespace tge::shader { 10 | class ShaderAPI; 11 | } 12 | 13 | namespace tge::graphics { 14 | 15 | class GameGraphicsModule; 16 | 17 | enum class IndexSize { UINT16, UINT32, NONE }; 18 | 19 | struct RenderInfo { 20 | std::vector vertexBuffer; 21 | size_t indexBuffer; 22 | size_t materialId; 23 | size_t indexCount; 24 | size_t instanceCount = 1; 25 | size_t indexOffset = 0; 26 | IndexSize indexSize = IndexSize::UINT32; 27 | std::vector vertexOffsets; 28 | size_t bindingID = UINT64_MAX; 29 | }; 30 | 31 | struct TextureInfo { 32 | uint8_t *data = nullptr; 33 | uint32_t size; 34 | uint32_t width; 35 | uint32_t height; 36 | uint32_t channel; 37 | }; 38 | 39 | enum class FilterSetting { NEAREST, LINEAR }; 40 | 41 | enum class AddressMode { 42 | REPEAT, 43 | MIRROR_REPEAT, 44 | CLAMP_TO_EDGE, 45 | CLAMP_TO_BORDER, 46 | MIRROR_CLAMP_TO_EDGE 47 | }; 48 | 49 | struct SamplerInfo { 50 | FilterSetting minFilter; 51 | FilterSetting magFilter; 52 | AddressMode uMode; 53 | AddressMode vMode; 54 | int anisotropy = 0; 55 | }; 56 | 57 | struct Light { 58 | glm::vec3 pos; 59 | float __alignment = 0; 60 | glm::vec3 color; 61 | float intensity; 62 | 63 | Light() = default; 64 | 65 | Light(glm::vec3 pos, glm::vec3 color, float intensity) 66 | : pos(pos), color(color), intensity(intensity) {} 67 | }; 68 | 69 | struct LightMap { 70 | glm::vec3 lightPos; 71 | glm::vec3 direction; 72 | }; 73 | 74 | enum class DataType { IndexData, VertexData, VertexIndexData, Uniform }; 75 | 76 | class APILayer : public main::Module { // Interface 77 | public: 78 | GameGraphicsModule *graphicsModule; 79 | shader::ShaderAPI *shaderAPI; 80 | 81 | void setGameGraphicsModule(GameGraphicsModule *graphicsModule) { 82 | this->graphicsModule = graphicsModule; 83 | } 84 | 85 | virtual ~APILayer() {} 86 | 87 | _NODISCARD virtual void * 88 | loadShader(const MaterialType type) = 0; // Legacy support 89 | 90 | _NODISCARD virtual size_t pushMaterials(const size_t materialcount, 91 | const Material *materials) = 0; 92 | 93 | _NODISCARD virtual size_t pushData(const size_t dataCount, void *data, 94 | const size_t *dataSizes, 95 | const DataType type) = 0; 96 | 97 | virtual void changeData(const size_t bufferIndex, const void *data, 98 | const size_t dataSizes, const size_t offset = 0) = 0; 99 | 100 | void changeData(const size_t bufferIndex, void* data, const size_t dataSizes, 101 | const size_t offset = 0) { 102 | changeData(bufferIndex, (const void *)data, dataSizes, offset); 103 | } 104 | 105 | virtual void pushRender(const size_t renderInfoCount, 106 | const RenderInfo *renderInfos) = 0; 107 | 108 | _NODISCARD virtual size_t pushSampler(const SamplerInfo &sampler) = 0; 109 | 110 | _NODISCARD virtual size_t pushTexture(const size_t textureCount, 111 | const TextureInfo *textures) = 0; 112 | 113 | _NODISCARD virtual size_t pushLights(const size_t lightCount, 114 | const Light *lights, 115 | const size_t offset = 0) = 0; 116 | 117 | _NODISCARD virtual size_t generateLightMaps(const size_t count, 118 | const LightMap *lightMaps) = 0; 119 | 120 | 121 | _NODISCARD GameGraphicsModule *getGraphicsModule() { return graphicsModule; }; 122 | 123 | _NODISCARD shader::ShaderAPI *getShaderAPI() { return this->shaderAPI; } 124 | }; 125 | 126 | } // namespace tge::graphics 127 | -------------------------------------------------------------------------------- /TGEngine/public/graphics/GUIModule.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Module.hpp" 4 | 5 | namespace tge::gui { 6 | 7 | class GUIModule : public tge::main::Module { 8 | 9 | public: 10 | 11 | void *pool; 12 | void *buffer; 13 | void *renderpass; 14 | void *framebuffer; 15 | 16 | main::Error init() override; 17 | 18 | void tick(double deltatime) override; 19 | 20 | void destroy() override; 21 | 22 | virtual void renderGUI() = 0; 23 | }; 24 | 25 | } // namespace tge::gui 26 | -------------------------------------------------------------------------------- /TGEngine/public/graphics/GameGraphicsModule.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../public/Error.hpp" 4 | #include "../../public/Module.hpp" 5 | #include "APILayer.hpp" 6 | #include "GameShaderModule.hpp" 7 | #include "Material.hpp" 8 | #include "WindowModule.hpp" 9 | #include "stdint.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace tge::graphics { 17 | 18 | struct NodeTransform { 19 | glm::vec3 translation = glm::vec3(0.0f, 0.0f, 0.0f); 20 | glm::vec3 scale = glm::vec3(1.0f, 1.0f, 1.0f); 21 | glm::quat rotation = glm::quat(0.0f, 0.0f, 0.0f, 0.0f); 22 | }; 23 | 24 | struct NodeInfo { 25 | size_t bindingID = UINT64_MAX; 26 | NodeTransform transforms = {}; 27 | size_t parent = UINT64_MAX; 28 | }; 29 | 30 | class GameGraphicsModule : public main::Module { 31 | 32 | APILayer *apiLayer; 33 | WindowModule *windowModule; 34 | 35 | glm::mat4 projectionMatrix; 36 | glm::mat4 viewMatrix; 37 | std::vector modelMatrices; 38 | std::vector node; 39 | std::vector parents; 40 | std::vector bindingID; 41 | std::vector status; // jesus fuck not going to use a bool here 42 | 43 | public: 44 | size_t dataID = UINT64_MAX; 45 | size_t defaultMaterial; 46 | tge::shader::ShaderPipe defaultPipe; 47 | 48 | GameGraphicsModule(APILayer *apiLayer, WindowModule *winModule); 49 | 50 | _NODISCARD size_t loadModel(const std::vector &data, const bool binary, 51 | const std::string &baseDir, 52 | void *shaderPipe = nullptr); 53 | 54 | _NODISCARD size_t loadModel(const std::vector &data, 55 | const bool binary) { 56 | return loadModel(data, binary, ""); 57 | } 58 | 59 | _NODISCARD uint32_t loadTextures(const std::vector> &data); 60 | 61 | _NODISCARD uint32_t loadTextures(const std::vector &names); 62 | 63 | _NODISCARD size_t addNode(const NodeInfo *nodeInfos, const size_t count); 64 | 65 | void updateTransform(const size_t nodeID, const NodeTransform &transform); 66 | 67 | void updateViewMatrix(const glm::mat4 matrix) { 68 | this->projectionMatrix = matrix; 69 | } 70 | 71 | void updateCameraMatrix(const glm::mat4 matrix) { this->viewMatrix = matrix; } 72 | 73 | void updateScale(const size_t nodeID, const glm::vec3 scale) { 74 | this->node[nodeID].scale = scale; 75 | this->status[nodeID] = 1; 76 | } 77 | 78 | main::Error init() override; 79 | 80 | void tick(double time) override; 81 | 82 | void destroy() override; 83 | 84 | _NODISCARD APILayer *getAPILayer() { return apiLayer; } 85 | 86 | _NODISCARD WindowModule *getWindowModule() { return windowModule; } 87 | }; 88 | 89 | } // namespace tge::graphics -------------------------------------------------------------------------------- /TGEngine/public/graphics/GameShaderModule.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Material.hpp" 4 | #include 5 | #include 6 | #undef ERROR 7 | #include "../headerlibs/json.hpp" 8 | #define SPR_NO_JSON_HPP_INCLUDE 1 9 | #include 10 | 11 | namespace tge::shader { 12 | 13 | using ShaderCreateInfo = permute::Permute; 14 | 15 | using ShaderPipe = void *; 16 | 17 | enum BindingType { UniformBuffer, Texture, Sampler, InputAttachment }; 18 | 19 | struct BufferBindingData { 20 | size_t dataID; 21 | size_t size; 22 | size_t offset; 23 | }; 24 | 25 | struct TextureBindingData { 26 | size_t texture; 27 | size_t sampler; 28 | }; 29 | 30 | struct BindingInfo { 31 | size_t binding; 32 | size_t bindingSet; 33 | BindingType type; 34 | union BiningData { 35 | BufferBindingData buffer; 36 | TextureBindingData texture; 37 | } data; 38 | size_t arrayID = 0; 39 | }; 40 | 41 | class ShaderAPI { 42 | 43 | public: 44 | virtual ~ShaderAPI() {} 45 | 46 | _NODISCARD virtual ShaderPipe loadShaderPipeAndCompile( 47 | const std::vector &shadernames, 48 | const std::vector &dependencies = {}) = 0; 49 | 50 | _NODISCARD virtual ShaderPipe 51 | createShaderPipe(ShaderCreateInfo *shaderCreateInfo, 52 | const size_t shaderCount, 53 | const std::vector &dependencies = {}) = 0; 54 | 55 | _NODISCARD virtual size_t createBindings(ShaderPipe pipe, 56 | const size_t count = 1) = 0; 57 | 58 | virtual void changeInputBindings(const ShaderPipe pipe, 59 | const size_t bindingID, 60 | const size_t buffer) = 0; 61 | 62 | virtual void updateAllTextures() = 0; 63 | 64 | virtual void bindData(const BindingInfo *info, const size_t count) = 0; 65 | 66 | virtual void addToRender(const size_t *bindingID, const size_t size, 67 | void *customData) = 0; 68 | 69 | virtual void addToMaterial(const graphics::Material *material, 70 | void *customData) = 0; 71 | 72 | virtual void init() = 0; 73 | 74 | virtual void destroy() = 0; 75 | }; 76 | 77 | } // namespace tge::shader 78 | -------------------------------------------------------------------------------- /TGEngine/public/graphics/Material.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace tge::graphics { 6 | 7 | class APILayer; 8 | 9 | using Color = float[4]; 10 | 11 | enum class MaterialType { None, TextureOnly }; 12 | constexpr MaterialType MAX_TYPE = MaterialType::TextureOnly; 13 | 14 | struct TextureMaterial { 15 | uint32_t textureIndex; 16 | uint32_t samplerIndex; 17 | }; 18 | 19 | struct Material { 20 | 21 | Material(const TextureMaterial texture, APILayer *layer); 22 | 23 | Material(void *costumShaderData) : costumShaderData(costumShaderData) {} 24 | 25 | Material() = default; 26 | 27 | MaterialType type = MaterialType::None; 28 | union data { 29 | TextureMaterial textureMaterial; 30 | } data; 31 | void *costumShaderData = nullptr; // API dependent 32 | bool doubleSided = false; 33 | }; 34 | } // namespace tge::graphics 35 | -------------------------------------------------------------------------------- /TGEngine/public/graphics/WindowModule.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Module.hpp" 4 | #include 5 | #include 6 | 7 | namespace tge::graphics { 8 | 9 | struct WindowProperties { 10 | bool centered = false; // Not implemented 11 | int x = 0; // Ignored if centered 12 | int y = 0; // Ignored if centered 13 | char fullscreenmode = 0; // Not implemented 14 | int width = 1000; // Ignored if fullscreenmode != 0 15 | int height = 1000; // Ignored if fullscreenmode != 0 16 | }; 17 | 18 | class WindowModule : public main::Module { 19 | 20 | public: 21 | void *hInstance; 22 | void *hWnd; 23 | std::vector customFn; 24 | bool closeRequest = false; 25 | bool closing = false; 26 | std::thread osThread; 27 | std::mutex osMutex; 28 | std::mutex exitMutex; 29 | 30 | main::Error init() override; 31 | 32 | void tick(double deltatime) override; 33 | 34 | void destroy() override; 35 | 36 | WindowProperties getWindowProperties(); 37 | }; 38 | 39 | } // namespace tge::graphics 40 | -------------------------------------------------------------------------------- /TGEngine/public/graphics/vulkan/VulkanGraphicsModule.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../GameGraphicsModule.hpp" 4 | #include 5 | #include 6 | #include 7 | 8 | #ifndef APPLICATION_NAME 9 | #define APPLICATION_NAME "unknown" 10 | #endif 11 | 12 | #ifndef APPLICATION_VERSION 13 | #define APPLICATION_VERSION VK_MAKE_VERSION(1, 0, 0) 14 | #endif 15 | 16 | namespace tge::graphics { 17 | 18 | APILayer *getNewVulkanModule(); 19 | 20 | } // namespace tge::graphics 21 | -------------------------------------------------------------------------------- /TGEngine/public/graphics/vulkan/VulkanModuleDef.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef WIN32 4 | #include 5 | #define VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL 1 6 | #define VK_USE_PLATFORM_WIN32_KHR 1 7 | #endif // WIN32 8 | #include "../../../public/Module.hpp" 9 | #include "../GameGraphicsModule.hpp" 10 | #include "VulkanShaderModule.hpp" 11 | #include "VulkanShaderPipe.hpp" 12 | #include 13 | #include 14 | 15 | namespace tge::graphics { 16 | 17 | using namespace vk; 18 | 19 | class VulkanGraphicsModule : public APILayer { 20 | 21 | public: 22 | Instance instance; 23 | PhysicalDevice physicalDevice; 24 | Device device; 25 | SurfaceKHR surface; 26 | SurfaceFormatKHR format; 27 | Format depthFormat = Format::eUndefined; 28 | SwapchainKHR swapchain; 29 | std::vector swapchainImages; 30 | RenderPass renderpass; 31 | RenderPass lightRenderpass; 32 | std::vector swapchainImageviews; 33 | std::vector framebuffer; 34 | CommandPool pool; 35 | std::vector cmdbuffer; 36 | std::vector pipelines; 37 | std::vector lightMapPipelines; 38 | Queue queue; 39 | uint32_t queueFamilyIndex; 40 | uint32_t queueIndex; 41 | Semaphore waitSemaphore; 42 | Semaphore signalSemaphore; 43 | Fence commandBufferFence; 44 | std::vector shaderModules; 45 | uint32_t memoryTypeHostVisibleCoherent; 46 | uint32_t memoryTypeDeviceLocal; 47 | std::vector bufferList; 48 | std::vector bufferSizeList; 49 | std::vector bufferMemoryList; 50 | Viewport viewport; 51 | std::vector secondaryCommandBuffer; 52 | std::vector lightCommandBuffer; 53 | std::mutex commandBufferRecording; // protects secondaryCommandBuffer from 54 | // memory invalidation 55 | std::vector sampler; 56 | std::vector textureImages; 57 | std::vector> textureMemorys; 58 | std::vector textureImageViews; 59 | std::vector shaderPipes; 60 | std::vector primary = {CommandBuffer()}; 61 | std::vector renderInfos; 62 | 63 | size_t depthImage; 64 | size_t albedoImage; 65 | size_t normalImage; 66 | size_t roughnessMetallicImage; 67 | size_t position; 68 | 69 | size_t lightData; 70 | size_t lightPipe; 71 | size_t lightBindings; 72 | Material lightMat; 73 | 74 | uint32_t nextImage = 0; 75 | 76 | bool isInitialiazed = false; 77 | bool exitFailed = false; 78 | 79 | struct Lights { 80 | Light lights[50]; 81 | int lightCount; 82 | } lights; 83 | 84 | #ifdef DEBUG 85 | DebugUtilsMessengerEXT debugMessenger; 86 | #endif 87 | 88 | main::Error init() override; 89 | 90 | void tick(double time) override; 91 | 92 | void destroy() override; 93 | 94 | size_t pushMaterials(const size_t materialcount, 95 | const Material *materials) override; 96 | 97 | size_t pushData(const size_t dataCount, void *data, 98 | const size_t *dataSizes, const DataType type) override; 99 | 100 | void changeData(const size_t bufferIndex, const void *data, 101 | const size_t dataSizes, const size_t offset = 0) override; 102 | 103 | void pushRender(const size_t renderInfoCount, 104 | const RenderInfo *renderInfos) override; 105 | 106 | size_t pushSampler(const SamplerInfo &sampler) override; 107 | 108 | size_t pushTexture(const size_t textureCount, 109 | const TextureInfo *textures) override; 110 | 111 | size_t pushLights(const size_t lightCount, const Light *lights, 112 | const size_t offset = 0) override; 113 | 114 | void *loadShader(const MaterialType type) override; 115 | 116 | size_t generateLightMaps(const size_t count, 117 | const LightMap *lightMaps) override; 118 | }; 119 | 120 | } // namespace tge::graphics -------------------------------------------------------------------------------- /TGEngine/public/graphics/vulkan/VulkanShaderModule.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../GameShaderModule.hpp" 4 | #include "VulkanShaderPipe.hpp" 5 | #include 6 | 7 | namespace tge::shader { 8 | 9 | struct BindingPipeInfo { 10 | size_t descSet; 11 | size_t pipeline; 12 | }; 13 | 14 | class VulkanShaderModule : public tge::shader::ShaderAPI { 15 | 16 | public: 17 | explicit VulkanShaderModule(void *vgm) : vgm(vgm) {} 18 | 19 | void *vgm; 20 | std::vector textureDesc; 21 | std::vector descPools; 22 | std::vector pipeLayouts; 23 | std::vector setLayouts; 24 | std::vector descSets; 25 | std::vector pipeInfos; 26 | std::vector shaderPipes; 27 | DescriptorSetLayout defaultDescLayout; 28 | PipelineLayout defaultLayout; 29 | // Legacy support 30 | std::vector> defaultbindings; 31 | 32 | void updateAllTextures() override; 33 | 34 | ShaderPipe loadShaderPipeAndCompile( 35 | const std::vector &shadernames, 36 | const std::vector &dependencies = {}) override; 37 | 38 | ShaderPipe 39 | createShaderPipe(ShaderCreateInfo *shaderCreateInfo, 40 | const size_t shaderCount, 41 | const std::vector &dependencies = {}) override; 42 | 43 | size_t createBindings(ShaderPipe pipe, const size_t count = 1) override; 44 | 45 | void changeInputBindings(const ShaderPipe pipe, const size_t bindingID, 46 | const size_t buffer) override; 47 | 48 | void bindData(const BindingInfo *info, const size_t count) override; 49 | 50 | void addToRender(const size_t *bindingID, const size_t size, 51 | void *customData) override; 52 | 53 | void addToMaterial(const graphics::Material *material, 54 | void *customData) override; 55 | 56 | void init() override; 57 | 58 | void destroy() override; 59 | }; 60 | 61 | } // namespace tge::shader 62 | -------------------------------------------------------------------------------- /TGEngine/public/graphics/vulkan/VulkanShaderPipe.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace tge::shader { 9 | 10 | using namespace vk; 11 | using namespace std::string_literals; 12 | 13 | const std::array shaderNames = { 14 | std::vector({"assets/testvec4.vert"s, "assets/test.frag"s}), 15 | std::vector({"assets/testUV.vert"s, "assets/testTexture.frag"s})}; 16 | 17 | struct VulkanShaderPipe { 18 | std::vector, ShaderStageFlagBits>> shader; 19 | std::vector pipelineShaderStage; 20 | std::vector vertexInputBindings; 21 | std::vector vertexInputAttributes; 22 | PipelineVertexInputStateCreateInfo inputStateCreateInfo; 23 | PipelineRasterizationStateCreateInfo rasterization; 24 | std::vector descriptorLayoutBindings; 25 | size_t layoutID = UINT64_MAX; 26 | }; 27 | 28 | } // namespace tge::graphics 29 | -------------------------------------------------------------------------------- /TGEngine/renderTest/TGRenderTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace tge::main; 11 | using namespace tge::graphics; 12 | 13 | class TableTest : public tge::main::Module { 14 | public: 15 | GameGraphicsModule *ggm; 16 | float rotation = 0; 17 | size_t nodeID; 18 | glm::vec3 direction = glm::vec3(4, -4, 4); 19 | glm::vec3 pos = glm::vec3(4, -4, 4); 20 | Light light = Light({10, 5, 0}, {1, 1, 1}, 0.5f); 21 | bool rotate = false; 22 | 23 | tge::main::Error init() { 24 | ggm = getGameGraphicsModule(); 25 | auto api = ggm->getAPILayer(); 26 | api->pushLights(1, &light); 27 | const auto vec = tge::util::wholeFile("assets/Test/test.gltf"); 28 | nodeID = getGameGraphicsModule()->loadModel(vec, false, "assets/Test/"); 29 | ggm->updateScale(nodeID, glm::vec3(0.2f, 0.2f, 0.2f)); 30 | const LightMap map = {light.pos, glm::vec3(1.0f, 0.0f, 1.0f)}; 31 | api->generateLightMaps(1, &map); 32 | return tge::main::Error::NONE; 33 | } 34 | 35 | void tick(double time) { 36 | if (rotate) { 37 | ggm->updateCameraMatrix( 38 | glm::lookAt(pos, pos - direction, glm::vec3(0, 1, 0))); 39 | } 40 | } 41 | }; 42 | 43 | class TestRenderGUI : public tge::gui::GUIModule { 44 | 45 | public: 46 | float *__tmp; 47 | float *__r; 48 | bool *__rotate; 49 | 50 | float *lightPos; 51 | 52 | void renderGUI() { 53 | ImGui::Begin("test"); 54 | ImGui::SliderFloat3("Dir", __tmp, -2.0f, 2.0f, "%.3f"); 55 | ImGui::SliderFloat3("Position", __r, -4.0f, 4.0f, "%.3f"); 56 | ImGui::SliderFloat3("Light Pos", lightPos, -5, 5, "%.3f"); 57 | ImGui::Checkbox("Rotate", __rotate); 58 | ImGui::End(); 59 | } 60 | }; 61 | 62 | class TestIOMode : public tge::io::IOModule { 63 | public: 64 | TableTest *tt; 65 | int x; 66 | int y; 67 | 68 | TestIOMode(TableTest *tt) : tt(tt) {} 69 | 70 | void mouseEvent(const tge::io::MouseEvent event) { 71 | tt->direction.x -= (event.x - x) * 0.01f; 72 | tt->direction.y += (event.y - y) * 0.01f; 73 | x = event.x; 74 | y = event.y; 75 | } 76 | 77 | void keyboardEvent(const tge::io::KeyboardEvent event) { 78 | float xf = 0; 79 | float yf = 0; 80 | switch (event.signal) { 81 | case 'W': 82 | xf = 0.1f; 83 | break; 84 | case 'A': 85 | yf = 0.1f; 86 | break; 87 | case 'S': 88 | xf = -0.1f; 89 | break; 90 | case 'D': 91 | yf = -0.1f; 92 | break; 93 | case tge::io::KC_F8: 94 | tt->rotate = !tt->rotate; 95 | default: 96 | break; 97 | } 98 | tt->pos += glm::vec3(xf, 0, yf); 99 | } 100 | }; 101 | 102 | int main() { 103 | TableTest *av = new TableTest(); 104 | tge::main::lateModules.push_back(av); 105 | TestRenderGUI *gui = new TestRenderGUI(); 106 | tge::main::lateModules.push_back(gui); 107 | TestIOMode *iotest = new TestIOMode(av); 108 | tge::main::lateModules.push_back(iotest); 109 | 110 | gui->__tmp = &av->direction.x; 111 | gui->__r = &av->pos.x; 112 | gui->__rotate = &av->rotate; 113 | gui->lightPos = &av->light.pos.x; 114 | 115 | const auto res = init(); 116 | if (res != Error::NONE) { 117 | printf("Error in init!"); 118 | return -1; 119 | } 120 | 121 | const auto startRes = start(); 122 | if (startRes != Error::NONE) { 123 | printf("Error in start!"); 124 | return -1; 125 | } 126 | 127 | return (uint32_t)startRes; 128 | } 129 | -------------------------------------------------------------------------------- /TGEngine/test/TGTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define GLM_FORCE_DEPTH_ZERO_TO_ONE 1 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define DEFAULT_TIME (120.0f) 17 | 18 | #define MODEL_TEST 0 19 | 20 | bool hasInit = false; 21 | bool hasTick = false; 22 | bool hasDestroy = false; 23 | 24 | using namespace tge::main; 25 | using namespace tge::graphics; 26 | using namespace tge::util; 27 | 28 | void exitWaitCheck(); 29 | 30 | double alltime = 0; 31 | std::mutex syncMutex; 32 | 33 | inline void waitForTime() { 34 | alltime = 0; 35 | while (alltime < DEFAULT_TIME) 36 | continue; 37 | } 38 | 39 | class TestModule : public tge::main::Module { 40 | Error init() { 41 | hasInit = true; 42 | return Error::NONE; 43 | } 44 | void tick(double time) { 45 | hasTick = true; 46 | alltime += time; 47 | } 48 | void destroy() { hasDestroy = true; } 49 | }; 50 | 51 | int exitCode = 0; 52 | Error err; 53 | 54 | bool testExitRequest = false; 55 | 56 | int main(int argv, char **in) { 57 | auto thr = std::thread([&, rt = &exitCode, exReq = &testExitRequest]() { 58 | syncMutex.lock(); 59 | testing::InitGoogleTest(&argv, in); 60 | *rt = RUN_ALL_TESTS(); 61 | syncMutex.unlock(); 62 | *exReq = true; 63 | requestExit(); 64 | }); 65 | thr.detach(); 66 | while (!testExitRequest) { 67 | syncMutex.lock(); 68 | err = start(); 69 | syncMutex.unlock(); 70 | printf(" "); 71 | } 72 | std::lock_guard guard(syncMutex); 73 | return exitCode; 74 | } 75 | 76 | class TableTest : public tge::main::Module { 77 | public: 78 | GameGraphicsModule *ggm; 79 | float rotation = 0; 80 | size_t nodeID; 81 | glm::vec3 scale = glm::vec3(4, -4, 4); 82 | Light light = Light({10, 5, 0}, {1, 1, 1}, 0.5f); 83 | bool rotate = true; 84 | 85 | void tick(double time) { 86 | if (rotate) { 87 | rotation += (float)time; 88 | const NodeTransform transform = { 89 | {}, scale, glm::toQuat(glm::rotate(rotation, glm::vec3(0, 1, 0)))}; 90 | ggm->updateTransform(nodeID, transform); 91 | } 92 | ggm->getAPILayer()->pushLights(1, &light); 93 | } 94 | }; 95 | 96 | float *__tmp; 97 | float *__r; 98 | bool *__rotate; 99 | 100 | TEST(EngineMain, TestModel) { 101 | tge::main::lateModules.push_back(new TestModule()); 102 | TableTest *av = new TableTest(); 103 | tge::main::lateModules.push_back(av); 104 | 105 | ASSERT_EQ(init(), Error::NONE); 106 | av->ggm = getGameGraphicsModule(); 107 | 108 | __tmp = &av->light.intensity; 109 | __r = &av->light.pos.x; 110 | __rotate = &av->rotate; 111 | 112 | const auto vec = tge::util::wholeFile("assets/Test/test.gltf"); 113 | const auto mdlID = 114 | getGameGraphicsModule()->loadModel(vec, false, "assets/Test/"); 115 | ASSERT_NE(mdlID, UINT64_MAX); 116 | av->nodeID = mdlID; 117 | av->scale = glm::vec3(0.02f, 0.02f, 0.02f); 118 | 119 | syncMutex.unlock(); 120 | waitForTime(); 121 | exitWaitCheck(); 122 | } 123 | 124 | void defaultTestData() { 125 | APILayer *apiLayer = getAPILayer(); 126 | size_t materialOffset; 127 | 128 | std::vector test = {"assets/testvec4.vert", "assets/test.frag"}; 129 | Material mat; 130 | ASSERT_NO_THROW( 131 | mat.costumShaderData = 132 | getAPILayer()->getShaderAPI()->loadShaderPipeAndCompile(test)); 133 | ASSERT_NE(mat.costumShaderData, nullptr); 134 | 135 | ASSERT_NO_THROW(materialOffset = apiLayer->pushMaterials(1, &mat)); 136 | const std::array vertData = {-1.0f, 0.0f, 0.2f, 1.0f, // 137 | 1.0f, 0.0f, 0.2f, 1.0f, // 138 | 1.0f, 1.0f, 0.2f, 1.0f, // 139 | -1.0f, 1.0f, 0.2f, 1.0f, // 140 | // 141 | -1.0f, 0.0f, 0.1f, 1.0f, // 142 | 1.0f, 0.0f, 0.1f, 1.0f, // 143 | 1.0f, 1.0f, 0.1f, 1.0f, // 144 | -1.0f, 1.0f, 0.1f, 1.0f}; 145 | const std::array dptr = {vertData.data()}; 146 | const std::array size = {vertData.size() * sizeof(float)}; 147 | size_t dataOffset; 148 | ASSERT_NO_THROW(dataOffset = 149 | apiLayer->pushData(1, (const uint8_t **)dptr.data(), 150 | size.data(), DataType::VertexData)); 151 | 152 | const std::array indexData = {0, 1, 2, 2, 3, 0}; 153 | const std::array indexdptr = {indexData.data()}; 154 | const std::array indexsize = {indexData.size() * sizeof(int)}; 155 | size_t __dNoDiscard1; 156 | ASSERT_NO_THROW(__dNoDiscard1 = apiLayer->pushData( 157 | 1, (const uint8_t **)indexdptr.data(), indexsize.data(), 158 | DataType::IndexData)); 159 | 160 | RenderInfo renderInfo; 161 | renderInfo.indexBuffer = 1 + dataOffset; 162 | renderInfo.materialId = materialOffset; 163 | renderInfo.indexCount = indexData.size(); 164 | renderInfo.vertexBuffer.push_back(dataOffset); 165 | ASSERT_NO_THROW(apiLayer->pushRender(1, &renderInfo)); 166 | } 167 | 168 | class Avocado2Test : public tge::main::Module { 169 | public: 170 | GameGraphicsModule *ggm; 171 | float rotation = 0; 172 | size_t nodeID; 173 | glm::vec3 scale = glm::vec3(4, -4, 4); 174 | 175 | void tick(double time) { 176 | rotation += (float)time; 177 | const NodeTransform transform = { 178 | {}, scale, glm::toQuat(glm::rotate(rotation, glm::vec3(0, 1, 0)))}; 179 | ggm->updateTransform(nodeID, transform); 180 | } 181 | }; 182 | 183 | TEST(EngineMain, AvocadoTestOne) { 184 | tge::main::lateModules.push_back(new TestModule()); 185 | Avocado2Test *av = new Avocado2Test(); 186 | tge::main::lateModules.push_back(av); 187 | 188 | ASSERT_EQ(init(), Error::NONE); 189 | av->ggm = getGameGraphicsModule(); 190 | 191 | std::vector test = {"assets/avocado.vert", 192 | "assets/testTexture.frag"}; 193 | auto ptr = (tge::shader::VulkanShaderPipe *)getAPILayer() 194 | ->getShaderAPI() 195 | ->loadShaderPipeAndCompile(test); 196 | 197 | const auto vec = tge::util::wholeFile( 198 | "assets/glTF-Sample-Models/2.0/Avocado/glTF/Avocado.gltf"); 199 | const auto mdlID = getGameGraphicsModule()->loadModel( 200 | vec, false, "assets/glTF-Sample-Models/2.0/Avocado/glTF/", ptr); 201 | ASSERT_NE(mdlID, UINT64_MAX); 202 | av->nodeID = mdlID; 203 | 204 | syncMutex.unlock(); 205 | waitForTime(); 206 | exitWaitCheck(); 207 | } 208 | 209 | TEST(ShaderCompiler, Create) { 210 | tge::main::lateModules.push_back(new TestModule()); 211 | 212 | ASSERT_EQ(init(), Error::NONE); 213 | 214 | tge::shader::ShaderCreateInfo sh[2]; 215 | sh[0].__code = "gl_Position = ublock_0.mvp * test;"; 216 | sh[0].inputs.push_back({"test", tge::shader::IOType::VEC4, 0}); 217 | sh[0].outputs.push_back({"testout", tge::shader::IOType::VEC2, 0}); 218 | sh[0].unifromIO.push_back({"mvp", tge::shader::IOType::MAT4, 2}); 219 | sh[0].shaderType = tge::shader::ShaderType::VERTEX; 220 | 221 | sh[1].__code = "color = texture(sampler2D(diffuse, samp), testin);"; 222 | sh[1].outputs.push_back({"color", tge::shader::IOType::VEC4, 0}); 223 | sh[1].inputs.push_back({"testin", tge::shader::IOType::VEC2, 1}); 224 | sh[1].samplerIO.push_back({"samp", tge::shader::SamplerIOType::SAMPLER, 0}); 225 | sh[1].samplerIO.push_back( 226 | {"diffuse", tge::shader::SamplerIOType::TEXTURE, 1}); 227 | sh[1].shaderType = tge::shader::ShaderType::FRAGMENT; 228 | 229 | void *__noDiscard; 230 | ASSERT_NO_THROW(__noDiscard = 231 | getAPILayer()->getShaderAPI()->createShaderPipe(sh, 2)); 232 | 233 | namespace s = tge::shader; 234 | sh[0].__code = ""; 235 | sh[0].instructions = { 236 | {{"ublock_0.mvp", "test"}, 237 | s::IOType::VEC4, 238 | s::InstructionType::MULTIPLY, 239 | "_tmp1"}, 240 | {{"_tmp1"}, s::IOType::VEC4, s::InstructionType::SET, "gl_Position"} 241 | }; 242 | 243 | sh[1].__code = ""; 244 | sh[1].instructions = { 245 | {{"sampler2D(diffuse, samp)", "testin"}, s::IOType::VEC4, s::InstructionType::TEXTURE, "_tmp"}, 246 | {{"_tmp"}, s::IOType::VEC4, s::InstructionType::SET, "color"} 247 | }; 248 | ASSERT_NO_THROW(__noDiscard = 249 | getAPILayer()->getShaderAPI()->createShaderPipe(sh, 2)); 250 | 251 | syncMutex.unlock(); 252 | waitForTime(); 253 | exitWaitCheck(); 254 | } 255 | 256 | TEST(EngineMain, SamplerAndTextures) { 257 | tge::main::lateModules.push_back(new TestModule()); 258 | 259 | ASSERT_EQ(init(), Error::NONE); 260 | 261 | const SamplerInfo sampler = {FilterSetting::NEAREST, FilterSetting::NEAREST, 262 | AddressMode::REPEAT, AddressMode::REPEAT, 0}; 263 | APILayer *apiLayer = getAPILayer(); 264 | 265 | TextureMaterial texMat; 266 | 267 | ASSERT_NO_THROW(texMat.samplerIndex = apiLayer->pushSampler(sampler)); 268 | 269 | size_t __dNoDiscard1 = 0; 270 | ASSERT_ANY_THROW(__dNoDiscard1 = getGameGraphicsModule()->loadTextures( 271 | {"assets/test3c.png"})); 272 | 273 | ASSERT_NO_THROW(texMat.textureIndex = getGameGraphicsModule()->loadTextures( 274 | {"assets/test.png"})); 275 | 276 | const Material mat(texMat, apiLayer); 277 | 278 | size_t materialOffset; 279 | ASSERT_NO_THROW(materialOffset = apiLayer->pushMaterials(1, &mat)); 280 | const std::array vertData = { 281 | 0.0f, 0.0f, -1.0f, 0.0f, 0.2f, 1.0f, // 282 | 1.0f, 0.0f, 1.0f, 0.0f, 0.2f, 1.0f, // 283 | 1.0f, 1.0f, 1.0f, 1.0f, 0.2f, 1.0f, // 284 | 0.0f, 1.0f, -1.0f, 1.0f, 0.2f, 1.0f, // 285 | }; 286 | 287 | const std::array dptr = {vertData.data()}; 288 | const std::array size = {vertData.size() * sizeof(float)}; 289 | size_t dataOffset = -1; 290 | ASSERT_NO_THROW(dataOffset = 291 | apiLayer->pushData(1, (const uint8_t **)dptr.data(), 292 | size.data(), DataType::VertexData)); 293 | 294 | const std::array indexData = {0, 1, 2, 2, 3, 0}; 295 | const std::array indexdptr = {indexData.data()}; 296 | const std::array indexsize = {indexData.size() * sizeof(int)}; 297 | size_t indexBuffer = -1; 298 | ASSERT_NO_THROW( 299 | indexBuffer = apiLayer->pushData(1, (const uint8_t **)indexdptr.data(), 300 | indexsize.data(), DataType::IndexData)); 301 | 302 | RenderInfo renderInfo; 303 | renderInfo.indexBuffer = indexBuffer; 304 | renderInfo.materialId = materialOffset; 305 | renderInfo.indexCount = indexData.size(); 306 | renderInfo.vertexBuffer.push_back(dataOffset); 307 | ASSERT_NO_THROW(apiLayer->pushRender(1, &renderInfo)); 308 | 309 | syncMutex.unlock(); 310 | waitForTime(); 311 | exitWaitCheck(); 312 | } 313 | 314 | TEST(EngineMain, Start) { 315 | tge::main::lateModules.push_back(new TestModule()); 316 | ASSERT_EQ(start(), Error::NOT_INITIALIZED); 317 | ASSERT_EQ(init(), Error::NONE); 318 | 319 | defaultTestData(); 320 | 321 | ASSERT_EQ(init(), Error::ALREADY_INITIALIZED); 322 | syncMutex.unlock(); 323 | } 324 | 325 | TEST(EngineMain, InitAndTickTest) { 326 | ASSERT_TRUE(hasInit); 327 | ASSERT_TRUE(hasTick); 328 | waitForTime(); 329 | ASSERT_EQ(start(), Error::ALREADY_RUNNING); 330 | } 331 | 332 | void exitWaitCheck() { 333 | ASSERT_NO_FATAL_FAILURE(requestExit()); 334 | syncMutex.lock(); 335 | ASSERT_TRUE(hasDestroy); 336 | ASSERT_EQ(err, Error::NONE); 337 | } 338 | 339 | TEST(EngineMain, Exit) { exitWaitCheck(); } 340 | 341 | TEST(EngineMain, Restart) { ASSERT_EQ(lateModules.size(), 0); } 342 | 343 | TEST(EngineMain, SimpleModel) { 344 | tge::main::lateModules.push_back(new TestModule()); 345 | 346 | ASSERT_EQ(init(), Error::NONE); 347 | 348 | const auto data = tge::util::wholeFile("assets/Triangle.gltf"); 349 | ASSERT_FALSE(data.empty()); 350 | ASSERT_NE(getGameGraphicsModule()->loadModel(data, false, "assets"), 351 | UINT64_MAX); 352 | 353 | syncMutex.unlock(); 354 | waitForTime(); 355 | exitWaitCheck(); 356 | } 357 | 358 | TEST(EngineApi, GameAPIChecks) {} 359 | 360 | TEST(EngineApi, GraphicsAPIChecks) { 361 | APILayer *apiLayer = getAPILayer(); 362 | ASSERT_EQ(apiLayer, nullptr); 363 | ASSERT_NO_THROW(apiLayer = getNewVulkanModule()); 364 | ASSERT_NE(apiLayer, nullptr); 365 | const uint8_t data = 1; 366 | const uint8_t *dataptr = &data; 367 | const size_t size = 1; 368 | size_t __dNoDiscard1; 369 | ASSERT_THROW(__dNoDiscard1 = 370 | apiLayer->pushData(1, &dataptr, &size, DataType::VertexData), 371 | std::runtime_error); 372 | tge::graphics::Material mat; 373 | ASSERT_THROW(__dNoDiscard1 = apiLayer->pushMaterials(1, &mat), 374 | std::runtime_error); 375 | 376 | tge::graphics::RenderInfo renderInfo; 377 | ASSERT_THROW(apiLayer->pushRender(1, &renderInfo), std::runtime_error); 378 | 379 | tge::graphics::TextureInfo textureInfo; 380 | ASSERT_THROW(__dNoDiscard1 = apiLayer->pushTexture(1, &textureInfo), 381 | std::runtime_error); 382 | 383 | void *__dNoDiscard2; 384 | for (size_t i = 0; i <= (size_t)MAX_TYPE; i++) { 385 | ASSERT_THROW(__dNoDiscard2 = apiLayer->loadShader((MaterialType)i), 386 | std::runtime_error); 387 | } 388 | 389 | delete apiLayer; 390 | 391 | ASSERT_EQ(init(), Error::NONE); 392 | apiLayer = getAPILayer(); 393 | ASSERT_NE(apiLayer, nullptr); 394 | 395 | for (size_t i = 0; i <= (size_t)MAX_TYPE; i++) { 396 | ASSERT_NO_THROW(__dNoDiscard2 = apiLayer->loadShader((MaterialType)i)); 397 | } 398 | 399 | ASSERT_THROW(__dNoDiscard2 = 400 | apiLayer->loadShader((MaterialType)10000000000000), 401 | std::runtime_error); 402 | 403 | ASSERT_THROW(__dNoDiscard1 = 404 | apiLayer->pushData(0, &dataptr, &size, DataType::VertexData), 405 | std::runtime_error); 406 | ASSERT_THROW(__dNoDiscard1 = apiLayer->pushMaterials(0, &mat), 407 | std::runtime_error); 408 | ASSERT_THROW(apiLayer->pushRender(0, &renderInfo), std::runtime_error); 409 | ASSERT_THROW(__dNoDiscard1 = apiLayer->pushTexture(0, &textureInfo), 410 | std::runtime_error); 411 | 412 | ASSERT_THROW(__dNoDiscard1 = 413 | apiLayer->pushData(1, nullptr, &size, DataType::VertexData), 414 | std::runtime_error); 415 | ASSERT_THROW(__dNoDiscard1 = apiLayer->pushData(1, &dataptr, nullptr, 416 | DataType::VertexData), 417 | std::runtime_error); 418 | ASSERT_THROW(__dNoDiscard1 = apiLayer->pushMaterials(1, nullptr), 419 | std::runtime_error); 420 | ASSERT_THROW(apiLayer->pushRender(1, nullptr), std::runtime_error); 421 | ASSERT_THROW(__dNoDiscard1 = apiLayer->pushTexture(1, nullptr), 422 | std::runtime_error); 423 | } 424 | 425 | TEST(EngineApi, Exit) { 426 | syncMutex.unlock(); 427 | exitWaitCheck(); 428 | } 429 | 430 | #if MODEL_TEST 431 | TEST(EngineModel, ModelTest) { 432 | const std::string path = "assets/glTF-Sample-Models/2.0/"; 433 | nlohmann::json js; 434 | std::ifstream fstr(path + "model-index.json"); 435 | fstr >> js; 436 | for (const auto &pthObj : js) { 437 | const auto name = pthObj["name"].get(); 438 | std::cout << "==================" << std::endl 439 | << name << std::endl 440 | << "==================" << std::endl; 441 | for (const auto &pair : pthObj["variants"].items()) { 442 | const auto &typname = pair.key(); 443 | if (typname.compare("glTF-Draco") == 0) 444 | continue; 445 | const std::string actualPath = path + name + "/" + typname + "/"; 446 | const std::string actualFile = 447 | actualPath + pair.value().get(); 448 | 449 | tge::main::lateModules.push_back(new TestModule()); 450 | 451 | ASSERT_EQ(init(), Error::NONE); 452 | 453 | const auto data = tge::util::wholeFile(actualFile); 454 | ASSERT_FALSE(data.empty()); 455 | ASSERT_EQ(getGameGraphicsModule()->loadModel( 456 | data, typname.compare("glTF-Binary") == 0, actualPath), 457 | Error::NONE); 458 | 459 | syncMutex.unlock(); 460 | waitForTime(); 461 | exitWaitCheck(); 462 | } 463 | } 464 | } 465 | #endif 466 | -------------------------------------------------------------------------------- /TGEngine/test/assets/Test/apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Troblecodings/TGEngine/9e364840b5db3b3d642c2921264e07b5148783f2/TGEngine/test/assets/Test/apple.png -------------------------------------------------------------------------------- /TGEngine/test/assets/Test/cup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Troblecodings/TGEngine/9e364840b5db3b3d642c2921264e07b5148783f2/TGEngine/test/assets/Test/cup.png -------------------------------------------------------------------------------- /TGEngine/test/assets/Test/plate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Troblecodings/TGEngine/9e364840b5db3b3d642c2921264e07b5148783f2/TGEngine/test/assets/Test/plate.png -------------------------------------------------------------------------------- /TGEngine/test/assets/Test/table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Troblecodings/TGEngine/9e364840b5db3b3d642c2921264e07b5148783f2/TGEngine/test/assets/Test/table.png -------------------------------------------------------------------------------- /TGEngine/test/assets/Test/teapot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Troblecodings/TGEngine/9e364840b5db3b3d642c2921264e07b5148783f2/TGEngine/test/assets/Test/teapot.png -------------------------------------------------------------------------------- /TGEngine/test/assets/Test/test.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Troblecodings/TGEngine/9e364840b5db3b3d642c2921264e07b5148783f2/TGEngine/test/assets/Test/test.bin -------------------------------------------------------------------------------- /TGEngine/test/assets/Test/test.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset" : { 3 | "copyright" : "Jeronimo", 4 | "generator" : "Khronos glTF Blender I/O v1.6.16", 5 | "version" : "2.0" 6 | }, 7 | "scene" : 0, 8 | "scenes" : [ 9 | { 10 | "name" : "Scene", 11 | "nodes" : [ 12 | 0, 13 | 1, 14 | 2, 15 | 3, 16 | 4, 17 | 5, 18 | 6 19 | ] 20 | } 21 | ], 22 | "nodes" : [ 23 | { 24 | "mesh" : 0, 25 | "name" : "Teapot", 26 | "rotation" : [ 27 | 0.6936597228050232, 28 | 0.13724517822265625, 29 | -0.13724519312381744, 30 | 0.6936596035957336 31 | ], 32 | "scale" : [ 33 | 1.320000171661377, 34 | 1.2750002145767212, 35 | 1.0500004291534424 36 | ], 37 | "translation" : [ 38 | -4.825139999389648, 39 | 14.033792495727539, 40 | 4.399777889251709 41 | ] 42 | }, 43 | { 44 | "mesh" : 1, 45 | "name" : "Cup", 46 | "rotation" : [ 47 | 0.6935466527938843, 48 | -0.13781537115573883, 49 | 0.13781540095806122, 50 | 0.6935465931892395 51 | ], 52 | "scale" : [ 53 | 0.5887317657470703, 54 | 0.968550980091095, 55 | 1.0530040264129639 56 | ], 57 | "translation" : [ 58 | -4.592345237731934, 59 | 13.569999694824219, 60 | -3.2338063716888428 61 | ] 62 | }, 63 | { 64 | "mesh" : 2, 65 | "name" : "Apple", 66 | "translation" : [ 67 | 0.9080434441566467, 68 | 13.417152404785156, 69 | -0.0213010311126709 70 | ] 71 | }, 72 | { 73 | "mesh" : 3, 74 | "name" : "Plate", 75 | "translation" : [ 76 | 1.2774605751037598, 77 | 13.399999618530273, 78 | -0.11954818665981293 79 | ] 80 | }, 81 | { 82 | "mesh" : 4, 83 | "name" : "Table", 84 | "scale" : [ 85 | 6, 86 | 0.4000000059604645, 87 | 6 88 | ], 89 | "translation" : [ 90 | 0, 91 | 12, 92 | 0 93 | ] 94 | }, 95 | { 96 | "name" : "Point", 97 | "rotation" : [ 98 | -0.30367815494537354, 99 | -0.011718022637069225, 100 | 0.21186362206935883, 101 | 0.9288466572761536 102 | ], 103 | "translation" : [ 104 | -11.530174255371094, 105 | 32.510169982910156, 106 | -16.003170013427734 107 | ] 108 | }, 109 | { 110 | "name" : "Camera", 111 | "rotation" : [ 112 | -0.019092019647359848, 113 | 0.8237253427505493, 114 | -0.5652461051940918, 115 | -0.04011165350675583 116 | ], 117 | "translation" : [ 118 | -3.568521022796631, 119 | 17.35301399230957, 120 | -29.51756477355957 121 | ] 122 | } 123 | ], 124 | "materials" : [ 125 | { 126 | "doubleSided" : true, 127 | "name" : "teapot", 128 | "pbrMetallicRoughness" : { 129 | "baseColorTexture" : { 130 | "index" : 0 131 | }, 132 | "metallicFactor" : 0, 133 | "roughnessFactor" : 0.5 134 | } 135 | }, 136 | { 137 | "doubleSided" : true, 138 | "name" : "cup", 139 | "pbrMetallicRoughness" : { 140 | "baseColorTexture" : { 141 | "index" : 1 142 | }, 143 | "metallicFactor" : 0, 144 | "roughnessFactor" : 0.5 145 | } 146 | }, 147 | { 148 | "doubleSided" : true, 149 | "name" : "apple", 150 | "pbrMetallicRoughness" : { 151 | "baseColorTexture" : { 152 | "index" : 2 153 | }, 154 | "metallicFactor" : 0, 155 | "roughnessFactor" : 0.5 156 | } 157 | }, 158 | { 159 | "doubleSided" : true, 160 | "name" : "plate", 161 | "pbrMetallicRoughness" : { 162 | "baseColorTexture" : { 163 | "index" : 3 164 | }, 165 | "metallicFactor" : 0, 166 | "roughnessFactor" : 0.5 167 | } 168 | }, 169 | { 170 | "doubleSided" : true, 171 | "name" : "table", 172 | "pbrMetallicRoughness" : { 173 | "baseColorTexture" : { 174 | "index" : 4 175 | }, 176 | "metallicFactor" : 0, 177 | "roughnessFactor" : 0.5 178 | } 179 | } 180 | ], 181 | "meshes" : [ 182 | { 183 | "name" : "Torus", 184 | "primitives" : [ 185 | { 186 | "attributes" : { 187 | "POSITION" : 0, 188 | "NORMAL" : 1, 189 | "TEXCOORD_0" : 2, 190 | "COLOR_0" : 3 191 | }, 192 | "indices" : 4, 193 | "material" : 0 194 | } 195 | ] 196 | }, 197 | { 198 | "name" : "Torus.001", 199 | "primitives" : [ 200 | { 201 | "attributes" : { 202 | "POSITION" : 5, 203 | "NORMAL" : 6, 204 | "TEXCOORD_0" : 7 205 | }, 206 | "indices" : 8, 207 | "material" : 1 208 | } 209 | ] 210 | }, 211 | { 212 | "name" : "Sphere.003", 213 | "primitives" : [ 214 | { 215 | "attributes" : { 216 | "POSITION" : 9, 217 | "NORMAL" : 10, 218 | "TEXCOORD_0" : 11 219 | }, 220 | "indices" : 12, 221 | "material" : 2 222 | } 223 | ] 224 | }, 225 | { 226 | "name" : "Cylinder.006", 227 | "primitives" : [ 228 | { 229 | "attributes" : { 230 | "POSITION" : 13, 231 | "NORMAL" : 14, 232 | "TEXCOORD_0" : 15 233 | }, 234 | "indices" : 16, 235 | "material" : 3 236 | } 237 | ] 238 | }, 239 | { 240 | "name" : "Cube", 241 | "primitives" : [ 242 | { 243 | "attributes" : { 244 | "POSITION" : 17, 245 | "NORMAL" : 18, 246 | "TEXCOORD_0" : 19 247 | }, 248 | "indices" : 20, 249 | "material" : 4 250 | } 251 | ] 252 | } 253 | ], 254 | "textures" : [ 255 | { 256 | "sampler" : 0, 257 | "source" : 0 258 | }, 259 | { 260 | "sampler" : 0, 261 | "source" : 1 262 | }, 263 | { 264 | "sampler" : 0, 265 | "source" : 2 266 | }, 267 | { 268 | "sampler" : 0, 269 | "source" : 3 270 | }, 271 | { 272 | "sampler" : 0, 273 | "source" : 4 274 | } 275 | ], 276 | "images" : [ 277 | { 278 | "mimeType" : "image/png", 279 | "name" : "teapot", 280 | "uri" : "teapot.png" 281 | }, 282 | { 283 | "mimeType" : "image/png", 284 | "name" : "cup", 285 | "uri" : "cup.png" 286 | }, 287 | { 288 | "mimeType" : "image/png", 289 | "name" : "apple", 290 | "uri" : "apple.png" 291 | }, 292 | { 293 | "mimeType" : "image/png", 294 | "name" : "plate", 295 | "uri" : "plate.png" 296 | }, 297 | { 298 | "mimeType" : "image/png", 299 | "name" : "table", 300 | "uri" : "table.png" 301 | } 302 | ], 303 | "accessors" : [ 304 | { 305 | "bufferView" : 0, 306 | "componentType" : 5126, 307 | "count" : 2244, 308 | "max" : [ 309 | 3.932236909866333, 310 | 1.6588220596313477, 311 | 1.555992841720581 312 | ], 313 | "min" : [ 314 | -1.1579766273498535, 315 | -1.6588209867477417, 316 | -2.3248727321624756 317 | ], 318 | "type" : "VEC3" 319 | }, 320 | { 321 | "bufferView" : 1, 322 | "componentType" : 5126, 323 | "count" : 2244, 324 | "type" : "VEC3" 325 | }, 326 | { 327 | "bufferView" : 2, 328 | "componentType" : 5126, 329 | "count" : 2244, 330 | "type" : "VEC2" 331 | }, 332 | { 333 | "bufferView" : 3, 334 | "componentType" : 5123, 335 | "count" : 2244, 336 | "normalized" : true, 337 | "type" : "VEC4" 338 | }, 339 | { 340 | "bufferView" : 4, 341 | "componentType" : 5123, 342 | "count" : 9084, 343 | "type" : "SCALAR" 344 | }, 345 | { 346 | "bufferView" : 5, 347 | "componentType" : 5126, 348 | "count" : 808, 349 | "max" : [ 350 | 3.782409429550171, 351 | 1.032470703125, 352 | 1.1094865798950195 353 | ], 354 | "min" : [ 355 | -0.8500002026557922, 356 | -1.032470703125, 357 | -0.8071513772010803 358 | ], 359 | "type" : "VEC3" 360 | }, 361 | { 362 | "bufferView" : 6, 363 | "componentType" : 5126, 364 | "count" : 808, 365 | "type" : "VEC3" 366 | }, 367 | { 368 | "bufferView" : 7, 369 | "componentType" : 5126, 370 | "count" : 808, 371 | "type" : "VEC2" 372 | }, 373 | { 374 | "bufferView" : 8, 375 | "componentType" : 5123, 376 | "count" : 3162, 377 | "type" : "SCALAR" 378 | }, 379 | { 380 | "bufferView" : 9, 381 | "componentType" : 5126, 382 | "count" : 1007, 383 | "max" : [ 384 | 0.9999997019767761, 385 | 1.2089776992797852, 386 | 0.9999994039535522 387 | ], 388 | "min" : [ 389 | -0.9999990463256836, 390 | -0.9465193748474121, 391 | -0.9999987483024597 392 | ], 393 | "type" : "VEC3" 394 | }, 395 | { 396 | "bufferView" : 10, 397 | "componentType" : 5126, 398 | "count" : 1007, 399 | "type" : "VEC3" 400 | }, 401 | { 402 | "bufferView" : 11, 403 | "componentType" : 5126, 404 | "count" : 1007, 405 | "type" : "VEC2" 406 | }, 407 | { 408 | "bufferView" : 12, 409 | "componentType" : 5123, 410 | "count" : 4890, 411 | "type" : "SCALAR" 412 | }, 413 | { 414 | "bufferView" : 13, 415 | "componentType" : 5126, 416 | "count" : 296, 417 | "max" : [ 418 | 2.999999523162842, 419 | -0.8377890586853027, 420 | 2.999999523162842 421 | ], 422 | "min" : [ 423 | -2.999999523162842, 424 | -1, 425 | -2.999999523162842 426 | ], 427 | "type" : "VEC3" 428 | }, 429 | { 430 | "bufferView" : 14, 431 | "componentType" : 5126, 432 | "count" : 296, 433 | "type" : "VEC3" 434 | }, 435 | { 436 | "bufferView" : 15, 437 | "componentType" : 5126, 438 | "count" : 296, 439 | "type" : "VEC2" 440 | }, 441 | { 442 | "bufferView" : 16, 443 | "componentType" : 5123, 444 | "count" : 1140, 445 | "type" : "SCALAR" 446 | }, 447 | { 448 | "bufferView" : 17, 449 | "componentType" : 5126, 450 | "count" : 104, 451 | "max" : [ 452 | 1, 453 | 1, 454 | 1 455 | ], 456 | "min" : [ 457 | -1, 458 | -30, 459 | -1 460 | ], 461 | "type" : "VEC3" 462 | }, 463 | { 464 | "bufferView" : 18, 465 | "componentType" : 5126, 466 | "count" : 104, 467 | "type" : "VEC3" 468 | }, 469 | { 470 | "bufferView" : 19, 471 | "componentType" : 5126, 472 | "count" : 104, 473 | "type" : "VEC2" 474 | }, 475 | { 476 | "bufferView" : 20, 477 | "componentType" : 5123, 478 | "count" : 156, 479 | "type" : "SCALAR" 480 | } 481 | ], 482 | "bufferViews" : [ 483 | { 484 | "buffer" : 0, 485 | "byteLength" : 26928, 486 | "byteOffset" : 0 487 | }, 488 | { 489 | "buffer" : 0, 490 | "byteLength" : 26928, 491 | "byteOffset" : 26928 492 | }, 493 | { 494 | "buffer" : 0, 495 | "byteLength" : 17952, 496 | "byteOffset" : 53856 497 | }, 498 | { 499 | "buffer" : 0, 500 | "byteLength" : 17952, 501 | "byteOffset" : 71808 502 | }, 503 | { 504 | "buffer" : 0, 505 | "byteLength" : 18168, 506 | "byteOffset" : 89760 507 | }, 508 | { 509 | "buffer" : 0, 510 | "byteLength" : 9696, 511 | "byteOffset" : 107928 512 | }, 513 | { 514 | "buffer" : 0, 515 | "byteLength" : 9696, 516 | "byteOffset" : 117624 517 | }, 518 | { 519 | "buffer" : 0, 520 | "byteLength" : 6464, 521 | "byteOffset" : 127320 522 | }, 523 | { 524 | "buffer" : 0, 525 | "byteLength" : 6324, 526 | "byteOffset" : 133784 527 | }, 528 | { 529 | "buffer" : 0, 530 | "byteLength" : 12084, 531 | "byteOffset" : 140108 532 | }, 533 | { 534 | "buffer" : 0, 535 | "byteLength" : 12084, 536 | "byteOffset" : 152192 537 | }, 538 | { 539 | "buffer" : 0, 540 | "byteLength" : 8056, 541 | "byteOffset" : 164276 542 | }, 543 | { 544 | "buffer" : 0, 545 | "byteLength" : 9780, 546 | "byteOffset" : 172332 547 | }, 548 | { 549 | "buffer" : 0, 550 | "byteLength" : 3552, 551 | "byteOffset" : 182112 552 | }, 553 | { 554 | "buffer" : 0, 555 | "byteLength" : 3552, 556 | "byteOffset" : 185664 557 | }, 558 | { 559 | "buffer" : 0, 560 | "byteLength" : 2368, 561 | "byteOffset" : 189216 562 | }, 563 | { 564 | "buffer" : 0, 565 | "byteLength" : 2280, 566 | "byteOffset" : 191584 567 | }, 568 | { 569 | "buffer" : 0, 570 | "byteLength" : 1248, 571 | "byteOffset" : 193864 572 | }, 573 | { 574 | "buffer" : 0, 575 | "byteLength" : 1248, 576 | "byteOffset" : 195112 577 | }, 578 | { 579 | "buffer" : 0, 580 | "byteLength" : 832, 581 | "byteOffset" : 196360 582 | }, 583 | { 584 | "buffer" : 0, 585 | "byteLength" : 312, 586 | "byteOffset" : 197192 587 | } 588 | ], 589 | "samplers" : [ 590 | { 591 | "magFilter" : 9729, 592 | "minFilter" : 9987 593 | } 594 | ], 595 | "buffers" : [ 596 | { 597 | "byteLength" : 197504, 598 | "uri" : "test.bin" 599 | } 600 | ] 601 | } 602 | -------------------------------------------------------------------------------- /TGEngine/test/assets/Triangle.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "scene" : 0, 3 | "scenes" : [ 4 | { 5 | "nodes" : [ 0 ] 6 | } 7 | ], 8 | 9 | "nodes" : [ 10 | { 11 | "mesh" : 0 12 | } 13 | ], 14 | 15 | "meshes" : [ 16 | { 17 | "primitives" : [ { 18 | "attributes" : { 19 | "POSITION" : 1 20 | }, 21 | "indices" : 0 22 | } ] 23 | } 24 | ], 25 | 26 | "buffers" : [ 27 | { 28 | "uri" : "simpleTriangle.bin", 29 | "byteLength" : 44 30 | } 31 | ], 32 | "bufferViews" : [ 33 | { 34 | "buffer" : 0, 35 | "byteOffset" : 0, 36 | "byteLength" : 6, 37 | "target" : 34963 38 | }, 39 | { 40 | "buffer" : 0, 41 | "byteOffset" : 8, 42 | "byteLength" : 36, 43 | "target" : 34962 44 | } 45 | ], 46 | "accessors" : [ 47 | { 48 | "bufferView" : 0, 49 | "byteOffset" : 0, 50 | "componentType" : 5123, 51 | "count" : 3, 52 | "type" : "SCALAR", 53 | "max" : [ 2 ], 54 | "min" : [ 0 ] 55 | }, 56 | { 57 | "bufferView" : 1, 58 | "byteOffset" : 0, 59 | "componentType" : 5126, 60 | "count" : 3, 61 | "type" : "VEC3", 62 | "max" : [ 1.0, 1.0, 0.0 ], 63 | "min" : [ 0.0, 0.0, 0.0 ] 64 | } 65 | ], 66 | 67 | "asset" : { 68 | "version" : "2.0" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /TGEngine/test/assets/avocado.vert: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | layout(location=0) in vec4 TAN; 4 | layout(location=1) in vec3 NORMAL; 5 | layout(location=2) in vec3 POSIN; 6 | layout(location=3) in vec2 UV; 7 | 8 | layout(location=0) out vec2 UVOUT; 9 | 10 | layout(binding=2) uniform MVP { 11 | mat4 matrix; 12 | } mvp; 13 | 14 | out gl_PerVertex { 15 | vec4 gl_Position; 16 | }; 17 | 18 | void main() { 19 | UVOUT = UV; 20 | gl_Position = mvp.matrix * vec4(POSIN, 1); 21 | } 22 | -------------------------------------------------------------------------------- /TGEngine/test/assets/lightPass.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_KHR_vulkan_glsl: enable 3 | 4 | layout(input_attachment_index=0, set=0, binding = 0) uniform subpassInput ALBEDO; 5 | layout(input_attachment_index=1, set=0, binding = 1) uniform subpassInput NORMAL; 6 | layout(input_attachment_index=2, set=0, binding = 2) uniform subpassInput ROUGHNESS_METALLIC; 7 | layout(input_attachment_index=3, set=0, binding = 3) uniform subpassInput POSITION; 8 | 9 | struct Light { 10 | vec3 pos; 11 | vec3 color; 12 | float intensity; 13 | }; 14 | 15 | layout(set=0, binding = 4) uniform _TMP { 16 | Light light[50]; 17 | int lightCount; 18 | } lights; 19 | 20 | layout(location=0) out vec4 colorout; 21 | 22 | void main() { 23 | vec3 color = subpassLoad(ALBEDO).rgb; 24 | vec3 normal = normalize(subpassLoad(NORMAL).rgb); 25 | vec3 pos = subpassLoad(POSITION).rgb; 26 | vec2 roughnessMetallic = subpassLoad(ROUGHNESS_METALLIC).rg; 27 | 28 | vec3 multiplier = vec3(0.05f, 0.05f, 0.05f); 29 | for(int x = 0; x < lights.lightCount; x++) { 30 | Light lightInfo = lights.light[x]; 31 | vec3 diff = lightInfo.pos - pos; 32 | vec3 l = normalize(lightInfo.pos); 33 | float refl = dot(normal, l); 34 | multiplier += lightInfo.color * refl * lightInfo.intensity; 35 | } 36 | colorout = vec4(color * multiplier, 1); 37 | } 38 | -------------------------------------------------------------------------------- /TGEngine/test/assets/lightPass.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_KHR_vulkan_glsl: enable 3 | 4 | out gl_PerVertex { 5 | vec4 gl_Position; 6 | }; 7 | 8 | void main() { 9 | gl_Position = vec4(vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2) * 2.0f - 1.0f, 0.0f, 1.0f); 10 | } 11 | -------------------------------------------------------------------------------- /TGEngine/test/assets/simpleTriangle.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Troblecodings/TGEngine/9e364840b5db3b3d642c2921264e07b5148783f2/TGEngine/test/assets/simpleTriangle.bin -------------------------------------------------------------------------------- /TGEngine/test/assets/test.frag: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | layout(location=0) out vec4 COLOR; 4 | layout(location=1) out vec4 NORMAL; 5 | layout(location=2) out float ROUGHNESS; 6 | layout(location=3) out float METALLIC; 7 | 8 | void main() { 9 | COLOR = vec4(1, 0, 0, 1); 10 | NORMAL = vec4(1, 1, 1, 1); 11 | ROUGHNESS = 0; 12 | METALLIC = 0; 13 | } 14 | -------------------------------------------------------------------------------- /TGEngine/test/assets/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Troblecodings/TGEngine/9e364840b5db3b3d642c2921264e07b5148783f2/TGEngine/test/assets/test.png -------------------------------------------------------------------------------- /TGEngine/test/assets/test.vert: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | layout(location=0) in vec3 inpos; 4 | 5 | layout(binding=2) uniform TEST { 6 | mat4 matrix; 7 | } test; 8 | 9 | out gl_PerVertex { 10 | vec4 gl_Position; 11 | }; 12 | 13 | void main() { 14 | gl_Position = test.matrix * vec4(inpos, 1); 15 | } 16 | -------------------------------------------------------------------------------- /TGEngine/test/assets/test3c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Troblecodings/TGEngine/9e364840b5db3b3d642c2921264e07b5148783f2/TGEngine/test/assets/test3c.png -------------------------------------------------------------------------------- /TGEngine/test/assets/testLight.frag: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | layout(location=0) in vec2 UV; 4 | 5 | layout(location=0) out vec4 COLOR; 6 | layout(location=1) out vec4 NORMAL; 7 | layout(location=2) out float ROUGHNESS; 8 | layout(location=3) out float METALLIC; 9 | 10 | layout(binding=0) uniform sampler SAMP; 11 | layout(binding=1) uniform texture2D TEX; 12 | 13 | void main() { 14 | color = texture(sampler2D(tex, samp), uv); 15 | NORMAL = vec4(1, 1, 1, 1); 16 | ROUGHNESS = 0; 17 | METALLIC = 0; 18 | } 19 | -------------------------------------------------------------------------------- /TGEngine/test/assets/testLight.vert: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | layout(location=0) in vec4 COLOR_0; 4 | layout(location=1) in vec3 NORMAL; 5 | layout(location=2) in vec3 POSITION; 6 | layout(location=3) in vec2 TEXCOORD_0; 7 | 8 | layout(location=0) out vec2 UVOUT; 9 | 10 | layout(binding=2) uniform MVP { 11 | mat4 matrix; 12 | } mvp; 13 | 14 | out gl_PerVertex { 15 | vec4 gl_Position; 16 | }; 17 | 18 | void main() { 19 | UVOUT = TEXCOORD_0; 20 | gl_Position = mvp.matrix * vec4(POSITION, 1); 21 | } 22 | -------------------------------------------------------------------------------- /TGEngine/test/assets/testTexture.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_KHR_vulkan_glsl: enable 3 | 4 | layout(binding=0) uniform sampler samp; 5 | layout(binding=1) uniform texture2D tex; 6 | 7 | layout(location=0) in vec2 uv; 8 | 9 | layout(location=0) out vec4 COLOR; 10 | layout(location=1) out vec4 NORMAL; 11 | layout(location=2) out float ROUGHNESS; 12 | layout(location=3) out float METALLIC; 13 | 14 | void main() { 15 | COLOR = texture(sampler2D(tex, samp), uv); 16 | NORMAL = vec4(1, 1, 1, 1); 17 | ROUGHNESS = 0; 18 | METALLIC = 0; 19 | } 20 | -------------------------------------------------------------------------------- /TGEngine/test/assets/testUV.vert: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | layout(location=0) in vec2 uv; 4 | layout(location=1) in vec4 inpos; 5 | 6 | layout(location=0) out vec2 uvOut; 7 | 8 | out gl_PerVertex { 9 | vec4 gl_Position; 10 | }; 11 | 12 | void main() { 13 | gl_Position = inpos; 14 | uvOut = uv; 15 | } 16 | -------------------------------------------------------------------------------- /TGEngine/test/assets/testvec4.vert: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | layout(location=0) in vec4 inpos; 4 | 5 | out gl_PerVertex { 6 | vec4 gl_Position; 7 | }; 8 | 9 | void main() { 10 | gl_Position = inpos; 11 | } 12 | -------------------------------------------------------------------------------- /install.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | python setup.py 1 0 -------------------------------------------------------------------------------- /setup.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | python setup.py 3 | pause -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import zipfile 2 | import traceback 3 | import os 4 | import os.path 5 | import urllib.request 6 | import sys 7 | import subprocess 8 | import struct 9 | import shutil 10 | from shutil import copyfile 11 | import platform 12 | 13 | osn = platform.system() 14 | if osn == "Windows": 15 | def clear(): 16 | os.system("cls") 17 | else: 18 | def clear(): 19 | os.system("clear") 20 | 21 | 22 | vulkan = os.getenv("VULKAN_SDK") 23 | dependencies_file = None 24 | msg = None 25 | 26 | 27 | def isValidFile(name): 28 | return name.endswith(".h") or name.endswith(".xml") or name.endswith( 29 | ".hpp") or name.endswith(".md") or name.endswith( 30 | ".cpp") or name.endswith(".c") or name.endswith( 31 | ".bat") or name.endswith(".py") or name.endswith( 32 | ".html") or name.endswith(".cs") 33 | 34 | 35 | def wrt(vk, src, tp=""): 36 | print(".", end="", flush=True) 37 | dependencies_file.write(vk + src, 38 | arcname=tp + src, 39 | compress_type=zipfile.ZIP_DEFLATED) 40 | 41 | 42 | def wrtdir(vk, src, tp=""): 43 | for str2 in os.listdir(vk + src): 44 | if os.path.isdir(vk + src + str2): 45 | wrtdir(vk, src + str2 + "\\", tp) 46 | else: 47 | wrt(vk, src + str2, tp) 48 | 49 | 50 | files = 0 51 | loc = 0 52 | 53 | 54 | def find(path): 55 | global files 56 | global loc 57 | global msg 58 | data = os.listdir(path) 59 | for file in data: 60 | if "stb" not in path and "dependencies" not in path and "fbx" not in path and os.path.isdir( 61 | path + "/" + file): 62 | find(path + "/" + file) 63 | elif isValidFile(file): 64 | files += 1 65 | print("#", end="", flush=True) 66 | with open(path + "/" + file, "rb") as fl: 67 | loc += len(fl.readline()) 68 | 69 | 70 | def trigger(id): 71 | global msg 72 | global dependencies_file 73 | global files 74 | global loc 75 | files = 0 76 | loc = 0 77 | try: 78 | if id == 0: 79 | exit(0) 80 | elif id == 1: 81 | print("Starting... this can take a while") 82 | dependencies_file = zipfile.ZipFile("Dependencies.zip", mode="w") 83 | updateSubmodules() 84 | wrtdir(vulkan, "\\Include\\") 85 | wrtdir(vulkan, "\\Lib\\") 86 | wrtdir(vulkan, "\\Lib32\\") 87 | wrtdir(vulkan, "\\Third-Party\\") 88 | wrt(vulkan, "\\LICENSE.txt") 89 | dependencies_file.close() 90 | msg = "Finished!" 91 | clear() 92 | return 93 | elif id == 2: 94 | find(os.getcwd()) 95 | msg = "Found " + str(files) + " files\nWith " + str( 96 | loc) + " lines of code" 97 | clear() 98 | return 99 | except IOError or ValueError: 100 | clear() 101 | print(traceback.format_exc()) 102 | return 103 | 104 | 105 | if len(sys.argv) > 1: 106 | for ids in sys.argv: 107 | try: 108 | trigger(int(ids)) 109 | except ValueError: 110 | continue 111 | 112 | while True: 113 | print("=============================") 114 | print(" DEPENDENCIES 3.0 ") 115 | print("=============================") 116 | print("") 117 | if msg is not None: 118 | print(msg) 119 | print("") 120 | print("1. Get all dependencies") 121 | print("2. Get states") 122 | print("0. Close") 123 | try: 124 | trigger(int(input())) 125 | except ValueError: 126 | clear() 127 | print(traceback.format_exc()) 128 | continue 129 | --------------------------------------------------------------------------------