diff --git a/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl b/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl new file mode 100644 index 0000000..03d4636 --- /dev/null +++ b/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl @@ -0,0 +1,55 @@ +#version 450 + +layout(constant_id = 0) const int USE_AA = 0; + +const float GAMMA_CONST = 0.4545; +const float SPAN_MAX = 8.0; +const float REDUCE_MIN = 1.0/128.0; +const float REDUCE_MUL = 1.0/32.0; + +layout(location = 0) in vec2 inTextCoord; +layout(location = 0) out vec4 outFragColor; + +layout(set = 0, binding = 0) uniform sampler2DMS inputTexture; + +layout(set = 1, binding = 0) uniform ScreenSize{ + vec2 size; +} screenSize; + +vec4 gamma(vec4 color){ + return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a); +} + + +vec4 msaa(int sampleCount, sampler2DMS textureIn,vec2 TextCoord){ + ivec2 pixelCoords = ivec2(TextCoord * textureSize(textureIn)); + vec4 colorSum = vec4(0.0); + + for(int i = 0; i < sampleCount; ++i) { + vec4 sampleColor = texelFetch(textureIn, pixelCoords, i); + sampleColor.rgb = sampleColor.rgb / (sampleColor.rgb + vec3(1.0)); + colorSum += sampleColor; + } + return colorSum / float(sampleCount); +} + +void main(){ + ivec2 pixelCoords = ivec2(inTextCoord * textureSize(inputTexture)); + + if(USE_AA == 0){ + outFragColor = texelFetch(inputTexture,pixelCoords,0); + } + if(USE_AA == 1){ + outFragColor = texelFetch(inputTexture,pixelCoords,0); + } + if(USE_AA == 2){ + outFragColor = msaa(2,inputTexture,inTextCoord); + } + if(USE_AA == 3){ + outFragColor = msaa(4,inputTexture,inTextCoord); + } + if(USE_AA == 4){ + outFragColor = msaa(8,inputTexture,inTextCoord); + } + outFragColor = gamma(outFragColor); +} \ No newline at end of file diff --git a/resources/EngineResources/shaders/post_process_frag.glsl b/resources/EngineResources/shaders/post_process_frag.glsl new file mode 100644 index 0000000..df90574 --- /dev/null +++ b/resources/EngineResources/shaders/post_process_frag.glsl @@ -0,0 +1,91 @@ +#version 450 + +layout(constant_id = 0) const int USE_AA = 0; + +const float GAMMA_CONST = 0.4545; +const float SPAN_MAX = 8.0; +const float REDUCE_MIN = 1.0/128.0; +const float REDUCE_MUL = 1.0/32.0; + +layout(location = 0) in vec2 inTextCoord; +layout(location = 0) out vec4 outFragColor; + +layout(set = 0, binding = 0) uniform sampler2D inputTexture; + +layout(set = 1, binding = 0) uniform ScreenSize{ + vec2 size; +} screenSize; + +vec4 gamma(vec4 color){ + return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a); +} + +// Sourced from: https://mini.gmshaders.com/p/gm-shaders-mini-fxaa + +vec4 fxaa(sampler2D tex, vec2 uv) { + vec2 u_texel = 1.0 / screenSize.size; + + //Sample center and 4 corners + vec3 rgbCC = texture(tex, uv).rgb; + vec3 rgb00 = texture(tex, uv+vec2(-0.5,-0.5)*u_texel).rgb; + vec3 rgb10 = texture(tex, uv+vec2(+0.5,-0.5)*u_texel).rgb; + vec3 rgb01 = texture(tex, uv+vec2(-0.5,+0.5)*u_texel).rgb; + vec3 rgb11 = texture(tex, uv+vec2(+0.5,+0.5)*u_texel).rgb; + + //Luma coefficients + const vec3 luma = vec3(0.299, 0.587, 0.114); + //Get luma from the 5 samples + float lumaCC = dot(rgbCC, luma); + float luma00 = dot(rgb00, luma); + float luma10 = dot(rgb10, luma); + float luma01 = dot(rgb01, luma); + float luma11 = dot(rgb11, luma); + + //Compute gradient from luma values + vec2 dir = vec2((luma01 + luma11) - (luma00 + luma10), (luma00 + luma01) - (luma10 + luma11)); + //Diminish dir length based on total luma + float dirReduce = max((luma00 + luma10 + luma01 + luma11) * REDUCE_MUL, REDUCE_MIN); + //Divide dir by the distance to nearest edge plus dirReduce + float rcpDir = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); + //Multiply by reciprocal and limit to pixel span + dir = clamp(dir * rcpDir, -SPAN_MAX, SPAN_MAX) * u_texel.xy; + + //Average middle texels along dir line + vec4 A = 0.5 * ( + texture(tex, uv - dir * (1.0/6.0)) + + texture(tex, uv + dir * (1.0/6.0))); + + //Average with outer texels along dir line + vec4 B = A * 0.5 + 0.25 * ( + texture(tex, uv - dir * (0.5)) + + texture(tex, uv + dir * (0.5))); + + + //Get lowest and highest luma values + float lumaMin = min(lumaCC, min(min(luma00, luma10), min(luma01, luma11))); + float lumaMax = max(lumaCC, max(max(luma00, luma10), max(luma01, luma11))); + + //Get average luma + float lumaB = dot(B.rgb, luma); + //If the average is outside the luma range, using the middle average + return ((lumaB < lumaMin) || (lumaB > lumaMax)) ? A : B; +} + +void main(){ + + if(USE_AA == 1){ + outFragColor = fxaa(inputTexture, inTextCoord); + outFragColor = gamma(outFragColor); + return; + } + if(USE_AA == 2){ + + } + if(USE_AA == 3){ + + } + if(USE_AA == 4){ + + } + outFragColor = gamma(texture(inputTexture,inTextCoord)); +} \ No newline at end of file diff --git a/resources/EngineResources/shaders/post_process_vtx.glsl b/resources/EngineResources/shaders/post_process_vtx.glsl new file mode 100644 index 0000000..bcc462a --- /dev/null +++ b/resources/EngineResources/shaders/post_process_vtx.glsl @@ -0,0 +1,9 @@ +#version 450 + +layout(location = 0 ) out vec2 outTextCoord; + +void main() +{ + outTextCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); + gl_Position = vec4(outTextCoord.x * 2.0f - 1.0f, outTextCoord.y * -2.0f + 1.0f,0.0f,1.0f); +} \ No newline at end of file diff --git a/resources/shaders/scene_fragment.glsl b/resources/EngineResources/shaders/scene_fragment.glsl similarity index 78% rename from resources/shaders/scene_fragment.glsl rename to resources/EngineResources/shaders/scene_fragment.glsl index 6b51322..a1387ad 100644 --- a/resources/shaders/scene_fragment.glsl +++ b/resources/EngineResources/shaders/scene_fragment.glsl @@ -1,6 +1,6 @@ #version 450 -const int MAX_TEXTURES = 100; +const int MAX_TEXTURES = 500; layout(location = 0) in vec2 inTextCoords; layout(location = 0) out vec4 outFragColor; @@ -26,7 +26,9 @@ void main() { Material material = matUniform.materials[push_constants.materialIdx]; if(material.hasTexture == 1){ - outFragColor = texture(textSampler[material.textureIdx],inTextCoords); + vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords); + if(texColor.a < 0.1){discard;} + outFragColor = texColor; } else{ outFragColor = material.diffuseColor; } diff --git a/resources/shaders/scene_vertex.glsl b/resources/EngineResources/shaders/scene_vertex.glsl similarity index 100% rename from resources/shaders/scene_vertex.glsl rename to resources/EngineResources/shaders/scene_vertex.glsl diff --git a/resources/EngineResources/shaders/swap_frag.glsl b/resources/EngineResources/shaders/swap_frag.glsl new file mode 100644 index 0000000..4b36f7d --- /dev/null +++ b/resources/EngineResources/shaders/swap_frag.glsl @@ -0,0 +1,10 @@ +#version 450 +layout(location = 0) in vec2 inTextCoord; +layout(location = 0) out vec4 outFragColor; + +layout(set = 0, binding = 0) uniform sampler2D albedoSampler; + +void main() { + vec3 albedo = texture(albedoSampler, inTextCoord).rgb; + outFragColor = vec4(albedo,1.0); +} diff --git a/resources/EngineResources/shaders/swap_vtx.glsl b/resources/EngineResources/shaders/swap_vtx.glsl new file mode 100644 index 0000000..ebbaca0 --- /dev/null +++ b/resources/EngineResources/shaders/swap_vtx.glsl @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) out vec2 outTextCoord; + +void main() { + outTextCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); + gl_Position = vec4(outTextCoord.x * 2.0f - 1.0f, outTextCoord.y * -2.0f + 1.0f,0.0f,1.0f); +} diff --git a/resources/models/Corvette/corvetteclass.png b/resources/models/Corvette/corvetteclass.png index 3256cf4..0234a62 100644 Binary files a/resources/models/Corvette/corvetteclass.png and b/resources/models/Corvette/corvetteclass.png differ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java index b6747ae..f2ebd1b 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java @@ -4,17 +4,17 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; import net.halbear.Terrain4J.EngineCore.Logic.InitData; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache; -import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData; -import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialsCache; -import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData; -import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelsCache; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.PostProcessing.PostProcess; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.*; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandPool; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.Fence; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.Semaphore; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SceneRender; -import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SwapChain; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SceneRenderer; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChain; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChainRender; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkCommandBufferSubmitInfo; @@ -22,11 +22,11 @@ import org.lwjgl.vulkan.VkExtent2D; import org.lwjgl.vulkan.VkSemaphoreSubmitInfo; import org.tinylog.Logger; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static org.lwjgl.vulkan.VK13.VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT; -import static org.lwjgl.vulkan.VK13.VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT; +import static org.lwjgl.vulkan.VK13.*; public class Render { @@ -39,14 +39,22 @@ public class Render { private final Semaphore[] PresentCompleteSemaphores; private final Queue.PresentQueue PresentQueue; private final Semaphore[] RenderCompleteSemaphores; - private final SceneRender sceneRender; + private final SceneRenderer sceneRender; + private final PostProcess PostProcessor; + private final SwapChainRender swapChainRender; private int CurrentFrame; private final VulkanContext RendererContext; private boolean Resize = false; + private List Materials = new ArrayList<>(); + private List Models = new ArrayList<>(); + private List VoxelModels = new ArrayList<>(); private final MaterialsCache materialsCache; private TextureCache textureCache; + public TextureCache GetTextureCache(){return textureCache;} + public MaterialsCache GetMaterialsCache(){return materialsCache;} + public Render(EngineInstance engineInstance) { RendererContext = new VulkanContext(engineInstance.window()); CurrentFrame = 0; @@ -68,6 +76,8 @@ public class Render { RenderCompleteSemaphores[i] = new Semaphore(RendererContext); } sceneRender = new SceneRender(RendererContext); + PostProcessor = new PostProcess(RendererContext,sceneRender.GetAttachmentColour()); + swapChainRender = new SwapChainRender(RendererContext,PostProcessor.GetAttachment()); textureCache = new TextureCache(); materialsCache = new MaterialsCache(); modelsCache = new ModelsCache(); @@ -76,19 +86,27 @@ public class Render { public void Initialise(InitData initData){ - List Materials = initData.Materials(); + Materials.addAll(initData.Materials()); Logger.debug("Loading {} Materials", Materials.size()); + //materialsCache.CleanUp(RendererContext); materialsCache.LoadMaterials(RendererContext, Materials,textureCache, CommandPools[0], GraphicsQueue); Logger.debug("Loaded {} Materials", Materials.size()); Logger.debug("Transitioning Textures"); + //textureCache.CleanUp(RendererContext); textureCache.TransitionTexts(RendererContext, CommandPools[0], GraphicsQueue); Logger.debug("Transitioned Textures"); - List Models = initData.Models(); + Models.addAll(initData.Models()); Logger.debug("Loading {} models", Models.size()); + //modelsCache.CleanUp(RendererContext); modelsCache.loadModels(RendererContext, Models, CommandPools[0], GraphicsQueue); Logger.debug("Loaded {} models", Models.size()); + + VoxelModels.addAll(initData.voxelModels()); + Logger.debug("Loading {} Voxel models", VoxelModels.size()); + modelsCache.loadVoxelModels(RendererContext, VoxelModels, CommandPools[0], GraphicsQueue); + Logger.debug("Loaded {} Voxel models", VoxelModels.size()); sceneRender.LoadMaterials(RendererContext,materialsCache,textureCache); } @@ -105,6 +123,8 @@ public class Render { RendererContext.GetDevice().waitIdle(); Logger.debug("Waiting Vulkan Context"); sceneRender.cleanup(RendererContext); + PostProcessor.CleanUp(RendererContext); + swapChainRender.CleanUp(RendererContext); Logger.debug("Dynamic Renderer Cleaned up"); Arrays.asList(RenderCompleteSemaphores).forEach(i->i.cleanup(RendererContext)); Logger.debug("Render Semaphores cleaned up"); @@ -128,12 +148,18 @@ public class Render { var CommandPool = CommandPools[CurrentFrame]; var CommandBuffer = CommandBuffers[CurrentFrame]; RecordingStart(CommandPool, CommandBuffer); + + sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame); + PostProcessor.Render(RendererContext,CommandBuffer,sceneRender.GetAttachmentColour()); + int ImageIndex;// = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[CurrentFrame]); if (Resize || (ImageIndex = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[CurrentFrame])) < 0){ resize(engineInstance); return; } - sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,ImageIndex,CurrentFrame); + + swapChainRender.Render(RendererContext,CommandBuffer,PostProcessor.GetAttachment(),ImageIndex); + RecordingStop(CommandBuffer); Submit(CommandBuffer, CurrentFrame, ImageIndex); Resize = swapChain.PresentImage(PresentQueue, RenderCompleteSemaphores[ImageIndex],ImageIndex); @@ -161,6 +187,8 @@ public class Render { VkExtent2D extend = RendererContext.GetSwapChain().GetSwapChainExtent(); engineInstance.scene().GetProjection().Resize(extend.width(),extend.height()); sceneRender.Resize(engineInstance,RendererContext); + PostProcessor.Resize(RendererContext,sceneRender.GetAttachmentColour()); + swapChainRender.Resize(RendererContext,PostProcessor.GetAttachment()); } private void ResetFence(int currentFrame){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Input/MouseListener.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Input/MouseListener.java index 9f679ba..dc112ea 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Input/MouseListener.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Input/MouseListener.java @@ -30,6 +30,7 @@ public class MouseListener { middleButtonPressed = button == GLFW_MOUSE_BUTTON_3 && action == GLFW_PRESS; }); } + public boolean IsWindowFocused(){return FocusWindow;} public Vector2f getCurrentPos() { return currentPos; } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java index 493afb0..e0c1103 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java @@ -8,6 +8,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Properties; +import static org.lwjgl.vulkan.VK10.*; + public class EngineConfig { public static final double DegToRad = Math.PI/180.0; public static final double RadToDeg = 180.0/Math.PI; @@ -51,6 +53,8 @@ public class EngineConfig { private float zNearPlane; private boolean GPU_SUPPORTS_LOGGING = true; private int MaxDescriptors = 1000; + private int AAValue = 1; + private AntiAliasType AAMode = AntiAliasType.FXAA; public void GPU_Does_Not_Support_Logging(){ GPU_SUPPORTS_LOGGING = false; @@ -58,6 +62,32 @@ public class EngineConfig { public boolean doesGPUSupportLogging(){return GPU_SUPPORTS_LOGGING;} public String GetDefaultTexturePath(){return DefaultTexturePath;} public int GetMaxDescriptors(){return MaxDescriptors;} + public int RenderAA(){return AAValue;} + + public enum AntiAliasType{ + NONE, + FXAA, + MSAAx2, + MSAAx4, + MSAAx8 + } + + public int GetRenderSampleCount(){ + switch(AAMode){ + case MSAAx2: + return VK_SAMPLE_COUNT_2_BIT; + case MSAAx4: + return VK_SAMPLE_COUNT_4_BIT; + case MSAAx8: + return VK_SAMPLE_COUNT_8_BIT; + case FXAA: + return VK_SAMPLE_COUNT_1_BIT; + case NONE: + return VK_SAMPLE_COUNT_1_BIT; + default: + return VK_SAMPLE_COUNT_1_BIT; + } + } private EngineConfig() { var EngineConfigVar = new Properties(); @@ -120,6 +150,25 @@ public class EngineConfig { FOV = (float)(DegToRad * Float.parseFloat(EngineConfigVar.getOrDefault("field_of_view", 60.0f).toString())); zNearPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_near_plane", 1.0f).toString())); zFarPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_far_plane", 100.0f).toString())); + AAValue = (Integer.parseInt(EngineConfigVar.getOrDefault("anti_alias_mode", 1).toString())); + switch(AAValue){ + case 0: + AAMode = AntiAliasType.NONE; + break; + case 2: + AAMode = AntiAliasType.MSAAx2; + break; + case 3: + AAMode = AntiAliasType.MSAAx4; + break; + case 4: + AAMode = AntiAliasType.MSAAx8; + break; + case 1: + default: + AAMode = AntiAliasType.FXAA; + break; + } DefaultTexturePath = EngineConfigVar.getOrDefault("DefaultTexturePath","/EngineResources/Texture/DefaultTexture.png").toString(); Logger.debug("\n\nsuccessfully loaded configuration: \n{}\n\n",EngineConfigVar.toString()); } @@ -149,6 +198,7 @@ public class EngineConfig { EngineConfigVar.setProperty("z_far_plane","100"); EngineConfigVar.setProperty("DefaultTexturePath",DefaultTexturePath); EngineConfigVar.setProperty("MaxDescriptors","1000"); + EngineConfigVar.setProperty("anti_alias_mode","1"); EngineConfigVar.store(new FileWriter(path.toAbsolutePath().toString() + "/" + FILENAME), "created new properties file"); Logger.debug("Wrote New Config File [{}]", ConfigFile.getAbsolutePath()); } catch (IOException excp2) { diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineInstance.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineInstance.java index 87ab35c..569d824 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineInstance.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineInstance.java @@ -1,9 +1,14 @@ package net.halbear.Terrain4J.EngineCore.Logic; +import net.halbear.Terrain4J.EngineCore.Display.Render; +import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene; import net.halbear.Terrain4J.EngineCore.Display.Window; +import net.halbear.Terrain4J.EngineCore.Threads.FastTickThread; +import net.halbear.Terrain4J.EngineCore.Threads.MainThread; +import net.halbear.Terrain4J.EngineCore.Threads.RenderThread; -public record EngineInstance(Window window, Scene scene) { +public record EngineInstance(Window window, Scene scene, PrimaryRuntime PrimaryThread) { public void cleanup(){ window.cleanup(); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/InitData.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/InitData.java index 0e44d94..9806620 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/InitData.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/InitData.java @@ -2,8 +2,9 @@ package net.halbear.Terrain4J.EngineCore.Logic; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.CompatibleVoxelMesh; import java.util.List; -public record InitData(List Models, List Materials) { +public record InitData(List Models, List voxelModels, List Materials) { } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/InitVoxelData.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/InitVoxelData.java new file mode 100644 index 0000000..7f4bffa --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/InitVoxelData.java @@ -0,0 +1,9 @@ +package net.halbear.Terrain4J.EngineCore.Logic; + +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.CompatibleVoxelMesh; + +import java.util.List; + +public record InitVoxelData(List Models, List Materials) { +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelCompiler.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelCompiler.java index d72bdac..5ce37f8 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelCompiler.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelCompiler.java @@ -208,7 +208,7 @@ public class ModelCompiler { int EmbeddedTextureIndex = matcher.matches() && matcher.groupCount() > 0 ? Integer.parseInt(matcher.group(1)) : -1; if (EmbeddedTextureIndex >= 0 && EmbeddedTextureIndex < EmbeddedTextureCount){ var aiTexture = AITexture.create(aiScene.mTextures().get(EmbeddedTextureIndex)); - String BaseFile = aiTexture.mFilename().dataString() + ".png"; + String BaseFile = aiTexture.mFilename().dataString() + "ModelTexture" +EmbeddedTextureIndex + ".png"; TexturePath = BaseDirectory + File.separator + BaseFile; Logger.info("Dumping Texture File to [{}]",TexturePath); var Channel = FileChannel.open(Path.of(TexturePath), StandardOpenOption.CREATE,StandardOpenOption.WRITE); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/VulkanContext.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/VulkanContext.java index f67460d..27d542f 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/VulkanContext.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/VulkanContext.java @@ -7,7 +7,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorAlloca import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDevice; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.Surface; -import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SwapChain; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChain; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanMemoryAllocator; import org.tinylog.Logger; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java index 21e8ce7..9e46529 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java @@ -3,16 +3,15 @@ package net.halbear.Terrain4J.EngineCore.Main; import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput; import net.halbear.Terrain4J.EngineCore.Input.MouseListener; -import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; -import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; -import net.halbear.Terrain4J.EngineCore.Logic.GameLogic; -import net.halbear.Terrain4J.EngineCore.Logic.InitData; +import net.halbear.Terrain4J.EngineCore.Logic.*; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.ModelLoader; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor; import net.halbear.Terrain4J.EngineCore.Main.Scene.Camera; import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene; +import net.halbear.Terrain4J.EngineCore.Main.Util.Maths.T4Math; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.CompatibleVoxelMesh; import org.joml.Vector2f; import org.joml.Vector3f; import org.tinylog.Logger; @@ -33,6 +32,8 @@ public class GameCore implements GameLogic { private List Velocities = new ArrayList<>(); private Actor CubeActor; private List CubeActors = new ArrayList<>(); + private Vector2f LastMousePos = new Vector2f(0,0); + private int Ticks = 0; @Override public void cleanup() { @@ -41,50 +42,80 @@ public class GameCore implements GameLogic { @Override public InitData Initialise(EngineInstance engineInstance) { + + CompatibleVoxelMesh GrassCube = new CompatibleVoxelMesh("GrassBlock") + .CreateMeshFace(CompatibleVoxelMesh.FaceDirection.North, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture1.png") + .CreateMeshFace(CompatibleVoxelMesh.FaceDirection.East, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture14.png") + .CreateMeshFace(CompatibleVoxelMesh.FaceDirection.South, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture13.png") + .CreateMeshFace(CompatibleVoxelMesh.FaceDirection.West, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture12.png") + .CreateMeshFace(CompatibleVoxelMesh.FaceDirection.Up, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture15.png") + .CreateMeshFace(CompatibleVoxelMesh.FaceDirection.Down, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture0.png").CompileMesh(); + + InitVoxelData Voxels = CompatibleVoxelMesh.GetVoxelModelsGenerated(); + List VoxelModels = Voxels.Models(); + for(int i = 0; i < VoxelModels.size(); i++){ + Logger.debug("Voxel -> [{}]",VoxelModels.get(i).ID()); + } Scene scene = engineInstance.scene(); List models = new ArrayList<>(); + //ModelData SponzaData = ModelLoader.LoadModel("resources/models/Unit02/evangelion_unit-02.json"); + //List SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Unit02/evangelion_unit-02_mat.json"); ModelData SponzaData = ModelLoader.LoadModel("resources/models/Sponza/Sponza.json"); List SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Sponza/Sponza_mat.json"); scene.AddActor(new Actor("Sponza", SponzaData.ID(), new Vector3f(0,0,-5f))); models.add(ModelLoader.LoadModel("resources/models/Metro/OBJ/MetroLeadCar.json")); - models.add(ModelLoader.LoadModel("resources/models/Corvette/CorvetteOBJ.json")); - //models.add(ModelLoader.LoadModel("resources/models/Sloop/SloopOBJ.json")); models.add(ModelLoader.LoadModel("resources/models/melona/melona.json")); models.add(ModelLoader.LoadModel("resources/models/Alice/Welsh040Alice.json")); + models.add(ModelLoader.LoadModel("resources/models/Sloop/SloopOBJ.json")); + models.add(ModelLoader.LoadModel("resources/models/Corvette/corvetteclass.json")); for(int i = 0; i < 50000; i++) { - CubeActors.add(new Actor("CubeEntity" + i, models.get((int)Math.round(Math.min(Math.max((Math.random() * models.size() - 1),0),models.size() - 1))).ID(), new Vector3f((float)(-200 + Math.random() * 400), (float)(-50 + Math.random() * 100), (float)(250 + Math.random() * -500)))); + CubeActors.add(new Actor("AdvancedModel" + i, models.get((int)Math.round(Math.min(Math.max(Math.random() *(Math.random() * models.size() - 1),0),models.size() - 1))).ID(), new Vector3f((float)(-200 + Math.random() * 400), (float)(-50 + Math.random() * 100), (float)(250 + Math.random() * -500)))); angles.add((float)(Math.random() * 360)); rotatingAngles.add(new Vector3f((float)(Math.random()*2), (float)(Math.random()*2), (float)(Math.random()*2))); - Velocities.add(new Vector3f((float)(Math.random()*2), (float)(Math.random()*2), (float)(Math.random()*2))); + Velocities.add(new Vector3f((float)(-2 + Math.random()*4), -2 + (float)(Math.random()*4), -2 + (float)(Math.random()*4))); } CubeActors.forEach(scene::AddActor); List materials = new ArrayList<>(); materials.addAll(ModelLoader.LoadMaterials("resources/models/Metro/OBJ/MetroLeadCar_mat.json")); - materials.addAll(ModelLoader.LoadMaterials("resources/models/Corvette/CorvetteOBJ_mat.json")); - materials.addAll(ModelLoader.LoadMaterials("resources/models/Sloop/SloopOBJ_mat.json")); + materials.addAll(ModelLoader.LoadMaterials("resources/models/Corvette/corvetteclass_mat.json")); materials.addAll(ModelLoader.LoadMaterials("resources/models/melona/melona_mat.json")); materials.addAll(ModelLoader.LoadMaterials("resources/models/Alice/Welsh040Alice_mat.json")); + materials.addAll(ModelLoader.LoadMaterials("resources/models/Sloop/SloopOBJ_mat.json")); materials.addAll(SponzaMaterial); + materials.addAll(Voxels.Materials()); models.add(SponzaData); Camera camera = scene.GetCamera(); - camera.SetPosition(0.0f, 0.0f, 0.0f); - camera.SetRotation((float) Math.toRadians(0.0f), (float) Math.toRadians(0.0f),0); - return new InitData(models,materials); + camera.SetPosition(40.0f, 155.0f, -42.0f); + camera.SetPosition(0,0,0); + camera.SetRotation((float) Math.toRadians(10.0f), (float) Math.toRadians(-90.0f),0); + camera.SetRotation(0,0,0); + return new InitData(models,VoxelModels,materials); } @Override public void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) { + float Multiplier = MOUSE_SENSITIVITY; Scene scene = engineInstance.scene(); Window window = engineInstance.window(); Camera camera = scene.GetCamera(); MouseListener MouseInput = window.getMouseInput(); + Vector2f CurrentMousePos = window.getMouseInput().getCurrentPos(); + Vector2f deltaPos = new Vector2f(0,0); + deltaPos.x = 0; + deltaPos.y = 0; + if (LastMousePos.x >= 0 && LastMousePos.y >= 0 && window.getMouseInput().IsWindowFocused()) { + deltaPos.x = CurrentMousePos.x - LastMousePos.x; + deltaPos.y = CurrentMousePos.y - LastMousePos.y; + } + LastMousePos.x = CurrentMousePos.x; + LastMousePos.y = CurrentMousePos.y; if(MouseInput.isRightButtonPressed()){ - Vector2f deltaPos = MouseInput.getDeltaPos(); - camera.AddRotation((float)Math.toRadians(-deltaPos.y * MOUSE_SENSITIVITY),(float)Math.toRadians(-deltaPos.x * MOUSE_SENSITIVITY),0); + + camera.AddRotation((float)Math.toRadians(-deltaPos.y * Multiplier),(float)Math.toRadians(-deltaPos.x * Multiplier),0); } } @@ -122,9 +153,13 @@ public class GameCore implements GameLogic { for(int i = 0; i < angles.size()/2; i++) { angles.set(i, (angles.get(i) + 0.1f* DeltaTime) % 360); CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngles.get(i)); - //CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime); + CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime); CubeActors.get(i).UpdateModelMatrix(); } + Ticks++; + if(Ticks == 1000){ + + } } @Override @@ -133,7 +168,7 @@ public class GameCore implements GameLogic { for(int i = angles.size()/2; i < angles.size(); i++) { angles.set(i, (angles.get(i) + 1.0f* DeltaTime) % 360); CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngles.get(i)); - // CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime); + CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime); CubeActors.get(i).UpdateModelMatrix(); } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java index bcef070..7511a9b 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java @@ -10,6 +10,11 @@ import net.halbear.Terrain4J.EngineCore.Threads.MainThread; import net.halbear.Terrain4J.EngineCore.Threads.RenderThread; import org.tinylog.Logger; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + public class PrimaryRuntime { private int Frames = 0; private int TickFrames = 0; @@ -30,9 +35,23 @@ public class PrimaryRuntime { private static GameLogic gameLogic; public PrimaryRuntime(String windowTitle, GameLogic appLogic) { + String[] knownDLSSfiles = {"nvngx_dlss.dll", "nvngx_dlssg.dll", "_nvngx.dll"}; + for (String dllName : knownDLSSfiles) { + Path dllPath = Paths.get(System.getProperty("user.dir"), dllName); + if (Files.exists(dllPath)) { + try { + Logger.warn("DLSS is not supported, and is not allowed to be used with Terrain4J: [{}]",dllName); + Files.delete(dllPath); + Logger.info("removed local DLSS hook."); + } catch (IOException e) { + Logger.error("Could not remove DLSS DLL. Exiting to prevent pipeline corruption."); + System.exit(1); + } + } + } window = new Window(windowTitle); gameLogic = appLogic; - engineInstance = new EngineInstance(window, new Scene(window)); + engineInstance = new EngineInstance(window, new Scene(window),this); InitData initData = appLogic.Initialise(engineInstance); PrimaryThread = new MainThread(engineInstance, appLogic); FastThread = new FastTickThread(engineInstance, appLogic); @@ -40,6 +59,9 @@ public class PrimaryRuntime { cpuProfiler = new CPUMonitor(); Thread.currentThread().setName("Terrain4J Primary Runtime Thread"); } + public static MainThread GetMainThread(){return PrimaryThread;} + public static RenderThread GetRenderThread(){return DrawingThread;} + public static FastTickThread GetFastThread(){return FastThread;} public static void UpdateFrameAccuracy(){ if(EngineConfig.getInstance().IsEngineThrottled()){ Logger.debug("ThrottlingEngine"); @@ -101,7 +123,6 @@ public class PrimaryRuntime { EngineConfig.FrameRate_PRIMARYTHREAD = Frames; EngineConfig.TPS = TickFrames; Logger.info("Primary Thread FPS: " + Frames + " TPS: " + TickFrames + " Window Draw FPS: " + EngineConfig.RENDERFRAMES); - Logger.info(cpuProfiler.LogCPUUsage() + "\t"); Frames = 0; TickFrames = 0; EngineConfig.RENDERFRAMES = 0; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Util/Maths/T4Math.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Util/Maths/T4Math.java index fe9572b..2682f1d 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Util/Maths/T4Math.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Util/Maths/T4Math.java @@ -4,4 +4,5 @@ public class T4Math { public static double Log2(int n){ return Math.log(n) / Math.log(n); } + public static double Square(double n){return n*n;} } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/FastTickThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/FastTickThread.java index c4c062f..5080445 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/FastTickThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/FastTickThread.java @@ -15,6 +15,7 @@ public class FastTickThread extends EngineThread { @Override public void TickEvent(long nsTimeDiff){ + gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (nsTimeDiff)); gameLogic.UpdateFastThread(PrimaryRuntime.GetEngineInstance(), nsTimeDiff); } @Override diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java index 4dff1eb..b9c38e6 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java @@ -10,7 +10,7 @@ public class MainThread extends EngineThread { @Override public void TickEvent(long nsTimeDiff){ - gameLogic.Update(PrimaryRuntime.GetEngineInstance(), nsTimeDiff); + } @Override public void FrameEvent(long now, long InitialTime){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java index 5d43670..b55d620 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java @@ -18,13 +18,14 @@ public class RenderThread extends EngineThread { render.Initialise(initData); } + public Render GetRenderer(){return render;} + @Override public void TickEvent(long nsTimeDiff){ - } @Override public void FrameEvent(long now, long InitialTime){ - gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (now - InitialTime)); + gameLogic.Update(PrimaryRuntime.GetEngineInstance(), (now - InitialTime)); render.render(PrimaryRuntime.GetEngineInstance()); } @Override diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/EmptyVertexBufferStruct.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/EmptyVertexBufferStruct.java new file mode 100644 index 0000000..c4a2fc0 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/EmptyVertexBufferStruct.java @@ -0,0 +1,16 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering; + +import org.lwjgl.vulkan.VkPipelineVertexInputStateCreateInfo; + +public class EmptyVertexBufferStruct { + + private final VkPipelineVertexInputStateCreateInfo VertexInput; + + public EmptyVertexBufferStruct(){ + VertexInput = VkPipelineVertexInputStateCreateInfo.calloc(); + VertexInput.sType$Default(); + } + + public void CleanUp(){VertexInput.free();} + public VkPipelineVertexInputStateCreateInfo GetVertexInput(){return VertexInput;} +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/DefaultPipeline.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/DefaultPipeline.java new file mode 100644 index 0000000..bd6b1b5 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/DefaultPipeline.java @@ -0,0 +1,193 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline; + +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSetLayout; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.ShaderModule; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.*; +import org.tinylog.Logger; + +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.nio.LongBuffer; + +import static org.lwjgl.vulkan.VK13.*; +import static org.lwjgl.vulkan.VK13.VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; +import static org.lwjgl.vulkan.VK13.VK_BLEND_FACTOR_SRC_ALPHA; +import static org.lwjgl.vulkan.VK13.VK_BLEND_FACTOR_ZERO; +import static org.lwjgl.vulkan.VK13.VK_BLEND_OP_ADD; +import static org.lwjgl.vulkan.VK13.VK_COLOR_COMPONENT_A_BIT; +import static org.lwjgl.vulkan.VK13.VK_COLOR_COMPONENT_B_BIT; +import static org.lwjgl.vulkan.VK13.VK_COLOR_COMPONENT_G_BIT; +import static org.lwjgl.vulkan.VK13.VK_COLOR_COMPONENT_R_BIT; +import static org.lwjgl.vulkan.VK13.VK_CULL_MODE_NONE; +import static org.lwjgl.vulkan.VK13.VK_DYNAMIC_STATE_SCISSOR; +import static org.lwjgl.vulkan.VK13.VK_DYNAMIC_STATE_VIEWPORT; +import static org.lwjgl.vulkan.VK13.VK_FORMAT_UNDEFINED; +import static org.lwjgl.vulkan.VK13.VK_FRONT_FACE_CLOCKWISE; +import static org.lwjgl.vulkan.VK13.VK_NULL_HANDLE; +import static org.lwjgl.vulkan.VK13.VK_SAMPLE_COUNT_1_BIT; +import static org.lwjgl.vulkan.VK13.VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; +import static org.lwjgl.vulkan.VK13.vkCreateGraphicsPipelines; +import static org.lwjgl.vulkan.VK13.vkCreatePipelineLayout; +import static org.lwjgl.vulkan.VK13.vkDestroyPipeline; +import static org.lwjgl.vulkan.VK13.vkDestroyPipelineLayout; + +public class DefaultPipeline implements Pipeline { + private final long VulkanPipeline; + private final long VulkanPipelineLayout; + + public DefaultPipeline(VulkanContext VkCtx, PipelineBuildInfo BuildInfo){ + Logger.debug("Creating Pipeline"); + Device device = VkCtx.GetDevice(); + try(var MemStack = MemoryStack.stackPush()){ + LongBuffer longPtr = MemStack.mallocLong(1); + ByteBuffer main = MemStack.UTF8("main"); + ShaderModule[] ShaderModules = BuildInfo.GetShaderModules(); + int ModuleCount = ShaderModules.length; + var ShaderStages = VkPipelineShaderStageCreateInfo.calloc(ModuleCount, MemStack); + for(int i = 0; i < ModuleCount; i++){ + ShaderModule shaderModule = ShaderModules[i]; + ShaderStages.get(i) + .sType$Default() + .stage(shaderModule.GetShaderStage()) + .module(shaderModule.GetHandle()) + .pName(main); + if(shaderModule.GetSpecializationInfo() != null){ + ShaderStages.get(i).pSpecializationInfo(shaderModule.GetSpecializationInfo()); + } + } + + var AssemblyStateCreateInfo = VkPipelineInputAssemblyStateCreateInfo.calloc(MemStack) + .sType$Default() + .topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + var ViewportCreateStateInfo = VkPipelineViewportStateCreateInfo.calloc(MemStack) + .sType$Default() + .viewportCount(1) + .scissorCount(1); + var RasterizationStateCreateInfo = VkPipelineRasterizationStateCreateInfo.calloc(MemStack) + .sType(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO) + .polygonMode(VK_POLYGON_MODE_FILL) + .cullMode(VK_CULL_MODE_NONE) + .frontFace(VK_FRONT_FACE_CLOCKWISE) + .lineWidth(1.0f); + int sampleCount = EngineConfig.getInstance().GetRenderSampleCount(); + var MultisampleStateCreateInfo = VkPipelineMultisampleStateCreateInfo.calloc(MemStack) + .sType$Default() + .rasterizationSamples(sampleCount) + .sampleShadingEnable(false) + .minSampleShading(1.0f) + .pSampleMask(null) + .alphaToCoverageEnable(false) + .alphaToOneEnable(false); + + VkPipelineDepthStencilStateCreateInfo DepthStencil = null; + if(BuildInfo.GetDepthFormat() != VK_FORMAT_UNDEFINED){ + DepthStencil = VkPipelineDepthStencilStateCreateInfo.calloc(MemStack) + .sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO) + .depthTestEnable(true) + .depthWriteEnable(true) + .depthCompareOp(VK_COMPARE_OP_GREATER_OR_EQUAL) + .depthBoundsTestEnable(false) + .stencilTestEnable(false); + } + + + VkPipelineDynamicStateCreateInfo VulkanPipelineDynamicStateCreateInfo = VkPipelineDynamicStateCreateInfo.calloc(MemStack) + .sType$Default() + .pDynamicStates(MemStack.ints( + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + )); + + + VkPushConstantRange.Buffer VkPushConstRangeBuffer = null; + PushConstantsRange[] PushConstRanges = BuildInfo.GetPushConstantRanges(); + int PushConstCount = PushConstRanges != null ? PushConstRanges.length != 0 ? PushConstRanges.length : 0 : 0; + if(PushConstCount > 0){ + VkPushConstRangeBuffer = VkPushConstantRange.calloc(PushConstCount,MemStack); + for(int i = 0; i < PushConstCount; i++){ + PushConstantsRange pushConstantsRange = PushConstRanges[i]; + VkPushConstRangeBuffer.get(i) + .stageFlags(pushConstantsRange.Stage()) + .offset(pushConstantsRange.Offset()) + .size(pushConstantsRange.Size()); + } + } + DescriptorSetLayout[] descriptorSetLayouts = BuildInfo.GetDescriptorSetLayouts(); + int LayoutCount = descriptorSetLayouts != null ? descriptorSetLayouts.length : 0; + LongBuffer ppLayout = MemStack.mallocLong(LayoutCount); + for(int i = 0; i < LayoutCount; i++){ + ppLayout.put(i, descriptorSetLayouts[i].GetVkDescriptorLayout()); + } + var BlendAttributeState = VkPipelineColorBlendAttachmentState.calloc(1,MemStack) + .colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT) + .blendEnable(BuildInfo.BlendingUsed()); + if(BuildInfo.BlendingUsed()){ + BlendAttributeState.get(0).colorBlendOp(VK_BLEND_OP_ADD) + .alphaBlendOp(VK_BLEND_OP_ADD) + .srcColorBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA) + .dstColorBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA) + .srcAlphaBlendFactor(VK_BLEND_FACTOR_ONE) + .dstAlphaBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA); + } + + var ColourBlendState = VkPipelineColorBlendStateCreateInfo.calloc(MemStack) + .sType$Default() + .pAttachments(BlendAttributeState); + + IntBuffer ColourFormats = MemStack.mallocInt(1); + ColourFormats.put(0,BuildInfo.GetColourFormat()); + + var RendererCreateInfo = VkPipelineRenderingCreateInfo.calloc(MemStack) + .sType$Default() + .colorAttachmentCount(1) + .pColorAttachmentFormats(ColourFormats); + + if(DepthStencil != null){RendererCreateInfo.depthAttachmentFormat(BuildInfo.GetDepthFormat());} + + var PipelineLayoutCreateInfoPtr = VkPipelineLayoutCreateInfo.calloc(MemStack) + .sType$Default() + .pSetLayouts(ppLayout) + .pPushConstantRanges(VkPushConstRangeBuffer); + + VulkanUtils.vkCheck(vkCreatePipelineLayout(device.FetchVulkanDevice(), PipelineLayoutCreateInfoPtr,null,longPtr) + ,"Unable to create new pipeline layout"); + VulkanPipelineLayout = longPtr.get(0); + + var PipelineCreateInfo = VkGraphicsPipelineCreateInfo.calloc(1,MemStack) + .sType$Default() + .renderPass(VK_NULL_HANDLE) + .pStages(ShaderStages) + .pVertexInputState(BuildInfo.GetVertexInputStateCreateInfo()) + .pInputAssemblyState(AssemblyStateCreateInfo) + .pViewportState(ViewportCreateStateInfo) + .pRasterizationState(RasterizationStateCreateInfo) + .pColorBlendState(ColourBlendState) + .pMultisampleState(MultisampleStateCreateInfo) + .pDynamicState(VulkanPipelineDynamicStateCreateInfo) + .layout(VulkanPipelineLayout) + .pNext(RendererCreateInfo); + + + if(DepthStencil != null){PipelineCreateInfo.pDepthStencilState(DepthStencil);} + + VulkanUtils.vkCheck(vkCreateGraphicsPipelines(device.FetchVulkanDevice(), + VkCtx.GetVkPipelineCache().GetVkPipelineCache(), PipelineCreateInfo, + null, longPtr),"Could not create new pipeline"); + VulkanPipeline = longPtr.get(0); + } + } + public long GetVulkanPipeline(){return VulkanPipeline;} + public long GetVulkanPipelineLayout(){return VulkanPipelineLayout;} + public void CleanUp(VulkanContext VkCtx){ + Logger.debug("destroying Pipeline"); + VkDevice vkDevice = VkCtx.GetDevice().FetchVulkanDevice(); + vkDestroyPipelineLayout(vkDevice,VulkanPipelineLayout,null); + vkDestroyPipeline(vkDevice,VulkanPipeline,null); + } + +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/GraphUtils.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/GraphUtils.java index a5d4664..c2c15ad 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/GraphUtils.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/GraphUtils.java @@ -1,6 +1,7 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline; import net.halbear.Terrain4J.EngineCore.Display.GLFWImageParser; +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.ImageSrc; import org.lwjgl.system.MemoryStack; import org.tinylog.Logger; @@ -29,8 +30,8 @@ public class GraphUtils { IntBuffer height = MemStack.mallocInt(1); image = stbi_load(Filename, width, height, channels, 4); if (image == null) { - Logger.error("Could not load or find image inputted."); - throw new IOException("Image file [" + Filename + "] not loaded: " + stbi_failure_reason()); + Logger.error("Could not load or find image inputted. Image file [" + Filename + "] not loaded: " + stbi_failure_reason()); + image = stbi_load(EngineConfig.getInstance().GetDefaultTexturePath(), width, height, channels, 4); } newImage = new ImageSrc(image, width.get(0), height.get(0), channels.get(0)); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Attachment.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Attachment.java index 980f3c2..573efd1 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Attachment.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Attachment.java @@ -1,5 +1,6 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images; +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView; @@ -11,8 +12,8 @@ public class Attachment { private boolean DepthAttachment; public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage){ - var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format) - .Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT).MemoryUsage(VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT); + var ImageData = new Image.ImageData().Width(Width).Height(Height) + .Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT).Format(Format).MemoryUsage(VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT).SampleCount(EngineConfig.getInstance().GetRenderSampleCount()); VkImage = new Image(VkCtx, ImageData); int AspectMask = 0; @@ -25,7 +26,7 @@ public class Attachment { DepthAttachment = true; } var ImageViewData = new ImageView.ImageViewData().Format(VkImage.GetFormat()).AspectMask(AspectMask); - VkImageView = new ImageView(VkCtx.GetDevice(), VkImage.getVulkanImage(), ImageViewData,false); + VkImageView = new ImageView(VkCtx.GetDevice(), VkImage.getVulkanImage(), ImageViewData,DepthAttachment); } public Image GetVkImage(){return VkImage;} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Image.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Image.java index 2e6274c..bacd8bb 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Image.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Image.java @@ -1,5 +1,6 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images; +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; @@ -22,12 +23,19 @@ public class Image { private final int Format; private final int MipLevels; private final long VulkanImage; + private final int Width; + private final int Height; //private final long VulkanMemory; + public int GetWidth(){return Width;} + public int GetHeight(){return Height;} + public Image(VulkanContext VkCtx, ImageData imageData){ try(var MemStack = MemoryStack.stackPush()){ this.Format = imageData.Format; this.MipLevels = imageData.MipMapLevels; + this.Width = imageData.Width; + this.Height = imageData.Height; VkImageCreateInfo vkImageCreateInfo = VkImageCreateInfo.calloc(MemStack) .sType$Default() diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Texture.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Texture.java index 3487d3d..7d6f047 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Texture.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Texture.java @@ -9,6 +9,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; import org.lwjgl.vulkan.*; +import org.tinylog.Logger; import java.nio.ByteBuffer; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/TextureCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/TextureCache.java index be6b8f8..8859b5c 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/TextureCache.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/TextureCache.java @@ -4,6 +4,7 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.GraphUtils; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.IndexedLinkedHashMap; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.VulkanMaterial; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandPool; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue; @@ -17,25 +18,16 @@ import java.util.UUID; import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB; public class TextureCache { - public static final int MAX_TEXTURES = 100; + public static final int MAX_TEXTURES = 500; private final IndexedLinkedHashMap TextureMap; + private final IndexedLinkedHashMap UnpaddedTextureMap; public TextureCache(){ TextureMap = new IndexedLinkedHashMap<>(); + UnpaddedTextureMap = new IndexedLinkedHashMap<>(); } - public Texture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format){ - if(TextureMap.size() > MAX_TEXTURES){ - throw new IllegalArgumentException("Texture Cache Is Full"); - } - Texture newTexture = TextureMap.get(ID); - if(newTexture == null){ - newTexture = new Texture(VkCtx, ID, imageSrc, Format); - TextureMap.put(ID, newTexture); - } - return newTexture; - } - public Texture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format) { + public Texture AddToMainMap(VulkanContext VkCtx, String ID, String TexturePath, int Format) { ImageSrc imageSrc = null; Texture result = null; try{ @@ -50,15 +42,45 @@ public class TextureCache { } return result; } + public Texture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format){ + if(TextureMap.size() > MAX_TEXTURES){ + throw new IllegalArgumentException("Texture Cache Is Full"); + } + Texture newTexture = UnpaddedTextureMap.get(ID); + if(newTexture == null){ + newTexture = new Texture(VkCtx, ID, imageSrc, Format); + UnpaddedTextureMap.put(ID, newTexture); + TextureMap.put(ID, newTexture); + } + return newTexture; + } + public Texture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format) { + ImageSrc imageSrc = null; + Texture result = null; + try{ + + imageSrc = GraphUtils.LoadImage(TexturePath); + result = AddTexture(VkCtx, ID, imageSrc, Format); + } catch (IOException exception){ + Logger.error("Could not load texture from patch [{}], exception: {}",TexturePath, exception); + } finally{ + if(imageSrc != null){ + GraphUtils.CleanImageData(imageSrc); + } + } + return result; + } public void TransitionTexts(VulkanContext VkCtx, CommandPool CmdPool, Queue queue){ Logger.debug("Recording Texture Transition"); + TextureMap.clear(); + TextureMap.putAll(UnpaddedTextureMap); int TextureCount = TextureMap.size(); if(TextureCount < MAX_TEXTURES){ int PaddingTextCount = MAX_TEXTURES - TextureCount; String DefaultTexturePath = EngineConfig.getInstance().GetDefaultTexturePath(); for(int i = 0; i < PaddingTextCount; i++){ - AddTexture(VkCtx, UUID.randomUUID().toString(), DefaultTexturePath, VK_FORMAT_R8G8B8A8_SRGB); + AddToMainMap(VkCtx, UUID.randomUUID().toString(), DefaultTexturePath, VK_FORMAT_R8G8B8A8_SRGB); } } var CommandBuffer = new CommandBuffer(VkCtx, CmdPool, true, true); @@ -71,6 +93,7 @@ public class TextureCache { Logger.debug("Recorded Texture Transition"); } + public IndexedLinkedHashMap GetTextureCache(){return TextureMap;} public List GetTextureList(){return new ArrayList<>(TextureMap.values());} public int GetPosition(String ID){ int result = -1; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/IndexedLinkedHashMap.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/IndexedLinkedHashMap.java index b02c82c..5bc28fa 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/IndexedLinkedHashMap.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/IndexedLinkedHashMap.java @@ -3,6 +3,7 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; public class IndexedLinkedHashMap extends LinkedHashMap { private final List IndexList = new ArrayList<>(); @@ -20,4 +21,11 @@ public class IndexedLinkedHashMap extends LinkedHashMap { if(!super.containsKey(key)) IndexList.add(key); return super.put(key,value); } + //@Override + //public void putAll(Map m) { + // m.forEach((k, v)->{ + // put(k,v); + // IndexList.add(k); + // }); + //} } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Pipeline.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Pipeline.java index 0e39196..68dc670 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Pipeline.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Pipeline.java @@ -1,163 +1,10 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; -import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSetLayout; -import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.ShaderModule; -import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; -import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; -import org.lwjgl.system.MemoryStack; -import org.lwjgl.vulkan.*; -import org.tinylog.Logger; -import java.nio.ByteBuffer; -import java.nio.IntBuffer; -import java.nio.LongBuffer; - -import static org.lwjgl.vulkan.VK10.*; -import static org.lwjgl.vulkan.VK13.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - -public class Pipeline { - private final long VulkanPipeline; - private final long VulkanPipelineLayout; - - public Pipeline(VulkanContext VkCtx, PipelineBuildInfo BuildInfo){ - Logger.debug("Creating Pipeline"); - Device device = VkCtx.GetDevice(); - try(var MemStack = MemoryStack.stackPush()){ - LongBuffer longPtr = MemStack.mallocLong(1); - ByteBuffer main = MemStack.UTF8("main"); - ShaderModule[] ShaderModules = BuildInfo.GetShaderModules(); - int ModuleCount = ShaderModules.length; - var ShaderStages = VkPipelineShaderStageCreateInfo.calloc(ModuleCount, MemStack); - for(int i = 0; i < ModuleCount; i++){ - ShaderModule shaderModule = ShaderModules[i]; - ShaderStages.get(i) - .sType$Default() - .stage(shaderModule.GetShaderStage()) - .module(shaderModule.GetHandle()) - .pName(main); - } - - var AssemblyStateCreateInfo = VkPipelineInputAssemblyStateCreateInfo.calloc(MemStack) - .sType$Default() - .topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); - var ViewportCreateStateInfo = VkPipelineViewportStateCreateInfo.calloc(MemStack) - .sType$Default() - .viewportCount(1) - .scissorCount(1); - var RasterizationStateCreateInfo = VkPipelineRasterizationStateCreateInfo.calloc(MemStack) - .sType$Default() - .polygonMode(VK_POLYGON_MODE_FILL) - .cullMode(VK_CULL_MODE_NONE) - .frontFace(VK_FRONT_FACE_CLOCKWISE) - .lineWidth(1.0f); - var MultisampleStateCreateInfo = VkPipelineMultisampleStateCreateInfo.calloc(MemStack) - .sType$Default() - .rasterizationSamples(VK_SAMPLE_COUNT_1_BIT); - - VkPipelineDepthStencilStateCreateInfo DepthStencil = null; - if(BuildInfo.GetDepthFormat() != VK_FORMAT_UNDEFINED){ - DepthStencil = VkPipelineDepthStencilStateCreateInfo.calloc(MemStack) - .sType$Default() - .depthTestEnable(true) - .depthWriteEnable(true) - .depthCompareOp(VK_COMPARE_OP_LESS_OR_EQUAL) - .depthBoundsTestEnable(false) - .stencilTestEnable(false); - } - - - VkPipelineDynamicStateCreateInfo VulkanPipelineDynamicStateCreateInfo = VkPipelineDynamicStateCreateInfo.calloc(MemStack) - .sType$Default() - .pDynamicStates(MemStack.ints( - VK_DYNAMIC_STATE_VIEWPORT, - VK_DYNAMIC_STATE_SCISSOR - )); - - - VkPushConstantRange.Buffer VkPushConstRangeBuffer = null; - PushConstantsRange[] PushConstRanges = BuildInfo.GetPushConstantRanges(); - int PushConstCount = PushConstRanges.length != 0 ? PushConstRanges.length : 0; - if(PushConstCount > 0){ - VkPushConstRangeBuffer = VkPushConstantRange.calloc(PushConstCount,MemStack); - for(int i = 0; i < PushConstCount; i++){ - PushConstantsRange pushConstantsRange = PushConstRanges[i]; - VkPushConstRangeBuffer.get(i) - .stageFlags(pushConstantsRange.Stage()) - .offset(pushConstantsRange.Offset()) - .size(pushConstantsRange.Size()); - } - } - DescriptorSetLayout[] descriptorSetLayouts = BuildInfo.GetDescriptorSetLayouts(); - int LayoutCount = descriptorSetLayouts != null ? descriptorSetLayouts.length : 0; - LongBuffer ppLayout = MemStack.mallocLong(LayoutCount); - for(int i = 0; i < LayoutCount; i++){ - ppLayout.put(i, descriptorSetLayouts[i].GetVkDescriptorLayout()); - } - var BlendAttributeState = VkPipelineColorBlendAttachmentState.calloc(1,MemStack) - .colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT) - .blendEnable(BuildInfo.BlendingUsed()); - if(BuildInfo.BlendingUsed()){ - BlendAttributeState.get(0).colorBlendOp(VK_BLEND_OP_ADD) - .alphaBlendOp(VK_BLEND_OP_ADD) - .srcColorBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA) - .dstColorBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA) - .srcAlphaBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA) - .dstAlphaBlendFactor(VK_BLEND_FACTOR_ZERO); - } - - - var ColourBlendState = VkPipelineColorBlendStateCreateInfo.calloc(MemStack) - .sType$Default() - .pAttachments(BlendAttributeState); - IntBuffer ColourFormats = MemStack.mallocInt(1); - ColourFormats.put(0,BuildInfo.GetColourFormat()); - - var RendererCreateInfo = VkPipelineRenderingCreateInfo.calloc(MemStack) - .sType$Default() - .colorAttachmentCount(1) - .pColorAttachmentFormats(ColourFormats); - - if(DepthStencil != null){RendererCreateInfo.depthAttachmentFormat(BuildInfo.GetDepthFormat());} - - var PipelineLayoutCreateInfoPtr = VkPipelineLayoutCreateInfo.calloc(MemStack) - .sType$Default() - .pSetLayouts(ppLayout) - .pPushConstantRanges(VkPushConstRangeBuffer); - - VulkanUtils.vkCheck(vkCreatePipelineLayout(device.FetchVulkanDevice(), PipelineLayoutCreateInfoPtr,null,longPtr) - ,"Unable to create new pipeline layout"); - VulkanPipelineLayout = longPtr.get(0); - - var PipelineCreateInfo = VkGraphicsPipelineCreateInfo.calloc(1,MemStack) - .sType$Default() - .renderPass(VK_NULL_HANDLE) - .pStages(ShaderStages) - .pVertexInputState(BuildInfo.GetVertexInputStateCreateInfo()) - .pInputAssemblyState(AssemblyStateCreateInfo) - .pViewportState(ViewportCreateStateInfo) - .pRasterizationState(RasterizationStateCreateInfo) - .pColorBlendState(ColourBlendState) - .pMultisampleState(MultisampleStateCreateInfo) - .pDynamicState(VulkanPipelineDynamicStateCreateInfo) - .layout(VulkanPipelineLayout) - .pNext(RendererCreateInfo); - - if(DepthStencil != null){PipelineCreateInfo.pDepthStencilState(DepthStencil);} - - VulkanUtils.vkCheck(vkCreateGraphicsPipelines(device.FetchVulkanDevice(), - VkCtx.GetVkPipelineCache().GetVkPipelineCache(), PipelineCreateInfo, - null, longPtr),"Could not create new pipeline"); - VulkanPipeline = longPtr.get(0); - } - } - public long GetVulkanPipeline(){return VulkanPipeline;} - public long GetVulkanPipelineLayout(){return VulkanPipelineLayout;} - public void CleanUp(VulkanContext VkCtx){ - Logger.debug("destroying Pipeline"); - VkDevice vkDevice = VkCtx.GetDevice().FetchVulkanDevice(); - vkDestroyPipelineLayout(vkDevice,VulkanPipelineLayout,null); - vkDestroyPipeline(vkDevice,VulkanPipeline,null); - } +public interface Pipeline { + public long GetVulkanPipeline(); + public long GetVulkanPipelineLayout(); + public void CleanUp(VulkanContext VkCtx); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/VoxelPipeline.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/VoxelPipeline.java new file mode 100644 index 0000000..a0dac07 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/VoxelPipeline.java @@ -0,0 +1,174 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline; + +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSetLayout; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.*; +import org.tinylog.Logger; + +import java.nio.LongBuffer; + +import static org.lwjgl.vulkan.VK10.*; + +public class VoxelPipeline implements Pipeline{ + private final long VulkanPipeline; + private final long VulkanPipelineLayout; + + public VoxelPipeline(VulkanContext VkCtx, PipelineBuildInfo BuildInfo){ + Device device = VkCtx.GetDevice(); + try(var MemStack = MemoryStack.stackPush()) { + LongBuffer longPtr = MemStack.mallocLong(1); + VkPushConstantRange.Buffer VkPushConstRangeBuffer = null; + PushConstantsRange[] PushConstRanges = BuildInfo.GetPushConstantRanges(); + int PushConstCount = PushConstRanges.length != 0 ? PushConstRanges.length : 0; + if (PushConstCount > 0) { + VkPushConstRangeBuffer = VkPushConstantRange.calloc(PushConstCount, MemStack); + for (int i = 0; i < PushConstCount; i++) { + PushConstantsRange pushConstantsRange = PushConstRanges[i]; + VkPushConstRangeBuffer.get(i) + .stageFlags(pushConstantsRange.Stage()) + .offset(pushConstantsRange.Offset()) + .size(pushConstantsRange.Size()); + } + } + DescriptorSetLayout[] descriptorSetLayouts = BuildInfo.GetDescriptorSetLayouts(); + int LayoutCount = descriptorSetLayouts != null ? descriptorSetLayouts.length : 0; + LongBuffer ppLayout = MemStack.mallocLong(LayoutCount); + for (int i = 0; i < LayoutCount; i++) { + ppLayout.put(i, descriptorSetLayouts[i].GetVkDescriptorLayout()); + } + + var PipelineLayoutCreateInfoPtr = VkPipelineLayoutCreateInfo.calloc(MemStack) + .sType$Default() + .pSetLayouts(ppLayout) + .pPushConstantRanges(VkPushConstRangeBuffer); + + VulkanUtils.vkCheck(vkCreatePipelineLayout(device.FetchVulkanDevice(), PipelineLayoutCreateInfoPtr, null, longPtr) + , "Unable to create new pipeline layout"); + VulkanPipelineLayout = longPtr.get(0); + VulkanPipeline = CreateVoxelPipeline(VkCtx,device.FetchVulkanDevice(), 0, VulkanPipelineLayout,MemStack); + } + } + + public static long CreatePipelineLayout(VkDevice device,LongBuffer DescriptorSetLayout, MemoryStack MemStack){ + VkDescriptorSetLayoutBinding.Buffer BindingBuffer = VkDescriptorSetLayoutBinding.calloc(2,MemStack); + BindingBuffer.get(0) + .binding(0) + .descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) + .descriptorCount(1) + .stageFlags(VK_SHADER_STAGE_VERTEX_BIT); + BindingBuffer.get(1) + .binding(1) + .descriptorType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) + .descriptorCount(1) + .stageFlags(VK_SHADER_STAGE_FRAGMENT_BIT); + VkDescriptorSetLayoutCreateInfo LayoutInfo = VkDescriptorSetLayoutCreateInfo.calloc(MemStack) + .sType$Default() + .pBindings(BindingBuffer); + + LongBuffer LongPtr = MemStack.mallocLong(1); + VulkanUtils.vkCheck(vkCreateDescriptorSetLayout(device, LayoutInfo, + null, LongPtr),"Could not create new Descriptor Set Layout"); + Long pDescriptorSetLayout = LongPtr.get(0); + DescriptorSetLayout.put(0,pDescriptorSetLayout); + LongBuffer LayoutPointer = MemStack.longs(pDescriptorSetLayout); + VkPipelineLayoutCreateInfo PipelineLayoutInfo = VkPipelineLayoutCreateInfo.calloc(MemStack) + .sType$Default() + .pSetLayouts(LayoutPointer); + VulkanUtils.vkCheck(vkCreatePipelineLayout(device, PipelineLayoutInfo, + null, LongPtr),"Could not create Pipeline Layout"); + return LongPtr.get(0); + } + + public static long CreateVoxelPipeline(VulkanContext VkCtx,VkDevice device, long RenderPass, long PipelineLayout, MemoryStack MemStack) { + LongBuffer longPtr = MemStack.mallocLong(1); + VkVertexInputBindingDescription.Buffer BindingDescriptionBuffer = VkVertexInputBindingDescription.calloc(1, MemStack) + .binding(0) + .stride(5) + .inputRate(VK_VERTEX_INPUT_RATE_VERTEX); + VkVertexInputAttributeDescription.Buffer AttributeDescriptionsBuffer = VkVertexInputAttributeDescription.calloc(2, MemStack); + + AttributeDescriptionsBuffer.get(0) + .location(0) + .binding(0) + .format(VK_FORMAT_R8G8B8_UINT) + .offset(0); + AttributeDescriptionsBuffer.get(1) + .location(1) + .binding(0) + .format(VK_FORMAT_R8G8_UINT); + VkPipelineVertexInputStateCreateInfo VertexInputInfo = VkPipelineVertexInputStateCreateInfo.calloc(MemStack) + .sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO) + .pVertexBindingDescriptions(BindingDescriptionBuffer) + .pVertexAttributeDescriptions(AttributeDescriptionsBuffer); + var AssemblyStateCreateInfo = VkPipelineInputAssemblyStateCreateInfo.calloc(MemStack) + .sType(VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO) + .topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST).primitiveRestartEnable(false); + var ViewportCreateStateInfo = VkPipelineViewportStateCreateInfo.calloc(MemStack) + .sType$Default() + .viewportCount(1) + .scissorCount(1); + var RasterizationStateCreateInfo = VkPipelineRasterizationStateCreateInfo.calloc(MemStack) + .sType(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO) + .depthClampEnable(false) + .rasterizerDiscardEnable(false) + .polygonMode(VK_POLYGON_MODE_FILL) + .cullMode(VK_CULL_MODE_BACK_BIT) + .frontFace(VK_FRONT_FACE_CLOCKWISE) + .lineWidth(1.0f) + .depthBiasEnable(false); + var MultisampleStateCreateInfo = VkPipelineMultisampleStateCreateInfo.calloc(MemStack) + .sType$Default() + .sampleShadingEnable(false) + .rasterizationSamples(VK_SAMPLE_COUNT_1_BIT); + VkPipelineColorBlendAttachmentState.Buffer ColourBlendAttachment = VkPipelineColorBlendAttachmentState.calloc(1, MemStack) + .colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT) + .blendEnable(false); + VkPipelineColorBlendStateCreateInfo ColourBlending = VkPipelineColorBlendStateCreateInfo.calloc(MemStack) + .sType(VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO) + .logicOpEnable(false) + .pAttachments(ColourBlendAttachment); + + VkGraphicsPipelineCreateInfo.Buffer PipelineInfo = VkGraphicsPipelineCreateInfo.calloc(1) + .sType(VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO) + .pVertexInputState(VertexInputInfo) + .pInputAssemblyState(AssemblyStateCreateInfo) + .pViewportState(ViewportCreateStateInfo) + .pRasterizationState(RasterizationStateCreateInfo) + .pMultisampleState(MultisampleStateCreateInfo) + .pColorBlendState(ColourBlending) + .layout(PipelineLayout) + .renderPass(RenderPass) + .subpass(0); + VulkanUtils.vkCheck(vkCreateGraphicsPipelines(device, + VkCtx.GetVkPipelineCache().GetVkPipelineCache(), PipelineInfo, + null, longPtr),"Could not create new pipeline"); + + // Clean up allocation structs + PipelineInfo.free(); ColourBlending.free(); ColourBlendAttachment.free(); + MultisampleStateCreateInfo.free(); RasterizationStateCreateInfo.free(); ViewportCreateStateInfo.free(); + AssemblyStateCreateInfo.free(); VertexInputInfo.free(); AssemblyStateCreateInfo.free(); + BindingDescriptionBuffer.free(); + + return longPtr.get(0); + } + @Override + public long GetVulkanPipeline() { + return VulkanPipeline; + } + + @Override + public long GetVulkanPipelineLayout() { + return VulkanPipelineLayout; + } + + @Override + public void CleanUp(VulkanContext VkCtx) { + Logger.debug("destroying Pipeline"); + VkDevice vkDevice = VkCtx.GetDevice().FetchVulkanDevice(); + vkDestroyPipelineLayout(vkDevice,VulkanPipelineLayout,null); + vkDestroyPipeline(vkDevice,VulkanPipeline,null); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/PostProcessing/PostProcess.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/PostProcessing/PostProcess.java new file mode 100644 index 0000000..aa39317 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/PostProcessing/PostProcess.java @@ -0,0 +1,219 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.PostProcessing; + +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.EmptyVertexBufferStruct; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Image; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.PipelineBuildInfo; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.*; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChain; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.system.MemoryUtil; +import org.lwjgl.util.shaderc.Shaderc; +import org.lwjgl.vulkan.*; + +import java.nio.FloatBuffer; +import java.nio.LongBuffer; +import java.util.Arrays; + +import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK13.*; + +public class PostProcess { + public static final int COLOUR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; + private static final String DESCRIPTOR_ID_ATTACHMENT = "POST_DESC_ID_ATT"; + private static final String DESCRIPTOR_ID_SCREEN_SIZE = "POST_DESC_ID_SCREEN_SIZE"; + private static final String MULTI_PASS_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl"; + private static final String MULTI_PASS_FRAGMENT_SHADER_FILE_SPV = MULTI_PASS_FRAGMENT_SHADER_FILE_GLSL + ".spv"; + private static final String SINGLE_PASS_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/post_process_frag.glsl"; + private static final String SINGLE_PASS_FRAGMENT_SHADER_FILE_SPV = SINGLE_PASS_FRAGMENT_SHADER_FILE_GLSL + ".spv"; + private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/post_process_vtx.glsl"; + private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; + + private final DescriptorSetLayout AttachmentDescriptorSetLayout; + private final VkClearValue ClearValueColour; + private final DescriptorSetLayout FragmentUniformDescriptorSetLayout; + private final Pipeline pipeline; + private final VulkanBuffer ScreenSizeBuffer; + private final SpecializationConstants specConstants; + private final TextureSampler textureSampler; + private Attachment ColourAttachment; + private VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo; + private VkRenderingInfo RenderingInfo; + + public PostProcess(VulkanContext VkCtx, Attachment SrcAttachment){ + ClearValueColour = VkClearValue.calloc(); + ClearValueColour.color(c->c.float32(0,0.0f).float32(1,0.0f).float32(2,0.0f).float32(3,0.0f)); + + ColourAttachment = CreateColourAttachment(VkCtx); + ColourAttachmentInfo = CreateColourAttachmentInfo(ColourAttachment,ClearValueColour); + RenderingInfo = CreateRenderInfo(ColourAttachment,ColourAttachmentInfo); + + var TextureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT,VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,1,true); + textureSampler = new TextureSampler(VkCtx, TextureSamplerInfo); + + var LayoutInfo = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,0,1,VK_SHADER_STAGE_FRAGMENT_BIT); + AttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx, LayoutInfo); + CreateAttachmentDescriptorSet(VkCtx, AttachmentDescriptorSetLayout, SrcAttachment,textureSampler); + + LayoutInfo = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0,1,VK_SHADER_STAGE_FRAGMENT_BIT); + FragmentUniformDescriptorSetLayout = new DescriptorSetLayout(VkCtx, LayoutInfo); + ScreenSizeBuffer = VulkanUtils.CreateHostVisibleBuffer(VkCtx, VulkanUtils.VEC2_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,DESCRIPTOR_ID_SCREEN_SIZE,FragmentUniformDescriptorSetLayout); + SetScreenSizeBuffer(VkCtx); + + specConstants = new SpecializationConstants(); + ShaderModule[] shaderModules = CreateShaderModules(VkCtx, specConstants); + + pipeline = CreatePipeline(VkCtx, shaderModules, new DescriptorSetLayout[]{AttachmentDescriptorSetLayout, FragmentUniformDescriptorSetLayout}); + Arrays.asList(shaderModules).forEach(shader->shader.CleanUp(VkCtx)); + } + + private static Attachment CreateColourAttachment(VulkanContext VkCtx){ + SwapChain swapChain = VkCtx.GetSwapChain(); + VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent(); + return new Attachment(VkCtx,SwapChainExtent.width(),SwapChainExtent.height(),COLOUR_FORMAT,VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + } + + private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment SrcAttachment, VkClearValue ClearValue){ + return VkRenderingAttachmentInfo.calloc(1) + .sType$Default() + .imageView(SrcAttachment.GetVkImageView().GetVulkanImageView()) + .imageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) + .storeOp(VK_ATTACHMENT_STORE_OP_STORE) + .clearValue(ClearValue); + } + + private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descriptorSetLayouts){ + var VertexBufferStruct = new EmptyVertexBufferStruct(); + var BuildInfo = new PipelineBuildInfo(shaderModules,VertexBufferStruct.GetVertexInput(),COLOUR_FORMAT).SetDescriptorSetLayouts(descriptorSetLayouts).BlendingIsUsed(true); + var PipeLine = new DefaultPipeline(VkCtx,BuildInfo); + VertexBufferStruct.CleanUp(); + return PipeLine; + } + + private static VkRenderingInfo CreateRenderInfo(Attachment ColourAttachment, VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo){ + VkRenderingInfo renderingInfo; + try(var MemStack = MemoryStack.stackPush()){ + Image image = ColourAttachment.GetVkImage(); + VkExtent2D extent2D = VkExtent2D.calloc(MemStack).width(image.GetWidth()).height(image.GetHeight()); + var RenderArea = VkRect2D.calloc(MemStack).extent(extent2D); + + renderingInfo = VkRenderingInfo.calloc() + .sType$Default() + .renderArea(RenderArea) + .layerCount(1) + .pColorAttachments(ColourAttachmentInfo); + } + return renderingInfo; + } + + private static void CreateAttachmentDescriptorSet(VulkanContext VkCtx, DescriptorSetLayout descriptorSetLayout, Attachment attachment, TextureSampler textureSampler){ + DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); + Device device = VkCtx.GetDevice(); + DescriptorSet descriptorSet = descriptorAllocator.AddDescriptorSets(device,DESCRIPTOR_ID_ATTACHMENT,1 , descriptorSetLayout)[0]; + descriptorSet.SetImage(device,attachment.GetVkImageView(),textureSampler,0); + } + + private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, SpecializationConstants specConstants){ + String ShaderPath = SINGLE_PASS_FRAGMENT_SHADER_FILE_GLSL; + if(EngineConfig.getInstance().RecompileShaders()){ + ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); + if(EngineConfig.getInstance().RenderAA() > 1) ShaderPath = MULTI_PASS_FRAGMENT_SHADER_FILE_GLSL; + ShaderCompiler.CompileGLSLShaderOnChange(ShaderPath, Shaderc.shaderc_glsl_fragment_shader); + } + ShaderPath = SINGLE_PASS_FRAGMENT_SHADER_FILE_SPV; + if(EngineConfig.getInstance().RenderAA() > 1) ShaderPath = MULTI_PASS_FRAGMENT_SHADER_FILE_SPV; + return new ShaderModule[]{ + new ShaderModule(VkCtx,VK_SHADER_STAGE_VERTEX_BIT,VERTEX_SHADER_FILE_SPV,null), + new ShaderModule(VkCtx,VK_SHADER_STAGE_FRAGMENT_BIT,ShaderPath,specConstants.GetSpecializationInfo()) + }; + } + + public void Render(VulkanContext VkCtx, CommandBuffer commandBuffer, Attachment SrcAttachment){ + try(var MemStack = MemoryStack.stackPush()){ + SwapChain swapChain = VkCtx.GetSwapChain(); + VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer(); + + VulkanUtils.ImageBarrier(MemStack, CommandHandle, SrcAttachment.GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_ACCESS_2_SHADER_READ_BIT,VK_IMAGE_ASPECT_COLOR_BIT); + VulkanUtils.ImageBarrier(MemStack,CommandHandle,ColourAttachment.GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_UNDEFINED,VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT,VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_2_NONE,VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_IMAGE_ASPECT_COLOR_BIT); + vkCmdBeginRendering(CommandHandle,RenderingInfo); + vkCmdBindPipeline(CommandHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,pipeline.GetVulkanPipeline()); + + VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent(); + int Width = SwapChainExtent.width(); + int Height = SwapChainExtent.height(); + var Viewport = VkViewport.calloc(1,MemStack) + .x(0) + .y(Height) + .height(-Height) + .width(Width) + .minDepth(0.0f) + .maxDepth(1.0f); + vkCmdSetViewport(CommandHandle,0,Viewport); + + var Scissor = VkRect2D.calloc(1,MemStack) + .extent(it->it.width(Width).height(Height)) + .offset(it->it.x(0).y(0)); + vkCmdSetScissor(CommandHandle,0,Scissor); + + DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); + LongBuffer DescriptorSets = MemStack.mallocLong(2) + .put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT).GetVkDescriptorSet()) + .put(1,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_SCREEN_SIZE).GetVkDescriptorSet()); + vkCmdBindDescriptorSets(CommandHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,pipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null); + vkCmdDraw(CommandHandle,3,1,0,0); + vkCmdEndRendering(CommandHandle); + } + } + + public void Resize(VulkanContext VkCtx, Attachment SrcAttachment){ + RenderingInfo.free();; + ColourAttachment.CleanUp(VkCtx); + ColourAttachmentInfo.free(); + ColourAttachment = CreateColourAttachment(VkCtx); + ColourAttachmentInfo = CreateColourAttachmentInfo(ColourAttachment,ClearValueColour); + RenderingInfo = CreateRenderInfo(ColourAttachment,ColourAttachmentInfo); + + DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); + DescriptorSet descriptorSet = descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT); + descriptorSet.SetImage(VkCtx.GetDevice(),SrcAttachment.GetVkImageView(),textureSampler,0); + + SetScreenSizeBuffer(VkCtx); + } + + private void SetScreenSizeBuffer(VulkanContext VkCtx){ + long MappedMemory = ScreenSizeBuffer.MapMemory(VkCtx); + FloatBuffer dataBuffer = MemoryUtil.memFloatBuffer(MappedMemory,(int)ScreenSizeBuffer.GetRequestedSize()); + VkExtent2D SwapChainExtent = VkCtx.GetSwapChain().GetSwapChainExtent(); + dataBuffer.put(0,SwapChainExtent.width()); + dataBuffer.put(1,SwapChainExtent.height()); + ScreenSizeBuffer.UnMapMemory(VkCtx); + } + + public Attachment GetAttachment(){return ColourAttachment;} + + public void CleanUp(VulkanContext VkCtx){ + ClearValueColour.free(); + ColourAttachment.CleanUp(VkCtx); + textureSampler.CleanUp(VkCtx); + AttachmentDescriptorSetLayout.CleanUp(VkCtx); + FragmentUniformDescriptorSetLayout.CleanUp(VkCtx); + pipeline.CleanUp(VkCtx); + RenderingInfo.free(); + ColourAttachmentInfo.free(); + ScreenSizeBuffer.cleanup(VkCtx); + specConstants.CleanUp(); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/PostProcessing/SpecializationConstants.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/PostProcessing/SpecializationConstants.java new file mode 100644 index 0000000..a55ce40 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/PostProcessing/SpecializationConstants.java @@ -0,0 +1,39 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.PostProcessing; + +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; +import org.lwjgl.system.MemoryUtil; +import org.lwjgl.vulkan.VkSpecializationInfo; +import org.lwjgl.vulkan.VkSpecializationMapEntry; + +import java.nio.ByteBuffer; + +public class SpecializationConstants { + + private final ByteBuffer data; + private final VkSpecializationMapEntry.Buffer SpecializationEntryMap; + private final VkSpecializationInfo SpecializationInfo; + + public SpecializationConstants(){ + var EngineCfg = EngineConfig.getInstance(); + data = MemoryUtil.memAlloc(VulkanUtils.INT_SIZE); + data.putInt(EngineCfg.RenderAA()); + data.flip(); + + SpecializationEntryMap = VkSpecializationMapEntry.calloc(1); + SpecializationEntryMap.get(0) + .constantID(0) + .size(VulkanUtils.INT_SIZE) + .offset(0); + + SpecializationInfo = VkSpecializationInfo.calloc(); + SpecializationInfo.pData(data).pMapEntries(SpecializationEntryMap); + } + + public void CleanUp(){ + MemoryUtil.memFree(SpecializationEntryMap); + SpecializationInfo.free(); + MemoryUtil.memFree(data); + } + public VkSpecializationInfo GetSpecializationInfo(){return SpecializationInfo;} +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Shader/ShaderModule.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Shader/ShaderModule.java index cb0abe9..9624fda 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Shader/ShaderModule.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Shader/ShaderModule.java @@ -6,6 +6,8 @@ import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.VkShaderModuleCreateInfo; import static org.lwjgl.vulkan.VK13.vkCreateShaderModule; import static org.lwjgl.vulkan.VK13.vkDestroyShaderModule; + +import org.lwjgl.vulkan.VkSpecializationInfo; import org.tinylog.Logger; import java.io.File; @@ -18,12 +20,14 @@ import java.nio.file.Files; public class ShaderModule { private final long Handle; private final int ShaderStage; + private final VkSpecializationInfo SpecializationInfo; - public ShaderModule(VulkanContext VkCtx, int ShaderStage, String ShaderSPVFile){ + public ShaderModule(VulkanContext VkCtx, int ShaderStage, String ShaderSPVFile,VkSpecializationInfo SpecializationInfo){ try{ byte[] Contents = Files.readAllBytes(new File(ShaderSPVFile).toPath()); Handle = CreateShaderModule(VkCtx, Contents); this.ShaderStage = ShaderStage; + this.SpecializationInfo = SpecializationInfo; } catch(IOException exception){ Logger.error("Cannot Read Shader Files",exception); throw new RuntimeException(exception); @@ -42,6 +46,8 @@ public class ShaderModule { } } + public VkSpecializationInfo GetSpecializationInfo(){return SpecializationInfo;} + public void CleanUp(VulkanContext VkCtx){ vkDestroyShaderModule(VkCtx.GetDevice().FetchVulkanDevice(), Handle, null); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/CompatibleVoxelMesh.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/CompatibleVoxelMesh.java new file mode 100644 index 0000000..08e003f --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/CompatibleVoxelMesh.java @@ -0,0 +1,225 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel; + +import net.halbear.Terrain4J.EngineCore.Display.Render; +import net.halbear.Terrain4J.EngineCore.Logic.InitVoxelData; + +import org.joml.Vector4f; +import org.lwjgl.system.MemoryUtil; +import org.tinylog.Logger; + +import java.nio.FloatBuffer; +import java.nio.IntBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + + +public class CompatibleVoxelMesh { + private static final int VERTEX_STRIDE = 6; + public static List voxelModels = new ArrayList<>(); + public static List TexturePaths = new ArrayList<>(); + private Render renderInstance; + private float[] VertexArray; + private int[] IndicesArray; + private final String ID; + private boolean[] Faces = new boolean[]{false,false,false,false,false,false}; + private int[] Textureindex = new int[6]; + private Vector4f[] DiffuseColours = new Vector4f[]{new Vector4f(0.6f, 0.6f, 0.6f, 1.0f),new Vector4f(0.5f, 0.5f, 0.5f, 1.0f),new Vector4f(0.4f, 0.4f, 0.4f, 1.0f),new Vector4f(0.5f, 0.5f, 0.5f, 1.0f),new Vector4f(0.7f, 0.7f, 0.7f, 1.0f),new Vector4f(0.3f, 0.3f, 0.3f, 1.0f)}; + + static{ + TexturePaths.add("resources/EngineResources/Texture/DefaultTexture.png"); + } + + public enum FaceDirection{ + North(0), + South(2), + East(1), + West(3), + Up(4), + Down(5); + + private final int value; + + FaceDirection(int value) { + this.value = value; + } + + // 3. Add a getter method to access the number + public int getValue() { + return value; + } + } + + public record VoxelModelInitData(VoxelModelData voxelModel, List materialData){} + public record VoxelModelData(String ID, List meshes, FloatBuffer vertexBuffer, IntBuffer indexBuffer){} + public record VoxelMeshData(String ID, FloatBuffer vertexBuffer, IntBuffer indexBuffer, int VertexCount, int IndexCount){} + + public CompatibleVoxelMesh(String VoxelID){ + VertexArray = new float[6 * 20]; + IndicesArray = new int[6 * 6]; + ID = VoxelID; + } + public CompatibleVoxelMesh(Render rendererInstance, String VoxelID){ + renderInstance = rendererInstance; + VertexArray = new float[6 * 20]; + IndicesArray = new int[6 * 6]; + ID = VoxelID; + } + public CompatibleVoxelMesh SetSideTexture(int SideNumber, String TextureID){ + int index = TexturePaths.indexOf(TextureID); + if(index < 0){ + TexturePaths.add(TextureID); + index = TexturePaths.indexOf(TextureID); + } + Textureindex[SideNumber] = index; + return this; + } + + public CompatibleVoxelMesh CreateMeshFace(FaceDirection faceDirection, String TextureID){ + int side = faceDirection.getValue(); + Faces[side] = true; + + int index = TexturePaths.indexOf(TextureID); + if (index < 0) { + TexturePaths.add(TextureID); + index = TexturePaths.indexOf(TextureID); + } + Textureindex[side] = index; + + float[] srcFace = switch (faceDirection) { + case North -> FrontFace; + case South -> BackFace; + case East -> RightFace; + case West -> LeftFace; + case Up -> TopFace; + case Down -> BottomFace; + }; + + System.arraycopy(srcFace, 0, VertexArray, side * 20, 20); + return this; + } + + public static InitVoxelData GetVoxelModelsGenerated(){ + List models = new ArrayList<>(); + List materials = new ArrayList<>(); + for(int i = 0; i < voxelModels.size(); i++){ + models.add(voxelModels.get(i).voxelModel()); + materials.addAll(voxelModels.get(i).materialData()); + } + return new InitVoxelData(models,materials); + } + + public CompatibleVoxelMesh CompileMesh(){ + CompileMeshNoReturn(); + return this; + } + + public void CompileMeshNoReturn() { + List meshes = new ArrayList<>(); + List materials = new ArrayList<>(); + List AddedMaterials = new ArrayList<>(); + int faceCount = 0; + for (int i = 0; i < 6; i++) { + if (Faces[i]) { + faceCount++; + } + } + VoxelMeshData data = new VoxelMeshData(ID, MemoryUtil.memAllocFloat(20*faceCount), MemoryUtil.memAllocInt(6*faceCount), 4, 6); + float[] vertexArray = new float[faceCount * 20]; + faceCount = 0; + for(int i = 0; i < 6; i++){ + if(Faces[i]){ + String TextureID = "N/A_NULL"; + if(Textureindex[i] >= 0 && Textureindex[i] < TexturePaths.size()) TextureID = TexturePaths.get(Textureindex[i]); + else TextureID = "resources/EngineResources/Texture/DefaultTexture.png"; + if(!AddedMaterials.contains(TextureID)) { + materials.add(new MaterialData(TextureID, TextureID,DiffuseColours[i])); + AddedMaterials.add(TextureID); + } + for(int j = 0; j < 20; j++){ + vertexArray[(faceCount * 20) + j] = VertexArray[(i * 20) + j]; + } + if(!Objects.equals(TextureID, "N/A_NULL")){ + meshes.add(new MeshData(ID + "_" + i, TextureID,faceCount * 20, 20, faceCount * 6, 6)); + } + int offset = faceCount * 4; + data.indexBuffer.put(offset); + data.indexBuffer.put(offset + 1); + data.indexBuffer.put(offset + 2); + data.indexBuffer.put(offset + 2); + data.indexBuffer.put(offset + 3); + data.indexBuffer.put(offset); + faceCount++; + } + } + Logger.debug("Voxel with [{}] sides generated",faceCount); + data.indexBuffer.flip(); + data.vertexBuffer.put(vertexArray).flip(); + VoxelModelData model = new VoxelModelData(ID,meshes, data.vertexBuffer, data.indexBuffer); + voxelModels.add(new VoxelModelInitData(model, materials)); + } + + public float[] FetchFaceWithTexture(float TextureIndex, FaceDirection direction){ + float[] meshData = new float[20]; + this.Textureindex[direction.getValue()] = (int) TextureIndex; + switch (direction){ + case North -> { + System.arraycopy(FrontFace, 0, meshData, 0, 20); + } + case South -> { + System.arraycopy(BackFace, 0, meshData, 0, 20); + } + case East -> { + System.arraycopy(RightFace, 0, meshData, 0, 20); + } + case West -> { + System.arraycopy(LeftFace, 0, meshData, 0, 20); + } + case Up -> { + System.arraycopy(TopFace, 0, meshData, 0, 20); + } + case Down -> { + System.arraycopy(BottomFace, 0, meshData, 0, 20); + } + } + return meshData; + } + + public static final float[] FrontFace = new float[]{ + -0.5f, -0.5f, 0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f + }; + public static final float[] BackFace = new float[]{ + 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, -0.5f, 1.0f, 1.0f, + -0.5f, 0.5f, -0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f + }; + public static final float[] TopFace = new float[]{ + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f + }; + public static final float[] BottomFace = new float[]{ + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f + }; + public static final float[] LeftFace = new float[]{ + -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 1.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f + }; + public static final float[] RightFace = new float[]{ + 0.5f, -0.5f, 0.5f, 0.0f, 1.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f + }; + +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/MaterialsCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/MaterialsCache.java index 78b0806..2e1eb55 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/MaterialsCache.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/MaterialsCache.java @@ -56,15 +56,19 @@ public class MaterialsCache { if(ValidTexture){ Logger.debug("Loading Texture [{}]",TexturePath); Texture newTexture = textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB); - TransparentTexture = newTexture.HasTransparency(); + if(newTexture == null) { + TransparentTexture = false; + TexturePath = "resources/EngineResources/Texture/DefaultTexture.png"; + } + else TransparentTexture = newTexture.HasTransparency(); } else{ + TexturePath = "resources/EngineResources/Texture/DefaultTexture.png"; TransparentTexture = Material.DiffuseColour().w < 1.0f; } VulkanMaterial newMaterial = new VulkanMaterial(Material.ID(),TransparentTexture); MaterialsMap.put(newMaterial.ID(), newMaterial); Logger.trace(Material.toString()); - data.position(Offset); - Material.DiffuseColour().get(data); + Material.DiffuseColour().get(Offset,data); Logger.debug("Set Diffuse Colour -> [{}]",Material.DiffuseColour()); data.putInt(Offset + VulkanUtils.VEC4_SIZE, ValidTexture ? 1 : 0); data.putInt(Offset + VulkanUtils.VEC4_SIZE + VulkanUtils.INT_SIZE, textureCache.GetPosition(TexturePath)); @@ -76,6 +80,7 @@ public class MaterialsCache { } data.position(0); + SrcBuffer.Flush(VkCtx); SrcBuffer.UnMapMemory(VkCtx); transferBuffer.RecordTransferCommand(CmdBuffer); CmdBuffer.EndRecording(); @@ -91,6 +96,7 @@ public class MaterialsCache { } } + public IndexedLinkedHashMap GetMaterialCache(){return MaterialsMap;} public VulkanMaterial GetMaterial(String ID){return MaterialsMap.get(ID);} public VulkanBuffer GetMaterialsBuffer(){return MaterialsBuffer;} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/ModelsCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/ModelsCache.java index 3f83e32..37705d6 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/ModelsCache.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/VkModel/ModelsCache.java @@ -10,10 +10,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import org.lwjgl.system.MemoryUtil; import org.tinylog.Logger; -import java.io.BufferedInputStream; -import java.io.DataInputStream; -import java.io.FileInputStream; -import java.io.IOException; +import java.io.*; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.util.ArrayList; @@ -31,6 +28,39 @@ public class ModelsCache { ModelsMap = new HashMap<>(); } + public void loadVoxelModels(VulkanContext VkCtx, List Models, CommandPool commandPool, Queue queue){ + try { + List StagingBufferList = new ArrayList<>(); + var Command = new CommandBuffer(VkCtx, commandPool, true, true); + Command.BeginRecording(); + + for (CompatibleVoxelMesh.VoxelModelData modelData : Models) { + VulkanModel VKModel = new VulkanModel(modelData.ID()); + ModelsMap.put(VKModel.GetID(), VKModel); + + for (MeshData meshData : modelData.meshes()) { + TransferBuffer VerticesBuffers = CreateVoxelVerticesBuffer(VkCtx, meshData,modelData.vertexBuffer()); + TransferBuffer IndicesBuffers = CreateVoxelIndicesBuffer(VkCtx, meshData,modelData.indexBuffer()); + StagingBufferList.add(VerticesBuffers.SrcBuffer()); + StagingBufferList.add(IndicesBuffers.SrcBuffer()); + VerticesBuffers.RecordTransferCommand(Command); + IndicesBuffers.RecordTransferCommand(Command); + Logger.debug("Creating new Vulkan Mesh -> ID=[{}] MaterialID=[{}]",meshData.ID(),meshData.MaterialID()); + VulkanMesh VkMesh = new VulkanMesh(meshData.ID(), VerticesBuffers.DstBuffer(), IndicesBuffers.DstBuffer(), + meshData.IndexSize(), meshData.MaterialID()); + VKModel.GetVkMeshList().add(VkMesh); + } + } + Command.EndRecording(); + Command.SubmitAndWait(VkCtx,queue); + Command.cleanup(VkCtx,commandPool); + + StagingBufferList.forEach(b -> b.cleanup(VkCtx)); + } catch (Exception exception){ + throw new RuntimeException(exception); + } + } + public void loadModels(VulkanContext VkCtx, List Models, CommandPool commandPool, Queue queue){ try { List StagingBufferList = new ArrayList<>(); @@ -69,6 +99,43 @@ public class ModelsCache { } } + private static TransferBuffer CreateVoxelIndicesBuffer(VulkanContext VkCtx, MeshData meshData, IntBuffer IndexBuffer) throws IOException{ + int BufferSize = meshData.IndexSize(); + var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + var DstBuffer = new VulkanBuffer(VkCtx, BufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0); + long MappedMemory = SrcBuffer.MapMemory(VkCtx); + IntBuffer data = MemoryUtil.memIntBuffer(MappedMemory,(int) SrcBuffer.GetRequestedSize()); + IndexBuffer.rewind(); + for(int i = 0; i < meshData.IndexSize(); i++){ + data.put(IndexBuffer.get(meshData.OffsetIndex() + i)); + } + SrcBuffer.UnMapMemory(VkCtx); + return new TransferBuffer(SrcBuffer,DstBuffer); + } + private static TransferBuffer CreateVoxelVerticesBuffer(VulkanContext VkCtx, MeshData meshData, FloatBuffer VertexBuffer) throws IOException { + Logger.debug("Creating Vertices Transfer Buffer, Mesh Data -> ID=[{}] VertexSize=[{}]",meshData.ID(),meshData.VertexSize()); + int BufferSize = meshData.VertexSize(); + var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); + var DstBuffer = new VulkanBuffer(VkCtx, BufferSize, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0); + if (BufferSize <= 0) { + Logger.error("Computed buffer allocation size cannot be 0. SrcBuffer -> [{}] DstBuffer -> [{}]",SrcBuffer,DstBuffer); + throw new RuntimeException("Computed buffer allocation size cannot be 0. SrcBuffer -> ["+SrcBuffer+"] DstBuffer -> ["+DstBuffer+"]"); + } + Logger.debug("Starting to create vertex Transfer Buffer"); + long MappedMemory = SrcBuffer.MapMemory(VkCtx); + FloatBuffer data = MemoryUtil.memFloatBuffer(MappedMemory, (int) SrcBuffer.GetRequestedSize()); + VertexBuffer.rewind(); + for(int i = 0; i < meshData.VertexSize(); i++){ + data.put(VertexBuffer.get(meshData.OffsetVertex() + i)); + } + SrcBuffer.UnMapMemory(VkCtx); + return new TransferBuffer(SrcBuffer,DstBuffer); + } + private static TransferBuffer CreateVerticesBuffer(VulkanContext VkCtx, MeshData meshData, DataInputStream VertexStream) throws IOException { Logger.debug("Creating Vertices Transfer Buffer, Mesh Data -> ID=[{}] VertexSize=[{}]",meshData.ID(),meshData.VertexSize()); int BufferSize = meshData.VertexSize(); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java index 8adace2..1b7a853 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java @@ -3,11 +3,12 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen; import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; -import net.halbear.Terrain4J.EngineCore.Main.GameCore; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor; import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Image; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Texture; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline; @@ -18,6 +19,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VertexBufferStructure; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.*; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChain; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import org.joml.Matrix4f; @@ -32,11 +34,10 @@ import java.nio.LongBuffer; import java.util.Arrays; import java.util.List; -import static org.lwjgl.vulkan.KHRSwapchain.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; import static org.lwjgl.vulkan.KHRSynchronization2.VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR; import static org.lwjgl.vulkan.VK13.*; -public class SceneRender {//dynamic rendering +public class SceneRender implements SceneRenderer {//dynamic rendering private static final String DESCRIPTOR_ID_MAT = "SCN_DESC_ID_MAT"; private static final String DESCRIPTOR_ID_PRJ = "SCN_DESC_ID_PRJ"; @@ -49,26 +50,28 @@ public class SceneRender {//dynamic rendering private final DescriptorSetLayout descriptorLayoutVertexUniform; private final TextureSampler textureSampler; + private static final int COLOUR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; private static final int DEPTH_FORMAT = VK_FORMAT_D16_UNORM; private final VkClearValue ClearValueDepth; private final ByteBuffer PushConstBuffer; - private Attachment[] AttDepth; - private VkRenderingAttachmentInfo[] AttInfoDepth; + private Attachment AttachmentDepth; + private Attachment AttachmentColour; + private VkRenderingAttachmentInfo AttachmentInfoDepth; private VkClearValue ClearValueColour; - private VkRenderingAttachmentInfo.Buffer[] AttachmentInfoColour; - private VkRenderingInfo[] RenderInfo; - private float R = 0f; - private float G = 0.5f; - private float B = 0.7f; + private VkRenderingAttachmentInfo.Buffer AttachmentInfoColour; + private VkRenderingInfo RenderInfo; + private float R = 0.5f; + private float G = 0.75f; + private float B = 1.0f; private boolean Rb = false; private boolean Gb = true; private boolean Bb = false; public int Frames = 0; private static String LastGPULog = ""; - private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/shaders/scene_fragment.glsl"; + private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_fragment.glsl"; private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv"; - private static final String VERTEX_SHADER_FILE_GLSL = "resources/shaders/scene_vertex.glsl"; + private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_vertex.glsl"; private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; private final VulkanBuffer[] BufferViewMatrices; private final Pipeline VkPipeline; @@ -76,14 +79,14 @@ public class SceneRender {//dynamic rendering public SceneRender(VulkanContext vulkanContext){ ClearValueColour = VkClearValue.calloc().color( - c -> c.float32(0, 0.0f).float32(1, 0.0f).float32(2, 0.0f).float32(3, 0.0f)); - //ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 1.0f)); - ClearValueDepth = VkClearValue.calloc().depthStencil(c -> c.depth(1.0f).stencil()); - AttDepth = createDepthAttachments(vulkanContext); - AttInfoDepth = createDepthAttachmentsInfo(vulkanContext, AttDepth, ClearValueDepth); - ClearValueColour = VkClearValue.calloc().color(c->c.float32(0,R).float32(1,G).float32(2,B).float32(3,1.0f)); - AttachmentInfoColour = CreateColourAttachmentsInfo(vulkanContext,ClearValueColour); - RenderInfo = CreateRenderInfo(vulkanContext, AttachmentInfoColour, AttInfoDepth); + c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 1.0f)); + ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 0.0f)); + AttachmentColour = CreateColourAttachment(vulkanContext); + AttachmentDepth = CreateDepthAttachment(vulkanContext); + AttachmentInfoDepth = CreateDepthAttachmentInfo(AttachmentDepth, ClearValueDepth); + AttachmentInfoColour = CreateColourAttachmentInfo(AttachmentColour,ClearValueColour); + RenderInfo = CreateRenderInfo(AttachmentColour, AttachmentInfoColour, AttachmentInfoDepth); + ShaderModule[] shaderModules = SceneRender.CreateShaderModules(vulkanContext); PushConstBuffer = (MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE)); @@ -114,6 +117,40 @@ public class SceneRender {//dynamic rendering Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext)); } + private static Attachment CreateColourAttachment(VulkanContext VkCtx){ + SwapChain swapChain = VkCtx.GetSwapChain(); + VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent(); + return new Attachment(VkCtx, SwapChainExtent.width(), SwapChainExtent.height(), COLOUR_FORMAT,VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + } + + private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment attachment, VkClearValue ClearValue){ + return VkRenderingAttachmentInfo.calloc(1) + .sType$Default() + .imageView(attachment.GetVkImageView().GetVulkanImageView()) + .imageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) + .storeOp(VK_ATTACHMENT_STORE_OP_STORE) + .clearValue(ClearValue); + } + + private static Attachment CreateDepthAttachment(VulkanContext VkCtx){ + SwapChain swapChain = VkCtx.GetSwapChain(); + VkExtent2D swapChainExtent = swapChain.GetSwapChainExtent(); + return new Attachment(VkCtx, swapChainExtent.width(), swapChainExtent.height(), + DEPTH_FORMAT,VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + } + + + private static VkRenderingAttachmentInfo CreateDepthAttachmentInfo(Attachment DepthAttachment, VkClearValue clearValue){ + return VkRenderingAttachmentInfo.calloc() + .sType$Default() + .imageView(DepthAttachment.GetVkImageView().GetVulkanImageView()) + .imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) + .storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE) + .clearValue(clearValue); + } + private static Attachment[] createDepthAttachments(VulkanContext VkCtx){ SwapChain swapChain = VkCtx.GetSwapChain(); int ImageCount = swapChain.GetImageCount(); @@ -149,15 +186,14 @@ public class SceneRender {//dynamic rendering ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); } return new ShaderModule[]{ - new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV), - new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV) + new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV,null), + new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV,null) }; } private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts){ var vertexBufferStructure = new VertexBufferStructure(); - var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(), - VkCtx.GetSurface().GetSurfaceFormat().ImageFormat()) + var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),COLOUR_FORMAT) .SetDepthFormat(DEPTH_FORMAT) .SetPushConstantRanges( new PushConstantsRange[]{ @@ -166,62 +202,33 @@ public class SceneRender {//dynamic rendering }) .SetDescriptorSetLayouts(DescriptorSetLayouts) .BlendingIsUsed(true); - var pipeline = new Pipeline(VkCtx, BuildInfo); + var pipeline = new DefaultPipeline(VkCtx, BuildInfo); vertexBufferStructure.cleanup(); return pipeline; } - public void UpdateColours(VulkanContext vulkanContext){ - if (Gb){ - if (G < 1.0f && Math.random() <0.5) G+=0.0005f; - else if (G >= 1.0f) Gb = false; - } else{ - if (G >0.0f&& Math.random() <0.5) G-=0.0005f; - else if (G <= 0.0f) Gb = true; - } - if (Rb){ - if (R < 1.0f&& Math.random() <0.3) R+=0.0005f; - else if (R >= 1.0f) Rb = false; - } else{ - if (R >0.0f&& Math.random() <0.3) R-=0.0005f; - else if (R <= 0.0f) Rb = true; - } - if (Bb){ - if (B < 1.0f&& Math.random() <0.7) B+=0.0005f; - else if (B >= 1.0f) Bb = false; - } else{ - if (B >0.0f&& Math.random() <0.7) B-=0.0005f; - else if (B <= 0.0f) Bb = true; - } - //ClearValueColour = VkClearValue.calloc().color(c->c.float32(0,R).float32(1,G).float32(2,B).float32(3,1.0f)); - //AttachmentInfoColour = CreateColourAttachmentsInfo(vulkanContext,ClearValueColour); - //RenderInfo = CreateRenderInfo(vulkanContext, AttachmentInfoColour, AttInfoDepth); - } - public void Render(EngineInstance engineInstance,VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache,MaterialsCache materialsCache, int ImageIndex, int CurrentFrame){ - UpdateColours(vulkanContext); + public void Render(EngineInstance engineInstance,VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache,MaterialsCache materialsCache, int CurrentFrame){ try(var MemStack = MemoryStack.stackPush()){ - SwapChain swapChain = vulkanContext.GetSwapChain(); - long SwapChainImage = swapChain.GetVulkanImageView(ImageIndex).GetVulkanImage(); VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer(); - VulkanUtils.ImageBarrier(MemStack, CommandHandle, SwapChainImage, + VulkanUtils.ImageBarrier(MemStack, CommandHandle, AttachmentColour.GetVkImage().getVulkanImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT); - VulkanUtils.ImageBarrier(MemStack, CommandHandle, AttDepth[ImageIndex].GetVkImage().getVulkanImage(), + VulkanUtils.ImageBarrier(MemStack, CommandHandle, AttachmentDepth.GetVkImage().getVulkanImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_DEPTH_BIT); - vkCmdBeginRendering(CommandHandle, RenderInfo[ImageIndex]); + vkCmdBeginRendering(CommandHandle, RenderInfo); vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipeline()); - VkExtent2D swapChainExtent = swapChain.GetSwapChainExtent(); - int width = swapChainExtent.width(); - int height = swapChainExtent.height(); + Image ColourImage = AttachmentColour.GetVkImage(); + int width = ColourImage.GetWidth(); + int height = ColourImage.GetHeight(); var Viewport = VkViewport.calloc(1,MemStack) .x(0) .y(height) @@ -239,7 +246,7 @@ public class SceneRender {//dynamic rendering DescriptorAllocator descriptorAllocator = vulkanContext.GetDescriptorAllocator(); LongBuffer DescriptorSets = MemStack.mallocLong(4) .put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ).GetVkDescriptorSet()) - .put(1,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_VIEW).GetVkDescriptorSet()) + .put(1,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_VIEW, CurrentFrame).GetVkDescriptorSet()) .put(2,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet()) .put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet()); vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null); @@ -248,12 +255,6 @@ public class SceneRender {//dynamic rendering RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, true); vkCmdEndRendering(CommandHandle); - - VulkanUtils.ImageBarrier(MemStack, CommandHandle, SwapChainImage, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, - VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_2_NONE, - VK_IMAGE_ASPECT_COLOR_BIT); } } @@ -294,19 +295,23 @@ public class SceneRender {//dynamic rendering private void SetPushConstants(VkCommandBuffer CmdHandle, Matrix4f ModelMatrix, int MaterialIndex){ ModelMatrix.get(0,PushConstBuffer); PushConstBuffer.putInt(VulkanUtils.MATRIX4X4_SIZE, MaterialIndex); - vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, PushConstBuffer.slice(0,VulkanUtils.MATRIX4X4_SIZE)); - vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, VulkanUtils.MATRIX4X4_SIZE, PushConstBuffer.slice(VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.INT_SIZE)); + vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, + PushConstBuffer.slice(0,VulkanUtils.MATRIX4X4_SIZE)); + vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, VulkanUtils.MATRIX4X4_SIZE, + PushConstBuffer.slice(VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.INT_SIZE)); } public void Resize(EngineInstance instance, VulkanContext VkCtx){ - Arrays.asList(RenderInfo).forEach(VkRenderingInfo::free); - Arrays.asList(AttInfoDepth).forEach(VkRenderingAttachmentInfo::free); - Arrays.asList(AttachmentInfoColour).forEach(VkRenderingAttachmentInfo.Buffer::free); - Arrays.asList(AttDepth).forEach(Attachment->Attachment.CleanUp(VkCtx)); - AttDepth = createDepthAttachments(VkCtx); - AttachmentInfoColour = CreateColourAttachmentsInfo(VkCtx, ClearValueColour); - AttInfoDepth = createDepthAttachmentsInfo(VkCtx, AttDepth, ClearValueDepth); - RenderInfo = CreateRenderInfo(VkCtx, AttachmentInfoColour, AttInfoDepth); + RenderInfo.free(); + AttachmentInfoColour.free(); + AttachmentColour.CleanUp(VkCtx); + AttachmentDepth.CleanUp(VkCtx); + AttachmentInfoDepth.free(); + AttachmentColour = CreateColourAttachment(VkCtx); + AttachmentDepth = CreateDepthAttachment(VkCtx); + AttachmentInfoColour = CreateColourAttachmentInfo(AttachmentColour, ClearValueColour); + AttachmentInfoDepth = CreateDepthAttachmentInfo(AttachmentDepth, ClearValueDepth); + RenderInfo = CreateRenderInfo(AttachmentColour, AttachmentInfoColour, AttachmentInfoDepth); VulkanUtils.CopyMatrixToBuffer(VkCtx, BufferProjectionMatrix, instance.scene().GetProjection().GetProjectionMatrix(),0); } @@ -322,24 +327,19 @@ public class SceneRender {//dynamic rendering descriptorSet.SetImageArray(device,imageViews,textureSampler,0); } - private static VkRenderingInfo[] CreateRenderInfo(VulkanContext vulkanContext, VkRenderingAttachmentInfo.Buffer[] ColourAttachments, VkRenderingAttachmentInfo[] DepthAttachments){ - SwapChain swapChain = vulkanContext.GetSwapChain(); - int ImageCount = swapChain.GetImageCount(); - var Result = new VkRenderingInfo[ImageCount]; - + private static VkRenderingInfo CreateRenderInfo(Attachment ColourAttachment, VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo, VkRenderingAttachmentInfo DepthAttachmentInfo){ + VkRenderingInfo Result; try(var MemStack = MemoryStack.stackPush()){ - VkExtent2D Extent = swapChain.GetSwapChainExtent(); + VkExtent2D Extent = VkExtent2D.calloc(MemStack); + Extent.width(ColourAttachment.GetVkImage().GetWidth()); + Extent.height(ColourAttachment.GetVkImage().GetHeight()); var RenderArea = VkRect2D.calloc(MemStack).extent(Extent); - - for(int i = 0; i < ImageCount; i++){ - var RenderInfo = VkRenderingInfo.calloc() - .sType$Default() - .renderArea(RenderArea) - .layerCount(1) - .pColorAttachments(ColourAttachments[i]) - .pDepthAttachment(DepthAttachments[i]); - Result[i] = RenderInfo; - } + Result = VkRenderingInfo.calloc() + .sType$Default() + .renderArea(RenderArea) + .layerCount(1) + .pColorAttachments(ColourAttachmentInfo) + .pDepthAttachment(DepthAttachmentInfo); } return Result; } @@ -361,12 +361,12 @@ public class SceneRender {//dynamic rendering } public void cleanup(VulkanContext VkCtx){ VkPipeline.CleanUp(VkCtx); - Arrays.asList(RenderInfo).forEach(VkRenderingInfo::free); Arrays.asList(BufferViewMatrices).forEach(buffer -> buffer.cleanup(VkCtx)); - Arrays.asList(AttachmentInfoColour).forEach(VkRenderingAttachmentInfo.Buffer::free); - Arrays.asList(AttInfoDepth).forEach(VkRenderingAttachmentInfo::free); - Arrays.asList(AttachmentInfoColour).forEach(VkRenderingAttachmentInfo.Buffer::free); - Arrays.asList(AttDepth).forEach(Attachment->Attachment.CleanUp(VkCtx)); + RenderInfo.free(); + AttachmentInfoColour.free(); + AttachmentColour.CleanUp(VkCtx); + AttachmentDepth.CleanUp(VkCtx); + AttachmentInfoDepth.free(); MemoryUtil.memFree(PushConstBuffer); ClearValueDepth.free(); ClearValueColour.free(); @@ -376,4 +376,9 @@ public class SceneRender {//dynamic rendering descriptorLayoutVertexUniform.CleanUp(VkCtx); textureSampler.CleanUp(VkCtx); } + + @Override + public Attachment GetAttachmentColour() { + return AttachmentColour; + } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRenderer.java new file mode 100644 index 0000000..56f93ff --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRenderer.java @@ -0,0 +1,24 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen; + +import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSetLayout; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.ShaderModule; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialsCache; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelsCache; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; +import org.lwjgl.vulkan.VkClearValue; +import org.lwjgl.vulkan.VkCommandBuffer; +import org.lwjgl.vulkan.VkRenderingAttachmentInfo; + +public interface SceneRenderer { + + public void Render(EngineInstance engineInstance, VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache, MaterialsCache materialsCache, int CurrentFrame); + public void Resize(EngineInstance instance, VulkanContext VkCtx); + public void LoadMaterials(VulkanContext VkCtx, MaterialsCache materialsCache, TextureCache textureCache); + public void cleanup(VulkanContext VkCtx); + public Attachment GetAttachmentColour(); +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/Surface.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/Surface.java index 9905847..52ea5a1 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/Surface.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/Surface.java @@ -15,6 +15,7 @@ import java.nio.IntBuffer; import java.nio.LongBuffer; import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck; +import static org.lwjgl.vulkan.VK10.VK_FORMAT_B8G8R8A8_UNORM; import static org.lwjgl.vulkan.VK13.VK_FORMAT_B8G8R8A8_SRGB; public class Surface { @@ -52,11 +53,11 @@ public class Surface { var SurfaceFormats = VkSurfaceFormatKHR.calloc(SurfaceFormatCount, MemStack); vkCheck(KHRSurface.vkGetPhysicalDeviceSurfaceFormatsKHR(PhysDevice.GetPhysicalDevice(),VulkanSurface, IntPointer, SurfaceFormats), "Failed to get surface formats"); - ImageFormat = VK_FORMAT_B8G8R8A8_SRGB; + ImageFormat = VK_FORMAT_B8G8R8A8_UNORM; ColourSpace = SurfaceFormats.get(0).colorSpace(); for(int i = 0; i < SurfaceFormatCount; i++){ VkSurfaceFormatKHR SurfaceFormatKHR = SurfaceFormats.get(i); - if (SurfaceFormatKHR.format() == VK_FORMAT_B8G8R8A8_SRGB && SurfaceFormatKHR.colorSpace() == KHRSurface.VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){ + if (SurfaceFormatKHR.format() == VK_FORMAT_B8G8R8A8_UNORM && SurfaceFormatKHR.colorSpace() == KHRSurface.VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){ ImageFormat = SurfaceFormatKHR.format(); ColourSpace = SurfaceFormatKHR.colorSpace(); break; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SwapChain.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/SwapChain/SwapChain.java similarity index 97% rename from src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SwapChain.java rename to src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/SwapChain/SwapChain.java index c72fe6b..5c46f38 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SwapChain.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/SwapChain/SwapChain.java @@ -1,10 +1,12 @@ -package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen; +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain; import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.Semaphore; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.Surface; import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; import org.lwjgl.vulkan.*; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/SwapChain/SwapChainRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/SwapChain/SwapChainRender.java new file mode 100644 index 0000000..bfd7559 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/SwapChain/SwapChainRender.java @@ -0,0 +1,192 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain; + +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.EmptyVertexBufferStruct; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.PipelineBuildInfo; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.*; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.util.shaderc.Shaderc; +import org.lwjgl.vulkan.*; + +import java.nio.LongBuffer; +import java.util.Arrays; + +import static org.lwjgl.vulkan.KHRSwapchain.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; +import static org.lwjgl.vulkan.KHRSynchronization2.VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR; +import static org.lwjgl.vulkan.VK10.*; +import static org.lwjgl.vulkan.VK13.*; + +public class SwapChainRender { + + private static final String DESCRIPTOR_ID_ATTACHMENT = "FWD_DESC_ID_ATT"; + private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/swap_frag.glsl"; + private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv"; + private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/swap_vtx.glsl"; + private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; + private final DescriptorSetLayout AttachmentDescriptorSetLayout; + private final VkClearValue ClearValueColour; + private final Pipeline pipeline; + private final TextureSampler textureSampler; + private VkRenderingAttachmentInfo.Buffer[] ColourAttachmentsInfo; + private VkRenderingInfo[] RenderInfo; + + public SwapChainRender(VulkanContext VkCtx, Attachment SrcAttachment){ + ClearValueColour = VkClearValue.calloc(); + ClearValueColour.color(c->c.float32(0,0.0f).float32(1,0.0f).float32(2,0.0f).float32(3,0.0f)); + + ColourAttachmentsInfo = CreateColourAttachmentsInfo(VkCtx,ClearValueColour); + RenderInfo = CreateRenderInfo(VkCtx,ColourAttachmentsInfo); + + var TextureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT,VK_BORDER_COLOR_INT_OPAQUE_BLACK,1,true); + textureSampler = new TextureSampler(VkCtx,TextureSamplerInfo); + + var LayoutInfo = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,0,1,VK_SHADER_STAGE_FRAGMENT_BIT); + AttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx,LayoutInfo); + CreateAttachmentDescriptorSet(VkCtx,AttachmentDescriptorSetLayout,SrcAttachment,textureSampler); + + ShaderModule[] shaderModules = CreateShaderModules(VkCtx); + + pipeline = CreatePipeline(VkCtx,shaderModules,new DescriptorSetLayout[]{AttachmentDescriptorSetLayout}); + Arrays.asList(shaderModules).forEach(s->s.CleanUp(VkCtx)); + } + + private static void CreateAttachmentDescriptorSet(VulkanContext VkCtx, DescriptorSetLayout descriptorSetLayout, Attachment attachment, TextureSampler sampler){ + DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); + Device device = VkCtx.GetDevice(); + DescriptorSet descriptorSet = descriptorAllocator.AddDescriptorSets(device,DESCRIPTOR_ID_ATTACHMENT,1,descriptorSetLayout)[0]; + descriptorSet.SetImage(device,attachment.GetVkImageView(),sampler,0); + } + + private static VkRenderingAttachmentInfo.Buffer[] CreateColourAttachmentsInfo(VulkanContext VkCtx, VkClearValue ClearView){ + SwapChain swapChain = VkCtx.GetSwapChain(); + int ImageCount = swapChain.GetImageCount(); + var Result = new VkRenderingAttachmentInfo.Buffer[ImageCount]; + + for(int i = 0; i < ImageCount; i++){ + var Attachments = VkRenderingAttachmentInfo.calloc(1); + Attachments.get(0) + .sType$Default() + .imageView(swapChain.GetVulkanImageView(i).GetVulkanImageView()) + .imageLayout(VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR) + .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) + .storeOp(VK_ATTACHMENT_STORE_OP_STORE) + .clearValue(ClearView); + Result[i] = Attachments; + } + return Result; + } + private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descriptorSetLayouts){ + var VertexBufferStruct = new EmptyVertexBufferStruct(); + var BuildInfo = new PipelineBuildInfo(shaderModules, VertexBufferStruct.GetVertexInput(),VkCtx.GetSurface().GetSurfaceFormat().ImageFormat()).SetDescriptorSetLayouts(descriptorSetLayouts).BlendingIsUsed(true); + var pipeline = new DefaultPipeline(VkCtx,BuildInfo); + VertexBufferStruct.CleanUp(); + return pipeline; + } + + private static VkRenderingInfo[] CreateRenderInfo(VulkanContext VkCtx, VkRenderingAttachmentInfo.Buffer[] ColourAttachments){ + SwapChain swapChain = VkCtx.GetSwapChain(); + int ImageCount = swapChain.GetImageCount(); + var Result = new VkRenderingInfo[ImageCount]; + + try(var MemStack = MemoryStack.stackPush()){ + VkExtent2D extent2D = swapChain.GetSwapChainExtent(); + var RenderArea = VkRect2D.calloc(MemStack).extent(extent2D); + + for(int i = 0; i < ImageCount; i++){ + var renderingInfo = VkRenderingInfo.calloc() + .sType$Default() + .renderArea(RenderArea) + .layerCount(1) + .pColorAttachments(ColourAttachments[i]); + Result[i] = renderingInfo; + } + } + return Result; + } + + private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx){ + if(EngineConfig.getInstance().RecompileShaders()){ + ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); + ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); + } + return new ShaderModule[]{ + new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV, null), + new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV, null) + }; + } + + public void Render(VulkanContext VkCtx, CommandBuffer commandBuffer, Attachment SrcAttachment, int ImageIndex){ + try(var MemStack = MemoryStack.stackPush()){ + SwapChain swapChain = VkCtx.GetSwapChain(); + + long SwapChainImage = swapChain.GetVulkanImageView(ImageIndex).GetVulkanImage(); + VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer(); + + VulkanUtils.ImageBarrier(MemStack,CommandHandle,SwapChainImage, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_NONE,VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_IMAGE_ASPECT_COLOR_BIT); + VulkanUtils.ImageBarrier(MemStack,CommandHandle,SrcAttachment.GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_ACCESS_2_SHADER_READ_BIT,VK_IMAGE_ASPECT_COLOR_BIT); + + vkCmdBeginRendering(CommandHandle, RenderInfo[ImageIndex]); + vkCmdBindPipeline(CommandHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,pipeline.GetVulkanPipeline()); + + VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent(); + int Width = SwapChainExtent.width(); + int Height = SwapChainExtent.height(); + var Viewport = VkViewport.calloc(1,MemStack) + .x(0) + .y(Height) + .height(-Height) + .width(Width) + .minDepth(0.0f) + .maxDepth(1.0f); + vkCmdSetViewport(CommandHandle,0,Viewport); + + var Scissor = VkRect2D.calloc(1,MemStack) + .extent(it->it.width(Width).height(Height)) + .offset(it->it.x(0).y(0)); + vkCmdSetScissor(CommandHandle,0,Scissor); + + DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); + LongBuffer DescriptorSets = MemStack.mallocLong(1).put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT).GetVkDescriptorSet()); + vkCmdBindDescriptorSets(CommandHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,pipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null); + + vkCmdDraw(CommandHandle,3,1,0,0); + + vkCmdEndRendering(CommandHandle); + + VulkanUtils.ImageBarrier(MemStack,CommandHandle,SwapChainImage,VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, + VK_PIPELINE_STAGE_2_NONE, VK_IMAGE_ASPECT_COLOR_BIT); + } + } + + public void Resize(VulkanContext VkCtx, Attachment SrcAttachment){ + Arrays.asList(RenderInfo).forEach(VkRenderingInfo::free); + Arrays.asList(ColourAttachmentsInfo).forEach(VkRenderingAttachmentInfo.Buffer::free); + ColourAttachmentsInfo = CreateColourAttachmentsInfo(VkCtx,ClearValueColour); + RenderInfo = CreateRenderInfo(VkCtx,ColourAttachmentsInfo); + + DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); + DescriptorSet descriptorSet = descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT); + descriptorSet.SetImage(VkCtx.GetDevice(),SrcAttachment.GetVkImageView(),textureSampler,0); + } + + public void CleanUp(VulkanContext VkCtx){ + textureSampler.CleanUp(VkCtx); + AttachmentDescriptorSetLayout.CleanUp(VkCtx); + pipeline.CleanUp(VkCtx); + Arrays.asList(RenderInfo).forEach(VkRenderingInfo::free); + Arrays.asList(ColourAttachmentsInfo).forEach(VkRenderingAttachmentInfo.Buffer::free); + ClearValueColour.free(); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Util/VulkanBuffer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Util/VulkanBuffer.java index c79ea6b..3af05c7 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Util/VulkanBuffer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Util/VulkanBuffer.java @@ -56,27 +56,6 @@ public class VulkanBuffer { Buffer = LongPointer.get(0); Allocation = AllocationPointer.get(0); pointerBuffer = MemoryUtil.memAllocPointer(1); - /* var MemoryRequirements = VkMemoryRequirements.calloc(MemStack); - vkGetBufferMemoryRequirements(device.FetchVulkanDevice(), Buffer, MemoryRequirements); - - var MemoryAllocation = VkMemoryAllocateInfo.calloc(MemStack) - .sType$Default() - .allocationSize(MemoryRequirements.size()) - .memoryTypeIndex(VulkanUtils.MemoryTypeFromProperties(vulkanContext, MemoryRequirements.memoryTypeBits(), RequestMask)); - - vkCheck(vkAllocateMemory(device.FetchVulkanDevice(),MemoryAllocation,null,LongPointer),"Failed to allocate memory for Vulkan"); - AllocationSize = MemoryAllocation.allocationSize(); - Memory = LongPointer.get(0); - pointerBuffer = MemoryUtil.memAllocPointer(1); - if (Buffer == 0) { - Logger.error("Vulkan crash blocked: Native bufferHandle cannot be 0!"); - throw new IllegalArgumentException("Vulkan crash blocked: Native bufferHandle cannot be 0!"); - } - if (Memory == 0) { - Logger.error("Vulkan crash blocked: Native memoryHandle cannot be 0! Device out of memory or allocation failed."); - throw new IllegalArgumentException("Vulkan crash blocked: Native memoryHandle cannot be 0! Device out of memory or allocation failed."); - } - vkCheck(vkBindBufferMemory(device.FetchVulkanDevice(),Buffer,Memory,0),"Failed to Bind Vulkan Memory Buffer");*/ } } public void cleanup(VulkanContext vulkanContext){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Util/VulkanUtils.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Util/VulkanUtils.java index 2ad671c..e9dfe30 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Util/VulkanUtils.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Util/VulkanUtils.java @@ -10,7 +10,13 @@ import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryUtil; import org.lwjgl.vulkan.*; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; +import java.nio.IntBuffer; import java.util.Locale; import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; @@ -25,6 +31,7 @@ public class VulkanUtils { public static final int INT_SIZE = 4; public static final int MATRIX4X4_SIZE = 16 * FLOAT_SIZE; public static final int VEC4_SIZE = 4 * FLOAT_SIZE; + public static final int VEC2_SIZE = 2 * FLOAT_SIZE; public static void CopyMatrixToBuffer(VulkanContext VkCtx, VulkanBuffer VkBuffer, Matrix4f matrix, int Offset){ long MappedMemory = VkBuffer.MapMemory(VkCtx); @@ -136,4 +143,24 @@ public class VulkanUtils { throw new RuntimeException(ErrorMessage + ": " + ErrorCode + " [" + Error + "]"); } } + + public static InputStream convertFloatBufferToInputStream(FloatBuffer floatBuffer) { + floatBuffer.rewind(); + byte[] byteArray = new byte[floatBuffer.remaining() * 4]; + ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray); + byteBuffer.order(ByteOrder.nativeOrder()); + byteBuffer.asFloatBuffer().put(floatBuffer); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray); + return new BufferedInputStream(byteArrayInputStream); + } + + public static InputStream convertIntBufferToInputStream(IntBuffer intBuffer) { + intBuffer.rewind(); + byte[] byteArray = new byte[intBuffer.remaining() * 4]; + ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray); + byteBuffer.order(ByteOrder.nativeOrder()); + byteBuffer.asIntBuffer().put(intBuffer); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray); + return new BufferedInputStream(byteArrayInputStream); + } } diff --git a/terrain4j.properties b/terrain4j.properties index 25bd983..6162312 100644 --- a/terrain4j.properties +++ b/terrain4j.properties @@ -13,14 +13,21 @@ frame_accuracy=0 throttle_on_unfocus=true throttle_accuracy=500000000 #event tick rate for game process -master_tick_rate=120 +master_tick_rate=240 main_thread_tickrate=120 fast_thread_tickrate=240 -cap_master_to_tickrate=false +cap_master_to_tickrate=true cap_main_to_tickrate=true cap_fast_to_tickrate=true #Renderer Properties +#AA settings +#0=No AA +#1=FXAA +#2=MSAAx2 +#3=MSAAx4 +#4=MSAAx8 +anti_alias_mode=0 Debug_Shaders = false ShaderRecompiling = true #Vulkan Debugging toggle @@ -34,7 +41,7 @@ PhysicalDeviceName= #3D Projection Properties field_of_view=60.0f -z_near_plane=0.10f -z_far_plane=1000.0f +z_far_plane=1f +z_near_plane=10000.0f