]> O.S.I.I.S - jp/vke.net.git/commitdiff
update with latest modif from old vk.net branch
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 10 Sep 2019 03:02:43 +0000 (05:02 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Tue, 10 Sep 2019 03:02:43 +0000 (05:02 +0200)
45 files changed:
addons/Directory.Build.props
addons/EnvironmentPipeline/EnvironmentPipeline.cs [new file with mode: 0644]
addons/EnvironmentPipeline/EnvironmentPipeline.csproj [new file with mode: 0644]
addons/EnvironmentPipeline/shaders/filtercube.vert [new file with mode: 0644]
addons/EnvironmentPipeline/shaders/genbrdflut.frag [new file with mode: 0644]
addons/EnvironmentPipeline/shaders/genbrdflut.vert [new file with mode: 0644]
addons/EnvironmentPipeline/shaders/irradiancecube.frag [new file with mode: 0644]
addons/EnvironmentPipeline/shaders/prefilterenvmap.frag [new file with mode: 0644]
addons/EnvironmentPipeline/shaders/skybox.frag [new file with mode: 0644]
addons/EnvironmentPipeline/shaders/skybox.vert [new file with mode: 0644]
samples/Directory.Build.props
samples/DistanceFieldFontTest/Program.cs
samples/Model/main.cs
samples/Textured/main.cs
samples/TexturedCube/main.cs
samples/Triangle/main.cs
samples/common/CrowWin.cs
samples/deferred/main-crow.cs
samples/deferred/main.cs
samples/pbr/main.cs
samples/pbr/pbr.csproj
vke/src/MarshaledObject.cs
vke/src/MemoryPool.cs
vke/src/ResourceManager.cs
vke/src/ShaderInfo.cs
vke/src/VkWindow.cs
vke/src/base/Device.cs
vke/src/base/Queue.cs
vke/src/base/RenderPass.cs
vke/src/base/SwapChain.cs
vke/src/glfw/CodePoint.cs
vke/src/glfw/Delegates.cs
vke/src/glfw/ErrorCode.cs
vke/src/glfw/Glfw3.cs
vke/src/glfw/InputAction.cs
vke/src/glfw/Key.cs
vke/src/glfw/Modifier.cs
vke/src/glfw/MonitorEvent.cs
vke/src/glfw/MonitorHandle.cs
vke/src/glfw/MouseButton.cs
vke/src/glfw/NativeString.cs
vke/src/glfw/VideoMode.cs
vke/src/glfw/VideoModePointer.cs
vke/src/glfw/WindowAttribute.cs
vke/src/ktx.cs

index 0e3fb5578b152f357961464b0166b432e8c7990f..bce5b09d20aecb6d84c8bef86686cfee8ed2c0ef 100644 (file)
        </PropertyGroup>
        <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
                <DefineConstants>NETSTANDARD;NETSTANDARD2_0;WITH_SHADOWS;_WITH_VKVG</DefineConstants>    
-       </PropertyGroup>  
-       
-       <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">              
-               <ProjectReference Include="$(RootDirectory)vke\vke.csproj" />
-       </ItemGroup>    
-       <ItemGroup >            
-               <PackageReference Include="vke" Version="0.1.7-beta" Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "/>
-       </ItemGroup>    
+       </PropertyGroup>        
        
        <ItemGroup>
+               <PackageReference Include="vke" Version="0.1.7-beta" />
                <PackageReference Include="SpirVTasks" Version="0.1.9-beta" />        
                <PackageReference Include="Vulkan" Version="0.1.4" />
        </ItemGroup>    
diff --git a/addons/EnvironmentPipeline/EnvironmentPipeline.cs b/addons/EnvironmentPipeline/EnvironmentPipeline.cs
new file mode 100644 (file)
index 0000000..12a0df9
--- /dev/null
@@ -0,0 +1,318 @@
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using System.Runtime.InteropServices;
+using VK;
+
+namespace CVKL {
+       public class EnvironmentCube : GraphicPipeline {
+
+               GPUBuffer vboSkybox;
+
+               public Image cubemap { get; private set; }
+               public Image lutBrdf { get; private set; }
+               public Image irradianceCube { get; private set; }
+               public Image prefilterCube { get; set; }
+
+               public EnvironmentCube (string cubemapPath, DescriptorSet dsSkybox, PipelineLayout plLayout, Queue staggingQ, RenderPass renderPass, PipelineCache cache = null)
+               : base (renderPass, cache, "EnvCube pipeline") {
+
+                       using (CommandPool cmdPool = new CommandPool (staggingQ.Dev, staggingQ.index)) {
+
+                               vboSkybox = new GPUBuffer<float> (staggingQ, cmdPool, VkBufferUsageFlags.VertexBuffer, box_vertices);
+
+                               cubemap = KTX.KTX.Load (staggingQ, cmdPool, cubemapPath,
+                                       VkImageUsageFlags.Sampled, VkMemoryPropertyFlags.DeviceLocal, true);
+                               cubemap.CreateView (VkImageViewType.Cube, VkImageAspectFlags.Color);
+                               cubemap.CreateSampler (VkSamplerAddressMode.ClampToEdge);
+                               cubemap.SetName ("skybox Texture");
+                               cubemap.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
+
+                               GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, renderPass.Samples, false);
+                               cfg.RenderPass = renderPass;
+                               cfg.Layout = plLayout;
+                               cfg.AddVertexBinding (0, 3 * sizeof (float));
+                               cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat);
+                               cfg.AddShader (VkShaderStageFlags.Vertex, "#CVKLEnvironment.skybox.vert.spv");
+                               cfg.AddShader (VkShaderStageFlags.Fragment, "#CVKLEnvironment.skybox.frag.spv");
+                               cfg.multisampleState.rasterizationSamples = Samples;
+
+                               layout = cfg.Layout;
+
+                               init (cfg);
+
+                               generateBRDFLUT (staggingQ, cmdPool);
+                               generateCubemaps (staggingQ, cmdPool);
+                       }
+
+               }
+
+               public void RecordDraw (CommandBuffer cmd) {
+                       Bind (cmd);
+                       cmd.BindVertexBuffer (vboSkybox);
+                       cmd.Draw (36);
+               }
+
+               #region skybox
+
+               static float[] box_vertices = {
+                        1.0f, 1.0f,-1.0f,  // +X side
+                        1.0f, 1.0f, 1.0f,
+                        1.0f,-1.0f, 1.0f,
+                        1.0f,-1.0f, 1.0f,
+                        1.0f,-1.0f,-1.0f,
+                        1.0f, 1.0f,-1.0f,
+
+                       -1.0f,-1.0f,-1.0f,      // +X side
+                       -1.0f,-1.0f, 1.0f,
+                       -1.0f, 1.0f, 1.0f,
+                       -1.0f, 1.0f, 1.0f,
+                       -1.0f, 1.0f,-1.0f,
+                       -1.0f,-1.0f,-1.0f,
+
+                       -1.0f, 1.0f,-1.0f,  // +Y side
+                       -1.0f, 1.0f, 1.0f,
+                        1.0f, 1.0f, 1.0f,
+                       -1.0f, 1.0f,-1.0f,
+                        1.0f, 1.0f, 1.0f,
+                        1.0f, 1.0f,-1.0f,
+
+                       -1.0f,-1.0f,-1.0f,  // -Y side
+                        1.0f,-1.0f,-1.0f,
+                        1.0f,-1.0f, 1.0f,
+                       -1.0f,-1.0f,-1.0f,
+                        1.0f,-1.0f, 1.0f,
+                       -1.0f,-1.0f, 1.0f,
+
+                       -1.0f, 1.0f, 1.0f,  // +Z side
+                       -1.0f,-1.0f, 1.0f,
+                        1.0f, 1.0f, 1.0f,
+                       -1.0f,-1.0f, 1.0f,
+                        1.0f,-1.0f, 1.0f,
+                        1.0f, 1.0f, 1.0f,
+
+                       -1.0f,-1.0f,-1.0f,  // -Z side
+                        1.0f, 1.0f,-1.0f,
+                        1.0f,-1.0f,-1.0f,
+                       -1.0f,-1.0f,-1.0f,
+                       -1.0f, 1.0f,-1.0f,
+                        1.0f, 1.0f,-1.0f,
+
+               };
+               #endregion
+
+               void generateBRDFLUT (Queue staggingQ, CommandPool cmdPool) {
+                       const VkFormat format = VkFormat.R16g16Sfloat;
+                       const int dim = 512;
+
+                       lutBrdf = new Image (Dev, format, VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.Sampled,
+                               VkMemoryPropertyFlags.DeviceLocal, dim, dim);
+                       lutBrdf.SetName ("lutBrdf");
+
+                       lutBrdf.CreateView ();
+                       lutBrdf.CreateSampler (VkSamplerAddressMode.ClampToEdge);
+
+                       GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false);
+
+                       cfg.Layout = new PipelineLayout (Dev, new DescriptorSetLayout (Dev));
+                       cfg.RenderPass = new RenderPass (Dev);
+                       cfg.RenderPass.AddAttachment (format, VkImageLayout.ShaderReadOnlyOptimal);
+                       cfg.RenderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0, 0, 0) });
+                       cfg.RenderPass.AddSubpass (new SubPass (VkImageLayout.ColorAttachmentOptimal));
+                       cfg.AddShader (VkShaderStageFlags.Vertex, "#CVKLEnvironment.genbrdflut.vert.spv");
+                       cfg.AddShader (VkShaderStageFlags.Fragment, "#CVKLEnvironment.genbrdflut.frag.spv");
+
+                       using (GraphicPipeline pl = new GraphicPipeline (cfg)) {
+                               using (Framebuffer fb = new Framebuffer (cfg.RenderPass, dim, dim, lutBrdf)) {
+                                       CommandBuffer cmd = cmdPool.AllocateCommandBuffer ();
+                                       cmd.Start (VkCommandBufferUsageFlags.OneTimeSubmit);
+                                       pl.RenderPass.Begin (cmd, fb);
+                                       cmd.SetViewport (dim, dim);
+                                       cmd.SetScissor (dim, dim);
+                                       pl.Bind (cmd);
+                                       cmd.Draw (3, 1, 0, 0);
+                                       pl.RenderPass.End (cmd);
+                                       cmd.End ();
+
+                                       staggingQ.Submit (cmd);
+                                       staggingQ.WaitIdle ();
+
+                                       cmd.Free ();
+                               }
+                       }
+                       lutBrdf.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
+               }
+
+               public enum CBTarget { IRRADIANCE = 0, PREFILTEREDENV = 1 };
+
+               public Image generateCubeMap (Queue staggingQ, CommandPool cmdPool, CBTarget target) {
+                       const float deltaPhi = (2.0f * (float)Math.PI) / 180.0f;
+                       const float deltaTheta = (0.5f * (float)Math.PI) / 64.0f;
+
+                       VkFormat format = VkFormat.R32g32b32a32Sfloat;
+                       uint dim = 64;
+
+                       if (target == CBTarget.PREFILTEREDENV) {
+                               format = VkFormat.R16g16b16a16Sfloat;
+                               dim = 512;
+                       }
+
+                       uint numMips = (uint)Math.Floor (Math.Log (dim, 2)) + 1;
+
+                       Image imgFbOffscreen = new Image (Dev, format, VkImageUsageFlags.TransferSrc | VkImageUsageFlags.ColorAttachment,
+                               VkMemoryPropertyFlags.DeviceLocal, dim, dim);
+                       imgFbOffscreen.SetName ("offscreenfb");
+                       imgFbOffscreen.CreateView ();
+
+                       Image cmap = new Image (Dev, format, VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled,
+                               VkMemoryPropertyFlags.DeviceLocal, dim, dim, VkImageType.Image2D, VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal,
+                               numMips, 6, 1, VkImageCreateFlags.CubeCompatible);
+                       if (target == CBTarget.PREFILTEREDENV)
+                               cmap.SetName ("prefilterenvmap");
+                       else
+                               cmap.SetName ("irradianceCube");
+                       cmap.CreateView (VkImageViewType.Cube, VkImageAspectFlags.Color, 6, 0);
+                       cmap.CreateSampler (VkSamplerAddressMode.ClampToEdge);
+
+                       DescriptorPool dsPool = new DescriptorPool (Dev, 2, new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler));
+
+                       DescriptorSetLayout dsLayout = new DescriptorSetLayout (Dev,
+                               new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler));
+
+
+                       GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false);
+                       cfg.Layout = new PipelineLayout (Dev, dsLayout);
+                       cfg.Layout.AddPushConstants (
+                               new VkPushConstantRange (VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, (uint)Marshal.SizeOf<Matrix4x4> () + 8));
+
+                       cfg.RenderPass = new RenderPass (Dev);
+                       cfg.RenderPass.AddAttachment (format, VkImageLayout.ColorAttachmentOptimal);
+                       cfg.RenderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0, 0, 0) });
+                       cfg.RenderPass.AddSubpass (new SubPass (VkImageLayout.ColorAttachmentOptimal));
+
+                       cfg.AddVertexBinding (0, 3 * sizeof (float));
+                       cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat);
+
+                       cfg.AddShader (VkShaderStageFlags.Vertex, "#CVKLEnvironment.filtercube.vert.spv");
+                       if (target == CBTarget.PREFILTEREDENV)
+                               cfg.AddShader (VkShaderStageFlags.Fragment, "#CVKLEnvironment.prefilterenvmap.frag.spv");
+                       else
+                               cfg.AddShader (VkShaderStageFlags.Fragment, "#CVKLEnvironment.irradiancecube.frag.spv");
+
+                       Matrix4x4[] matrices = {
+                               // POSITIVE_X
+                               Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)) * Matrix4x4.CreateRotationY(Utils.DegreesToRadians(90)),
+                               // NEGATIVE_X
+                               Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)) * Matrix4x4.CreateRotationY(Utils.DegreesToRadians(-90)),
+                               // POSITIVE_Y
+                               Matrix4x4.CreateRotationX(Utils.DegreesToRadians(-90)),
+                               // NEGATIVE_Y
+                               Matrix4x4.CreateRotationX(Utils.DegreesToRadians(90)),
+                               // POSITIVE_Z
+                               Matrix4x4.CreateRotationX(Utils.DegreesToRadians(180)),
+                               // NEGATIVE_Z
+                               Matrix4x4.CreateRotationZ(Utils.DegreesToRadians(180))
+                       };
+
+                       VkImageSubresourceRange subRes = new VkImageSubresourceRange (VkImageAspectFlags.Color, 0, numMips, 0, 6);
+
+                       using (GraphicPipeline pl = new GraphicPipeline (cfg)) {
+
+                               DescriptorSet dset = dsPool.Allocate (dsLayout);
+                               DescriptorSetWrites dsUpdate = new DescriptorSetWrites (dsLayout);
+                               dsUpdate.Write (Dev, dset, cubemap.Descriptor);
+                               Dev.WaitIdle ();
+
+                               using (Framebuffer fb = new Framebuffer (pl.RenderPass, dim, dim, imgFbOffscreen)) {
+                                       CommandBuffer cmd = cmdPool.AllocateCommandBuffer ();
+                                       cmd.Start (VkCommandBufferUsageFlags.OneTimeSubmit);
+
+                                       cmap.SetLayout (cmd, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, subRes);
+
+                                       float roughness = 0;
+
+                                       cmd.SetScissor (dim, dim);
+                                       cmd.SetViewport ((float)(dim), (float)dim);
+
+                                       for (int m = 0; m < numMips; m++) {
+                                               roughness = (float)m / ((float)numMips - 1f);
+
+                                               for (int f = 0; f < 6; f++) {
+                                                       pl.RenderPass.Begin (cmd, fb);
+
+                                                       pl.Bind (cmd);
+
+                                                       float viewPortSize = (float)Math.Pow (0.5, m) * dim;
+                                                       cmd.SetViewport (viewPortSize, viewPortSize);
+                                                       cmd.PushConstant (pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment,
+                                                               matrices[f] * Matrix4x4.CreatePerspectiveFieldOfView (Utils.DegreesToRadians (90), 1f, 0.1f, 512f));
+                                                       if (target == CBTarget.IRRADIANCE) {
+                                                               cmd.PushConstant (pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, deltaPhi, (uint)Marshal.SizeOf<Matrix4x4> ());
+                                                               cmd.PushConstant (pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, deltaTheta, (uint)Marshal.SizeOf<Matrix4x4> () + 4);
+                                                       } else {
+                                                               cmd.PushConstant (pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, roughness, (uint)Marshal.SizeOf<Matrix4x4> ());
+                                                               cmd.PushConstant (pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, 64u, (uint)Marshal.SizeOf<Matrix4x4> () + 4);
+                                                       }
+
+                                                       cmd.BindDescriptorSet (pl.Layout, dset);
+                                                       cmd.BindVertexBuffer (vboSkybox);
+                                                       cmd.Draw (36);
+
+                                                       pl.RenderPass.End (cmd);
+
+                                                       imgFbOffscreen.SetLayout (cmd, VkImageAspectFlags.Color,
+                                                               VkImageLayout.ColorAttachmentOptimal, VkImageLayout.TransferSrcOptimal);
+
+                                                       VkImageCopy region = new VkImageCopy ();
+                                                       region.srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1);
+                                                       region.dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, (uint)m, (uint)f);
+                                                       region.extent = new VkExtent3D { width = (uint)viewPortSize, height = (uint)viewPortSize, depth = 1 };
+
+                                                       Vk.vkCmdCopyImage (cmd.Handle,
+                                                               imgFbOffscreen.Handle, VkImageLayout.TransferSrcOptimal,
+                                                               cmap.Handle, VkImageLayout.TransferDstOptimal,
+                                                               1, region.Pin ());
+                                                       region.Unpin ();
+
+                                                       imgFbOffscreen.SetLayout (cmd, VkImageAspectFlags.Color,
+                                                               VkImageLayout.TransferSrcOptimal, VkImageLayout.ColorAttachmentOptimal);
+
+                                               }
+                                       }
+
+                                       cmap.SetLayout (cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal, subRes);
+
+                                       cmd.End ();
+
+                                       staggingQ.Submit (cmd);
+                                       staggingQ.WaitIdle ();
+
+                                       cmd.Free ();
+                               }
+                       }
+                       cmap.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
+
+                       dsLayout.Dispose ();
+                       imgFbOffscreen.Dispose ();
+                       dsPool.Dispose ();
+
+                       return cmap;
+               }
+
+               void generateCubemaps (Queue staggingQ, CommandPool cmdPool) {
+                       irradianceCube = generateCubeMap (staggingQ, cmdPool, CBTarget.IRRADIANCE);
+                       prefilterCube = generateCubeMap (staggingQ, cmdPool, CBTarget.PREFILTEREDENV);
+               }
+
+               protected override void Dispose (bool disposing) {
+                       vboSkybox.Dispose ();
+                       cubemap.Dispose ();
+                       lutBrdf.Dispose ();
+                       irradianceCube.Dispose ();
+                       prefilterCube.Dispose ();
+
+                       base.Dispose (disposing);
+               }
+       }
+
+}
diff --git a/addons/EnvironmentPipeline/EnvironmentPipeline.csproj b/addons/EnvironmentPipeline/EnvironmentPipeline.csproj
new file mode 100644 (file)
index 0000000..511e55b
--- /dev/null
@@ -0,0 +1,20 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <Import Project="$(RootDirectory)netfx.props" />
+  <PropertyGroup>
+    <AssemblyName>CVKLEnvironment</AssemblyName>
+    <PackageId>CVKLEnvironmentPipeline</PackageId>
+    <AssemblyVersion>0.1.0</AssemblyVersion>
+    <Description>CVKL Environment cube</Description>
+    <PackageTags>vulkan CVKL</PackageTags>    
+    <PackageVersion>$(AssemblyVersion)-beta</PackageVersion>
+    <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
+    <PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
+    <PackageProjectUrl>https://github.com/jpbruyere/vk.net/blob/master/README.md</PackageProjectUrl>
+    <License>MIT</License>
+    <PackageReleaseNotes></PackageReleaseNotes>
+    <SynchReleaseVersion>false</SynchReleaseVersion>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>    
+  </PropertyGroup>
+
+</Project>
diff --git a/addons/EnvironmentPipeline/shaders/filtercube.vert b/addons/EnvironmentPipeline/shaders/filtercube.vert
new file mode 100644 (file)
index 0000000..1226e28
--- /dev/null
@@ -0,0 +1,19 @@
+#version 450
+
+layout (location = 0) in vec3 inPos;
+
+layout(push_constant) uniform PushConsts {
+       layout (offset = 0) mat4 mvp;
+} pushConsts;
+
+layout (location = 0) out vec3 outUVW;
+
+out gl_PerVertex {
+       vec4 gl_Position;
+};
+
+void main() 
+{
+       outUVW = inPos;
+       gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0);
+}
diff --git a/addons/EnvironmentPipeline/shaders/genbrdflut.frag b/addons/EnvironmentPipeline/shaders/genbrdflut.frag
new file mode 100644 (file)
index 0000000..b6290dd
--- /dev/null
@@ -0,0 +1,90 @@
+#version 450
+
+layout (location = 0) in vec2 inUV;
+layout (location = 0) out vec4 outColor;
+layout (constant_id = 0) const uint NUM_SAMPLES = 1024u;
+
+const float PI = 3.1415926536;
+
+// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
+float random(vec2 co)
+{
+       float a = 12.9898;
+       float b = 78.233;
+       float c = 43758.5453;
+       float dt= dot(co.xy ,vec2(a,b));
+       float sn= mod(dt,3.14);
+       return fract(sin(sn) * c);
+}
+
+vec2 hammersley2d(uint i, uint N) 
+{
+       // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+       uint bits = (i << 16u) | (i >> 16u);
+       bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+       bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+       bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+       bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+       float rdi = float(bits) * 2.3283064365386963e-10;
+       return vec2(float(i) /float(N), rdi);
+}
+
+// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
+vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) 
+{
+       // Maps a 2D point to a hemisphere with spread based on roughness
+       float alpha = roughness * roughness;
+       float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1;
+       float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y));
+       float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+       vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
+
+       // Tangent space
+       vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+       vec3 tangentX = normalize(cross(up, normal));
+       vec3 tangentY = normalize(cross(normal, tangentX));
+
+       // Convert to world Space
+       return normalize(tangentX * H.x + tangentY * H.y + normal * H.z);
+}
+
+// Geometric Shadowing function
+float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness)
+{
+       float k = (roughness * roughness) / 2.0;
+       float GL = dotNL / (dotNL * (1.0 - k) + k);
+       float GV = dotNV / (dotNV * (1.0 - k) + k);
+       return GL * GV;
+}
+
+vec2 BRDF(float NoV, float roughness)
+{
+       // Normal always points along z-axis for the 2D lookup 
+       const vec3 N = vec3(0.0, 0.0, 1.0);
+       vec3 V = vec3(sqrt(1.0 - NoV*NoV), 0.0, NoV);
+
+       vec2 LUT = vec2(0.0);
+       for(uint i = 0u; i < NUM_SAMPLES; i++) {
+               vec2 Xi = hammersley2d(i, NUM_SAMPLES);
+               vec3 H = importanceSample_GGX(Xi, roughness, N);
+               vec3 L = 2.0 * dot(V, H) * H - V;
+
+               float dotNL = max(dot(N, L), 0.0);
+               float dotNV = max(dot(N, V), 0.0);
+               float dotVH = max(dot(V, H), 0.0); 
+               float dotNH = max(dot(H, N), 0.0);
+
+               if (dotNL > 0.0) {
+                       float G = G_SchlicksmithGGX(dotNL, dotNV, roughness);
+                       float G_Vis = (G * dotVH) / (dotNH * dotNV);
+                       float Fc = pow(1.0 - dotVH, 5.0);
+                       LUT += vec2((1.0 - Fc) * G_Vis, Fc * G_Vis);
+               }
+       }
+       return LUT / float(NUM_SAMPLES);
+}
+
+void main() 
+{
+       outColor = vec4(BRDF(inUV.s, 1.0-inUV.t), 0.0, 1.0);
+}
\ No newline at end of file
diff --git a/addons/EnvironmentPipeline/shaders/genbrdflut.vert b/addons/EnvironmentPipeline/shaders/genbrdflut.vert
new file mode 100644 (file)
index 0000000..f3dd233
--- /dev/null
@@ -0,0 +1,9 @@
+#version 450
+
+layout (location = 0) out vec2 outUV;
+
+void main()
+{
+       outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
+       gl_Position = vec4(outUV * 2.0f - 1.0f, 0.0f, 1.0f);
+}
\ No newline at end of file
diff --git a/addons/EnvironmentPipeline/shaders/irradiancecube.frag b/addons/EnvironmentPipeline/shaders/irradiancecube.frag
new file mode 100644 (file)
index 0000000..340d679
--- /dev/null
@@ -0,0 +1,37 @@
+// Generates an irradiance cube from an environment map using convolution
+
+#version 450
+
+layout (location = 0) in vec3 inPos;
+layout (location = 0) out vec4 outColor;
+layout (binding = 0) uniform samplerCube samplerEnv;
+
+layout(push_constant) uniform PushConsts {
+       layout (offset = 64) float deltaPhi;
+       layout (offset = 68) float deltaTheta;
+} consts;
+
+#define PI 3.1415926535897932384626433832795
+
+void main()
+{
+       vec3 N = normalize(inPos);
+       vec3 up = vec3(0.0, 1.0, 0.0);
+       vec3 right = normalize(cross(up, N));
+       up = cross(N, right);
+
+       const float TWO_PI = PI * 2.0;
+       const float HALF_PI = PI * 0.5;
+
+       vec3 color = vec3(0.0);
+       uint sampleCount = 0u;
+       for (float phi = 0.0; phi < TWO_PI; phi += consts.deltaPhi) {
+               for (float theta = 0.0; theta < HALF_PI; theta += consts.deltaTheta) {
+                       vec3 tempVec = cos(phi) * right + sin(phi) * up;
+                       vec3 sampleVector = cos(theta) * N + sin(theta) * tempVec;
+                       color += texture(samplerEnv, sampleVector).rgb * cos(theta) * sin(theta);
+                       sampleCount++;
+               }
+       }
+       outColor = vec4(PI * color / float(sampleCount), 1.0);//texture(samplerEnv, inPos).rgba;
+}
diff --git a/addons/EnvironmentPipeline/shaders/prefilterenvmap.frag b/addons/EnvironmentPipeline/shaders/prefilterenvmap.frag
new file mode 100644 (file)
index 0000000..ae1212e
--- /dev/null
@@ -0,0 +1,105 @@
+#version 450
+
+layout (location = 0) in vec3 inPos;
+layout (location = 0) out vec4 outColor;
+
+layout (binding = 0) uniform samplerCube samplerEnv;
+
+layout(push_constant) uniform PushConsts {
+       layout (offset = 64) float roughness;
+       layout (offset = 68) uint numSamples;
+} consts;
+
+const float PI = 3.1415926536;
+
+// Based omn http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
+float random(vec2 co)
+{
+       float a = 12.9898;
+       float b = 78.233;
+       float c = 43758.5453;
+       float dt= dot(co.xy ,vec2(a,b));
+       float sn= mod(dt,3.14);
+       return fract(sin(sn) * c);
+}
+
+vec2 hammersley2d(uint i, uint N) 
+{
+       // Radical inverse based on http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+       uint bits = (i << 16u) | (i >> 16u);
+       bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+       bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+       bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+       bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+       float rdi = float(bits) * 2.3283064365386963e-10;
+       return vec2(float(i) /float(N), rdi);
+}
+
+// Based on http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_slides.pdf
+vec3 importanceSample_GGX(vec2 Xi, float roughness, vec3 normal) 
+{
+       // Maps a 2D point to a hemisphere with spread based on roughness
+       float alpha = roughness * roughness;
+       float phi = 2.0 * PI * Xi.x + random(normal.xz) * 0.1;
+       float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha*alpha - 1.0) * Xi.y));
+       float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+       vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
+
+       // Tangent space
+       vec3 up = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
+       vec3 tangentX = normalize(cross(up, normal));
+       vec3 tangentY = normalize(cross(normal, tangentX));
+
+       // Convert to world Space
+       return normalize(tangentX * H.x + tangentY * H.y + normal * H.z);
+}
+
+// Normal Distribution function
+float D_GGX(float dotNH, float roughness)
+{
+       float alpha = roughness * roughness;
+       float alpha2 = alpha * alpha;
+       float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0;
+       return (alpha2)/(PI * denom*denom); 
+}
+
+vec3 prefilterEnvMap(vec3 R, float roughness)
+{
+       vec3 N = R;
+       vec3 V = R;
+       vec3 color = vec3(0.0);
+       float totalWeight = 0.0;
+       float envMapDim = float(textureSize(samplerEnv, 0).s);
+       for(uint i = 0u; i < consts.numSamples; i++) {
+               vec2 Xi = hammersley2d(i, consts.numSamples);
+               vec3 H = importanceSample_GGX(Xi, roughness, N);
+               vec3 L = 2.0 * dot(V, H) * H - V;
+               float dotNL = clamp(dot(N, L), 0.0, 1.0);
+               if(dotNL > 0.0) {
+                       // Filtering based on https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filtering-for-image-based-lighting/
+
+                       float dotNH = clamp(dot(N, H), 0.0, 1.0);
+                       float dotVH = clamp(dot(V, H), 0.0, 1.0);
+
+                       // Probability Distribution Function
+                       float pdf = D_GGX(dotNH, roughness) * dotNH / (4.0 * dotVH) + 0.0001;
+                       // Slid angle of current smple
+                       float omegaS = 1.0 / (float(consts.numSamples) * pdf);
+                       // Solid angle of 1 pixel across all cube faces
+                       float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim);
+                       // Biased (+1.0) mip level for better result
+                       float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f);
+                       color += textureLod(samplerEnv, L, mipLevel).rgb * dotNL;
+                       totalWeight += dotNL;
+
+               }
+       }
+       return (color / totalWeight);
+}
+
+
+void main()
+{              
+       vec3 N = normalize(inPos);
+       outColor = vec4(prefilterEnvMap(N, consts.roughness), 1.0);
+}
diff --git a/addons/EnvironmentPipeline/shaders/skybox.frag b/addons/EnvironmentPipeline/shaders/skybox.frag
new file mode 100644 (file)
index 0000000..e505ef1
--- /dev/null
@@ -0,0 +1,12 @@
+#version 450
+
+layout (binding = 2) uniform samplerCube samplerEnv;
+
+layout (set = 0, location = 0) in vec3 inUVW;
+
+layout (set = 0, location = 0) out vec4 outColor;
+
+void main() 
+{    
+    outColor = vec4(textureLod(samplerEnv, inUVW, 1.5).rgb, 1.0);
+}
\ No newline at end of file
diff --git a/addons/EnvironmentPipeline/shaders/skybox.vert b/addons/EnvironmentPipeline/shaders/skybox.vert
new file mode 100644 (file)
index 0000000..22e285e
--- /dev/null
@@ -0,0 +1,27 @@
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+
+layout (binding = 0) uniform UBO 
+{
+    mat4 projection;
+    mat4 model;
+    mat4 view;
+} ubo;
+
+layout (location = 0) out vec3 outUVW;
+
+out gl_PerVertex 
+{
+    vec4 gl_Position;
+};
+
+void main() 
+{
+    outUVW = inPos;
+    outUVW.y = -outUVW.y;        
+    gl_Position = ubo.projection * mat4(mat3(ubo.view)) * vec4(inPos, 1.0);    
+}
index 738ae0bd3b2c3d4298c53cdaf2874021fbade04e..b61e7bda40a2c6aa3b094499a4454d839bf30ab9 100644 (file)
        <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
                <DefineConstants>NETSTANDARD;NETSTANDARD2_0;WITH_SHADOWS;_WITH_VKVG</DefineConstants>    
        </PropertyGroup>
-       
-       <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">              
-               <ProjectReference Include="$(RootDirectory)vke\vke.csproj" />
-       </ItemGroup>    
-       <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">            
-               <PackageReference Include="vke" Version="0.1.7-beta" />
-       </ItemGroup>   
-       
+               
        <ItemGroup>
+               <PackageReference Include="vke" Version="0.1.7-beta" />
                <PackageReference Include="SpirVTasks" Version="0.1.9-beta" />     
                <PackageReference Include="Vulkan" Version="0.1.4" />        
        </ItemGroup>    
index 1eea93271ef81537c9d671bf92c798f45bc5a38b..5820a0231ad94f5c89e516ad77ac6948f540c0c0 100644 (file)
@@ -13,6 +13,7 @@ namespace DistanceFieldFontTest {
 
        class Program : VkWindow {
                static void Main (string[] args) {
+                       SwapChain.PREFERED_FORMAT = VkFormat.B8g8r8a8Unorm;
 #if DEBUG
                        Instance.VALIDATION = true;
                        Instance.DEBUG_UTILS = true;
@@ -26,6 +27,8 @@ namespace DistanceFieldFontTest {
                float rotSpeed = 0.01f, zoomSpeed = 0.01f;
                float rotX, rotY, rotZ = 0f, zoom = 1f;
 
+               float rotAnim = 1f;
+
                struct Matrices {
                        public Matrix4x4 projection;
                        public Matrix4x4 view;
@@ -62,7 +65,7 @@ namespace DistanceFieldFontTest {
 
                Program () : base () {
 
-                       font = new BMFont (Utils.DataDirectory + "font.fnt");
+                       font = new BMFont ("../data/font.fnt");
 
                        vbo = new GPUBuffer<float> (dev, VkBufferUsageFlags.VertexBuffer, 1024);
                        ibo = new GPUBuffer<ushort> (dev, VkBufferUsageFlags.IndexBuffer, 2048);
@@ -118,6 +121,8 @@ namespace DistanceFieldFontTest {
 
                        staggingVbo.Dispose ();
                        staggingIbo.Dispose ();
+
+                       UpdateFrequency = 10;
                }
 
 
@@ -184,6 +189,11 @@ namespace DistanceFieldFontTest {
                                buildCommandBuffers ();
                                rebuildBuffers = false;
                        }
+                       if (rotAnim < 0.000001f)
+                               return;
+                       rotY += rotAnim;
+                       rotAnim *= 0.95f;
+                       updateViewRequested = true;
                }
 
                void buildCommandBuffers () {
@@ -244,6 +254,9 @@ namespace DistanceFieldFontTest {
 
                protected override void onKeyDown (Key key, int scanCode, Modifier modifiers) {
                        switch (key) {
+                               case Key.Space:
+                                       rotAnim += 0.1f;
+                                       break;
                                case Key.F2:
                                        if (modifiers.HasFlag (Modifier.Shift))
                                                outlineColor.W -= 0.01f;
@@ -257,6 +270,7 @@ namespace DistanceFieldFontTest {
                        }                                       
                }
                protected override void OnResize () {
+                       base.OnResize ();
 
                        updateViewRequested = true;
 
index 6a9862957ec27b22814aab2fba51100229ebcb28..e60810e589ab4d575097b92a5f295f7cc615aaa4 100644 (file)
@@ -166,6 +166,7 @@ namespace ModelSample {
                }
 
                protected override void OnResize () {
+                       base.OnResize();
 
                        if (frameBuffers != null)
                                for (int i = 0; i < swapChain.ImageCount; ++i)
index 6b64eed41c5d773bf407f89ccf6b45976dcd8c82..390e217f6589c4e63de7f3615691ef585348f992 100644 (file)
@@ -219,6 +219,7 @@ namespace Textured {
                }
 
                protected override void OnResize () {
+                       base.OnResize();
 
                        updateMatrices ();
 
index 21aef3379e8db966c3c20c284bfaf7902c7e1e2a..98fd5c38bf1d754260f90587b2143210199a133e 100644 (file)
@@ -275,10 +275,10 @@ namespace TextureCube {
                }
 
                protected override void OnResize () {
-                       dev.WaitIdle ();
+                       base.OnResize ();
 
 #if WITH_VKVG
-                       vkvgPipeline.Resize ((int)swapChain.Width, (int)swapChain.Height, new DescriptorSetWrites (dsVkvg, dsLayout.Bindings[1]));
+                       vkvgPipeline.Resize ((int)Width, (int)Height, new DescriptorSetWrites (dsVkvg, dsLayout.Bindings[1]));
 #endif
 
                        updateMatrices ();
index 75c20ed4673dbc1a4a5dfd128762208ba769435d..2dcb68ff7f550233ba55e32ca72d754ac8f1edca 100644 (file)
@@ -67,10 +67,10 @@ namespace Triangle {
                        dsLayout = new DescriptorSetLayout (dev,
                                new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer));
 
-                       GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1);
+                       GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1,false);
 
                        cfg.Layout = new PipelineLayout (dev, dsLayout);
-                       cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat (), cfg.Samples);
+                       cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, cfg.Samples);
                        cfg.AddVertexBinding<Vertex> (0);
                        cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat);
 
@@ -141,7 +141,7 @@ namespace Triangle {
                }
 
                protected override void OnResize () {
-                       dev.WaitIdle ();
+                       base.OnResize ();
 
                        if (frameBuffers != null)
                                for (int i = 0; i < swapChain.ImageCount; ++i)
@@ -152,16 +152,12 @@ namespace Triangle {
                                frameBuffers[i] = new Framebuffer (pipeline.RenderPass, swapChain.Width, swapChain.Height,
                                        (pipeline.Samples == VkSampleCountFlags.SampleCount1) ? new Image[] {
                                                swapChain.images[i],
-                                               null
                                        } : new Image[] {
-                                               null,
                                                null,
                                                swapChain.images[i]
                                        });
 
                        buildCommandBuffers ();
-
-                       dev.WaitIdle ();
                }
 
                protected override void Dispose (bool disposing) {              
index 4eb8730c9631a0eee03da65be95342776a0f0d5c..0a9809e0fdbbaa1638182abaf8fb9e81ef2b0ba3 100644 (file)
@@ -23,7 +23,7 @@ namespace Crow {
                protected Interface crow;
                protected vkvg.Device vkvgDev;
                protected CVKL.Image uiImage;
-               protected bool isRunning;
+               protected bool isRunning, rebuildBuffers;
 
                protected CrowWin (string name = "CrowWin", uint _width = 1024, uint _height = 768, bool vSync = false) :
                        base (name, _width, _height, vSync) {
index fe0fc4c082cfe07ef403c3653b53163bb4a5c89d..e5c5598e9bc6f89a3b402d58a6f1fa47a4c10760 100644 (file)
@@ -129,7 +129,6 @@ namespace deferred {
 
                int curModelIndex = 0;
                bool reloadModel;
-               bool rebuildBuffers;
 
                Queue transferQ;
                DeferredPbrRenderer renderer;
index f15132ba46f32ae77a4de5cee8b398a6748acad1..8ad5dbe02df140319cfeb7fb2f1e19e8a60a30fe 100644 (file)
@@ -12,7 +12,7 @@ namespace deferred {
 #if DEBUG
                        Instance.VALIDATION = true;
                        Instance.DEBUG_UTILS = true;
-                       Instance.RENDER_DOC_CAPTURE = false;
+                       //Instance.RENDER_DOC_CAPTURE = false;
 #endif
                        SwapChain.PREFERED_FORMAT = VkFormat.B8g8r8a8Srgb;
                        DeferredPbrRenderer.TEXTURE_ARRAY = true;
@@ -55,7 +55,6 @@ namespace deferred {
                        Utils.DataDirectory + "textures/uffizi_cube.ktx",
                };
                string[] modelPathes = {
-                               //"/mnt/devel/gts/vkChess.net/data/models/chess.glb",
                                Utils.DataDirectory + "models/DamagedHelmet/glTF/DamagedHelmet.gltf",
                                Utils.DataDirectory + "models/shadow.glb",
                                Utils.DataDirectory + "models/Hubble.glb",
@@ -211,24 +210,25 @@ namespace deferred {
                float finalDebug = -1.0f;
 
                void buildCommandBuffers () {
-                       cmdPbr?.Free ();
-                       cmdPbr = cmdPool.AllocateAndStart ();
-                       renderer.buildCommandBuffers (cmdPbr);
-                       cmdPbr.End ();
+                       //cmdPbr?.Free ();
+                       //cmdPbr = cmdPool.AllocateAndStart ();
+                       //renderer.buildCommandBuffers (cmdPbr);
+                       //cmdPbr.End ();
 
-                       cmdBlur?.Free ();
-                       cmdBlur = computeCmdPool.AllocateAndStart ();
-                       buildBlurCmd (cmdBlur);
+                       //cmdBlur?.Free ();
+                       //cmdBlur = computeCmdPool.AllocateAndStart ();
+                       //buildBlurCmd (cmdBlur);
 
 
                        for (int i = 0; i < swapChain.ImageCount; ++i) {
                                cmds[i]?.Free ();
                                cmds[i] = cmdPool.AllocateAndStart ();
 
+                               renderer.buildCommandBuffers (cmds[i]);
                                //renderer.hdrImgResolved.SetLayout (cmds[i], VkImageAspectFlags.Color,
-                                       //VkAccessFlags.TransferRead, VkAccessFlags.ShaderRead,
-                                       //VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal,
-                                       //VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);
+                               //VkAccessFlags.TransferRead, VkAccessFlags.ShaderRead,
+                               //VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal,
+                               //VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);
 
                                plToneMap.RenderPass.Begin (cmds[i], frameBuffers[i]);
 
@@ -290,21 +290,18 @@ namespace deferred {
                        }
 
                        if (cmds[idx] == null)
-                               return;
-
-                       presentQueue.Submit (cmdPbr, swapChain.presentComplete, renderer.DrawComplete);
-
-                       computeQ.Submit (cmdBlur, renderer.DrawComplete, blurComplete);
+                               return;                         
 
-                       presentQueue.Submit (cmds[idx], blurComplete, drawComplete[idx]);
+                       presentQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx]);
                        presentQueue.Present (swapChain, drawComplete[idx]);
-
-                       presentQueue.WaitIdle ();
                }
+
                protected override void OnResize () {
+                       base.OnResize ();
+
                        dev.WaitIdle ();
 
-                       renderer.Resize (swapChain.Width, swapChain.Height);
+                       renderer.Resize (Width, Height);
 
                        UpdateView ();
 
index b664c50fd4d1275d5e4edc4cf52463b40df7a951..0a0cd3516543b190a6e3fe66814c5195724761d7 100644 (file)
@@ -247,6 +247,8 @@ namespace pbrSample {
 
                 
                protected override void OnResize () {
+                       base.OnResize();
+
                        dev.WaitIdle ();
 #if WITH_VKVG
                        vkvgPipeline.Resize ((int)swapChain.Width, (int)swapChain.Height,
index deb35f4788f0befc91f257dacc61db3c548aea5c..acc948d734ed5c7daeaa48f7378064440cab92c5 100644 (file)
@@ -6,7 +6,7 @@
                 
   <ItemGroup>
     <GLSLShader Update="shaders/simpletexture.frag">
-               <LogicalName>CVKL.simpletexture.frag.spv</LogicalName>          
+               <LogicalName>vke.simpletexture.frag.spv</LogicalName>           
        </GLSLShader>
   </ItemGroup>    
        
index 611607114f5f0826c65d387f2402891f9cd709d4..231e69aa908d34988276f5ef1aed8156d06c74c1 100644 (file)
@@ -1,28 +1,6 @@
-//
-// MarshaledObject.cs
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
 //
-// Author:
-//       Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2019 jp
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 using System;
 using System.Runtime.InteropServices;
 
index 1c5e3ab2d39515a6d8120ad6d4c67635e9ab7b40..2fbc8d8b97e6c3b6cf9bc74c470faa7c4a17c55e 100644 (file)
@@ -1,6 +1,7 @@
-using System;
-using System.IO;
-using System.Runtime.InteropServices;
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
 using VK;
 
 using static VK.Vk;
@@ -11,6 +12,9 @@ namespace CVKL {
                Random,
                Linear 
        }
+       /// <summary>
+       /// A memory pool is a single chunck of memory of a kind shared among multiple resources.
+       /// </summary>
        public class MemoryPool : IDisposable {
                Device dev;
                internal VkDeviceMemory vkMemory;
@@ -30,6 +34,12 @@ namespace CVKL {
                public IntPtr MappedData => mappedPointer;
                public Resource Last => lastResource;
 
+               /// <summary>
+               /// Initializes a new instance of the <see cref="T:CVKL.MemoryPool"/> class.
+               /// </summary>
+               /// <param name="dev">device</param>
+               /// <param name="memoryTypeIndex">Memory type index.</param>
+               /// <param name="size">Size</param>
                public MemoryPool (Device dev, uint memoryTypeIndex, UInt64 size) {
                        this.dev = dev;
                        memInfo.allocationSize = size;
@@ -94,10 +104,8 @@ namespace CVKL {
                        resource.bindMemory ();
                }
 
-
-
-               public void Defrag () { 
-
+               public void Defrag () {
+                       throw new NotImplementedException ();
                }
 
                public void Remove (Resource resource) {
@@ -113,7 +121,6 @@ namespace CVKL {
                        }
                        resource.next = resource.previous = null;
                }
-
                public void Map (ulong size = Vk.WholeSize, ulong offset = 0) {
                        Utils.CheckResult (vkMapMemory (dev.VkDev, vkMemory, offset, size, 0, ref mappedPointer));
                }
@@ -127,8 +134,11 @@ namespace CVKL {
 
                protected virtual void Dispose (bool disposing) {
                        if (!disposedValue) {
-                               if (!disposing)
+                               if (disposing) {
+                                       //TODO:should automatically free resources here
+                               } else
                                        System.Diagnostics.Debug.WriteLine ("MemoryPool disposed by Finalizer.");
+
                                vkFreeMemory (dev.VkDev, vkMemory, IntPtr.Zero);
                                disposedValue = true;
                        }
index e450754ec02207b13ab2edb17e1cdef95e1ac387..c6bbd2252486b6a87db4722681da69d6b03c9c5d 100644 (file)
@@ -1,21 +1,22 @@
 using System;
-using System.Diagnostics;
-using System.IO;
-using System.Runtime.InteropServices;
 using VK;
 
-using static VK.Vk;
-
 namespace CVKL {
 #if MEMORY_POOLS
+       /// <summary>
+       /// Resource manager is responsible for the memory allocations. It holds one pool for each memory type
+       /// </summary>
        public class ResourceManager : IDisposable {
                VkPhysicalDeviceMemoryProperties memoryProperties;
                public MemoryPool[] memoryPools;
                ulong[] reservedHeapMemory;
 
                VkMemoryHeap getHeapFromMemoryIndex (uint i) => memoryProperties.memoryHeaps[memoryProperties.memoryTypes[i].heapIndex];
-
-
+               /// <summary>
+               /// Create a new resource manager that will create one memory pool for each kind of memory available on the device
+               /// </summary>
+               /// <param name="dev">Device</param>
+               /// <param name="defaultPoolsBlockDivisor">part of the whole available memory size to reserve by pools</param>
                public ResourceManager (Device dev, ulong defaultPoolsBlockDivisor = 4) {
                        memoryProperties = dev.phy.memoryProperties;
                        memoryPools = new MemoryPool[memoryProperties.memoryTypeCount];
@@ -27,7 +28,10 @@ namespace CVKL {
                                reservedHeapMemory[memoryProperties.memoryTypes[i].heapIndex] += size;
                        }
                }
-
+               /// <summary>
+               /// Add one or more resources to the manager, pool will be choosen depending on the resource memory flags
+               /// </summary>
+               /// <param name="resources">Resource(s).</param>
                public void Add (params Resource[] resources) {
                        foreach (Resource res in resources) {
                                res.updateMemoryRequirements ();
@@ -46,7 +50,9 @@ namespace CVKL {
                        }
                        throw new InvalidOperationException ("Could not find a suitable memory type!");
                }
-
+               /// <summary>
+               /// Dispose all memory pools held by this resource manager.
+               /// </summary>
                public void Dispose () {
                        for (uint i = 0; i < memoryPools.Length; i++)
                                memoryPools[i].Dispose ();
index f523f060fc9b606d624d0d26c66e50a31e6c226d..105883085ca4ddd16e77fe7abe01504f9f67493a 100644 (file)
@@ -5,6 +5,9 @@ using System;
 using VK;
 
 namespace CVKL {
+       /// <summary>
+       /// This class is a helper class for VkPipelineShaderStageCreateInfo creation.
+       /// </summary>
        public class ShaderInfo : IDisposable {
                public VkShaderStageFlags StageFlags;
                public string SpirvPath;
@@ -15,9 +18,11 @@ namespace CVKL {
                        StageFlags = _stageFlags;
                        SpirvPath = _spirvPath;
                        EntryPoint = new FixedUtf8String (_entryPoint);
-                       this.SpecializationInfo = specializationInfo;
+                       SpecializationInfo = specializationInfo;
                }
-
+               /// <summary>
+               /// Create the VkPipelineShaderStageCreateInfo structure. Note that the ShaderModule is created here and has to be destroy after the pipeline creation
+               /// </summary>
                public VkPipelineShaderStageCreateInfo GetStageCreateInfo (Device dev) {
                        return new VkPipelineShaderStageCreateInfo {
                                sType = VkStructureType.PipelineShaderStageCreateInfo,
@@ -33,9 +38,9 @@ namespace CVKL {
 
                protected virtual void Dispose (bool disposing) {
                        if (!disposedValue) {
-                               if (disposing)
+                               if (disposing) {
                                        EntryPoint.Dispose ();
-
+                               }
                                disposedValue = true;
                        }
                }
index 6f5d9e43e18ca8f0af495e464e4313c74ee971b8..320757415266a5d78462b0215ff116dc3d604115 100644 (file)
@@ -2,6 +2,7 @@
 //
 // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 using System;
+using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
 using Glfw;
@@ -14,7 +15,7 @@ namespace CVKL {
        /// Provide default swapchain with its command pool and buffers per image and the main present queue
        /// </summary>
        public abstract class VkWindow : IDisposable {
-               static VkWindow currentWindow;
+               static Dictionary<IntPtr,VkWindow> windows = new Dictionary<IntPtr, VkWindow>();
 
                IntPtr hWin;
 
@@ -40,7 +41,6 @@ namespace CVKL {
                /// </summary>
                protected Camera camera = new Camera (Utils.DegreesToRadians (45f), 1f);
 
-               uint width, height;
                bool[] buttons = new bool[10];
                public Modifier KeyModifiers = 0;
 
@@ -57,21 +57,25 @@ namespace CVKL {
                /// </summary>
                public long UpdateFrequency = 200;
 
-               public uint Width => width;
-               public uint Height => height;
+               public uint Width { get; private set; }
+               public uint Height { get; private set; }
+               public string Title {
+                       set {
+                               Glfw3.SetWindowTitle (hWin, value);
+                       }
+               }
 
                public VkWindow (string name = "VkWindow", uint _width = 800, uint _height = 600, bool vSync = false) {
-                       currentWindow = this;
 
-                       width = _width;
-                       height = _height;
+                       Width = _width;
+                       Height = _height;
 
                        Glfw3.Init ();
 
                        Glfw3.WindowHint (WindowAttribute.ClientApi, 0);
                        Glfw3.WindowHint (WindowAttribute.Resizable, 1);
 
-                       hWin = Glfw3.CreateWindow ((int)width, (int)height, name, MonitorHandle.Zero, IntPtr.Zero);
+                       hWin = Glfw3.CreateWindow ((int)Width, (int)Height, name, MonitorHandle.Zero, IntPtr.Zero);
 
                        if (hWin == IntPtr.Zero)
                                throw new Exception ("[GLFW3] Unable to create vulkan Window");
@@ -83,6 +87,8 @@ namespace CVKL {
                        Glfw3.SetScrollCallback (hWin, HandleScrollDelegate);
                        Glfw3.SetCharCallback (hWin, HandleCharDelegate);
 
+                       windows.Add (hWin, this);
+
                        initVulkan (vSync);
                }
                IntPtr currentCursor;
@@ -120,21 +126,24 @@ namespace CVKL {
                        //activate the device to have effective queues created accordingly to what's available
                        dev.Activate (enabledFeatures, EnabledDeviceExtensions);
 
-                       swapChain = new SwapChain (presentQueue as PresentQueue, width, height, SwapChain.PREFERED_FORMAT,
+                       swapChain = new SwapChain (presentQueue as PresentQueue, Width, Height, SwapChain.PREFERED_FORMAT,
                                vSync ? VkPresentModeKHR.FifoKHR : VkPresentModeKHR.MailboxKHR);
                        swapChain.Create ();
 
+                       Width = swapChain.Width;
+                       Height = swapChain.Height;
+
                        cmdPool = new CommandPool (dev, presentQueue.qFamIndex);
 
                        cmds = new CommandBuffer[swapChain.ImageCount];
                        drawComplete = new VkSemaphore[swapChain.ImageCount];
 
-                       for (int i = 0; i < swapChain.ImageCount; i++)
+                       for (int i = 0; i < swapChain.ImageCount; i++) {
                                drawComplete[i] = dev.CreateSemaphore ();
+                               drawComplete[i].SetDebugMarkerName (dev, "Semaphore DrawComplete" + i);
+                       }
 
                        cmdPool.SetName ("main CmdPool");
-                       for (int i = 0; i < swapChain.ImageCount; i++)
-                               drawComplete[i].SetDebugMarkerName (dev, "Semaphore DrawComplete" + i);
                }
                /// <summary>
                /// override this method to modify enabled features before device creation
@@ -188,10 +197,10 @@ namespace CVKL {
                        switch (key) {
                                case Key.F4:
                                        if (modifiers == Modifier.Alt)
-                                               Glfw3.SetWindowShouldClose (currentWindow.hWin, 1);
+                                               Glfw3.SetWindowShouldClose (hWin, 1);
                                        break;
                                case Key.Escape:
-                                       Glfw3.SetWindowShouldClose (currentWindow.hWin, 1);
+                                       Glfw3.SetWindowShouldClose (hWin, 1);
                                        break;
                                case Key.Up:
                                        camera.Move (0, 0, 1);
@@ -226,32 +235,32 @@ namespace CVKL {
                #region events delegates
                static void HandleWindowSizeDelegate (IntPtr window, int width, int height) { }
                static void HandleCursorPosDelegate (IntPtr window, double xPosition, double yPosition) {
-                       currentWindow.onMouseMove (xPosition, yPosition);
-                       currentWindow.lastMouseX = xPosition;
-                       currentWindow.lastMouseY = yPosition;
+                       windows[window].onMouseMove (xPosition, yPosition);
+                       windows[window].lastMouseX = xPosition;
+                       windows[window].lastMouseY = yPosition;
                }
                static void HandleMouseButtonDelegate (IntPtr window, Glfw.MouseButton button, InputAction action, Modifier mods) {
                        if (action == InputAction.Press) {
-                               currentWindow.buttons[(int)button] = true;
-                               currentWindow.onMouseButtonDown (button);
+                               windows[window].buttons[(int)button] = true;
+                               windows[window].onMouseButtonDown (button);
                        } else {
-                               currentWindow.buttons[(int)button] = false;
-                               currentWindow.onMouseButtonUp (button);
+                               windows[window].buttons[(int)button] = false;
+                               windows[window].onMouseButtonUp (button);
                        }
                }
                static void HandleScrollDelegate (IntPtr window, double xOffset, double yOffset) {
-                       currentWindow.onScroll (xOffset, yOffset);
+                       windows[window].onScroll (xOffset, yOffset);
                }
                static void HandleKeyDelegate (IntPtr window, Key key, int scanCode, InputAction action, Modifier modifiers) {
-                       currentWindow.KeyModifiers = modifiers;
+                       windows[window].KeyModifiers = modifiers;
                        if (action == InputAction.Press || action == InputAction.Repeat) {
-                               currentWindow.onKeyDown (key, scanCode, modifiers);
+                               windows[window].onKeyDown (key, scanCode, modifiers);
                        } else {
-                               currentWindow.onKeyUp (key, scanCode, modifiers);
+                               windows[window].onKeyUp (key, scanCode, modifiers);
                        }
                }
                static void HandleCharDelegate (IntPtr window, CodePoint codepoint) {
-                       currentWindow.onChar (codepoint);
+                       windows[window].onChar (codepoint);
                }
                #endregion
 
@@ -296,9 +305,13 @@ namespace CVKL {
                public virtual void Update () { }
 
                /// <summary>
-               /// called when swapchain has been resized, override this method to resize your framebuffers coupled to the swapchain
+               /// called when swapchain has been resized, override this method to resize your framebuffers coupled to the swapchain.
+               /// The base method will update Window width and height with new swapchain's dimensions.
                /// </summary>
-               protected virtual void OnResize () { }
+               protected virtual void OnResize () {
+                       Width = swapChain.Width;
+                       Height = swapChain.Height;
+               }
 
 
                #region IDisposable Support
index 1bb9e099c742e6f024652f75dda23248cf8e55d2..299b2886d274520e491b83115ff9daf914c94bc5 100644 (file)
@@ -133,6 +133,7 @@ namespace CVKL {
                }
                public void DestroySemaphore (VkSemaphore semaphore) {
                        vkDestroySemaphore (dev, semaphore, IntPtr.Zero);
+                       semaphore = 0;
                }
                public VkFence CreateFence (bool signaled = false) {
                        VkFence tmp;
@@ -141,8 +142,11 @@ namespace CVKL {
                        Utils.CheckResult (vkCreateFence (dev, ref info, IntPtr.Zero, out tmp));
                        return tmp;
                }
+               /// <summary>Destroy the fence.</summary>
+               /// <param name="fence">A valid fence handle.</param>
                public void DestroyFence (VkFence fence) {
                        vkDestroyFence (dev, fence, IntPtr.Zero);
+                       fence = 0;
                }
                public void WaitForFence (VkFence fence, ulong timeOut = UInt64.MaxValue) {
                        vkWaitForFences (dev, 1, ref fence, 1, timeOut);
@@ -161,6 +165,7 @@ namespace CVKL {
 
                public void DestroyShaderModule (VkShaderModule module) {
                        vkDestroyShaderModule (VkDev, module, IntPtr.Zero);
+                       module = 0;
                }
                public void WaitIdle () {
                        Utils.CheckResult (vkDeviceWaitIdle (dev));
index b463ba600c0d82efbd4425dd15255abd20e34396..93444aeb75d105e8b9e220faebbdbcae609270c8 100644 (file)
@@ -65,7 +65,7 @@ namespace CVKL {
             VkPresentInfoKHR present = VkPresentInfoKHR.New();
 
             uint idx = swapChain.currentImageIndex;
-            VkSwapchainKHR sc = swapChain.handle;
+            VkSwapchainKHR sc = swapChain.Handle;
             present.swapchainCount = 1;
             present.pSwapchains = sc.Pin();
             present.waitSemaphoreCount = 1;
index 1609f56f96915c1f7c9443629c5c6e83dcf2c070..c5662f96d8cb68e096c018308ea133a5d2cbeae2 100644 (file)
@@ -57,7 +57,7 @@ namespace CVKL {
                        Samples = samples;
 
                        AddAttachment (colorFormat, (samples == VkSampleCountFlags.SampleCount1) ? VkImageLayout.PresentSrcKHR : VkImageLayout.ColorAttachmentOptimal, samples,
-                               loadOp, VkAttachmentStoreOp.Store, VkImageLayout.Undefined);
+                               loadOp, VkAttachmentStoreOp.Store);
             ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) });
 
                        SubPass subpass0 = new SubPass ();
@@ -73,10 +73,10 @@ namespace CVKL {
 
             AddDependency (Vk.SubpassExternal, 0,
                 VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput,
-                VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite);
+                VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentWrite);
             AddDependency (0, Vk.SubpassExternal,
                 VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe,
-                VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);
+                VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);
 
                }
         /// <summary>
index 0ebdb0d13ec53ebd2ff9aab0b7148f72ec11dfd7..f5190551937bb7ea0c55bc7f6dca00dbb65a7df3 100644 (file)
@@ -38,7 +38,7 @@ namespace CVKL {
                /// </summary>
                public static VkImageUsageFlags IMAGES_USAGE = VkImageUsageFlags.ColorAttachment;
 
-               internal VkSwapchainKHR handle;
+               public VkSwapchainKHR Handle { get; private set; }
 
                internal uint currentImageIndex;
                VkSwapchainCreateInfoKHR createInfos;
@@ -48,11 +48,11 @@ namespace CVKL {
         public Image[] images;
 
                protected override VkDebugMarkerObjectNameInfoEXT DebugMarkerInfo
-                       => new VkDebugMarkerObjectNameInfoEXT (VkDebugReportObjectTypeEXT.SwapchainKhrEXT, handle.Handle);
-
+                       => new VkDebugMarkerObjectNameInfoEXT (VkDebugReportObjectTypeEXT.SwapchainKhrEXT, Handle.Handle);
 
+               /// <summary>Swapchain images count.</summary>
                public uint ImageCount => (uint)images?.Length;
-        public uint Width => createInfos.imageExtent.width;
+               public uint Width => createInfos.imageExtent.width;
         public uint Height => createInfos.imageExtent.height;
         public VkFormat ColorFormat => createInfos.imageFormat;
         public VkImageUsageFlags ImageUsage => createInfos.imageUsage;
@@ -101,7 +101,9 @@ namespace CVKL {
                        }
                        base.Activate ();
                }
-
+               /// <summary>
+               /// Create swapchain and populate images array
+               /// </summary>
                public void Create () {
                        if (state != ActivableState.Activated)
                                Activate ();
@@ -112,7 +114,7 @@ namespace CVKL {
 
             createInfos.minImageCount = capabilities.minImageCount;
             createInfos.preTransform = capabilities.currentTransform;
-            createInfos.oldSwapchain = handle;
+            createInfos.oldSwapchain = Handle;
 
             if (capabilities.currentExtent.width == 0xFFFFFFFF) {
                 if (createInfos.imageExtent.width < capabilities.minImageExtent.width)
@@ -128,11 +130,11 @@ namespace CVKL {
                 createInfos.imageExtent = capabilities.currentExtent;
 
             VkSwapchainKHR newSwapChain = Dev.CreateSwapChain (createInfos);
-            if (handle.Handle != 0)
+            if (Handle.Handle != 0)
                 _destroy ();
-            handle = newSwapChain;
+            Handle = newSwapChain;
 
-            VkImage[] tmp = Dev.GetSwapChainImages (handle);
+            VkImage[] tmp = Dev.GetSwapChainImages (Handle);
             images = new Image[tmp.Length];
             for (int i = 0; i < tmp.Length; i++) {
                 images[i] = new Image (Dev, tmp[i], ColorFormat, ImageUsage, Width, Height);
@@ -141,9 +143,13 @@ namespace CVKL {
                                images[i].Descriptor.imageView.SetDebugMarkerName (Dev, "SwapChain Img" + i + " view");
             }
         }
-
-        public int GetNextImage () {
-            VkResult res = vkAcquireNextImageKHR (Dev.VkDev, handle, UInt64.MaxValue, presentComplete, VkFence.Null, out currentImageIndex);
+               /// <summary>
+               /// Acquire next image, recreate swapchain if out of date or suboptimal error.
+               /// </summary>
+               /// <returns>Swapchain image index or -1 if failed</returns>
+               /// <param name="fence">Fence param of 'vkAcquireNextImageKHR'</param>
+        public int GetNextImage (VkFence fence = default(VkFence)) {
+            VkResult res = vkAcquireNextImageKHR (Dev.VkDev, Handle, UInt64.MaxValue, presentComplete, fence, out currentImageIndex);
             if (res == VkResult.ErrorOutOfDateKHR || res == VkResult.SuboptimalKHR) {
                 Create ();
                 return -1;
@@ -156,11 +162,11 @@ namespace CVKL {
             for (int i = 0; i < ImageCount; i++) 
                 images[i].Dispose ();
 
-            Dev.DestroySwapChain (handle);
+            Dev.DestroySwapChain (Handle);
         }
 
                public override string ToString () {
-                       return string.Format ($"{base.ToString ()}[0x{handle.Handle.ToString ("x")}]");
+                       return string.Format ($"{base.ToString ()}[0x{Handle.Handle.ToString ("x")}]");
                }
 
                #region IDisposable Support
index 142dbc7bc812a8e5eb504da7b8843ba532f4a6e2..09a60c9630931a958b072b843e634a26aad4d4a7 100644 (file)
@@ -1,43 +1,39 @@
-using System.Text;
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System.Runtime.InteropServices;
+using System.Text;
 
 namespace Glfw
 {
-    /// <summary>
-    /// Represents a native UTF32 codepoint.
-    /// </summary>
-    public struct CodePoint
+       /// <summary>
+       /// Represents a native UTF32 codepoint.
+       /// </summary>
+       [StructLayout (LayoutKind.Explicit)]
+       public struct CodePoint
     {
-        /// <summary>
-        /// The numeric value of the codepoint.
-        /// </summary>
-        public readonly uint Value;
-
-        /// <summary>
-        /// Casts the codepoint to System.Char.
-        /// </summary>
-        /// <returns>
-        /// The character representation of the codepoint.
-        /// </returns>
-        public unsafe char ToChar()
-        {
-            uint value = this.Value;
-
-            char result;
-
-            Encoding.UTF32.GetChars((byte*)&value, 4, &result, 1);
-
-            return result;
-        }
-
+               /// <summary>
+               /// The numeric value of the codepoint.
+               /// </summary>
+               [FieldOffset (0)] public readonly uint Value;
+               [FieldOffset (0)] readonly byte byte0;
+               [FieldOffset (1)] readonly byte byte1;
+               [FieldOffset (2)] readonly byte byte2;
+               [FieldOffset (3)] readonly byte byte3;
+               /// <summary>
+               /// Casts the codepoint to System.Char.
+               /// </summary>
+               /// <returns>
+               /// The character representation of the codepoint.
+               /// </returns>
+               public char ToChar() => Encoding.UTF32.GetChars (new byte[] { byte0, byte0, byte0, byte0 })[0];
         /// <summary>
         /// Converts the value of this instance to its equivalent string representation.
         /// </summary>
         /// <returns>
         /// A string containing the character representation of the codepoint.
         /// </returns>
-        public override string ToString()
-        {
-            return this.ToChar().ToString();
-        }
+        public override string ToString() => ToChar().ToString();
     }
 }
index 2f2acb6d9b731914a3ca6710d2aac70d6408d11d..bfcbb0e2e4e9f2b401ce6f730619611b0e34ff70 100644 (file)
@@ -1,4 +1,8 @@
-using System;
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)using System;
+using System;
 using System.Runtime.InteropServices;
 
 namespace Glfw {
index c757488f3fde069f30ed44e05705c64d0b7d3013..ef76890484c14223a87b40b7a4ac54015cd0b691 100644 (file)
@@ -1,4 +1,8 @@
-namespace Glfw
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+namespace Glfw
 {
     /// <summary>
     /// Indicates the general category of an error.
index 27e74970f120c8b1d9ef7eeca7cda76d4021a7e0..1531d79ba49f0fe0efc0f7c407bc1d32d9930157 100644 (file)
@@ -1,9 +1,11 @@
-using System;
-using System.Text;
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
 using System.Runtime.InteropServices;
 
-namespace Glfw
-{
+namespace Glfw {
        public enum CursorShape
        {
                Arrow           = 0x00036001,
@@ -16,7 +18,7 @@ namespace Glfw
        /// <summary>
        /// Interop functions for the GLFW3 API.
        /// </summary>
-       public unsafe static class Glfw3
+       public static class Glfw3
     {
         /// <summary>
         /// The base name for the GLFW3 library.
@@ -185,7 +187,7 @@ namespace Glfw
         /// An array of extension names, or Null if an error occurred.
         /// </returns>
         [DllImport(GlfwDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "glfwGetRequiredInstanceExtensions")]
-        public static extern byte** GetRequiredInstanceExtensions(out int count);
+        public static extern IntPtr GetRequiredInstanceExtensions(out int count);
 
         /// <summary>
         /// Sets the size callback of the specified window, which is called
@@ -229,7 +231,7 @@ namespace Glfw
         /// if an error occurred.
         /// </returns>
         [DllImport(GlfwDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "glfwGetMonitors")]
-        public static extern MonitorHandle* GetMonitors(out int count);
+        public static extern IntPtr GetMonitors(out int count);
 
         /// <summary>
         /// Returns the primary monitor. This is usually the monitor where
@@ -320,7 +322,7 @@ namespace Glfw
         /// An array of video modes, or Null if an error occurred.
         /// </returns>
         [DllImport(GlfwDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "glfwGetVideoModes")]
-        public static extern VideoMode* GetVideoModes(MonitorHandle monitor, out int count);
+        public static extern IntPtr GetVideoModes(MonitorHandle monitor, out int count);
 
         /// <summary>
         /// Returns the current video mode of the specified monitor. If you
@@ -448,13 +450,14 @@ namespace Glfw
         /// </returns>
         public static string[] GetRequiredInstanceExtensions()
         {
-            byte** namePointer = GetRequiredInstanceExtensions(out int count);
+            IntPtr names = GetRequiredInstanceExtensions(out int count);
 
             var result = new string[count];
 
             for (int nameIndex = 0; nameIndex < count; nameIndex++)
             {
-                result[nameIndex] = Marshal.PtrToStringAnsi(new System.IntPtr (namePointer[nameIndex]));
+                               IntPtr name = Marshal.ReadIntPtr (names, nameIndex);
+                result[nameIndex] = Marshal.PtrToStringAnsi(name);
             }
 
             return result;
@@ -471,14 +474,12 @@ namespace Glfw
         /// </returns>
         public static MonitorHandle[] GetMonitors()
         {
-            MonitorHandle* monitorPointer = GetMonitors(out int count);
+            IntPtr monitors = GetMonitors(out int count);
 
             var result = new MonitorHandle[count];
 
-            for (int i = 0; i < count; i++)
-            {
-                result[i] = monitorPointer[i];
-            }
+            for (int i = 0; i < count; i++)            
+                result[i] = new MonitorHandle(Marshal.ReadIntPtr(monitors, i));            
 
             return result;
         }
@@ -497,14 +498,12 @@ namespace Glfw
         /// </returns>
         public static VideoMode[] GetVideoModes(MonitorHandle monitor)
         {
-            VideoMode* videoModePointer = GetVideoModes(monitor, out int count);
+            IntPtr videoModes = GetVideoModes(monitor, out int count);
 
             var result = new VideoMode[count];
 
-            for (int i = 0; i < count; i++)
-            {
-                result[i] = videoModePointer[i];
-            }
+            for (int i = 0; i < count; i++)            
+                result[i] = Marshal.PtrToStructure<VideoMode>(Marshal.ReadIntPtr(videoModes, i));            
 
             return result;
         }
index a0f7ee3c666ebf0bde5d9d9407c36b5640a75123..3ee57f7166d2f7a8ff6e9893ff023edfd84db09e 100644 (file)
@@ -1,4 +1,8 @@
-namespace Glfw
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+namespace Glfw
 {
     /// <summary>
     /// Represents the action of an input key event or the state of a key.
index 0cc2a64ef53b45670544117ea05cc8532c194769..1e8c19da73b7f9b57db9f4ef1ca54a6256e575fd 100644 (file)
@@ -1,4 +1,8 @@
-namespace Glfw
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+namespace Glfw
 {
     /// <summary>
     /// Represents a key on a keyboard.
index 55da485a2a80fcf8a0a55ac6e65fb251ae65e174..98205c7dfa172b147053224698a44ec121691a22 100644 (file)
@@ -1,4 +1,8 @@
-using System;
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
 
 namespace Glfw
 {
index 340ba6ec37847c6256af5e7f37019df070df3303..d93397b502a486d645ba6b588fcae35aef05f3da 100644 (file)
@@ -1,4 +1,8 @@
-namespace Glfw
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+namespace Glfw
 {
     /// <summary>
     /// Events that may be raised from a monitor callback.
index 16b8a71a863db05efb1a64a0c95876d8cc589910..38ed035afec4ee428cb927e651a0cf2ad89c0c3c 100644 (file)
@@ -1,4 +1,8 @@
-using System;
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
 
 namespace Glfw
 {
@@ -7,28 +11,20 @@ namespace Glfw
     /// </summary>
     public struct MonitorHandle
     {
-        internal MonitorHandle(System.IntPtr handle)
-        {
-            this.handle = handle;
-        }
-
-        private System.IntPtr handle;
+               readonly IntPtr handle;
 
-        /// <summary>
-        /// Gets the underlying native pointer to the monitor object.
-        /// </summary>
-        public IntPtr RawHandle
+               internal MonitorHandle(IntPtr handle)
         {
-            get
-            {
-                return this.handle;
-            }
+            this.handle = handle;
         }
-
+               /// <summary>
+               /// Gets the underlying native pointer to the monitor object.
+               /// </summary>
+               public IntPtr RawHandle => handle;
         /// <summary>
         /// A read-only field that represents a MonitorHandle that has been
         /// inititalised to zero.
         /// </summary>
-        public static readonly MonitorHandle Zero = new MonitorHandle (System.IntPtr.Zero);
+        public static readonly MonitorHandle Zero = new MonitorHandle (IntPtr.Zero);
     }
 }
index 12425ad415c0cf93322b366879f87bf03371bfe2..b29184a04b2b61eb2db98d95897364dbc9a8be44 100644 (file)
@@ -1,4 +1,8 @@
-namespace Glfw
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+namespace Glfw
 {
     /// <summary>
     /// The index and name of mouse buttons for callbacks.
index f191e3380752e4b25e5bc7ef7f08b4391146a72d..02181cb90845dfd402727ff0ae26a75e0841f267 100644 (file)
@@ -1,6 +1,10 @@
 using System;
 using System.Runtime.InteropServices;
 
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 namespace Glfw
 {
     /// <summary>
@@ -8,43 +12,31 @@ namespace Glfw
     /// </summary>
     public struct NativeString
     {
-        internal NativeString(System.IntPtr pointer)
+        internal NativeString(IntPtr pointer)
         {
             this.pointer = pointer;
         }
 
-        private System.IntPtr pointer;
-
-        /// <summary>
-        /// Gets the marshalled string value for this native string.
-        /// </summary>
-        public string Value
-        {
-            get
-            {
-                if (this.IsNull)
-                {
-                    throw new NullReferenceException();
-                }
-
-                return Marshal.PtrToStringAnsi(this.pointer);
-            }
-        }
+        readonly IntPtr pointer;
 
+               /// <summary>
+               /// Gets the marshalled string value for this native string.
+               /// </summary>
+               public string Value => IsNull ? throw new NullReferenceException () : Marshal.PtrToStringAnsi (this.pointer);
         /// <summary>
         /// Gets a value indicating whether the pointer wrapped by this
         /// instance is null.
         /// </summary>
-        public bool IsNull => this.pointer == System.IntPtr.Zero;
+        public bool IsNull => pointer == IntPtr.Zero;
 
         /// <summary>
         /// The underlying pointer wrapped by this instance.
         /// </summary>
-        public IntPtr RawPointer => this.pointer;
+        public IntPtr RawPointer => pointer;
 
         public override string ToString()
         {
-            return this.Value;
+            return Value;
         }
     }
 }
index 8a6026984eda105124e9b69983c66d0094e36575..baeb196e1c22450972c9098707a2dcd8d52d3f59 100644 (file)
@@ -8,15 +8,11 @@ namespace Glfw
     [StructLayout(LayoutKind.Sequential)]
     public struct VideoMode
     {
-        private int width;
-
-        private int height;
-
-        private int redBits;
-
-        private int greenBits;
-
-        private int blueBits;
+        private readonly int width;
+        private readonly int height;
+        private readonly int redBits;
+        private readonly int greenBits;
+        private readonly int blueBits;
 
         /// <summary>
         /// The resolution, in screen coordinates, of the video mode.
index e740772a258fb5c377d6c556112deb289863466e..66631c6e82e281271aab0444ce18d08f0e18172f 100644 (file)
@@ -1,4 +1,8 @@
-using System;
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System;
 using System.Runtime.InteropServices;
 
 namespace Glfw
@@ -8,27 +12,23 @@ namespace Glfw
     /// </summary>
     public struct VideoModePointer
     {
-        internal VideoModePointer(System.IntPtr pointer)
+               private readonly IntPtr pointer;
+               internal VideoModePointer (IntPtr pointer)
         {
             this.pointer = pointer;
         }
-
-        private System.IntPtr pointer;
-        
         /// <summary>
         /// Gets the VideoMode value at the referenced memory location.
         /// </summary>
-        public VideoMode Value => this.IsNull ? throw new NullReferenceException() : Marshal.PtrToStructure<VideoMode>(this.pointer);
-
+        public VideoMode Value => IsNull ? throw new NullReferenceException() : Marshal.PtrToStructure<VideoMode>(pointer);
         /// <summary>
         /// Gets a value indicating whether the pointer wrapped by this
         /// instance is null.
         /// </summary>
-        public bool IsNull => this.pointer == System.IntPtr.Zero;
-
+        public bool IsNull => pointer == IntPtr.Zero;
         /// <summary>
         /// The underlying pointer wrapped by this instance.
         /// </summary>
-        public IntPtr RawPointer => this.pointer;
+        public IntPtr RawPointer => pointer;
     }
 }
index 5d862af56144103a6ec5345263e7cd75c7c819c9..f77266755d51b82f0f9cf529d071e5cc34305b39 100644 (file)
@@ -1,4 +1,8 @@
-namespace Glfw
+// Copyright (c) 2019 Andrew Armstrong/FacticiusVir
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+namespace Glfw
 {
     /// <summary>
     /// Attributes of a window or its framebuffer or context, that can be
index cc6885416c2302ec8d196a32da1717c4e7a730b5..4ea7c41a2eb2fdc06693833e62ea58f154375d26 100644 (file)
@@ -1,28 +1,6 @@
-//
-// ktx.cs
+// Copyright (c) 2019 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
 //
-// Author:
-//       Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2019 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 using System;
 using System.IO;