]> O.S.I.I.S - jp/vke.net.git/commitdiff
tesselation support v0.2.1-beta
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 11 Sep 2021 21:54:11 +0000 (21:54 +0000)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 11 Sep 2021 21:54:11 +0000 (21:54 +0000)
30 files changed:
Directory.Build.props
addons/Directory.Build.props
addons/gltfLoader/PbrModel.cs
addons/gltfLoader/PbrModelTexArray.cs
addons/gltfLoader/glTFLoader.cs
clean.sh [deleted file]
samples/Directory.Build.props
samples/Tesselation/README.md [new file with mode: 0644]
samples/Tesselation/Tesselation.csproj [new file with mode: 0644]
samples/Tesselation/main.cs [new file with mode: 0644]
samples/Tesselation/shaders/main.frag [new file with mode: 0644]
samples/Tesselation/shaders/main.vert [new file with mode: 0644]
samples/Triangle/Triangle.csproj
samples/Triangle/main.cs
samples/Triangle/shaders/main.frag
samples/deferred/DeferredPbrRenderer.cs
vke.net.sln
vke/src/Camera.cs
vke/src/ExtensionMethods.cs
vke/src/VkWindow.cs
vke/src/base/Activable.cs
vke/src/base/Device.cs
vke/src/base/FrameBuffer.cs
vke/src/base/GraphicPipeline.cs
vke/src/base/GraphicPipelineConfig.cs
vke/src/base/PNextNode.cs [new file with mode: 0644]
vke/src/base/PhysicalDevice.cs
vke/src/base/RenderPass.cs
vke/src/model/Model.cs
vke/vke.csproj

index 2f2d567671afdceed292304d42b39891c73c912b..12b32f3ef3ea8bb062f7bd592cbb6cc4b9851712 100644 (file)
@@ -4,19 +4,19 @@
                <RestoreAdditionalProjectSources Condition="Exists('$(SolutionDir)build\$(Configuration)\')">$(SolutionDir)build\$(Configuration)\</RestoreAdditionalProjectSources>
                <SpirVTasksReleaseVersion>0.1.44</SpirVTasksReleaseVersion>
                <SpirVTasksPackageVersion>$(SpirVTasksReleaseVersion)</SpirVTasksPackageVersion>
-               <VkeReleaseVersion>0.2.0</VkeReleaseVersion>
+               <VkeReleaseVersion>0.2.1</VkeReleaseVersion>
                <VkePackageVersion>$(VkeReleaseVersion)-beta</VkePackageVersion>
                <UseStbSharp>true</UseStbSharp>
                <UseMemoryPools>false</UseMemoryPools>
                <LangVersion>7.2</LangVersion>
 
        </PropertyGroup>
-       
+
        <PropertyGroup Condition=" '$(UseMemoryPools)' == 'true'">
                <DefineConstants>$(DefineConstants);MEMORY_POOLS</DefineConstants>
        </PropertyGroup>
        <PropertyGroup Condition=" '$(UseStbSharp)' == 'true'">
                <DefineConstants>$(DefineConstants);STB_SHARP</DefineConstants>
        </PropertyGroup>
-       
+
 </Project>
index f8470f037c039e9e0854bc8e6c1848f7abba98bd..b0ee5f7afe39f01c41e61e73558334a329c93f4d 100644 (file)
@@ -4,7 +4,7 @@
                <RootDirectory>$(MSBuildThisFileDirectory)../</RootDirectory>
                <Deterministic>true</Deterministic>
 
-               <TargetFrameworks>netstandard2.0</TargetFrameworks>             
+               <TargetFrameworks>netstandard2.0</TargetFrameworks>
 
                <RepositoryUrl>https://github.com/jpbruyere/vke.net</RepositoryUrl>
                <PackageLicenseExpression>MIT</PackageLicenseExpression>
                <OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
                <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
                <IncludeDefaultNoneItems>false</IncludeDefaultNoneItems>
-                               
+
                <SpirVAdditionalIncludeDirectories>$(MSBuildThisFileDirectory)common\shaders</SpirVAdditionalIncludeDirectories>
-               
+
                <RestoreAdditionalProjectSources Condition="Exists('$(SolutionDir)build\$(Configuration)\')">$(SolutionDir)build\$(Configuration)\</RestoreAdditionalProjectSources>
        </PropertyGroup>
-    
+
        <ItemGroup Condition=" '$(Configuration)|$(Platform)' != 'BuildPackages|AnyCPU' ">
                <ProjectReference Include="..\..\vke\vke.csproj" />
        </ItemGroup>
        <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'BuildPackages|AnyCPU' ">
                <PackageReference Include="vke" Version="$(VkePackageVersion)" />
        </ItemGroup>
-       
+
        <ItemGroup>
                <PackageReference Include="SpirVTasks" Version="$(SpirVTasksPackageVersion)" />
-               <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />                  
-       </ItemGroup>    
-       
+               <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
+       </ItemGroup>
+
        <ItemGroup>
                <GLSLShader Include="shaders\**\*.frag;shaders\**\*.vert;shaders\**\*.comp;shaders\**\*.geom" />
        </ItemGroup>
index d5e04a8cc1bbdbfeaa135293c3baf4a5409cf0ba..0fc7fb58e5f183b6d786175c5972db09c24ab029 100644 (file)
@@ -17,6 +17,11 @@ namespace vke.glTF {
                public Buffer materialUBO;
 
                protected PbrModel () { }
+               /// <summary>
+               /// Load gltf file and load solids into vbo and ibo
+               /// </summary>
+               /// <param name="transferQ"></param>
+               /// <param name="path"></param>
                public PbrModel (Queue transferQ, string path) {
                        dev = transferQ.Dev;
                        using (CommandPool cmdPool = new CommandPool (dev, transferQ.index)) {
@@ -62,7 +67,7 @@ namespace vke.glTF {
                public void DrawAll (CommandBuffer cmd, PipelineLayout pipelineLayout, bool shadowPass = false) {
                        foreach (Scene sc in Scenes) {
                                foreach (Node node in sc.Root.Children)
-                                       RenderNode (cmd, pipelineLayout, node, sc.Root.localMatrix, shadowPass);                                
+                                       RenderNode (cmd, pipelineLayout, node, sc.Root.localMatrix, shadowPass);
                        }
                }
         public void Draw(CommandBuffer cmd, PipelineLayout pipelineLayout, Scene scene, bool shadowPass = false)
index a91e0990899d1208f77dc1eef56e2e91441106fd..e7439249f1dc147ffc35993b1ec4578819f9c17c 100644 (file)
@@ -73,15 +73,15 @@ namespace vke.glTF {
                                                        VkMemoryPropertyFlags.DeviceLocal, TEXTURE_DIM, TEXTURE_DIM, VkImageType.Image2D,
                                                        VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal, Image.ComputeMipLevels (TEXTURE_DIM), 1);
                                                PrimaryCommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);
-                                               texArray.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.ShaderReadOnlyOptimal);                                                
-                                               transferQ.EndSubmitAndWait (cmd, true);                                                                                         
+                                               texArray.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.ShaderReadOnlyOptimal);
+                                               transferQ.EndSubmitAndWait (cmd, true);
                                        }
 
                                        texArray.CreateView (VkImageViewType.ImageView2DArray, VkImageAspectFlags.Color, texArray.CreateInfo.arrayLayers);
                                        texArray.CreateSampler ();
                                        texArray.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
                                        texArray.SetName ("model texArray");
-                                       
+
 
                                        loadMaterials (ctx);
                                        materialUBO = new HostBuffer<Material> (dev, VkBufferUsageFlags.UniformBuffer, materials);
@@ -125,7 +125,7 @@ namespace vke.glTF {
 
                        if (node.Mesh != null) {
                                foreach (Primitive p in node.Mesh.Primitives) {
-                                       if (!shadowPass) 
+                                       if (!shadowPass)
                                                cmd.PushConstant (pipelineLayout, VkShaderStageFlags.Fragment, (int)p.material, (uint)Marshal.SizeOf<Matrix4x4> ());
                                        cmd.DrawIndexed (p.indexCount, 1, p.indexBase, p.vertexBase, 0);
                                }
@@ -139,7 +139,7 @@ namespace vke.glTF {
                protected override void Dispose (bool disposing) {
                        if (!isDisposed) {
                                if (disposing) {
-                                       texArray?.Dispose ();                                           
+                                       texArray?.Dispose ();
                                } else
                                        Debug.WriteLine ("model was not disposed");
                        }
index 5942deaab80b8c728b1139aedd25d95863b73048..9d39f4779ef776ac2696e669f11e015d9f5d2133 100644 (file)
@@ -17,6 +17,7 @@ namespace vke.glTF {
        using static Vulkan.Utils;
        using static vke.Model;
        using System.Runtime.CompilerServices;
+       using System.Reflection;
 
        /// <summary>
        /// Loading context with I as the vertex index type (uint16,uint32)
@@ -133,7 +134,7 @@ namespace vke.glTF {
                }
 
                public uint ImageCount => gltf.Images == null ? 0 : (uint)gltf.Images.Length;
-               
+
 
                //TODO: some buffer data are reused between primitives, and I duplicate the datas
                //buffers must be constructed without duplications
@@ -151,6 +152,9 @@ namespace vke.glTF {
                        int vertexCount = 0, indexCount = 0;
                        int autoNamedMesh = 1;
 
+                       bool secondUv = typeof (TVertex).GetFields ().
+                               Select<FieldInfo, VertexAttributeAttribute> (f => f.GetCustomAttribute<VertexAttributeAttribute> ()).Where (va=>va.Type == VertexAttributeType.UVs).Count() > 1;
+
                        meshes = new List<Mesh> ();
 
                        using (HostBuffer stagging = new HostBuffer (dev, VkBufferUsageFlags.TransferSrc, size)) {
@@ -235,7 +239,8 @@ namespace vke.glTF {
                                                                        inUvPtr = inUvPtr.Slice (8);
                                                                }
                                                                if (inUv1Ptr != null) {
-                                                                       inUv1Ptr.Slice (0, 8).CopyTo (stagVertPtr.Slice (32));
+                                                                       if (secondUv)
+                                                                               inUv1Ptr.Slice (0, 8).CopyTo (stagVertPtr.Slice (32));
                                                                        inUv1Ptr = inUvPtr.Slice (8);
                                                                }
                                                                stagVertPtr = stagVertPtr.Slice (vertexByteSize);
@@ -274,7 +279,7 @@ namespace vke.glTF {
                                                                                Span<ushort> usPtr = MemoryMarshal.Cast<byte, ushort> (stagIdxPtr);
                                                                                Span<uint> inPtr = MemoryMarshal.Cast<byte, uint> (inIdxPtr);
 
-                                                                               for (int i = 0; i < acc.Count; i++) 
+                                                                               for (int i = 0; i < acc.Count; i++)
                                                                                        usPtr[i] = (ushort)inPtr[i];
                                                                                stagIdxPtr = stagIdxPtr.Slice (acc.Count * 2);
                                                                        }
@@ -337,8 +342,8 @@ namespace vke.glTF {
                                return new Scene[] {};
 
                        List<Scene> scenes = new List<Scene> ();
-                       defaultScene = (int)gltf.Scene;                 
-                       
+                       defaultScene = (int)gltf.Scene;
+
                        for (int i = 0; i < gltf.Scenes.Length; i++) {
                                GL.Scene scene = gltf.Scenes[i];
                                Debug.WriteLine ("Loading Scene {0}", scene.Name);
@@ -378,11 +383,11 @@ namespace vke.glTF {
                                   M[12],M[13],M[14],M[15]);
                        }
 
-                       if (gltfNode.Translation != null) 
+                       if (gltfNode.Translation != null)
                                FromFloatArray (ref translation, gltfNode.Translation);
-                       if (gltfNode.Translation != null) 
-                               FromFloatArray (ref rotation, gltfNode.Rotation);                       
-                       if (gltfNode.Translation != null) 
+                       if (gltfNode.Translation != null)
+                               FromFloatArray (ref rotation, gltfNode.Rotation);
+                       if (gltfNode.Translation != null)
                                FromFloatArray (ref scale, gltfNode.Scale);
 
                        localTransform *=
@@ -418,10 +423,10 @@ namespace vke.glTF {
                        int texDim = (int)texArray.CreateInfo.extent.width;
 
                        PrimaryCommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);
-                       texArray.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, 
+                       texArray.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal,
                                                VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.Transfer);
                        transferQ.EndSubmitAndWait (cmd, true);
-                       
+
                        VkImageBlit imageBlit = new VkImageBlit {
                                srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0),
                                dstOffsets_1 = new VkOffset3D (texDim, texDim, 1)
@@ -455,8 +460,8 @@ namespace vke.glTF {
 
                                Vk.vkCmdBlitImage (cmd.Handle, vkimg.Handle, VkImageLayout.TransferSrcOptimal,
                                        texArray.Handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear);
-                               
-                               transferQ.EndSubmitAndWait (cmd, true);                                                         
+
+                               transferQ.EndSubmitAndWait (cmd, true);
 
                                vkimg.Dispose ();
                        }
diff --git a/clean.sh b/clean.sh
deleted file mode 100755 (executable)
index d39df8f..0000000
--- a/clean.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-rm -fr build && find . -iname bin -o -iname obj | xargs rm -rf
index 994e2c6f86dee59ff85aa3d95443959533d76dc0..c2598c2b838dcbfaf4755680090c7b87a636b179 100644 (file)
@@ -4,7 +4,7 @@
                <RootDirectory>$(MSBuildThisFileDirectory)../</RootDirectory>
                <Deterministic>true</Deterministic>
 
-               <TargetFrameworks>netcoreapp3.1</TargetFrameworks>              
+               <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
 
                <RepositoryUrl>https://github.com/jpbruyere/vke.net</RepositoryUrl>
                <License>MIT</License>
 
                <OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
                <OutputType>Exe</OutputType>
-               
+
                <IncludeDefaultNoneItems>false</IncludeDefaultNoneItems>
 
                <SpirVAdditionalIncludeDirectories>$(MSBuildThisFileDirectory)common\shaders</SpirVAdditionalIncludeDirectories>
-               
+
                <RestoreAdditionalProjectSources Condition="Exists('$(SolutionDir)build\$(Configuration)\')">$(SolutionDir)build\$(Configuration)\</RestoreAdditionalProjectSources>
        </PropertyGroup>
-               
+
        <ItemGroup Condition=" '$(Configuration)|$(Platform)' != 'BuildPackages|AnyCPU' ">
                <ProjectReference Include="..\..\vke\vke.csproj" />
        </ItemGroup>
        <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'BuildPackages|AnyCPU' ">
                <PackageReference Include="vke" Version="$(VkePackageVersion)" />
        </ItemGroup>
-                       
+
        <ItemGroup>
                <PackageReference Include="SpirVTasks" Version="$(SpirVTasksPackageVersion)" />
-       </ItemGroup>    
+       </ItemGroup>
 
        <ItemGroup>
                <Compile Include="$(MSBuildThisFileDirectory)common\Utils.cs;$(MSBuildThisFileDirectory)common\SampleBase.cs"/>
                <GLSLShader Include="shaders\**\*.frag;shaders\**\*.vert;shaders\**\*.comp;shaders\**\*.geom">
                        <LogicalName>shaders.%(Filename)%(Extension).spv</LogicalName>
-               </GLSLShader>           
+               </GLSLShader>
                <EmbeddedResource Include="ui\**\*.*">
                        <LogicalName>ui.%(Filename)%(Extension)</LogicalName>
                </EmbeddedResource>
-       </ItemGroup>     
+       </ItemGroup>
 </Project>
diff --git a/samples/Tesselation/README.md b/samples/Tesselation/README.md
new file mode 100644 (file)
index 0000000..27f9eb3
--- /dev/null
@@ -0,0 +1,60 @@
+### Creating buffers
+
+Vke has two classes to handle buffers. Mappable [`HostBuffer`](../../../../wiki/vke.HostBuffer) and device only [`GPUBuffer`](../../../../wiki/vke.GPUBuffer). 
+For this first simple example, we will only use host mappable buffers. Those classes can handle a Generic argument of a blittable type to handle arrays. Resources like buffers or images are activated in constructor, and they need to be explicitly disposed on cleanup. Create them in the `initVulkan` override.
+
+```csharp
+//the vertex buffer
+vbo = new HostBuffer<Vertex> (dev, VkBufferUsageFlags.VertexBuffer, vertices);
+//the index buffer
+ibo = new HostBuffer<ushort> (dev, VkBufferUsageFlags.IndexBuffer, indices);   
+//a permanantly mapped buffer for the mvp matrice
+uboMats = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, mvp, true);
+```
+
+To be able to access the mvp matrix in a shader, we need a descriptor. This implies to create a descriptor  pool to allocate it from and configure the triangle pipeline layout with a corresponding descriptor layout for our matrix.
+```csharp
+descriptorPool = new DescriptorPool (dev, 1, new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer));
+```
+Graphic pipeline configuration are predefined by the [`GraphicPipelineConfig`](../../../../wiki/vke.GraphicPipelineConfig) class, which ease sharing configs for several pipelines having lots in common. The pipeline layout will be automatically activated on pipeline creation, so that sharing layout among different pipelines will benefit from the reference counting to automatically dispose unused layout on pipeline clean up. It's the same for [`DescriptorSetLayout`](../../wiki/api/DescriptorSetLayout).
+```csharp
+GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (
+      VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false);
+      
+cfg.Layout = new PipelineLayout (dev,
+  new DescriptorSetLayout (dev,
+     new VkDescriptorSetLayoutBinding (
+       0, VkShaderStageFlags.Vertex, VkDescriptorType.UniformBuffer)));
+```
+Next we configure a default [`RenderPass`](../../../../wiki/vke.RenderPass) with just a color attachment for the swap chain image, a default sub-pass is automatically created and the render pass activation will follow the pipeline life cycle and will be automatically disposed when no longer in use.
+```csharp
+       cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, cfg.Samples);
+```
+Configuration of vertex bindings and attributes
+```csharp
+cfg.AddVertexBinding<Vertex> (0);
+cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat,  //position
+                            VkFormat.R32g32b32Sfloat);//color
+```
+shader are automatically compiled by [`SpirVTasks`](../../SpirVTasks/README.md) if added to the project. The resulting shaders are automatically embedded in the assembly. To specifiy that the shader path is a resource name, put the **'#'** prefix. Else the path will be search on disk.
+```csharp
+cfg.AddShader (dev, VkShaderStageFlags.Vertex, "#shaders.main.vert.spv");
+cfg.AddShader (dev, VkShaderStageFlags.Fragment, "#shaders.main.frag.spv");
+```
+Once the pipeline configuration is complete, we use it to effectively create and activate a graphic pipeline. Activables used by the pipeline (like the RenderPass, or the PipelineLayout) are referenced in the newly created managed pipeline. So the Configuration object doesn't need cleanup.
+```csharp
+       pipeline = new GraphicPipeline (cfg);
+```
+Because descriptor layouts used for a pipeline are only activated on pipeline activation, descriptor sets must not be allocated before, except if the layout has been manually activated, but in this case, layouts will also need to be explicitly disposed.
+```csharp
+       descriptorSet = descriptorPool.Allocate (pipeline.Layout.DescriptorSetLayouts[0]);
+```
+The descriptor update is a two step operation. First we create a [`DescriptorSetWrites`](../../../../wiki/vke.DescriptorSetWrites) object defining the layout(s), than we write the descriptor(s).
+The `Descriptor` property of the mvp HostBuffer will return a default descriptor with no offset of the full size of the buffer.
+
+```csharp
+DescriptorSetWrites uboUpdate =
+    new DescriptorSetWrites (descriptorSet, pipeline.Layout.DescriptorSetLayouts[0]);
+
+uboUpdate.Write (dev, uboMats.Descriptor);
+```
diff --git a/samples/Tesselation/Tesselation.csproj b/samples/Tesselation/Tesselation.csproj
new file mode 100644 (file)
index 0000000..672fb5a
--- /dev/null
@@ -0,0 +1,5 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <IncludeDefaultNoneItems>false</IncludeDefaultNoneItems>
+  </PropertyGroup>
+</Project>
diff --git a/samples/Tesselation/main.cs b/samples/Tesselation/main.cs
new file mode 100644 (file)
index 0000000..6f95779
--- /dev/null
@@ -0,0 +1,186 @@
+// 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.Numerics;
+using System.Runtime.InteropServices;
+using vke;
+using Vulkan;
+using Glfw;
+
+namespace Tesselation {
+       class Program : SampleBase {
+               static void Main (string[] args) {
+#if DEBUG
+                       Instance.VALIDATION = true;
+#endif
+                       using (Program vke = new Program ()) {
+                               vke.Run ();
+                       }
+               }
+
+               const float rotSpeed = 0.01f, zoomSpeed = 0.01f;
+               float rotX, rotY, zoom = 1f;
+
+               //vertex structure
+               [StructLayout(LayoutKind.Sequential)]
+               struct Vertex {
+                       Vector3 position;
+                       Vector3 color;
+
+                       public Vertex (float x, float y, float z, float r, float g, float b) {
+                               position = new Vector3 (x, y, z);
+                               color = new Vector3 (r, g, b);
+                       }
+               }
+
+               Matrix4x4 mvp;      //the model view projection matrix
+
+               HostBuffer ibo;     //a host mappable buffer to hold the indices.
+               HostBuffer vbo;     //a host mappable buffer to hold vertices.
+               HostBuffer uboMats; //a host mappable buffer for mvp matrice.
+
+               DescriptorPool descriptorPool;
+               DescriptorSet descriptorSet;//descriptor set for the mvp matrice.
+
+               FrameBuffers frameBuffers;      //the frame buffer collection coupled to the swapchain images
+               GraphicPipeline pipeline;   //the triangle rendering pipeline
+
+               //triangle vertices (position + color per vertex) and indices.
+               Vertex[] vertices = {
+                       new Vertex (-1.0f, -1.0f, 0.0f ,  1.0f, 0.0f, 0.0f),
+                       new Vertex ( 1.0f, -1.0f, 0.0f ,  0.0f, 1.0f, 0.0f),
+                       new Vertex ( 0.0f,  1.0f, 0.0f ,  0.0f, 0.0f, 1.0f),
+               };
+               ushort[] indices = new ushort[] { 0, 1, 2 };
+
+               protected override void initVulkan () {                 
+                       base.initVulkan ();
+
+                       //first create the needed buffers
+                       vbo = new HostBuffer<Vertex> (dev, VkBufferUsageFlags.VertexBuffer, vertices);
+                       ibo = new HostBuffer<ushort> (dev, VkBufferUsageFlags.IndexBuffer, indices);
+                       //because mvp matrice may be updated by mouse move, we keep it mapped after creation.
+                       uboMats = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, mvp, true);
+
+                       //a descriptor pool to allocate the mvp matrice descriptor from.
+                       descriptorPool = new DescriptorPool (dev, 1, new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer));
+
+                       //Graphic pipeline configuration are predefined by the GraphicPipelineConfig class, which ease sharing config for several pipelines having lots in common.
+                       using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false)) {
+                               //Create the pipeline layout, it will be automatically activated on pipeline creation, so that sharing layout among different pipelines will benefit
+                               //from the reference counting to automatically dispose unused layout on pipeline clean up. It's the same for DescriptorSetLayout.
+                               cfg.Layout = new PipelineLayout (dev,
+                                       new DescriptorSetLayout (dev, new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex, VkDescriptorType.UniformBuffer)));
+                               //create a default renderpass with just a color attachment for the swapchain image, a default subpass is automatically created and the renderpass activation
+                               //will follow the pipeline life cicle and will be automatically disposed when no longuer used.
+                               cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, cfg.Samples);
+                               //configuration of vertex bindings and attributes
+                               cfg.AddVertexBinding<Vertex> (0);
+                               cfg.AddVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat);//position + color
+
+                               //shader are automatically compiled by SpirVTasks if added to the project. The resulting shaders are automatically embedded in the assembly.
+                               //To specifiy that the shader path is a resource name, put the '#' prefix. Else the path will be search on disk.
+                               cfg.AddShaders (
+                                       new ShaderInfo (dev, VkShaderStageFlags.Vertex, "#shaders.main.vert.spv"),
+                                       new ShaderInfo (dev, VkShaderStageFlags.Fragment, "#shaders.main.frag.spv")
+                               );
+
+                               //create and activate the pipeline with the configuration we've just done.
+                               pipeline = new GraphicPipeline (cfg);
+                       }
+
+                       //because descriptor layout used for a pipeline are only activated on pipeline activation, descriptor set must not be allocated before, except if the layout has been manually activated, 
+                       //but in this case, layout will need also to be explicitly disposed.
+                       descriptorSet = descriptorPool.Allocate (pipeline.Layout.DescriptorSetLayouts[0]);
+
+                       //Write the content of the descriptor, the mvp matrice.
+                       DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descriptorSet, pipeline.Layout.DescriptorSetLayouts[0]);
+                       //Descriptor property of the mvp buffer will return a default descriptor with no offset of the full size of the buffer.
+                       uboUpdate.Write (dev, uboMats.Descriptor);
+
+                       //allocate the default VkWindow buffers, one per swapchain image. Their will be only reset when rebuilding and not reallocated.
+                       cmds = cmdPool.AllocateCommandBuffer (swapChain.ImageCount);
+               }
+
+               //view update override, see base method for more informations.
+               public override void UpdateView () {
+                       mvp =
+                               Matrix4x4.CreateFromAxisAngle (Vector3.UnitY, rotY) *
+                               Matrix4x4.CreateFromAxisAngle (Vector3.UnitX, rotX) *
+                               Matrix4x4.CreateTranslation (0, 0, -3f * zoom) *
+                               Utils.CreatePerspectiveFieldOfView (Utils.DegreesToRadians (45f), (float)swapChain.Width / (float)swapChain.Height, 0.1f, 256.0f);
+
+                       uboMats.Update (mvp, (uint)Marshal.SizeOf<Matrix4x4> ());
+                       base.UpdateView ();
+               }
+               protected override void onMouseMove (double xPos, double yPos) {
+                       double diffX = lastMouseX - xPos;
+                       double diffY = lastMouseY - yPos;
+                       if (GetButton (MouseButton.Left) == InputAction.Press) {
+                               rotY -= rotSpeed * (float)diffX;
+                               rotX += rotSpeed * (float)diffY;
+                               updateViewRequested = true;
+                       } else if (GetButton (MouseButton.Right) == InputAction.Press) {
+                               zoom += zoomSpeed * (float)diffY;
+                               updateViewRequested = true;
+                       }
+               }
+
+               void buildCommandBuffers() {
+                       cmdPool.Reset (VkCommandPoolResetFlags.ReleaseResources);
+
+                       for (int i = 0; i < swapChain.ImageCount; ++i) {
+                               FrameBuffer fb = frameBuffers[i];
+                               cmds[i].Start ();
+
+                               pipeline.RenderPass.Begin (cmds[i], fb);
+
+                               cmds[i].SetViewport (swapChain.Width, swapChain.Height);
+                               cmds[i].SetScissor (swapChain.Width, swapChain.Height);
+
+                               cmds[i].BindDescriptorSet (pipeline.Layout, descriptorSet);
+
+                               cmds[i].BindPipeline (pipeline);
+
+                               cmds[i].BindVertexBuffer (vbo);
+                               cmds[i].BindIndexBuffer (ibo, VkIndexType.Uint16);
+                               cmds[i].DrawIndexed ((uint)indices.Length);
+
+                               pipeline.RenderPass.End (cmds[i]);
+
+                               cmds[i].End ();
+                       }
+               }
+
+               protected override void OnResize () {
+                       base.OnResize ();
+                       UpdateView ();
+
+                       frameBuffers?.Dispose();
+                       frameBuffers = pipeline.RenderPass.CreateFrameBuffers(swapChain);
+
+                       buildCommandBuffers ();
+               }
+               //clean up
+               protected override void Dispose (bool disposing) {              
+                       dev.WaitIdle ();
+                       if (disposing) {
+                               if (!isDisposed) {
+                                       //pipeline clean up will dispose PipelineLayout, DescriptorSet layouts and render pass automatically. If their reference count is zero, their handles will be destroyed.
+                                       pipeline.Dispose ();
+                                       //frame buffers are automatically activated on creation as for resources, so it requests an explicit call to dispose.
+                                       frameBuffers?.Dispose();
+                                       //the descriptor pool
+                                       descriptorPool.Dispose ();
+                                       //resources have to be explicityly disposed.
+                                       vbo.Dispose ();
+                                       ibo.Dispose ();
+                                       uboMats.Dispose ();
+                               }
+                       }
+
+                       base.Dispose (disposing);
+               }
+       }
+}
diff --git a/samples/Tesselation/shaders/main.frag b/samples/Tesselation/shaders/main.frag
new file mode 100644 (file)
index 0000000..a3cafac
--- /dev/null
@@ -0,0 +1,12 @@
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inColor;
+layout (location = 0) out vec4 outFragColor;
+
+void main() 
+{
+    outFragColor = vec4(inColor, 1.0);
+}
\ No newline at end of file
diff --git a/samples/Tesselation/shaders/main.vert b/samples/Tesselation/shaders/main.vert
new file mode 100644 (file)
index 0000000..0997ca9
--- /dev/null
@@ -0,0 +1,26 @@
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+layout (location = 0) in vec3 inPos;
+layout (location = 1) in vec3 inColor;
+
+layout (binding = 0) uniform UBO 
+{
+       mat4 mvp;
+};
+
+layout (location = 0) out vec3 outColor;
+
+out gl_PerVertex 
+{
+    vec4 gl_Position;   
+};
+
+
+void main() 
+{
+       outColor = inColor;
+       gl_Position = mvp * vec4(inPos.xyz, 1.0);
+}
index 1b81ff7008bbdcad78ab00ece0725f8eef035bc0..672fb5a2d9852417bc0b675f4e428d47f7f14319 100644 (file)
@@ -1,5 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
-  <PropertyGroup>              
-    <IncludeDefaultNoneItems>false</IncludeDefaultNoneItems>           
-  </PropertyGroup>  
+  <PropertyGroup>
+    <IncludeDefaultNoneItems>false</IncludeDefaultNoneItems>
+  </PropertyGroup>
 </Project>
index 1d6e97d9ef69ec4f4cca39f3634d846c2df0db95..d3804aff861d5cf1001b312f9d46a546ce252939 100644 (file)
@@ -55,7 +55,7 @@ namespace Triangle {
                };
                ushort[] indices = new ushort[] { 0, 1, 2 };
 
-               protected override void initVulkan () {                 
+               protected override void initVulkan () {
                        base.initVulkan ();
 
                        //first create the needed buffers
@@ -91,7 +91,7 @@ namespace Triangle {
                                pipeline = new GraphicPipeline (cfg);
                        }
 
-                       //because descriptor layout used for a pipeline are only activated on pipeline activation, descriptor set must not be allocated before, except if the layout has been manually activated, 
+                       //because descriptor layout used for a pipeline are only activated on pipeline activation, descriptor set must not be allocated before, except if the layout has been manually activated,
                        //but in this case, layout will need also to be explicitly disposed.
                        descriptorSet = descriptorPool.Allocate (pipeline.Layout.DescriptorSetLayouts[0]);
 
@@ -164,7 +164,7 @@ namespace Triangle {
                        buildCommandBuffers ();
                }
                //clean up
-               protected override void Dispose (bool disposing) {              
+               protected override void Dispose (bool disposing) {
                        dev.WaitIdle ();
                        if (disposing) {
                                if (!isDisposed) {
index 5ff09f56495008f637b82e21fa37963af55f5aeb..a3cafac5cda8e14103a15bc8225161d875a773f7 100644 (file)
@@ -1,4 +1,7 @@
-#include <preamble.inc>
+#version 450
+
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
 
 layout (location = 0) in vec3 inColor;
 layout (location = 0) out vec4 outFragColor;
index 9a898a46eb5fcc3dc59464ee811bdd7abed7bef9..e1f394ac5d93625ff8ddba93fb43a159ce177767 100644 (file)
@@ -117,7 +117,7 @@ namespace deferred {
                                new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 6),
                                new VkDescriptorPoolSize (VkDescriptorType.InputAttachment, 5),
                                new VkDescriptorPoolSize (VkDescriptorType.StorageImage, 4)
-                       );                              
+                       );
 
                        uboMatrices = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, matrices, true);
                        uboLights = new HostBuffer<Light> (dev, VkBufferUsageFlags.UniformBuffer, lights, true);
@@ -216,14 +216,14 @@ namespace deferred {
 
                        if (TEXTURE_ARRAY) {
                                descLayoutMain.Bindings.Add (new VkDescriptorSetLayoutBinding (7, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler));//texture array
-                       } else { 
+                       } else {
                                descLayoutTextures = new DescriptorSetLayout (dev,
                                        new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),
                                        new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),
                                        new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),
                                        new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),
                                        new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)
-                               ); 
+                               );
                        }
 
                        descLayoutGBuff = new DescriptorSetLayout (dev,
@@ -277,7 +277,7 @@ namespace deferred {
                                cfg.rasterizationState.cullMode = VkCullModeFlags.Front;
                                //COMPOSE PIPELINE
                                cfg.blendAttachments.Clear ();
-                               cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false));                             
+                               cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false));
                                cfg.SubpassIndex = SP_COMPOSE;
                                cfg.Layout = gBuffPipeline.Layout;
                                cfg.depthStencilState.depthTestEnable = false;
@@ -310,7 +310,7 @@ namespace deferred {
                        matrices.prefilteredCubeMipLevels = envCube.prefilterCube.CreateInfo.mipLevels;
 
                        DescriptorSetWrites dsMainWrite = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings.GetRange (0, 5).ToArray ());
-                       dsMainWrite.Write (dev, 
+                       dsMainWrite.Write (dev,
                                uboMatrices.Descriptor,
                                envCube.irradianceCube.Descriptor,
                                envCube.prefilterCube.Descriptor,
@@ -329,10 +329,10 @@ namespace deferred {
                        model?.Dispose ();
 
                        if (TEXTURE_ARRAY) {
-                               PbrModelTexArray mod = new PbrModelTexArray (transferQ, path);                          
+                               PbrModelTexArray mod = new PbrModelTexArray (transferQ, path);
                                DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[5], descLayoutMain.Bindings[7]);
                                uboUpdate.Write (dev, mod.materialUBO.Descriptor, mod.texArray.Descriptor);
-                               
+
                                model = mod;
                        } else {
                                model = new PbrModelSeparatedTextures (transferQ, path,
@@ -468,7 +468,7 @@ namespace deferred {
                        frameBuffer?.Dispose ();
                        createGBuff ();
 
-                       frameBuffer = new FrameBuffer (renderPass, width, height, new Image[] {
+                       frameBuffer = new FrameBuffer (renderPass, width, height, 1, new Image[] {
                                        hdrImgResolved, null, gbColorRough, gbEmitMetal, gbN_AO, gbPos});
                }
 
index eebcb5d437ffba44130d9070eb71e4fec204bcf1..c19d4edd01426ad163e89f944d7bf1efba14026d 100644 (file)
@@ -1,4 +1,4 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio Version 16
 VisualStudioVersion = 16.0.30104.148
 MinimumVisualStudioVersion = 10.0.40219.1
@@ -44,6 +44,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "deferred", "samples\deferre
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "pbr", "samples\pbr\pbr.csproj", "{7EB2430B-6BC0-4AE9-B1FA-57C3DB2AE1C5}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tesselation", "samples\Tesselation\Tesselation.csproj", "{FCE58652-47B9-4A3C-90B0-3B2EE2C8042D}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                BuildPackages|Any CPU = BuildPackages|Any CPU
@@ -137,6 +139,14 @@ Global
                {7EB2430B-6BC0-4AE9-B1FA-57C3DB2AE1C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {7EB2430B-6BC0-4AE9-B1FA-57C3DB2AE1C5}.Release|Any CPU.Build.0 = Release|Any CPU
                {7EB2430B-6BC0-4AE9-B1FA-57C3DB2AE1C5}.ReleaseSpirVTasks|Any CPU.ActiveCfg = Release|Any CPU
+               {FCE58652-47B9-4A3C-90B0-3B2EE2C8042D}.BuildPackages|Any CPU.ActiveCfg = Debug|Any CPU
+               {FCE58652-47B9-4A3C-90B0-3B2EE2C8042D}.BuildPackages|Any CPU.Build.0 = Debug|Any CPU
+               {FCE58652-47B9-4A3C-90B0-3B2EE2C8042D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {FCE58652-47B9-4A3C-90B0-3B2EE2C8042D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {FCE58652-47B9-4A3C-90B0-3B2EE2C8042D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {FCE58652-47B9-4A3C-90B0-3B2EE2C8042D}.Release|Any CPU.Build.0 = Release|Any CPU
+               {FCE58652-47B9-4A3C-90B0-3B2EE2C8042D}.ReleaseSpirVTasks|Any CPU.ActiveCfg = Debug|Any CPU
+               {FCE58652-47B9-4A3C-90B0-3B2EE2C8042D}.ReleaseSpirVTasks|Any CPU.Build.0 = Debug|Any CPU
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
@@ -153,6 +163,7 @@ Global
                {8185163E-A67C-4C0E-8548-67E2A9F16309} = {16439374-B8DB-4643-8116-EB3358B49A12}
                {D9A41382-444E-44ED-B638-3D8F06F2FBC2} = {16439374-B8DB-4643-8116-EB3358B49A12}
                {7EB2430B-6BC0-4AE9-B1FA-57C3DB2AE1C5} = {16439374-B8DB-4643-8116-EB3358B49A12}
+               {FCE58652-47B9-4A3C-90B0-3B2EE2C8042D} = {16439374-B8DB-4643-8116-EB3358B49A12}
        EndGlobalSection
        GlobalSection(ExtensibilityGlobals) = postSolution
                SolutionGuid = {1360F94D-CF3C-4121-A8D7-E227F41668F1}
index d0da1d14230fae05c823603c59a96f0fd78b1621..383e70066a92894ce42d655f269d06f237c00494 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (c) 2019  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+// Copyright (c) 2019-2021  Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
 //
 // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
 using System.Numerics;
@@ -29,94 +29,146 @@ namespace vke {
                public float FarPlane => zFar;
 
                public CamType Type;
-               
+
                public float AspectRatio {
-                       get { return aspectRatio; }
+                       get => aspectRatio;
                        set {
                                aspectRatio = value;
-                               Update ();
+                               update ();
                        }
                }
                public float FieldOfView {
-                       get { return fov; }
+                       get => fov;
                        set {
                                fov = value;
-                               Update ();
+                               update ();
                        }
                }
-               public Matrix4x4 Perspective {
-                       get { return Matrix4x4.CreatePerspectiveFieldOfView (fov, aspectRatio, zNear, zFar); }
-               }
 
                public Camera (float fieldOfView, float aspectRatio, float nearPlane = 0.1f, float farPlane = 16f) {
                        fov = fieldOfView;
                        this.aspectRatio = aspectRatio;
                        zNear = nearPlane;
                        zFar = farPlane;
-                       Update ();
+                       Model = Matrix4x4.Identity;
+                       update ();
                }
-
+               /// <summary>
+               /// Rotate the camera by an angle given in radian for each axes.
+               /// </summary>
+               /// <param name="x">rotation around the x axis</param>
+               /// <param name="y">rotation around the y axis</param>
+               /// <param name="z">rotation around the z axis</param>
                public void Rotate (float x, float y, float z = 0) {
                        rotation.X += rotSpeed * x;
                        rotation.Y += rotSpeed * y;
                        rotation.Z += rotSpeed * z;
-                       Update ();
+                       update ();
+               }
+               public void Rotate (Vector3 angle) {
+                       rotation += rotSpeed * angle;
+                       update ();
                }
                public float Zoom {
-                       get { return zoom; }
+                       get => zoom;
                        set {
                                zoom = value;
-                               Update ();
+                               update ();
                        }
                }
+               /// <summary>
+               /// Set the current rotation angle in radian around each axes
+               /// </summary>
+               /// <param name="x">current rotation around the x axis</param>
+               /// <param name="y">current rotation around the y axis</param>
+               /// <param name="z">current rotation around the z axis</param>
                public void SetRotation (float x, float y, float z = 0) {
                        rotation.X = x;
                        rotation.Y = y;
                        rotation.Z = z;
-                       Update ();
+                       update ();
                }
+               public void SetRotation (Vector3 newRotationVector) {
+                       rotation = newRotationVector;
+                       update ();
+               }
+               /// <summary>
+               /// Set the current position of the camera.
+               /// </summary>
+               /// <param name="x">position on the x axis</param>
+               /// <param name="y">position on the y axis</param>
+               /// <param name="z">position on the z axis</param>
                public void SetPosition (float x, float y, float z = 0) {
                        position.X = x;
                        position.Y = y;
                        position.Z = z;
-                       Update ();
+                       update ();
+               }
+               public void SetPosition (Vector3 newPosition) {
+                       position = newPosition;
+                       update ();
                }
+               /// <summary>
+               /// Move the camera by an amount given for each axis.
+               /// </summary>
+               /// <param name="x">displacement on the x axis</param>
+               /// <param name="y">displacement on the y axis</param>
+               /// <param name="z">displacement on the z axis</param>
                public void Move (float x, float y, float z = 0) {
                        position.X += moveSpeed * x;
                        position.Y += moveSpeed * y;
                        position.Z += moveSpeed * z;
-                       Update ();
+                       update ();
+               }
+               public void Move (Vector3 displacementVector) {
+                       position += moveSpeed * displacementVector;
+                       update ();
                }
                public void SetZoom (float factor) {
                        zoom += zoomSpeed * factor;
-                       Update ();
+                       update ();
                }
-
+               /// <summary>
+               /// The resulting projection matrix of the camera.
+               /// Manual update may be triggered by calling the 'Update' method.
+               /// </summary>
                public Matrix4x4 Projection { get; private set;}
+               /// <summary>
+               /// The resulting view matrix of the camera.
+               /// Manual update may be triggered by calling the 'Update' method.
+               /// </summary>
                public Matrix4x4 View { get; private set;}
+               /// <summary>
+               /// The model matrix. By default set to identity. It does not influence the
+               /// view and proj matrices, it's only a convenient store place for the model matrix
+               /// associated with this camera.
+               /// </summary>
                public Matrix4x4 Model {
-                       get { return model; }
+                       get => model;
                        set {
                                model = value;
-                               Update ();
-                       } 
+                               update ();
+                       }
                }
-
-               public Matrix4x4 SkyboxView {
-                       get { 
-                               return
+               /// <summary>
+               /// compute the skybox view matrix for this camera using it's rotation angles.
+               /// </summary>
+               public Matrix4x4 SkyboxView =>
                                        Matrix4x4.CreateFromAxisAngle (Vector3.UnitZ, rotation.Z) *
                                        Matrix4x4.CreateFromAxisAngle (Vector3.UnitY, rotation.Y) *
                                        Matrix4x4.CreateFromAxisAngle (Vector3.UnitX, rotation.X);
-                       }
-               }
-
-               public void Update () {
+               /// <summary>
+               /// Recompute the projection and the view matrices from the current parameters
+               /// of this camera (fov, near, far, position, rotation, aspectRatio).
+               /// After the call to this method, the projection and the view matrices will be
+               /// in sync with the parameters. It's automatically called after rotation, move, etc...
+               /// </summary>
+               void update () {
                        Projection =  Vulkan.Utils.CreatePerspectiveFieldOfView (fov, aspectRatio, zNear, zFar);
 
-                       Matrix4x4 translation = Matrix4x4.CreateTranslation (position * zoom);// * new Vector3(1,1,-1)) ;
+                       Matrix4x4 translation = Matrix4x4.CreateTranslation (position * zoom);
                        if (Type == CamType.LookAt) {
-                               View = 
+                               View =
                                                Matrix4x4.CreateFromAxisAngle (Vector3.UnitZ, rotation.Z) *
                                                Matrix4x4.CreateFromAxisAngle (Vector3.UnitY, rotation.Y) *
                                                Matrix4x4.CreateFromAxisAngle (Vector3.UnitX, rotation.X) *
index 589ae2a9bcdf5edacf6b4d23ccaa6066d8339cd2..93c680013802fa16f475301190ba08e3a2725e85 100644 (file)
@@ -89,7 +89,7 @@ namespace vke {
                        ctx.Handles.Add (hnd);
                        return hnd.AddrOfPinnedObject ();
                }
-               public static IntPtr Pin<T> (this List<T> obj, PinnedObjects ctx) {
+               public static IntPtr Pin<T> (this IList<T> obj, PinnedObjects ctx) {
                        GCHandle hnd = GCHandle.Alloc (obj.ToArray (), GCHandleType.Pinned);
                        ctx.Handles.Add (hnd);
                        return hnd.AddrOfPinnedObject ();
index 0c165e0d8f9ac56336cb71cbe2e7be01b9fdbeea..bd92295c0876044c852e1f06c091908abafd2fa5 100644 (file)
@@ -18,17 +18,17 @@ namespace vke {
        public abstract class VkWindow : IDisposable {
 
                /** GLFW callback may return a custom pointer, this list makes the link between the GLFW window pointer and the
-                       manage VkWindow instance. */            
+                       manage VkWindow instance. */
                static Dictionary<IntPtr,VkWindow> windows = new Dictionary<IntPtr, VkWindow>();
                /** GLFW window native pointer. */
                IntPtr hWin;
                /**Vulkan Surface */
                protected VkSurfaceKHR hSurf;
                /**vke Instance encapsulating a VkInstance. */
-               protected Instance instance;    
+               protected Instance instance;
                /**vke Physical device associated with this window*/
                protected PhysicalDevice phy;
-               /**vke logical device */                        
+               /**vke logical device */
                protected Device dev;
                protected PresentQueue presentQueue;
                protected SwapChain swapChain;
@@ -47,7 +47,7 @@ namespace vke {
 
                /**Default camera initialized with a Field of view of 40° and and aspect ratio of 1. */
                protected Camera camera = new Camera (Utils.DegreesToRadians (45f), 1f);
-               
+
                public Modifier KeyModifiers = 0;
                IntPtr currentCursor;
                uint frameCount;
@@ -323,7 +323,7 @@ namespace vke {
                /// - if the `updateViewRequested` field is set to 'true', call the `UpdateView` method.
                /// - frame counting and chrono.
                /// - if elapsed time reached `UpdateFrequency` value, the `Update` method is called and the elapsed time chrono is reseet.
-               /// - GLFW events are polled at the end of the loop. 
+               /// - GLFW events are polled at the end of the loop.
                /// </summary>
                public virtual void Run () {
                        initVulkan ();
@@ -348,7 +348,7 @@ namespace vke {
                                        frameChrono.Stop ();
                                        totTime += frameChrono.ElapsedMilliseconds;
                                        fps = (uint)((double)frameCount / (double)totTime * 1000.0);
-                                       Glfw3.SetWindowTitle (hWin, "FPS: " + fps.ToString ());                    
+                                       Glfw3.SetWindowTitle (hWin, "FPS: " + fps.ToString ());
                                        if (totTime > 2000) {
                                                frameCount = 0;
                                                totTime = 0;
index 2f7edf52ca56bcd80ed985470a76308e02f09e3d..1c3d0bef9fa0888df29beb94879d469aea77d35a 100644 (file)
@@ -50,6 +50,7 @@ namespace vke {
                /// Vulkan logical device this activable is bound to.
                /// </summary>
                [XmlIgnore] public Device Dev { get; private set; }
+               public PNextNode PNext;
 
                #region CTOR
                protected Activable (Device dev) {
index fca29f2143e009cbd8fce9d6b870bae1762dbe85..293585d6971f958e3e160cb05aa1328d76771493 100644 (file)
@@ -20,7 +20,7 @@ namespace vke {
                public readonly PhysicalDevice phy;                                                                             /**Vulkan physical device class*/
 
                VkDevice dev;
-               public VkDevice VkDev => dev;                                           /**Vulkan logical device handle*/               
+               public VkDevice VkDev => dev;                                           /**Vulkan logical device handle*/
 
 
                internal List<Queue> queues = new List<Queue> ();
@@ -66,8 +66,8 @@ namespace vke {
                        //enable only supported exceptions
                        List<IntPtr> deviceExtensions = new List<IntPtr> ();
                        for (int i = 0; i < extensions.Length; i++) {
-                               if (phy.GetDeviceExtensionSupported (extensions[i])) 
-                                       deviceExtensions.Add (new FixedUtf8String (extensions[i]));                             
+                               if (phy.GetDeviceExtensionSupported (extensions[i]))
+                                       deviceExtensions.Add (new FixedUtf8String (extensions[i]));
                        }
 
                        VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.New ();
@@ -158,7 +158,7 @@ namespace vke {
                // This function is used to request a Device memory type that supports all the property flags we request (e.g. Device local, host visibile)
                // Upon success it will return the index of the memory type that fits our requestes memory properties
                // This is necessary as implementations can offer an arbitrary number of memory types with different
-               // memory properties. 
+               // memory properties.
                // You can check http://vulkan.gpuinfo.org/ for details on different memory configurations
                internal uint GetMemoryTypeIndex (uint typeBits, VkMemoryPropertyFlags properties) {
             // Iterate over all memory types available for the Device used in this example
index a6220c54704a3695e48530389c9c4eab91b5ba9d..f2bdd69b315db0e3cad651c0ec6ae6d3d977c46f 100644 (file)
@@ -45,7 +45,18 @@ namespace vke {
                /// <param name="views">Array of image views. If null and not in unused state, attachment image and view will be automatically created from the
                /// supplied renderpass configuration.</param>
                public FrameBuffer (RenderPass _renderPass, uint _width, uint _height, params Image[] views)
-               : this (_renderPass, _width, _height) {
+                       : this (_renderPass, _width, _height, 1, views) {}
+        /// <summary>
+        /// Create and Activate a new frabuffer for the supplied RenderPass.
+        /// </summary>
+        /// <param name="_renderPass">Render pass.</param>
+        /// <param name="_width">Width.</param>
+        /// <param name="_height">Height.</param>
+        /// <param name="layers">layers count</param>
+        /// <param name="views">Array of image views. If null and not in unused state, attachment image and view will be automatically created from the
+        /// supplied renderpass configuration.</param>
+        public FrameBuffer (RenderPass _renderPass, uint _width, uint _height, uint layers, params Image[] views)
+               : this (_renderPass, _width, _height, layers) {
                        for (int i = 0; i < views.Length; i++) {
                                Image v = views[i];
                                if (v == null) {
@@ -79,9 +90,15 @@ namespace vke {
                                createInfo.attachmentCount = (uint)views.Length;
                                createInfo.pAttachments = views.Pin ();
 
+                               if (PNext != null)
+                                       createInfo.pNext = PNext.GetPointer();
+
                                Utils.CheckResult (vkCreateFramebuffer (renderPass.Dev.VkDev, ref createInfo, IntPtr.Zero, out handle));
 
                                views.Unpin ();
+                               if (PNext != null)
+                                       PNext.ReleasePointer ();
+
                        }
                        base.Activate ();
                }
index dafacab40dffa4719240c6023f37f48fbd284e35..bb9c3e16520059345678d3278de49a1023577cd7 100644 (file)
@@ -42,9 +42,14 @@ namespace vke {
                                RenderPass.Activate ();
                                Cache?.Activate ();
 
+                               bool enableTesselation = false;
+
                                List<VkPipelineShaderStageCreateInfo> shaderStages = new List<VkPipelineShaderStageCreateInfo> ();
-                               foreach (ShaderInfo shader in cfg.Shaders)
+                               foreach (ShaderInfo shader in cfg.Shaders) {
+                                       if (shader.Stage == VkShaderStageFlags.TessellationControl || shader.Stage == VkShaderStageFlags.TessellationEvaluation)
+                                               enableTesselation = true;
                                        shaderStages.Add (shader.Info);
+                               }
 
                                using (PinnedObjects pctx = new PinnedObjects ()) {
 
@@ -98,6 +103,12 @@ namespace vke {
                                        info.pStages = shaderStages.Pin (pctx);
                                        info.subpass = cfg.SubpassIndex;
 
+                                       if (enableTesselation) {
+                                               VkPipelineTessellationStateCreateInfo tessellationInfo = VkPipelineTessellationStateCreateInfo.New();
+                                               tessellationInfo.patchControlPoints = cfg.TessellationPatchControlPoints;
+                                               info.pTessellationState = tessellationInfo.Pin (pctx);
+                                       }
+
                                        Utils.CheckResult (vkCreateGraphicsPipelines (Dev.VkDev, Cache == null ? VkPipelineCache.Null : Cache.handle, 1, ref info, IntPtr.Zero, out handle));
                                }
                        }
index b576e7c13eb0d6c53f29f6cfd1e6ec584dfdbdd5..1269f5c80470bec8b96f0cd96e9424359ad0fd3a 100644 (file)
@@ -37,24 +37,25 @@ namespace vke {
                public VkPipelineBindPoint bindPoint = VkPipelineBindPoint.Graphics;
                public VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = VkPipelineInputAssemblyStateCreateInfo.New ();
                public VkPipelineRasterizationStateCreateInfo rasterizationState = VkPipelineRasterizationStateCreateInfo.New ();
-               public List<VkViewport> Viewports = new List<VkViewport> ();
-               public List<VkRect2D> Scissors = new List<VkRect2D> ();
+               public IList<VkViewport> Viewports = new List<VkViewport> ();
+               public IList<VkRect2D> Scissors = new List<VkRect2D> ();
                public VkPipelineDepthStencilStateCreateInfo depthStencilState = VkPipelineDepthStencilStateCreateInfo.New ();
                public VkPipelineMultisampleStateCreateInfo multisampleState = VkPipelineMultisampleStateCreateInfo.New ();
-               public List<VkPipelineColorBlendAttachmentState> blendAttachments = new List<VkPipelineColorBlendAttachmentState> ();
-               public List<VkDynamicState> dynamicStates = new List<VkDynamicState> ();
-               public List<VkVertexInputBindingDescription> vertexBindings = new List<VkVertexInputBindingDescription> ();
-               public List<VkVertexInputAttributeDescription> vertexAttributes = new List<VkVertexInputAttributeDescription> ();
+               public IList<VkPipelineColorBlendAttachmentState> blendAttachments = new List<VkPipelineColorBlendAttachmentState> ();
+               public IList<VkDynamicState> dynamicStates = new List<VkDynamicState> ();
+               public IList<VkVertexInputBindingDescription> vertexBindings = new List<VkVertexInputBindingDescription> ();
+               public IList<VkVertexInputAttributeDescription> vertexAttributes = new List<VkVertexInputAttributeDescription> ();
                /// <summary>
                /// List of ShaderInfo's used to in this pipeline configuration. Those shaders have to be Disposed
                /// after pipeline creation from this configuration. The 'DisposeShaders' helper method with clear the list.
                /// To replace a single shader between two use of this configuration object to create two different pipelines, use
                /// the 'ReplaceShader' helper method to automatically dispose the replace shader.
                /// </summary>
-               public List<ShaderInfo> Shaders = new List<ShaderInfo> ();
+               public IList<ShaderInfo> Shaders = new List<ShaderInfo> ();
                public VkBool32 ColorBlendLogicOpEnable = false;
                public VkLogicOp ColorBlendLogicOp;
                public Vector4 ColorBlendConstants;
+               public uint TessellationPatchControlPoints = 0;
 
                public VkSampleCountFlags Samples {
                        get { return multisampleState.rasterizationSamples; }
@@ -144,19 +145,20 @@ namespace vke {
                        AddVertexAttributes (binding, attribs);
                }
                /// <summary>
-               /// Add shaders to this pipeline configuration. 
+               /// Add shaders to this pipeline configuration.
                /// </summary>
                public void AddShaders (params ShaderInfo[] shaderInfos) {
-                       Shaders.AddRange (shaderInfos);
+                       foreach (ShaderInfo si in shaderInfos)
+                               Shaders.Add (si);
                }
                /// <summary>
-               /// Add a new shader to this pipeline configuration. 
+               /// Add a new shader to this pipeline configuration.
                /// </summary>
                public void AddShader (VkShaderStageFlags stageFlags, VkShaderModule module, SpecializationInfo specializationInfo = null, string entryPoint = "main") {
                        Shaders.Add (new ShaderInfo (stageFlags, module, specializationInfo, entryPoint));
                }
                /// <summary>
-               /// Add a new shader to this pipeline configuration. 
+               /// Add a new shader to this pipeline configuration.
                /// </summary>
                public void AddShader (Device dev, VkShaderStageFlags stageFlags, string spirvShaderPath, SpecializationInfo specializationInfo = null, string entryPoint = "main") {
                        Shaders.Add (new ShaderInfo (dev, stageFlags, spirvShaderPath, specializationInfo, entryPoint));
diff --git a/vke/src/base/PNextNode.cs b/vke/src/base/PNextNode.cs
new file mode 100644 (file)
index 0000000..9afd001
--- /dev/null
@@ -0,0 +1,47 @@
+// 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.Reflection;
+
+namespace vke {
+       public abstract class PNextNode {
+               protected bool isPinned;
+               public abstract IntPtr GetPointer ();
+               public abstract void ReleasePointer ();
+       }
+       public class PNextNode<T> : PNextNode {
+               protected T nodeStruct;
+               public PNextNode (T thisNodeStructure) {
+                       nodeStruct = thisNodeStructure;
+               }
+               public override IntPtr GetPointer () {
+                       isPinned = true;
+                       return nodeStruct.Pin();
+               }
+               public override void ReleasePointer () {
+                       nodeStruct.Unpin ();
+                       isPinned = false;
+               }
+       }
+       public class PNextNode<T,U> : PNextNode<T> {
+               PNextNode<U> nextNodeStruct;
+               //T.pNext to store pinned reference of next struct
+               FieldInfo fiPnextFromNodeStruct;
+               public PNextNode (T thisNodeStruct, PNextNode<U> nextStruct) : base (thisNodeStruct) {
+                       nextNodeStruct = nextStruct;
+                       fiPnextFromNodeStruct = typeof(T).GetField ("pNext");
+               }
+
+               public override IntPtr GetPointer()
+               {
+                       fiPnextFromNodeStruct.SetValue (nodeStruct, nextNodeStruct.GetPointer ());
+                       return base.GetPointer();
+               }
+               public override void ReleasePointer()
+               {
+                       nextNodeStruct.ReleasePointer ();
+                       base.ReleasePointer();
+               }
+       }
+}
\ No newline at end of file
index dee264e4235c15d620004f9ab8883ac9e9104ed6..91645b43b0f7db3d2ae7d0b0ee7108e54309b482 100644 (file)
@@ -143,7 +143,7 @@ namespace vke {
                                modes.Unpin ();
                                VkPresentModeKHR[] mds = new VkPresentModeKHR[count];
                                for (int i = 0; i < count; i++)
-                                       mds[i] = (VkPresentModeKHR)modes[i];                            
+                                       mds[i] = (VkPresentModeKHR)modes[i];
                                return mds;
                        } else {
                                VkPresentModeKHR[] modes = new VkPresentModeKHR[count];//enums not blittable on ms.Net
index d632045f5117f2e8bff3d9712ac8c1bd28014461..eed45fc1194226ab78a82fa3740844bd062d1fc8 100644 (file)
@@ -9,14 +9,14 @@ using Vulkan;
 using static Vulkan.Vk;
 
 namespace vke {
-    public class RenderPass : Activable {
-        internal VkRenderPass handle;        
+       public class RenderPass : Activable {
+               internal VkRenderPass handle;        
 
                public readonly VkSampleCountFlags Samples;
 
-        internal List<VkAttachmentDescription> attachments = new List<VkAttachmentDescription> ();
-        internal List<SubPass> subpasses = new List<SubPass> ();
-        List<VkSubpassDependency> dependencies = new List<VkSubpassDependency> ();
+               internal List<VkAttachmentDescription> attachments = new List<VkAttachmentDescription> ();
+               internal List<SubPass> subpasses = new List<SubPass> ();
+               List<VkSubpassDependency> dependencies = new List<VkSubpassDependency> ();
                public List<VkClearValue> ClearValues = new List<VkClearValue> ();
                public VkAttachmentDescription [] Attachments => attachments.ToArray ();
                public SubPass [] SubPasses => subpasses.ToArray ();
@@ -41,7 +41,7 @@ namespace vke {
 
                        AddAttachment (colorFormat, (samples == VkSampleCountFlags.SampleCount1) ? VkImageLayout.PresentSrcKHR : VkImageLayout.ColorAttachmentOptimal, samples,
                                loadOp, VkAttachmentStoreOp.Store);
-            ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) });
+                       ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) });
 
                        SubPass subpass0 = new SubPass ();
                        subpass0.AddColorReference (0, VkImageLayout.ColorAttachmentOptimal);
@@ -52,29 +52,29 @@ namespace vke {
                                subpass0.AddResolveReference (1, VkImageLayout.ColorAttachmentOptimal);
                        }
 
-            AddSubpass (subpass0);
+                       AddSubpass (subpass0);
 
-            AddDependency (Vk.SubpassExternal, 0,
-                VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput,
-                VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentWrite);
-            AddDependency (0, Vk.SubpassExternal,
-                VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe,
-                VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);
+                       AddDependency (Vk.SubpassExternal, 0,
+                               VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput,
+                               VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentWrite);
+                       AddDependency (0, Vk.SubpassExternal,
+                               VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe,
+                               VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);
 
                }
-        /// <summary>
-        /// Create default renderpass with one color, one depth attachments, and a resolve one if needed.
-        /// </summary>
-        public RenderPass (Device device, VkFormat colorFormat, VkFormat depthFormat, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1)
-            : this (device){
+               /// <summary>
+               /// Create default renderpass with one color, one depth attachments, and a resolve one if needed.
+               /// </summary>
+               public RenderPass (Device device, VkFormat colorFormat, VkFormat depthFormat, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1)
+                       : this (device){
 
                        Samples = samples;
 
                        AddAttachment (colorFormat, (samples == VkSampleCountFlags.SampleCount1) ? VkImageLayout.PresentSrcKHR : VkImageLayout.ColorAttachmentOptimal, samples);
                        AddAttachment (depthFormat, VkImageLayout.DepthStencilAttachmentOptimal, samples);
 
-            ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) });
-            ClearValues.Add (new VkClearValue { depthStencil = new VkClearDepthStencilValue (1.0f, 0) });
+                       ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) });
+                       ClearValues.Add (new VkClearValue { depthStencil = new VkClearDepthStencilValue (1.0f, 0) });
 
                        SubPass subpass0 = new SubPass ();
 
@@ -87,15 +87,15 @@ namespace vke {
                                subpass0.AddResolveReference (2, VkImageLayout.ColorAttachmentOptimal);
                        }
 
-            AddSubpass (subpass0);
+                       AddSubpass (subpass0);
 
-            AddDependency (Vk.SubpassExternal, 0,
-                VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput,
-                VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite);
-            AddDependency (0, Vk.SubpassExternal,
-                VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe,
-                VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);
-        }
+                       AddDependency (Vk.SubpassExternal, 0,
+                               VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput,
+                               VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite);
+                       AddDependency (0, Vk.SubpassExternal,
+                               VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe,
+                               VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);
+               }
                #endregion
 
                public override void Activate () {
@@ -111,54 +111,58 @@ namespace vke {
                                renderPassInfo.pSubpasses = spDescs.Pin ();
                                renderPassInfo.dependencyCount = (uint)dependencies.Count;
                                renderPassInfo.pDependencies = dependencies.Pin ();
+                               if (PNext != null)
+                                       renderPassInfo.pNext = PNext.GetPointer ();
 
                                handle = Dev.CreateRenderPass (renderPassInfo);
 
                                foreach (SubPass sp in subpasses)
                                        sp.UnpinLists ();
 
+                               if (PNext != null)
+                                       PNext.ReleasePointer ();
                                attachments.Unpin ();
                                spDescs.Unpin ();
                                dependencies.Unpin ();
                        }
                        base.Activate ();
-        }
-
-
-        public void AddAttachment (VkFormat format,
-            VkImageLayout finalLayout, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1,
-            VkAttachmentLoadOp loadOp = VkAttachmentLoadOp.Clear,
-            VkAttachmentStoreOp storeOp = VkAttachmentStoreOp.Store,
-            VkImageLayout initialLayout = VkImageLayout.Undefined) {
-            attachments.Add (new VkAttachmentDescription {
-                format = format,
-                samples = samples,
-                loadOp = loadOp,
-                storeOp = storeOp,
-                stencilLoadOp = VkAttachmentLoadOp.DontCare,
-                stencilStoreOp = VkAttachmentStoreOp.DontCare,
-                initialLayout = initialLayout,
-                finalLayout = finalLayout,
-            }); 
-        }
-        public void AddAttachment (VkFormat format, VkImageLayout finalLayout,
-            VkAttachmentLoadOp stencilLoadOp,
-            VkAttachmentStoreOp stencilStoreOp,
-            VkAttachmentLoadOp loadOp = VkAttachmentLoadOp.DontCare,
-            VkAttachmentStoreOp storeOp = VkAttachmentStoreOp.DontCare,
-            VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1,
-            VkImageLayout initialLayout = VkImageLayout.Undefined) {
-            attachments.Add (new VkAttachmentDescription {
-                format = format,
-                samples = samples,
-                loadOp = loadOp,
-                storeOp = storeOp,
-                stencilLoadOp = stencilLoadOp,
-                stencilStoreOp = stencilStoreOp,
-                initialLayout = initialLayout,
-                finalLayout = finalLayout,
-            });
-        }
+               }
+
+
+               public void AddAttachment (VkFormat format,
+                       VkImageLayout finalLayout, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1,
+                       VkAttachmentLoadOp loadOp = VkAttachmentLoadOp.Clear,
+                       VkAttachmentStoreOp storeOp = VkAttachmentStoreOp.Store,
+                       VkImageLayout initialLayout = VkImageLayout.Undefined) {
+                       attachments.Add (new VkAttachmentDescription {
+                               format = format,
+                               samples = samples,
+                               loadOp = loadOp,
+                               storeOp = storeOp,
+                               stencilLoadOp = VkAttachmentLoadOp.DontCare,
+                               stencilStoreOp = VkAttachmentStoreOp.DontCare,
+                               initialLayout = initialLayout,
+                               finalLayout = finalLayout,
+                       }); 
+               }
+               public void AddAttachment (VkFormat format, VkImageLayout finalLayout,
+                       VkAttachmentLoadOp stencilLoadOp,
+                       VkAttachmentStoreOp stencilStoreOp,
+                       VkAttachmentLoadOp loadOp = VkAttachmentLoadOp.DontCare,
+                       VkAttachmentStoreOp storeOp = VkAttachmentStoreOp.DontCare,
+                       VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1,
+                       VkImageLayout initialLayout = VkImageLayout.Undefined) {
+                       attachments.Add (new VkAttachmentDescription {
+                               format = format,
+                               samples = samples,
+                               loadOp = loadOp,
+                               storeOp = storeOp,
+                               stencilLoadOp = stencilLoadOp,
+                               stencilStoreOp = stencilStoreOp,
+                               initialLayout = initialLayout,
+                               finalLayout = finalLayout,
+                       });
+               }
                //public void AddDependency (SubPass srcSubpass, SubPass dstSubpass,
                //      VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
                //      VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
@@ -169,57 +173,57 @@ namespace vke {
                //}
 
                public void AddDependency (uint srcSubpass, uint dstSubpass,
-            VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
-            VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
-            VkDependencyFlags dependencyFlags = VkDependencyFlags.ByRegion) {
-            dependencies.Add (new VkSubpassDependency {
-                srcSubpass = srcSubpass,
-                dstSubpass = dstSubpass,
-                srcStageMask = srcStageMask,
-                dstStageMask = dstStageMask,
-                srcAccessMask = srcAccessMask,
-                dstAccessMask = dstAccessMask,
-                dependencyFlags = dependencyFlags
-            });
-        }
-        public void AddSubpass (params SubPass[] subPass) {
+                       VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
+                       VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
+                       VkDependencyFlags dependencyFlags = VkDependencyFlags.ByRegion) {
+                       dependencies.Add (new VkSubpassDependency {
+                               srcSubpass = srcSubpass,
+                               dstSubpass = dstSubpass,
+                               srcStageMask = srcStageMask,
+                               dstStageMask = dstStageMask,
+                               srcAccessMask = srcAccessMask,
+                               dstAccessMask = dstAccessMask,
+                               dependencyFlags = dependencyFlags
+                       });
+               }
+               public void AddSubpass (params SubPass[] subPass) {
                        for (uint i = 0; i < subPass.Length; i++) {
                                subPass[i].Index = (uint)subpasses.Count + i;
                                subpasses.Add (subPass[i]);
                        }
-        }
-        /// <summary>
-        /// Begin Render pass with framebuffer extent dimensions
-        /// </summary>
-        public void Begin (PrimaryCommandBuffer cmd, FrameBuffer frameBuffer, VkSubpassContents contents = VkSubpassContents.Inline) {
-            Begin (cmd, frameBuffer, frameBuffer.Width, frameBuffer.Height, contents);
-        }
-        /// <summary>
-        /// Begin Render pass with custom render area
-        /// </summary>
-        public void Begin (PrimaryCommandBuffer cmd, FrameBuffer frameBuffer, uint width, uint height, VkSubpassContents contents = VkSubpassContents.Inline) {
-
-            VkRenderPassBeginInfo info = VkRenderPassBeginInfo.New();
-            info.renderPass = handle;
-            info.renderArea.extent.width = width;
-            info.renderArea.extent.height = height;
-            info.clearValueCount = (uint)ClearValues.Count;
-            info.pClearValues = ClearValues.Pin ();
-            info.framebuffer = frameBuffer.handle;
+               }
+               /// <summary>
+               /// Begin Render pass with framebuffer extent dimensions
+               /// </summary>
+               public void Begin (PrimaryCommandBuffer cmd, FrameBuffer frameBuffer, VkSubpassContents contents = VkSubpassContents.Inline) {
+                       Begin (cmd, frameBuffer, frameBuffer.Width, frameBuffer.Height, contents);
+               }
+               /// <summary>
+               /// Begin Render pass with custom render area
+               /// </summary>
+               public void Begin (PrimaryCommandBuffer cmd, FrameBuffer frameBuffer, uint width, uint height, VkSubpassContents contents = VkSubpassContents.Inline) {
+
+                       VkRenderPassBeginInfo info = VkRenderPassBeginInfo.New();
+                       info.renderPass = handle;
+                       info.renderArea.extent.width = width;
+                       info.renderArea.extent.height = height;
+                       info.clearValueCount = (uint)ClearValues.Count;
+                       info.pClearValues = ClearValues.Pin ();
+                       info.framebuffer = frameBuffer.handle;
 
                        vkCmdBeginRenderPass (cmd.Handle, ref info, contents);
 
                        ClearValues.Unpin ();
-        }
+               }
                /// <summary>
                /// Switch to next subpass
                /// </summary>
                public void BeginSubPass (PrimaryCommandBuffer cmd, VkSubpassContents subpassContents = VkSubpassContents.Inline) {
                        vkCmdNextSubpass (cmd.Handle, subpassContents);
                }
-        public void End (PrimaryCommandBuffer cmd) {
-            vkCmdEndRenderPass (cmd.Handle);
-        }
+               public void End (PrimaryCommandBuffer cmd) {
+                       vkCmdEndRenderPass (cmd.Handle);
+               }
                /// <summary>
                /// Create one framebuffer per swapchain images. The presentable attachment of this renderpass is found searching for its final layout that could be PresentSrcKHR or SharedPresentKHR.
                /// </summary>
@@ -246,7 +250,7 @@ namespace vke {
                public override string ToString () {
                        return string.Format ($"{base.ToString ()}[0x{handle.Handle.ToString("x")}]");
                }
-        
+               
                #region IDisposable Support
                protected override void Dispose (bool disposing) {
                        if (state == ActivableState.Activated) {
index c94ae474e3148d0be35a791ed141c4c7542babef..1ad79c56551bcca75aacea04f78f9de10802da27 100644 (file)
@@ -61,13 +61,13 @@ namespace vke {
                                max = _max;
                        }
                }
-        
+
         public class InstancedCmd
         {
             public int meshIdx;
             public uint count;
         }
-        
+
         public class Primitive {
                        public string name;
                        public uint indexBase;
@@ -149,7 +149,7 @@ namespace vke {
                                        aabb = Mesh.bb.getAABB (curTransform);
 
                                if (Children != null) {
-                                       for (int i = 0; i < Children.Count; i++) 
+                                       for (int i = 0; i < Children.Count; i++)
                                                aabb += Children[i].GetAABB (curTransform);
                                }
                                return aabb;
@@ -178,6 +178,6 @@ namespace vke {
             return null;
         }
 
-        
+
        }
 }
index fb73c03b59890a19f3096c69ed440841d98fb239..19434e5900dc0af666e675d3066dfb480b64fef9 100644 (file)
@@ -2,47 +2,46 @@
 <Project Sdk="Microsoft.NET.Sdk">
        <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
-               
+
                <ReleaseVersion>$(VkeReleaseVersion)</ReleaseVersion>
-               
+
                <AssemblyVersion>$(VkeReleaseVersion)</AssemblyVersion>
-               <Description>C# vulkan library with IDispose model and references counting</Description>                
+               <Description>C# vulkan library with IDispose model and references counting</Description>
                <RepositoryUrl>https://github.com/jpbruyere/vke.net</RepositoryUrl>
                <PackageTags>vulkan game engine compute glfw c#</PackageTags>
                <PackageVersion>$(VkePackageVersion)</PackageVersion>
-               
+
                <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
                <GenerateDocumentationFile>true</GenerateDocumentationFile>
-               
+
                <PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
                <PackageProjectUrl>https://github.com/jpbruyere/vke.net/blob/master/README.md</PackageProjectUrl>
                <PackageLicenseExpression>MIT</PackageLicenseExpression>
                <PackageIcon>icon.png</PackageIcon>
                <License>MIT</License>
                <Authors>Jean-Philippe Bruyère</Authors>
-               <PackageReleaseNotes>                   
+               <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>          
-               <LangVersion>7.2</LangVersion>
-               <GenerateDocumentationFile>true</GenerateDocumentationFile>    
-               <NoWarn>$(NoWarn);1591</NoWarn>         
-               
+
+               <EnableDefaultNoneItems>false</EnableDefaultNoneItems>
+               <GenerateDocumentationFile>true</GenerateDocumentationFile>
+               <NoWarn>$(NoWarn);1591</NoWarn>
+
                <RestoreAdditionalProjectSources Condition="Exists('$(SolutionDir)build\$(Configuration)\')">$(SolutionDir)build\$(Configuration)\</RestoreAdditionalProjectSources>
        </PropertyGroup>
-               
+
        <ItemGroup Condition="$(TargetFramework.StartsWith('netstandard'))">
-               <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />          
+               <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
        </ItemGroup>
-               
+
        <ItemGroup Condition=" '$(UseStbSharp)' == 'true'">
                <PackageReference Include="StbImageSharp" Version="2.22.4" />
        </ItemGroup>
@@ -53,7 +52,7 @@
                <PackageReference Include="shaderc.net" Version="0.1.0" />
                <PackageReference Include="glfw-sharp" Version="0.2.12-beta" />
        </ItemGroup>
-       
+
        <ItemGroup>
                <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.1" />
        </ItemGroup>