├── .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 | [](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) | [](https://ci.appveyor.com/project/MrTroble/tgengine) |
30 | | Linux |  |
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 |
--------------------------------------------------------------------------------