diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-08-03 19:49:15 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-08-03 19:49:15 +0200 |
| commit | e6030fa04a8de3fdae1dc19d081bf5feb3d3d73c (patch) | |
| tree | 89f392cd974d1109a203ade305da467bd378ee48 /Samples/main.cs | |
| parent | cad504c62d45952b4651603579f34df0d230841e (diff) | |
sample directory
Diffstat (limited to 'Samples/main.cs')
| -rw-r--r-- | Samples/main.cs | 564 |
1 files changed, 564 insertions, 0 deletions
diff --git a/Samples/main.cs b/Samples/main.cs new file mode 100644 index 00000000..46a89038 --- /dev/null +++ b/Samples/main.cs @@ -0,0 +1,564 @@ +using System; +using System.Numerics; +using System.Runtime.InteropServices; +using Glfw; +using VK; +using CVKL; +using System.Threading; + +namespace pbrSachaWillem { + class Program : VkWindow, Crow.IValueChange { + static void Main (string[] args) { + using (Program vke = new Program ()) { + vke.Run (); + } + } + bool isRunning; + + protected override void render () { + int idx = swapChain.GetNextImage (); + + lock (crow.RenderMutex) { + if (idx < 0) { + OnResize (); + return; + } + + presentQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx]); + presentQueue.Present (swapChain, drawComplete[idx]); + presentQueue.WaitIdle (); + } + } + + #region crow + + void crow_thread_func () { + vkvgDev = new vkvg.Device (instance.Handle, phy.Handle, dev.VkDev.Handle, presentQueue.qFamIndex, + vkvg.SampleCount.Sample_4, presentQueue.index); + + crow = new Crow.Interface (vkvgDev, 800, 600); + + isRunning = true; + //int frameCount = 0; + + while (isRunning) { + crow.Update (); + + /*if (frameCount++ > 100) { + for (int i = 0; i < crow.PerfMeasures.Count; i++) + crow.PerfMeasures[i].NotifyChanges (); + frameCount = 0; + }*/ + + Thread.Sleep (2); + } + dev.WaitIdle (); + crow.Dispose (); + vkvgDev.Dispose (); + } + + #region IValueChange implementation + public event EventHandler<Crow.ValueChangeEventArgs> ValueChanged; + public virtual void NotifyValueChanged(string MemberName, object _value) + { + if (ValueChanged != null) + ValueChanged.Invoke(this, new Crow.ValueChangeEventArgs(MemberName, _value)); + } + #endregion + + public float Gamma { + get { return pbrPipeline.matrices.gamma; } + set { + if (value == pbrPipeline.matrices.gamma) + return; + pbrPipeline.matrices.gamma = value; + NotifyValueChanged ("Gamma", value); + updateViewRequested = true; + } + } + public float Exposure { + get { return pbrPipeline.matrices.exposure; } + set { + if (value == pbrPipeline.matrices.exposure) + return; + pbrPipeline.matrices.exposure = value; + NotifyValueChanged ("Exposure", value); + updateViewRequested = true; + } + } + Crow.Interface crow; + #endregion + + protected override void configureEnabledFeatures (VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures features) { + base.configureEnabledFeatures (available_features, ref features); +#if PIPELINE_STATS + features.pipelineStatisticsQuery = true; +#endif + features.samplerAnisotropy = true; + } + + VkSampleCountFlags samples = VkSampleCountFlags.SampleCount4; + + Framebuffer[] frameBuffers; + PBRPipeline pbrPipeline; + + enum DebugView { + none, + color, + normal, + occlusion, + emissive, + metallic, + roughness + } + + DebugView currentDebugView = DebugView.none; + +#if PIPELINE_STATS + PipelineStatisticsQueryPool statPool; + TimestampQueryPool timestampQPool; + ulong[] results; +#endif + + + bool queryUpdatePrefilCube, showDebugImg, showUI = true; + + + Image uiImage; + + #region ui + //DescriptorSet dsDebugImg; + //void initDebugImg () { + // dsDebugImg = descriptorPool.Allocate (descLayoutMain); + // pbrPipeline.envCube.debugImg.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + // DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsDebugImg, descLayoutMain); + // uboUpdate.Write (dev, pbrPipeline.envCube.debugImg.Descriptor); + //} + + vkvg.Device vkvgDev; + + Pipeline uiPipeline; + + void initUIPipeline () { + GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, samples, false); + cfg.RenderPass = pbrPipeline.RenderPass; + cfg.Layout = pbrPipeline.Layout; + cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/FullScreenQuad.vert.spv"); + cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/simpletexture.frag.spv"); + cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState (true); + + uiPipeline = new GraphicPipeline (cfg); + + } + void initUISurface () { + lock (crow.UpdateMutex) { + uiImage?.Dispose (); + uiImage = new CVKL.Image (dev, new VkImage ((ulong)crow.surf.VkImage.ToInt64 ()), VkFormat.B8g8r8a8Unorm, + VkImageUsageFlags.Sampled, swapChain.Width, swapChain.Height); + uiImage.SetName ("uiImage"); + uiImage.CreateView (VkImageViewType.ImageView2D, VkImageAspectFlags.Color); + uiImage.CreateSampler (VkFilter.Nearest, VkFilter.Nearest, VkSamplerMipmapMode.Nearest, VkSamplerAddressMode.ClampToBorder); + uiImage.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + } + } + + + void recordDrawOverlay (CommandBuffer cmd) { + uiPipeline.Bind (cmd); + + uiImage.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.ColorAttachmentOptimal, VkImageLayout.ShaderReadOnlyOptimal, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader); + + cmd.Draw (3, 1, 0, 0); + + uiImage.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.ShaderReadOnlyOptimal, VkImageLayout.ColorAttachmentOptimal, + VkPipelineStageFlags.FragmentShader, VkPipelineStageFlags.BottomOfPipe); + + //if (!showDebugImg) + // return; + //const uint debugImgSize = 256; + //const uint debugImgMargin = 10; + + //cmd.BindDescriptorSet (uiPipeline.Layout, dsDebugImg); + + //cmd.SetViewport (debugImgSize, debugImgSize, debugImgMargin, swapChain.Height - debugImgSize - debugImgMargin); + //cmd.SetScissor (debugImgSize, debugImgSize, (int)debugImgMargin, (int)(swapChain.Height - debugImgSize - debugImgMargin)); + + //cmd.Draw (3, 1, 0, 0); + } + #endregion + + + Vector4 lightPos = new Vector4 (1, 0, 0, 0); + BoundingBox modelAABB; + + Program () { + camera.SetPosition (0, 0, 5); + + Thread crowThread = new Thread (crow_thread_func); + crowThread.IsBackground = true; + crowThread.Start (); + + while (crow == null) + Thread.Sleep (5); + + initUISurface (); + + pbrPipeline = new PBRPipeline (presentQueue, + new RenderPass (dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat (), samples), uiImage); + + initUIPipeline (); + + modelAABB = pbrPipeline.model.DefaultScene.AABB; + + crow.Load ("ui/fps.crow").DataSource = this; + //crow.Load ("#vkvgCrowTest.perfMeasures.crow").DataSource = crow; + + //crow.LoadIMLFragment ("<Window Height='200' Width='200' CornerRadius='5'/>").DataSource=this; + //crow.LoadIMLFragment ("<Window Height='200' Width='200'/>").DataSource = this; + crow.LoadIMLFragment (@"<Image Margin='1' Path='/mnt/devel/gts/vk.net/crow/Images/crow.png' Width='100' Height='100' Background='White' MouseEnter='{Background=Blue}' MouseLeave='{Background=White}'/>"); + //crow.LoadIMLFragment ("<Window Height='200' Width='200'/>").DataSource = this; + UpdateFrequency = 20; + } + + void buildCommandBuffers () { + for (int i = 0; i < swapChain.ImageCount; ++i) { + cmds[i]?.Free (); + cmds[i] = cmdPool.AllocateAndStart (); +#if PIPELINE_STATS + statPool.Begin (cmds[i]); + recordDraw (cmds[i], frameBuffers[i]); + statPool.End (cmds[i]); +#else + recordDraw (cmds[i], frameBuffers[i]); +#endif + + cmds[i].End (); + } + } + void recordDraw (CommandBuffer cmd, Framebuffer fb) { + pbrPipeline.RenderPass.Begin (cmd, fb); + + cmd.SetViewport (fb.Width, fb.Height); + cmd.SetScissor (fb.Width, fb.Height); + + pbrPipeline.RecordDraw (cmd); + + if (showUI) + recordDrawOverlay (cmd); + + pbrPipeline.RenderPass.End (cmd); + } + + + #region update + public override void UpdateView () { + camera.AspectRatio = (float)swapChain.Width / swapChain.Height; + + pbrPipeline.matrices.lightDir = lightPos; + pbrPipeline.matrices.projection = camera.Projection; + pbrPipeline.matrices.view = camera.View; + pbrPipeline.matrices.model = camera.Model; + + + pbrPipeline.matrices.camPos = new Vector4 ( + -camera.Position.Z * (float)Math.Sin (camera.Rotation.Y) * (float)Math.Cos (camera.Rotation.X), + camera.Position.Z * (float)Math.Sin (camera.Rotation.X), + camera.Position.Z * (float)Math.Cos (camera.Rotation.Y) * (float)Math.Cos (camera.Rotation.X), + 0 + ); + pbrPipeline.matrices.debugViewInputs = (float)currentDebugView; + + pbrPipeline.uboMats.Update (pbrPipeline.matrices, (uint)Marshal.SizeOf<PBRPipeline.Matrices> ()); + + updateViewRequested = false; + } + + int frameCount = 0; + + public override void Update () { +#if PIPELINE_STATS + results = statPool.GetResults (); +#endif + camera.Model *= Matrix4x4.CreateRotationY(0.05f); + updateViewRequested = true; + + if (rebuildBuffers) { + buildCommandBuffers (); + rebuildBuffers = false; + } + + if (++frameCount > 20) { + NotifyValueChanged ("fps", fps); + frameCount = 0; + } + } + #endregion + + + protected override void OnResize () { + crow.ProcessResize (new Crow.Rectangle (0,0,(int)swapChain.Width, (int)swapChain.Height)); + + initUISurface (); + + uiImage.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + DescriptorSetWrites uboUpdate = new DescriptorSetWrites (pbrPipeline.dsMain, pbrPipeline.Layout.DescriptorSetLayouts[0].Bindings[5]); + uboUpdate.Write (dev, uiImage.Descriptor); + + UpdateView (); + + if (frameBuffers != null) + for (int i = 0; i < swapChain.ImageCount; ++i) + frameBuffers[i]?.Dispose (); + + frameBuffers = new Framebuffer[swapChain.ImageCount]; + + for (int i = 0; i < swapChain.ImageCount; ++i) { + frameBuffers[i] = new Framebuffer (pbrPipeline.RenderPass, swapChain.Width, swapChain.Height, + (pbrPipeline.RenderPass.Samples == VkSampleCountFlags.SampleCount1) ? new Image[] { + swapChain.images[i], + null + } : new Image[] { + null, + null, + swapChain.images[i] + }); + } + + buildCommandBuffers (); + } + + #region Mouse and keyboard + protected override void onMouseMove (double xPos, double yPos) { + if (crow.ProcessMouseMove ((int)xPos, (int)yPos)) + return; + + double diffX = lastMouseX - xPos; + double diffY = lastMouseY - yPos; + if (MouseButton[0]) { + camera.Rotate ((float)-diffX, (float)-diffY); + } else if (MouseButton[1]) { + camera.SetZoom ((float)diffY); + } else + return; + + updateViewRequested = true; + } + protected override void onMouseButtonDown (Glfw.MouseButton button) { + if (crow.ProcessMouseButtonDown ((Crow.MouseButton)button)) + return; + base.onMouseButtonDown (button); + } + protected override void onMouseButtonUp (Glfw.MouseButton button) { + if (crow.ProcessMouseButtonUp ((Crow.MouseButton)button)) + return; + base.onMouseButtonUp (button); + } + + protected override void onKeyDown (Key key, int scanCode, Modifier modifiers) { + switch (key) { + case Key.F: + if (modifiers.HasFlag (Modifier.Shift)) { + pbrPipeline.envCube.debugFace--; + if (pbrPipeline.envCube.debugFace < 0) + pbrPipeline.envCube.debugFace = 5; + } else { + pbrPipeline.envCube.debugFace++; + if (pbrPipeline.envCube.debugFace > 5) + pbrPipeline.envCube.debugFace = 0; + } + queryUpdatePrefilCube = updateViewRequested = true; + break; + case Key.M: + if (modifiers.HasFlag (Modifier.Shift)) { + pbrPipeline.envCube.debugMip--; + if (pbrPipeline.envCube.debugMip < 0) + pbrPipeline.envCube.debugMip = (int)pbrPipeline.envCube.prefilterCube.CreateInfo.mipLevels - 1; + } else { + pbrPipeline.envCube.debugMip++; + if (pbrPipeline.envCube.debugMip > pbrPipeline.envCube.prefilterCube.CreateInfo.mipLevels) + pbrPipeline.envCube.debugMip = 0; + } + queryUpdatePrefilCube = updateViewRequested = true; + break; + case Key.P: + showDebugImg = !showDebugImg; + queryUpdatePrefilCube = updateViewRequested = true; + break; + case Key.Keypad0: + currentDebugView = DebugView.none; + break; + case Key.Keypad1: + currentDebugView = DebugView.color; + break; + case Key.Keypad2: + currentDebugView = DebugView.normal; + break; + case Key.Keypad3: + currentDebugView = DebugView.occlusion; + break; + case Key.Keypad4: + currentDebugView = DebugView.emissive; + break; + case Key.Keypad5: + currentDebugView = DebugView.metallic; + break; + case Key.Keypad6: + currentDebugView = DebugView.roughness; + break; + case Key.Up: + if (modifiers.HasFlag (Modifier.Shift)) + lightPos -= Vector4.UnitZ; + else + camera.Move (0, 0, 1); + break; + case Key.Down: + if (modifiers.HasFlag (Modifier.Shift)) + lightPos += Vector4.UnitZ; + else + camera.Move (0, 0, -1); + break; + case Key.Left: + if (modifiers.HasFlag (Modifier.Shift)) + lightPos -= Vector4.UnitX; + else + camera.Move (1, 0, 0); + break; + case Key.Right: + if (modifiers.HasFlag (Modifier.Shift)) + lightPos += Vector4.UnitX; + else + camera.Move (-1, 0, 0); + break; + case Key.PageUp: + if (modifiers.HasFlag (Modifier.Shift)) + lightPos += Vector4.UnitY; + else + camera.Move (0, 1, 0); + break; + case Key.PageDown: + if (modifiers.HasFlag (Modifier.Shift)) + lightPos -= Vector4.UnitY; + else + camera.Move (0, -1, 0); + break; + case Key.F1: + showUI = !showUI; + rebuildBuffers = true; + break; + case Key.F2: + if (modifiers.HasFlag (Modifier.Shift)) + pbrPipeline.matrices.exposure -= 0.3f; + else + pbrPipeline.matrices.exposure += 0.3f; + break; + case Key.F3: + if (modifiers.HasFlag (Modifier.Shift)) + pbrPipeline.matrices.gamma -= 0.1f; + else + pbrPipeline.matrices.gamma += 0.1f; + break; + case Key.F4: + if (camera.Type == Camera.CamType.FirstPerson) + camera.Type = Camera.CamType.LookAt; + else + camera.Type = Camera.CamType.FirstPerson; + Console.WriteLine ($"camera type = {camera.Type}"); + break; + default: + base.onKeyDown (key, scanCode, modifiers); + return; + } + updateViewRequested = true; + } + #endregion + + #region dispose + protected override void Dispose (bool disposing) { + if (disposing) { + if (!isDisposed) { + dev.WaitIdle (); + + isRunning = false; + + for (int i = 0; i < swapChain.ImageCount; ++i) + frameBuffers[i]?.Dispose (); + + pbrPipeline.Dispose (); + + uiPipeline.Dispose (); + + uiImage?.Dispose (); + } + } + + base.Dispose (disposing); + } + #endregion + } +} + + + + + + + +// protected override void onKeyDown (Glfw.Key key, int scanCode, Modifier modifiers) { +// switch (key) { +// case Glfw.Key.F1: +// if (modifiers.HasFlag (Modifier.Shift)) +// pbrPipeline.matrices.exposure -= 0.3f; +// else +// pbrPipeline.matrices.exposure += 0.3f; +// break; +// case Glfw.Key.F2: +// if (modifiers.HasFlag (Modifier.Shift)) +// pbrPipeline.matrices.gamma -= 0.1f; +// else +// pbrPipeline.matrices.gamma += 0.1f; +// break; +// case Glfw.Key.F3: +// if (camera.Type == Camera.CamType.FirstPerson) +// camera.Type = Camera.CamType.LookAt; +// else +// camera.Type = Camera.CamType.FirstPerson; +// Console.WriteLine ($"camera type = {camera.Type}"); +// break; +// default: +// base.onKeyDown (key, scanCode, modifiers); +// return; +// } +// updateViewRequested = true; +// } +// #endregion + +// protected override void Dispose (bool disposing) { +// if (disposing) { +// if (!isDisposed) { +// dev.WaitIdle (); +// for (int i = 0; i < swapChain.ImageCount; ++i) +// frameBuffers[i]?.Dispose (); + +// pbrPipeline.Dispose (); + +// uiPipeline.Dispose (); +// descLayoutMain.Dispose (); +// descriptorPool.Dispose (); + +// uiImage.Dispose (); + +// crow.Dispose (); + +// vkvgDev.Dispose (); + + +// } +// } + +// base.Dispose (disposing); +// } + + +// } +//} |