]> O.S.I.I.S - jp/vke.net.git/commitdiff
doc, update data download link
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 23 Oct 2021 12:53:17 +0000 (14:53 +0200)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sat, 23 Oct 2021 12:53:17 +0000 (14:53 +0200)
22 files changed:
.travis.yml
.vscode/launch.json
.vscode/tasks.json
Directory.Build.props
README.md
SpirVTasks/README.md
addons/DistanceFieldFont/BMFont.cs
addons/gltfLoader/glTFLoader.cs
download_datas.sh
samples/ClearScreen/README.md
samples/ClearScreen/main.cs
samples/Textured/README.md
samples/Textured/main.cs
samples/TexturedCube/main.cs
samples/Triangle/README.md
samples/Triangle/main.cs
vke/src/base/Activable.cs
vke/src/base/DescriptorSetLayout.cs
vke/src/base/Device.cs
vke/src/base/Image.cs
vke/src/base/RenderPass.cs
vke/src/ktx.cs

index 4996a9973bb8093298a187e2408141cd02fad31d..56dc2e9a2bc0c0856339bef96ab3a87e007afa11 100644 (file)
@@ -1,7 +1,7 @@
 
 language: csharp
 
-dist: bionic 
+dist: bionic
 
 dotnet: 3.1
 
@@ -10,11 +10,11 @@ env:
 
 before_install:
     - wget -qO - http://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
-    - sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-bionic.list https://packages.lunarg.com/vulkan/lunarg-vulkan-bionic.list 
+    - sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-bionic.list https://packages.lunarg.com/vulkan/lunarg-vulkan-bionic.list
     - sudo apt -qq update
     - sudo apt -y install vulkan-sdk
 
 script:
     - dotnet build /p:Configuration=ReleaseSpirVTasks
     - dotnet build /p:Configuration=Release
-    
+
index d5a945dc7a54a99d056be8e8af4ae920498e684a..a933a8992f37f392098a511c6f2f0ed291ad5400 100644 (file)
                        "console": "internalConsole"
                },
                {
-                       "name": ".NET Core Launch (console)",
+                       "name": ".NET Core Launch (ImmutableSampler)",
                        "type": "coreclr",
                        "request": "launch",
-                       "preLaunchTask": "build",
-                       "program": "${workspaceFolder}/build/Debug/netcoreapp3.1/Triangle",
+                       "preLaunchTask": "build immutableSampler",
+                       "program": "${workspaceFolder}/build/Debug/netcoreapp3.1/ImmutableSampler",
                        "args": [],
                        "cwd": "${workspaceFolder}/build/Debug/netcoreapp3.1/",
                        "console": "internalConsole",
index 9f2434f1d7d1a1d889bb2a99114abe7ddec68d6c..8aa8d5a247cd789b0fb3b7194bc81ad3f00123b6 100644 (file)
                        ],
                        "problemMatcher": "$msCompile"
                },
+               {
+                       "label": "build immutableSampler",
+                       "command": "dotnet",
+                       "type": "process",
+                       "args": [
+                               "build",
+                               "${workspaceFolder}/samples/ImmutableSampler/ImmutableSampler.csproj",
+                               "/property:GenerateFullPaths=true",
+                               "/property:SolutionDir=${workspaceFolder}/",
+                               "/property:Configuration=Debug",
+                               "/consoleloggerparameters:NoSummary"
+                       ],
+                       "problemMatcher": "$msCompile"
+               },
                {
                        "label": "publish",
                        "command": "dotnet",
index 245737510337e46e290cf9c25dcd353edcf63ce9..527f40a6426c25748fe307d1b48ccea76403ec63 100644 (file)
@@ -4,7 +4,7 @@
                <RestoreAdditionalProjectSources Condition="Exists('$(SolutionDir)build\$(Configuration)\')">$(SolutionDir)build\$(Configuration)\</RestoreAdditionalProjectSources>
                <SpirVTasksReleaseVersion>0.1.45</SpirVTasksReleaseVersion>
                <SpirVTasksPackageVersion>$(SpirVTasksReleaseVersion)</SpirVTasksPackageVersion>
-               <VkeReleaseVersion>0.2.1</VkeReleaseVersion>
+               <VkeReleaseVersion>0.2.2</VkeReleaseVersion>
                <VkePackageVersion>$(VkeReleaseVersion)-beta</VkePackageVersion>
                <UseStbSharp>true</UseStbSharp>
                <UseMemoryPools>false</UseMemoryPools>
index 0a411552d10980a9e9c5ee7e0dfac14a871778ac..986c08192de7b9c6ff8df4543ee0d949d0836e17 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
 <h1 align="center">
     vke.net
-    <br>  
+    <br>
     Vulkan Engine for .NET
-    <br>  
+    <br>
 <p align="center">
   <a href="https://www.nuget.org/packages/vke"><img src="https://buildstats.info/nuget/vke"></a>
   <a href="https://travis-ci.org/jpbruyere/vke.net">
 </p>
 
 ### Presentation
-**vke.net** (_vulkan engine for .net_) a vulkan abstraction layer writen in **c#** composed of high level classes encapsulating [vulkan](https://www.khronos.org/vulkan/) objects and commands with `IDispose` model and **reference counting**. [GLFW](https://www.glfw.org/)  handles the windowing system.
+**vke.net** (_vulkan engine for .net_) is a vulkan abstraction layer writen in **c#** composed of high level classes encapsulating [vulkan](https://www.khronos.org/vulkan/) objects and commands with `IDispose` model and **reference counting**. [GLFW](https://www.glfw.org/)  handles the default windowing system.
+
+vke aims to provide a simple api for all common vulkan tasks, ideal to quickly prototype vulkan applications, but fits also the needs to build complete application or game.
+
+To see **vke.net** in action check [vkChess.net](https://github.com/jpbruyere/vkChess.net).
 
 Vke use autogenerated [vk.net](https://github.com/jpbruyere/vk.net) library for low level binding to vulkan.
 
-Use the 'download_datas.sh' script for downloading sample's datas.
+Use the `download_datas.sh` script for downloading sample's datas.
 
 vke is in early development stage.
 
@@ -44,21 +48,21 @@ Create a new dotnet console project, and add the [vke nuget package](https://www
 
 ```xml
 <Project Sdk="Microsoft.NET.Sdk">
-       <TargetFrameworks>net472</TargetFrameworks>
-       <OutputType>Exe</OutputType>
+  <TargetFrameworks>net472</TargetFrameworks>
+  <OutputType>Exe</OutputType>
 
-       <ItemGroup>
-         <PackageReference Include="vke" />
-       </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="vke" />
+  </ItemGroup>
 </Project>
 ```
 For automatic shader compilation to SpirV, add also the [SpirVTasks](SpirVTasks/README.md) nuget package.
 
 ```xml
-       <ItemGroup>    
-       <PackageReference Include="SpirVTasks" />
-               <GLSLShader Include="shaders\*.*" />            
-       </ItemGroup>
+<ItemGroup>
+  <PackageReference Include="SpirVTasks" />
+    <GLSLShader Include="shaders\*.*" />
+</ItemGroup>
 ```
 ### Samples
 
@@ -69,7 +73,6 @@ For automatic shader compilation to SpirV, add also the [SpirVTasks](SpirVTasks/
 |    [Textured](samples/Textured/README.md)    |  ![screenshot](samples/screenShots/Textured.png)   |
 
 
-
 ### Features
 
 - physicaly based rendering, direct and deferred
index b5e805df421d0b63a76f613d56b481cb16e26d89..40d12ee3b8edd7d011cd81b06ede6f6448cdc311 100644 (file)
@@ -1,13 +1,13 @@
 <h1 align="center">
   SpirVTasks MSBuild add-on
-  <br>  
+  <br>
 <p align="center">
   <a href="https://www.nuget.org/packages/SpirVTasks">
     <img src="https://buildstats.info/nuget/SpirVTasks">
   </a>
   <a href="https://www.paypal.me/GrandTetraSoftware">
     <img src="https://img.shields.io/badge/Donate-PayPal-green.svg">
-  </a>  
+  </a>
 </p>
 </h1>
 
@@ -19,11 +19,11 @@ To enable SpirV compilation, you need to add the [nuget package](https://www.nug
 
 ```xml
 <ItemGroup>
-  <PackageReference Include="SpirVTasks"/>             
+  <PackageReference Include="SpirVTasks"/>
 </ItemGroup>
-<ItemGroup>    
+<ItemGroup>
   <GLSLShader Include="shaders\*.frag;shaders\*.vert;shaders\*.comp;shaders\*.geom" />
-</ItemGroup> 
+</ItemGroup>
 ```
 Resulting `.spv` files are automatically embedded with the resource ID: `ProjectName.file.ext.spv`. You can override this default id by adding a custom **LogicalName**.
 ```xml
@@ -31,7 +31,7 @@ Resulting `.spv` files are automatically embedded with the resource ID: `Project
   <GLSLShader Include="shaders\*.vert">
          <LogicalName>shaders.%(Filename)%(Extension).spv</LogicalName>
   </GLSLShader>
-</ItemGroup> 
+</ItemGroup>
 ```
 
 `VULKAN_SDK/bin` then `PATH` are searched for the **`glslc`** executable. You can also use the `SpirVglslcPath` property.
@@ -52,12 +52,12 @@ SpirVTasks add the ability to use **include** statements in your shader sources.
 layout (location = 0) in vec3 inColor;
 layout (location = 0) out vec4 outFragColor;
 
-void main() 
+void main()
 {
     outFragColor = vec4(inColor, 1.0);
 }
 ```
-Included files are searched from the location of the current parsed file, then in the `SpirVAdditionalIncludeDirectories`directories if present.
+Included files are searched from the location of the current parsed file, then in the `SpirVAdditionalIncludeDirectories` directories if present.
 ```xml
 <PropertyGroup>
   <SpirVAdditionalIncludeDirectories>$(MSBuildThisFileDirectory)common;testdir;../anotherdir</SpirVAdditionalIncludeDirectories>
@@ -71,7 +71,7 @@ It is also valid to add additional include search paths individually for each `G
   <GLSLShader Include="shaders\*.vert">
          <AdditionalIncludeDirectories>../include</AdditionalIncludeDirectories>
   </GLSLShader>
-</ItemGroup> 
+</ItemGroup>
 
 ```
 
@@ -86,7 +86,7 @@ Default optimization if this attribute is not present is **PERF**, accepted valu
 - PERF: spirv will be optimized for performances.
 - SIZE: resulting code size will be minimized.
 
-**DefineConstants** attribute may contains a semicolon separated list of implicit **MACRO** to define for compilation. Note that **project constants** are automatically to the compilation unit.
+**DefineConstants** attribute may contains a semicolon separated list of implicit **MACRO** to define for compilation. Note that **project constants** are automatically added to the compilation unit.
 
 ```xml
 <GLSLShader Include="shaders\skybox.vert" DefineConstants="DEBUG;SHADOW_FACTOR=0.15"/>
index 9b0a704cce66893ddcf0ead3457f5ccf58b97c56..b836363267f9335f0b5e8b3bb9ddae019a851375 100644 (file)
@@ -66,7 +66,7 @@ namespace vke.DistanceFieldFont {
                        if (path.EndsWith ("ktx", StringComparison.OrdinalIgnoreCase))
                                return KTX.KTX.Load (staggingQ, cmdPool, path,
                                        VkImageUsageFlags.Sampled, imgProp, genMipMaps, tiling);
-                       return Image.Load (staggingQ.Dev, staggingQ, cmdPool, path, VkFormat.R8g8b8a8Unorm, imgProp, tiling, genMipMaps);
+                       return Image.Load (staggingQ, cmdPool, path, VkFormat.R8g8b8a8Unorm, imgProp, tiling, genMipMaps);
                }
 
        }
index 9d39f4779ef776ac2696e669f11e015d9f5d2133..9a08362734a1371d0c6fd2e00b1d6ccf83a9c930 100644 (file)
@@ -524,7 +524,7 @@ namespace vke.glTF {
                                        vkimg = Image.Load (dev, transferQ, cmdPool, glTFLoader.loadDataUri (img));
                                } else {
                                        Debug.WriteLine ("loading image {0} : {1} : {2}", img.Name, img.MimeType, img.Uri);//load image from file path in uri
-                                       vkimg = Image.Load (dev, transferQ, cmdPool, Path.Combine (baseDirectory, img.Uri));
+                                       vkimg = Image.Load (transferQ, cmdPool, Path.Combine (baseDirectory, img.Uri));
                                        imgName += ";" + img.Uri;
                                }
 
index 64d3cc2d14d84d40120a65b951b1da8377499de3..faa256fd00c9555a93081303e429a734879189f8 100755 (executable)
@@ -1,3 +1,3 @@
 #!/bin/bash
-wget --no-check-certificate "https://onedrive.live.com/download?cid=B3181664476E9B48&resid=B3181664476E9B48%21167&authkey=APMbPmUMFnlrN6s" -O datas.zip
+wget --no-check-certificate "https://onedrive.live.com/download?cid=B3181664476E9B48&resid=B3181664476E9B48%21167&authkey=AIDq3olkU5xnxkQ" -O datas.zip
 unzip datas.zip
index 3851d6106102b57d6b721f955900141db666dd6c..b9f623fc8adfad47d8a65e618d351e3d46702f47 100644 (file)
@@ -4,19 +4,18 @@ To build a minimal vulkan application, add the [vke](https://www.nuget.org/packa
 
 ```xml
 <Project Sdk="Microsoft.NET.Sdk">
-    <PropertyGroup>
-        <TargetFrameworks>net472</TargetFrameworks>
-        <OutputType>Exe</OutputType>
-    </PropertyGroup>
-    <ItemGroup>    
-        <GLSLShader Include="shaders\*.*" />           
-    </ItemGroup>
-    <ItemGroup>
-        <PackageReference Include="SpirVTasks" />
-        <PackageReference Include="vke" />
-    </ItemGroup>
+  <PropertyGroup>
+    <TargetFrameworks>net472</TargetFrameworks>
+    <OutputType>Exe</OutputType>
+  </PropertyGroup>
+  <ItemGroup>
+    <GLSLShader Include="shaders\*.*" />
+  </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="SpirVTasks" />
+    <PackageReference Include="vke" />
+  </ItemGroup>
 </Project>
-
 ```
 
 ### VkWindow class
@@ -45,7 +44,7 @@ There are several method to clear the screen with vulkan. One is to use the rend
     renderPass = new RenderPass (dev, swapChain.ColorFormat);
     renderPass.ClearValues[0] = new VkClearValue (0.1f, 0.2f, 1);
     renderPass.Activate ();
-    
+
     cmds = cmdPool.AllocateCommandBuffer (swapChain.ImageCount);
 }
 ```
@@ -63,7 +62,7 @@ protected override void OnResize () {
 
        frameBuffers?.Dispose();
        frameBuffers = renderPass.CreateFrameBuffers(swapChain);
-       
+
        buildCommandBuffers ();
 }
 ```
@@ -73,7 +72,7 @@ It's common to rebuild the command buffers targeting the swap chain images after
 
 ### The command buffers
 
-The `VkWindow` class has a default array of command buffers, one for each swap chain image. But it's up to you to allocate and populate them. 
+The `VkWindow` class has a default array of command buffers, one for each swap chain image. But it's up to you to allocate and populate them.
 Here we simply record a begin/end render pass to clear the screen with the load operation of it.
 
 ```csharp
index 2792850559cda26361850ecb591b08be14aea608..caf5cbc14aeda66e80189a0bbb0ce0c330bc4365 100644 (file)
@@ -55,7 +55,7 @@ namespace ClearScreen {
                }
 
                //The resize method is called at least once before any rendering, so it's
-               //a safe place to initialize output size related vulkan objects like the 
+               //a safe place to initialize output size related vulkan objects like the
                //frame buffers.
                protected override void OnResize () {
                        base.OnResize ();
@@ -66,7 +66,7 @@ namespace ClearScreen {
                        buildCommandBuffers ();
                }
                //clean up
-               protected override void Dispose (bool disposing) {              
+               protected override void Dispose (bool disposing) {
                        dev.WaitIdle ();
 
                        renderPass.Dispose ();
index ece9973c0ab128c010858a8170cba3b7af500d35..f2bad6638e1da04948dc73fc46f672cdbaddf113 100644 (file)
@@ -18,8 +18,8 @@ the physical device selection, available features list is automatically queried
 ```csharp
 protected override void configureEnabledFeatures (
     VkPhysicalDeviceFeatures available_features,
-    ref VkPhysicalDeviceFeatures enabled_features) {    
-    
+    ref VkPhysicalDeviceFeatures enabled_features) {
+
     enabled_features.samplerAnisotropy = available_features.samplerAnisotropy;
 }
 ```
@@ -31,4 +31,24 @@ To create queues, override the **`createQueues`** method of **`VkWindow`**. This
 protected override void createQueues () {
        base.createQueues ();
        transferQ = new Queue (dev, VkQueueFlags.Transfer);
-}
\ No newline at end of file
+}
+```
+
+### Loading images
+
+The `vke.Image` classes has facilities to load bitmaps from disk (jpg, gif, ...). KTX images use the `KTX.KTX.Load` static method.
+
+```csharp
+KTX.KTX.Load (presentQueue, cmdPool, path, ...
+Image.Load (dev, presentQueue, cmdPool, path, ...
+```
+
+Once the image is loaded, you may create the associated View and Sampler by calling image instance methods. View and Sampler lifecycle will be bound to the image and disposed when the image is disposed.
+
+The `Descriptor` property of the image will old the created handles.
+
+```csharp
+nextTexture.CreateView ();
+nextTexture.CreateSampler ();
+nextTexture.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
+```
\ No newline at end of file
index 31337f40b3fb0a9c1fc1a5247bc5a5f57054ba0f..15e6567e96459aae989354b0340a84219d2233e3 100644 (file)
@@ -68,9 +68,9 @@ namespace Textured {
 
                protected override void initVulkan () {
                        base.initVulkan ();
-                                       
+
                        cmds = cmdPool.AllocateCommandBuffer(swapChain.ImageCount);
-                               
+
                        loadTexture (imgPathes[currentImgIndex]);
 
                        vbo = new GPUBuffer<float> (presentQueue, cmdPool, VkBufferUsageFlags.VertexBuffer, vertices);
@@ -134,7 +134,7 @@ namespace Textured {
 
                                pipeline.RenderPass.End (cmd);
 
-                               cmd.End ();                              
+                               cmd.End ();
                        }
                }
 
@@ -151,7 +151,7 @@ namespace Textured {
                                        nextTexture = KTX.KTX.Load (presentQueue, cmdPool, path,
                                                VkImageUsageFlags.Sampled, imgProp, genMipMaps, tiling);
                                else
-                                       nextTexture = Image.Load (dev, presentQueue, cmdPool, path, VkFormat.R8g8b8a8Unorm, imgProp, tiling, genMipMaps);
+                                       nextTexture = Image.Load (presentQueue, cmdPool, path, VkFormat.R8g8b8a8Unorm, imgProp, tiling, genMipMaps);
                                updateViewRequested = true;
                        } catch (Exception ex) {
                                Console.WriteLine (ex);
@@ -160,7 +160,7 @@ namespace Textured {
                }
 
                //in the main vulkan thread
-               void updateTextureSet (){ 
+               void updateTextureSet (){
                        nextTexture.CreateView ();
                        nextTexture.CreateSampler ();
                        nextTexture.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
@@ -175,7 +175,7 @@ namespace Textured {
                        nextTexture = null;
                }
 
-               void updateMatrices () { 
+               void updateMatrices () {
                        matrices.projection = Matrix4x4.CreatePerspectiveFieldOfView (Utils.DegreesToRadians (60f), (float)swapChain.Width / (float)swapChain.Height, 0.1f, 256.0f);
                        matrices.view = Matrix4x4.CreateTranslation (0, 0, -2.5f * zoom);
                        matrices.model =
@@ -190,7 +190,7 @@ namespace Textured {
                        if (nextTexture != null) {
                                updateTextureSet ();
                                buildCommandBuffers ();
-                       }else 
+                       }else
                                updateMatrices ();
 
                        updateViewRequested = false;
@@ -202,11 +202,11 @@ namespace Textured {
                        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;
                        }
-
-                       updateViewRequested = true;
                }
 
                protected override void onKeyDown (Key key, int scanCode, Modifier modifiers) {
@@ -232,7 +232,7 @@ namespace Textured {
                        frameBuffers = pipeline.RenderPass.CreateFrameBuffers(swapChain);
 
                        buildCommandBuffers ();
-               }       
+               }
 
                protected override void Dispose (bool disposing) {
                        dev.WaitIdle ();
index 0346914af79cf28f4faf4db3e22ba2e1bf0e9eee..5b006440fccbcb2eabeb3baefae63bc91775d90c 100644 (file)
@@ -58,35 +58,35 @@ namespace TextureCube {
                        -1.0f, 1.0f, 1.0f,    1.0f, 0.0f,
                        -1.0f, 1.0f,-1.0f,    0.0f, 0.0f,
                        -1.0f,-1.0f,-1.0f,    0.0f, 1.0f,
-                                             
+
                        -1.0f,-1.0f,-1.0f,    1.0f, 1.0f,  // -Z side
                         1.0f, 1.0f,-1.0f,    0.0f, 0.0f,
                         1.0f,-1.0f,-1.0f,    0.0f, 1.0f,
                        -1.0f,-1.0f,-1.0f,    1.0f, 1.0f,
                        -1.0f, 1.0f,-1.0f,    1.0f, 0.0f,
                         1.0f, 1.0f,-1.0f,    0.0f, 0.0f,
-                                             
+
                        -1.0f,-1.0f,-1.0f,    1.0f, 0.0f,  // -Y side
                         1.0f,-1.0f,-1.0f,    1.0f, 1.0f,
                         1.0f,-1.0f, 1.0f,    0.0f, 1.0f,
                        -1.0f,-1.0f,-1.0f,    1.0f, 0.0f,
                         1.0f,-1.0f, 1.0f,    0.0f, 1.0f,
                        -1.0f,-1.0f, 1.0f,    0.0f, 0.0f,
-                                             
+
                        -1.0f, 1.0f,-1.0f,    1.0f, 0.0f,  // +Y side
                        -1.0f, 1.0f, 1.0f,    0.0f, 0.0f,
                         1.0f, 1.0f, 1.0f,    0.0f, 1.0f,
                        -1.0f, 1.0f,-1.0f,    1.0f, 0.0f,
                         1.0f, 1.0f, 1.0f,    0.0f, 1.0f,
                         1.0f, 1.0f,-1.0f,    1.0f, 1.0f,
-                                             
+
                         1.0f, 1.0f,-1.0f,    1.0f, 0.0f,  // +X side
                         1.0f, 1.0f, 1.0f,    0.0f, 0.0f,
                         1.0f,-1.0f, 1.0f,    0.0f, 1.0f,
                         1.0f,-1.0f, 1.0f,    0.0f, 1.0f,
                         1.0f,-1.0f,-1.0f,    1.0f, 1.0f,
                         1.0f, 1.0f,-1.0f,    1.0f, 0.0f,
-                                             
+
                        -1.0f, 1.0f, 1.0f,    0.0f, 0.0f,  // +Z side
                        -1.0f,-1.0f, 1.0f,    0.0f, 1.0f,
                         1.0f, 1.0f, 1.0f,    1.0f, 0.0f,
@@ -142,12 +142,12 @@ namespace TextureCube {
 
                void buildCommandBuffers () {
                        cmdPool.Reset();
-                       for (int i = 0; i < swapChain.ImageCount; ++i) {                                                                
+                       for (int i = 0; i < swapChain.ImageCount; ++i) {
                                cmds[i].Start ();
                                recordDraw (cmds[i], frameBuffers[i]);
-                               cmds[i].End ();                          
+                               cmds[i].End ();
                        }
-               } 
+               }
                void recordDraw (PrimaryCommandBuffer cmd, FrameBuffer fb) {
                        pipeline.RenderPass.Begin (cmd, fb);
 
@@ -179,19 +179,19 @@ namespace TextureCube {
                }
 
                //in the main vulkan thread
-               void updateTextureSet (){ 
+               void updateTextureSet (){
                        nextTexture.CreateView (VkImageViewType.Cube,VkImageAspectFlags.Color,6);
                        nextTexture.CreateSampler ();
 
                        nextTexture.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
-                       DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descriptorSet, dsLayout.Bindings[1]);                          
+                       DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descriptorSet, dsLayout.Bindings[1]);
                        uboUpdate.Write (dev, nextTexture.Descriptor);
 
                        texture?.Dispose ();
                        texture = nextTexture;
                        nextTexture = null;
                }
-               void updateMatrices () { 
+               void updateMatrices () {
                        matrices.projection = Matrix4x4.CreatePerspectiveFieldOfView (Utils.DegreesToRadians (60f), (float)swapChain.Width / (float)swapChain.Height, 0.1f, 5.0f);
                        matrices.view =
                                Matrix4x4.CreateFromAxisAngle (Vector3.UnitZ, rotZ) *
@@ -211,7 +211,7 @@ namespace TextureCube {
                                dev.WaitIdle ();
                                updateTextureSet ();
                                buildCommandBuffers ();
-                       }else 
+                       }else
                                updateMatrices ();
 
                        updateViewRequested = false;
@@ -256,7 +256,7 @@ namespace TextureCube {
 
                        buildCommandBuffers();
                }
-                       
+
                protected override void Dispose (bool disposing) {
                        if (disposing) {
                                if (!isDisposed) {
index 27f9eb3ab1f6a47430aa18720bc166bb28801b80..d9343df0410cb18bcfe9f30a4438e72df483455a 100644 (file)
@@ -1,13 +1,13 @@
 ### Creating buffers
 
-Vke has two classes to handle buffers. Mappable [`HostBuffer`](../../../../wiki/vke.HostBuffer) and device only [`GPUBuffer`](../../../../wiki/vke.GPUBuffer). 
+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);   
+ibo = new HostBuffer<ushort> (dev, VkBufferUsageFlags.IndexBuffer, indices);
 //a permanantly mapped buffer for the mvp matrice
 uboMats = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, mvp, true);
 ```
@@ -16,15 +16,17 @@ To be able to access the mvp matrix in a shader, we need a descriptor. This impl
 ```csharp
 descriptorPool = new DescriptorPool (dev, 1, new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer));
 ```
+### Creating pipelines
+
 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)));
+using (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
@@ -41,6 +43,9 @@ shader are automatically compiled by [`SpirVTasks`](../../SpirVTasks/README.md)
 cfg.AddShader (dev, VkShaderStageFlags.Vertex, "#shaders.main.vert.spv");
 cfg.AddShader (dev, VkShaderStageFlags.Fragment, "#shaders.main.frag.spv");
 ```
+Because native ShaderModule used during pipeline creation may be disposed once the pipeline is created, The PipelineConfig class implement the
+'IDisposable' interface to release those pointers automaticaly.
+
 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);
@@ -49,6 +54,9 @@ Because descriptor layouts used for a pipeline are only activated on pipeline ac
 ```csharp
        descriptorSet = descriptorPool.Allocate (pipeline.Layout.DescriptorSetLayouts[0]);
 ```
+
+### Descriptor update
+
 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.
 
@@ -58,3 +66,24 @@ DescriptorSetWrites uboUpdate =
 
 uboUpdate.Write (dev, uboMats.Descriptor);
 ```
+
+### Updating the view
+
+Override the `UpdateView` method of the `VkWindow` class to update view related stuff like matrices.
+
+```csharp
+public override void UpdateView () {
+  mvp = Matrix4x4.Create ...
+  uboMats.Update (mvp, (uint)Marshal.SizeOf<Matrix4x4> ());
+  base.UpdateView ();
+}
+```
+This method is called at least once before the rendering loop just after 'OnResize'.
+Then, it is triggered in the render loop each time the `updateViewRequested` field of `VkWindow` is set to 'true',
+don't forget to reset `updateViewRequested` to 'false' or call the `base.UpdateView()` which will reset this boolean.
+
+In a typical application, the mouse movements will set `updateViewRequested` to true.
+```csharp
+protected override void onMouseMove (double xPos, double yPos) {
+  updateViewRequested = true;
+```
index d3804aff861d5cf1001b312f9d46a546ce252939..82b7374d16cd53f3ab830bd17eddefe75426a863 100644 (file)
@@ -67,7 +67,10 @@ namespace Triangle {
                        //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.
+                       //Graphic pipeline configuration are predefined by the GraphicPipelineConfig class,
+                       //which ease sharing config for several pipelines having lots in common.
+                       //Because 'ShaderInfo' instantiate temporary native ShaderModule, the GraphicPipelineConfig
+                       //class implement 'IDisposable' interface to dispose those modules once the pipeline(s) is created.
                        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.
@@ -156,7 +159,8 @@ namespace Triangle {
 
                protected override void OnResize () {
                        base.OnResize ();
-                       UpdateView ();
+
+                       updateViewRequested = true;
 
                        frameBuffers?.Dispose();
                        frameBuffers = pipeline.RenderPass.CreateFrameBuffers(swapChain);
index 1c3d0bef9fa0888df29beb94879d469aea77d35a..9b746e9710de80f58d8243a1f1d6c08ee1c1dcc6 100644 (file)
@@ -34,7 +34,7 @@ namespace vke {
        /// The activables that trigger activation only on usage does not require an additional dispose at the end.
        /// </remarks>
        public abstract class Activable : IDisposable {
-               //count number of activation, only the first one will create a handle 
+               //count number of activation, only the first one will create a handle
                [XmlIgnore] protected uint references;
                //keep track of the current state of activation.
                protected ActivableState state;
@@ -75,7 +75,7 @@ namespace vke {
                        VkDebugUtilsObjectNameInfoEXT dmo = DebugUtilsInfo;
                        dmo.pObjectName = name.Pin();
                        Utils.CheckResult (vkSetDebugUtilsObjectNameEXT (Dev.VkDev, ref dmo));
-                       name.Unpin ();                  
+                       name.Unpin ();
                }
                /// <summary>
                /// Activation of the object, the reference count is incremented and if Debug utils is enabled, name is set.
@@ -84,7 +84,7 @@ namespace vke {
                        references++;
                        if (state == ActivableState.Activated)
                                return;
-                       if (state == ActivableState.Disposed) 
+                       if (state == ActivableState.Disposed)
                                GC.ReRegisterForFinalize (this);
                        state = ActivableState.Activated;
                        SetName (name);
index d09c4c40335a7819274a3c9d869fc5ebf9ca60d5..3bcc963f1748c19f2889fef73f97c0fc348b5674 100644 (file)
@@ -13,7 +13,7 @@ namespace vke {
        /// </summary>
     public sealed class DescriptorSetLayout : Activable {
         internal VkDescriptorSetLayout handle;
-        
+
                public VkDescriptorSetLayoutCreateFlags Flags { get; private set; } = 0;
         public List<VkDescriptorSetLayoutBinding> Bindings { get; private set; } = new List<VkDescriptorSetLayoutBinding> ();
 
@@ -22,7 +22,7 @@ namespace vke {
 
                #region CTORS
                DescriptorSetLayout () : base (null) { }
-               public DescriptorSetLayout (Device device, VkDescriptorSetLayoutCreateFlags flags) : base (device) {            
+               public DescriptorSetLayout (Device device, VkDescriptorSetLayoutCreateFlags flags) : base (device) {
                        Flags = flags;
         }
                public DescriptorSetLayout (Device device, params VkDescriptorSetLayoutBinding[] bindings)
@@ -30,8 +30,8 @@ namespace vke {
         }
         public DescriptorSetLayout (Device device, VkDescriptorSetLayoutCreateFlags flags, params VkDescriptorSetLayoutBinding[] bindings)
         : this (device, flags) {
-            foreach (VkDescriptorSetLayoutBinding b in bindings) 
-                Bindings.Add (b);            
+            foreach (VkDescriptorSetLayoutBinding b in bindings)
+                Bindings.Add (b);
         }
                #endregion
 
index 293585d6971f958e3e160cb05aa1328d76771493..434a3abab9e7b7314c994d4fce72301a6f4773aa 100644 (file)
@@ -161,33 +161,33 @@ namespace vke {
                // 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
-            for (uint i = 0; i < phy.memoryProperties.memoryTypeCount; i++) {
-                if ((typeBits & 1) == 1) {
-                    if ((phy.memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) {
-                        return i;
-                    }
-                }
-                typeBits >>= 1;
-            }
-
-            throw new InvalidOperationException ("Could not find a suitable memory type!");
-        }
-        public VkFormat GetSuitableDepthFormat () {
-            VkFormat[] formats = new VkFormat[] {VkFormat.D32SfloatS8Uint, VkFormat.D32Sfloat, VkFormat.D24UnormS8Uint, VkFormat.D16UnormS8Uint, VkFormat.D16Unorm };
-            foreach (VkFormat f in formats) {
+                       // Iterate over all memory types available for the Device used in this example
+                       for (uint i = 0; i < phy.memoryProperties.memoryTypeCount; i++) {
+                               if ((typeBits & 1) == 1) {
+                                       if ((phy.memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) {
+                                               return i;
+                                       }
+                               }
+                               typeBits >>= 1;
+                       }
+
+                       throw new InvalidOperationException ("Could not find a suitable memory type!");
+               }
+               public VkFormat GetSuitableDepthFormat () {
+                       VkFormat[] formats = new VkFormat[] {VkFormat.D32SfloatS8Uint, VkFormat.D32Sfloat, VkFormat.D24UnormS8Uint, VkFormat.D16UnormS8Uint, VkFormat.D16Unorm };
+                       foreach (VkFormat f in formats) {
                                Console.WriteLine ( (int)phy.GetFormatProperties (f).optimalTilingFeatures);
-                if (phy.GetFormatProperties (f).optimalTilingFeatures.HasFlag(VkFormatFeatureFlags.DepthStencilAttachment))
-                    return f;
-            }
-            throw new InvalidOperationException ("No suitable depth format found.");
-        }
+                               if (phy.GetFormatProperties (f).optimalTilingFeatures.HasFlag(VkFormatFeatureFlags.DepthStencilAttachment))
+                                       return f;
+                       }
+                       throw new InvalidOperationException ("No suitable depth format found.");
+               }
                /// <summary>
                /// Load compiled SpirvShader.
                /// </summary>
                /// <returns>the vulkan shader module.</returns>
                /// <param name="filename">path of the spv shader.</param>
-        public VkShaderModule CreateShaderModule (string filename) {
+               public VkShaderModule CreateShaderModule (string filename) {
                        using (Stream stream = Utils.GetStreamFromPath (filename)) {
                                using (BinaryReader br = new BinaryReader (stream)) {
                                        byte[] shaderCode = br.ReadBytes ((int)stream.Length);
@@ -197,13 +197,13 @@ namespace vke {
                                        return shaderModule;
                                }
                        }
-        }/// <summary>
-        /// Load spirv code from unmanaged native pointer.
-        /// </summary>
-        /// <returns>the vulkan shader module.</returns>
-        /// <param name="code">unmanaged pointer holding the spirv code. Pointer must stay valid only during
+               }/// <summary>
+               /// Load spirv code from unmanaged native pointer.
+               /// </summary>
+               /// <returns>the vulkan shader module.</returns>
+               /// <param name="code">unmanaged pointer holding the spirv code. Pointer must stay valid only during
                /// the call to this method.</param>
-        /// <param name="codeSize">spirv code byte size.</param>
+               /// <param name="codeSize">spirv code byte size.</param>
                public VkShaderModule CreateShaderModule (IntPtr code, UIntPtr codeSize) {
                        VkShaderModuleCreateInfo moduleCreateInfo = VkShaderModuleCreateInfo.New ();
                        moduleCreateInfo.codeSize = codeSize;
@@ -215,8 +215,8 @@ namespace vke {
                #region IDisposable Support
                private bool disposedValue = false; // Pour détecter les appels redondants
 
-        protected virtual void Dispose (bool disposing) {
-            if (!disposedValue) {
+               protected virtual void Dispose (bool disposing) {
+                       if (!disposedValue) {
                                if (disposing) {
 #if MEMORY_POOLS
                                        resourceManager.Dispose ();
@@ -224,21 +224,21 @@ namespace vke {
                                } else
                                        System.Diagnostics.Debug.WriteLine ("Device disposed by Finalizer.");
 
-                vkDestroyDevice (dev, IntPtr.Zero);
+                               vkDestroyDevice (dev, IntPtr.Zero);
 
-                disposedValue = true;
-            }
-        }
+                               disposedValue = true;
+                       }
+               }
 
-        ~Device() {
-           Dispose(false);
-        }
+               ~Device() {
+                  Dispose(false);
+               }
 
-        // Ce code est ajouté pour implémenter correctement le modèle supprimable.
-        public void Dispose () {
-            Dispose (true);
-            GC.SuppressFinalize(this);
-        }
+               // Ce code est ajouté pour implémenter correctement le modèle supprimable.
+               public void Dispose () {
+                       Dispose (true);
+                       GC.SuppressFinalize(this);
+               }
 #endregion
-    }
+       }
 }
index 88ab2be28d010275cd041800cb108bf507bb5ab6..a49c0353790de6706d8eec7fe18266e73a60cab0 100644 (file)
@@ -267,13 +267,15 @@ namespace vke {
                /// Load bitmap into Image with stagging and mipmap generation if necessary
                /// and usage.
                /// </summary>
-               public static Image Load (Device dev, Queue staggingQ, CommandPool staggingCmdPool,
+               public static Image Load (Queue staggingQ, CommandPool staggingCmdPool,
                        string path, VkFormat format = VkFormat.Undefined,
                        VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.DeviceLocal,
                        VkImageTiling tiling = VkImageTiling.Optimal, bool generateMipmaps = true,
                        VkImageType imageType = VkImageType.Image2D,
                        VkImageUsageFlags usage = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst) {
 
+                       Device dev = staggingQ.dev;
+
                        if (format == VkFormat.Undefined)
                                format = DefaultTextureFormat;
                        if (tiling == VkImageTiling.Optimal)
index eed45fc1194226ab78a82fa3740844bd062d1fc8..be3278117237233e2c4cb7e90b20cb9fb63329b8 100644 (file)
@@ -10,7 +10,7 @@ using static Vulkan.Vk;
 
 namespace vke {
        public class RenderPass : Activable {
-               internal VkRenderPass handle;        
+               internal VkRenderPass handle;
 
                public readonly VkSampleCountFlags Samples;
 
@@ -36,7 +36,7 @@ namespace vke {
                /// Create renderpass with a single color attachment and a resolve one if needed
                /// </summary>
                public RenderPass (Device device, VkFormat colorFormat, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1, VkAttachmentLoadOp loadOp = VkAttachmentLoadOp.Clear)
-                       : this (device) { 
+                       : this (device) {
                        Samples = samples;
 
                        AddAttachment (colorFormat, (samples == VkSampleCountFlags.SampleCount1) ? VkImageLayout.PresentSrcKHR : VkImageLayout.ColorAttachmentOptimal, samples,
@@ -143,7 +143,7 @@ namespace vke {
                                stencilStoreOp = VkAttachmentStoreOp.DontCare,
                                initialLayout = initialLayout,
                                finalLayout = finalLayout,
-                       }); 
+                       });
                }
                public void AddAttachment (VkFormat format, VkImageLayout finalLayout,
                        VkAttachmentLoadOp stencilLoadOp,
@@ -245,12 +245,12 @@ namespace vke {
                        }
                        return fbs;
                }
-       
+
 
                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 2c38068c42dbe62f010aecc5e93bf238c811232a..28056bd3c95f48f732cfb0c9eab206df0a5860a9 100644 (file)
@@ -40,7 +40,7 @@ namespace KTX {
                                        UInt32 numberOfFaces = br.ReadUInt32 ();//only for cube map, else 1
                                        UInt32 numberOfMipmapLevels = Math.Max (1, br.ReadUInt32 ());
                                        UInt32 bytesOfKeyValueData = br.ReadUInt32 ();
-                                                                                       
+
                                        VkFormat vkFormat = GLHelper.vkGetFormatFromOpenGLInternalFormat (glInternalFormat);
                                        if (vkFormat == VkFormat.Undefined) {
                                                vkFormat = GLHelper.vkGetFormatFromOpenGLFormat (glFormat, glType);
@@ -56,7 +56,7 @@ namespace KTX {
                                        if (numberOfMipmapLevels == 1)
                                                requestedMipsLevels = (generateMipmaps && phyFormatSupport.HasFlag (VkFormatFeatureFlags.BlitSrc | VkFormatFeatureFlags.BlitDst)) ?
                                                        (uint)Math.Floor (Math.Log (Math.Max (pixelWidth, pixelHeight))) + 1 : 1 ;
-                                                       
+
                                        if (tiling == VkImageTiling.Optimal)
                                                usage |= VkImageUsageFlags.TransferDst;
                                        if (generateMipmaps)
@@ -68,7 +68,7 @@ namespace KTX {
                                                (pixelWidth == 0) ? throw new KtxException ("pixelWidth must be > 0") :
                                                (pixelHeight == 0) ? imgType = VkImageType.Image1D :
                                                (pixelDepth == 1) ? imgType = VkImageType.Image2D : imgType = VkImageType.Image3D;
-                                               
+
 
                                        VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1;
 
@@ -89,7 +89,7 @@ namespace KTX {
 
                                        img = new Image (staggingQ.Dev, vkFormat, usage, memoryProperty, pixelWidth, pixelHeight, imgType, samples,
                                                tiling, requestedMipsLevels, numberOfArrayElements, pixelDepth, createFlags);
-                                               
+
                                        byte[] keyValueDatas = br.ReadBytes ((int)bytesOfKeyValueData);
 
                                        uint blockW, blockH;
@@ -98,7 +98,6 @@ namespace KTX {
 
                                        if (memoryProperty.HasFlag (VkMemoryPropertyFlags.DeviceLocal)) {
                                                ulong staggingSize = img.AllocatedDeviceMemorySize;
-                                               Console.WriteLine ($"KtxStream size = {ktxStream.Length}, img Allocation = {img.AllocatedDeviceMemorySize}");
 
                                                using (HostBuffer stagging = new HostBuffer (staggingQ.Dev, VkBufferUsageFlags.TransferSrc, staggingSize)) {
                                                        stagging.Map ();
@@ -138,7 +137,7 @@ namespace KTX {
                                                                        //TODO:handle compressed formats
                                                                        for (uint face = 0; face < numberOfFaces; face++) {
                                                                                Marshal.Copy (br.ReadBytes ((int)imgSize), 0, stagging.MappedData + (int)bufferOffset, (int)imgSize);
-                                                                               uint faceOffset = imgSize + (imgSize % 4);//cube padding                                                                                                                                                                  
+                                                                               uint faceOffset = imgSize + (imgSize % 4);//cube padding
                                                                                bufferOffset += faceOffset;
                                                                        }
                                                                        buffCopies.Add (bufferCopyRegion);
@@ -156,7 +155,7 @@ namespace KTX {
                                                                        bufferOffset += imgSize;
                                                                }
 
-                                                               if (isCompressed && bufferOffset % blockSize > 0) 
+                                                               if (isCompressed && bufferOffset % blockSize > 0)
                                                                        bufferOffset += blockSize - bufferOffset % blockSize;
 
                                                                imgWidth /= 2;
@@ -169,7 +168,7 @@ namespace KTX {
                                                        buffCopies.Unpin ();
 
                                                        if (requestedMipsLevels > numberOfMipmapLevels)
-                                                               img.BuildMipmaps (cmd);                                                         
+                                                               img.BuildMipmaps (cmd);
                                                        else
                                                                img.SetLayout (cmd, VkImageAspectFlags.Color,
                                                                        VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal,
@@ -183,7 +182,8 @@ namespace KTX {
                                                        cmd.Free ();
 
                                                }
-                                       } else { 
+                                       } else {
+                                               throw new NotImplementedException();
                                        }
                                }
                        }