diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-09-06 14:51:57 +0000 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2021-09-06 14:51:57 +0000 |
| commit | ed2691f4385c5ab4dd050beac808a695eed2da45 (patch) | |
| tree | 28af8369d2671d8598f20707fb4822f3c9b8495d | |
| parent | e33ef6ca476fb9db5e4302f3af05592e29370b74 (diff) | |
wip
| -rw-r--r-- | data/chess.blend | bin | 0 -> 9170440 bytes | |||
| -rw-r--r-- | shaders/compose_with_shadows.frag | 4 | ||||
| -rw-r--r-- | shaders/tone_mapping2.frag | 72 | ||||
| -rw-r--r-- | src/VkChess.cs | 100 | ||||
| -rw-r--r-- | src/deferredPbrRenderer.cs | 481 | ||||
| -rw-r--r-- | src/deferredPbrRendererBase.cs | 502 | ||||
| -rw-r--r-- | src/shadowMapRenderer.cs | 6 | ||||
| -rw-r--r-- | vkChess.net.csproj | 3 |
8 files changed, 667 insertions, 501 deletions
diff --git a/data/chess.blend b/data/chess.blend Binary files differnew file mode 100644 index 0000000..548e173 --- /dev/null +++ b/data/chess.blend diff --git a/shaders/compose_with_shadows.frag b/shaders/compose_with_shadows.frag index 8b5b17d..558a26e 100644 --- a/shaders/compose_with_shadows.frag +++ b/shaders/compose_with_shadows.frag @@ -151,7 +151,7 @@ float textureProj(vec4 P, float layer, vec2 offset) if (shadowCoord.w > 0.0 && dist < shadowCoord.z) shadow = SHADOW_FACTOR; }else - shadow = 0.05f;//for debug view out of light proj + shadow = 0.0f;//for debug view out of light proj return shadow; } @@ -258,7 +258,7 @@ void main() vec3 color = NdotL * lights[i].color.rgb * (diffuseContrib + specContrib); // Calculate lighting contribution from image based lighting source (IBL) - colors += shadowFactor * (color + getIBLContribution(pbrInputs, n, reflection)); + colors += shadowFactor * (color + getIBLContribution(pbrInputs, n, reflection)); } colors /= NUM_LIGHTS; diff --git a/shaders/tone_mapping2.frag b/shaders/tone_mapping2.frag new file mode 100644 index 0000000..3bcbe1b --- /dev/null +++ b/shaders/tone_mapping2.frag @@ -0,0 +1,72 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout(push_constant) uniform PushConsts { + float exposure; + float gamma; +}; + +vec3 Uncharted2Tonemap(vec3 color) +{ + const float A = 0.15; + const float B = 0.50; + const float C = 0.10; + const float D = 0.20; + const float E = 0.02; + const float F = 0.30; + const float W = 11.2; + return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; +} + +vec4 tonemap(vec4 color, float exposure, float gamma) +{ + vec3 outcol = Uncharted2Tonemap(color.rgb * exposure); + outcol = outcol * (1.0f / Uncharted2Tonemap(vec3(11.2f))); + return vec4(pow(outcol, vec3(1.0f / gamma)), color.a); +} + +vec4 SRGBtoLINEAR(vec4 srgbIn) +{ + #ifdef MANUAL_SRGB + #ifdef SRGB_FAST_APPROXIMATION + vec3 linOut = pow(srgbIn.xyz,vec3(2.2)); + #else //SRGB_FAST_APPROXIMATION + vec3 bLess = step(vec3(0.04045),srgbIn.xyz); + vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess ); + #endif //SRGB_FAST_APPROXIMATION + return vec4(linOut,srgbIn.w);; + #else //MANUAL_SRGB + return srgbIn; + #endif //MANUAL_SRGB +} + +layout (set = 0, binding = 0) uniform sampler2D uiImage; +layout (set = 0, binding = 1) uniform sampler2D samplerHDR; + +layout (location = 0) in vec2 inUV; +layout (location = 0) out vec4 outColor; + +void main() +{ + //ivec2 ts = textureSize(samplerHDR); + //vec4 hdrColor = texelFetch (samplerHDR, ivec2(gl_FragCoord.xy), gl_SampleID); + + //vec4 hdrColor = texelFetch (samplerHDR, inUV); + //vec4 c = texture (bloom, inUV); + //float lum = (0.299*c.r + 0.587*c.g + 0.114*c.b); + //if (lum>1.0) + // hdrColor.rgb += c.rgb * 0.05; + //outColor = SRGBtoLINEAR(tonemap(hdrColor, exposure, gamma)); + vec4 hdrColor = texture(samplerHDR, inUV); + vec4 uiColor = texture(uiImage, inUV); + outColor = tonemap(hdrColor, exposure, gamma); + outColor = vec4(outColor.rgb * (1 - uiColor.a) + uiColor.rgb * uiColor.a, 1); + + /* + outColor = vec4(SRGBtoLINEAR(tonemap(hdrColor.rgb)), hdrColor.a);;*/ + +/* vec3 mapped = vec3(1.0) - exp(-hdrColor.rgb * pc.exposure); + mapped = pow(mapped, vec3(1.0 / pc.gamma)); + outColor = vec4(mapped, hdrColor.a);*/ +} diff --git a/src/VkChess.cs b/src/VkChess.cs index 0cb20dd..37975c8 100644 --- a/src/VkChess.cs +++ b/src/VkChess.cs @@ -40,11 +40,11 @@ namespace vkChess VkChess(){} static void Main (string [] args) { Instance.VALIDATION = true; - //Instance.RENDER_DOC_CAPTURE = true; + Instance.RENDER_DOC_CAPTURE = false; //SwapChain.PREFERED_FORMAT = VkFormat.B8g8r8a8Unorm; - DeferredPbrRenderer.MAX_MATERIAL_COUNT = 5; - DeferredPbrRenderer.MRT_FORMAT = VkFormat.R16g16b16a16Sfloat; - DeferredPbrRenderer.HDR_FORMAT = VkFormat.R16g16b16a16Sfloat; + DeferredPbrRendererBase.MAX_MATERIAL_COUNT = 5; + DeferredPbrRendererBase.MRT_FORMAT = VkFormat.R16g16b16a16Sfloat; + DeferredPbrRendererBase.HDR_FORMAT = VkFormat.R16g16b16a16Sfloat; PbrModelTexArray.TEXTURE_DIM = 512; ShadowMapRenderer.SHADOWMAP_SIZE = 1024; @@ -53,12 +53,13 @@ namespace vkChess } public override string [] EnabledInstanceExtensions => new string [] { #if DEBUG - Ext.I.VK_EXT_debug_utils, + //Ext.I.VK_EXT_debug_utils, #endif }; public override string [] EnabledDeviceExtensions => new string [] { Ext.D.VK_KHR_swapchain, + Ext.D.VK_KHR_multiview }; protected override void configureEnabledFeatures (VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures enabled_features) { base.configureEnabledFeatures (available_features, ref enabled_features); @@ -82,19 +83,77 @@ namespace vkChess public StatResult [] StatResults; #endif #if DEBUG - vke.DebugUtils.Messenger dbgmsg; + //vke.DebugUtils.Messenger dbgmsg; #endif + protected override void CreateRenderPass () { + renderPass = new RenderPass (dev, swapChain.ColorFormat, DeferredPbrRendererBase.NUM_SAMPLES); + /*renderPass = new RenderPass (dev, VkSampleCountFlags.SampleCount1); + renderPass.AddAttachment (swapChain.ColorFormat, VkImageLayout.PresentSrcKHR, VkSampleCountFlags.SampleCount1, + VkAttachmentLoadOp.Load, VkAttachmentStoreOp.DontCare, VkImageLayout.ColorAttachmentOptimal);//final outpout + SubPass subpass0 = new SubPass (); + subpass0.AddColorReference (0, VkImageLayout.ColorAttachmentOptimal); + renderPass.AddSubpass (subpass0); + renderPass.AddDependency (Vk.SubpassExternal, 0, + VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput, + VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentWrite); + renderPass.AddDependency (0, Vk.SubpassExternal, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe, + VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);*/ + } + GraphicPipeline plToneMap; + DescriptorSetLayout dslToneMap; + protected override void CreateDescriptors () { + dsPool = new DescriptorPool (dev, 1, + new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 2)); + descSet = dsPool.Allocate (dslToneMap); + } + protected override void CreatePipeline () { + using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, DeferredPbrRendererBase.NUM_SAMPLES)) { + if (DeferredPbrRendererBase.NUM_SAMPLES != VkSampleCountFlags.SampleCount1) { + cfg.multisampleState.sampleShadingEnable = true; + cfg.multisampleState.minSampleShading = 0.5f; + } + dslToneMap = new DescriptorSetLayout (dev, 0, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) + ); + cfg.Layout = new PipelineLayout (dev, + new VkPushConstantRange (VkShaderStageFlags.Fragment, 2 * sizeof (float)), dslToneMap); + + cfg.RenderPass = renderPass; + cfg.AddShaders ( + new ShaderInfo (dev, VkShaderStageFlags.Vertex, "#vke.FullScreenQuad.vert.spv"), + new ShaderInfo (dev, VkShaderStageFlags.Fragment, "#vkChess.net.tone_mapping2.frag.spv") + ); + + plToneMap = new GraphicPipeline (cfg); + + } + } + protected override void recordUICmd (PrimaryCommandBuffer cmd, int imageIndex) { + renderPass.Begin(cmd, frameBuffers[imageIndex]); + + cmd.SetViewport (frameBuffers[imageIndex].Width, frameBuffers[imageIndex].Height); + cmd.SetScissor (frameBuffers[imageIndex].Width, frameBuffers[imageIndex].Height); + + cmd.PushConstant (plToneMap.Layout, VkShaderStageFlags.Fragment, 8, new float[] { Exposure, Gamma }, 0); + plToneMap.BindDescriptorSet (cmd, descSet); + plToneMap.Bind (cmd); + cmd.Draw (3, 1, 0, 0); + + renderPass.End (cmd); + } protected override void initVulkan () { initLog (); base.initVulkan (); #if DEBUG - dbgmsg = new vke.DebugUtils.Messenger (instance, VkDebugUtilsMessageTypeFlagsEXT.PerformanceEXT | VkDebugUtilsMessageTypeFlagsEXT.ValidationEXT | VkDebugUtilsMessageTypeFlagsEXT.GeneralEXT, - //VkDebugUtilsMessageSeverityFlagsEXT.InfoEXT | + /*dbgmsg = new vke.DebugUtils.Messenger (instance, VkDebugUtilsMessageTypeFlagsEXT.PerformanceEXT | VkDebugUtilsMessageTypeFlagsEXT.ValidationEXT | VkDebugUtilsMessageTypeFlagsEXT.GeneralEXT, + VkDebugUtilsMessageSeverityFlagsEXT.InfoEXT | VkDebugUtilsMessageSeverityFlagsEXT.WarningEXT | VkDebugUtilsMessageSeverityFlagsEXT.ErrorEXT | - VkDebugUtilsMessageSeverityFlagsEXT.VerboseEXT); + VkDebugUtilsMessageSeverityFlagsEXT.VerboseEXT);*/ #endif #if PIPELINE_STATS statPool = new PipelineStatisticsQueryPool (dev, @@ -115,7 +174,7 @@ namespace vkChess camera.SetPosition (0, 0f, -12.0f); camera.AspectRatio = Width / Height; - DeferredPbrRenderer.NUM_SAMPLES = SampleCount; + DeferredPbrRendererBase.NUM_SAMPLES = SampleCount; renderer = new DeferredPbrRenderer (dev, swapChain, presentQueue, cubemapPathes [0], camera.NearPlane, camera.FarPlane); @@ -124,7 +183,7 @@ namespace vkChess renderer.matrices.scaleIBLAmbient = IBLAmbient; renderer.lights[0].color = new Vector4 (LightStrength); //renderer.LoadModel (transferQ, "data/models/chess.glb"); - renderer.LoadModel (transferQ, "/mnt/devel/vkChess.net/data/models/chess.glb"); + renderer.LoadModel (transferQ, "/mnt/devel/vkChess.net/data/models/chess2.glb"); camera.Model = Matrix4x4.CreateScale (0.5f);// Matrix4x4.CreateScale(1f / Math.Max(Math.Max(renderer.modelAABB.Width, renderer.modelAABB.Height), renderer.modelAABB.Depth)); UpdateFrequency = 5; @@ -151,7 +210,7 @@ namespace vkChess "data/textures/gcanyon_cube.ktx", }; - DeferredPbrRenderer renderer; + DeferredPbrRendererBase renderer; public struct InstanceData { @@ -167,9 +226,9 @@ namespace vkChess public HostBuffer<InstanceData> instanceBuff; Model.InstancedCmd [] instancedCmds; - public static DeferredPbrRenderer curRenderer; + public static DeferredPbrRendererBase curRenderer; bool rebuildBuffers = false; - public virtual DeferredPbrRenderer.DebugView CurrentDebugView { + public virtual DeferredPbrRendererBase.DebugView CurrentDebugView { get => renderer.currentDebugView; set { if (value == renderer.currentDebugView) @@ -267,6 +326,10 @@ namespace vkChess protected override void OnResize () { base.OnResize (); renderer.Resize (); + + DescriptorSetWrites dsw = new DescriptorSetWrites (descSet, dslToneMap.Bindings[1]); + dsw.Write (dev, renderer.HDROutput.Descriptor); + buildCommandBuffers (); updateViewRequested = true; } @@ -275,12 +338,13 @@ namespace vkChess protected override void Dispose (bool disposing) { if (disposing) { if (!isDisposed) { + plToneMap.Dispose(); renderer.Dispose (); instanceBuff.Dispose (); } } #if DEBUG - dbgmsg.Dispose (); + //dbgmsg.Dispose (); #endif #if PIPELINE_STATS timestampQPool?.Dispose (); @@ -632,7 +696,7 @@ namespace vkChess Configuration.Global.Set ("Gamma", value); renderer.matrices.gamma = value; NotifyValueChanged ("Gamma", value); - updateViewRequested = true; + rebuildBuffers = true; } } public float Exposure { @@ -643,7 +707,7 @@ namespace vkChess Configuration.Global.Set ("Exposure", value); renderer.matrices.exposure = value; NotifyValueChanged ("Exposure", value); - updateViewRequested = true; + rebuildBuffers = true; } } public float IBLAmbient { @@ -674,7 +738,7 @@ namespace vkChess if (value == SampleCount) return; Configuration.Global.Set ("SampleCount", value); - DeferredPbrRenderer.NUM_SAMPLES = value; + DeferredPbrRendererBase.NUM_SAMPLES = value; NotifyValueChanged ("SampleCount", value); } } diff --git a/src/deferredPbrRenderer.cs b/src/deferredPbrRenderer.cs index 49c0bc9..c234257 100644 --- a/src/deferredPbrRenderer.cs +++ b/src/deferredPbrRenderer.cs @@ -7,482 +7,9 @@ using Vulkan; namespace vkChess { - public class DeferredPbrRenderer : IDisposable { - Device dev; - SwapChain swapChain; - public PresentQueue presentQueue; - - public static int MAX_MATERIAL_COUNT = 8; - public static VkSampleCountFlags NUM_SAMPLES = VkSampleCountFlags.SampleCount1; - public static VkFormat HDR_FORMAT = VkFormat.R32g32b32a32Sfloat; - public static VkFormat MRT_FORMAT = VkFormat.R32g32b32a32Sfloat; - - public enum DebugView { - none, - color, - normal, - pos, - occlusion, - emissive, - metallic, - roughness, - depth, - prefill, - irradiance, - shadowMap - } - - public DebugView currentDebugView = DebugView.none; - public int lightNumDebug = 0; - public int debugMip = 0; - public int debugFace = 0; - - public struct Matrices { - public Matrix4x4 projection; - public Matrix4x4 model; - public Matrix4x4 view; - public Vector4 camPos; - public float exposure; - public float gamma; - public float prefilteredCubeMipLevels; - public float scaleIBLAmbient; - } - public struct Light { - public Vector4 position; - public Vector4 color; - public Matrix4x4 mvp; - } - - public Matrices matrices = new Matrices { - gamma = 1.2f, - exposure = 2.0f, - scaleIBLAmbient = 0.5f, - }; - //public Light[] lights = { - // new Light { - // position = new Vector4(3.5f,12.5f,2,0f), - // color = new Vector4(1,0.8f,0.8f,1) - // }, - // new Light { - // position = new Vector4(-3.5f,12.5f,2,0f), - // color = new Vector4(0.8f,0.8f,1,1) - // } - //}; - public Light [] lights = { - new Light { - position = new Vector4(5.5f,12.5f,2,0f), - color = new Vector4(1,1,1,1) - }, - new Light { - position = new Vector4(-5.5f,12.5f,-2,0f), - color = new Vector4(1,1,1,1) - } - }; - - //public DescriptorSetWrites UiImageUpdate => new DescriptorSetWrites (dsMain, descLayoutMain.Bindings [8]); - - const float lightMoveSpeed = 0.1f; - - FrameBuffers frameBuffers; - Image gbColorRough, gbEmitMetal, gbN_AO, gbPos, hdrImg; - - DescriptorPool descriptorPool; - DescriptorSetLayout descLayoutMain, descLayoutGBuff; - DescriptorSet dsMain, dsGBuff; - - public PipelineCache pipelineCache; - Pipeline depthPrepassPipeline, gBuffPipeline, composePipeline, toneMappingPipeline, debugPipeline; - - public HostBuffer uboMatrices { get; private set; } - public HostBuffer<Light> uboLights { get; private set; } - - RenderPass renderPass; - - public PbrModel model { get; private set; } - public vke.Environment.EnvironmentCube envCube; - public ShadowMapRenderer shadowMapRenderer; - - public BoundingBox modelAABB; - - const int SP_SKYBOX = 0; - const int SP_DEPTH_PREPASS = 1; - const int SP_MODELS = 2; - const int SP_COMPOSE = 3; - const int SP_TONE_MAPPING = 4; - - public Model.Scene mainScene; - - public DeferredPbrRenderer (Device dev, SwapChain swapChain, PresentQueue presentQueue, string cubemapPath, float nearPlane, float farPlane) { - this.dev = dev; - this.swapChain = swapChain; - this.presentQueue = presentQueue; - pipelineCache = new PipelineCache (dev); - - descriptorPool = new DescriptorPool (dev, 3, - new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer, 3), - new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 6), - new VkDescriptorPoolSize (VkDescriptorType.InputAttachment, 5) - ); - - uboMatrices = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, matrices, true); - uboLights = new HostBuffer<Light> (dev, VkBufferUsageFlags.UniformBuffer, lights, true); - shadowMapRenderer = new ShadowMapRenderer (dev, this, 32); - - init (nearPlane, farPlane, cubemapPath); - - dev.WaitIdle (); - } - - void init_renderpass () { - renderPass = new RenderPass (dev, NUM_SAMPLES); - - renderPass.AddAttachment (swapChain.ColorFormat, VkImageLayout.PresentSrcKHR, VkSampleCountFlags.SampleCount1);//swapchain image - renderPass.AddAttachment (dev.GetSuitableDepthFormat (), VkImageLayout.DepthStencilAttachmentOptimal, NUM_SAMPLES); - renderPass.AddAttachment (swapChain.ColorFormat, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff0 (color + roughness) and final color before resolve - renderPass.AddAttachment (VkFormat.R8g8b8a8Unorm, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff1 (emit + metal) - renderPass.AddAttachment (MRT_FORMAT, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff2 (normals + AO) - renderPass.AddAttachment (MRT_FORMAT, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff3 (Pos + depth) - renderPass.AddAttachment (HDR_FORMAT, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES);//hdr color - - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - renderPass.ClearValues.Add (new VkClearValue { depthStencil = new VkClearDepthStencilValue (1.0f, 0) }); - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); - renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.5f, 0.0f, 0.0f) }); - - SubPass[] subpasses = { new SubPass (), new SubPass (), new SubPass (), new SubPass (), new SubPass () }; - //skybox - subpasses[SP_SKYBOX].AddColorReference (6, VkImageLayout.ColorAttachmentOptimal); - - //depth pre pass - subpasses [SP_DEPTH_PREPASS].SetDepthReference (1, VkImageLayout.DepthStencilAttachmentOptimal); - subpasses [SP_DEPTH_PREPASS].AddPreservedReference (6); - //models - subpasses [SP_MODELS].AddColorReference (new VkAttachmentReference (2, VkImageLayout.ColorAttachmentOptimal), - new VkAttachmentReference (3, VkImageLayout.ColorAttachmentOptimal), - new VkAttachmentReference (4, VkImageLayout.ColorAttachmentOptimal), - new VkAttachmentReference (5, VkImageLayout.ColorAttachmentOptimal)); - subpasses[SP_MODELS].SetDepthReference (1, VkImageLayout.DepthStencilAttachmentOptimal); - subpasses[SP_MODELS].AddPreservedReference (6); - - //compose - subpasses[SP_COMPOSE].AddColorReference (6, VkImageLayout.ColorAttachmentOptimal); - subpasses[SP_COMPOSE].AddInputReference (new VkAttachmentReference (2, VkImageLayout.ShaderReadOnlyOptimal), - new VkAttachmentReference (3, VkImageLayout.ShaderReadOnlyOptimal), - new VkAttachmentReference (4, VkImageLayout.ShaderReadOnlyOptimal), - new VkAttachmentReference (5, VkImageLayout.ShaderReadOnlyOptimal)); - //tone mapping - subpasses[SP_TONE_MAPPING].AddColorReference ((NUM_SAMPLES == VkSampleCountFlags.SampleCount1) ? 0u : 2u, VkImageLayout.ColorAttachmentOptimal); - subpasses[SP_TONE_MAPPING].AddInputReference (new VkAttachmentReference (6, VkImageLayout.ShaderReadOnlyOptimal)); - if (NUM_SAMPLES != VkSampleCountFlags.SampleCount1) - subpasses[SP_TONE_MAPPING].AddResolveReference (0, VkImageLayout.ColorAttachmentOptimal); - - renderPass.AddSubpass (subpasses); - - renderPass.AddDependency (Vk.SubpassExternal, SP_SKYBOX, - VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput, - VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); - renderPass.AddDependency (SP_SKYBOX, SP_DEPTH_PREPASS, - VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, - VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); - renderPass.AddDependency (SP_DEPTH_PREPASS, SP_MODELS, - VkPipelineStageFlags.EarlyFragmentTests, VkPipelineStageFlags.FragmentShader, - VkAccessFlags.DepthStencilAttachmentWrite, VkAccessFlags.ShaderRead); - renderPass.AddDependency (SP_MODELS, SP_COMPOSE, - VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, - VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); - renderPass.AddDependency (SP_COMPOSE, SP_TONE_MAPPING, - VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, - VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); - renderPass.AddDependency (SP_TONE_MAPPING, Vk.SubpassExternal, - VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe, - VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead); - } - - void init (float nearPlane, float farPlane, string cubemapPath) { - init_renderpass (); - - descLayoutMain = new DescriptorSetLayout (dev, - new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer),//matrices and params - new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//irradiance - new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//prefil - new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//lut brdf - new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer),//lights - new VkDescriptorSetLayoutBinding (5, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer),//materials - new VkDescriptorSetLayoutBinding (6, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//shadow map - new VkDescriptorSetLayoutBinding (7, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)//texture array - //new VkDescriptorSetLayoutBinding (8, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) - );//uiImage - - descLayoutGBuff = new DescriptorSetLayout (dev, - new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//color + roughness - new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//emit + metal - new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//normals + AO - new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//Pos + depth - new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment));//hdr - - descLayoutMain.SetName ("main"); - descLayoutGBuff.SetName ("GBuff"); - - using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, NUM_SAMPLES)) { - - cfg.rasterizationState.cullMode = VkCullModeFlags.None; - - if (NUM_SAMPLES != VkSampleCountFlags.SampleCount1) { - cfg.multisampleState.sampleShadingEnable = true; - cfg.multisampleState.minSampleShading = 0.5f; - } - cfg.Cache = pipelineCache; - cfg.Layout = new PipelineLayout (dev, - new VkPushConstantRange[] { - new VkPushConstantRange (VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf<Matrix4x4> ()), - new VkPushConstantRange (VkShaderStageFlags.Fragment, sizeof (int), 64)}, - descLayoutMain, descLayoutGBuff); - - cfg.RenderPass = renderPass; - //cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); - - cfg.AddVertexBinding<PbrModelTexArray.Vertex> (0); - cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat, VkFormat.R32g32Sfloat); - - cfg.AddVertexBinding<VkChess.InstanceData> (1, VkVertexInputRate.Instance); - cfg.AddVertexAttributes (1, VkFormat.R32g32b32a32Sfloat, VkFormat.R32g32b32a32Sfloat, VkFormat.R32g32b32a32Sfloat, VkFormat.R32g32b32a32Sfloat, VkFormat.R32g32b32a32Sfloat); - - using (SpecializationInfo constants = new SpecializationInfo ( - new SpecializationConstant<float> (0, nearPlane), - new SpecializationConstant<float> (1, farPlane), - new SpecializationConstant<int> (2, MAX_MATERIAL_COUNT))) { - cfg.AddShader (dev, VkShaderStageFlags.Vertex, "#vkChess.net.GBuffPbrInstanced.vert.spv"); - - cfg.SubpassIndex = SP_DEPTH_PREPASS; - depthPrepassPipeline = new GraphicPipeline (cfg, "Depth prepass"); - - cfg.depthStencilState.depthCompareOp = VkCompareOp.Equal; - cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); - cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); - cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); - - cfg.SubpassIndex = SP_MODELS; - - cfg.AddShader (dev, VkShaderStageFlags.Fragment, "#vkChess.net.GBuffPbrTexArray.frag.spv", constants); - - gBuffPipeline = new GraphicPipeline (cfg, "GBuff"); - } - cfg.rasterizationState.cullMode = VkCullModeFlags.Front; - //COMPOSE PIPELINE - cfg.blendAttachments.Clear (); - cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); - - cfg.ResetShadersAndVerticesInfos (); - - cfg.SubpassIndex = SP_COMPOSE; - cfg.Layout = gBuffPipeline.Layout; - cfg.depthStencilState.depthTestEnable = false; - cfg.depthStencilState.depthWriteEnable = false; - using (SpecializationInfo constants = new SpecializationInfo ( - new SpecializationConstant<uint> (0, (uint)lights.Length), - new SpecializationConstant<float> (1, 0.25f))) { - cfg.AddShader (dev, VkShaderStageFlags.Vertex, "#vke.FullScreenQuad.vert.spv"); - cfg.AddShader (dev, VkShaderStageFlags.Fragment, "#vkChess.net.compose_with_shadows.frag.spv", constants); - composePipeline = new GraphicPipeline (cfg, "compose"); - } - //DEBUG DRAW use subpass of compose - cfg.ReplaceShader (1, new ShaderInfo (dev, VkShaderStageFlags.Fragment, "#vkChess.net.show_gbuff.frag.spv")); - cfg.SubpassIndex = SP_COMPOSE; - debugPipeline = new GraphicPipeline (cfg, "debug"); - //TONE MAPPING - cfg.ReplaceShader (1, new ShaderInfo (dev, VkShaderStageFlags.Fragment, "#vkChess.net.tone_mapping.frag.spv")); - cfg.SubpassIndex = SP_TONE_MAPPING; - toneMappingPipeline = new GraphicPipeline (cfg, "tonne mapping"); - } - - dsMain = descriptorPool.Allocate (descLayoutMain); - dsGBuff = descriptorPool.Allocate (descLayoutGBuff); - - envCube = new vke.Environment.EnvironmentCube (cubemapPath, gBuffPipeline.Layout, presentQueue, renderPass); - - matrices.prefilteredCubeMipLevels = envCube.prefilterCube.CreateInfo.mipLevels; - - DescriptorSetWrites dsMainWrite = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings.GetRange (0, 5).ToArray ()); - dsMainWrite.Write (dev, - uboMatrices.Descriptor, - envCube.irradianceCube.Descriptor, - envCube.prefilterCube.Descriptor, - envCube.lutBrdf.Descriptor, - uboLights.Descriptor); - - dsMainWrite = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[6]); - dsMainWrite.Write (dev, shadowMapRenderer.shadowMap.Descriptor); - } - - public void LoadModel (Queue transferQ, string path) { - dev.WaitIdle (); - - model?.Dispose (); - model = new PbrModelTexArray (transferQ, path); - - DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[5], descLayoutMain.Bindings[7]); - uboUpdate.Write (dev, model.materialUBO.Descriptor, (model as PbrModelTexArray).texArray.Descriptor); - - modelAABB = model.DefaultScene.AABB; - } - - public void recordDraw (PrimaryCommandBuffer cmd, int imageIndex, vke.Buffer instanceBuf = null, params Model.InstancedCmd[] instances) { - FrameBuffer fb = frameBuffers[imageIndex]; - renderPass.Begin(cmd, fb); - - cmd.SetViewport(fb.Width, fb.Height); - cmd.SetScissor(fb.Width, fb.Height); - - cmd.BindDescriptorSet(gBuffPipeline.Layout, dsMain); - - envCube.RecordDraw(cmd); - renderPass.BeginSubPass(cmd); - - if (model != null) { - model.Bind (cmd); - - depthPrepassPipeline.Bind (cmd); - if (instanceBuf != null) - model.Draw (cmd, gBuffPipeline.Layout, instanceBuf, false, instances); - - renderPass.BeginSubPass (cmd); - gBuffPipeline.Bind(cmd); - - if (instanceBuf != null) - model.Draw(cmd, gBuffPipeline.Layout, instanceBuf, false, instances); - } - renderPass.BeginSubPass(cmd); - - cmd.BindDescriptorSet(composePipeline.Layout, dsGBuff, 1); - - if (currentDebugView == DebugView.none) - composePipeline.Bind(cmd); - else { - debugPipeline.Bind(cmd); - uint debugValue = (uint)currentDebugView - 1; - if (currentDebugView == DebugView.shadowMap) - debugValue += (uint)((lightNumDebug << 8)); - else - debugValue += (uint)((debugFace << 8) + (debugMip << 16)); - cmd.PushConstant(debugPipeline.Layout, VkShaderStageFlags.Fragment, debugValue, (uint)Marshal.SizeOf<Matrix4x4>()); - } - - cmd.Draw(3, 1, 0, 0); - - renderPass.BeginSubPass(cmd); - toneMappingPipeline.Bind(cmd); - cmd.Draw(3, 1, 0, 0); - - renderPass.End(cmd); - } - - public void MoveLight (Vector4 dir) { - lights[lightNumDebug].position += dir * lightMoveSpeed; - shadowMapRenderer.updateShadowMap = true; - } - - #region update - public void UpdateView (Camera camera) { - camera.AspectRatio = (float)swapChain.Width / swapChain.Height; - - matrices.projection = camera.Projection; - matrices.view = camera.View; - matrices.model = camera.Model; - - Matrix4x4.Invert (camera.View, out Matrix4x4 inv); - matrices.camPos = new Vector4 (inv.M41, inv.M42, inv.M43, 0); - - uboMatrices.Update (matrices, (uint)Marshal.SizeOf<Matrices> ()); - shadowMapRenderer.updateShadowMap = true; + public class DeferredPbrRenderer : DeferredPbrRendererBase { + public DeferredPbrRenderer (Device dev, SwapChain swapChain, PresentQueue presentQueue, string cubemapPath, float nearPlane, float farPlane) + : base (dev, swapChain, presentQueue, cubemapPath, nearPlane, farPlane) { } - - #endregion - - void createGBuff () { - gbColorRough?.Dispose (); - gbEmitMetal?.Dispose (); - gbN_AO?.Dispose (); - gbPos?.Dispose (); - hdrImg?.Dispose (); - - gbColorRough = new Image (dev, swapChain.ColorFormat, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, NUM_SAMPLES); - gbEmitMetal = new Image (dev, VkFormat.R8g8b8a8Unorm, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, NUM_SAMPLES); - gbN_AO = new Image (dev, MRT_FORMAT, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, NUM_SAMPLES); - gbPos = new Image (dev, MRT_FORMAT, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, NUM_SAMPLES); - hdrImg = new Image (dev, HDR_FORMAT, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal | VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, NUM_SAMPLES); - - gbColorRough.CreateView (); - gbColorRough.CreateSampler (); - gbColorRough.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - gbEmitMetal.CreateView (); - gbEmitMetal.CreateSampler (); - gbEmitMetal.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - gbN_AO.CreateView (); - gbN_AO.CreateSampler (); - gbN_AO.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - gbPos.CreateView (); - gbPos.CreateSampler (); - gbPos.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - hdrImg.CreateView (); - hdrImg.CreateSampler (); - hdrImg.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - - DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descLayoutGBuff); - uboUpdate.Write (dev, dsGBuff, gbColorRough.Descriptor, - gbEmitMetal.Descriptor, - gbN_AO.Descriptor, - gbPos.Descriptor, - hdrImg.Descriptor); - gbColorRough.SetName ("GBuffColorRough"); - gbEmitMetal.SetName ("GBuffEmitMetal"); - gbN_AO.SetName ("GBuffN"); - gbPos.SetName ("GBuffPos"); - hdrImg.SetName ("HDRimg"); - } - - public void Resize () { - frameBuffers?.Dispose (); - frameBuffers = new FrameBuffers (); - - createGBuff (); - - for (int i = 0; i < swapChain.ImageCount; ++i) { - frameBuffers.Add (new FrameBuffer (renderPass, swapChain.Width, swapChain.Height, new Image [] { - swapChain.images[i], null, gbColorRough, gbEmitMetal, gbN_AO, gbPos, hdrImg})); - } - //frameBuffers = renderPass.CreateFrameBuffers (swapChain); - } - - public void Dispose () { - dev.WaitIdle (); - - frameBuffers?.Dispose (); - - gbColorRough.Dispose (); - gbEmitMetal.Dispose (); - gbN_AO.Dispose (); - gbPos.Dispose (); - hdrImg.Dispose (); - - gBuffPipeline.Dispose (); - composePipeline.Dispose (); - toneMappingPipeline.Dispose (); - debugPipeline.Dispose (); - depthPrepassPipeline.Dispose (); - - descLayoutMain.Dispose (); - descLayoutGBuff.Dispose (); - - uboMatrices.Dispose (); - uboLights.Dispose (); - model.Dispose (); - envCube.Dispose (); - shadowMapRenderer.Dispose (); - - descriptorPool.Dispose (); - } - } + } } diff --git a/src/deferredPbrRendererBase.cs b/src/deferredPbrRendererBase.cs new file mode 100644 index 0000000..dd42f9f --- /dev/null +++ b/src/deferredPbrRendererBase.cs @@ -0,0 +1,502 @@ +using System; +using System.Numerics; +using System.Runtime.InteropServices; +using vke; +using vke.glTF; +using Vulkan; + +namespace vkChess +{ + public class DeferredPbrRendererBase : IDisposable { + Device dev; + SwapChain swapChain; + public PresentQueue presentQueue; + + public static int MAX_MATERIAL_COUNT = 8; + public static VkSampleCountFlags NUM_SAMPLES = VkSampleCountFlags.SampleCount1; + public static VkFormat HDR_FORMAT = VkFormat.R32g32b32a32Sfloat; + public static VkFormat MRT_FORMAT = VkFormat.R32g32b32a32Sfloat; + + public enum DebugView { + none, + color, + normal, + pos, + occlusion, + emissive, + metallic, + roughness, + depth, + prefill, + irradiance, + shadowMap + } + + public DebugView currentDebugView = DebugView.none; + public int lightNumDebug = 0; + public int debugMip = 0; + public int debugFace = 0; + + public struct Matrices { + public Matrix4x4 projection; + public Matrix4x4 model; + public Matrix4x4 view; + public Vector4 camPos; + public float exposure; + public float gamma; + public float prefilteredCubeMipLevels; + public float scaleIBLAmbient; + } + public struct Light { + public Vector4 position; + public Vector4 color; + public Matrix4x4 mvp; + } + + public Matrices matrices = new Matrices { + gamma = 1.2f, + exposure = 2.0f, + scaleIBLAmbient = 0.5f, + }; + //public Light[] lights = { + // new Light { + // position = new Vector4(3.5f,12.5f,2,0f), + // color = new Vector4(1,0.8f,0.8f,1) + // }, + // new Light { + // position = new Vector4(-3.5f,12.5f,2,0f), + // color = new Vector4(0.8f,0.8f,1,1) + // } + //}; + public Light [] lights = { + new Light { + position = new Vector4(5.5f,12.5f,2,0f), + color = new Vector4(1,1,1,1) + }, + /*new Light { + position = new Vector4(-5.5f,12.5f,-2,0f), + color = new Vector4(1,1,1,1) + }*/ + }; + + //public DescriptorSetWrites UiImageUpdate => new DescriptorSetWrites (dsMain, descLayoutMain.Bindings [8]); + + const float lightMoveSpeed = 0.1f; + + FrameBuffers frameBuffers; + Image gbColorRough, gbEmitMetal, gbN_AO, gbPos, hdrImg; + + public Image HDROutput => hdrImg; + + DescriptorPool descriptorPool; + DescriptorSetLayout descLayoutMain, descLayoutGBuff; + DescriptorSet dsMain, dsGBuff; + + public PipelineCache pipelineCache; + Pipeline depthPrepassPipeline, gBuffPipeline, composePipeline, debugPipeline; + + public HostBuffer uboMatrices { get; private set; } + public HostBuffer<Light> uboLights { get; private set; } + + RenderPass renderPass; + + public PbrModel model { get; private set; } + public vke.Environment.EnvironmentCube envCube; + public ShadowMapRenderer shadowMapRenderer; + + public BoundingBox modelAABB; + + const int SP_SKYBOX = 0; + const int SP_DEPTH_PREPASS = 1; + const int SP_MODELS = 2; + const int SP_COMPOSE = 3; + //const int SP_TONE_MAPPING = 4; + + public Model.Scene mainScene; + + public DeferredPbrRendererBase (Device dev, SwapChain swapChain, PresentQueue presentQueue, string cubemapPath, float nearPlane, float farPlane) { + this.dev = dev; + this.swapChain = swapChain; + this.presentQueue = presentQueue; + pipelineCache = new PipelineCache (dev); + + descriptorPool = new DescriptorPool (dev, 3, + new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer, 3), + new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 6), + new VkDescriptorPoolSize (VkDescriptorType.InputAttachment, 5) + ); + + uboMatrices = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, matrices, true); + uboLights = new HostBuffer<Light> (dev, VkBufferUsageFlags.UniformBuffer, lights, true); + shadowMapRenderer = new ShadowMapRenderer (dev, this, 32); + + init (nearPlane, farPlane, cubemapPath); + + dev.WaitIdle (); + } + UInt32[] multiViewMasks = new UInt32[] { + 0b0001, + 0b0001, + 0b0011, + 0b0001 + }; + VkRenderPassMultiviewCreateInfo ciMultiview; + + void init_renderpass () { + ciMultiview = VkRenderPassMultiviewCreateInfo.New(); + ciMultiview.subpassCount = 4; + + renderPass = new RenderPass (dev, NUM_SAMPLES); + + renderPass.AddAttachment (HDR_FORMAT, VkImageLayout.ShaderReadOnlyOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.Store, VkImageLayout.ShaderReadOnlyOptimal);//hdr color + renderPass.AddAttachment (dev.GetSuitableDepthFormat (), VkImageLayout.DepthStencilAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare); + renderPass.AddAttachment (swapChain.ColorFormat, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff0 (color + roughness) and final color before resolve + renderPass.AddAttachment (VkFormat.R8g8b8a8Unorm, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff1 (emit + metal) + renderPass.AddAttachment (MRT_FORMAT, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff2 (normals + AO) + renderPass.AddAttachment (MRT_FORMAT, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff3 (Pos + depth) + + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + renderPass.ClearValues.Add (new VkClearValue { depthStencil = new VkClearDepthStencilValue (1.0f, 0) }); + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) }); + + SubPass[] subpasses = { new SubPass (), new SubPass (), new SubPass (), new SubPass () }; + //skybox + subpasses[SP_SKYBOX].AddColorReference (0, VkImageLayout.ColorAttachmentOptimal); + + //depth pre pass + subpasses [SP_DEPTH_PREPASS].SetDepthReference (1, VkImageLayout.DepthStencilAttachmentOptimal); + subpasses [SP_DEPTH_PREPASS].AddPreservedReference (0); + //models + subpasses [SP_MODELS].AddColorReference (new VkAttachmentReference (2, VkImageLayout.ColorAttachmentOptimal), + new VkAttachmentReference (3, VkImageLayout.ColorAttachmentOptimal), + new VkAttachmentReference (4, VkImageLayout.ColorAttachmentOptimal), + new VkAttachmentReference (5, VkImageLayout.ColorAttachmentOptimal)); + subpasses[SP_MODELS].SetDepthReference (1, VkImageLayout.DepthStencilAttachmentOptimal); + subpasses[SP_MODELS].AddPreservedReference (0); + + //compose + subpasses[SP_COMPOSE].AddColorReference (0, VkImageLayout.ColorAttachmentOptimal); + subpasses[SP_COMPOSE].AddInputReference (new VkAttachmentReference (2, VkImageLayout.ShaderReadOnlyOptimal), + new VkAttachmentReference (3, VkImageLayout.ShaderReadOnlyOptimal), + new VkAttachmentReference (4, VkImageLayout.ShaderReadOnlyOptimal), + new VkAttachmentReference (5, VkImageLayout.ShaderReadOnlyOptimal)); + //tone mapping + /*subpasses[SP_TONE_MAPPING].AddColorReference ((NUM_SAMPLES == VkSampleCountFlags.SampleCount1) ? 0u : 2u, VkImageLayout.ColorAttachmentOptimal); + subpasses[SP_TONE_MAPPING].AddInputReference (new VkAttachmentReference (6, VkImageLayout.ShaderReadOnlyOptimal)); + if (NUM_SAMPLES != VkSampleCountFlags.SampleCount1) + subpasses[SP_TONE_MAPPING].AddResolveReference (0, VkImageLayout.ColorAttachmentOptimal);*/ + + renderPass.AddSubpass (subpasses); + + renderPass.AddDependency (Vk.SubpassExternal, SP_SKYBOX, + VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput, + VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); + renderPass.AddDependency (SP_SKYBOX, SP_DEPTH_PREPASS, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, + VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); + renderPass.AddDependency (SP_DEPTH_PREPASS, SP_MODELS, + VkPipelineStageFlags.EarlyFragmentTests, VkPipelineStageFlags.FragmentShader, + VkAccessFlags.DepthStencilAttachmentWrite, VkAccessFlags.ShaderRead); + renderPass.AddDependency (SP_MODELS, SP_COMPOSE, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader, + VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead); + renderPass.AddDependency (SP_COMPOSE, Vk.SubpassExternal, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.Transfer, + VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.TransferRead); + } + + void init (float nearPlane, float farPlane, string cubemapPath) { + init_renderpass (); + + descLayoutMain = new DescriptorSetLayout (dev, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer),//matrices and params + new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//irradiance + new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//prefil + new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//lut brdf + new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer),//lights + new VkDescriptorSetLayoutBinding (5, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer),//materials + new VkDescriptorSetLayoutBinding (6, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//shadow map + new VkDescriptorSetLayoutBinding (7, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)//texture array + //new VkDescriptorSetLayoutBinding (8, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) + );//uiImage + + descLayoutGBuff = new DescriptorSetLayout (dev, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//color + roughness + new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//emit + metal + new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//normals + AO + new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//Pos + depth + new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment));//hdr + + descLayoutMain.SetName ("main"); + descLayoutGBuff.SetName ("GBuff"); + + ciMultiview.pViewMasks = multiViewMasks.Pin (); + //renderPass.PNext = new PNextNode<VkRenderPassMultiviewCreateInfo> (ciMultiview); + + using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, NUM_SAMPLES)) { + + cfg.rasterizationState.cullMode = VkCullModeFlags.None; + + if (NUM_SAMPLES != VkSampleCountFlags.SampleCount1) { + cfg.multisampleState.sampleShadingEnable = true; + cfg.multisampleState.minSampleShading = 0.5f; + } + cfg.Cache = pipelineCache; + cfg.Layout = new PipelineLayout (dev, + new VkPushConstantRange[] { + new VkPushConstantRange (VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf<Matrix4x4> ()), + new VkPushConstantRange (VkShaderStageFlags.Fragment, sizeof (int), 64)}, + descLayoutMain, descLayoutGBuff); + + cfg.RenderPass = renderPass; + //cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); + + cfg.AddVertexBinding<PbrModelTexArray.Vertex> (0); + cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat, VkFormat.R32g32Sfloat); + + cfg.AddVertexBinding<VkChess.InstanceData> (1, VkVertexInputRate.Instance); + cfg.AddVertexAttributes (1, VkFormat.R32g32b32a32Sfloat, VkFormat.R32g32b32a32Sfloat, VkFormat.R32g32b32a32Sfloat, VkFormat.R32g32b32a32Sfloat, VkFormat.R32g32b32a32Sfloat); + + using (SpecializationInfo constants = new SpecializationInfo ( + new SpecializationConstant<float> (0, nearPlane), + new SpecializationConstant<float> (1, farPlane), + new SpecializationConstant<int> (2, MAX_MATERIAL_COUNT))) { + cfg.AddShader (dev, VkShaderStageFlags.Vertex, "#vkChess.net.GBuffPbrInstanced.vert.spv"); + + cfg.SubpassIndex = SP_DEPTH_PREPASS; + depthPrepassPipeline = new GraphicPipeline (cfg, "Depth prepass"); + + cfg.depthStencilState.depthCompareOp = VkCompareOp.Equal; + cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); + cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); + cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); + + cfg.SubpassIndex = SP_MODELS; + + cfg.AddShader (dev, VkShaderStageFlags.Fragment, "#vkChess.net.GBuffPbrTexArray.frag.spv", constants); + + gBuffPipeline = new GraphicPipeline (cfg, "GBuff"); + } + cfg.rasterizationState.cullMode = VkCullModeFlags.Front; + //COMPOSE PIPELINE + cfg.blendAttachments.Clear (); + cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false)); + + cfg.ResetShadersAndVerticesInfos (); + + cfg.SubpassIndex = SP_COMPOSE; + cfg.Layout = gBuffPipeline.Layout; + cfg.depthStencilState.depthTestEnable = false; + cfg.depthStencilState.depthWriteEnable = false; + using (SpecializationInfo constants = new SpecializationInfo ( + new SpecializationConstant<uint> (0, (uint)lights.Length), + new SpecializationConstant<float> (1, 0.25f))) { + cfg.AddShader (dev, VkShaderStageFlags.Vertex, "#vke.FullScreenQuad.vert.spv"); + cfg.AddShader (dev, VkShaderStageFlags.Fragment, "#vkChess.net.compose_with_shadows.frag.spv", constants); + composePipeline = new GraphicPipeline (cfg, "compose"); + } + //DEBUG DRAW use subpass of compose + cfg.ReplaceShader (1, new ShaderInfo (dev, VkShaderStageFlags.Fragment, "#vkChess.net.show_gbuff.frag.spv")); + cfg.SubpassIndex = SP_COMPOSE; + debugPipeline = new GraphicPipeline (cfg, "debug"); + //TONE MAPPING + /*cfg.ReplaceShader (1, new ShaderInfo (dev, VkShaderStageFlags.Fragment, "#vkChess.net.tone_mapping.frag.spv")); + cfg.SubpassIndex = SP_TONE_MAPPING; + toneMappingPipeline = new GraphicPipeline (cfg, "tonne mapping");*/ + } + + dsMain = descriptorPool.Allocate (descLayoutMain); + dsGBuff = descriptorPool.Allocate (descLayoutGBuff); + + envCube = new vke.Environment.EnvironmentCube (cubemapPath, gBuffPipeline.Layout, presentQueue, renderPass); + + matrices.prefilteredCubeMipLevels = envCube.prefilterCube.CreateInfo.mipLevels; + + DescriptorSetWrites dsMainWrite = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings.GetRange (0, 5).ToArray ()); + dsMainWrite.Write (dev, + uboMatrices.Descriptor, + envCube.irradianceCube.Descriptor, + envCube.prefilterCube.Descriptor, + envCube.lutBrdf.Descriptor, + uboLights.Descriptor); + + dsMainWrite = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[6]); + dsMainWrite.Write (dev, shadowMapRenderer.shadowMap.Descriptor); + + multiViewMasks.Unpin (); + + } + + public void LoadModel (Queue transferQ, string path) { + dev.WaitIdle (); + + model?.Dispose (); + model = new PbrModelTexArray (transferQ, path); + + DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[5], descLayoutMain.Bindings[7]); + uboUpdate.Write (dev, model.materialUBO.Descriptor, (model as PbrModelTexArray).texArray.Descriptor); + + modelAABB = model.DefaultScene.AABB; + } + + public void recordDraw (PrimaryCommandBuffer cmd, int imageIndex, vke.Buffer instanceBuf = null, params Model.InstancedCmd[] instances) { + FrameBuffer fb = frameBuffers[imageIndex]; + renderPass.Begin(cmd, fb); + + cmd.SetViewport(fb.Width, fb.Height); + cmd.SetScissor(fb.Width, fb.Height); + + cmd.BindDescriptorSet(gBuffPipeline.Layout, dsMain); + + envCube.RecordDraw(cmd); + renderPass.BeginSubPass(cmd); + + if (model != null) { + model.Bind (cmd); + + depthPrepassPipeline.Bind (cmd); + if (instanceBuf != null) + model.Draw (cmd, gBuffPipeline.Layout, instanceBuf, false, instances); + + renderPass.BeginSubPass (cmd); + gBuffPipeline.Bind(cmd); + + if (instanceBuf != null) + model.Draw(cmd, gBuffPipeline.Layout, instanceBuf, false, instances); + } + renderPass.BeginSubPass(cmd); + + cmd.BindDescriptorSet(composePipeline.Layout, dsGBuff, 1); + + if (currentDebugView == DebugView.none) + composePipeline.Bind(cmd); + else { + debugPipeline.Bind(cmd); + uint debugValue = (uint)currentDebugView - 1; + if (currentDebugView == DebugView.shadowMap) + debugValue += (uint)((lightNumDebug << 8)); + else + debugValue += (uint)((debugFace << 8) + (debugMip << 16)); + cmd.PushConstant(debugPipeline.Layout, VkShaderStageFlags.Fragment, debugValue, (uint)Marshal.SizeOf<Matrix4x4>()); + } + + cmd.Draw(3, 1, 0, 0); + + /*renderPass.BeginSubPass(cmd); + toneMappingPipeline.Bind(cmd); + cmd.Draw(3, 1, 0, 0);*/ + + renderPass.End(cmd); + } + + public void MoveLight (Vector4 dir) { + lights[lightNumDebug].position += dir * lightMoveSpeed; + shadowMapRenderer.updateShadowMap = true; + } + + #region update + public void UpdateView (Camera camera) { + camera.AspectRatio = (float)swapChain.Width / swapChain.Height; + + matrices.projection = camera.Projection; + matrices.view = camera.View; + matrices.model = camera.Model; + + Matrix4x4.Invert (camera.View, out Matrix4x4 inv); + matrices.camPos = new Vector4 (inv.M41, inv.M42, inv.M43, 0); + + uboMatrices.Update (matrices, (uint)Marshal.SizeOf<Matrices> ()); + shadowMapRenderer.updateShadowMap = true; + } + + #endregion + + void createGBuff () { + gbColorRough?.Dispose (); + gbEmitMetal?.Dispose (); + gbN_AO?.Dispose (); + gbPos?.Dispose (); + hdrImg?.Dispose (); + + uint layerCount = 1; + + gbColorRough = new Image (dev, swapChain.ColorFormat, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, NUM_SAMPLES, VkImageTiling.Optimal, 1, layerCount); + gbEmitMetal = new Image (dev, VkFormat.R8g8b8a8Unorm, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, NUM_SAMPLES, VkImageTiling.Optimal, 1, layerCount); + gbN_AO = new Image (dev, MRT_FORMAT, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, NUM_SAMPLES, VkImageTiling.Optimal, 1, layerCount); + gbPos = new Image (dev, MRT_FORMAT, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment, VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, NUM_SAMPLES, VkImageTiling.Optimal, 1, layerCount); + hdrImg = new Image (dev, HDR_FORMAT, VkImageUsageFlags.InputAttachment | VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.TransientAttachment | VkImageUsageFlags.Sampled, VkMemoryPropertyFlags.DeviceLocal | VkMemoryPropertyFlags.DeviceLocal, swapChain.Width, swapChain.Height, VkImageType.Image2D, NUM_SAMPLES, VkImageTiling.Optimal, 1, 1); + + gbColorRough.CreateView (); + gbColorRough.CreateSampler (); + gbColorRough.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + gbEmitMetal.CreateView (); + gbEmitMetal.CreateSampler (); + gbEmitMetal.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + gbN_AO.CreateView (); + gbN_AO.CreateSampler (); + gbN_AO.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + gbPos.CreateView (); + gbPos.CreateSampler (); + gbPos.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + hdrImg.CreateView (); + hdrImg.CreateSampler (); + hdrImg.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + + DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descLayoutGBuff); + uboUpdate.Write (dev, dsGBuff, gbColorRough.Descriptor, + gbEmitMetal.Descriptor, + gbN_AO.Descriptor, + gbPos.Descriptor, + hdrImg.Descriptor); + gbColorRough.SetName ("GBuffColorRough"); + gbEmitMetal.SetName ("GBuffEmitMetal"); + gbN_AO.SetName ("GBuffN"); + gbPos.SetName ("GBuffPos"); + hdrImg.SetName ("HDRimg"); + } + + public void Resize () { + frameBuffers?.Dispose (); + frameBuffers = new FrameBuffers (); + + createGBuff (); + + for (int i = 0; i < swapChain.ImageCount; ++i) { + frameBuffers.Add (new FrameBuffer (renderPass, swapChain.Width, swapChain.Height, 1, new Image [] { + hdrImg, null, gbColorRough, gbEmitMetal, gbN_AO, gbPos})); + } + //frameBuffers = renderPass.CreateFrameBuffers (swapChain); + } + + public void Dispose () { + dev.WaitIdle (); + + frameBuffers?.Dispose (); + + gbColorRough.Dispose (); + gbEmitMetal.Dispose (); + gbN_AO.Dispose (); + gbPos.Dispose (); + hdrImg.Dispose (); + + gBuffPipeline.Dispose (); + composePipeline.Dispose (); + debugPipeline.Dispose (); + depthPrepassPipeline.Dispose (); + + descLayoutMain.Dispose (); + descLayoutGBuff.Dispose (); + + uboMatrices.Dispose (); + uboLights.Dispose (); + model.Dispose (); + envCube.Dispose (); + shadowMapRenderer.Dispose (); + + descriptorPool.Dispose (); + } + } +} diff --git a/src/shadowMapRenderer.cs b/src/shadowMapRenderer.cs index 2db9969..c9cef4b 100644 --- a/src/shadowMapRenderer.cs +++ b/src/shadowMapRenderer.cs @@ -9,7 +9,7 @@ using System.Runtime.InteropServices; using vke; using vke.glTF; using Vulkan; -using static vkChess.DeferredPbrRenderer; +using static vkChess.DeferredPbrRendererBase; namespace vkChess { public class ShadowMapRenderer : IDisposable { @@ -33,9 +33,9 @@ namespace vkChess { DescriptorPool descriptorPool; DescriptorSetLayout descLayoutShadow; DescriptorSet dsShadow; - DeferredPbrRenderer renderer; + DeferredPbrRendererBase renderer; - public ShadowMapRenderer (Device dev, DeferredPbrRenderer renderer, float farPlane = 16f) { + public ShadowMapRenderer (Device dev, DeferredPbrRendererBase renderer, float farPlane = 16f) { this.lightFarPlane = farPlane; this.dev = dev; this.renderer = renderer; diff --git a/vkChess.net.csproj b/vkChess.net.csproj index 17314a1..3337014 100644 --- a/vkChess.net.csproj +++ b/vkChess.net.csproj @@ -18,7 +18,8 @@ <EmbeddedResource Include="ui\*.style" /> </ItemGroup> <ItemGroup> - <PackageReference Include="VkCrowWindow" Version="0.3.1-beta" /> + <PackageReference Include="VkCrowWindow" Version="0.3.4-beta" /> + <PackageReference Include="vke" Version="0.2.2-beta" /> <PackageReference Include="SpirVTasks" Version="0.1.44" /> <PackageReference Include="vke.EnvironmentPipeline" Version="0.2.0-beta" /> <PackageReference Include="vke.gltfLoader" Version="0.2.0-beta" /> |