├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ └── feature-request.md └── workflows │ └── check.yml ├── .gitignore ├── LICENSE.txt ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── main ├── java └── me │ └── cortex │ └── vulkanite │ ├── acceleration │ ├── AccelerationBlasBuilder.java │ ├── AccelerationManager.java │ ├── AccelerationTLASManager.java │ ├── EntityBlasBuilder.java │ ├── JobPassThroughData.java │ └── SharedQuadVkIndexBuffer.java │ ├── client │ ├── ArbitarySyncPointCallback.java │ ├── Test.java │ ├── Vulkanite.java │ └── rendering │ │ ├── EntityCapture.java │ │ ├── SharedImageViewTracker.java │ │ └── VulkanPipeline.java │ ├── compat │ ├── GeometryData.java │ ├── IAccelerationBuildResult.java │ ├── IGetRaytracingSource.java │ ├── IRenderTargetVkGetter.java │ ├── IVGBuffer.java │ ├── IVGImage.java │ ├── IVulkanContextGetter.java │ ├── RaytracingShaderSet.java │ ├── RaytracingShaderSource.java │ └── SodiumResultAdapter.java │ ├── lib │ ├── base │ │ ├── DeviceProperties.java │ │ ├── TrackedResourceObject.java │ │ ├── VContext.java │ │ └── initalizer │ │ │ ├── VExtensions.java │ │ │ └── VInitializer.java │ ├── cmd │ │ ├── CommandManager.java │ │ ├── VCmdBuff.java │ │ └── VCommandPool.java │ ├── descriptors │ │ ├── DescriptorSetLayoutBuilder.java │ │ ├── DescriptorUpdateBuilder.java │ │ ├── VDescriptorPool.java │ │ ├── VDescriptorSet.java │ │ ├── VDescriptorSetLayout.java │ │ └── VTypedDescriptorPool.java │ ├── memory │ │ ├── HandleDescriptorManger.java │ │ ├── MemoryManager.java │ │ ├── UploadStream.java │ │ ├── VAccelerationStructure.java │ │ ├── VBuffer.java │ │ ├── VGBuffer.java │ │ ├── VGImage.java │ │ ├── VImage.java │ │ └── VmaAllocator.java │ ├── other │ │ ├── FormatConverter.java │ │ ├── VImageView.java │ │ ├── VQueryPool.java │ │ ├── VSampler.java │ │ ├── VUtil.java │ │ └── sync │ │ │ ├── SyncManager.java │ │ │ ├── VFence.java │ │ │ ├── VGSemaphore.java │ │ │ └── VSemaphore.java │ ├── pipeline │ │ ├── ComputePipelineBuilder.java │ │ ├── RaytracePipelineBuilder.java │ │ ├── VComputePipeline.java │ │ └── VRaytracePipeline.java │ └── shader │ │ ├── ShaderCompiler.java │ │ ├── ShaderModule.java │ │ ├── VShader.java │ │ └── reflection │ │ ├── ResourceType.java │ │ └── ShaderReflection.java │ └── mixin │ ├── iris │ ├── MixinCelestialUniforms.java │ ├── MixinCommonUniforms.java │ ├── MixinGlResource.java │ ├── MixinGlTexture.java │ ├── MixinNativeImageBackedTexture.java │ ├── MixinNewWorldRenderingPipeline.java │ ├── MixinPBRAtlasTexture.java │ ├── MixinPackRenderTargetDirectives.java │ ├── MixinProgramSet.java │ ├── MixinRenderTarget.java │ ├── MixinShaderPackSourceNames.java │ ├── MixinShaderStorageBuffer.java │ ├── MixinShaderStorageBufferHolder.java │ ├── MixinStandardMacros.java │ └── ShaderStorageBufferHolderAccessor.java │ ├── minecraft │ ├── MixinAbstractTexture.java │ ├── MixinMinecraftClient.java │ ├── MixinResourceTexture.java │ └── MixinSpriteAtlasTexture.java │ └── sodium │ ├── MixinRenderRegionManager.java │ ├── MixinRenderSection.java │ ├── MixinRenderSectionManager.java │ ├── PendingSectionUploadAccessor.java │ ├── chunk │ ├── MixinChunkBuildResult.java │ ├── MixinChunkRenderRebuildTask.java │ └── VertexFormatAccessor.java │ └── gl │ ├── MixinCommandList.java │ ├── MixinGLRenderDevice.java │ └── MixinMutableBuffer.java └── resources ├── assets └── vulkanite │ └── shaders │ └── include │ └── raylib.glsl ├── fabric.mod.json ├── vulkanite.accesswidener └── vulkanite.mixins.json /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Help me improve the demo pack 4 | title: "[BUG]: " 5 | labels: bug 6 | assignees: BalintCsala 7 | 8 | --- 9 | 10 | You _must_ include the following details: 11 | 12 | - A longer description of the issue (where it occurs, when, can you reproduce it every time, etc.). 13 | - If the issue is a visual glitch, post at least one screenshot of it, 14 | - Your PC specs 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[Feature request]: " 5 | labels: enhancement 6 | assignees: BalintCsala 7 | 8 | --- 9 | 10 | You must include the following things: 11 | 12 | - Longer description of the feature 13 | - What scenarios would this feature improve (preferably post a screenshot, but not a requirement) 14 | 15 | Not including any one of these will result in an immediate deletion of the request. 16 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: Check Build 2 | on: 3 | pull_request: 4 | branches: ['*'] 5 | push: 6 | branches: ['*'] 7 | jobs: 8 | build: 9 | name: Build 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - uses: gradle/wrapper-validation-action@v1 14 | - uses: actions/setup-java@v3 15 | with: 16 | distribution: 'zulu' 17 | java-version: '17' 18 | - uses: actions/cache@v3 19 | with: 20 | path: | 21 | ~/.gradle/caches 22 | ~/.gradle/wrapper 23 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} 24 | - run: ./gradlew build --stacktrace --no-daemon 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/ 3 | 4 | *.iml 5 | *.ipr 6 | *.iws 7 | 8 | # VS Code 9 | .vscode/ 10 | bin/ 11 | 12 | # IntelliJ 13 | out/ 14 | # mpeltonen/sbt-idea plugin 15 | .idea_modules/ 16 | 17 | # JIRA plugin 18 | atlassian-ide-plugin.xml 19 | 20 | # Compiled class file 21 | *.class 22 | 23 | # Log file 24 | *.log 25 | 26 | # BlueJ files 27 | *.ctxt 28 | 29 | # Package Files # 30 | *.jar 31 | *.war 32 | *.nar 33 | *.ear 34 | *.zip 35 | *.tar.gz 36 | *.rar 37 | 38 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 39 | hs_err_pid* 40 | 41 | *~ 42 | 43 | # temporary files which can be created if a process still has a handle open of a deleted file 44 | .fuse_hidden* 45 | 46 | # KDE directory preferences 47 | .directory 48 | 49 | # Linux trash folder which might appear on any partition or disk 50 | .Trash-* 51 | 52 | # .nfs files are created when an open file is removed but is still being accessed 53 | .nfs* 54 | 55 | # General 56 | .DS_Store 57 | .AppleDouble 58 | .LSOverride 59 | 60 | # Icon must end with two \r 61 | Icon 62 | 63 | # Thumbnails 64 | ._* 65 | 66 | # Files that might appear in the root of a volume 67 | .DocumentRevisions-V100 68 | .fseventsd 69 | .Spotlight-V100 70 | .TemporaryItems 71 | .Trashes 72 | .VolumeIcon.icns 73 | .com.apple.timemachine.donotpresent 74 | 75 | # Directories potentially created on remote AFP share 76 | .AppleDB 77 | .AppleDesktop 78 | Network Trash Folder 79 | Temporary Items 80 | .apdisk 81 | 82 | # Windows thumbnail cache files 83 | Thumbs.db 84 | Thumbs.db:encryptable 85 | ehthumbs.db 86 | ehthumbs_vista.db 87 | 88 | # Dump file 89 | *.stackdump 90 | 91 | # Folder config file 92 | [Dd]esktop.ini 93 | 94 | # Recycle Bin used on file shares 95 | $RECYCLE.BIN/ 96 | 97 | # Windows Installer files 98 | *.cab 99 | *.msi 100 | *.msix 101 | *.msm 102 | *.msp 103 | 104 | # Windows shortcuts 105 | *.lnk 106 | 107 | .gradle 108 | build/ 109 | 110 | # Ignore Gradle GUI config 111 | gradle-app.setting 112 | 113 | # Cache of project 114 | .gradletasknamecache 115 | 116 | **/build/ 117 | 118 | # Common working directory 119 | run/ 120 | 121 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 122 | !gradle-wrapper.jar 123 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Work in progress 2 | Minecraft mod that adds hardware raytracing support to minecraft using opengl vulkan interop 3 | 4 | Enables extra passes that shader devs can use with raytracing passes -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'fabric-loom' version '1.2-SNAPSHOT' 3 | id 'maven-publish' 4 | } 5 | 6 | version = project.mod_version 7 | group = project.maven_group 8 | 9 | loom { 10 | accessWidenerPath = file("src/main/resources/vulkanite.accesswidener") 11 | } 12 | 13 | repositories { 14 | exclusiveContent { 15 | forRepository { 16 | maven { 17 | name = "Modrinth" 18 | url = "https://api.modrinth.com/maven" 19 | } 20 | } 21 | filter { 22 | includeGroup "maven.modrinth" 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | // To change the versions see the gradle.properties file 29 | minecraft "com.mojang:minecraft:${project.minecraft_version}" 30 | mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" 31 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" 32 | modImplementation(fabricApi.module("fabric-rendering-fluids-v1", project.fabric_version)) 33 | modImplementation(fabricApi.module("fabric-key-binding-api-v1", project.fabric_version)) 34 | modImplementation(fabricApi.module("fabric-resource-loader-v0", project.fabric_version)) 35 | modImplementation(fabricApi.module("fabric-api-base", project.fabric_version)) 36 | modImplementation(fabricApi.module("fabric-block-view-api-v2", project.fabric_version)) 37 | modImplementation(fabricApi.module("fabric-rendering-fluids-v1", project.fabric_version)) 38 | modImplementation("net.fabricmc.fabric-api:fabric-rendering-data-attachment-v1:0.3.38+73761d2e9a") 39 | modImplementation(fabricApi.module("fabric-resource-loader-v0", project.fabric_version)) 40 | 41 | modImplementation "maven.modrinth:sodium:mc1.20.2-0.5.3" 42 | modImplementation "maven.modrinth:iris:1.6.9+1.20.2" 43 | 44 | modRuntimeOnly 'org.anarres:jcpp:1.4.14' 45 | modRuntimeOnly 'io.github.douira:glsl-transformer:2.0.0-pre13' 46 | 47 | modRuntimeOnly 'net.java.dev.jna:jna:5.9.0' 48 | } 49 | 50 | processResources { 51 | inputs.property "version", project.version 52 | filteringCharset "UTF-8" 53 | 54 | filesMatching("fabric.mod.json") { 55 | expand "version": project.version 56 | } 57 | } 58 | 59 | def targetJavaVersion = 17 60 | tasks.withType(JavaCompile).configureEach { 61 | // ensure that the encoding is set to UTF-8, no matter what the system default is 62 | // this fixes some edge cases with special characters not displaying correctly 63 | // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html 64 | // If Javadoc is generated, this must be specified in that task too. 65 | it.options.encoding = "UTF-8" 66 | if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { 67 | it.options.release = targetJavaVersion 68 | } 69 | } 70 | 71 | java { 72 | def javaVersion = JavaVersion.toVersion(targetJavaVersion) 73 | if (JavaVersion.current() < javaVersion) { 74 | toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) 75 | } 76 | archivesBaseName = project.archives_base_name 77 | // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task 78 | // if it is present. 79 | // If you remove this line, sources will not be generated. 80 | withSourcesJar() 81 | } 82 | 83 | jar { 84 | from("LICENSE") { 85 | rename { "${it}_${project.archivesBaseName}" } 86 | } 87 | } 88 | 89 | // configure the maven publication 90 | publishing { 91 | publications { 92 | mavenJava(MavenPublication) { 93 | from components.java 94 | } 95 | } 96 | 97 | // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. 98 | repositories { 99 | // Add repositories to publish to here. 100 | // Notice: This block does NOT have the same function as the block in the top level. 101 | // The repositories here will be used for publishing your artifact, not for 102 | // retrieving dependencies. 103 | } 104 | } 105 | 106 | 107 | import org.gradle.internal.os.OperatingSystem 108 | 109 | project.ext.lwjglVersion = "3.3.1" 110 | 111 | switch (OperatingSystem.current()) { 112 | case OperatingSystem.LINUX: 113 | def osArch = System.getProperty("os.arch") 114 | project.ext.lwjglNatives = osArch.startsWith("arm") || osArch.startsWith("aarch64") 115 | ? "natives-linux-${osArch.contains("64") || osArch.startsWith("armv8") ? "arm64" : "arm32"}" 116 | : "natives-linux" 117 | break 118 | case OperatingSystem.WINDOWS: 119 | project.ext.lwjglNatives = "natives-windows" 120 | break 121 | } 122 | 123 | repositories { 124 | mavenCentral() 125 | } 126 | project.ext.lwjglNatives = "natives-windows" 127 | 128 | dependencies { 129 | implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion") 130 | 131 | include(implementation("org.lwjgl:lwjgl-meshoptimizer")) 132 | include(implementation("org.lwjgl:lwjgl-vma")) 133 | include(implementation("org.lwjgl:lwjgl-vulkan")) 134 | include(implementation("org.lwjgl:lwjgl-shaderc")) 135 | include(implementation("org.lwjgl:lwjgl-spvc")) 136 | 137 | include(runtimeOnly("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:$lwjglNatives")) 138 | include(runtimeOnly("org.lwjgl:lwjgl-vma:$lwjglVersion:$lwjglNatives")) 139 | include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$lwjglNatives")) 140 | include(runtimeOnly("org.lwjgl:lwjgl-spvc:$lwjglVersion:$lwjglNatives")) 141 | 142 | include(implementation("org.lwjgl:lwjgl-meshoptimizer:$lwjglVersion:$lwjglNatives")) 143 | include(implementation("org.lwjgl:lwjgl-vma:$lwjglVersion:$lwjglNatives")) 144 | include(implementation("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$lwjglNatives")) 145 | include(implementation("org.lwjgl:lwjgl-spvc:$lwjglVersion:$lwjglNatives")) 146 | 147 | 148 | implementation "org.lwjgl:lwjgl" 149 | implementation "org.lwjgl:lwjgl-glfw" 150 | implementation "org.lwjgl:lwjgl-opengl" 151 | runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives" 152 | runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives" 153 | runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives" 154 | } 155 | 156 | 157 | project.ext.lwjglVersion = "3.3.1" 158 | project.ext.jomlVersion = "1.10.4" 159 | project.ext.winNatives = "natives-windows" 160 | project.ext.linuxNatives = "natives-linux" 161 | 162 | dependencies { 163 | include(implementation("org.lwjgl:lwjgl:$lwjglVersion")) 164 | include(implementation("org.lwjgl:lwjgl-vulkan:$lwjglVersion")) 165 | include(implementation("org.lwjgl:lwjgl-vma:$lwjglVersion")) 166 | include(implementation("org.joml:joml:${jomlVersion}")) 167 | include(runtimeOnly("org.lwjgl:lwjgl-vma:$lwjglVersion:$winNatives")) 168 | include(runtimeOnly("org.lwjgl:lwjgl-vma:$lwjglVersion:$linuxNatives")) 169 | 170 | include(implementation("org.lwjgl:lwjgl-glfw:$lwjglVersion")) 171 | include(runtimeOnly("org.lwjgl:lwjgl-glfw:$lwjglVersion:$winNatives")) 172 | include(runtimeOnly("org.lwjgl:lwjgl-glfw:$lwjglVersion:$linuxNatives")) 173 | include(implementation("org.lwjgl:lwjgl-stb:$lwjglVersion")) 174 | include(runtimeOnly("org.lwjgl:lwjgl-stb:$lwjglVersion:$winNatives")) 175 | include(runtimeOnly("org.lwjgl:lwjgl-stb:$lwjglVersion:$linuxNatives")) 176 | include(implementation("org.lwjgl:lwjgl-openal:$lwjglVersion")) 177 | include(runtimeOnly("org.lwjgl:lwjgl-openal:$lwjglVersion:$winNatives")) 178 | include(runtimeOnly("org.lwjgl:lwjgl-openal:$lwjglVersion:$linuxNatives")) 179 | include(runtimeOnly("org.lwjgl:lwjgl:$lwjglVersion:$winNatives")) 180 | include(runtimeOnly("org.lwjgl:lwjgl:$lwjglVersion:$linuxNatives")) 181 | 182 | include(implementation("org.lwjgl:lwjgl-shaderc:$lwjglVersion")) 183 | include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$winNatives")) 184 | include(runtimeOnly("org.lwjgl:lwjgl-shaderc:$lwjglVersion:$linuxNatives")) 185 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Done to increase the memory available to gradle. 2 | org.gradle.jvmargs=-Xmx4G 3 | # Fabric Properties 4 | # check these on https://modmuss50.me/fabric.html 5 | minecraft_version=1.20.2 6 | yarn_mappings=1.20.2+build.1 7 | loader_version=0.14.21 8 | 9 | #Fabric api 10 | fabric_version=0.88.5+1.20.2 11 | # Mod Properties 12 | mod_version=0.0.4-pre-alpha 13 | maven_group=me.cortex 14 | archives_base_name=vulkanite 15 | 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MCRcortex/vulkanite/06e56fbb45e6a132043db21487f89a91393b62c2/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip 4 | networkTimeout=10000 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { 4 | name = 'Fabric' 5 | url = 'https://maven.fabricmc.net/' 6 | } 7 | gradlePluginPortal() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/acceleration/AccelerationManager.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.acceleration; 2 | 3 | import me.cortex.vulkanite.lib.base.VContext; 4 | import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; 5 | import me.cortex.vulkanite.lib.memory.VAccelerationStructure; 6 | import me.cortex.vulkanite.lib.memory.VBuffer; 7 | import me.cortex.vulkanite.lib.other.sync.VSemaphore; 8 | import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; 9 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; 10 | import net.minecraft.client.render.BufferBuilder; 11 | import net.minecraft.client.render.RenderLayer; 12 | import net.minecraft.util.Pair; 13 | 14 | import java.util.LinkedList; 15 | import java.util.List; 16 | import java.util.concurrent.ConcurrentLinkedDeque; 17 | 18 | public class AccelerationManager { 19 | private final VContext ctx; 20 | 21 | private final AccelerationBlasBuilder blasBuilder; 22 | private final ConcurrentLinkedDeque blasResults = new ConcurrentLinkedDeque<>(); 23 | 24 | private final AccelerationTLASManager tlasManager; 25 | 26 | public AccelerationManager(VContext context, int blasBuildQueue) { 27 | this.ctx = context; 28 | this.blasBuilder = new AccelerationBlasBuilder(context, blasBuildQueue, blasResults::add); 29 | this.tlasManager = new AccelerationTLASManager(context, 0);//TODO: pick the main queue or something? (maybe can do the blasBuildQueue) 30 | } 31 | 32 | public void chunkBuilds(List results) { 33 | blasBuilder.enqueue(results); 34 | } 35 | 36 | 37 | public void setEntityData(List> data) { 38 | tlasManager.setEntityData(data); 39 | } 40 | 41 | private final List syncs = new LinkedList<>(); 42 | 43 | //This updates the tlas internal structure, DOES NOT INCLUDING BUILDING THE TLAS 44 | public void updateTick() { 45 | if (!blasResults.isEmpty()) {//If there are results 46 | //Atomicly collect the results from the queue 47 | List results = new LinkedList<>(); 48 | while (!blasResults.isEmpty()) { 49 | var batch = blasResults.poll(); 50 | results.addAll(batch.results()); 51 | syncs.add(batch.semaphore()); 52 | } 53 | tlasManager.updateSections(results); 54 | } 55 | } 56 | 57 | public VAccelerationStructure buildTLAS(VSemaphore inLink, VSemaphore outLink) { 58 | tlasManager.buildTLAS(inLink, outLink, syncs.toArray(new VSemaphore[0])); 59 | syncs.clear(); 60 | return tlasManager.getTlas(); 61 | } 62 | 63 | public void sectionRemove(RenderSection section) { 64 | tlasManager.removeSection(section); 65 | } 66 | 67 | //Cleans up any loose things such as semaphores waiting to be synced etc 68 | public void cleanup() { 69 | //TODO: FIXME: I DONT THINK THIS IS CORRECT OR WORKS, IM STILL LEAKING VRAM MEMORY OUT THE WAZOO WHEN f3+a reloading 70 | ctx.cmd.waitQueueIdle(0); 71 | ctx.cmd.waitQueueIdle(1); 72 | try { 73 | Thread.sleep(250L); 74 | } catch (InterruptedException e) { 75 | e.printStackTrace(); 76 | } 77 | ctx.cmd.waitQueueIdle(0); 78 | ctx.cmd.waitQueueIdle(1); 79 | syncs.forEach(VSemaphore::free); 80 | syncs.clear(); 81 | tlasManager.cleanupTick(); 82 | } 83 | 84 | public long getGeometrySet() { 85 | return tlasManager.getGeometrySet(); 86 | } 87 | 88 | public VDescriptorSetLayout getGeometryLayout() { 89 | return tlasManager.getGeometryLayout(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/acceleration/EntityBlasBuilder.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.acceleration; 2 | 3 | import me.cortex.vulkanite.compat.IVGImage; 4 | import me.cortex.vulkanite.lib.base.VContext; 5 | import me.cortex.vulkanite.lib.cmd.VCmdBuff; 6 | import me.cortex.vulkanite.lib.memory.VAccelerationStructure; 7 | import me.cortex.vulkanite.lib.memory.VBuffer; 8 | import me.cortex.vulkanite.lib.other.VUtil; 9 | import me.cortex.vulkanite.lib.other.sync.VFence; 10 | import net.coderbot.iris.vertices.IrisVertexFormats; 11 | import net.minecraft.client.MinecraftClient; 12 | import net.minecraft.client.render.BufferBuilder; 13 | import net.minecraft.client.render.RenderLayer; 14 | import net.minecraft.client.render.RenderPhase; 15 | import net.minecraft.client.render.VertexFormat; 16 | import net.minecraft.client.texture.TextureManager; 17 | import net.minecraft.util.Pair; 18 | import org.lwjgl.system.MemoryStack; 19 | import org.lwjgl.system.MemoryUtil; 20 | import org.lwjgl.vulkan.*; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; 26 | import static org.lwjgl.vulkan.KHRAccelerationStructure.*; 27 | import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; 28 | import static org.lwjgl.vulkan.KHRBufferDeviceAddress.VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR; 29 | import static org.lwjgl.vulkan.VK10.*; 30 | 31 | public class EntityBlasBuilder { 32 | private final VContext ctx; 33 | public EntityBlasBuilder(VContext context) { 34 | this.ctx = context; 35 | } 36 | 37 | private record BuildInfo(VertexFormat format, int quadCount, long address) {} 38 | Pair buildBlas(List> renders, VCmdBuff cmd, VFence fence) { 39 | long combined_size = 0; 40 | TextureManager textureManager = MinecraftClient.getInstance().getTextureManager(); 41 | for (var type : renders) { 42 | if (((RenderLayer.MultiPhase)type.getLeft()).phases.texture instanceof RenderPhase.Textures) { 43 | throw new IllegalStateException("Multi texture not supported"); 44 | } 45 | var textureId = ((RenderLayer.MultiPhase)type.getLeft()).phases.texture.getId().get(); 46 | var texture = textureManager.getTexture(textureId); 47 | var vkImage = ((IVGImage)texture).getVGImage(); 48 | if (vkImage == null) { 49 | throw new IllegalStateException("Vulkan texture not created for render layer " + type.getLeft()); 50 | } 51 | if (!type.getRight().getParameters().format().equals(IrisVertexFormats.ENTITY)) { 52 | throw new IllegalStateException("Unknown vertex format used"); 53 | } 54 | combined_size += type.getRight().getVertexBuffer().remaining() + 256;//Add just some buffer so we can do alignment etc 55 | } 56 | //Each render layer gets its own geometry entry in the blas 57 | 58 | //TODO: PUT THE BINDLESS TEXTURE REFERENCE AT THE START OF THE render layers geometry buffer 59 | var geometryBuffer = ctx.memory.createBuffer(combined_size, VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 0, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT); 60 | long ptr = geometryBuffer.map(); 61 | long offset = 0; 62 | List infos = new ArrayList<>(); 63 | for (var pair : renders) { 64 | offset = VUtil.alignUp(offset, 128); 65 | MemoryUtil.memCopy(MemoryUtil.memAddress(pair.getRight().getVertexBuffer()), ptr + offset, pair.getRight().getVertexBuffer().remaining()); 66 | infos.add(new BuildInfo(pair.getRight().getParameters().format(), pair.getRight().getParameters().indexCount()/6, geometryBuffer.deviceAddress() + offset)); 67 | 68 | 69 | offset += pair.getRight().getVertexBuffer().remaining(); 70 | } 71 | geometryBuffer.unmap(); 72 | 73 | VAccelerationStructure blas = null; 74 | try (var stack = MemoryStack.stackPush()) { 75 | int[] primitiveCounts = new int[infos.size()]; 76 | var buildInfo = populateBuildStructs(ctx, stack, cmd, infos, primitiveCounts); 77 | 78 | blas = executeBlasBuild(ctx, cmd, fence, stack, buildInfo, primitiveCounts); 79 | } 80 | 81 | 82 | return new Pair<>(blas, geometryBuffer); 83 | } 84 | 85 | private VkAccelerationStructureGeometryKHR.Buffer populateBuildStructs(VContext ctx, MemoryStack stack, VCmdBuff cmdBuff, List geometries, int[] primitiveCounts) { 86 | var geometryInfos = VkAccelerationStructureGeometryKHR.calloc(geometries.size(), stack); 87 | int i = 0; 88 | for (var geometry : geometries) { 89 | VkDeviceOrHostAddressConstKHR indexData = SharedQuadVkIndexBuffer.getIndexBuffer(ctx, cmdBuff, geometry.quadCount); 90 | int indexType = SharedQuadVkIndexBuffer.TYPE; 91 | 92 | VkDeviceOrHostAddressConstKHR vertexData = VkDeviceOrHostAddressConstKHR.calloc(stack).deviceAddress(geometry.address); 93 | int vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; 94 | int vertexStride = geometry.format.getVertexSizeByte(); 95 | 96 | geometryInfos.get() 97 | .sType$Default() 98 | .geometry(VkAccelerationStructureGeometryDataKHR.calloc(stack) 99 | .triangles(VkAccelerationStructureGeometryTrianglesDataKHR.calloc(stack) 100 | .sType$Default() 101 | 102 | .vertexData(vertexData) 103 | .vertexFormat(vertexFormat) 104 | .vertexStride(vertexStride) 105 | .maxVertex(geometry.quadCount * 4) 106 | 107 | .indexData(indexData) 108 | .indexType(indexType))) 109 | .geometryType(VK_GEOMETRY_TYPE_TRIANGLES_KHR) 110 | // .flags(geometry.geometryFlags) 111 | ; 112 | primitiveCounts[i++] = (geometry.quadCount * 2); 113 | } 114 | geometryInfos.rewind(); 115 | return geometryInfos; 116 | } 117 | 118 | private static VAccelerationStructure executeBlasBuild(VContext ctx, VCmdBuff cmd, VFence cleanupFence, MemoryStack stack, VkAccelerationStructureGeometryKHR.Buffer geometryInfos, int[] prims) { 119 | var buildInfos = VkAccelerationStructureBuildGeometryInfoKHR.calloc(1, stack); 120 | var buildRanges = VkAccelerationStructureBuildRangeInfoKHR.calloc(prims.length, stack); 121 | for (int primCount : prims) { 122 | buildRanges.get().primitiveCount(primCount); 123 | } 124 | 125 | var bi = buildInfos.get() 126 | .sType$Default() 127 | .type(VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) 128 | .flags(VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT_KHR) 129 | .pGeometries(geometryInfos) 130 | .geometryCount(geometryInfos.remaining()); 131 | 132 | VkAccelerationStructureBuildSizesInfoKHR buildSizesInfo = VkAccelerationStructureBuildSizesInfoKHR 133 | .calloc(stack) 134 | .sType$Default(); 135 | 136 | vkGetAccelerationStructureBuildSizesKHR( 137 | ctx.device, 138 | VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, 139 | bi, 140 | prims, 141 | buildSizesInfo); 142 | 143 | 144 | var structure = ctx.memory.createAcceleration(buildSizesInfo.accelerationStructureSize(), 256, 145 | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR, VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR); 146 | 147 | var scratch = ctx.memory.createBuffer(buildSizesInfo.buildScratchSize(), 148 | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 149 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 256, 0); 150 | 151 | bi.scratchData(VkDeviceOrHostAddressKHR.calloc(stack).deviceAddress(scratch.deviceAddress())); 152 | bi.dstAccelerationStructure(structure.structure); 153 | 154 | buildInfos.rewind(); 155 | buildRanges.rewind(); 156 | 157 | vkCmdBuildAccelerationStructuresKHR(cmd.buffer, buildInfos, stack.pointers(buildRanges)); 158 | 159 | vkCmdPipelineBarrier(cmd.buffer, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, VkMemoryBarrier.calloc(1) 160 | .sType$Default() 161 | .srcAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR) 162 | .dstAccessMask(VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR), null, null); 163 | 164 | ctx.sync.addCallback(cleanupFence, scratch::free); 165 | return structure; 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/acceleration/JobPassThroughData.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.acceleration; 2 | 3 | import me.cortex.vulkanite.lib.memory.VBuffer; 4 | import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; 5 | 6 | import java.util.List; 7 | 8 | public record JobPassThroughData(RenderSection section, long time, List geometryBuffers) { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/acceleration/SharedQuadVkIndexBuffer.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.acceleration; 2 | 3 | import me.cortex.vulkanite.lib.base.VContext; 4 | import me.cortex.vulkanite.lib.cmd.VCmdBuff; 5 | import me.cortex.vulkanite.lib.memory.VBuffer; 6 | import org.lwjgl.system.MemoryUtil; 7 | import org.lwjgl.vulkan.VkDeviceOrHostAddressConstKHR; 8 | 9 | import java.nio.ByteBuffer; 10 | import java.nio.IntBuffer; 11 | 12 | import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR; 13 | import static org.lwjgl.vulkan.VK10.*; 14 | import static org.lwjgl.vulkan.VK12.VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; 15 | 16 | public class SharedQuadVkIndexBuffer { 17 | public static final int TYPE = VK_INDEX_TYPE_UINT32; 18 | private static VBuffer indexBuffer = null; 19 | private static VkDeviceOrHostAddressConstKHR indexBufferAddr = null; 20 | private static int currentQuadCount = 0; 21 | 22 | public synchronized static VkDeviceOrHostAddressConstKHR getIndexBuffer(VContext context, VCmdBuff uploaCmdBuff, int quadCount) { 23 | if (currentQuadCount < quadCount) { 24 | makeNewIndexBuffer(context, uploaCmdBuff, quadCount); 25 | } 26 | 27 | return indexBufferAddr; 28 | } 29 | 30 | private static void makeNewIndexBuffer(VContext context, VCmdBuff uploaCmdBuff, int quadCount) { 31 | if (indexBuffer != null) { 32 | //TODO: need to enqueue the old indexBuffer for memory release 33 | indexBufferAddr.free();//Note this is calloced (in global heap) so need to release it IS SEPERATE FROM indexBuffer 34 | throw new IllegalStateException(); 35 | } 36 | 37 | ByteBuffer buffer = genQuadIdxs(quadCount); 38 | //TODO: dont harcode VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR and VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT 39 | indexBuffer = context.memory.createBuffer(buffer.remaining(), 40 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT 41 | | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR 42 | | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, 43 | VK_MEMORY_HEAP_DEVICE_LOCAL_BIT); 44 | 45 | uploaCmdBuff.encodeDataUpload(context.memory, MemoryUtil.memAddress(buffer), indexBuffer, 0, 46 | buffer.remaining()); 47 | 48 | indexBufferAddr = VkDeviceOrHostAddressConstKHR.calloc().deviceAddress(indexBuffer.deviceAddress()); 49 | currentQuadCount = quadCount; 50 | } 51 | 52 | public static ByteBuffer genQuadIdxs(int quadCount) { 53 | //short[] idxs = {0, 1, 2, 0, 2, 3}; 54 | 55 | int vertexCount = quadCount * 4; 56 | int indexCount = vertexCount * 3 / 2; 57 | ByteBuffer buffer = MemoryUtil.memAlloc(indexCount * Integer.BYTES); 58 | IntBuffer idxs = buffer.asIntBuffer(); 59 | //short[] idxs = new short[indexCount]; 60 | 61 | int j = 0; 62 | for(int i = 0; i < vertexCount; i += 4) { 63 | 64 | idxs.put(j, i); 65 | idxs.put(j + 1, (i + 1)); 66 | idxs.put(j + 2, (i + 2)); 67 | idxs.put(j + 3, (i)); 68 | idxs.put(j + 4, (i + 2)); 69 | idxs.put(j + 5, (i + 3)); 70 | 71 | j += 6; 72 | } 73 | 74 | return buffer; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/client/ArbitarySyncPointCallback.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.client; 2 | 3 | import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue; 4 | import it.unimi.dsi.fastutil.objects.ObjectArrayFIFOQueue; 5 | import org.lwjgl.opengl.GL32C; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.concurrent.locks.Lock; 10 | import java.util.concurrent.locks.ReentrantLock; 11 | 12 | import static org.lwjgl.opengl.ARBSync.*; 13 | import static org.lwjgl.opengl.GL11C.glGetError; 14 | 15 | public class ArbitarySyncPointCallback { 16 | private final List callbacks = new ArrayList<>(); 17 | private final Lock lock = new ReentrantLock(); 18 | public void enqueue(Runnable callback) { 19 | lock.lock(); 20 | callbacks.add(callback); 21 | lock.unlock(); 22 | } 23 | 24 | public Runnable generateCallback() { 25 | //Capture the callbacks into a local array 26 | lock.lock(); 27 | var capturedCallbacks = new ArrayList<>(callbacks); 28 | callbacks.clear(); 29 | lock.unlock(); 30 | if (capturedCallbacks.size() == 0) { 31 | return null; 32 | } else { 33 | return () -> capturedCallbacks.forEach(Runnable::run); 34 | } 35 | } 36 | 37 | 38 | private final LongArrayFIFOQueue fenceQueue = new LongArrayFIFOQueue(); 39 | private final ObjectArrayFIFOQueue callbackQueue = new ObjectArrayFIFOQueue<>(); 40 | //Injects a glFence into the cmd stream if there are any callbacks that need to be executed 41 | public void tick() { 42 | var callback = generateCallback(); 43 | if (callback != null) { 44 | long fence = GL32C.glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); 45 | if (fence == 0) { 46 | throw new IllegalStateException("glFenceSync was 0"); 47 | } 48 | fenceQueue.enqueue(fence); 49 | callbackQueue.enqueue(callback); 50 | } 51 | 52 | while (!fenceQueue.isEmpty()) { 53 | int result = glClientWaitSync(fenceQueue.firstLong(), 0, 1); 54 | if (result == GL_ALREADY_SIGNALED || result == GL_CONDITION_SATISFIED) { 55 | glDeleteSync(fenceQueue.dequeueLong()); 56 | callbackQueue.dequeue().run(); 57 | } else if (result == GL_WAIT_FAILED ) { 58 | throw new IllegalStateException("Other exception occurred waiting polling sync object: " + glGetError()); 59 | } else { 60 | break; 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/client/rendering/EntityCapture.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.client.rendering; 2 | 3 | import me.cortex.vulkanite.acceleration.SharedQuadVkIndexBuffer; 4 | import me.cortex.vulkanite.compat.IVGImage; 5 | import me.cortex.vulkanite.lib.base.VContext; 6 | import me.cortex.vulkanite.lib.cmd.VCmdBuff; 7 | import me.cortex.vulkanite.lib.memory.VAccelerationStructure; 8 | import me.cortex.vulkanite.lib.memory.VBuffer; 9 | import me.cortex.vulkanite.lib.other.VUtil; 10 | import me.cortex.vulkanite.lib.other.sync.VFence; 11 | import net.coderbot.iris.mixin.LevelRendererAccessor; 12 | import net.coderbot.iris.vertices.IrisVertexFormats; 13 | import net.minecraft.client.MinecraftClient; 14 | import net.minecraft.client.render.*; 15 | import net.minecraft.client.texture.TextureManager; 16 | import net.minecraft.client.util.math.MatrixStack; 17 | import net.minecraft.client.world.ClientWorld; 18 | import net.minecraft.util.Pair; 19 | import net.minecraft.world.World; 20 | import org.lwjgl.system.MemoryStack; 21 | import org.lwjgl.system.MemoryUtil; 22 | import org.lwjgl.vulkan.*; 23 | 24 | import java.util.ArrayList; 25 | import java.util.HashMap; 26 | import java.util.List; 27 | import java.util.Map; 28 | 29 | import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; 30 | import static org.lwjgl.vulkan.KHRAccelerationStructure.*; 31 | import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; 32 | import static org.lwjgl.vulkan.KHRBufferDeviceAddress.VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_KHR; 33 | import static org.lwjgl.vulkan.VK10.*; 34 | 35 | public class EntityCapture { 36 | private final VertexCaptureProvider capture = new VertexCaptureProvider(); 37 | 38 | //TODO: dont pass camera position of 0,0,0 in due to loss of precision 39 | public List> capture(float delta, ClientWorld world) { 40 | LevelRendererAccessor lra = (LevelRendererAccessor) MinecraftClient.getInstance().worldRenderer; 41 | 42 | MatrixStack stack = new MatrixStack(); 43 | 44 | //ImmediateState.renderWithExtendedVertexFormat = true; 45 | for (var entity : world.getEntities()) { 46 | lra.invokeRenderEntity(entity, 0,0,0, delta, stack, capture); 47 | } 48 | //ImmediateState.renderWithExtendedVertexFormat = false; 49 | 50 | //Note the lifetime of the buffer data is till the next call of render 51 | var buffers = capture.end(); 52 | if (buffers.isEmpty()) { 53 | return null; 54 | } 55 | return buffers; 56 | } 57 | 58 | 59 | private static class VertexCaptureProvider implements VertexConsumerProvider { 60 | private final Map builderMap = new HashMap<>(); 61 | 62 | @Override 63 | public VertexConsumer getBuffer(RenderLayer layer) { 64 | return builderMap.compute(layer, (layer1, builder)-> { 65 | if (builder == null) { 66 | builder = new BufferBuilder(420); 67 | } 68 | if (!builder.isBuilding()) { 69 | builder.reset(); 70 | builder.begin(layer1.getDrawMode(), layer1.getVertexFormat()); 71 | } 72 | return builder; 73 | }); 74 | } 75 | 76 | public List> end() { 77 | List> buffers = new ArrayList<>(); 78 | builderMap.forEach((layer,buffer)->{ 79 | if (buffer.isBuilding()) { 80 | var builtBuffer = buffer.end(); 81 | if (builtBuffer.getParameters().getBufferSize() == 0) { 82 | return;//Dont add empty buffers 83 | } 84 | //TODO: Doesnt support terrian vertex format yet, requires a second blas so that the instance offset can be the same 85 | // as terrain instance offset 86 | if (builtBuffer.getParameters().format().equals(IrisVertexFormats.TERRAIN)) { 87 | return; 88 | } 89 | //Dont support no texture things 90 | if (((RenderLayer.MultiPhase)layer).phases.texture.getId().isEmpty()) { 91 | return; 92 | } 93 | buffers.add(new Pair<>(layer, builtBuffer)); 94 | } 95 | }); 96 | return buffers; 97 | } 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/client/rendering/SharedImageViewTracker.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.client.rendering; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.cortex.vulkanite.lib.base.VContext; 5 | import me.cortex.vulkanite.lib.memory.VImage; 6 | import me.cortex.vulkanite.lib.other.VImageView; 7 | 8 | import java.util.function.Supplier; 9 | 10 | public class SharedImageViewTracker { 11 | private final VContext ctx; 12 | private final Supplier supplier; 13 | private VImageView view; 14 | public SharedImageViewTracker(VContext ctx, Supplier imageSupplier) { 15 | this.supplier = imageSupplier; 16 | this.ctx = ctx; 17 | } 18 | 19 | //NOTE: getting the image doesnt invalidate/check for a different image 20 | public VImage getImage() { 21 | if (view != null) { 22 | return view.image; 23 | } 24 | return null; 25 | } 26 | 27 | public VImageView getView() { 28 | return getView(this.supplier); 29 | } 30 | 31 | public VImageView getView(Supplier imageSupplier) { 32 | VImage image = imageSupplier.get(); 33 | if (this.view == null || this.view.image != image) { 34 | //TODO: move this to like a fence free that you pass in via an arg 35 | if (view != null) { 36 | Vulkanite.INSTANCE.addSyncedCallback(view::free); 37 | view = null; 38 | } 39 | if (image != null) { 40 | this.view = new VImageView(ctx, image); 41 | } 42 | } 43 | return view; 44 | } 45 | 46 | public void free() { 47 | if (view != null) { 48 | Vulkanite.INSTANCE.addSyncedCallback(view::free); 49 | view = null; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/compat/GeometryData.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.compat; 2 | 3 | import me.jellysquid.mods.sodium.client.util.NativeBuffer; 4 | 5 | public record GeometryData(int quadCount) { 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/compat/IAccelerationBuildResult.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.compat; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; 4 | import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType; 5 | import me.jellysquid.mods.sodium.client.util.NativeBuffer; 6 | 7 | import java.util.Map; 8 | 9 | public interface IAccelerationBuildResult { 10 | void setAccelerationGeometryData(Map map); 11 | Map getAccelerationGeometryData(); 12 | ChunkVertexType getVertexFormat(); 13 | void setVertexFormat(ChunkVertexType format); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/compat/IGetRaytracingSource.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.compat; 2 | 3 | public interface IGetRaytracingSource { 4 | RaytracingShaderSource[] getRaytracingSource(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/compat/IRenderTargetVkGetter.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.compat; 2 | 3 | import me.cortex.vulkanite.lib.memory.VGImage; 4 | 5 | public interface IRenderTargetVkGetter { 6 | VGImage getMain(); 7 | VGImage getAlt(); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/compat/IVGBuffer.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.compat; 2 | 3 | import me.cortex.vulkanite.lib.memory.VGBuffer; 4 | 5 | public interface IVGBuffer { 6 | VGBuffer getBuffer(); 7 | void setBuffer(VGBuffer buffer); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/compat/IVGImage.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.compat; 2 | 3 | import me.cortex.vulkanite.lib.memory.VGImage; 4 | 5 | public interface IVGImage { 6 | VGImage getVGImage(); 7 | void setVGImage(VGImage image); 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/compat/IVulkanContextGetter.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.compat; 2 | 3 | import me.cortex.vulkanite.lib.base.VContext; 4 | 5 | public interface IVulkanContextGetter { 6 | VContext getCtx(); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/compat/RaytracingShaderSet.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.compat; 2 | 3 | import me.cortex.vulkanite.lib.base.VContext; 4 | import me.cortex.vulkanite.lib.pipeline.RaytracePipelineBuilder; 5 | import me.cortex.vulkanite.lib.shader.ShaderModule; 6 | import me.cortex.vulkanite.lib.shader.VShader; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | import static org.lwjgl.vulkan.KHRRayTracingPipeline.*; 12 | 13 | public class RaytracingShaderSet { 14 | public final int maxDepth = 1; 15 | 16 | private record RayHit(ShaderModule close, ShaderModule any, ShaderModule intersection) {} 17 | private final ShaderModule raygen; 18 | private final ShaderModule[] raymiss; 19 | private final RayHit[] rayhits; 20 | 21 | private final VShader[] allShader; 22 | 23 | public RaytracingShaderSet(VContext ctx, RaytracingShaderSource source) { 24 | List shaderList = new ArrayList<>(); 25 | 26 | VShader shader = VShader.compileLoad(ctx, source.raygen, VK_SHADER_STAGE_RAYGEN_BIT_KHR); 27 | shaderList.add(shader); 28 | this.raygen = shader.named(); 29 | 30 | this.raymiss = new ShaderModule[source.raymiss.length]; 31 | for (int i = 0; i < raymiss.length; i++) { 32 | shader = VShader.compileLoad(ctx, source.raymiss[i], VK_SHADER_STAGE_MISS_BIT_KHR); 33 | shaderList.add(shader); 34 | this.raymiss[i] = shader.named(); 35 | } 36 | 37 | this.rayhits = new RayHit[source.rayhit.length]; 38 | for (int i = 0; i < this.rayhits.length; i++) { 39 | var hit = source.rayhit[i]; 40 | 41 | ShaderModule close = null; 42 | if (hit.close() != null) { 43 | shader = VShader.compileLoad(ctx, hit.close(), VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR); 44 | shaderList.add(shader); 45 | close = shader.named(); 46 | } 47 | 48 | ShaderModule any = null; 49 | if (hit.any() != null) { 50 | shader = VShader.compileLoad(ctx, hit.any(), VK_SHADER_STAGE_ANY_HIT_BIT_KHR); 51 | shaderList.add(shader); 52 | any = shader.named(); 53 | } 54 | 55 | ShaderModule intersection = null; 56 | if (hit.intersection() != null) { 57 | shader = VShader.compileLoad(ctx, hit.intersection(), VK_SHADER_STAGE_INTERSECTION_BIT_KHR); 58 | shaderList.add(shader); 59 | intersection = shader.named(); 60 | } 61 | 62 | this.rayhits[i] = new RayHit(close, any, intersection); 63 | } 64 | this.allShader = shaderList.toArray(new VShader[0]); 65 | } 66 | 67 | public void apply(RaytracePipelineBuilder builder) { 68 | builder.setRayGen(raygen); 69 | for (var miss : raymiss) { 70 | builder.addMiss(miss); 71 | } 72 | for (var hit : rayhits) { 73 | builder.addHit(hit.close, hit.any, hit.intersection); 74 | } 75 | } 76 | 77 | public int getRayHitCount() { 78 | return rayhits.length; 79 | } 80 | 81 | public void delete() { 82 | for (var shader : allShader) { 83 | shader.free(); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/compat/RaytracingShaderSource.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.compat; 2 | 3 | import net.coderbot.iris.shaderpack.ProgramDirectives; 4 | import net.coderbot.iris.shaderpack.ProgramSet; 5 | 6 | public class RaytracingShaderSource { 7 | public record RayHitSource(String close, String any, String intersection) {} 8 | public final String name; 9 | public final String raygen; 10 | public final String[] raymiss; 11 | public final RayHitSource[] rayhit; 12 | 13 | public RaytracingShaderSource(String name, String raygen, String[] raymiss, RayHitSource... rayhit) { 14 | this.name = name; 15 | this.raygen = raygen; 16 | this.raymiss = raymiss; 17 | this.rayhit = rayhit; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/compat/SodiumResultAdapter.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.compat; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; 4 | import me.jellysquid.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; 5 | import me.jellysquid.mods.sodium.client.util.NativeBuffer; 6 | import org.lwjgl.system.MemoryUtil; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | //TODO: FIXME! the native buffer is destroyed by the AccelerationBlasBuilder after its copied to the gpu, however 12 | // on world reload or for whatever reason that the result is destroyed (and not submitted to the blas builder) 13 | // must find a way to free the native buffers 14 | public class SodiumResultAdapter { 15 | public static void compute(ChunkBuildOutput buildResult) { 16 | var ebr = (IAccelerationBuildResult) buildResult; 17 | Map map = new HashMap<>(); 18 | for (var pass : buildResult.meshes.entrySet()) { 19 | var vertData = pass.getValue().getVertexData(); 20 | 21 | int stride = ebr.getVertexFormat().getVertexFormat().getStride(); 22 | 23 | if (vertData.getLength()%stride != 0) 24 | throw new IllegalStateException("Mismatch length and stride"); 25 | int vertices = vertData.getLength()/stride; 26 | if (vertices % 4 != 0) 27 | throw new IllegalStateException("Non multiple 4 vertex count"); 28 | 29 | map.put(pass.getKey(), new GeometryData(vertices>>2)); 30 | } 31 | 32 | if (!map.isEmpty()) { 33 | ebr.setAccelerationGeometryData(map); 34 | } else { 35 | ebr.setAccelerationGeometryData(null); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/base/DeviceProperties.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.base; 2 | 3 | import org.lwjgl.vulkan.VkDevice; 4 | import org.lwjgl.vulkan.VkPhysicalDeviceProperties2; 5 | import org.lwjgl.vulkan.VkPhysicalDeviceRayTracingPipelinePropertiesKHR; 6 | 7 | import static org.lwjgl.system.MemoryStack.stackPush; 8 | import static org.lwjgl.vulkan.VK11.vkGetPhysicalDeviceProperties2; 9 | 10 | public class DeviceProperties { 11 | //Allocates with a calloc, TODO: add a destroy function for cleanup 12 | 13 | public final VkPhysicalDeviceRayTracingPipelinePropertiesKHR rtPipelineProperties; 14 | public DeviceProperties(VkDevice device) { 15 | rtPipelineProperties = VkPhysicalDeviceRayTracingPipelinePropertiesKHR.calloc().sType$Default(); 16 | try (var stack = stackPush()) { 17 | vkGetPhysicalDeviceProperties2(device.getPhysicalDevice(), VkPhysicalDeviceProperties2.calloc(stack) 18 | .sType$Default() 19 | .pNext(rtPipelineProperties)); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/base/TrackedResourceObject.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.base; 2 | 3 | import java.lang.ref.Cleaner; 4 | 5 | public abstract class TrackedResourceObject { 6 | 7 | private final Ref ref; 8 | public TrackedResourceObject() { 9 | this.ref = register(this); 10 | } 11 | 12 | protected void free0() { 13 | ref.freedRef[0] = true; 14 | ref.cleanable.clean(); 15 | } 16 | 17 | public abstract void free(); 18 | 19 | public boolean isFreed() { 20 | return ref.freedRef[0]; 21 | } 22 | 23 | private record Ref(Cleaner.Cleanable cleanable, boolean[] freedRef) {} 24 | 25 | private static final Cleaner cleaner = Cleaner.create(); 26 | public static Ref register(Object obj) { 27 | String clazz = obj.getClass().getName(); 28 | Throwable trace = new Throwable(); 29 | boolean[] freed = new boolean[1]; 30 | var clean = cleaner.register(obj, ()->{ 31 | if (!freed[0]) { 32 | System.err.println("Object named: "+ clazz+" was not freed, location at: "); 33 | trace.printStackTrace(); 34 | } 35 | }); 36 | return new Ref(clean, freed); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/base/VContext.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.base; 2 | 3 | import me.cortex.vulkanite.lib.cmd.CommandManager; 4 | import me.cortex.vulkanite.lib.other.sync.SyncManager; 5 | import me.cortex.vulkanite.lib.memory.MemoryManager; 6 | import org.lwjgl.vulkan.VkDevice; 7 | 8 | public class VContext { 9 | public final VkDevice device; 10 | 11 | 12 | public final MemoryManager memory; 13 | public final SyncManager sync; 14 | public final CommandManager cmd; 15 | public final DeviceProperties properties; 16 | public VContext(VkDevice device, int queueCount, boolean hasDeviceAddresses) { 17 | this.device = device; 18 | memory = new MemoryManager(device, hasDeviceAddresses); 19 | sync = new SyncManager(device); 20 | cmd = new CommandManager(device, queueCount); 21 | properties = new DeviceProperties(device); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/base/initalizer/VExtensions.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.base.initalizer; 2 | 3 | public class VExtensions { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/base/initalizer/VInitializer.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.base.initalizer; 2 | 3 | import me.cortex.vulkanite.lib.base.VContext; 4 | import org.lwjgl.PointerBuffer; 5 | import org.lwjgl.system.MemoryStack; 6 | import org.lwjgl.system.MemoryUtil; 7 | import org.lwjgl.system.Struct; 8 | import org.lwjgl.vulkan.*; 9 | 10 | import java.nio.ByteBuffer; 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.HashSet; 14 | import java.util.List; 15 | import java.util.function.Consumer; 16 | import java.util.function.Function; 17 | 18 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 19 | import static org.lwjgl.system.MemoryStack.stackPush; 20 | import static org.lwjgl.system.MemoryUtil.memUTF8; 21 | import static org.lwjgl.vulkan.VK10.*; 22 | import static org.lwjgl.vulkan.VK11.*; 23 | 24 | public class VInitializer { 25 | private final VkInstance instance; 26 | private VkPhysicalDevice physicalDevice; 27 | private VkDevice device; 28 | private int queueCount; 29 | public VInitializer(String appName, String engineName, int major, int minor, String[] extensions, String[] layers) { 30 | try (MemoryStack stack = stackPush()) { 31 | VkApplicationInfo appInfo = VkApplicationInfo.calloc(stack) 32 | .sType$Default() 33 | .apiVersion(VK_MAKE_VERSION(major, minor, 0)) 34 | .pApplicationName(memUTF8(appName)) 35 | .pEngineName(memUTF8(engineName)); 36 | 37 | VkInstanceCreateInfo instanceCreateInfo = VkInstanceCreateInfo.calloc(stack) 38 | .sType$Default() 39 | .pApplicationInfo(appInfo) 40 | .ppEnabledExtensionNames(stack.pointers(Arrays.stream(extensions).map(stack::UTF8).toArray(ByteBuffer[]::new))) 41 | .ppEnabledLayerNames(stack.pointers(Arrays.stream(layers).map(stack::UTF8).toArray(ByteBuffer[]::new))); 42 | 43 | PointerBuffer result = stack.pointers(0); 44 | _CHECK_(vkCreateInstance(instanceCreateInfo, null, result)); 45 | 46 | instance = new VkInstance(result.get(0), instanceCreateInfo); 47 | } 48 | } 49 | 50 | public void findPhysicalDevice() { 51 | try (MemoryStack stack = stackPush()) { 52 | PointerBuffer devices = getPhysicalDevices(stack); 53 | for (int i = 0; i < devices.capacity(); i++) { 54 | VkPhysicalDeviceProperties props = VkPhysicalDeviceProperties.calloc(stack); 55 | vkGetPhysicalDeviceProperties(new VkPhysicalDevice(devices.get(i), instance), props); 56 | System.out.println(props.deviceNameString()); 57 | physicalDevice = new VkPhysicalDevice(devices.get(i), instance); 58 | break; 59 | } 60 | } 61 | } 62 | 63 | //TODO: add nice queue creation system 64 | public void createDevice(List extensions, List layers, float[] queuePriorities, Consumer deviceFeatures, List> applicators) { 65 | var deviceExtensions = new HashSet<>(getDeviceExtensionStrings(physicalDevice)); 66 | for (var extension : extensions) { 67 | if (!deviceExtensions.contains(extension)) { 68 | throw new IllegalStateException("Physical device is missing extension: " + extension); 69 | } 70 | } 71 | 72 | try (MemoryStack stack = stackPush()) { 73 | 74 | queueCount = queuePriorities.length; 75 | var queueCreateInfos = VkDeviceQueueCreateInfo.calloc(1, stack) 76 | .sType$Default() 77 | .pQueuePriorities(stack.floats(queuePriorities)) 78 | .queueFamilyIndex(0); 79 | 80 | VkDeviceCreateInfo createInfo = VkDeviceCreateInfo.calloc(stack) 81 | .sType$Default() 82 | .ppEnabledExtensionNames(stack.pointers(extensions.stream().map(stack::UTF8).toArray(ByteBuffer[]::new))) 83 | .ppEnabledLayerNames(stack.pointers(layers.stream().map(stack::UTF8).toArray(ByteBuffer[]::new))) 84 | .pQueueCreateInfos(queueCreateInfos); 85 | 86 | if (deviceFeatures != null) { 87 | var features = VkPhysicalDeviceFeatures.calloc(stack); 88 | deviceFeatures.accept(features); 89 | createInfo.pEnabledFeatures(features); 90 | } else { 91 | createInfo.pEnabledFeatures(null); 92 | } 93 | 94 | long chain = createInfo.address(); 95 | var deviceProperties2 = VkPhysicalDeviceFeatures2.calloc(stack).sType$Default(); 96 | for (var applicator : applicators) { 97 | Struct feature = applicator.apply(stack); 98 | deviceProperties2.pNext(feature.address()); 99 | vkGetPhysicalDeviceFeatures2(physicalDevice, deviceProperties2); 100 | long next = feature.address(); 101 | MemoryUtil.memPutAddress(chain+8, next); 102 | chain = next; 103 | } 104 | 105 | PointerBuffer pDevice = stack.callocPointer(1); 106 | _CHECK_(vkCreateDevice(physicalDevice, createInfo, null, pDevice)); 107 | device = new VkDevice(pDevice.get(0), physicalDevice, createInfo); 108 | } 109 | } 110 | 111 | private static VkLayerProperties.Buffer getInstanceLayers(MemoryStack stack) { 112 | int[] res = new int[1]; 113 | _CHECK_(vkEnumerateInstanceLayerProperties(res, null)); 114 | VkLayerProperties.Buffer layerProperties = VkLayerProperties.calloc(res[0], stack); 115 | _CHECK_(vkEnumerateInstanceLayerProperties(res, layerProperties)); 116 | if (res[0] != layerProperties.capacity()) 117 | throw new IllegalStateException(); 118 | return layerProperties; 119 | } 120 | 121 | private static VkExtensionProperties.Buffer getInstanceExtensions(MemoryStack stack) { 122 | int[] res = new int[1]; 123 | _CHECK_(vkEnumerateInstanceExtensionProperties((String) null, res, null)); 124 | VkExtensionProperties.Buffer extensionProperties = VkExtensionProperties.calloc(res[0], stack); 125 | _CHECK_(vkEnumerateInstanceExtensionProperties((String) null, res, extensionProperties)); 126 | if (res[0] != extensionProperties.capacity()) 127 | throw new IllegalStateException(); 128 | return extensionProperties; 129 | } 130 | 131 | private PointerBuffer getPhysicalDevices(MemoryStack stack) { 132 | int[] res = new int[1]; 133 | _CHECK_(vkEnumeratePhysicalDevices(instance, res, null)); 134 | PointerBuffer devices = stack.callocPointer(res[0]); 135 | _CHECK_(vkEnumeratePhysicalDevices(instance, res, devices)); 136 | if (res[0] != devices.capacity()) 137 | throw new IllegalStateException(); 138 | return devices; 139 | } 140 | 141 | private List getDeviceExtensionStrings(VkPhysicalDevice device) { 142 | List extensions = new ArrayList<>(); 143 | try (var stack = stackPush()) { 144 | var eb = getDeviceExtensions(stack, device); 145 | for (var extension : eb) { 146 | extensions.add(extension.extensionNameString()); 147 | } 148 | } 149 | return extensions; 150 | } 151 | 152 | private VkExtensionProperties.Buffer getDeviceExtensions(MemoryStack stack, long device) { 153 | return getDeviceExtensions(stack, new VkPhysicalDevice(device, instance)); 154 | } 155 | 156 | private VkExtensionProperties.Buffer getDeviceExtensions(MemoryStack stack, VkPhysicalDevice device) { 157 | int[] res = new int[1]; 158 | _CHECK_(vkEnumerateDeviceExtensionProperties(device, (String) null, res, null)); 159 | VkExtensionProperties.Buffer extensionProperties = VkExtensionProperties.calloc(res[0], stack); 160 | _CHECK_(vkEnumerateDeviceExtensionProperties(device, (String) null, res, extensionProperties)); 161 | if (res[0] != extensionProperties.capacity()) 162 | throw new IllegalStateException(); 163 | return extensionProperties; 164 | } 165 | 166 | public VContext createContext() { 167 | //TODO:FIXME: DONT HARDCODE THE FACT IT HAS DEVICE ADDRESSES 168 | return new VContext(device, queueCount, true); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/cmd/CommandManager.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.cmd; 2 | 3 | import com.mojang.blaze3d.systems.RenderSystem; 4 | 5 | import io.netty.util.internal.shaded.org.jctools.queues.MessagePassingQueue.Consumer; 6 | import me.cortex.vulkanite.lib.other.sync.VFence; 7 | import me.cortex.vulkanite.lib.other.sync.VSemaphore; 8 | import org.lwjgl.vulkan.VkCommandBufferBeginInfo; 9 | import org.lwjgl.vulkan.VkDevice; 10 | import org.lwjgl.vulkan.VkQueue; 11 | import org.lwjgl.vulkan.VkSubmitInfo; 12 | 13 | import java.nio.LongBuffer; 14 | 15 | import static org.lwjgl.system.MemoryStack.stackPush; 16 | import static org.lwjgl.vulkan.VK10.*; 17 | 18 | //Manages multiple command queues and fence synchronizations 19 | public class CommandManager { 20 | private final VkDevice device; 21 | private final VkQueue[] queues; 22 | 23 | private final VCommandPool singleUsePool; 24 | 25 | public CommandManager(VkDevice device, int queues) { 26 | this.device = device; 27 | this.queues = new VkQueue[queues]; 28 | try (var stack = stackPush()) { 29 | var pQ = stack.pointers(0); 30 | for (int i = 0; i < queues; i++) { 31 | vkGetDeviceQueue(device, 0, i, pQ); 32 | System.out.println("Queue "+i+" has address " + Long.toHexString(pQ.get(0))); 33 | this.queues[i] = new VkQueue(pQ.get(0), device); 34 | } 35 | } 36 | this.singleUsePool = createSingleUsePool(); 37 | } 38 | 39 | public VCommandPool createSingleUsePool() { 40 | return createPool(VK_COMMAND_POOL_CREATE_TRANSIENT_BIT); 41 | } 42 | 43 | public VCommandPool createPool(int flags) { 44 | return new VCommandPool(device, flags); 45 | } 46 | 47 | public void submit(int queueId, VkSubmitInfo submit) { 48 | try (var stack = stackPush()) { 49 | vkQueueSubmit(queues[queueId], submit, 0); 50 | } 51 | } 52 | 53 | public void submitOnceAndWait(int queueId, VCmdBuff cmdBuff) { 54 | try (var stack = stackPush()) { 55 | var submit = VkSubmitInfo.calloc(stack).sType$Default() 56 | .pCommandBuffers(stack.pointers(cmdBuff)) 57 | .pWaitSemaphores(stack.longs()) 58 | .pWaitDstStageMask(stack.ints()) 59 | .pSignalSemaphores(stack.longs()); 60 | vkQueueSubmit(queues[queueId], submit, 0); 61 | vkQueueWaitIdle(queues[queueId]); 62 | cmdBuff.freeInternal(); 63 | } 64 | } 65 | 66 | public void executeWait(Consumer cmdbuf) { 67 | var cmd = singleUsePool.createCommandBuffer(); 68 | cmd.begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT); 69 | cmdbuf.accept(cmd); 70 | cmd.end(); 71 | submitOnceAndWait(0, cmd); 72 | } 73 | 74 | //TODO: if its a single use command buffer, automatically add the required fences and stuff to free the command buffer once its done 75 | public void submit(int queueId, VCmdBuff[] cmdBuffs, VSemaphore[] waits, int[] waitStages, VSemaphore[] triggers, VFence fence) { 76 | if (queueId == 0) { 77 | RenderSystem.assertOnRenderThread(); 78 | } 79 | 80 | try (var stack = stackPush()) { 81 | LongBuffer waitSemaphores = stack.mallocLong(waits.length); 82 | LongBuffer signalSemaphores = stack.mallocLong(triggers.length); 83 | for (var wait : waits) {waitSemaphores.put(wait.address());} 84 | for (var trigger : triggers) {signalSemaphores.put(trigger.address());} 85 | waitSemaphores.rewind(); 86 | signalSemaphores.rewind(); 87 | var submit = VkSubmitInfo.calloc(stack).sType$Default() 88 | .pCommandBuffers(stack.pointers(cmdBuffs)) 89 | .pWaitSemaphores(waitSemaphores) 90 | .waitSemaphoreCount(waits.length) 91 | .pWaitDstStageMask(stack.ints(waitStages)) 92 | .pSignalSemaphores(signalSemaphores); 93 | vkQueueSubmit(queues[queueId], submit, fence==null?0:fence.address()); 94 | } 95 | } 96 | 97 | public void waitQueueIdle(int queue) { 98 | vkQueueWaitIdle(queues[queue]); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/cmd/VCommandPool.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.cmd; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import org.lwjgl.PointerBuffer; 5 | import org.lwjgl.system.MemoryStack; 6 | import org.lwjgl.vulkan.VkCommandBuffer; 7 | import org.lwjgl.vulkan.VkCommandBufferAllocateInfo; 8 | import org.lwjgl.vulkan.VkCommandPoolCreateInfo; 9 | import org.lwjgl.vulkan.VkDevice; 10 | 11 | import java.nio.LongBuffer; 12 | import java.util.concurrent.ConcurrentLinkedDeque; 13 | 14 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 15 | import static org.lwjgl.system.MemoryStack.stackPush; 16 | import static org.lwjgl.vulkan.VK10.*; 17 | 18 | public class VCommandPool extends TrackedResourceObject { 19 | final VkDevice device; 20 | final long pool; 21 | public VCommandPool(VkDevice device, int flags) { 22 | this(device, 0, flags); 23 | } 24 | 25 | public VCommandPool(VkDevice device, int family, int flags) { 26 | this.device = device; 27 | try (var stack = stackPush()) { 28 | VkCommandPoolCreateInfo cmdPoolInfo = VkCommandPoolCreateInfo.calloc(stack) 29 | .sType$Default() 30 | .queueFamilyIndex(family) 31 | .flags(flags); 32 | LongBuffer pCmdPool = stack.mallocLong(1); 33 | _CHECK_(vkCreateCommandPool(device, cmdPoolInfo, null, pCmdPool)); 34 | pool = pCmdPool.get(0); 35 | } 36 | } 37 | 38 | public synchronized VCmdBuff createCommandBuffer() { 39 | return createCommandBuffers(1)[0]; 40 | } 41 | 42 | public synchronized VCmdBuff[] createCommandBuffers(int count) { 43 | return createCommandBuffers(count, 0); 44 | } 45 | 46 | public synchronized VCmdBuff[] createCommandBuffers(int count, int level) { 47 | try (MemoryStack stack = MemoryStack.stackPush()){ 48 | PointerBuffer pCommandBuffer = stack.mallocPointer(count); 49 | _CHECK_(vkAllocateCommandBuffers(device, 50 | VkCommandBufferAllocateInfo 51 | .calloc(stack) 52 | .sType$Default() 53 | .commandPool(pool) 54 | .level(level) 55 | .commandBufferCount(count), pCommandBuffer), 56 | "Failed to create command buffer"); 57 | VCmdBuff[] buffers = new VCmdBuff[count]; 58 | for (int i = 0; i < count; i++) { 59 | buffers[i] = new VCmdBuff(this, new VkCommandBuffer(pCommandBuffer.get(i), device)); 60 | } 61 | return buffers; 62 | } 63 | } 64 | 65 | private final ConcurrentLinkedDeque toRelease = new ConcurrentLinkedDeque<>(); 66 | void free(VCmdBuff cmdBuff) { 67 | toRelease.add(cmdBuff); 68 | } 69 | 70 | public void doReleases() { 71 | while (!toRelease.isEmpty()) { 72 | toRelease.poll().freeInternal(); 73 | } 74 | } 75 | 76 | public void releaseNow(VCmdBuff cmd) { 77 | cmd.freeInternal(); 78 | } 79 | 80 | @Override 81 | public void free() { 82 | free0(); 83 | vkDestroyCommandPool(device, pool, null); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorSetLayoutBuilder.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.descriptors; 2 | 3 | import it.unimi.dsi.fastutil.ints.IntArrayList; 4 | import me.cortex.vulkanite.lib.base.VContext; 5 | import org.lwjgl.system.MemoryUtil; 6 | import org.lwjgl.vulkan.VkDescriptorSetLayoutBinding; 7 | import org.lwjgl.vulkan.VkDescriptorSetLayoutCreateInfo; 8 | import org.lwjgl.vulkan.VkDescriptorSetLayoutBindingFlagsCreateInfo; 9 | 10 | import java.nio.LongBuffer; 11 | import java.util.HashMap; 12 | 13 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 14 | import static org.lwjgl.system.MemoryStack.stackPush; 15 | import static org.lwjgl.vulkan.VK10.vkCreateDescriptorSetLayout; 16 | 17 | public class DescriptorSetLayoutBuilder { 18 | private IntArrayList types = new IntArrayList(); 19 | private HashMap bindingFlagsMap = new HashMap<>(); 20 | private VkDescriptorSetLayoutBinding.Buffer bindings = VkDescriptorSetLayoutBinding.calloc(0); 21 | public DescriptorSetLayoutBuilder binding(int binding, int type, int count, int stages) { 22 | bindings = VkDescriptorSetLayoutBinding.create(MemoryUtil.nmemRealloc(bindings.address(), (bindings.capacity() + 1L) * VkDescriptorSetLayoutBinding.SIZEOF), bindings.capacity() + 1); 23 | var struct = bindings.get(bindings.capacity()-1); 24 | struct.set(binding, type, count, stages, null); 25 | types.add(type); 26 | return this; 27 | } 28 | 29 | public DescriptorSetLayoutBuilder binding(int binding, int type, int stages) { 30 | return binding(binding, type, 1, stages); 31 | } 32 | public DescriptorSetLayoutBuilder binding(int type, int stages) { 33 | return binding(bindings.capacity(), type, stages); 34 | } 35 | 36 | public void setBindingFlags(int binding, int flag) { 37 | bindingFlagsMap.put(binding, flag); 38 | } 39 | 40 | int flags; 41 | public DescriptorSetLayoutBuilder() { 42 | this(0); 43 | } 44 | public DescriptorSetLayoutBuilder(int flags){ 45 | this.flags = flags; 46 | } 47 | 48 | public VDescriptorSetLayout build(VContext ctx) { 49 | try (var stack = stackPush()) { 50 | var info = VkDescriptorSetLayoutCreateInfo.calloc(stack) 51 | .sType$Default() 52 | .pBindings(bindings) 53 | .flags(flags); 54 | 55 | if (!bindingFlagsMap.isEmpty()) { 56 | var bindingFlags = new int[bindings.remaining()]; 57 | for (var i = 0; i < bindings.remaining(); i++) { 58 | bindingFlags[i] = bindingFlagsMap.getOrDefault(bindings.get(i).binding(), 0); 59 | } 60 | 61 | var bindingInfo = VkDescriptorSetLayoutBindingFlagsCreateInfo.calloc(stack) 62 | .sType$Default() 63 | .pBindingFlags(stack.ints(bindingFlags)); 64 | info.pNext(bindingInfo); 65 | } 66 | 67 | LongBuffer pBuffer = stack.mallocLong(1); 68 | _CHECK_(vkCreateDescriptorSetLayout(ctx.device, info, null, pBuffer)); 69 | return new VDescriptorSetLayout(ctx, pBuffer.get(0), types.toIntArray()); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/descriptors/DescriptorUpdateBuilder.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.descriptors; 2 | 3 | import me.cortex.vulkanite.lib.base.VContext; 4 | import me.cortex.vulkanite.lib.memory.VAccelerationStructure; 5 | import me.cortex.vulkanite.lib.memory.VBuffer; 6 | import me.cortex.vulkanite.lib.other.VImageView; 7 | import me.cortex.vulkanite.lib.other.VSampler; 8 | import me.cortex.vulkanite.lib.shader.reflection.ShaderReflection; 9 | import org.lwjgl.system.MemoryStack; 10 | import org.lwjgl.vulkan.VkDescriptorBufferInfo; 11 | import org.lwjgl.vulkan.VkDescriptorImageInfo; 12 | import org.lwjgl.vulkan.VkWriteDescriptorSet; 13 | import org.lwjgl.vulkan.VkWriteDescriptorSetAccelerationStructureKHR; 14 | 15 | import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; 16 | import static org.lwjgl.vulkan.VK10.*; 17 | 18 | import java.util.List; 19 | 20 | public class DescriptorUpdateBuilder { 21 | private final VContext ctx; 22 | private final MemoryStack stack; 23 | private final VkWriteDescriptorSet.Buffer updates; 24 | private final VImageView placeholderImageView; 25 | private ShaderReflection.Set refSet = null; 26 | 27 | public DescriptorUpdateBuilder(VContext ctx, int maxUpdates) { 28 | this(ctx, maxUpdates, null); 29 | } 30 | 31 | public DescriptorUpdateBuilder(VContext ctx, int maxUpdates, VImageView placeholderImageView) { 32 | this.ctx = ctx; 33 | this.stack = MemoryStack.stackPush(); 34 | this.updates = VkWriteDescriptorSet.calloc(maxUpdates, stack); 35 | this.placeholderImageView = placeholderImageView; 36 | } 37 | 38 | public DescriptorUpdateBuilder(VContext ctx, ShaderReflection.Set refSet) { 39 | this(ctx, refSet, null); 40 | } 41 | 42 | public DescriptorUpdateBuilder(VContext ctx, ShaderReflection.Set refSet, VImageView placeholderImageView) { 43 | this(ctx, refSet.bindings().size(), placeholderImageView); 44 | this.refSet = refSet; 45 | } 46 | 47 | private long viewOrPlaceholder(VImageView v) { 48 | if (v == null && placeholderImageView == null) return 0; 49 | return v == null ? placeholderImageView.view : v.view; 50 | } 51 | 52 | private long set; 53 | public DescriptorUpdateBuilder set(long set) { 54 | this.set = set; 55 | return this; 56 | } 57 | 58 | public DescriptorUpdateBuilder buffer(int binding, VBuffer buffer) { 59 | return buffer(binding, buffer, 0, VK_WHOLE_SIZE); 60 | } 61 | public DescriptorUpdateBuilder buffer(int binding, VBuffer buffer, long offset, long range) { 62 | if (refSet != null && refSet.getBindingAt(binding) == null) { 63 | return this; 64 | } 65 | updates.get() 66 | .sType$Default() 67 | .dstBinding(binding) 68 | .dstSet(set) 69 | .descriptorType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 70 | .descriptorCount(1) 71 | .pBufferInfo(VkDescriptorBufferInfo 72 | .calloc(1, stack) 73 | .buffer(buffer.buffer()) 74 | .offset(offset) 75 | .range(range)); 76 | 77 | return this; 78 | } 79 | 80 | public DescriptorUpdateBuilder buffer(int binding, int dstArrayElement, List buffers) { 81 | if (refSet != null && refSet.getBindingAt(binding) == null) { 82 | return this; 83 | } 84 | var bufInfo = VkDescriptorBufferInfo.calloc(buffers.size(), stack); 85 | for (int i = 0; i < buffers.size(); i++) { 86 | bufInfo.get(i) 87 | .buffer(buffers.get(i).buffer()) 88 | .offset(0) 89 | .range(VK_WHOLE_SIZE); 90 | } 91 | updates.get() 92 | .sType$Default() 93 | .dstBinding(binding) 94 | .dstSet(set) 95 | .dstArrayElement(dstArrayElement) 96 | .descriptorType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 97 | .descriptorCount(buffers.size()) 98 | .pBufferInfo(bufInfo); 99 | 100 | return this; 101 | } 102 | 103 | 104 | public DescriptorUpdateBuilder uniform(int binding, VBuffer buffer) { 105 | return uniform(binding, buffer, 0, VK_WHOLE_SIZE); 106 | } 107 | public DescriptorUpdateBuilder uniform(int binding, VBuffer buffer, long offset, long range) { 108 | if (refSet != null && refSet.getBindingAt(binding) == null) { 109 | return this; 110 | } 111 | updates.get() 112 | .sType$Default() 113 | .dstBinding(binding) 114 | .dstSet(set) 115 | .descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) 116 | .descriptorCount(1) 117 | .pBufferInfo(VkDescriptorBufferInfo 118 | .calloc(1, stack) 119 | .buffer(buffer.buffer()) 120 | .offset(offset) 121 | .range(range)); 122 | return this; 123 | } 124 | 125 | public DescriptorUpdateBuilder acceleration(int binding, VAccelerationStructure... structures) { 126 | if (refSet != null && refSet.getBindingAt(binding) == null) { 127 | return this; 128 | } 129 | var buff = stack.mallocLong(structures.length); 130 | for (var structure : structures) { 131 | buff.put(structure.structure); 132 | } 133 | buff.rewind(); 134 | updates.get() 135 | .sType$Default() 136 | .dstBinding(binding) 137 | .dstSet(set) 138 | .descriptorType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR) 139 | .descriptorCount(structures.length) 140 | .pNext(VkWriteDescriptorSetAccelerationStructureKHR.calloc(stack) 141 | .sType$Default() 142 | .pAccelerationStructures(buff)); 143 | return this; 144 | } 145 | 146 | public DescriptorUpdateBuilder imageStore(int binding, int dstArrayElement, List views) { 147 | if (refSet != null && refSet.getBindingAt(binding) == null) { 148 | return this; 149 | } 150 | var imgInfo = VkDescriptorImageInfo.calloc(views.size(), stack); 151 | for (int i = 0; i < views.size(); i++) { 152 | imgInfo.get(i) 153 | .imageLayout(VK_IMAGE_LAYOUT_GENERAL) 154 | .imageView(viewOrPlaceholder(views.get(i))); 155 | } 156 | updates.get() 157 | .sType$Default() 158 | .dstBinding(binding) 159 | .dstSet(set) 160 | .descriptorType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) 161 | .descriptorCount(views.size()) 162 | .pImageInfo(imgInfo); 163 | return this; 164 | } 165 | public DescriptorUpdateBuilder imageStore(int binding, VImageView view) { 166 | return imageStore(binding, VK_IMAGE_LAYOUT_GENERAL, view); 167 | } 168 | public DescriptorUpdateBuilder imageStore(int binding, int layout, VImageView view) { 169 | if (refSet != null && refSet.getBindingAt(binding) == null) { 170 | return this; 171 | } 172 | updates.get() 173 | .sType$Default() 174 | .dstBinding(binding) 175 | .dstSet(set) 176 | .descriptorType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) 177 | .descriptorCount(1) 178 | .pImageInfo(VkDescriptorImageInfo 179 | .calloc(1, stack) 180 | .imageLayout(layout) 181 | .imageView(viewOrPlaceholder(view))); 182 | return this; 183 | } 184 | 185 | public DescriptorUpdateBuilder imageSampler(int binding, VImageView view, VSampler sampler) { 186 | return imageSampler(binding, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, view, sampler); 187 | } 188 | 189 | public DescriptorUpdateBuilder imageSampler(int binding, int layout, VImageView view, VSampler sampler) { 190 | if (refSet != null && refSet.getBindingAt(binding) == null) { 191 | return this; 192 | } 193 | updates.get() 194 | .sType$Default() 195 | .dstBinding(binding) 196 | .dstSet(set) 197 | .descriptorType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 198 | .descriptorCount(1) 199 | .pImageInfo(VkDescriptorImageInfo 200 | .calloc(1, stack) 201 | .imageLayout(layout) 202 | .imageView(viewOrPlaceholder(view)) 203 | .sampler(sampler.sampler)); 204 | return this; 205 | } 206 | 207 | public void apply() { 208 | updates.limit(updates.position()); 209 | updates.rewind(); 210 | vkUpdateDescriptorSets(ctx.device, updates, null); 211 | stack.pop(); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorPool.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.descriptors; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import me.cortex.vulkanite.lib.base.VContext; 5 | import org.lwjgl.vulkan.VkDescriptorPoolCreateInfo; 6 | import org.lwjgl.vulkan.VkDescriptorPoolSize; 7 | import org.lwjgl.vulkan.VkDescriptorSetAllocateInfo; 8 | import org.lwjgl.vulkan.VkDescriptorSetVariableDescriptorCountAllocateInfo; 9 | 10 | import java.nio.LongBuffer; 11 | 12 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 13 | import static org.lwjgl.system.MemoryStack.stackPush; 14 | import static org.lwjgl.vulkan.VK10.*; 15 | 16 | public class VDescriptorPool extends TrackedResourceObject { 17 | private final VContext ctx; 18 | private final long pool; 19 | 20 | private final long[] sets; 21 | 22 | public VDescriptorPool(VContext ctx, int flags, int numSets, int... types) { 23 | this.ctx = ctx; 24 | this.sets = new long[numSets]; 25 | 26 | try (var stack = stackPush()) { 27 | var sizes = VkDescriptorPoolSize.calloc(types.length, stack); 28 | for (int i = 0; i < types.length; i++) { 29 | sizes.get(i).type(types[i]).descriptorCount(numSets); 30 | } 31 | LongBuffer pPool = stack.mallocLong(1); 32 | _CHECK_(vkCreateDescriptorPool(ctx.device, VkDescriptorPoolCreateInfo.calloc(stack) 33 | .sType$Default() 34 | .flags(flags) 35 | .maxSets(numSets) 36 | .pPoolSizes(sizes), null, pPool)); 37 | pool = pPool.get(0); 38 | } 39 | } 40 | 41 | public VDescriptorPool(VContext ctx, int flags, int numSets, int countPerType, int... types) { 42 | this.ctx = ctx; 43 | this.sets = new long[numSets]; 44 | 45 | try (var stack = stackPush()) { 46 | var sizes = VkDescriptorPoolSize.calloc(types.length, stack); 47 | for (int i = 0; i < types.length; i++) { 48 | sizes.get(i).type(types[i]).descriptorCount(numSets * countPerType); 49 | } 50 | LongBuffer pPool = stack.mallocLong(1); 51 | _CHECK_(vkCreateDescriptorPool(ctx.device, VkDescriptorPoolCreateInfo.calloc(stack) 52 | .sType$Default() 53 | .flags(flags) 54 | .maxSets(numSets) 55 | .pPoolSizes(sizes), null, pPool)); 56 | pool = pPool.get(0); 57 | } 58 | } 59 | 60 | public void allocateSets(VDescriptorSetLayout layout, int... variableSizes) { 61 | try (var stack = stackPush()) { 62 | var layouts = stack.mallocLong(sets.length); 63 | for (int i = 0; i < sets.length; i++) { 64 | layouts.put(layout.layout); 65 | } 66 | layouts.rewind(); 67 | LongBuffer pDescriptorSets = stack.mallocLong(sets.length); 68 | var allocInfo = VkDescriptorSetAllocateInfo.calloc(stack) 69 | .sType$Default() 70 | .descriptorPool(pool) 71 | .pSetLayouts(layouts); 72 | if (variableSizes != null) { 73 | var descriptorCounts = stack.mallocInt(variableSizes.length); 74 | for (int i = 0; i < variableSizes.length; i++) { 75 | descriptorCounts.put(variableSizes[i]); 76 | } 77 | descriptorCounts.rewind(); 78 | var variableCountInfo = VkDescriptorSetVariableDescriptorCountAllocateInfo.calloc(stack) 79 | .sType$Default() 80 | .pDescriptorCounts(descriptorCounts); 81 | allocInfo.pNext(variableCountInfo.address()); 82 | } 83 | _CHECK_(vkAllocateDescriptorSets(ctx.device, allocInfo, pDescriptorSets), 84 | "Failed to allocate descriptor set"); 85 | pDescriptorSets.get(sets); 86 | } 87 | } 88 | 89 | public void allocateSets(VDescriptorSetLayout layout) { 90 | allocateSets(layout, null); 91 | } 92 | 93 | public long get(int idx) { 94 | return sets[idx]; 95 | } 96 | 97 | @Override 98 | public void free() { 99 | free0(); 100 | vkDestroyDescriptorPool(ctx.device, pool, null); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSet.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.descriptors; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | 5 | public class VDescriptorSet extends TrackedResourceObject { 6 | private final VTypedDescriptorPool pool; 7 | public final long poolHandle; 8 | public final long set; 9 | 10 | VDescriptorSet(VTypedDescriptorPool pool, long poolHandle, long set) { 11 | this.pool = pool; 12 | this.poolHandle = poolHandle; 13 | this.set = set; 14 | } 15 | 16 | @Override 17 | public void free() { 18 | free0(); 19 | pool.freeSet(this); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/descriptors/VDescriptorSetLayout.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.descriptors; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 5 | import me.cortex.vulkanite.lib.base.VContext; 6 | import org.lwjgl.system.Pointer; 7 | import org.lwjgl.vulkan.VkDescriptorPoolCreateInfo; 8 | import org.lwjgl.vulkan.VkDescriptorPoolSize; 9 | 10 | import java.nio.LongBuffer; 11 | import java.util.Objects; 12 | 13 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 14 | import static org.lwjgl.system.MemoryStack.stackPush; 15 | import static org.lwjgl.vulkan.VK10.vkCreateDescriptorPool; 16 | import static org.lwjgl.vulkan.VK10.vkDestroyDescriptorSetLayout; 17 | 18 | public final class VDescriptorSetLayout extends TrackedResourceObject implements Pointer { 19 | private final VContext ctx; 20 | public final long layout; 21 | public final int[] types; 22 | 23 | public VDescriptorSetLayout(VContext ctx, long layout, int[] types) { 24 | this.ctx = ctx; 25 | this.layout = layout; 26 | this.types = types; 27 | } 28 | 29 | @Override 30 | public long address() { 31 | return layout; 32 | } 33 | 34 | @Override 35 | public void free() { 36 | Vulkanite.INSTANCE.removePoolByLayout(this); 37 | free0(); 38 | vkDestroyDescriptorSetLayout(ctx.device, layout, null); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/descriptors/VTypedDescriptorPool.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.descriptors; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import me.cortex.vulkanite.lib.base.VContext; 5 | import org.lwjgl.vulkan.VkDescriptorPoolCreateInfo; 6 | import org.lwjgl.vulkan.VkDescriptorPoolSize; 7 | import org.lwjgl.vulkan.VkDescriptorSetAllocateInfo; 8 | 9 | import java.nio.LongBuffer; 10 | import java.util.ArrayList; 11 | 12 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 13 | import static org.lwjgl.system.MemoryStack.stackPush; 14 | import static org.lwjgl.vulkan.VK10.*; 15 | 16 | public class VTypedDescriptorPool extends TrackedResourceObject { 17 | private final VContext ctx; 18 | private final ArrayList pools = new ArrayList<>(); 19 | private final ArrayList poolFreeSizes = new ArrayList<>(); 20 | private final VDescriptorSetLayout layout; 21 | private final int flags; 22 | 23 | private static final int nSetsPerPool = 16; 24 | 25 | public VTypedDescriptorPool(VContext ctx, VDescriptorSetLayout layout, int flags) { 26 | this.ctx = ctx; 27 | this.layout = layout; 28 | this.flags = flags; 29 | } 30 | 31 | private void createNewPool() { 32 | try (var stack = stackPush()) { 33 | var sizes = VkDescriptorPoolSize.calloc(layout.types.length, stack); 34 | for (int i = 0; i < layout.types.length; i++) { 35 | sizes.get(i).type(layout.types[i]).descriptorCount(nSetsPerPool); 36 | } 37 | LongBuffer pPool = stack.mallocLong(1); 38 | _CHECK_(vkCreateDescriptorPool(ctx.device, VkDescriptorPoolCreateInfo.calloc(stack) 39 | .sType$Default() 40 | .flags(flags | VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT) 41 | .maxSets(nSetsPerPool) 42 | .pPoolSizes(sizes), null, pPool)); 43 | pools.add(pPool.get(0)); 44 | poolFreeSizes.add(nSetsPerPool); 45 | } 46 | } 47 | 48 | public VDescriptorSet allocateSet() { 49 | if (poolFreeSizes.isEmpty() || poolFreeSizes.get(pools.size() - 1) == 0) { 50 | createNewPool(); 51 | } 52 | long pool = pools.get(pools.size() - 1); 53 | long set; 54 | poolFreeSizes.set(pools.size() - 1, poolFreeSizes.get(pools.size() - 1) - 1); 55 | try (var stack = stackPush()) { 56 | var pSet = stack.mallocLong(1); 57 | _CHECK_(vkAllocateDescriptorSets(ctx.device, VkDescriptorSetAllocateInfo.calloc(stack) 58 | .sType$Default() 59 | .descriptorPool(pool) 60 | .pSetLayouts(stack.mallocLong(1).put(0, layout.layout)), pSet)); 61 | set = pSet.get(0); 62 | } 63 | return new VDescriptorSet(this, pool, set); 64 | } 65 | 66 | public void freeSet(VDescriptorSet set) { 67 | int index = pools.indexOf(set.poolHandle); 68 | try (var stack = stackPush()) { 69 | var pDescriptorSets = stack.mallocLong(1).put(0, set.set); 70 | _CHECK_(vkFreeDescriptorSets(ctx.device, set.poolHandle, pDescriptorSets)); 71 | } 72 | poolFreeSizes.set(index, poolFreeSizes.get(index) + 1); 73 | if (poolFreeSizes.get(index) == nSetsPerPool) { 74 | vkDestroyDescriptorPool(ctx.device, set.poolHandle, null); 75 | pools.remove(index); 76 | poolFreeSizes.remove(index); 77 | } 78 | } 79 | 80 | @Override 81 | public void free() { 82 | free0(); 83 | for (long pool : pools) { 84 | vkDestroyDescriptorPool(ctx.device, pool, null); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/memory/HandleDescriptorManger.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.memory; 2 | 3 | import com.sun.jna.Pointer; 4 | import com.sun.jna.platform.linux.LibC; 5 | import com.sun.jna.platform.win32.Kernel32; 6 | import com.sun.jna.platform.win32.WinNT; 7 | import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; 8 | import me.cortex.vulkanite.client.Vulkanite; 9 | 10 | public class HandleDescriptorManger { 11 | private static final Long2IntOpenHashMap USED_HANDLE_DESCRIPTORS = new Long2IntOpenHashMap(); 12 | public static void add(long handleDescriptor) { 13 | synchronized (USED_HANDLE_DESCRIPTORS) { 14 | USED_HANDLE_DESCRIPTORS.addTo(handleDescriptor, 1); 15 | } 16 | } 17 | 18 | public static void close(long handleDescriptor) { 19 | synchronized (USED_HANDLE_DESCRIPTORS) { 20 | int val = USED_HANDLE_DESCRIPTORS.addTo(handleDescriptor, -1); 21 | if (val <= 0) { 22 | throw new IllegalStateException(); 23 | } 24 | if (val == 1) { 25 | USED_HANDLE_DESCRIPTORS.remove(handleDescriptor); 26 | if (Vulkanite.IS_WINDOWS) { 27 | if (!Kernel32.INSTANCE.CloseHandle(new WinNT.HANDLE(new Pointer(handleDescriptor)))) { 28 | throw new IllegalStateException(); 29 | } 30 | } else { 31 | if (LibC.INSTANCE.close((int) handleDescriptor) != 0) { 32 | throw new IllegalStateException(); 33 | } 34 | } 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/memory/UploadStream.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.memory; 2 | 3 | //Uses a host visible, client mapped buffer to stream data to the gpu, can use fence or something to signal once the 4 | // data is free 5 | 6 | import me.cortex.vulkanite.lib.cmd.VCmdBuff; 7 | 8 | public class UploadStream { 9 | 10 | public long malloc(long size) { 11 | return -1; 12 | } 13 | 14 | public void upload(long addr, VCmdBuff cmd) { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/memory/VAccelerationStructure.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.memory; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import org.lwjgl.system.MemoryStack; 5 | import org.lwjgl.vulkan.VkAccelerationStructureDeviceAddressInfoKHR; 6 | import org.lwjgl.vulkan.VkDevice; 7 | 8 | import java.util.concurrent.atomic.AtomicInteger; 9 | import java.util.concurrent.atomic.AtomicLong; 10 | 11 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 12 | import static org.lwjgl.vulkan.KHRAccelerationStructure.*; 13 | 14 | public class VAccelerationStructure extends TrackedResourceObject { 15 | public final long structure; 16 | public final VBuffer buffer; 17 | public final long deviceAddress; 18 | private final VkDevice device; 19 | 20 | VAccelerationStructure(VkDevice device, long structure, VBuffer buffer) { 21 | this.device = device; 22 | this.buffer = buffer; 23 | this.structure = structure; 24 | try (MemoryStack stack = MemoryStack.stackPush()){ 25 | deviceAddress = vkGetAccelerationStructureDeviceAddressKHR(device, 26 | VkAccelerationStructureDeviceAddressInfoKHR 27 | .calloc(stack) 28 | .sType$Default() 29 | .accelerationStructure(structure)); 30 | } 31 | } 32 | 33 | public void free() { 34 | free0(); 35 | vkDestroyAccelerationStructureKHR(device, structure, null); 36 | buffer.free(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/memory/VBuffer.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.memory; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | 5 | import static org.lwjgl.vulkan.VK10.VK_WHOLE_SIZE; 6 | 7 | public class VBuffer extends TrackedResourceObject { 8 | private VmaAllocator.BufferAllocation allocation; 9 | 10 | VBuffer(VmaAllocator.BufferAllocation allocation) { 11 | this.allocation = allocation; 12 | } 13 | 14 | public long buffer() { 15 | return allocation.buffer; 16 | } 17 | 18 | public void free() { 19 | free0(); 20 | allocation.free(); 21 | allocation = null; 22 | } 23 | 24 | public long deviceAddress() { 25 | if (allocation.deviceAddress == -1) 26 | throw new IllegalStateException(); 27 | return allocation.deviceAddress; 28 | } 29 | 30 | public long map() { 31 | return allocation.map(); 32 | } 33 | 34 | public void unmap() { 35 | allocation.unmap(); 36 | } 37 | 38 | public void flush() { 39 | allocation.flush(0, VK_WHOLE_SIZE); 40 | } 41 | 42 | public void flush(long offset, long size) { 43 | allocation.flush(offset, size); 44 | } 45 | 46 | public long size() { 47 | return allocation.size(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/memory/VGBuffer.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.memory; 2 | 3 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_GL_ERROR_; 4 | import static org.lwjgl.opengl.GL15C.glDeleteBuffers; 5 | 6 | public class VGBuffer extends VBuffer { 7 | public final int glId; 8 | private final long vkMemory; 9 | VGBuffer(VmaAllocator.BufferAllocation allocation, int glId) { 10 | super(allocation); 11 | this.glId = glId; 12 | this.vkMemory = allocation.ai.deviceMemory(); 13 | } 14 | 15 | @Override 16 | public void free() { 17 | glDeleteBuffers(glId); 18 | _CHECK_GL_ERROR_(); 19 | MemoryManager.ExternalMemoryTracker.release(this.vkMemory); 20 | super.free(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/memory/VGImage.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.memory; 2 | 3 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_GL_ERROR_; 4 | import static org.lwjgl.opengl.GL11C.glDeleteTextures; 5 | 6 | public class VGImage extends VImage { 7 | public final int glId; 8 | public final int glFormat; 9 | private final long vkMemory; 10 | 11 | VGImage(VmaAllocator.ImageAllocation allocation, int width, int height, int depth, int mipLayers, int format, int glFormat, int glId) { 12 | super(allocation, width, height, depth, mipLayers, format); 13 | this.glId = glId; 14 | this.glFormat = glFormat; 15 | this.vkMemory = allocation.ai.deviceMemory(); 16 | } 17 | 18 | public void free() { 19 | glDeleteTextures(glId); 20 | _CHECK_GL_ERROR_(); 21 | MemoryManager.ExternalMemoryTracker.release(this.vkMemory); 22 | super.free(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/memory/VImage.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.memory; 2 | 3 | import java.lang.ref.Cleaner; 4 | 5 | public class VImage { 6 | protected VmaAllocator.ImageAllocation allocation; 7 | public final int width; 8 | public final int height; 9 | public final int depth; 10 | public final int mipLayers; 11 | public final int format; 12 | 13 | public final int dimensions; 14 | 15 | VImage(VmaAllocator.ImageAllocation allocation, int width, int height, int depth, int mipLayers, int format) { 16 | this.allocation = allocation; 17 | this.width = width; 18 | this.height = height; 19 | this.mipLayers = mipLayers; 20 | this.format = format; 21 | this.depth = depth; 22 | 23 | int dimensions = 3; 24 | 25 | if (height == 1 && depth == 1) { 26 | dimensions = 1; 27 | } 28 | else if(height != 1 && depth == 1) { 29 | dimensions = 2; 30 | } 31 | 32 | this.dimensions = dimensions; 33 | } 34 | 35 | public void free() { 36 | allocation.free(); 37 | allocation = null; 38 | } 39 | 40 | public long image() { 41 | return allocation.image; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/other/FormatConverter.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.other; 2 | 3 | import net.coderbot.iris.gl.texture.InternalTextureFormat; 4 | 5 | import static org.lwjgl.opengl.GL11C.GL_RGB8; 6 | import static org.lwjgl.opengl.GL11C.GL_RGBA16; 7 | import static org.lwjgl.opengl.GL11C.GL_RGBA8; 8 | import static org.lwjgl.opengl.GL30C.*; 9 | import static org.lwjgl.opengl.GL30C.GL_R16F; 10 | import static org.lwjgl.vulkan.VK10.*; 11 | 12 | public class FormatConverter { 13 | public static int getVkFormatFromGl(InternalTextureFormat format) { 14 | // TODO: Support 3 component types 15 | 16 | return switch (format.getGlFormat()) { 17 | // Weird formats 18 | case GL_R11F_G11F_B10F -> VK_FORMAT_B10G11R11_UFLOAT_PACK32; 19 | case GL_RGB10_A2, GL_RGB10 -> VK_FORMAT_A2B10G10R10_UNORM_PACK32; 20 | case GL_RGB5, GL_RGB5_A1 -> VK_FORMAT_A1R5G5B5_UNORM_PACK16; 21 | case GL_RGB9_E5 -> VK_FORMAT_E5B9G9R9_UFLOAT_PACK32; 22 | 23 | // Floats 24 | case GL_RGB32F, GL_RGBA32F -> VK_FORMAT_R32G32B32A32_SFLOAT; 25 | case GL_RGB16F, GL_RGBA16F -> VK_FORMAT_R16G16B16A16_SFLOAT; 26 | case GL_RG16F -> VK_FORMAT_R16G16_SFLOAT; 27 | case GL_R16F -> VK_FORMAT_R16_SFLOAT; 28 | 29 | // Unorms 30 | case GL_RGB16, GL_RGBA16 -> VK_FORMAT_R16G16B16A16_UNORM; 31 | case GL_RG16 -> VK_FORMAT_R16G16_UNORM; 32 | case GL_R16 -> VK_FORMAT_R16_UNORM; 33 | case GL_RGBA, GL_RGB8, GL_RGBA8 -> VK_FORMAT_R8G8B8A8_UNORM; 34 | case GL_RG8 -> VK_FORMAT_R8G8_UNORM; 35 | case GL_R8 -> VK_FORMAT_R8_UNORM; 36 | 37 | // Ints 38 | case GL_RGB32I, GL_RGBA32I -> VK_FORMAT_R32G32B32A32_SINT; 39 | case GL_RG32I -> VK_FORMAT_R32G32_SINT; 40 | case GL_R32I -> VK_FORMAT_R32_SINT; 41 | case GL_RGB32UI, GL_RGBA32UI -> VK_FORMAT_R32G32B32A32_UINT; 42 | case GL_RG32UI -> VK_FORMAT_R32G32_UINT; 43 | case GL_R32UI -> VK_FORMAT_R32_UINT; 44 | case GL_RGB16I, GL_RGBA16I -> VK_FORMAT_R16G16B16A16_SINT; 45 | case GL_RG16I -> VK_FORMAT_R16G16_SINT; 46 | case GL_R16I -> VK_FORMAT_R16_SINT; 47 | case GL_RGB16UI, GL_RGBA16UI -> VK_FORMAT_R16G16B16A16_UINT; 48 | case GL_RG16UI -> VK_FORMAT_R16G16_UINT; 49 | case GL_R16UI -> VK_FORMAT_R16_UINT; 50 | case GL_RGB8I, GL_RGBA8I -> VK_FORMAT_R8G8B8A8_SINT; 51 | case GL_RG8I -> VK_FORMAT_R8G8_SINT; 52 | case GL_R8I -> VK_FORMAT_R8_SINT; 53 | case GL_RGB8UI, GL_RGBA8UI -> VK_FORMAT_R8G8B8A8_UINT; 54 | case GL_RG8UI -> VK_FORMAT_R8G8_UINT; 55 | case GL_R8UI -> VK_FORMAT_R8_UINT; 56 | 57 | default -> { 58 | throw new IllegalArgumentException("No known conversion to VK type for GL type " + format + " (" + format.getGlFormat() + ")."); 59 | } 60 | }; 61 | } 62 | 63 | public static InternalTextureFormat findFormatFromGlFormat(int glFormat) { 64 | InternalTextureFormat[] availableFormats = InternalTextureFormat.values(); 65 | 66 | for (InternalTextureFormat format : availableFormats) { 67 | if(format.getGlFormat() == glFormat) { 68 | return format; 69 | } 70 | } 71 | 72 | return null; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/other/VImageView.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.other; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import me.cortex.vulkanite.lib.base.VContext; 5 | import me.cortex.vulkanite.lib.memory.VImage; 6 | import org.lwjgl.vulkan.VkImageViewCreateInfo; 7 | 8 | import java.nio.LongBuffer; 9 | 10 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 11 | import static org.lwjgl.system.MemoryStack.stackPush; 12 | import static org.lwjgl.vulkan.VK10.*; 13 | 14 | public class VImageView extends TrackedResourceObject { 15 | private final VContext ctx; 16 | public final VImage image; 17 | public final long view; 18 | public VImageView(VContext ctx, VImage image) { 19 | this.ctx = ctx; 20 | this.image = image; 21 | 22 | int imageViewType = switch (image.dimensions) { 23 | case 1 -> VK_IMAGE_VIEW_TYPE_1D; 24 | case 2 -> VK_IMAGE_VIEW_TYPE_2D; 25 | case 3 -> VK_IMAGE_VIEW_TYPE_3D; 26 | default -> -1; 27 | }; 28 | 29 | try (var stack = stackPush()) { 30 | LongBuffer view = stack.callocLong(1); 31 | var vci = VkImageViewCreateInfo.calloc(stack) 32 | .sType$Default() 33 | .viewType(imageViewType) 34 | .format(image.format) 35 | .image(image.image()); 36 | vci.subresourceRange() 37 | .aspectMask(VK_IMAGE_ASPECT_COLOR_BIT) 38 | .layerCount(1) 39 | .levelCount(1); 40 | _CHECK_(vkCreateImageView(ctx.device, vci, null, view)); 41 | this.view = view.get(0); 42 | } 43 | } 44 | 45 | public void free() { 46 | free0(); 47 | vkDestroyImageView(ctx.device, view, null); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/other/VQueryPool.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.other; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import me.cortex.vulkanite.lib.cmd.VCmdBuff; 5 | import org.lwjgl.system.MemoryStack; 6 | import org.lwjgl.vulkan.VkCommandBuffer; 7 | import org.lwjgl.vulkan.VkDevice; 8 | import org.lwjgl.vulkan.VkQueryPoolCreateInfo; 9 | 10 | import java.nio.LongBuffer; 11 | 12 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 13 | import static org.lwjgl.system.MemoryStack.stackPush; 14 | import static org.lwjgl.vulkan.VK10.*; 15 | 16 | public class VQueryPool extends TrackedResourceObject { 17 | public final long pool; 18 | private final VkDevice device; 19 | public VQueryPool(VkDevice device, int count, int type) { 20 | this.device = device; 21 | try (MemoryStack stack = stackPush()) { 22 | LongBuffer pQueryPool = stack.mallocLong(1); 23 | _CHECK_(vkCreateQueryPool(device, 24 | VkQueryPoolCreateInfo 25 | .calloc(stack) 26 | .sType$Default() 27 | .queryCount(count) 28 | .queryType(type), 29 | null, pQueryPool), "Failed to create query pool"); 30 | pool = pQueryPool.get(0); 31 | } 32 | } 33 | 34 | public void reset(VCmdBuff cmd, int first, int size) { 35 | reset(cmd.buffer, first, size); 36 | } 37 | 38 | public void reset(VkCommandBuffer cmd, int first, int size) { 39 | vkCmdResetQueryPool(cmd, pool, first, size); 40 | } 41 | 42 | public long[] getResultsLong(int count) { 43 | return getResultsLong(0, count, VK_QUERY_RESULT_WAIT_BIT); 44 | } 45 | 46 | public long[] getResultsLong(int start, int count, int flags) { 47 | try (var stack = stackPush()) { 48 | LongBuffer results = stack.mallocLong(count); 49 | _CHECK_(vkGetQueryPoolResults(device, pool, start, count, results, Long.BYTES, VK_QUERY_RESULT_64_BIT | flags)); 50 | var res = new long[count]; 51 | results.get(res); 52 | return res; 53 | } 54 | } 55 | 56 | public void free() { 57 | free0(); 58 | vkDestroyQueryPool(device, pool, null); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/other/VSampler.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.other; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import me.cortex.vulkanite.lib.base.VContext; 5 | import org.lwjgl.system.MemoryStack; 6 | import org.lwjgl.vulkan.VkSamplerCreateInfo; 7 | 8 | import java.nio.LongBuffer; 9 | import java.util.function.Consumer; 10 | 11 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 12 | import static org.lwjgl.system.MemoryStack.stackPush; 13 | import static org.lwjgl.vulkan.VK10.*; 14 | 15 | public class VSampler extends TrackedResourceObject { 16 | private final VContext ctx; 17 | public final long sampler; 18 | 19 | public VSampler(VContext context, Consumer setup) { 20 | this.ctx = context; 21 | try (MemoryStack stack = stackPush()) { 22 | LongBuffer pSampler = stack.mallocLong(1); 23 | var create = VkSamplerCreateInfo 24 | .calloc(stack) 25 | .sType$Default(); 26 | setup.accept(create); 27 | _CHECK_(vkCreateSampler(ctx.device, create, null, pSampler), 28 | "Failed to create sampler"); 29 | sampler = pSampler.get(0); 30 | } 31 | } 32 | 33 | @Override 34 | public void free() { 35 | free0(); 36 | vkDestroySampler(ctx.device, sampler, null); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/other/VUtil.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.other; 2 | 3 | import org.lwjgl.system.MemoryStack; 4 | 5 | import java.nio.LongBuffer; 6 | 7 | import static org.lwjgl.opengl.GL11C.GL_NO_ERROR; 8 | import static org.lwjgl.opengl.GL11C.glGetError; 9 | import static org.lwjgl.vulkan.EXTDebugReport.VK_ERROR_VALIDATION_FAILED_EXT; 10 | import static org.lwjgl.vulkan.KHRDisplaySwapchain.VK_ERROR_INCOMPATIBLE_DISPLAY_KHR; 11 | import static org.lwjgl.vulkan.KHRSurface.VK_ERROR_NATIVE_WINDOW_IN_USE_KHR; 12 | import static org.lwjgl.vulkan.KHRSurface.VK_ERROR_SURFACE_LOST_KHR; 13 | import static org.lwjgl.vulkan.KHRSwapchain.VK_ERROR_OUT_OF_DATE_KHR; 14 | import static org.lwjgl.vulkan.KHRSwapchain.VK_SUBOPTIMAL_KHR; 15 | import static org.lwjgl.vulkan.VK10.*; 16 | 17 | public class VUtil { 18 | public static String translateVulkanResult(int result) { 19 | switch (result) { 20 | // Success codes 21 | case VK_SUCCESS: 22 | return "Command successfully completed."; 23 | case VK_NOT_READY: 24 | return "A fence or query has not yet completed."; 25 | case VK_TIMEOUT: 26 | return "A wait operation has not completed in the specified time."; 27 | case VK_EVENT_SET: 28 | return "An event is signaled."; 29 | case VK_EVENT_RESET: 30 | return "An event is unsignaled."; 31 | case VK_INCOMPLETE: 32 | return "A return array was too small for the result."; 33 | case VK_SUBOPTIMAL_KHR: 34 | return "A swapchain no longer matches the surface properties exactly, but can still be used to present to the surface successfully."; 35 | 36 | // Error codes 37 | case VK_ERROR_OUT_OF_HOST_MEMORY: 38 | return "A host memory allocation has failed."; 39 | case VK_ERROR_OUT_OF_DEVICE_MEMORY: 40 | return "A device memory allocation has failed."; 41 | case VK_ERROR_INITIALIZATION_FAILED: 42 | return "Initialization of an object could not be completed for implementation-specific reasons."; 43 | case VK_ERROR_DEVICE_LOST: 44 | return "The logical or physical device has been lost."; 45 | case VK_ERROR_MEMORY_MAP_FAILED: 46 | return "Mapping of a memory object has failed."; 47 | case VK_ERROR_LAYER_NOT_PRESENT: 48 | return "A requested layer is not present or could not be loaded."; 49 | case VK_ERROR_EXTENSION_NOT_PRESENT: 50 | return "A requested extension is not supported."; 51 | case VK_ERROR_FEATURE_NOT_PRESENT: 52 | return "A requested feature is not supported."; 53 | case VK_ERROR_INCOMPATIBLE_DRIVER: 54 | return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible for implementation-specific reasons."; 55 | case VK_ERROR_TOO_MANY_OBJECTS: 56 | return "Too many objects of the type have already been created."; 57 | case VK_ERROR_FORMAT_NOT_SUPPORTED: 58 | return "A requested format is not supported on this device."; 59 | case VK_ERROR_SURFACE_LOST_KHR: 60 | return "A surface is no longer available."; 61 | case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: 62 | return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API."; 63 | case VK_ERROR_OUT_OF_DATE_KHR: 64 | return "A surface has changed in such a way that it is no longer compatible with the swapchain, and further presentation requests using the " 65 | + "swapchain will fail. Applications must query the new surface properties and recreate their swapchain if they wish to continue" 66 | + "presenting to the surface."; 67 | case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: 68 | return "The display used by a swapchain does not use the same presentable image layout, or is incompatible in a way that prevents sharing an" 69 | + " image."; 70 | case VK_ERROR_VALIDATION_FAILED_EXT: 71 | return "A validation layer found an error."; 72 | default: 73 | return String.format("%s [%d]", "Unknown", Integer.valueOf(result)); 74 | } 75 | } 76 | 77 | public static void _CHECK_(int ret) { 78 | _CHECK_(ret, ""); 79 | } 80 | 81 | public static void _CHECK_(int ret, String msg) { 82 | if (ret != VK_SUCCESS) 83 | throw new AssertionError(msg + ": " + translateVulkanResult(ret)); 84 | } 85 | 86 | public static LongBuffer repeat(MemoryStack stack, long value, int count) { 87 | LongBuffer ret = stack.mallocLong(count); 88 | for (int i = 0; i < count; i++) { 89 | ret.put(i, value); 90 | } 91 | return ret; 92 | } 93 | 94 | public static void _CHECK_GL_ERROR_() { 95 | int e = glGetError(); 96 | if (e != GL_NO_ERROR) { 97 | throw new AssertionError("Gl error: "+e); 98 | } 99 | } 100 | 101 | 102 | public static int alignUp(int size, int alignment) { 103 | return (size + alignment - 1) & -alignment; 104 | } 105 | 106 | public static long alignUp(long size, long alignment) { 107 | return (size + alignment - 1) & -alignment; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/other/sync/SyncManager.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.other.sync; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.cortex.vulkanite.lib.memory.HandleDescriptorManger; 5 | import org.lwjgl.PointerBuffer; 6 | import org.lwjgl.vulkan.*; 7 | 8 | import java.nio.IntBuffer; 9 | import java.nio.LongBuffer; 10 | import java.util.HashMap; 11 | import java.util.LinkedList; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 16 | import static org.lwjgl.opengl.EXTMemoryObjectFD.GL_HANDLE_TYPE_OPAQUE_FD_EXT; 17 | import static org.lwjgl.opengl.EXTMemoryObjectFD.glImportMemoryFdEXT; 18 | import static org.lwjgl.opengl.EXTSemaphore.glGenSemaphoresEXT; 19 | import static org.lwjgl.opengl.EXTSemaphore.glIsSemaphoreEXT; 20 | import static org.lwjgl.opengl.EXTSemaphoreFD.glImportSemaphoreFdEXT; 21 | import static org.lwjgl.opengl.EXTSemaphoreWin32.GL_HANDLE_TYPE_OPAQUE_WIN32_EXT; 22 | import static org.lwjgl.opengl.EXTSemaphoreWin32.glImportSemaphoreWin32HandleEXT; 23 | import static org.lwjgl.opengl.GL11C.glGetError; 24 | import static org.lwjgl.opengl.KHRRobustness.GL_NO_ERROR; 25 | import static org.lwjgl.system.MemoryStack.stackPush; 26 | import static org.lwjgl.vulkan.KHRExternalSemaphoreFd.vkGetSemaphoreFdKHR; 27 | import static org.lwjgl.vulkan.KHRExternalSemaphoreWin32.vkGetSemaphoreWin32HandleKHR; 28 | import static org.lwjgl.vulkan.VK10.*; 29 | import static org.lwjgl.vulkan.VK11.VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; 30 | import static org.lwjgl.vulkan.VK11.VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT; 31 | 32 | //TODO: the sync manager (probably rename) manages all sync operations 33 | // should expand it to also add a fence watcher, that is can register a callback on a fence to wait for completion 34 | // use this to add a cleanup system for e.g. single use command buffers is a good example, the fences themselves 35 | // semaphores, scratch/temp buffers etc 36 | public class SyncManager { 37 | private static final int EXTERNAL_SEMAPHORE_TYPE = Vulkanite.IS_WINDOWS?VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT:VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; 38 | private final VkDevice device; 39 | public SyncManager(VkDevice device) { 40 | this.device = device; 41 | } 42 | 43 | public VFence createFence() { 44 | try (var stack = stackPush()) { 45 | LongBuffer res = stack.callocLong(1); 46 | _CHECK_(vkCreateFence(device, VkFenceCreateInfo.calloc(stack).sType$Default(), null, res)); 47 | return new VFence(device, res.get(0)); 48 | } 49 | } 50 | 51 | private VGSemaphore createSharedBinarySemaphoreWin32() { 52 | try (var stack = stackPush()) { 53 | LongBuffer res = stack.callocLong(1); 54 | _CHECK_(vkCreateSemaphore(device, 55 | VkSemaphoreCreateInfo.calloc(stack) 56 | .sType$Default() 57 | .pNext(VkExportSemaphoreCreateInfo.calloc(stack) 58 | .sType$Default() 59 | .handleTypes(EXTERNAL_SEMAPHORE_TYPE)), 60 | null, res)); 61 | long semaphore = res.get(0); 62 | 63 | PointerBuffer pb = stack.callocPointer(1); 64 | _CHECK_(vkGetSemaphoreWin32HandleKHR(device, 65 | VkSemaphoreGetWin32HandleInfoKHR.calloc(stack) 66 | .sType$Default() 67 | .semaphore(semaphore) 68 | .handleType(EXTERNAL_SEMAPHORE_TYPE), 69 | pb)); 70 | 71 | if (pb.get(0)== 0) { 72 | throw new IllegalStateException(); 73 | } 74 | HandleDescriptorManger.add(pb.get(0)); 75 | 76 | int glSemaphore = glGenSemaphoresEXT(); 77 | glImportSemaphoreWin32HandleEXT(glSemaphore, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, pb.get(0)); 78 | if (!glIsSemaphoreEXT(glSemaphore)) 79 | throw new IllegalStateException(); 80 | if (glGetError() != GL_NO_ERROR) 81 | throw new IllegalStateException(); 82 | 83 | return new VGSemaphore(device, semaphore, glSemaphore, pb.get(0)); 84 | } 85 | } 86 | 87 | private VGSemaphore createSharedBinarySemaphoreFd() { 88 | try (var stack = stackPush()) { 89 | LongBuffer res = stack.callocLong(1); 90 | _CHECK_(vkCreateSemaphore(device, 91 | VkSemaphoreCreateInfo.calloc(stack) 92 | .sType$Default() 93 | .pNext(VkExportSemaphoreCreateInfo.calloc(stack) 94 | .sType$Default() 95 | .handleTypes(EXTERNAL_SEMAPHORE_TYPE)), 96 | null, res)); 97 | long semaphore = res.get(0); 98 | 99 | IntBuffer fd = stack.callocInt(1); 100 | _CHECK_(vkGetSemaphoreFdKHR(device, 101 | VkSemaphoreGetFdInfoKHR.calloc(stack) 102 | .sType$Default() 103 | .semaphore(semaphore) 104 | .handleType(EXTERNAL_SEMAPHORE_TYPE), 105 | fd)); 106 | 107 | if (fd.get(0)== 0) { 108 | throw new IllegalStateException(); 109 | } 110 | HandleDescriptorManger.add(fd.get(0)); 111 | 112 | int glSemaphore = glGenSemaphoresEXT(); 113 | glImportSemaphoreFdEXT(glSemaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd.get(0)); 114 | if (!glIsSemaphoreEXT(glSemaphore)) 115 | throw new IllegalStateException(); 116 | if (glGetError() != GL_NO_ERROR) 117 | throw new IllegalStateException(); 118 | 119 | return new VGSemaphore(device, semaphore, glSemaphore, fd.get(0)); 120 | } 121 | } 122 | 123 | public VGSemaphore createSharedBinarySemaphore() { 124 | return Vulkanite.IS_WINDOWS?createSharedBinarySemaphoreWin32():createSharedBinarySemaphoreFd(); 125 | } 126 | 127 | public VSemaphore createBinarySemaphore() { 128 | try (var stack = stackPush()) { 129 | LongBuffer res = stack.callocLong(1); 130 | _CHECK_(vkCreateSemaphore(device, VkSemaphoreCreateInfo.calloc(stack).sType$Default(), null, res)); 131 | return new VSemaphore(device, res.get(0)); 132 | } 133 | } 134 | 135 | //TODO: MAKE THIS LOCKFREE 136 | 137 | private final Map> callbacks = new HashMap<>(); 138 | public void addCallback(VFence fence, Runnable callback) { 139 | //The "issue" with this is that since its multithreaded there is a very very small case that (even with lock free) concurrent hashmap 140 | // the only (simple) way to guarentee this is never the case without locks is to ensure that add callback is called before 141 | // a fence can ever be marked as signaled 142 | synchronized (callbacks) { 143 | callbacks.computeIfAbsent(fence, a->new LinkedList<>()).add(callback); 144 | } 145 | } 146 | 147 | //TODO: optimize this 148 | public void checkFences() { 149 | synchronized (callbacks) { 150 | List toRemove = new LinkedList<>(); 151 | for (var cb : callbacks.entrySet()) { 152 | int status = vkGetFenceStatus(device, cb.getKey().address()); 153 | if (status == VK_SUCCESS) { 154 | cb.getValue().forEach(Runnable::run); 155 | toRemove.add(cb.getKey()); 156 | } else if (status == VK_NOT_READY) { 157 | continue; 158 | } 159 | _CHECK_(status); 160 | } 161 | toRemove.forEach(callbacks::remove); 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/other/sync/VFence.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.other.sync; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import org.lwjgl.system.Pointer; 5 | import org.lwjgl.vulkan.VkDevice; 6 | 7 | import java.util.Objects; 8 | 9 | import static org.lwjgl.vulkan.VK10.vkDestroyFence; 10 | 11 | public final class VFence extends TrackedResourceObject implements Pointer { 12 | private final VkDevice device; 13 | private final long fence; 14 | 15 | public VFence(VkDevice device, long fence) { 16 | this.device = device; 17 | this.fence = fence; 18 | } 19 | 20 | @Override 21 | public long address() { 22 | return fence; 23 | } 24 | 25 | public void free() { 26 | free0(); 27 | vkDestroyFence(device, fence, null); 28 | } 29 | 30 | @Override 31 | public boolean equals(Object obj) { 32 | if (obj == this) 33 | return true; 34 | if (obj == null || obj.getClass() != this.getClass()) 35 | return false; 36 | var that = (VFence) obj; 37 | return Objects.equals(this.device, that.device) && 38 | this.fence == that.fence; 39 | } 40 | 41 | @Override 42 | public int hashCode() { 43 | return Objects.hash(device, fence); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/other/sync/VGSemaphore.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.other.sync; 2 | 3 | import me.cortex.vulkanite.lib.memory.HandleDescriptorManger; 4 | import me.cortex.vulkanite.lib.memory.MemoryManager; 5 | import org.lwjgl.vulkan.VkDevice; 6 | 7 | import static org.lwjgl.opengl.EXTSemaphore.*; 8 | 9 | public class VGSemaphore extends VSemaphore { 10 | public final int glSemaphore; 11 | private final long handleDescriptor; 12 | 13 | public VGSemaphore(VkDevice device, long semaphore, int glSemaphore, long handleDescriptor) { 14 | super(device, semaphore); 15 | this.glSemaphore = glSemaphore; 16 | this.handleDescriptor = handleDescriptor; 17 | } 18 | 19 | @Override 20 | public void free() { 21 | HandleDescriptorManger.close(handleDescriptor); 22 | glDeleteSemaphoresEXT(glSemaphore); 23 | super.free(); 24 | } 25 | 26 | //Note: dstLayout is for the textures 27 | public void glSignal(int[] buffers, int[] textures, int[] dstLayouts) { 28 | glSignalSemaphoreEXT(glSemaphore, buffers, textures, dstLayouts); 29 | } 30 | 31 | //Note: srcLayout is for the textures 32 | public void glWait(int[] buffers, int[] textures, int[] srcLayouts) { 33 | glWaitSemaphoreEXT(glSemaphore, buffers, textures, srcLayouts); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/other/sync/VSemaphore.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.other.sync; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import org.lwjgl.system.Pointer; 5 | import org.lwjgl.vulkan.VkDevice; 6 | 7 | import java.util.Objects; 8 | 9 | import static org.lwjgl.vulkan.VK10.vkDestroySemaphore; 10 | 11 | public class VSemaphore extends TrackedResourceObject implements Pointer { 12 | private final VkDevice device; 13 | private final long semaphore; 14 | 15 | public VSemaphore(VkDevice device, long semaphore) { 16 | this.device = device; 17 | this.semaphore = semaphore; 18 | } 19 | 20 | @Override 21 | public long address() { 22 | return semaphore; 23 | } 24 | 25 | public void free() { 26 | free0(); 27 | vkDestroySemaphore(device, semaphore, null); 28 | } 29 | 30 | public VkDevice device() { 31 | return device; 32 | } 33 | 34 | public long semaphore() { 35 | return semaphore; 36 | } 37 | 38 | @Override 39 | public boolean equals(Object obj) { 40 | if (obj == this) 41 | return true; 42 | if (obj == null || obj.getClass() != this.getClass()) 43 | return false; 44 | var that = (VSemaphore) obj; 45 | return Objects.equals(this.device, that.device) && 46 | this.semaphore == that.semaphore; 47 | } 48 | 49 | @Override 50 | public int hashCode() { 51 | return Objects.hash(device, semaphore); 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return "VSemaphore[" + 57 | "device=" + device + ", " + 58 | "semaphore=" + semaphore + ']'; 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/pipeline/ComputePipelineBuilder.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.pipeline; 2 | 3 | import me.cortex.vulkanite.lib.base.VContext; 4 | import me.cortex.vulkanite.lib.descriptors.VDescriptorSetLayout; 5 | import me.cortex.vulkanite.lib.shader.ShaderModule; 6 | import org.lwjgl.vulkan.*; 7 | 8 | import java.nio.LongBuffer; 9 | import java.util.*; 10 | 11 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 12 | import static me.cortex.vulkanite.lib.other.VUtil.alignUp; 13 | import static org.lwjgl.system.MemoryStack.stackPush; 14 | import static org.lwjgl.system.MemoryUtil.memCopy; 15 | import static org.lwjgl.vulkan.VK10.*; 16 | 17 | public class ComputePipelineBuilder { 18 | public ComputePipelineBuilder() { 19 | 20 | } 21 | 22 | Set layouts = new LinkedHashSet<>(); 23 | public ComputePipelineBuilder addLayout(VDescriptorSetLayout layout) { 24 | layouts.add(layout); 25 | return this; 26 | } 27 | 28 | private ShaderModule compute; 29 | public ComputePipelineBuilder set(ShaderModule shader) { 30 | this.compute = shader; 31 | return this; 32 | } 33 | 34 | private record PushConstant(int size, int offset) {} 35 | private List pushConstants = new ArrayList<>(); 36 | 37 | public void addPushConstantRange(int size, int offset) { 38 | pushConstants.add(new PushConstant(size, offset)); 39 | } 40 | 41 | public VComputePipeline build(VContext context) { 42 | try (var stack = stackPush()) { 43 | 44 | VkPipelineLayoutCreateInfo layoutCreateInfo = VkPipelineLayoutCreateInfo.calloc(stack) 45 | .sType$Default(); 46 | { 47 | //TODO: cleanup and add push constants 48 | layoutCreateInfo.pSetLayouts(stack.longs(layouts.stream().mapToLong(a->a.layout).toArray())); 49 | } 50 | 51 | if (pushConstants.size() > 0) { 52 | var pushConstantRanges = VkPushConstantRange.calloc(pushConstants.size(), stack); 53 | for (int i = 0; i < pushConstants.size(); i++) { 54 | var pushConstant = pushConstants.get(i); 55 | pushConstantRanges.get(i) 56 | .stageFlags(VK_SHADER_STAGE_ALL) 57 | .offset(pushConstant.offset) 58 | .size(pushConstant.size); 59 | } 60 | layoutCreateInfo.pPushConstantRanges(pushConstantRanges); 61 | } 62 | 63 | LongBuffer pLayout = stack.mallocLong(1); 64 | _CHECK_(vkCreatePipelineLayout(context.device, layoutCreateInfo, null, pLayout)); 65 | 66 | VkPipelineShaderStageCreateInfo shaderStage = VkPipelineShaderStageCreateInfo.calloc(stack); 67 | compute.setupStruct(stack, shaderStage); 68 | LongBuffer pPipeline = stack.mallocLong(1); 69 | _CHECK_(vkCreateComputePipelines(context.device, 0, VkComputePipelineCreateInfo.calloc(1, stack) 70 | .sType$Default() 71 | .layout(pLayout.get(0)) 72 | .stage(shaderStage), null, pPipeline)); 73 | 74 | return new VComputePipeline(context, pLayout.get(0), pPipeline.get(0)); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/pipeline/VComputePipeline.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.pipeline; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import me.cortex.vulkanite.lib.base.VContext; 5 | import me.cortex.vulkanite.lib.other.sync.VFence; 6 | 7 | public class VComputePipeline extends TrackedResourceObject { 8 | private final VContext context; 9 | private final long pipeline; 10 | private final long layout; 11 | 12 | public VComputePipeline(VContext context, long layout, long pipeline) { 13 | this.context = context; 14 | this.layout = layout; 15 | this.pipeline = pipeline; 16 | } 17 | 18 | public long layout() { 19 | return layout; 20 | } 21 | 22 | public long pipeline() { 23 | return pipeline; 24 | } 25 | 26 | @Override 27 | public void free() { 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/pipeline/VRaytracePipeline.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.pipeline; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import me.cortex.vulkanite.lib.base.VContext; 5 | import me.cortex.vulkanite.lib.cmd.VCmdBuff; 6 | import me.cortex.vulkanite.lib.memory.VBuffer; 7 | import me.cortex.vulkanite.lib.shader.ShaderModule; 8 | import me.cortex.vulkanite.lib.shader.reflection.ShaderReflection; 9 | import org.lwjgl.vulkan.VkStridedDeviceAddressRegionKHR; 10 | 11 | import java.util.Set; 12 | 13 | import static org.lwjgl.vulkan.KHRRayTracingPipeline.VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; 14 | import static org.lwjgl.vulkan.KHRRayTracingPipeline.vkCmdTraceRaysKHR; 15 | import static org.lwjgl.vulkan.VK10.*; 16 | 17 | public class VRaytracePipeline extends TrackedResourceObject { 18 | private final VContext context; 19 | private final long pipeline; 20 | private final long layout; 21 | private final VBuffer shader_binding_table; 22 | private final VkStridedDeviceAddressRegionKHR gen; 23 | private final VkStridedDeviceAddressRegionKHR miss; 24 | private final VkStridedDeviceAddressRegionKHR hit; 25 | private final VkStridedDeviceAddressRegionKHR callable; 26 | private final Set shadersUsed; 27 | public final ShaderReflection reflection; 28 | 29 | VRaytracePipeline(VContext context, long pipeline, long layout, VBuffer sbtMap, 30 | VkStridedDeviceAddressRegionKHR raygen, 31 | VkStridedDeviceAddressRegionKHR miss, 32 | VkStridedDeviceAddressRegionKHR hit, 33 | VkStridedDeviceAddressRegionKHR callable, 34 | Set shadersUsed, 35 | ShaderReflection reflection) { 36 | 37 | this.context = context; 38 | this.pipeline = pipeline; 39 | this.layout = layout; 40 | this.shader_binding_table = sbtMap; 41 | this.gen = raygen; 42 | this.miss = miss; 43 | this.hit = hit; 44 | this.callable = callable; 45 | this.shadersUsed = shadersUsed; 46 | this.reflection = reflection; 47 | } 48 | 49 | public void bind(VCmdBuff cmd) { 50 | vkCmdBindPipeline(cmd.buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline); 51 | } 52 | 53 | public void trace(VCmdBuff cmd, int width, int height, int depth) { 54 | vkCmdTraceRaysKHR(cmd.buffer, gen, miss, hit, callable, width, height, depth); 55 | } 56 | 57 | public void bindDSet(VCmdBuff cmd, long... descs) { 58 | vkCmdBindDescriptorSets(cmd.buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, layout, 0, descs, null); 59 | } 60 | 61 | public void free() { 62 | free0(); 63 | vkDestroyPipeline(context.device, pipeline, null); 64 | shader_binding_table.free(); 65 | gen.free(); 66 | miss.free(); 67 | hit.free(); 68 | callable.free(); 69 | reflection.freeLayouts(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/shader/ShaderCompiler.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.shader; 2 | 3 | import me.cortex.vulkanite.lib.shader.reflection.ShaderReflection; 4 | 5 | import java.nio.ByteBuffer; 6 | 7 | import static org.lwjgl.util.shaderc.Shaderc.*; 8 | import static org.lwjgl.util.shaderc.Shaderc.shaderc_result_release; 9 | import static org.lwjgl.vulkan.KHRRayTracingPipeline.*; 10 | import static org.lwjgl.vulkan.VK10.*; 11 | 12 | public class ShaderCompiler { 13 | private static int vulkanStageToShadercKind(int stage) { 14 | switch (stage) { 15 | case VK_SHADER_STAGE_VERTEX_BIT: 16 | return shaderc_vertex_shader; 17 | case VK_SHADER_STAGE_FRAGMENT_BIT: 18 | return shaderc_fragment_shader; 19 | case VK_SHADER_STAGE_RAYGEN_BIT_KHR: 20 | return shaderc_raygen_shader; 21 | case VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR: 22 | return shaderc_closesthit_shader; 23 | case VK_SHADER_STAGE_MISS_BIT_KHR: 24 | return shaderc_miss_shader; 25 | case VK_SHADER_STAGE_ANY_HIT_BIT_KHR: 26 | return shaderc_anyhit_shader; 27 | case VK_SHADER_STAGE_INTERSECTION_BIT_KHR: 28 | return shaderc_intersection_shader; 29 | case VK_SHADER_STAGE_COMPUTE_BIT: 30 | return shaderc_compute_shader; 31 | default: 32 | throw new IllegalArgumentException("Stage: " + stage); 33 | } 34 | } 35 | 36 | public static ByteBuffer compileShader(String filename, String source, int vulkanStage) { 37 | long compiler = shaderc_compiler_initialize(); 38 | if (compiler == 0) { 39 | throw new RuntimeException("Failed to create shader compiler"); 40 | } 41 | long options = shaderc_compile_options_initialize(); 42 | shaderc_compile_options_set_target_env(options, shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2); 43 | shaderc_compile_options_set_target_spirv(options, shaderc_spirv_version_1_4); 44 | shaderc_compile_options_set_generate_debug_info(options); 45 | shaderc_compile_options_set_optimization_level(options, shaderc_optimization_level_performance); 46 | 47 | long result = shaderc_compile_into_spv(compiler, source, vulkanStageToShadercKind(vulkanStage), filename, "main", options); 48 | 49 | if (result == 0) { 50 | throw new RuntimeException("Failed to compile shader " + filename + " into SPIR-V"); 51 | } 52 | 53 | if (shaderc_result_get_compilation_status(result) != shaderc_compilation_status_success) { 54 | throw new RuntimeException("Failed to compile shader " + filename + "into SPIR-V:\n " + shaderc_result_get_error_message(result)); 55 | } 56 | shaderc_compile_options_release(options); 57 | shaderc_compiler_release(compiler); 58 | ByteBuffer code = shaderc_result_get_bytes(result); 59 | var ret = ByteBuffer.allocateDirect(code.capacity()).put(code).rewind(); 60 | shaderc_result_release(result); 61 | return ret; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/shader/ShaderModule.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.shader; 2 | 3 | import org.lwjgl.system.MemoryStack; 4 | import org.lwjgl.vulkan.VkPipelineShaderStageCreateInfo; 5 | 6 | public record ShaderModule( 7 | VShader shader, String name) { 8 | public void setupStruct(MemoryStack stack, VkPipelineShaderStageCreateInfo struct) { 9 | struct.sType$Default() 10 | .stage(shader.stage) 11 | .module(shader.module) 12 | .pName(stack.UTF8(name)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/shader/VShader.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.shader; 2 | 3 | import me.cortex.vulkanite.lib.base.TrackedResourceObject; 4 | import me.cortex.vulkanite.lib.base.VContext; 5 | import me.cortex.vulkanite.lib.shader.reflection.ShaderReflection; 6 | import org.lwjgl.vulkan.VkShaderModuleCreateInfo; 7 | 8 | import java.nio.ByteBuffer; 9 | import java.nio.LongBuffer; 10 | 11 | import static me.cortex.vulkanite.lib.other.VUtil._CHECK_; 12 | import static org.lwjgl.system.MemoryStack.stackPush; 13 | import static org.lwjgl.util.shaderc.Shaderc.*; 14 | import static org.lwjgl.vulkan.KHRRayTracingPipeline.*; 15 | import static org.lwjgl.vulkan.VK10.*; 16 | 17 | public class VShader extends TrackedResourceObject { 18 | private final VContext ctx; 19 | public final long module; 20 | public final int stage; 21 | public final ShaderReflection reflection; 22 | 23 | public ShaderReflection getReflection() { 24 | return reflection; 25 | } 26 | 27 | public VShader(VContext ctx, long module, int stage, ShaderReflection reflection) { 28 | this.ctx = ctx; 29 | this.module = module; 30 | this.stage = stage; 31 | this.reflection = reflection; 32 | } 33 | 34 | public ShaderModule named() { 35 | return named("main"); 36 | } 37 | 38 | public ShaderModule named(String name) { 39 | return new ShaderModule(this, name); 40 | } 41 | 42 | public static VShader compileLoad(VContext ctx, String source, int stage) { 43 | try (var stack = stackPush()) { 44 | ByteBuffer code = ShaderCompiler.compileShader("shader", source, stage); 45 | 46 | ShaderReflection reflection = new ShaderReflection(code); 47 | 48 | VkShaderModuleCreateInfo createInfo = VkShaderModuleCreateInfo.calloc(stack) 49 | .sType$Default() 50 | .pCode(code); 51 | LongBuffer pShaderModule = stack.mallocLong(1); 52 | _CHECK_(vkCreateShaderModule(ctx.device, createInfo, null, pShaderModule)); 53 | return new VShader(ctx, pShaderModule.get(0), stage, reflection); 54 | } 55 | } 56 | 57 | @Override 58 | public void free() { 59 | free0(); 60 | vkDestroyShaderModule(ctx.device, module, null); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/lib/shader/reflection/ResourceType.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.lib.shader.reflection; 2 | 3 | import static org.lwjgl.util.spvc.Spvc.*; 4 | import static org.lwjgl.vulkan.KHRAccelerationStructure.VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; 5 | import static org.lwjgl.vulkan.VK10.*; 6 | 7 | public enum ResourceType { 8 | UNIFORM_BUFFER(SPVC_RESOURCE_TYPE_UNIFORM_BUFFER), 9 | STORAGE_BUFFER(SPVC_RESOURCE_TYPE_STORAGE_BUFFER), 10 | STAGE_INPUT(SPVC_RESOURCE_TYPE_STAGE_INPUT), 11 | STAGE_OUTPUT(SPVC_RESOURCE_TYPE_STAGE_OUTPUT), 12 | SUBPASS_INPUT(SPVC_RESOURCE_TYPE_SUBPASS_INPUT), 13 | STORAGE_IMAGE(SPVC_RESOURCE_TYPE_STORAGE_IMAGE), 14 | SAMPLED_IMAGE(SPVC_RESOURCE_TYPE_SAMPLED_IMAGE), 15 | ATOMIC_COUNTER(SPVC_RESOURCE_TYPE_ATOMIC_COUNTER), 16 | PUSH_CONSTANT(SPVC_RESOURCE_TYPE_PUSH_CONSTANT), 17 | SEPARATE_IMAGE(SPVC_RESOURCE_TYPE_SEPARATE_IMAGE), 18 | SEPARATE_SAMPLERS(SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS), 19 | ACCELERATION_STRUCTURE(SPVC_RESOURCE_TYPE_ACCELERATION_STRUCTURE); 20 | public final int id; 21 | 22 | ResourceType(int id) { 23 | this.id = id; 24 | } 25 | 26 | public int toVkDescriptorType() { 27 | switch (this.id) { 28 | case SPVC_RESOURCE_TYPE_UNIFORM_BUFFER: 29 | return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; 30 | case SPVC_RESOURCE_TYPE_STORAGE_BUFFER: 31 | return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 32 | case SPVC_RESOURCE_TYPE_STAGE_INPUT: 33 | return -1; 34 | case SPVC_RESOURCE_TYPE_STAGE_OUTPUT: 35 | return -1; 36 | case SPVC_RESOURCE_TYPE_SUBPASS_INPUT: 37 | return VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; 38 | case SPVC_RESOURCE_TYPE_STORAGE_IMAGE: 39 | return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; 40 | case SPVC_RESOURCE_TYPE_SAMPLED_IMAGE: 41 | return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; 42 | case SPVC_RESOURCE_TYPE_ATOMIC_COUNTER: 43 | return -1; 44 | case SPVC_RESOURCE_TYPE_PUSH_CONSTANT: 45 | return -1; 46 | case SPVC_RESOURCE_TYPE_SEPARATE_IMAGE: 47 | return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; 48 | case SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS: 49 | return VK_DESCRIPTOR_TYPE_SAMPLER; 50 | case SPVC_RESOURCE_TYPE_ACCELERATION_STRUCTURE: 51 | return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; 52 | default: 53 | return -1; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinCelestialUniforms.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import net.coderbot.iris.uniforms.CelestialUniforms; 4 | import org.joml.Vector4f; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Invoker; 7 | 8 | @Mixin(value = CelestialUniforms.class, remap = false) 9 | public interface MixinCelestialUniforms { 10 | @Invoker("getSunPosition") 11 | public Vector4f invokeGetSunPosition(); 12 | 13 | @Invoker("getMoonPosition") 14 | public Vector4f invokeGetMoonPosition(); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinCommonUniforms.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import net.coderbot.iris.uniforms.CommonUniforms; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.gen.Invoker; 6 | 7 | @Mixin(value = CommonUniforms.class, remap = false) 8 | public interface MixinCommonUniforms { 9 | @Invoker("isEyeInWater") 10 | public static int invokeIsEyeInWater() { return 0; } // Must have a body, but this is just a dummy body and doesn't actually get executed. 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlResource.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.cortex.vulkanite.compat.IRenderTargetVkGetter; 5 | import me.cortex.vulkanite.lib.memory.VGImage; 6 | import net.coderbot.iris.gl.GlResource; 7 | import net.coderbot.iris.gl.texture.InternalTextureFormat; 8 | import net.coderbot.iris.gl.texture.PixelFormat; 9 | import net.coderbot.iris.rendertarget.RenderTarget; 10 | import org.spongepowered.asm.mixin.*; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.Redirect; 14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 15 | 16 | import static org.lwjgl.opengl.GL11C.*; 17 | import static org.lwjgl.opengl.GL30C.*; 18 | import static org.lwjgl.vulkan.VK10.*; 19 | 20 | @Mixin(value = GlResource.class, remap = false) 21 | public abstract class MixinGlResource { 22 | @Shadow private boolean isValid; 23 | 24 | @Shadow protected abstract void assertValid(); 25 | 26 | @Unique private int newId; 27 | 28 | @Inject(method = "", at=@At("TAIL")) 29 | protected void GlResource(int id, CallbackInfo ci) { 30 | this.newId = id; 31 | if(id == -1) { 32 | isValid = false; 33 | } 34 | } 35 | 36 | protected void setGlId(int id) { 37 | if(this.newId == -1) { 38 | this.newId = id; 39 | isValid = true; 40 | } 41 | } 42 | 43 | @Overwrite 44 | protected int getGlId(){ 45 | assertValid(); 46 | return this.newId; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinGlTexture.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import com.mojang.blaze3d.systems.RenderSystem; 4 | import me.cortex.vulkanite.client.Vulkanite; 5 | import me.cortex.vulkanite.compat.IVGImage; 6 | import me.cortex.vulkanite.lib.memory.VGImage; 7 | import me.cortex.vulkanite.lib.other.FormatConverter; 8 | import net.coderbot.iris.gl.IrisRenderSystem; 9 | import net.coderbot.iris.gl.texture.GlTexture; 10 | import net.coderbot.iris.gl.texture.InternalTextureFormat; 11 | import net.coderbot.iris.gl.texture.TextureType; 12 | import net.coderbot.iris.shaderpack.texture.TextureFilteringData; 13 | import org.lwjgl.opengl.GL30; 14 | import org.spongepowered.asm.mixin.*; 15 | import org.spongepowered.asm.mixin.injection.At; 16 | import org.spongepowered.asm.mixin.injection.Redirect; 17 | 18 | import java.nio.ByteBuffer; 19 | 20 | import static org.lwjgl.opengl.GL11C.*; 21 | import static org.lwjgl.vulkan.VK10.*; 22 | 23 | @Mixin(value = GlTexture.class, remap = false) 24 | public abstract class MixinGlTexture extends MixinGlResource implements IVGImage { 25 | @Unique private VGImage sharedImage; 26 | 27 | @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_genTexture()I")) 28 | private static int redirectGen() { 29 | return -1; 30 | } 31 | 32 | @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/texture/GlTexture;getGlId()I", ordinal = 0)) 33 | private int redirectTextureCreation(GlTexture instance, TextureType target, int sizeX, int sizeY, int sizeZ, int internalFormat, int format, int pixelType, byte[] pixels, TextureFilteringData filteringData) { 34 | // Before getting the texture id, create the texture that wasn't created earlier 35 | 36 | InternalTextureFormat textureFormat = FormatConverter.findFormatFromGlFormat(internalFormat); 37 | int vkFormat = FormatConverter.getVkFormatFromGl(textureFormat); 38 | 39 | // Clamp y,z to 1 as per VK spec 40 | sizeY = Math.max(sizeY, 1); 41 | sizeZ = Math.max(sizeZ, 1); 42 | 43 | sharedImage = Vulkanite.INSTANCE.getCtx().memory 44 | .createSharedImage( 45 | (sizeZ == 1 && sizeY == 1? 1 : (sizeZ == 1?2:3)), 46 | sizeX, 47 | sizeY, 48 | sizeZ, 49 | 1, 50 | vkFormat, 51 | textureFormat.getGlFormat(), 52 | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 53 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT 54 | ); 55 | 56 | Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { 57 | cmdbuf.encodeImageTransition(sharedImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); 58 | }); 59 | 60 | this.setGlId(sharedImage.glId); 61 | 62 | return sharedImage.glId; 63 | } 64 | 65 | @Redirect(method="", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/texture/TextureType;apply(IIIIIIILjava/nio/ByteBuffer;)V")) 66 | private void redirectUpload(TextureType instance, int glId, int width, int height, int depth, int internalFormat, int format, int pixelType, ByteBuffer data) { 67 | int target = instance.getGlType(); 68 | 69 | RenderSystem.assertOnRenderThreadOrInit(); 70 | IrisRenderSystem.bindTextureForSetup(target, glId); 71 | 72 | switch (instance) { 73 | case TEXTURE_1D: 74 | GL30.glTexSubImage1D(target, 0, 0, width, format, pixelType, data); 75 | break; 76 | case TEXTURE_2D, TEXTURE_RECTANGLE: 77 | GL30.glTexSubImage2D(target, 0, 0, 0, width, height, format, pixelType, data); 78 | break; 79 | case TEXTURE_3D: 80 | GL30.glTexSubImage3D(target, 0, 0, 0, 0, width, height, depth, format, pixelType, data); 81 | break; 82 | } 83 | } 84 | 85 | @Overwrite 86 | protected void destroyInternal(){ 87 | glFinish(); 88 | sharedImage.free(); 89 | } 90 | 91 | public VGImage getVGImage() { 92 | return sharedImage; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinNativeImageBackedTexture.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import com.mojang.blaze3d.platform.GlStateManager; 4 | import com.mojang.blaze3d.platform.TextureUtil; 5 | import com.mojang.blaze3d.systems.RenderSystem; 6 | import me.cortex.vulkanite.client.Vulkanite; 7 | import me.cortex.vulkanite.compat.IVGImage; 8 | import me.cortex.vulkanite.mixin.minecraft.MixinAbstractTexture; 9 | import net.coderbot.iris.gl.IrisRenderSystem; 10 | import net.coderbot.iris.rendertarget.NativeImageBackedCustomTexture; 11 | import net.minecraft.client.texture.AbstractTexture; 12 | import net.minecraft.client.texture.NativeImage; 13 | import net.minecraft.client.texture.NativeImageBackedTexture; 14 | import org.jetbrains.annotations.Nullable; 15 | import org.lwjgl.opengl.GL30; 16 | import org.spongepowered.asm.mixin.*; 17 | import org.spongepowered.asm.mixin.injection.At; 18 | import org.spongepowered.asm.mixin.injection.Redirect; 19 | 20 | import java.io.IOException; 21 | import java.nio.ByteBuffer; 22 | 23 | import static org.lwjgl.opengl.GL11C.*; 24 | import static org.lwjgl.vulkan.VK10.*; 25 | 26 | @Mixin(value = NativeImageBackedTexture.class, remap = false) 27 | public abstract class MixinNativeImageBackedTexture extends AbstractTexture implements IVGImage { 28 | @Redirect(remap = true, method = "(Lnet/minecraft/client/texture/NativeImage;)V", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(III)V")) 29 | private void redirectGen(int id, int width, int height) { 30 | if(!((Object) this instanceof NativeImageBackedCustomTexture)) { 31 | TextureUtil.prepareImage(id, width, height); 32 | return; 33 | } 34 | 35 | if (glId != -1) { 36 | glDeleteTextures(glId); 37 | glId = -1; 38 | } 39 | if (getVGImage() != null) { 40 | System.err.println("Vulkan image already allocated, releasing"); 41 | Vulkanite.INSTANCE.addSyncedCallback(getVGImage()::free); 42 | setVGImage(null); 43 | } 44 | 45 | var img = Vulkanite.INSTANCE.getCtx().memory.createSharedImage( 46 | width, 47 | height, 48 | 1, 49 | VK_FORMAT_R8G8B8A8_UNORM, 50 | GL_RGBA8, 51 | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 52 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 53 | setVGImage(img); 54 | 55 | Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { 56 | cmdbuf.encodeImageTransition(img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); 57 | }); 58 | 59 | GlStateManager._bindTexture(img.glId); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinNewWorldRenderingPipeline.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import it.unimi.dsi.fastutil.objects.Object2ObjectMap; 4 | import it.unimi.dsi.fastutil.objects.Object2ObjectMap.Entry; 5 | import me.cortex.vulkanite.client.Vulkanite; 6 | import me.cortex.vulkanite.client.rendering.VulkanPipeline; 7 | import me.cortex.vulkanite.compat.*; 8 | import me.cortex.vulkanite.lib.base.VContext; 9 | import me.cortex.vulkanite.lib.memory.VGImage; 10 | import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; 11 | import net.coderbot.iris.gl.texture.TextureAccess; 12 | import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; 13 | import net.coderbot.iris.gl.uniform.DynamicUniformHolder; 14 | import net.coderbot.iris.mixin.LevelRendererAccessor; 15 | import net.coderbot.iris.pipeline.CustomTextureManager; 16 | import net.coderbot.iris.pipeline.newshader.NewWorldRenderingPipeline; 17 | import net.coderbot.iris.rendertarget.RenderTargets; 18 | import net.coderbot.iris.shaderpack.ProgramSet; 19 | import net.coderbot.iris.shaderpack.texture.TextureStage; 20 | import net.coderbot.iris.uniforms.CelestialUniforms; 21 | import net.coderbot.iris.uniforms.custom.CustomUniforms; 22 | import net.minecraft.client.render.Camera; 23 | import org.jetbrains.annotations.Nullable; 24 | import org.spongepowered.asm.mixin.Final; 25 | import org.spongepowered.asm.mixin.Mixin; 26 | import org.spongepowered.asm.mixin.Shadow; 27 | import org.spongepowered.asm.mixin.Unique; 28 | import org.spongepowered.asm.mixin.injection.At; 29 | import org.spongepowered.asm.mixin.injection.Inject; 30 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 31 | 32 | import java.util.ArrayList; 33 | import java.util.Comparator; 34 | import java.util.List; 35 | 36 | @Mixin(value = NewWorldRenderingPipeline.class, remap = false) 37 | public class MixinNewWorldRenderingPipeline { 38 | 39 | @Shadow @Final private RenderTargets renderTargets; 40 | @Shadow @Final private CustomTextureManager customTextureManager; 41 | @Shadow private ShaderStorageBufferHolder shaderStorageBufferHolder; 42 | 43 | @Shadow @Final private float sunPathRotation; 44 | @Unique private RaytracingShaderSet[] rtShaderPasses = null; 45 | @Unique private VContext ctx; 46 | @Unique private VulkanPipeline pipeline; 47 | 48 | @Unique 49 | private VGImage[] getCustomTextures() { 50 | Object2ObjectMap texturesBinary = customTextureManager.getIrisCustomTextures(); 51 | Object2ObjectMap texturesPNGs = customTextureManager.getCustomTextureIdMap(TextureStage.GBUFFERS_AND_SHADOW); 52 | 53 | List> entryList = new ArrayList<>(); 54 | entryList.addAll(texturesBinary.object2ObjectEntrySet()); 55 | entryList.addAll(texturesPNGs.object2ObjectEntrySet()); 56 | 57 | entryList.sort(Comparator.comparing(Entry::getKey)); 58 | 59 | return entryList.stream() 60 | .map(entry -> ((IVGImage) entry.getValue()).getVGImage()) 61 | .toArray(VGImage[]::new); 62 | } 63 | 64 | @Inject(method = "", at = @At("TAIL")) 65 | private void injectRTShader(ProgramSet set, CallbackInfo ci) { 66 | ctx = Vulkanite.INSTANCE.getCtx(); 67 | var passes = ((IGetRaytracingSource)set).getRaytracingSource(); 68 | if (passes != null) { 69 | rtShaderPasses = new RaytracingShaderSet[passes.length]; 70 | for (int i = 0; i < passes.length; i++) { 71 | rtShaderPasses[i] = new RaytracingShaderSet(ctx, passes[i]); 72 | } 73 | } 74 | // Still create this, later down the line we might add Vulkan compute pipelines or mesh shading, etc. 75 | pipeline = new VulkanPipeline(ctx, Vulkanite.INSTANCE.getAccelerationManager(), rtShaderPasses, set.getPackDirectives().getBufferObjects().keySet().toArray(new int[0]), getCustomTextures()); 76 | } 77 | 78 | @Inject(method = "renderShadows", at = @At("TAIL")) 79 | private void renderShadows(LevelRendererAccessor par1, Camera par2, CallbackInfo ci) { 80 | ShaderStorageBuffer[] buffers = new ShaderStorageBuffer[0]; 81 | 82 | if(shaderStorageBufferHolder != null) { 83 | buffers = ((ShaderStorageBufferHolderAccessor)shaderStorageBufferHolder).getBuffers(); 84 | } 85 | 86 | List outImgs = new ArrayList<>(); 87 | for (int i = 0; i < renderTargets.getRenderTargetCount(); i++) { 88 | outImgs.add(((IRenderTargetVkGetter)renderTargets.getOrCreate(i)).getMain()); 89 | } 90 | 91 | MixinCelestialUniforms celestialUniforms = (MixinCelestialUniforms)(Object) new CelestialUniforms(this.sunPathRotation); 92 | 93 | pipeline.renderPostShadows(outImgs, par2, buffers, celestialUniforms); 94 | } 95 | 96 | @Inject(method = "destroyShaders", at = @At("TAIL")) 97 | private void destory(CallbackInfo ci) { 98 | ctx.cmd.waitQueueIdle(0); 99 | if (rtShaderPasses != null) { 100 | for (var pass : rtShaderPasses) { 101 | pass.delete(); 102 | } 103 | } 104 | pipeline.destory(); 105 | rtShaderPasses = null; 106 | pipeline = null; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinPBRAtlasTexture.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import com.mojang.blaze3d.platform.GlStateManager; 4 | import me.cortex.vulkanite.client.Vulkanite; 5 | import me.cortex.vulkanite.compat.IVGImage; 6 | import net.coderbot.iris.texture.pbr.PBRAtlasTexture; 7 | import net.minecraft.client.texture.AbstractTexture; 8 | import net.minecraft.client.texture.SpriteAtlasTexture; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Redirect; 12 | 13 | import static org.lwjgl.opengl.GL11C.GL_RGBA8; 14 | import static org.lwjgl.opengl.GL11C.glDeleteTextures; 15 | import static org.lwjgl.vulkan.VK10.*; 16 | 17 | @Mixin(PBRAtlasTexture.class) 18 | public abstract class MixinPBRAtlasTexture extends AbstractTexture implements IVGImage { 19 | @Redirect(method = "upload", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(IIII)V")) 20 | private void redirect(int id, int maxLevel, int width, int height) { 21 | if (getVGImage() != null) { 22 | System.err.println("Vulkan image already allocated, releasing"); 23 | Vulkanite.INSTANCE.addSyncedCallback(getVGImage()::free); 24 | setVGImage(null); 25 | } 26 | 27 | if (glId != -1) { 28 | glDeleteTextures(glId); 29 | glId = -1; 30 | } 31 | var img = Vulkanite.INSTANCE.getCtx().memory.createSharedImage( 32 | width, 33 | height, 34 | maxLevel + 1, 35 | VK_FORMAT_R8G8B8A8_UNORM, 36 | GL_RGBA8, 37 | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 38 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 39 | setVGImage(img); 40 | 41 | Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { 42 | cmdbuf.encodeImageTransition(img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); 43 | }); 44 | 45 | 46 | GlStateManager._bindTexture(getGlId()); 47 | if (maxLevel >= 0) { 48 | GlStateManager._texParameter(3553, 33085, maxLevel); 49 | GlStateManager._texParameter(3553, 33082, 0); 50 | GlStateManager._texParameter(3553, 33083, maxLevel); 51 | GlStateManager._texParameter(3553, 34049, 0.0F); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinPackRenderTargetDirectives.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import com.google.common.collect.ImmutableSet; 4 | import net.coderbot.iris.shaderpack.PackRenderTargetDirectives; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Redirect; 8 | 9 | import java.util.Set; 10 | 11 | @Mixin(value = PackRenderTargetDirectives.class, remap = false) 12 | public class MixinPackRenderTargetDirectives { 13 | @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableSet$Builder;build()Lcom/google/common/collect/ImmutableSet;")) 14 | private static ImmutableSet redirectBuild(ImmutableSet.Builder instance) { 15 | ImmutableSet.Builder fake = new ImmutableSet.Builder<>(); 16 | for (int i = 0; i < 10; i++) { 17 | fake.add(i); 18 | } 19 | return fake.build(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinProgramSet.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import me.cortex.vulkanite.compat.IGetRaytracingSource; 4 | import me.cortex.vulkanite.compat.RaytracingShaderSource; 5 | import net.coderbot.iris.shaderpack.ProgramSet; 6 | import net.coderbot.iris.shaderpack.ProgramSource; 7 | import net.coderbot.iris.shaderpack.ShaderPack; 8 | import net.coderbot.iris.shaderpack.ShaderProperties; 9 | import net.coderbot.iris.shaderpack.include.AbsolutePackPath; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Unique; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | import org.spongepowered.asm.mixin.injection.Inject; 14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | import java.util.function.Function; 19 | 20 | @Mixin(value = ProgramSet.class, remap = false) 21 | public abstract class MixinProgramSet implements IGetRaytracingSource { 22 | @Unique private RaytracingShaderSource[] sources; 23 | 24 | @Inject(method = "", at = @At("TAIL")) 25 | private void injectRTShaders(AbsolutePackPath directory, Function sourceProvider, 26 | ShaderProperties shaderProperties, ShaderPack pack, CallbackInfo ci) { 27 | List sourceList = new ArrayList<>(); 28 | int passId = 0; 29 | while (true) { 30 | int pass = passId++; 31 | var gen = sourceProvider.apply(directory.resolve("ray"+pass+".rgen")); 32 | if (gen == null) 33 | break; 34 | List missSources = new ArrayList<>(); 35 | int missId = 0; 36 | while (true) { 37 | var miss = sourceProvider.apply(directory.resolve("ray"+pass+"_"+(missId++)+".rmiss")); 38 | if (miss == null) 39 | break; 40 | missSources.add(miss); 41 | } 42 | List hitSources = new ArrayList<>(); 43 | int hitId = 0; 44 | while (true) { 45 | int hit = hitId++; 46 | var close = sourceProvider.apply(directory.resolve("ray"+pass+"_"+hit+".rchit")); 47 | var any = sourceProvider.apply(directory.resolve("ray"+pass+"_"+hit+".rahit")); 48 | var intersect = sourceProvider.apply(directory.resolve("ray"+pass+"_"+hit+".rint")); 49 | if (close == null && any == null && intersect == null) 50 | break; 51 | hitSources.add(new RaytracingShaderSource.RayHitSource(close, any, intersect)); 52 | } 53 | if (missSources.isEmpty()) { 54 | throw new IllegalStateException("No miss shaders for pass " + pass); 55 | } 56 | if (hitSources.isEmpty()) { 57 | throw new IllegalStateException("No hit shaders for pass " + pass); 58 | } 59 | sourceList.add(new RaytracingShaderSource("raypass_"+pass, 60 | gen, 61 | missSources.toArray(new String[0]), 62 | hitSources.toArray(new RaytracingShaderSource.RayHitSource[0]))); 63 | } 64 | if (!sourceList.isEmpty()) { 65 | sources = sourceList.toArray(new RaytracingShaderSource[0]); 66 | } 67 | } 68 | 69 | @Override 70 | public RaytracingShaderSource[] getRaytracingSource() { 71 | return sources; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinRenderTarget.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.cortex.vulkanite.compat.IRenderTargetVkGetter; 5 | import me.cortex.vulkanite.lib.memory.VGImage; 6 | import me.cortex.vulkanite.lib.other.FormatConverter; 7 | import net.coderbot.iris.gl.texture.InternalTextureFormat; 8 | import net.coderbot.iris.gl.texture.PixelFormat; 9 | import net.coderbot.iris.rendertarget.RenderTarget; 10 | import org.spongepowered.asm.mixin.*; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.Redirect; 14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 15 | 16 | import static org.lwjgl.opengl.GL11C.*; 17 | import static org.lwjgl.opengl.GL30C.*; 18 | import static org.lwjgl.vulkan.VK10.*; 19 | 20 | @Mixin(value = RenderTarget.class, remap = false) 21 | public abstract class MixinRenderTarget implements IRenderTargetVkGetter { 22 | @Shadow @Final private PixelFormat format; 23 | @Shadow @Final private InternalTextureFormat internalFormat; 24 | 25 | @Shadow protected abstract void setupTexture(int i, int i1, int i2, boolean b); 26 | 27 | @Unique private VGImage vgMainTexture; 28 | @Unique private VGImage vgAltTexture; 29 | 30 | @Redirect(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_genTextures([I)V")) 31 | private void redirectGen(int[] textures) { 32 | 33 | } 34 | 35 | @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/rendertarget/RenderTarget;setupTexture(IIIZ)V", ordinal = 0)) 36 | private void redirectMain(RenderTarget instance, int id, int width, int height, boolean allowsLinear) { 37 | setupTextures(width, height, allowsLinear); 38 | } 39 | 40 | @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/rendertarget/RenderTarget;setupTexture(IIIZ)V", ordinal = 1)) 41 | private void redirectAlt(RenderTarget instance, int id, int width, int height, boolean allowsLinear) {} 42 | 43 | @Redirect(method = "setupTexture", at = @At(value = "INVOKE",target = "Lnet/coderbot/iris/rendertarget/RenderTarget;resizeTexture(III)V")) 44 | private void redirectResize(RenderTarget instance, int t, int w, int h) {} 45 | 46 | @Overwrite 47 | public int getMainTexture() { 48 | return vgMainTexture.glId; 49 | } 50 | 51 | @Overwrite 52 | public int getAltTexture() { 53 | return vgAltTexture.glId; 54 | } 55 | 56 | @Overwrite 57 | public void resize(int width, int height) { 58 | glFinish(); 59 | //TODO: block the gpu fully before deleting and resizing the textures 60 | vgMainTexture.free(); 61 | vgAltTexture.free(); 62 | 63 | setupTextures(width, height, !internalFormat.getPixelFormat().isInteger()); 64 | } 65 | 66 | private void setupTextures(int width, int height, boolean allowsLinear) { 67 | var ctx = Vulkanite.INSTANCE.getCtx(); 68 | 69 | int glfmt = internalFormat.getGlFormat(); 70 | glfmt = (glfmt == GL_RGBA) ? GL_RGBA8 : glfmt; 71 | 72 | int vkfmt = FormatConverter.getVkFormatFromGl(internalFormat); 73 | 74 | vgMainTexture = ctx.memory.createSharedImage(width, height, 1, vkfmt, glfmt, VK_IMAGE_USAGE_STORAGE_BIT , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 75 | vgAltTexture = ctx.memory.createSharedImage(width, height, 1, vkfmt, glfmt, VK_IMAGE_USAGE_STORAGE_BIT , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 76 | Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { 77 | cmdbuf.encodeImageTransition(vgMainTexture, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); 78 | cmdbuf.encodeImageTransition(vgAltTexture, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); 79 | }); 80 | 81 | setupTexture(getMainTexture(), width, height, allowsLinear); 82 | setupTexture(getAltTexture(), width, height, allowsLinear); 83 | } 84 | 85 | @Redirect(method = "destroy", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_deleteTextures([I)V")) 86 | private void redirectResize(int[] textures) { 87 | glFinish(); 88 | //TODO: block the gpu fully before deleting and resizing the textures 89 | vgMainTexture.free(); 90 | vgAltTexture.free(); 91 | } 92 | 93 | public VGImage getMain() { 94 | return vgMainTexture; 95 | } 96 | 97 | public VGImage getAlt() { 98 | return vgAltTexture; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderPackSourceNames.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import net.coderbot.iris.shaderpack.include.ShaderPackSourceNames; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 9 | 10 | @Mixin(value = ShaderPackSourceNames.class, remap = false) 11 | public class MixinShaderPackSourceNames { 12 | @Inject(method = "findPotentialStarts", at = @At("RETURN"), cancellable = true) 13 | private static void injectRaytraceShaderNames(CallbackInfoReturnable> cir) { 14 | ImmutableList.Builder builder = ImmutableList.builder(); 15 | builder.addAll(cir.getReturnValue()); 16 | for (int i = 0; i < 3; i++) { 17 | builder.add("ray"+i+".rgen"); 18 | for (int j = 0; j < 4; j++) { 19 | builder.add("ray"+i+"_"+j+".rmiss"); 20 | builder.add("ray"+i+"_"+j+".rchit"); 21 | builder.add("ray"+i+"_"+j+".rahit"); 22 | builder.add("ray"+i+"_"+j+".rint"); 23 | } 24 | } 25 | cir.setReturnValue(builder.build()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBuffer.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.cortex.vulkanite.compat.IVGBuffer; 5 | import me.cortex.vulkanite.lib.memory.VGBuffer; 6 | import net.coderbot.iris.gl.IrisRenderSystem; 7 | import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import org.spongepowered.asm.mixin.Unique; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.Redirect; 14 | 15 | import static org.lwjgl.opengl.GL15C.glDeleteBuffers; 16 | 17 | @Mixin(value = ShaderStorageBuffer.class, remap = false) 18 | public class MixinShaderStorageBuffer implements IVGBuffer { 19 | @Shadow protected int id; 20 | @Unique 21 | private VGBuffer vkBuffer; 22 | 23 | public VGBuffer getBuffer() { 24 | return vkBuffer; 25 | } 26 | 27 | public void setBuffer(VGBuffer buffer) { 28 | if (vkBuffer != null && buffer != null) { 29 | throw new IllegalStateException("Override buffer not null"); 30 | } 31 | this.vkBuffer = buffer; 32 | if (buffer != null) { 33 | glDeleteBuffers(id); 34 | id = vkBuffer.glId; 35 | } 36 | } 37 | 38 | @Redirect(method = "destroy", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/IrisRenderSystem;deleteBuffers(I)V")) 39 | private void redirectDelete(int id) { 40 | if (vkBuffer != null) { 41 | Vulkanite.INSTANCE.addSyncedCallback(vkBuffer::free); 42 | } else { 43 | IrisRenderSystem.deleteBuffers(id); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinShaderStorageBufferHolder.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import com.mojang.blaze3d.platform.GlStateManager; 4 | import me.cortex.vulkanite.client.Vulkanite; 5 | import me.cortex.vulkanite.compat.IVGBuffer; 6 | import me.cortex.vulkanite.lib.memory.VGBuffer; 7 | import net.coderbot.iris.gl.IrisRenderSystem; 8 | import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; 9 | import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; 10 | import net.coderbot.iris.gl.buffer.ShaderStorageInfo; 11 | import org.lwjgl.opengl.GL43C; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Unique; 14 | import org.spongepowered.asm.mixin.injection.At; 15 | import org.spongepowered.asm.mixin.injection.Redirect; 16 | 17 | import static org.lwjgl.vulkan.VK10.VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; 18 | import static org.lwjgl.vulkan.VK10.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 19 | 20 | @Mixin(value = ShaderStorageBufferHolder.class, remap = false) 21 | public class MixinShaderStorageBufferHolder { 22 | @Unique private ShaderStorageInfo storageInfo; 23 | 24 | @Redirect(method = "lambda$new$0", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/buffer/ShaderStorageInfo;relative()Z")) 25 | private boolean alwaysReturnTrue(ShaderStorageInfo instance) { 26 | this.storageInfo = instance; 27 | return true; 28 | } 29 | 30 | private static VGBuffer alloc(int size) { 31 | return Vulkanite.INSTANCE.getCtx().memory.createSharedBuffer(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 32 | } 33 | 34 | @Redirect(method = "lambda$new$0", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/buffer/ShaderStorageBuffer;resizeIfRelative(II)V")) 35 | private void redirectSizeAllocation(ShaderStorageBuffer instance, int width, int height) { 36 | if (storageInfo.relative()) { 37 | instance.resizeIfRelative(width, height); 38 | } else { 39 | ((IVGBuffer)instance).setBuffer(alloc(storageInfo.size())); 40 | GlStateManager._glBindBuffer(GL43C.GL_SHADER_STORAGE_BUFFER, instance.getId()); 41 | IrisRenderSystem.clearBufferSubData(GL43C.GL_SHADER_STORAGE_BUFFER, GL43C.GL_R8, 0, storageInfo.size(), GL43C.GL_RED, GL43C.GL_BYTE, new int[] {0}); 42 | IrisRenderSystem.bindBufferBase(GL43C.GL_SHADER_STORAGE_BUFFER, instance.getIndex(), instance.getId()); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/MixinStandardMacros.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import net.coderbot.iris.gl.shader.StandardMacros; 4 | import net.coderbot.iris.shaderpack.StringPair; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 9 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 10 | 11 | import java.util.ArrayList; 12 | 13 | @Mixin(value = StandardMacros.class, remap = false) 14 | public class MixinStandardMacros { 15 | @Inject(method = "createStandardEnvironmentDefines", at = @At(value = "INVOKE", target = "Lnet/coderbot/iris/gl/shader/StandardMacros;define(Ljava/util/List;Ljava/lang/String;)V", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD) 16 | private static void injectVulkaniteDefine(CallbackInfoReturnable> cir, ArrayList defines) { 17 | defines.add(new StringPair("VULKANITE", " ")); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/iris/ShaderStorageBufferHolderAccessor.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.iris; 2 | 3 | import net.coderbot.iris.gl.buffer.ShaderStorageBuffer; 4 | import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Accessor; 7 | 8 | @Mixin(value = ShaderStorageBufferHolder.class, remap = false) 9 | public interface ShaderStorageBufferHolderAccessor { 10 | @Accessor 11 | ShaderStorageBuffer[] getBuffers(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinAbstractTexture.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.minecraft; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.cortex.vulkanite.compat.IVGImage; 5 | import me.cortex.vulkanite.lib.memory.VGImage; 6 | import net.minecraft.client.texture.AbstractTexture; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import org.spongepowered.asm.mixin.Unique; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 14 | 15 | @Mixin(AbstractTexture.class) 16 | public class MixinAbstractTexture implements IVGImage { 17 | @Shadow protected int glId; 18 | @Unique private VGImage vgImage; 19 | 20 | @Override 21 | public void setVGImage(VGImage image) { 22 | this.vgImage = image; 23 | } 24 | 25 | @Override 26 | public VGImage getVGImage() { 27 | return vgImage; 28 | } 29 | 30 | @Inject(method = "getGlId", at = @At("HEAD"), cancellable = true) 31 | private void redirectGetId(CallbackInfoReturnable cir) { 32 | if (vgImage != null) { 33 | if (glId != -1) { 34 | throw new IllegalStateException("glId != -1 while VGImage is set"); 35 | } 36 | cir.setReturnValue(vgImage.glId); 37 | cir.cancel(); 38 | } 39 | } 40 | 41 | @Inject(method = "clearGlId", at = @At("HEAD"), cancellable = true) 42 | private void redirectClear(CallbackInfo ci) { 43 | if (vgImage != null) { 44 | Vulkanite.INSTANCE.addSyncedCallback(vgImage::free); 45 | vgImage = null; 46 | glId = -1; 47 | ci.cancel(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinMinecraftClient.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.minecraft; 2 | 3 | import com.mojang.blaze3d.systems.RenderSystem; 4 | import me.cortex.vulkanite.client.Vulkanite; 5 | import net.minecraft.client.MinecraftClient; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.Redirect; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 11 | 12 | @Mixin(MinecraftClient.class) 13 | public class MixinMinecraftClient { 14 | @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V", shift = At.Shift.BEFORE)) 15 | private void onRenderTick(boolean tick, CallbackInfo ci) { 16 | Vulkanite.INSTANCE.renderTick(); 17 | } 18 | 19 | @Inject(method = "render", at = @At(value = "TAIL")) 20 | private void tickFences(boolean tick, CallbackInfo ci) { 21 | Vulkanite.INSTANCE.fenceTick(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinResourceTexture.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.minecraft; 2 | 3 | import com.mojang.blaze3d.platform.GlConst; 4 | import com.mojang.blaze3d.platform.GlStateManager; 5 | import com.mojang.blaze3d.systems.RenderSystem; 6 | import me.cortex.vulkanite.client.Vulkanite; 7 | import me.cortex.vulkanite.compat.IVGImage; 8 | import me.cortex.vulkanite.lib.memory.VGImage; 9 | import net.minecraft.client.texture.AbstractTexture; 10 | import net.minecraft.client.texture.ResourceTexture; 11 | import net.minecraft.resource.ResourceManager; 12 | import org.lwjgl.opengl.GL11; 13 | import org.lwjgl.opengl.GL12; 14 | import org.lwjgl.opengl.GL14; 15 | import org.spongepowered.asm.mixin.Mixin; 16 | import org.spongepowered.asm.mixin.injection.At; 17 | import org.spongepowered.asm.mixin.injection.Redirect; 18 | 19 | import java.io.IOException; 20 | 21 | import static org.lwjgl.opengl.GL11C.GL_RGBA8; 22 | import static org.lwjgl.opengl.GL11C.glDeleteTextures; 23 | import static org.lwjgl.vulkan.VK10.*; 24 | import static org.lwjgl.vulkan.VK10.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; 25 | 26 | @Mixin(ResourceTexture.class) 27 | public abstract class MixinResourceTexture extends AbstractTexture implements IVGImage { 28 | @Redirect(method = "upload", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(IIII)V")) 29 | private void redirect(int id, int maxLevel, int width, int height) { 30 | GlStateManager._bindTexture(0); 31 | RenderSystem.assertOnRenderThreadOrInit(); 32 | if (getVGImage() != null) { 33 | System.err.println("Vulkan image already allocated, releasing"); 34 | Vulkanite.INSTANCE.addSyncedCallback(getVGImage()::free); 35 | setVGImage(null); 36 | } 37 | 38 | if (glId != -1) { 39 | glDeleteTextures(glId); 40 | glId = -1; 41 | } 42 | var img = Vulkanite.INSTANCE.getCtx().memory.createSharedImage( 43 | width, 44 | height, 45 | maxLevel + 1, 46 | VK_FORMAT_R8G8B8A8_UNORM, 47 | GL_RGBA8, 48 | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 49 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 50 | setVGImage(img); 51 | 52 | Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { 53 | cmdbuf.encodeImageTransition(img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); 54 | }); 55 | 56 | GlStateManager._bindTexture(getGlId()); 57 | if (maxLevel >= 0) { 58 | GlStateManager._texParameter(3553, 33085, maxLevel); 59 | GlStateManager._texParameter(3553, 33082, 0); 60 | GlStateManager._texParameter(3553, 33083, maxLevel); 61 | GlStateManager._texParameter(3553, 34049, 0.0F); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/minecraft/MixinSpriteAtlasTexture.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.minecraft; 2 | 3 | import com.mojang.blaze3d.platform.GlStateManager; 4 | import me.cortex.vulkanite.client.Vulkanite; 5 | import me.cortex.vulkanite.compat.IVGImage; 6 | import net.minecraft.client.texture.AbstractTexture; 7 | import net.minecraft.client.texture.SpriteAtlasTexture; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Redirect; 11 | 12 | import static org.lwjgl.opengl.GL11C.GL_RGBA8; 13 | import static org.lwjgl.opengl.GL11C.glDeleteTextures; 14 | import static org.lwjgl.vulkan.VK10.*; 15 | 16 | @Mixin(SpriteAtlasTexture.class) 17 | public abstract class MixinSpriteAtlasTexture extends AbstractTexture implements IVGImage { 18 | @Redirect(method = "upload", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/TextureUtil;prepareImage(IIII)V")) 19 | private void redirect(int id, int maxLevel, int width, int height) { 20 | if (getVGImage() != null) { 21 | System.err.println("Vulkan image already allocated, releasing"); 22 | Vulkanite.INSTANCE.addSyncedCallback(getVGImage()::free); 23 | setVGImage(null); 24 | } 25 | 26 | if (glId != -1) { 27 | glDeleteTextures(glId); 28 | glId = -1; 29 | } 30 | var img = Vulkanite.INSTANCE.getCtx().memory.createSharedImage( 31 | width, 32 | height, 33 | maxLevel + 1, 34 | VK_FORMAT_R8G8B8A8_UNORM, 35 | GL_RGBA8, 36 | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 37 | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); 38 | setVGImage(img); 39 | 40 | Vulkanite.INSTANCE.getCtx().cmd.executeWait(cmdbuf -> { 41 | cmdbuf.encodeImageTransition(img, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_ASPECT_COLOR_BIT, VK_REMAINING_MIP_LEVELS); 42 | }); 43 | 44 | 45 | GlStateManager._bindTexture(getGlId()); 46 | if (maxLevel >= 0) { 47 | GlStateManager._texParameter(3553, 33085, maxLevel); 48 | GlStateManager._texParameter(3553, 33082, 0); 49 | GlStateManager._texParameter(3553, 33083, maxLevel); 50 | GlStateManager._texParameter(3553, 34049, 0.0F); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/sodium/MixinRenderRegionManager.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.sodium; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.jellysquid.mods.sodium.client.gl.arena.GlBufferArena; 5 | import me.jellysquid.mods.sodium.client.gl.device.CommandList; 6 | import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; 7 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; 8 | import me.jellysquid.mods.sodium.client.render.chunk.region.RenderRegion; 9 | import me.jellysquid.mods.sodium.client.render.chunk.region.RenderRegionManager; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 15 | 16 | import java.util.ArrayList; 17 | import java.util.Collection; 18 | import java.util.List; 19 | 20 | //The process needs to go like this 21 | //(This is for if a chunk mesh already exists) 22 | //Make a copy of the old chunk mesh 23 | // set that as the primary reference pointer 24 | //Once the chunk update blas job is built and processed 25 | // destroy the old pointer 26 | @Mixin(value = RenderRegionManager.class, remap = false) 27 | public class MixinRenderRegionManager { 28 | @Inject(method = "uploadMeshes(Lme/jellysquid/mods/sodium/client/gl/device/CommandList;Lme/jellysquid/mods/sodium/client/render/chunk/region/RenderRegion;Ljava/util/Collection;)V", 29 | at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/gl/arena/GlBufferArena;upload(Lme/jellysquid/mods/sodium/client/gl/device/CommandList;Ljava/util/stream/Stream;)Z", 30 | shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD) 31 | private void afterUpload(CommandList commandList, RenderRegion region, Collection results, CallbackInfo ci, ArrayList uploads, RenderRegion.DeviceResources resources, GlBufferArena arena) { 32 | for (var res : results) { 33 | //((IRenderSectionExtension)(res.render)).setArena(region.getResources().getGeometryArena()); 34 | //((IRenderSectionExtension)(res.render)).getAllocations().clear(); 35 | } 36 | 37 | for (PendingSectionUploadAccessor uploadObj : uploads) { 38 | //((IRenderSectionExtension)(uploadObj.getSection())).getAllocations().add(uploadObj.getVertexUpload().getResult()); 39 | } 40 | } 41 | 42 | @Inject(method = "uploadMeshes(Lme/jellysquid/mods/sodium/client/gl/device/CommandList;Lme/jellysquid/mods/sodium/client/render/chunk/region/RenderRegion;Ljava/util/Collection;)V", 43 | at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/region/RenderRegion;refresh(Lme/jellysquid/mods/sodium/client/gl/device/CommandList;)V", 44 | shift = At.Shift.AFTER)) 45 | private void arenaBufferChanged(CommandList commandList, RenderRegion region, Collection results, CallbackInfo ci) { 46 | List sectionsInRegion = new ArrayList<>(); 47 | for (int id = 0; id < 256; id++) { 48 | if (region.getSection(id) != null) { 49 | sectionsInRegion.add(region.getSection(id)); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/sodium/MixinRenderSection.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.sodium; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 9 | 10 | @Mixin(value = RenderSection.class, remap = false) 11 | public class MixinRenderSection { 12 | @Inject(method = "delete", at = @At("HEAD")) 13 | private void onSectionDelete(CallbackInfo ci) { 14 | Vulkanite.INSTANCE.sectionRemove((RenderSection)(Object)this); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/sodium/MixinRenderSectionManager.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.sodium; 2 | 3 | import it.unimi.dsi.fastutil.longs.Long2ReferenceMap; 4 | import it.unimi.dsi.fastutil.objects.Reference2ReferenceLinkedOpenHashMap; 5 | import me.cortex.vulkanite.compat.IAccelerationBuildResult; 6 | import me.cortex.vulkanite.client.Vulkanite; 7 | import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; 8 | import me.jellysquid.mods.sodium.client.render.chunk.RenderSectionManager; 9 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; 10 | import me.jellysquid.mods.sodium.client.util.NativeBuffer; 11 | import org.spongepowered.asm.mixin.Final; 12 | import org.spongepowered.asm.mixin.Mixin; 13 | import org.spongepowered.asm.mixin.Shadow; 14 | import org.spongepowered.asm.mixin.injection.At; 15 | import org.spongepowered.asm.mixin.injection.Inject; 16 | import org.spongepowered.asm.mixin.injection.Redirect; 17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 18 | 19 | import java.util.ArrayList; 20 | 21 | @Mixin(value = RenderSectionManager.class, remap = false) 22 | public abstract class MixinRenderSectionManager { 23 | @Shadow @Final private Long2ReferenceMap sectionByPosition; 24 | 25 | @Inject(method = "destroy", at = @At("HEAD")) 26 | private void onDestroy(CallbackInfo ci) { 27 | for (var section : sectionByPosition.values()) { 28 | Vulkanite.INSTANCE.sectionRemove(section); 29 | } 30 | Vulkanite.INSTANCE.destroy(); 31 | } 32 | 33 | @Redirect(method = "destroy", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;delete()V")) 34 | private void destroyAccelerationData(ChunkBuildOutput instance) { 35 | var data = ((IAccelerationBuildResult)instance).getAccelerationGeometryData(); 36 | instance.delete(); 37 | //TODO: need to ingest and cleanup all the blas builds and tlas updates 38 | } 39 | 40 | @Inject(method = "processChunkBuildResults", at = @At("HEAD")) 41 | private void processResults(ArrayList results, CallbackInfo ci) { 42 | Reference2ReferenceLinkedOpenHashMap map = new Reference2ReferenceLinkedOpenHashMap<>(); 43 | for(ChunkBuildOutput output : results) { 44 | if (((IAccelerationBuildResult)output).getAccelerationGeometryData() == null) 45 | continue; 46 | if (!output.render.isDisposed() && output.render.getLastBuiltFrame() <= output.buildTime) { 47 | RenderSection render = output.render; 48 | ChunkBuildOutput previous = map.get(render); 49 | if (previous == null || previous.buildTime < output.buildTime) { 50 | var prev = map.put(render, output); 51 | } 52 | } 53 | } 54 | if (!map.values().isEmpty()) { 55 | Vulkanite.INSTANCE.upload(new ArrayList<>(map.values())); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/sodium/PendingSectionUploadAccessor.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.sodium; 2 | 3 | import me.jellysquid.mods.sodium.client.gl.arena.PendingUpload; 4 | import me.jellysquid.mods.sodium.client.render.chunk.RenderSection; 5 | import me.jellysquid.mods.sodium.client.render.chunk.data.BuiltSectionMeshParts; 6 | import me.jellysquid.mods.sodium.client.render.chunk.region.RenderRegionManager; 7 | import me.jellysquid.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.gen.Accessor; 10 | 11 | @Mixin(targets = {"me.jellysquid.mods.sodium.client.render.chunk.region.RenderRegionManager$PendingSectionUpload"}, remap = false) 12 | public interface PendingSectionUploadAccessor { 13 | @Accessor 14 | RenderSection getSection(); 15 | @Accessor 16 | TerrainRenderPass getPass(); 17 | @Accessor 18 | PendingUpload getVertexUpload(); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/sodium/chunk/MixinChunkBuildResult.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.sodium.chunk; 2 | 3 | import me.cortex.vulkanite.compat.GeometryData; 4 | import me.cortex.vulkanite.compat.IAccelerationBuildResult; 5 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; 6 | import me.jellysquid.mods.sodium.client.render.chunk.terrain.TerrainRenderPass; 7 | import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType; 8 | import me.jellysquid.mods.sodium.client.util.NativeBuffer; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Unique; 11 | 12 | import java.util.Map; 13 | 14 | @Mixin(value = ChunkBuildOutput.class, remap = false) 15 | public class MixinChunkBuildResult implements IAccelerationBuildResult { 16 | @Unique private Map geometryMap; 17 | @Unique private ChunkVertexType vertexType; 18 | 19 | @Override 20 | public void setAccelerationGeometryData(Map map) { 21 | this.geometryMap = map; 22 | } 23 | 24 | @Override 25 | public Map getAccelerationGeometryData() { 26 | return geometryMap; 27 | } 28 | 29 | @Override 30 | public ChunkVertexType getVertexFormat() { 31 | return vertexType; 32 | } 33 | 34 | @Override 35 | public void setVertexFormat(ChunkVertexType format) { 36 | vertexType = format; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/sodium/chunk/MixinChunkRenderRebuildTask.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.sodium.chunk; 2 | 3 | import me.cortex.vulkanite.compat.IAccelerationBuildResult; 4 | import me.cortex.vulkanite.compat.SodiumResultAdapter; 5 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildContext; 6 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildOutput; 7 | import me.jellysquid.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask; 8 | import me.jellysquid.mods.sodium.client.util.task.CancellationToken; 9 | import net.irisshaders.iris.api.v0.IrisApi; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 14 | 15 | @Mixin(value = ChunkBuilderMeshingTask.class, remap = false) 16 | public class MixinChunkRenderRebuildTask { 17 | @Inject(method = "execute(Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lme/jellysquid/mods/sodium/client/util/task/CancellationToken;)Lme/jellysquid/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;", at = @At("TAIL")) 18 | private void performExtraBuild(ChunkBuildContext buildContext, CancellationToken cancellationToken, CallbackInfoReturnable cir) { 19 | if (IrisApi.getInstance().isShaderPackInUse()) { 20 | var buildResult = cir.getReturnValue(); 21 | ((IAccelerationBuildResult) buildResult).setVertexFormat(((VertexFormatAccessor) buildContext.buffers).getVertexType()); 22 | SodiumResultAdapter.compute(buildResult); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/sodium/chunk/VertexFormatAccessor.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.sodium.chunk; 2 | 3 | import me.jellysquid.mods.sodium.client.render.chunk.compile.ChunkBuildBuffers; 4 | import me.jellysquid.mods.sodium.client.render.chunk.vertex.format.ChunkVertexType; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Accessor; 7 | 8 | @Mixin(value = ChunkBuildBuffers.class, remap = false) 9 | public interface VertexFormatAccessor { 10 | @Accessor 11 | ChunkVertexType getVertexType(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinCommandList.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.sodium.gl; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.cortex.vulkanite.compat.IVulkanContextGetter; 5 | import me.cortex.vulkanite.lib.base.VContext; 6 | import me.jellysquid.mods.sodium.client.gl.device.CommandList; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | 9 | @Mixin(value = CommandList.class, remap = false) 10 | public interface MixinCommandList extends IVulkanContextGetter { 11 | default VContext getCtx() { 12 | return Vulkanite.INSTANCE.getCtx(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinGLRenderDevice.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.sodium.gl; 2 | 3 | import me.cortex.vulkanite.client.Vulkanite; 4 | import me.cortex.vulkanite.compat.IVGBuffer; 5 | import me.jellysquid.mods.sodium.client.gl.buffer.GlBuffer; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(targets = {"me.jellysquid.mods.sodium.client.gl.device.GLRenderDevice$ImmediateCommandList"}, remap = false) 12 | public class MixinGLRenderDevice { 13 | @Inject(method = "deleteBuffer", at = @At("HEAD"), cancellable = true) 14 | private void redirectDelete(GlBuffer buffer, CallbackInfo ci) { 15 | if (buffer instanceof IVGBuffer vkBuffer && vkBuffer.getBuffer() != null) { 16 | Vulkanite.INSTANCE.addSyncedCallback(vkBuffer.getBuffer()::free); 17 | ci.cancel(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/me/cortex/vulkanite/mixin/sodium/gl/MixinMutableBuffer.java: -------------------------------------------------------------------------------- 1 | package me.cortex.vulkanite.mixin.sodium.gl; 2 | 3 | import me.cortex.vulkanite.compat.IVGBuffer; 4 | import me.cortex.vulkanite.lib.memory.VGBuffer; 5 | import me.jellysquid.mods.sodium.client.gl.buffer.GlBuffer; 6 | import me.jellysquid.mods.sodium.client.gl.buffer.GlMutableBuffer; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Unique; 9 | 10 | import static org.lwjgl.opengl.GL15C.glDeleteBuffers; 11 | 12 | @Mixin(value = GlMutableBuffer.class, remap = false) 13 | public class MixinMutableBuffer extends GlBuffer implements IVGBuffer { 14 | @Unique private VGBuffer vkBuffer; 15 | 16 | public VGBuffer getBuffer() { 17 | return vkBuffer; 18 | } 19 | 20 | public void setBuffer(VGBuffer buffer) { 21 | if (vkBuffer != null && buffer != null) { 22 | throw new IllegalStateException("Override buffer not null"); 23 | } 24 | this.vkBuffer = buffer; 25 | if (buffer != null) { 26 | glDeleteBuffers(handle()); 27 | setHandle(vkBuffer.glId); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/resources/assets/vulkanite/shaders/include/raylib.glsl: -------------------------------------------------------------------------------- 1 | struct Vertex { 2 | u16vec4 position; 3 | u8vec4 colour; 4 | u16vec2 block_texture; 5 | u16vec2 light_texture; 6 | u16vec2 mid_tex_coord; 7 | i8vec4 tangent; 8 | i8vec3 normal; 9 | uint8_t padA__; 10 | i16vec2 block_id; 11 | i8vec3 mid_block; 12 | uint8_t padB__; 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "vulkanite", 4 | "version": "${version}", 5 | "name": "Vulkanite", 6 | "description": "A minecraft mod that brings hardware accelerated raytracing and other vulkan features to minecraft java edition", 7 | "authors": ["Cortex"], 8 | "contact": {}, 9 | "icon": "assets/vulkanite/icon.png", 10 | "environment": "client", 11 | "entrypoints": { 12 | }, 13 | "mixins": [ 14 | "vulkanite.mixins.json" 15 | ], 16 | "depends": { 17 | "fabricloader": ">=0.14.21", 18 | "iris": "=1.6.9", 19 | "sodium": "=0.5.3" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/resources/vulkanite.accesswidener: -------------------------------------------------------------------------------- 1 | accessWidener v1 named 2 | 3 | accessible class net/minecraft/client/render/RenderLayer$MultiPhase 4 | accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters 5 | accessible class net/minecraft/client/render/RenderPhase$Textures 6 | accessible class net/minecraft/client/render/RenderPhase$Texture 7 | 8 | accessible field net/minecraft/client/render/RenderLayer$MultiPhase phases Lnet/minecraft/client/render/RenderLayer$MultiPhaseParameters; 9 | accessible field net/minecraft/client/render/RenderLayer$MultiPhaseParameters texture Lnet/minecraft/client/render/RenderPhase$TextureBase; 10 | 11 | accessible method net/minecraft/client/render/RenderPhase$TextureBase getId ()Ljava/util/Optional; 12 | -------------------------------------------------------------------------------- /src/main/resources/vulkanite.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "minVersion": "0.8", 4 | "package": "me.cortex.vulkanite.mixin", 5 | "compatibilityLevel": "JAVA_17", 6 | "client": [ 7 | "iris.MixinCelestialUniforms", 8 | "iris.MixinCommonUniforms", 9 | "iris.MixinGlResource", 10 | "iris.MixinGlTexture", 11 | "iris.MixinNativeImageBackedTexture", 12 | "iris.MixinNewWorldRenderingPipeline", 13 | "iris.MixinPackRenderTargetDirectives", 14 | "iris.MixinPBRAtlasTexture", 15 | "iris.MixinProgramSet", 16 | "iris.MixinRenderTarget", 17 | "iris.MixinShaderPackSourceNames", 18 | "iris.MixinStandardMacros", 19 | "minecraft.MixinAbstractTexture", 20 | "minecraft.MixinMinecraftClient", 21 | "minecraft.MixinResourceTexture", 22 | "minecraft.MixinSpriteAtlasTexture", 23 | "sodium.MixinRenderRegionManager", 24 | "sodium.MixinRenderSection", 25 | "sodium.MixinRenderSectionManager", 26 | "sodium.PendingSectionUploadAccessor", 27 | "sodium.chunk.MixinChunkBuildResult", 28 | "sodium.chunk.MixinChunkRenderRebuildTask", 29 | "sodium.chunk.VertexFormatAccessor", 30 | "sodium.gl.MixinCommandList", 31 | "sodium.gl.MixinGLRenderDevice", 32 | "sodium.gl.MixinMutableBuffer" 33 | ], 34 | "injectors": { 35 | "defaultRequire": 1 36 | }, 37 | "mixins": [ 38 | "iris.MixinShaderStorageBuffer", 39 | "iris.MixinShaderStorageBufferHolder", 40 | "iris.ShaderStorageBufferHolderAccessor" 41 | ] 42 | } 43 | --------------------------------------------------------------------------------