diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-09-10 01:05:55 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-09-10 01:05:55 +0200 |
| commit | 1a4635df4a90d1aac1226cf12883b9c5a4462fcc (patch) | |
| tree | 16836b660c7d77f354f6e1f5f36e612b33222732 | |
| parent | 706d7000db3c780eeed538799b5a47be28c5263a (diff) | |
wip
48 files changed, 1030 insertions, 319 deletions
diff --git a/CVKL.Addons/Directory.Build.props b/CVKL.Addons/Directory.Build.props index 93b5a7f..b6f67c5 100644 --- a/CVKL.Addons/Directory.Build.props +++ b/CVKL.Addons/Directory.Build.props @@ -25,15 +25,9 @@ <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)CVKL\CVKL.csproj" /> - </ItemGroup> - <ItemGroup > - <PackageReference Include="CVKL" Version="0.1.7-beta" Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "/> - </ItemGroup> - + <ItemGroup> + <PackageReference Include="CVKL" Version="0.1.7-beta" /> <PackageReference Include="SpirVTasks" Version="0.1.9-beta" /> <PackageReference Include="Vulkan" Version="0.1.4" /> </ItemGroup> diff --git a/CVKL.Addons/EnvironmentPipeline/EnvironmentPipeline.cs b/CVKL.Addons/EnvironmentPipeline/EnvironmentPipeline.cs new file mode 100644 index 0000000..12a0df9 --- /dev/null +++ b/CVKL.Addons/EnvironmentPipeline/EnvironmentPipeline.cs @@ -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/CVKL.Addons/EnvironmentPipeline/EnvironmentPipeline.csproj b/CVKL.Addons/EnvironmentPipeline/EnvironmentPipeline.csproj new file mode 100644 index 0000000..511e55b --- /dev/null +++ b/CVKL.Addons/EnvironmentPipeline/EnvironmentPipeline.csproj @@ -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/CVKL.Addons/EnvironmentPipeline/shaders/filtercube.vert b/CVKL.Addons/EnvironmentPipeline/shaders/filtercube.vert new file mode 100644 index 0000000..1226e28 --- /dev/null +++ b/CVKL.Addons/EnvironmentPipeline/shaders/filtercube.vert @@ -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/CVKL.Addons/EnvironmentPipeline/shaders/genbrdflut.frag b/CVKL.Addons/EnvironmentPipeline/shaders/genbrdflut.frag new file mode 100644 index 0000000..b6290dd --- /dev/null +++ b/CVKL.Addons/EnvironmentPipeline/shaders/genbrdflut.frag @@ -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/CVKL.Addons/EnvironmentPipeline/shaders/genbrdflut.vert b/CVKL.Addons/EnvironmentPipeline/shaders/genbrdflut.vert new file mode 100644 index 0000000..f3dd233 --- /dev/null +++ b/CVKL.Addons/EnvironmentPipeline/shaders/genbrdflut.vert @@ -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/CVKL.Addons/EnvironmentPipeline/shaders/irradiancecube.frag b/CVKL.Addons/EnvironmentPipeline/shaders/irradiancecube.frag new file mode 100644 index 0000000..340d679 --- /dev/null +++ b/CVKL.Addons/EnvironmentPipeline/shaders/irradiancecube.frag @@ -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/CVKL.Addons/EnvironmentPipeline/shaders/prefilterenvmap.frag b/CVKL.Addons/EnvironmentPipeline/shaders/prefilterenvmap.frag new file mode 100644 index 0000000..ae1212e --- /dev/null +++ b/CVKL.Addons/EnvironmentPipeline/shaders/prefilterenvmap.frag @@ -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/CVKL.Addons/EnvironmentPipeline/shaders/skybox.frag b/CVKL.Addons/EnvironmentPipeline/shaders/skybox.frag new file mode 100644 index 0000000..e505ef1 --- /dev/null +++ b/CVKL.Addons/EnvironmentPipeline/shaders/skybox.frag @@ -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/CVKL.Addons/EnvironmentPipeline/shaders/skybox.vert b/CVKL.Addons/EnvironmentPipeline/shaders/skybox.vert new file mode 100644 index 0000000..22e285e --- /dev/null +++ b/CVKL.Addons/EnvironmentPipeline/shaders/skybox.vert @@ -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); +} diff --git a/CVKL/CVKL.csproj b/CVKL/CVKL.csproj index 443ed77..d9bf387 100644 --- a/CVKL/CVKL.csproj +++ b/CVKL/CVKL.csproj @@ -2,11 +2,10 @@ <Project Sdk="Microsoft.NET.Sdk"> <!-- <Import Project="$(RootDirectory)netfx.props" />--> <PropertyGroup> - <AssemblyName>CVKL</AssemblyName> - <Product>CVKL</Product> - <PackageId>CVKL</PackageId> - <AssemblyVersion>0.1.7</AssemblyVersion> + <ReleaseVersion>0.1.7</ReleaseVersion> + <AssemblyVersion>$(ReleaseVersion)</AssemblyVersion> <Description>C# vulkan library with IDispose model and references counting</Description> + <PackageTags>C# vulkan game library compute glfw</PackageTags> <PackageVersion>$(AssemblyVersion)-beta</PackageVersion> <GeneratePackageOnBuild>True</GeneratePackageOnBuild> @@ -14,13 +13,17 @@ <PackageProjectUrl>https://github.com/jpbruyere/vk.net/blob/master/README.md</PackageProjectUrl> <License>MIT</License> <PackageReleaseNotes> + </PackageReleaseNotes> <!--<PackageIconUrl>https://github.com/KhronosGroup/glTF/blob/master/specification/figures/gltf.png</PackageIconUrl>--> <SynchReleaseVersion>false</SynchReleaseVersion> + <OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath> + <IntermediateOutputPath>$(SolutionDir)build\$(Configuration)\</IntermediateOutputPath> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> - <EnableDefaultNoneItems>false</EnableDefaultNoneItems> + <EnableDefaultNoneItems>false</EnableDefaultNoneItems> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> diff --git a/CVKL/src/MarshaledObject.cs b/CVKL/src/MarshaledObject.cs index 6116071..231e69a 100644 --- a/CVKL/src/MarshaledObject.cs +++ b/CVKL/src/MarshaledObject.cs @@ -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; diff --git a/CVKL/src/MemoryPool.cs b/CVKL/src/MemoryPool.cs index 1c5e3ab..2fbc8d8 100644 --- a/CVKL/src/MemoryPool.cs +++ b/CVKL/src/MemoryPool.cs @@ -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; } diff --git a/CVKL/src/ResourceManager.cs b/CVKL/src/ResourceManager.cs index e450754..c6bbd22 100644 --- a/CVKL/src/ResourceManager.cs +++ b/CVKL/src/ResourceManager.cs @@ -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 (); diff --git a/CVKL/src/ShaderInfo.cs b/CVKL/src/ShaderInfo.cs index f523f06..1058830 100644 --- a/CVKL/src/ShaderInfo.cs +++ b/CVKL/src/ShaderInfo.cs @@ -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; } } diff --git a/CVKL/src/VkWindow.cs b/CVKL/src/VkWindow.cs index 6f5d9e4..9a1a142 100644 --- a/CVKL/src/VkWindow.cs +++ b/CVKL/src/VkWindow.cs @@ -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; @@ -27,6 +28,7 @@ namespace CVKL { protected CommandPool cmdPool; protected CommandBuffer[] cmds; protected VkSemaphore[] drawComplete; + protected VkFence[] drawFences; DebugReport dbgRepport; @@ -40,7 +42,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 +58,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 +88,8 @@ namespace CVKL { Glfw3.SetScrollCallback (hWin, HandleScrollDelegate); Glfw3.SetCharCallback (hWin, HandleCharDelegate); + windows.Add (hWin, this); + initVulkan (vSync); } IntPtr currentCursor; @@ -120,21 +127,26 @@ 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]; + drawFences = new VkFence[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); + drawFences[i] = dev.CreateFence (true); + } 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 @@ -164,10 +176,11 @@ namespace CVKL { if (cmds[idx] == null) return; - presentQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx]); - presentQueue.Present (swapChain, drawComplete[idx]); + dev.WaitForFence (drawFences[idx]); + dev.ResetFence (drawFences[idx]); - presentQueue.WaitIdle (); + presentQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx], drawFences[idx]); + presentQueue.Present (swapChain, drawComplete[idx]); } protected virtual void onScroll (double xOffset, double yOffset) { } @@ -188,10 +201,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 +239,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 +309,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 @@ -310,6 +327,7 @@ namespace CVKL { for (int i = 0; i < swapChain.ImageCount; i++) { dev.DestroySemaphore (drawComplete[i]); + dev.DestroyFence (drawFences[i]); cmds[i].Free (); } diff --git a/CVKL/src/base/Device.cs b/CVKL/src/base/Device.cs index 1bb9e09..299b288 100644 --- a/CVKL/src/base/Device.cs +++ b/CVKL/src/base/Device.cs @@ -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)); diff --git a/CVKL/src/base/Queue.cs b/CVKL/src/base/Queue.cs index b463ba6..93444ae 100644 --- a/CVKL/src/base/Queue.cs +++ b/CVKL/src/base/Queue.cs @@ -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; diff --git a/CVKL/src/base/RenderPass.cs b/CVKL/src/base/RenderPass.cs index 1609f56..c5662f9 100644 --- a/CVKL/src/base/RenderPass.cs +++ b/CVKL/src/base/RenderPass.cs @@ -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> diff --git a/CVKL/src/base/SwapChain.cs b/CVKL/src/base/SwapChain.cs index 0ebdb0d..f519055 100644 --- a/CVKL/src/base/SwapChain.cs +++ b/CVKL/src/base/SwapChain.cs @@ -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 diff --git a/CVKL/src/glfw/CodePoint.cs b/CVKL/src/glfw/CodePoint.cs index 142dbc7..09a60c9 100644 --- a/CVKL/src/glfw/CodePoint.cs +++ b/CVKL/src/glfw/CodePoint.cs @@ -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(); } } diff --git a/CVKL/src/glfw/Delegates.cs b/CVKL/src/glfw/Delegates.cs index 2f2acb6..bfcbb0e 100644 --- a/CVKL/src/glfw/Delegates.cs +++ b/CVKL/src/glfw/Delegates.cs @@ -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 { diff --git a/CVKL/src/glfw/ErrorCode.cs b/CVKL/src/glfw/ErrorCode.cs index c757488..ef76890 100644 --- a/CVKL/src/glfw/ErrorCode.cs +++ b/CVKL/src/glfw/ErrorCode.cs @@ -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. diff --git a/CVKL/src/glfw/Glfw3.cs b/CVKL/src/glfw/Glfw3.cs index 27e7497..1531d79 100644 --- a/CVKL/src/glfw/Glfw3.cs +++ b/CVKL/src/glfw/Glfw3.cs @@ -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; } diff --git a/CVKL/src/glfw/InputAction.cs b/CVKL/src/glfw/InputAction.cs index a0f7ee3..3ee57f7 100644 --- a/CVKL/src/glfw/InputAction.cs +++ b/CVKL/src/glfw/InputAction.cs @@ -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. diff --git a/CVKL/src/glfw/Key.cs b/CVKL/src/glfw/Key.cs index 0cc2a64..1e8c19d 100644 --- a/CVKL/src/glfw/Key.cs +++ b/CVKL/src/glfw/Key.cs @@ -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. diff --git a/CVKL/src/glfw/Modifier.cs b/CVKL/src/glfw/Modifier.cs index 55da485..98205c7 100644 --- a/CVKL/src/glfw/Modifier.cs +++ b/CVKL/src/glfw/Modifier.cs @@ -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 { diff --git a/CVKL/src/glfw/MonitorEvent.cs b/CVKL/src/glfw/MonitorEvent.cs index 340ba6e..d93397b 100644 --- a/CVKL/src/glfw/MonitorEvent.cs +++ b/CVKL/src/glfw/MonitorEvent.cs @@ -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. diff --git a/CVKL/src/glfw/MonitorHandle.cs b/CVKL/src/glfw/MonitorHandle.cs index 16b8a71..38ed035 100644 --- a/CVKL/src/glfw/MonitorHandle.cs +++ b/CVKL/src/glfw/MonitorHandle.cs @@ -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); } } diff --git a/CVKL/src/glfw/MouseButton.cs b/CVKL/src/glfw/MouseButton.cs index 12425ad..b29184a 100644 --- a/CVKL/src/glfw/MouseButton.cs +++ b/CVKL/src/glfw/MouseButton.cs @@ -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. diff --git a/CVKL/src/glfw/NativeString.cs b/CVKL/src/glfw/NativeString.cs index f191e33..02181cb 100644 --- a/CVKL/src/glfw/NativeString.cs +++ b/CVKL/src/glfw/NativeString.cs @@ -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; } } } diff --git a/CVKL/src/glfw/VideoMode.cs b/CVKL/src/glfw/VideoMode.cs index 8a60269..baeb196 100644 --- a/CVKL/src/glfw/VideoMode.cs +++ b/CVKL/src/glfw/VideoMode.cs @@ -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. diff --git a/CVKL/src/glfw/VideoModePointer.cs b/CVKL/src/glfw/VideoModePointer.cs index e740772..66631c6 100644 --- a/CVKL/src/glfw/VideoModePointer.cs +++ b/CVKL/src/glfw/VideoModePointer.cs @@ -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; } } diff --git a/CVKL/src/glfw/WindowAttribute.cs b/CVKL/src/glfw/WindowAttribute.cs index 5d862af..f772667 100644 --- a/CVKL/src/glfw/WindowAttribute.cs +++ b/CVKL/src/glfw/WindowAttribute.cs @@ -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 diff --git a/CVKL/src/ktx.cs b/CVKL/src/ktx.cs index cc68854..4ea7c41 100644 --- a/CVKL/src/ktx.cs +++ b/CVKL/src/ktx.cs @@ -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; diff --git a/CVKL/src/model/IModelLoader.cs b/CVKL/src/model/IModelLoader.cs new file mode 100644 index 0000000..36f8108 --- /dev/null +++ b/CVKL/src/model/IModelLoader.cs @@ -0,0 +1,15 @@ +// 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; + +namespace CVKL { + public interface IModelLoader { + void GetVertexCount (out ulong vertexCount, out ulong indexCount, out VkIndexType largestIndexType); + Model.Mesh[] LoadMeshes<TVertex> (VkIndexType indexType, Buffer vbo, ulong vboOffset, Buffer ibo, ulong iboOffset); + Model.Scene[] LoadScenes (out int defaultScene); + Image[] LoadImages (); + //Material[] LoadMaterial (); + } +} diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props index 2c30df4..144a6ae 100644 --- a/samples/Directory.Build.props +++ b/samples/Directory.Build.props @@ -25,14 +25,9 @@ <DefineConstants>NETSTANDARD;NETSTANDARD2_0;WITH_SHADOWS;_WITH_VKVG</DefineConstants> </PropertyGroup> - <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <ProjectReference Include="$(RootDirectory)CVKL\CVKL.csproj" /> - </ItemGroup> - <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <PackageReference Include="CVKL" Version="0.1.7-beta" /> - </ItemGroup> <ItemGroup> + <PackageReference Include="CVKL" Version="0.1.7-beta" /> <PackageReference Include="SpirVTasks" Version="0.1.9-beta" /> <PackageReference Include="Vulkan" Version="0.1.4" /> </ItemGroup> diff --git a/samples/DistanceFieldFontTest/Program.cs b/samples/DistanceFieldFontTest/Program.cs index 7d9ce45..5820a02 100644 --- a/samples/DistanceFieldFontTest/Program.cs +++ b/samples/DistanceFieldFontTest/Program.cs @@ -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; @@ -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; diff --git a/samples/Model/main.cs b/samples/Model/main.cs index f74b144..c8e6c42 100644 --- a/samples/Model/main.cs +++ b/samples/Model/main.cs @@ -166,6 +166,7 @@ namespace ModelSample { } protected override void OnResize () { + base.OnResize (); if (frameBuffers != null) for (int i = 0; i < swapChain.ImageCount; ++i) diff --git a/samples/Textured/main.cs b/samples/Textured/main.cs index 4705a54..988203f 100644 --- a/samples/Textured/main.cs +++ b/samples/Textured/main.cs @@ -219,6 +219,7 @@ namespace Textured { } protected override void OnResize () { + base.OnResize (); updateMatrices (); diff --git a/samples/TexturedCube/main.cs b/samples/TexturedCube/main.cs index f05c72f..445a06b 100644 --- a/samples/TexturedCube/main.cs +++ b/samples/TexturedCube/main.cs @@ -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 (); diff --git a/samples/Triangle/main.cs b/samples/Triangle/main.cs index 75c20ed..2dcb68f 100644 --- a/samples/Triangle/main.cs +++ b/samples/Triangle/main.cs @@ -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) { diff --git a/samples/Triangle/shaders/main.frag b/samples/Triangle/shaders/main.frag index 5ff09f5..5b2c3af 100644 --- a/samples/Triangle/shaders/main.frag +++ b/samples/Triangle/shaders/main.frag @@ -5,5 +5,5 @@ layout (location = 0) out vec4 outFragColor; void main() { - outFragColor = vec4(inColor, 1.0); + outFragColor = vec4(inColor, 0.5); }
\ No newline at end of file diff --git a/samples/common/CrowWin.cs b/samples/common/CrowWin.cs index 4eb8730..0a9809e 100644 --- a/samples/common/CrowWin.cs +++ b/samples/common/CrowWin.cs @@ -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) { diff --git a/samples/deferred/main.cs b/samples/deferred/main.cs index 5b74eed..9022d27 100644 --- a/samples/deferred/main.cs +++ b/samples/deferred/main.cs @@ -10,8 +10,8 @@ namespace deferred { class Deferred : VkWindow { static void Main (string[] args) { #if DEBUG - Instance.VALIDATION = true; - Instance.DEBUG_UTILS = true; + //Instance.VALIDATION = true; + //Instance.DEBUG_UTILS = true; Instance.RENDER_DOC_CAPTURE = false; #endif SwapChain.PREFERED_FORMAT = VkFormat.B8g8r8a8Srgb; @@ -55,7 +55,6 @@ namespace deferred { "../data/textures/uffizi_cube.ktx", }; string[] modelPathes = { - //"/mnt/devel/gts/vkChess.net/data/models/chess.glb", "../data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", "../data/models/shadow.glb", "../data/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]); @@ -283,8 +283,10 @@ namespace deferred { protected override void render () { - int idx = swapChain.GetNextImage (); + VkFence fence = dev.CreateFence(); + int idx = swapChain.GetNextImage (fence); if (idx < 0) { + dev.DestroyFence (fence); OnResize (); return; } @@ -292,19 +294,19 @@ namespace deferred { if (cmds[idx] == null) return; - presentQueue.Submit (cmdPbr, swapChain.presentComplete, renderer.DrawComplete); + dev.WaitForFence (drawFences[idx]); + dev.ResetFence (drawFences[idx]); - computeQ.Submit (cmdBlur, renderer.DrawComplete, blurComplete); - - presentQueue.Submit (cmds[idx], blurComplete, drawComplete[idx]); + presentQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx], drawFences[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 (); diff --git a/samples/pbr/main.cs b/samples/pbr/main.cs index b664c50..19064ab 100644 --- a/samples/pbr/main.cs +++ b/samples/pbr/main.cs @@ -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, @@ -33,15 +33,21 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Model", "samples\Model\Mode EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VkvgPipeline", "CVKL.Addons\VkvgPipeline\VkvgPipeline.csproj", "{58A3D415-B90A-4C54-B28F-F66E2F5E77E3}" EndProject -Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "compute", "samples\compute\compute.csproj", "{807FEF05-1368-4917-90E4-260DEBF5AA51}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Textured", "samples\Textured\Textured.csproj", "{D0E725A8-116C-4DED-A656-1C254AAFA953}" EndProject -Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "tests", "samples\tests\tests.csproj", "{F7848BAF-E3A8-47FD-959E-226D6E612718}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lines", "samples\Lines\Lines.csproj", "{164FF123-89B2-4546-8261-97D4867CE47B}" EndProject -Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "vkvg_tests", "samples\vkvg_tests\vkvg_tests.csproj", "{6FFDEEB2-90B2-4081-A9AF-DCEFB48F18DB}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sponza", "samples\sponza\sponza.csproj", "{A5DFED73-F5CE-4D08-B5CB-3B64CCD46526}" EndProject -Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "datas", "samples\datas\datas.csproj", "{39D038E6-35F7-4926-86D9-16D279A79767}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnvironmentPipeline", "CVKL.Addons\EnvironmentPipeline\EnvironmentPipeline.csproj", "{6EDDA888-7F40-4265-B50B-742BD0494807}" EndProject -Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "Textured", "samples\Textured\Textured.csproj", "{D0E725A8-116C-4DED-A656-1C254AAFA953}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "datas", "samples\datas\datas.csproj", "{0819E729-64D0-4D96-B7A7-FFDE86639977}" +EndProject +Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "compute", "samples\compute\compute.csproj", "{C6BA22CF-826F-460D-8AD7-3D272B0ABFF7}" +EndProject +Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "tests", "samples\tests\tests.csproj", "{5631BE86-EF1B-458D-B53B-1A897D4FBF76}" +EndProject +Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "vkvg_tests", "samples\vkvg_tests\vkvg_tests.csproj", "{4090A954-C6FE-4DE7-8F9E-E09CC7C7CAF9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -69,16 +75,19 @@ Global {B105512C-9461-4802-B299-A6E7A29CDAEE}.Release|Any CPU.ActiveCfg = Release|Any CPU {B105512C-9461-4802-B299-A6E7A29CDAEE}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU {B105512C-9461-4802-B299-A6E7A29CDAEE}.BuildPackages|Any CPU.ActiveCfg = Release|Any CPU + {B105512C-9461-4802-B299-A6E7A29CDAEE}.BuildPackages|Any CPU.Build.0 = Release|Any CPU {5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}.Debug|Any CPU.Build.0 = Debug|Any CPU {5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}.Release|Any CPU.ActiveCfg = Release|Any CPU {5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU {5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}.BuildPackages|Any CPU.ActiveCfg = Release|Any CPU + {5EC0F6C6-74C9-4509-8AC8-FAE3574AF5C7}.BuildPackages|Any CPU.Build.0 = Release|Any CPU {37D01BE5-5FE2-4742-BD5B-5D2C25FCF146}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {37D01BE5-5FE2-4742-BD5B-5D2C25FCF146}.Debug|Any CPU.Build.0 = Debug|Any CPU {37D01BE5-5FE2-4742-BD5B-5D2C25FCF146}.Release|Any CPU.ActiveCfg = Release|Any CPU {37D01BE5-5FE2-4742-BD5B-5D2C25FCF146}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU {37D01BE5-5FE2-4742-BD5B-5D2C25FCF146}.BuildPackages|Any CPU.ActiveCfg = Release|Any CPU + {37D01BE5-5FE2-4742-BD5B-5D2C25FCF146}.BuildPackages|Any CPU.Build.0 = Release|Any CPU {39E7BD7A-0489-4681-ACBD-6CEE13C6C9C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {39E7BD7A-0489-4681-ACBD-6CEE13C6C9C2}.Debug|Any CPU.Build.0 = Debug|Any CPU {39E7BD7A-0489-4681-ACBD-6CEE13C6C9C2}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -105,8 +114,8 @@ Global {85BDCBF2-4918-4F74-9FF1-DFEA8514A573}.Release|Any CPU.Build.0 = Release|Any CPU {85BDCBF2-4918-4F74-9FF1-DFEA8514A573}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU {85BDCBF2-4918-4F74-9FF1-DFEA8514A573}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU - {85BDCBF2-4918-4F74-9FF1-DFEA8514A573}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU - {85BDCBF2-4918-4F74-9FF1-DFEA8514A573}.BuildPackages|Any CPU.Build.0 = Debug|Any CPU + {85BDCBF2-4918-4F74-9FF1-DFEA8514A573}.BuildPackages|Any CPU.ActiveCfg = Release|Any CPU + {85BDCBF2-4918-4F74-9FF1-DFEA8514A573}.BuildPackages|Any CPU.Build.0 = Release|Any CPU {72CA1818-AF80-497D-AD9B-C67C1A0CA913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {72CA1818-AF80-497D-AD9B-C67C1A0CA913}.Debug|Any CPU.Build.0 = Debug|Any CPU {72CA1818-AF80-497D-AD9B-C67C1A0CA913}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -137,34 +146,56 @@ Global {58A3D415-B90A-4C54-B28F-F66E2F5E77E3}.Release|Any CPU.Build.0 = Release|Any CPU {58A3D415-B90A-4C54-B28F-F66E2F5E77E3}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU {58A3D415-B90A-4C54-B28F-F66E2F5E77E3}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU - {58A3D415-B90A-4C54-B28F-F66E2F5E77E3}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU - {58A3D415-B90A-4C54-B28F-F66E2F5E77E3}.BuildPackages|Any CPU.Build.0 = Debug|Any CPU - {807FEF05-1368-4917-90E4-260DEBF5AA51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {807FEF05-1368-4917-90E4-260DEBF5AA51}.Debug|Any CPU.Build.0 = Debug|Any CPU - {807FEF05-1368-4917-90E4-260DEBF5AA51}.Release|Any CPU.ActiveCfg = Release|Any CPU - {807FEF05-1368-4917-90E4-260DEBF5AA51}.Release|Any CPU.Build.0 = Release|Any CPU - {807FEF05-1368-4917-90E4-260DEBF5AA51}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU - {807FEF05-1368-4917-90E4-260DEBF5AA51}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU - {F7848BAF-E3A8-47FD-959E-226D6E612718}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F7848BAF-E3A8-47FD-959E-226D6E612718}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F7848BAF-E3A8-47FD-959E-226D6E612718}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F7848BAF-E3A8-47FD-959E-226D6E612718}.Release|Any CPU.Build.0 = Release|Any CPU - {F7848BAF-E3A8-47FD-959E-226D6E612718}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU - {F7848BAF-E3A8-47FD-959E-226D6E612718}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU - {6FFDEEB2-90B2-4081-A9AF-DCEFB48F18DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6FFDEEB2-90B2-4081-A9AF-DCEFB48F18DB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6FFDEEB2-90B2-4081-A9AF-DCEFB48F18DB}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU - {6FFDEEB2-90B2-4081-A9AF-DCEFB48F18DB}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU - {39D038E6-35F7-4926-86D9-16D279A79767}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {39D038E6-35F7-4926-86D9-16D279A79767}.Debug|Any CPU.Build.0 = Debug|Any CPU - {39D038E6-35F7-4926-86D9-16D279A79767}.Release|Any CPU.ActiveCfg = Release|Any CPU - {39D038E6-35F7-4926-86D9-16D279A79767}.Release|Any CPU.Build.0 = Release|Any CPU + {58A3D415-B90A-4C54-B28F-F66E2F5E77E3}.BuildPackages|Any CPU.ActiveCfg = Release|Any CPU + {58A3D415-B90A-4C54-B28F-F66E2F5E77E3}.BuildPackages|Any CPU.Build.0 = Release|Any CPU {D0E725A8-116C-4DED-A656-1C254AAFA953}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D0E725A8-116C-4DED-A656-1C254AAFA953}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0E725A8-116C-4DED-A656-1C254AAFA953}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0E725A8-116C-4DED-A656-1C254AAFA953}.Release|Any CPU.Build.0 = Release|Any CPU {D0E725A8-116C-4DED-A656-1C254AAFA953}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU {D0E725A8-116C-4DED-A656-1C254AAFA953}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU + {164FF123-89B2-4546-8261-97D4867CE47B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {164FF123-89B2-4546-8261-97D4867CE47B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {164FF123-89B2-4546-8261-97D4867CE47B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {164FF123-89B2-4546-8261-97D4867CE47B}.Release|Any CPU.Build.0 = Release|Any CPU + {164FF123-89B2-4546-8261-97D4867CE47B}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU + {164FF123-89B2-4546-8261-97D4867CE47B}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU + {164FF123-89B2-4546-8261-97D4867CE47B}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU + {A5DFED73-F5CE-4D08-B5CB-3B64CCD46526}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5DFED73-F5CE-4D08-B5CB-3B64CCD46526}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5DFED73-F5CE-4D08-B5CB-3B64CCD46526}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5DFED73-F5CE-4D08-B5CB-3B64CCD46526}.Release|Any CPU.Build.0 = Release|Any CPU + {A5DFED73-F5CE-4D08-B5CB-3B64CCD46526}.DebugCrow|Any CPU.ActiveCfg = DebugCrow|Any CPU + {A5DFED73-F5CE-4D08-B5CB-3B64CCD46526}.DebugCrow|Any CPU.Build.0 = DebugCrow|Any CPU + {A5DFED73-F5CE-4D08-B5CB-3B64CCD46526}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU + {6EDDA888-7F40-4265-B50B-742BD0494807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6EDDA888-7F40-4265-B50B-742BD0494807}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6EDDA888-7F40-4265-B50B-742BD0494807}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6EDDA888-7F40-4265-B50B-742BD0494807}.Release|Any CPU.Build.0 = Release|Any CPU + {6EDDA888-7F40-4265-B50B-742BD0494807}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU + {6EDDA888-7F40-4265-B50B-742BD0494807}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU + {6EDDA888-7F40-4265-B50B-742BD0494807}.BuildPackages|Any CPU.ActiveCfg = Release|Any CPU + {6EDDA888-7F40-4265-B50B-742BD0494807}.BuildPackages|Any CPU.Build.0 = Release|Any CPU + {0819E729-64D0-4D96-B7A7-FFDE86639977}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0819E729-64D0-4D96-B7A7-FFDE86639977}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0819E729-64D0-4D96-B7A7-FFDE86639977}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0819E729-64D0-4D96-B7A7-FFDE86639977}.Release|Any CPU.Build.0 = Release|Any CPU + {C6BA22CF-826F-460D-8AD7-3D272B0ABFF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6BA22CF-826F-460D-8AD7-3D272B0ABFF7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6BA22CF-826F-460D-8AD7-3D272B0ABFF7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6BA22CF-826F-460D-8AD7-3D272B0ABFF7}.Release|Any CPU.Build.0 = Release|Any CPU + {C6BA22CF-826F-460D-8AD7-3D272B0ABFF7}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU + {C6BA22CF-826F-460D-8AD7-3D272B0ABFF7}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU + {5631BE86-EF1B-458D-B53B-1A897D4FBF76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5631BE86-EF1B-458D-B53B-1A897D4FBF76}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5631BE86-EF1B-458D-B53B-1A897D4FBF76}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5631BE86-EF1B-458D-B53B-1A897D4FBF76}.Release|Any CPU.Build.0 = Release|Any CPU + {5631BE86-EF1B-458D-B53B-1A897D4FBF76}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU + {5631BE86-EF1B-458D-B53B-1A897D4FBF76}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU + {4090A954-C6FE-4DE7-8F9E-E09CC7C7CAF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4090A954-C6FE-4DE7-8F9E-E09CC7C7CAF9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4090A954-C6FE-4DE7-8F9E-E09CC7C7CAF9}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU + {4090A954-C6FE-4DE7-8F9E-E09CC7C7CAF9}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {39E7BD7A-0489-4681-ACBD-6CEE13C6C9C2} = {95E6BE33-0082-4E01-B064-864B411FD6B8} @@ -176,11 +207,14 @@ Global {A5F8810A-622A-4137-B779-8A34E4C7BDDC} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} {2B8B9356-982A-4CAC-9AE3-69DD49890FEF} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} {58A3D415-B90A-4C54-B28F-F66E2F5E77E3} = {95E6BE33-0082-4E01-B064-864B411FD6B8} - {807FEF05-1368-4917-90E4-260DEBF5AA51} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} - {F7848BAF-E3A8-47FD-959E-226D6E612718} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} - {6FFDEEB2-90B2-4081-A9AF-DCEFB48F18DB} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} - {39D038E6-35F7-4926-86D9-16D279A79767} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} {D0E725A8-116C-4DED-A656-1C254AAFA953} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} + {164FF123-89B2-4546-8261-97D4867CE47B} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} + {A5DFED73-F5CE-4D08-B5CB-3B64CCD46526} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} + {6EDDA888-7F40-4265-B50B-742BD0494807} = {95E6BE33-0082-4E01-B064-864B411FD6B8} + {0819E729-64D0-4D96-B7A7-FFDE86639977} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} + {C6BA22CF-826F-460D-8AD7-3D272B0ABFF7} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} + {5631BE86-EF1B-458D-B53B-1A897D4FBF76} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} + {4090A954-C6FE-4DE7-8F9E-E09CC7C7CAF9} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354} EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0 diff --git a/vknet.png b/vknet.png Binary files differnew file mode 100644 index 0000000..714f488 --- /dev/null +++ b/vknet.png |