aboutsummaryrefslogtreecommitdiffstatsci
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2019-05-08 01:41:55 +0200
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2019-05-08 01:41:55 +0200
commitb4fb4b4067534f69c1aa055ad6b4b3a7a488b13d (patch)
tree76d9d3198bb26d78b8f6f0c0c97c20c1fbfa8e75
parentf89a45f4083ad1b1d7129fde4616ca35e29d3e58 (diff)
wip
-rw-r--r--.travis.yml12
-rw-r--r--samples/Triangle/main.cs6
-rw-r--r--samples/common/CrowWin.cs2
-rw-r--r--samples/compute/delaunay.cs21
-rw-r--r--samples/deferred/deferred.csproj4
-rw-r--r--samples/deferred/deferredPbrRenderer.cs101
-rw-r--r--samples/deferred/main-crow.cs65
-rw-r--r--samples/deferred/main.cs31
-rw-r--r--samples/deferred/shaders/GBuffPbr.frag24
-rw-r--r--samples/deferred/shaders/GBuffPbrTexArray.frag211
-rw-r--r--samples/deferred/shaders/compose.frag8
-rw-r--r--samples/deferred/shaders/compose_with_shadows.frag10
-rw-r--r--samples/deferred/shaders/show_gbuff.frag10
-rw-r--r--samples/deferred/shaders/tone_mapping.frag2
-rw-r--r--samples/deferred/shadowMapRenderer.cs1
-rw-r--r--samples/pbrSashaWillem/SachaWillemPbr.csproj1
-rw-r--r--vk.net.sln14
-rw-r--r--vke/CVKL.csproj2
-rw-r--r--vke/src/Image.cs205
-rw-r--r--vke/src/Instance.cs23
-rw-r--r--vke/src/MarshaledObject.cs64
-rw-r--r--vke/src/Model.cs59
-rw-r--r--vke/src/PbrModel.cs170
-rw-r--r--vke/src/PbrModelSeparateTextures.cs198
-rw-r--r--vke/src/PbrModelTexArray.cs168
-rw-r--r--vke/src/SubPass.cs84
-rw-r--r--vke/src/SwapChain.cs85
-rw-r--r--vke/src/VkWindow.cs217
-rw-r--r--vke/src/glTFLoader.cs133
29 files changed, 1244 insertions, 687 deletions
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..610673e
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,12 @@
+language: csharp
+dist: xenial
+
+dotnet: 2.1.502
+mono: latest
+
+script:
+ - nuget restore
+ - msbuild
+ - dotnet restore
+ - dotnet build
+
diff --git a/samples/Triangle/main.cs b/samples/Triangle/main.cs
index 55ce742..347f83a 100644
--- a/samples/Triangle/main.cs
+++ b/samples/Triangle/main.cs
@@ -49,7 +49,7 @@ namespace Triangle {
};
ushort[] indices = new ushort[] { 0, 1, 2 };
- Program () : base (true) {
+ Program () : base (false) {
vbo = new HostBuffer<Vertex> (dev, VkBufferUsageFlags.VertexBuffer, vertices);
ibo = new HostBuffer<ushort> (dev, VkBufferUsageFlags.IndexBuffer, indices);
uboMats = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, matrices);
@@ -61,10 +61,6 @@ namespace Triangle {
GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1);
cfg.Layout = new PipelineLayout (dev, dsLayout);
- cfg.Layout.AddPushConstants (
- new VkPushConstantRange (VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf<Matrix4x4> ()),
- new VkPushConstantRange (VkShaderStageFlags.Fragment, (uint)Marshal.SizeOf<PbrModel.PbrMaterial> (), 64)
- );
cfg.RenderPass = new RenderPass (dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat (), cfg.Samples);
cfg.AddVertexBinding<Vertex> (0);
cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat);
diff --git a/samples/common/CrowWin.cs b/samples/common/CrowWin.cs
index 5f59e83..ae3ca71 100644
--- a/samples/common/CrowWin.cs
+++ b/samples/common/CrowWin.cs
@@ -33,7 +33,7 @@ namespace Crow {
crowThread.Start ();
while (crow == null)
- Thread.Sleep (5);
+ Thread.Sleep (2);
initUISurface ();
diff --git a/samples/compute/delaunay.cs b/samples/compute/delaunay.cs
index d87c02a..a0af948 100644
--- a/samples/compute/delaunay.cs
+++ b/samples/compute/delaunay.cs
@@ -49,15 +49,14 @@ namespace delaunay {
public Program () : base () {
-#if DEBUG
- dbgReport = new DebugReport (instance,
- VkDebugReportFlagsEXT.ErrorEXT
- | VkDebugReportFlagsEXT.DebugEXT
- | VkDebugReportFlagsEXT.WarningEXT
- | VkDebugReportFlagsEXT.PerformanceWarningEXT
-
- );
-#endif
+ if (Instance.DebugUtils)
+ dbgReport = new DebugReport (instance,
+ VkDebugReportFlagsEXT.ErrorEXT
+ | VkDebugReportFlagsEXT.DebugEXT
+ | VkDebugReportFlagsEXT.WarningEXT
+ | VkDebugReportFlagsEXT.PerformanceWarningEXT
+
+ );
imgResult = new Image (dev, VkFormat.R32g32b32a32Sfloat, VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled, VkMemoryPropertyFlags.DeviceLocal,
imgDim, imgDim);
imgResult.CreateView ();
@@ -313,9 +312,7 @@ namespace delaunay {
imgResult.Dispose ();
-#if DEBUG
- dbgReport.Dispose ();
-#endif
+ dbgReport?.Dispose ();
}
}
diff --git a/samples/deferred/deferred.csproj b/samples/deferred/deferred.csproj
index 4d0a27c..a670d9f 100644
--- a/samples/deferred/deferred.csproj
+++ b/samples/deferred/deferred.csproj
@@ -31,8 +31,7 @@
<Compile Include="EnvironmentPipeline.cs;deferredPbrRenderer.cs;shadowMapRenderer.cs" />
</ItemGroup>
- <ItemGroup Condition="$(Configuration) == 'DebugCrow' ">
- <PackageReference Include="Crow.VK" Version="0.9.0-beta" />
+ <ItemGroup Condition="'$(Configuration)' == 'DebugCrow' ">
<Compile Include="../common/CrowWin.cs" />
<Compile Include="main-crow.cs" />
<EmbeddedResource Include="ui\**\*.*">
@@ -51,6 +50,7 @@
<ItemGroup>
<PackageReference Include="Vulkan" Version="0.1.2.8-beta" />
<ProjectReference Include="..\..\vke\CVKL.csproj" />
+ <PackageReference Include="Crow.VK" Version="0.9.0-beta" />
</ItemGroup>
<Import Project="$(SolutionDir)spirv.targets" />
diff --git a/samples/deferred/deferredPbrRenderer.cs b/samples/deferred/deferredPbrRenderer.cs
index 74dc4ca..971eb64 100644
--- a/samples/deferred/deferredPbrRenderer.cs
+++ b/samples/deferred/deferredPbrRenderer.cs
@@ -10,7 +10,8 @@ namespace deferred {
SwapChain swapChain;
public PresentQueue presentQueue;
- public static VkSampleCountFlags NUM_SAMPLES = VkSampleCountFlags.SampleCount4;
+ public static int MAX_MATERIAL_COUNT = 8;
+ public static VkSampleCountFlags NUM_SAMPLES = VkSampleCountFlags.SampleCount1;
public static VkFormat HDR_FORMAT = VkFormat.R32g32b32a32Sfloat;
public static VkFormat MRT_FORMAT = VkFormat.R32g32b32a32Sfloat;
@@ -29,6 +30,8 @@ namespace deferred {
shadowMap
}
+ public static bool EnableTextureArray = false;
+
public DebugView currentDebugView = DebugView.none;
public int lightNumDebug = 0;
public int debugMip = 0;
@@ -57,11 +60,11 @@ namespace deferred {
};
public Light[] lights = {
new Light {
- position = new Vector4(2.5f,3.5f,2,0f),
+ position = new Vector4(2.5f,5.5f,2,0f),
color = new Vector4(1,0.8f,0.8f,1)
},
new Light {
- position = new Vector4(-2.5f,2.5f,2,0f),
+ position = new Vector4(-2.5f,5.5f,2,0f),
color = new Vector4(0.8f,0.8f,1,1)
}
};
@@ -106,8 +109,8 @@ namespace deferred {
descriptorPool = new DescriptorPool (dev, 3,
new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer, 3),
new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 5),
- new VkDescriptorPoolSize (VkDescriptorType.InputAttachment, 6)
- );
+ new VkDescriptorPoolSize (VkDescriptorType.InputAttachment, 5)
+ );
uboMatrices = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, matrices, true);
uboLights = new HostBuffer<Light> (dev, VkBufferUsageFlags.UniformBuffer, lights, true);
@@ -119,12 +122,11 @@ namespace deferred {
init (nearPlane, farPlane);
}
- void init (float nearPlane, float farPlane) {
-
+ void init_renderpass () {
renderPass = new RenderPass (dev, NUM_SAMPLES);
renderPass.AddAttachment (swapChain.ColorFormat, VkImageLayout.PresentSrcKHR, VkSampleCountFlags.SampleCount1);//swapchain image
- renderPass.AddAttachment (dev.GetSuitableDepthFormat(), VkImageLayout.DepthStencilAttachmentOptimal, NUM_SAMPLES);
+ renderPass.AddAttachment (dev.GetSuitableDepthFormat (), VkImageLayout.DepthStencilAttachmentOptimal, NUM_SAMPLES);
renderPass.AddAttachment (swapChain.ColorFormat, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff0 (color + roughness) and final color before resolve
renderPass.AddAttachment (VkFormat.R8g8b8a8Unorm, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff1 (emit + metal)
renderPass.AddAttachment (MRT_FORMAT, VkImageLayout.ColorAttachmentOptimal, NUM_SAMPLES, VkAttachmentLoadOp.Clear, VkAttachmentStoreOp.DontCare);//GBuff2 (normals + AO)
@@ -139,7 +141,7 @@ namespace deferred {
renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) });
renderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0.0f, 0.0f, 0.0f) });
- SubPass[] subpass = { new SubPass (), new SubPass (), new SubPass(), new SubPass() };
+ SubPass[] subpass = { new SubPass (), new SubPass (), new SubPass (), new SubPass () };
//skybox
subpass[SP_SKYBOX].AddColorReference (6, VkImageLayout.ColorAttachmentOptimal);
//models
@@ -156,17 +158,17 @@ namespace deferred {
new VkAttachmentReference (3, VkImageLayout.ShaderReadOnlyOptimal),
new VkAttachmentReference (4, VkImageLayout.ShaderReadOnlyOptimal),
new VkAttachmentReference (5, VkImageLayout.ShaderReadOnlyOptimal));
- //tone mapping
+ //tone mapping
subpass[SP_TONE_MAPPING].AddColorReference ((NUM_SAMPLES == VkSampleCountFlags.SampleCount1) ? 0u : 2u, VkImageLayout.ColorAttachmentOptimal);
subpass[SP_TONE_MAPPING].AddInputReference (new VkAttachmentReference (6, VkImageLayout.ShaderReadOnlyOptimal));
- if (NUM_SAMPLES != VkSampleCountFlags.SampleCount1)
+ if (NUM_SAMPLES != VkSampleCountFlags.SampleCount1)
subpass[SP_TONE_MAPPING].AddResolveReference (0, VkImageLayout.ColorAttachmentOptimal);
-
+
renderPass.AddSubpass (subpass);
renderPass.AddDependency (Vk.SubpassExternal, SP_SKYBOX,
- VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput,
- VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite);
+ VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput,
+ VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite);
renderPass.AddDependency (SP_SKYBOX, SP_MODELS,
VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader,
VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead);
@@ -177,9 +179,12 @@ namespace deferred {
VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader,
VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.ShaderRead);
renderPass.AddDependency (SP_TONE_MAPPING, Vk.SubpassExternal,
- VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe,
- VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);
+ VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe,
+ VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead);
+ }
+ void init (float nearPlane, float farPlane) {
+ init_renderpass ();
descLayoutMain = new DescriptorSetLayout (dev,
new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer),//matrices and params
@@ -192,13 +197,17 @@ namespace deferred {
descLayoutMain.Bindings.Add (new VkDescriptorSetLayoutBinding (6, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler));
#endif
- 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)
- );
+ if (EnableTextureArray) {
+ descLayoutMain.Bindings.Add (new VkDescriptorSetLayoutBinding (7, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler));//texture array
+ } 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,
new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.InputAttachment),//color + roughness
@@ -215,7 +224,11 @@ namespace deferred {
cfg.multisampleState.minSampleShading = 0.5f;
}
cfg.Cache = pipelineCache;
- cfg.Layout = new PipelineLayout (dev, descLayoutMain, descLayoutTextures, descLayoutGBuff);
+ if (EnableTextureArray)
+ cfg.Layout = new PipelineLayout (dev, descLayoutMain, descLayoutGBuff);
+ else
+ cfg.Layout = new PipelineLayout (dev, descLayoutMain, descLayoutGBuff, descLayoutTextures);
+
cfg.Layout.AddPushConstants (
new VkPushConstantRange (VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf<Matrix4x4> ()),
new VkPushConstantRange (VkShaderStageFlags.Fragment, sizeof (int), 64)
@@ -232,10 +245,14 @@ namespace deferred {
using (SpecializationInfo constants = new SpecializationInfo (
new SpecializationConstant<float> (0, nearPlane),
- new SpecializationConstant<float> (1, farPlane))) {
+ new SpecializationConstant<float> (1, farPlane),
+ new SpecializationConstant<float> (2, MAX_MATERIAL_COUNT))) {
cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/GBuffPbr.vert.spv");
- cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/GBuffPbr.frag.spv", constants);
+ if (EnableTextureArray)
+ cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/GBuffPbrTexArray.frag.spv", constants);
+ else
+ cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/GBuffPbr.frag.spv", constants);
gBuffPipeline = new GraphicPipeline (cfg);
}
@@ -291,16 +308,26 @@ namespace deferred {
public void LoadModel (Queue transferQ, string path) {
dev.WaitIdle ();
model?.Dispose ();
- model = new PbrModel (transferQ, path,
- descLayoutTextures,
- AttachmentType.Color,
- AttachmentType.PhysicalProps,
- AttachmentType.Normal,
- AttachmentType.AmbientOcclusion,
- AttachmentType.Emissive);
- DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[5]);
- uboUpdate.Write (dev, model.materialUBO.Descriptor);
+ if (EnableTextureArray) {
+ model = new PbrModelTexArray (transferQ, path);
+
+ DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[5], descLayoutMain.Bindings[7]);
+ uboUpdate.Write (dev, model.materialUBO.Descriptor, (model as PbrModelTexArray).texArray.Descriptor);
+
+ } else {
+ model = new PbrModelSeparatedTextures (transferQ, path,
+ descLayoutTextures,
+ AttachmentType.Color,
+ AttachmentType.PhysicalProps,
+ AttachmentType.Normal,
+ AttachmentType.AmbientOcclusion,
+ AttachmentType.Emissive);
+
+ DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[5]);
+ uboUpdate.Write (dev, model.materialUBO.Descriptor);
+ }
+
modelAABB = model.DefaultScene.AABB;
}
@@ -327,7 +354,7 @@ namespace deferred {
}
renderPass.BeginSubPass (cmd);
- cmd.BindDescriptorSet (composePipeline.Layout, dsGBuff, 2);
+ cmd.BindDescriptorSet (composePipeline.Layout, dsGBuff, 1);
if (currentDebugView == DebugView.none)
composePipeline.Bind (cmd);
@@ -451,7 +478,7 @@ namespace deferred {
debugPipeline.Dispose ();
descLayoutMain.Dispose ();
- descLayoutTextures.Dispose ();
+ descLayoutTextures?.Dispose ();
descLayoutGBuff.Dispose ();
uboMatrices.Dispose ();
diff --git a/samples/deferred/main-crow.cs b/samples/deferred/main-crow.cs
index 2a64e32..f3c06b4 100644
--- a/samples/deferred/main-crow.cs
+++ b/samples/deferred/main-crow.cs
@@ -1,21 +1,26 @@
using System;
using System.Numerics;
-using System.Runtime.InteropServices;
using Glfw;
using VK;
using CVKL;
-using System.Threading;
using System.Collections.Generic;
using System.Linq;
namespace deferred {
class Program : Crow.CrowWin {
static void Main (string[] args) {
+ Instance.DebugUtils = true;
+ Instance.Validation = true;
+ //Instance.RenderDocCapture = true;
+ DeferredPbrRenderer.EnableTextureArray = true;
+ PbrModelTexArray.TEXTURE_DIM = 512;
+
using (Program vke = new Program ()) {
vke.Run ();
}
}
+ #region crow ui
public Crow.Command CMDViewScenes, CMDViewEditor, CMDViewDebug, CMDViewMaterials;
void init_crow_commands () {
CMDViewScenes = new Crow.Command (new Action (() => loadWindow ("#deferred.main.crow", this))) { Caption = "Lighting", Icon = new Crow.SvgPicture ("#deferred.crow.svg"), CanExecute = true };
@@ -24,11 +29,6 @@ namespace deferred {
CMDViewMaterials = new Crow.Command (new Action (() => loadWindow ("#deferred.materials.crow", this))) { Caption = "Materials", Icon = new Crow.SvgPicture ("#deferred.crow.svg"), CanExecute = true };
}
- void onApplyMaterialChanges (object sender, Crow.MouseButtonEventArgs e) {
- Crow.ListBox lb = ((sender as Crow.Widget).Parent as Crow.Group).Children[0] as Crow.ListBox;
- renderer.model.materialUBO.Update (renderer.model.materials);
- }
-
public DeferredPbrRenderer.DebugView CurrentDebugView {
get { return renderer.currentDebugView; }
set {
@@ -73,8 +73,7 @@ namespace deferred {
}
public List<DeferredPbrRenderer.Light> Lights => renderer.lights.ToList ();
public List<Model.Scene> Scenes => renderer.model.Scenes;
- public PbrModel.PbrMaterial[] Materials => renderer.model.materials;
-
+ #endregion
protected override void configureEnabledFeatures (VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures features) {
base.configureEnabledFeatures (available_features, ref features);
@@ -82,9 +81,17 @@ namespace deferred {
features.samplerAnisotropy = available_features.samplerAnisotropy;
features.sampleRateShading = available_features.sampleRateShading;
features.geometryShader = available_features.geometryShader;
+ features.pipelineStatisticsQuery = true;
- if (available_features.textureCompressionBC) {
+ if (available_features.textureCompressionETC2) {
+ features.textureCompressionETC2 = true;
+ Image.DefaultTextureFormat = VkFormat.Etc2R8g8b8a8UnormBlock;
+ }else if (available_features.textureCompressionBC) {
+ //features.textureCompressionBC = true;
+ //Image.DefaultTextureFormat = VkFormat.Bc3UnormBlock;
}
+
+
}
protected override void createQueues () {
@@ -100,6 +107,7 @@ namespace deferred {
"../../../samples/data/textures/uffizi_cube.ktx",
};
string[] modelPathes = {
+ "/mnt/devel/gts/vkChess.net/data/models/chess.glb",
"../../../samples/data/models/DamagedHelmet/glTF/DamagedHelmet.gltf",
"../../../samples/data/models/shadow.glb",
"../../../samples/data/models/Hubble.glb",
@@ -112,8 +120,22 @@ namespace deferred {
Queue transferQ;
DeferredPbrRenderer renderer;
+ PipelineStatisticsQueryPool statPool;
+ TimestampQueryPool timestampQPool;
+ ulong[] results;
+
+ DebugReport dbgRepport;
Program () : base(true) {
+
+ if (Instance.DebugUtils)
+ dbgRepport = new DebugReport (instance,
+ VkDebugReportFlagsEXT.ErrorEXT
+ | VkDebugReportFlagsEXT.DebugEXT
+ | VkDebugReportFlagsEXT.WarningEXT
+ | VkDebugReportFlagsEXT.PerformanceWarningEXT
+ );
+
camera = new Camera (Utils.DegreesToRadians (45f), 1f, 0.1f, 16f);
camera.SetPosition (0, 0, 2);
@@ -121,16 +143,24 @@ namespace deferred {
renderer.LoadModel (transferQ, modelPathes[curModelIndex]);
camera.Model = Matrix4x4.CreateScale (1f / Math.Max (Math.Max (renderer.modelAABB.Width, renderer.modelAABB.Height), renderer.modelAABB.Depth));
+ statPool = new PipelineStatisticsQueryPool (dev,
+ VkQueryPipelineStatisticFlags.InputAssemblyVertices |
+ VkQueryPipelineStatisticFlags.InputAssemblyPrimitives |
+ VkQueryPipelineStatisticFlags.ClippingInvocations |
+ VkQueryPipelineStatisticFlags.ClippingPrimitives |
+ VkQueryPipelineStatisticFlags.FragmentShaderInvocations);
+
+ timestampQPool = new TimestampQueryPool (dev);
+
init_crow_commands ();
crow.Load ("#deferred.menu.crow").DataSource = this;
- //crow.Load ("#deferred.testImage.crow").DataSource = this;
-
- //crow.LoadIMLFragment (@"<Image Width='32' Height='32' Margin='2' HorizontalAlignment='Left' VerticalAlignment='Top' Path='/mnt/devel/gts/vkvg/build/data/tiger.svg' Background='Grey' MouseEnter='{Background=Blue}' MouseLeave='{Background=White}'/>");
}
protected override void recordDraw (CommandBuffer cmd, int imageIndex) {
+ statPool.Begin (cmd);
renderer.buildCommandBuffers (cmd, imageIndex);
+ statPool.End (cmd);
}
public override void UpdateView () {
@@ -161,6 +191,8 @@ namespace deferred {
NotifyValueChanged ("fps", fps);
frameCount = 0;
}
+
+ results = statPool.GetResults ();
}
protected override void OnResize () {
renderer.Resize ();
@@ -168,7 +200,6 @@ namespace deferred {
}
#region Mouse and keyboard
-
protected override void onMouseMove (double xPos, double yPos) {
if (crow.ProcessMouseMove ((int)xPos, (int)yPos))
return;
@@ -345,8 +376,12 @@ namespace deferred {
protected override void Dispose (bool disposing) {
if (disposing) {
- if (!isDisposed)
+ if (!isDisposed) {
renderer.Dispose ();
+ statPool.Dispose ();
+ timestampQPool.Dispose ();
+ dbgRepport?.Dispose ();
+ }
}
base.Dispose (disposing);
diff --git a/samples/deferred/main.cs b/samples/deferred/main.cs
index 975f5d0..40f96cb 100644
--- a/samples/deferred/main.cs
+++ b/samples/deferred/main.cs
@@ -5,9 +5,16 @@ using Glfw;
using VK;
namespace deferred {
- class Program : VkWindow {
+ class Deferred : VkWindow {
static void Main (string[] args) {
- using (Program vke = new Program ()) {
+
+ Instance.Validation = true;
+ //Instance.DebugUtils = true;
+ //Instance.RenderDocCapture = true;
+ DeferredPbrRenderer.EnableTextureArray = true;
+ PbrModelTexArray.TEXTURE_DIM = 512;
+
+ using (Deferred vke = new Deferred ()) {
vke.Run ();
}
}
@@ -34,6 +41,7 @@ namespace deferred {
"../../../samples/data/textures/uffizi_cube.ktx",
};
string[] modelPathes = {
+ "/mnt/devel/gts/vkChess.net/data/models/chess.glb",
"../../../samples/data/models/DamagedHelmet/glTF/DamagedHelmet.gltf",
"../../../samples/data/models/shadow.glb",
"../../../samples/data/models/Hubble.glb",
@@ -47,11 +55,22 @@ namespace deferred {
Queue transferQ;
DeferredPbrRenderer renderer;
- Program () : base(true) {
+ DebugReport dbgRepport;
+
+ Deferred () : base(true) {
+
+ if (Instance.DebugUtils)
+ dbgRepport = new DebugReport (instance,
+ VkDebugReportFlagsEXT.ErrorEXT
+ | VkDebugReportFlagsEXT.DebugEXT
+ | VkDebugReportFlagsEXT.WarningEXT
+ | VkDebugReportFlagsEXT.PerformanceWarningEXT
+ );
+
camera = new Camera (Utils.DegreesToRadians (45f), 1f, 0.1f, 16f);
camera.SetPosition (0, 0, 2);
- renderer = new DeferredPbrRenderer (dev, swapChain, presentQueue, cubemapPathes[0], camera.NearPlane, camera.FarPlane);
+ renderer = new DeferredPbrRenderer (dev, swapChain, presentQueue, cubemapPathes[2], camera.NearPlane, camera.FarPlane);
renderer.LoadModel (transferQ, modelPathes[curModelIndex]);
camera.Model = Matrix4x4.CreateScale (1f / Math.Max (Math.Max (renderer.modelAABB.Width, renderer.modelAABB.Height), renderer.modelAABB.Depth));
@@ -255,8 +274,10 @@ namespace deferred {
protected override void Dispose (bool disposing) {
if (disposing) {
- if (!isDisposed)
+ if (!isDisposed) {
renderer.Dispose ();
+ dbgRepport?.Dispose ();
+ }
}
base.Dispose (disposing);
}
diff --git a/samples/deferred/shaders/GBuffPbr.frag b/samples/deferred/shaders/GBuffPbr.frag
index 20dcf13..ca398e6 100644
--- a/samples/deferred/shaders/GBuffPbr.frag
+++ b/samples/deferred/shaders/GBuffPbr.frag
@@ -7,6 +7,7 @@
layout (constant_id = 0) const float NEAR_PLANE = 0.1f;
layout (constant_id = 1) const float FAR_PLANE = 256.0f;
+layout (constant_id = 2) const int MAT_COUNT = 1;
struct Material {
vec4 baseColorFactor;
@@ -41,28 +42,17 @@ layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inUV0;
layout (location = 3) in vec2 inUV1;
-layout (set = 0, binding = 0) uniform UBO {
- mat4 projection;
- mat4 model;
- mat4 view;
- vec4 camPos;
-} ubo;
layout (set = 0, binding = 5) uniform UBOMaterials {
- Material materials[16];
+ Material materials[MAT_COUNT];
};
-layout (set = 0, binding = 1) uniform samplerCube samplerIrradiance;
-layout (set = 0, binding = 2) uniform samplerCube prefilteredMap;
-layout (set = 0, binding = 3) uniform sampler2D samplerBRDFLUT;
-
// Material bindings
-
-layout (set = 1, binding = 0) uniform sampler2D colorMap;
-layout (set = 1, binding = 1) uniform sampler2D physicalDescriptorMap;
-layout (set = 1, binding = 2) uniform sampler2D normalMap;
-layout (set = 1, binding = 3) uniform sampler2D aoMap;
-layout (set = 1, binding = 4) uniform sampler2D emissiveMap;
+layout (set = 2, binding = 0) uniform sampler2D colorMap;
+layout (set = 2, binding = 1) uniform sampler2D physicalDescriptorMap;
+layout (set = 2, binding = 2) uniform sampler2D normalMap;
+layout (set = 2, binding = 3) uniform sampler2D aoMap;
+layout (set = 2, binding = 4) uniform sampler2D emissiveMap;
layout (push_constant) uniform PushCsts {
diff --git a/samples/deferred/shaders/GBuffPbrTexArray.frag b/samples/deferred/shaders/GBuffPbrTexArray.frag
new file mode 100644
index 0000000..dee3471
--- /dev/null
+++ b/samples/deferred/shaders/GBuffPbrTexArray.frag
@@ -0,0 +1,211 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_ARB_shading_language_420pack : enable
+
+#define MANUAL_SRGB 0
+#define DEBUG 0
+
+layout (constant_id = 0) const float NEAR_PLANE = 0.1f;
+layout (constant_id = 1) const float FAR_PLANE = 256.0f;
+layout (constant_id = 2) const int MAT_COUNT = 1;
+
+struct Material {
+ vec4 baseColorFactor;
+ vec4 emissiveFactor;
+ vec4 diffuseFactor;
+ vec4 specularFactor;
+
+ float workflow;
+ uint tex0;
+ uint tex1;
+ int baseColorTex;
+
+ int physicalDescTex;
+ int normalTex;
+ int occlusionTex;
+ int emissiveTex;
+
+ float metallicFactor;
+ float roughnessFactor;
+ float alphaMask;
+ float alphaMaskCutoff;
+};
+const float M_PI = 3.141592653589793;
+const float c_MinRoughness = 0.04;
+
+const float PBR_WORKFLOW_METALLIC_ROUGHNESS = 1.0;
+const float PBR_WORKFLOW_SPECULAR_GLOSINESS = 2.0f;
+
+const uint MAP_COLOR = 0x1;
+const uint MAP_NORMAL = 0x2;
+const uint MAP_AO = 0x4;
+const uint MAP_METAL = 0x8;
+const uint MAP_ROUGHNESS = 0x10;
+const uint MAP_METALROUGHNESS = 0x20;
+const uint MAP_EMISSIVE = 0x40;
+
+layout (location = 0) in vec3 inWorldPos;
+layout (location = 1) in vec3 inNormal;
+layout (location = 2) in vec2 inUV0;
+layout (location = 3) in vec2 inUV1;
+
+layout (set = 0, binding = 5) uniform UBOMaterials {
+ Material materials[MAT_COUNT];
+};
+layout (set = 0, binding = 7) uniform sampler2DArray texArray;
+
+layout (push_constant) uniform PushCsts {
+ layout(offset = 64)
+ int materialIdx;
+};
+
+
+layout (location = 0) out vec4 outColorRough;
+layout (location = 1) out vec4 outEmitMetal;
+layout (location = 2) out vec4 outN_AO;
+layout (location = 3) out vec4 outPos;
+
+vec4 SRGBtoLINEAR(vec4 srgbIn)
+{
+ #ifdef MANUAL_SRGB
+ #ifdef SRGB_FAST_APPROXIMATION
+ vec3 linOut = pow(srgbIn.xyz,vec3(2.2));
+ #else //SRGB_FAST_APPROXIMATION
+ vec3 bLess = step(vec3(0.04045),srgbIn.xyz);
+ vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
+ #endif //SRGB_FAST_APPROXIMATION
+ return vec4(linOut,srgbIn.w);;
+ #else //MANUAL_SRGB
+ return srgbIn;
+ #endif //MANUAL_SRGB
+}
+
+// Find the normal for this fragment, pulling either from a predefined normal map
+// or from the interpolated mesh normal and tangent attributes.
+vec3 getNormal()
+{
+ vec3 tangentNormal;
+ // Perturb normal, see http://www.thetenthplanet.de/archives/1180
+ if ((materials[materialIdx].tex0 & MAP_NORMAL) == MAP_NORMAL)
+ tangentNormal = texture(texArray, vec3(inUV0, materials[materialIdx].normalTex)).xyz * 2.0 - 1.0;
+ else if ((materials[materialIdx].tex1 & MAP_NORMAL) == MAP_NORMAL)
+ tangentNormal = texture(texArray, vec3(inUV1, materials[materialIdx].normalTex)).xyz * 2.0 - 1.0;
+ else
+ return normalize(inNormal);
+
+ vec3 q1 = dFdx(inWorldPos);
+ vec3 q2 = dFdy(inWorldPos);
+ vec2 st1 = dFdx(inUV0);
+ vec2 st2 = dFdy(inUV0);
+
+ vec3 N = normalize(inNormal);
+ vec3 T = normalize(q1 * st2.t - q2 * st1.t);
+ vec3 B = -normalize(cross(N, T));
+ mat3 TBN = mat3(T, B, N);
+
+ return normalize(TBN * tangentNormal);
+}
+
+// Gets metallic factor from specular glossiness workflow inputs
+float convertMetallic(vec3 diffuse, vec3 specular, float maxSpecular) {
+ float perceivedDiffuse = sqrt(0.299 * diffuse.r * diffuse.r + 0.587 * diffuse.g * diffuse.g + 0.114 * diffuse.b * diffuse.b);
+ float perceivedSpecular = sqrt(0.299 * specular.r * specular.r + 0.587 * specular.g * specular.g + 0.114 * specular.b * specular.b);
+ if (perceivedSpecular < c_MinRoughness) {
+ return 0.0;
+ }
+ float a = c_MinRoughness;
+ float b = perceivedDiffuse * (1.0 - maxSpecular) / (1.0 - c_MinRoughness) + perceivedSpecular - 2.0 * c_MinRoughness;
+ float c = c_MinRoughness - perceivedSpecular;
+ float D = max(b * b - 4.0 * a * c, 0.0);
+ return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0);
+}
+
+float linearDepth(float depth)
+{
+ float z = depth * 2.0f - 1.0f;
+ return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE));
+}
+
+void main()
+{
+ float perceptualRoughness;
+ float metallic;
+ vec4 baseColor;
+ vec3 emissive = vec3(0);
+
+ baseColor = materials[materialIdx].baseColorFactor;
+
+ if (materials[materialIdx].workflow == PBR_WORKFLOW_METALLIC_ROUGHNESS) {
+ perceptualRoughness = materials[materialIdx].roughnessFactor;
+ metallic = materials[materialIdx].metallicFactor;
+ // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
+ // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
+ if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){
+ perceptualRoughness *= texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).g;
+ metallic *= texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).b;
+ }else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){
+ perceptualRoughness *= texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).g;
+ metallic *= texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).b;
+ }
+ perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
+ metallic = clamp(metallic, 0.0, 1.0);
+
+ // The albedo may be defined from a base texture or a flat color
+ if ((materials[materialIdx].tex0 & MAP_COLOR) == MAP_COLOR)
+ baseColor *= SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].baseColorTex)));
+ else if ((materials[materialIdx].tex1 & MAP_COLOR) == MAP_COLOR)
+ baseColor *= SRGBtoLINEAR(texture(texArray, vec3(inUV1, materials[materialIdx].baseColorTex)));
+ }
+
+ if (materials[materialIdx].alphaMask == 1.0f) {
+ if (baseColor.a < materials[materialIdx].alphaMaskCutoff)
+ discard;
+ }
+
+ if (materials[materialIdx].workflow == PBR_WORKFLOW_SPECULAR_GLOSINESS) {
+ // Values from specular glossiness workflow are converted to metallic roughness
+ if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS)
+ perceptualRoughness = 1.0 - texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).a;
+ else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS)
+ perceptualRoughness = 1.0 - texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).a;
+ else
+ perceptualRoughness = 0.0;
+
+ const float epsilon = 1e-6;
+
+ vec4 diffuse = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].baseColorTex)));
+ vec3 specular = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex))).rgb;
+
+ float maxSpecular = max(max(specular.r, specular.g), specular.b);
+
+ // Convert metallic value from specular glossiness inputs
+ metallic = convertMetallic(diffuse.rgb, specular, maxSpecular);
+
+ vec3 baseColorDiffusePart = diffuse.rgb * ((1.0 - maxSpecular) / (1 - c_MinRoughness) / max(1 - metallic, epsilon)) * materials[materialIdx].diffuseFactor.rgb;
+ vec3 baseColorSpecularPart = specular - (vec3(c_MinRoughness) * (1 - metallic) * (1 / max(metallic, epsilon))) * materials[materialIdx].specularFactor.rgb;
+ baseColor = vec4(mix(baseColorDiffusePart, baseColorSpecularPart, metallic * metallic), diffuse.a);
+
+ }
+
+ const float u_OcclusionStrength = 1.0f;
+ const float u_EmissiveFactor = 1.0f;
+ float ao = 1.0f;
+
+ if ((materials[materialIdx].tex0 & MAP_EMISSIVE) == MAP_EMISSIVE)
+ emissive = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].emissiveTex))).rgb * u_EmissiveFactor;
+ else if ((materials[materialIdx].tex1 & MAP_EMISSIVE) == MAP_EMISSIVE)
+ emissive = SRGBtoLINEAR(texture(texArray, vec3(inUV1, materials[materialIdx].emissiveTex))).rgb * u_EmissiveFactor;
+
+ if ((materials[materialIdx].tex0 & MAP_AO) == MAP_AO)
+ ao = texture(texArray, vec3(inUV0, materials[materialIdx].occlusionTex)).r;
+ else if ((materials[materialIdx].tex1 & MAP_AO) == MAP_AO)
+ ao = texture(texArray, vec3(inUV1, materials[materialIdx].occlusionTex)).r;
+
+ vec3 n = getNormal();
+ vec3 p = inWorldPos;
+
+ outColorRough = vec4 (baseColor.rgb, perceptualRoughness);
+ outEmitMetal = vec4 (emissive, metallic);
+ outN_AO = vec4 (n, ao);
+ outPos = vec4 (p, linearDepth(gl_FragCoord.z));
+} \ No newline at end of file
diff --git a/samples/deferred/shaders/compose.frag b/samples/deferred/shaders/compose.frag
index 4b5c205..81312bd 100644
--- a/samples/deferred/shaders/compose.frag
+++ b/samples/deferred/shaders/compose.frag
@@ -28,10 +28,10 @@ layout (set = 0, binding = 4) uniform UBOLights {
const float M_PI = 3.141592653589793;
const float c_MinRoughness = 0.04;
-layout (input_attachment_index = 0, set = 2, binding = 0) uniform subpassInputMS samplerColorRough;
-layout (input_attachment_index = 1, set = 2, binding = 1) uniform subpassInputMS samplerEmitMetal;
-layout (input_attachment_index = 2, set = 2, binding = 2) uniform subpassInputMS samplerN_AO;
-layout (input_attachment_index = 3, set = 2, binding = 3) uniform subpassInputMS samplerPos;
+layout (input_attachment_index = 0, set = 1, binding = 0) uniform subpassInputMS samplerColorRough;
+layout (input_attachment_index = 1, set = 1, binding = 1) uniform subpassInputMS samplerEmitMetal;
+layout (input_attachment_index = 2, set = 1, binding = 2) uniform subpassInputMS samplerN_AO;
+layout (input_attachment_index = 3, set = 1, binding = 3) uniform subpassInputMS samplerPos;
layout (set = 0, binding = 1) uniform samplerCube samplerIrradiance;
layout (set = 0, binding = 2) uniform samplerCube prefilteredMap;
diff --git a/samples/deferred/shaders/compose_with_shadows.frag b/samples/deferred/shaders/compose_with_shadows.frag
index e65aaaf..d8ad270 100644
--- a/samples/deferred/shaders/compose_with_shadows.frag
+++ b/samples/deferred/shaders/compose_with_shadows.frag
@@ -27,12 +27,12 @@ layout (set = 0, binding = 4) uniform UBOLights {
const float M_PI = 3.141592653589793;
const float c_MinRoughness = 0.04;
-#define SHADOW_FACTOR 0.55
+#define SHADOW_FACTOR 0.15
-layout (input_attachment_index = 0, set = 2, binding = 0) uniform subpassInputMS samplerColorRough;
-layout (input_attachment_index = 1, set = 2, binding = 1) uniform subpassInputMS samplerEmitMetal;
-layout (input_attachment_index = 2, set = 2, binding = 2) uniform subpassInputMS samplerN_AO;
-layout (input_attachment_index = 3, set = 2, binding = 3) uniform subpassInputMS samplerPos;
+layout (input_attachment_index = 0, set = 1, binding = 0) uniform subpassInputMS samplerColorRough;
+layout (input_attachment_index = 1, set = 1, binding = 1) uniform subpassInputMS samplerEmitMetal;
+layout (input_attachment_index = 2, set = 1, binding = 2) uniform subpassInputMS samplerN_AO;
+layout (input_attachment_index = 3, set = 1, binding = 3) uniform subpassInputMS samplerPos;
layout (set = 0, binding = 1) uniform samplerCube samplerIrradiance;
layout (set = 0, binding = 2) uniform samplerCube prefilteredMap;
diff --git a/samples/deferred/shaders/show_gbuff.frag b/samples/deferred/shaders/show_gbuff.frag
index a494688..7859e36 100644
--- a/samples/deferred/shaders/show_gbuff.frag
+++ b/samples/deferred/shaders/show_gbuff.frag
@@ -2,15 +2,15 @@
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
-layout (input_attachment_index = 0, set = 2, binding = 0) uniform subpassInputMS samplerColorRough;
-layout (input_attachment_index = 1, set = 2, binding = 1) uniform subpassInputMS samplerEmitMetal;
-layout (input_attachment_index = 2, set = 2, binding = 2) uniform subpassInputMS samplerN_AO;
-layout (input_attachment_index = 3, set = 2, binding = 3) uniform subpassInputMS samplerPos;
+layout (input_attachment_index = 0, set = 1, binding = 0) uniform subpassInputMS samplerColorRough;
+layout (input_attachment_index = 1, set = 1, binding = 1) uniform subpassInputMS samplerEmitMetal;
+layout (input_attachment_index = 2, set = 1, binding = 2) uniform subpassInputMS samplerN_AO;
+layout (input_attachment_index = 3, set = 1, binding = 3) uniform subpassInputMS samplerPos;
layout (set = 0, binding = 1) uniform samplerCube samplerIrradiance;
layout (set = 0, binding = 2) uniform samplerCube prefilteredMap;
layout (set = 0, binding = 3) uniform sampler2D samplerBRDFLUT;
-layout (set = 0, binding = 7) uniform sampler2DArray samplerShadowMap;
+layout (set = 0, binding = 6) uniform sampler2DArray samplerShadowMap;
layout (push_constant) uniform PushCsts {
layout(offset = 64)
diff --git a/samples/deferred/shaders/tone_mapping.frag b/samples/deferred/shaders/tone_mapping.frag
index 9c4dd43..187d672 100644
--- a/samples/deferred/shaders/tone_mapping.frag
+++ b/samples/deferred/shaders/tone_mapping.frag
@@ -11,7 +11,7 @@ layout (set = 0, binding = 0) uniform UBO {
float gamma;
} ubo;
-layout (input_attachment_index = 0, set = 2, binding = 4) uniform subpassInputMS samplerHDR;
+layout (input_attachment_index = 0, set = 1, binding = 4) uniform subpassInputMS samplerHDR;
layout (location = 0) in vec2 inUV;
layout (location = 0) out vec4 outColor;
diff --git a/samples/deferred/shadowMapRenderer.cs b/samples/deferred/shadowMapRenderer.cs
index e34b60f..2f5a24e 100644
--- a/samples/deferred/shadowMapRenderer.cs
+++ b/samples/deferred/shadowMapRenderer.cs
@@ -147,7 +147,6 @@ namespace deferred {
public void Dispose () {
shadowPipeline?.Dispose ();
fbShadowMap?.Dispose ();
- shadowPass?.Dispose ();
shadowMap?.Dispose ();
descriptorPool?.Dispose ();
}
diff --git a/samples/pbrSashaWillem/SachaWillemPbr.csproj b/samples/pbrSashaWillem/SachaWillemPbr.csproj
index 9deadf5..1e1cb59 100644
--- a/samples/pbrSashaWillem/SachaWillemPbr.csproj
+++ b/samples/pbrSashaWillem/SachaWillemPbr.csproj
@@ -24,6 +24,7 @@
<ItemGroup>
<PackageReference Include="Vulkan" Version="0.1.2.8-beta" />
+ <PackageReference Include="vkvg.net" Version="0.2.2-beta" />
</ItemGroup>
<ItemGroup>
diff --git a/vk.net.sln b/vk.net.sln
index fe63750..4addd1e 100644
--- a/vk.net.sln
+++ b/vk.net.sln
@@ -38,13 +38,13 @@ Global
{96A2E0B8-91AE-4EB9-A435-185D01E24067}.Release|Any CPU.Build.0 = Release|Any CPU
{96A2E0B8-91AE-4EB9-A435-185D01E24067}.temp|Any CPU.ActiveCfg = Debug|Any CPU
{96A2E0B8-91AE-4EB9-A435-185D01E24067}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
- {96A2E0B8-91AE-4EB9-A435-185D01E24067}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
+ {96A2E0B8-91AE-4EB9-A435-185D01E24067}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96A2A7896-91AE-4EB9-A435-185D01E24067}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96A2A7896-91AE-4EB9-A435-185D01E24067}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96A2A7896-91AE-4EB9-A435-185D01E24067}.Release|Any CPU.Build.0 = Release|Any CPU
{96A2A7896-91AE-4EB9-A435-185D01E24067}.temp|Any CPU.ActiveCfg = Debug|Any CPU
{96A2A7896-91AE-4EB9-A435-185D01E24067}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
- {96A2A7896-91AE-4EB9-A435-185D01E24067}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
+ {96A2A7896-91AE-4EB9-A435-185D01E24067}.Debug|Any CPU.Build.0 = Debug|Any CPU
{87AC7BE1-143E-4FF4-91F8-981B1CAAF1DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{87AC7BE1-143E-4FF4-91F8-981B1CAAF1DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{87AC7BE1-143E-4FF4-91F8-981B1CAAF1DD}.Release|Any CPU.Build.0 = Release|Any CPU
@@ -52,7 +52,6 @@ Global
{87AC7BE1-143E-4FF4-91F8-981B1CAAF1DD}.temp|Any CPU.ActiveCfg = Debug|Any CPU
{87AC7BE1-143E-4FF4-91F8-981B1CAAF1DD}.temp|Any CPU.Build.0 = Debug|Any CPU
{87AC7BE1-143E-4FF4-91F8-981B1CAAF1DD}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
- {87AC7BE1-143E-4FF4-91F8-981B1CAAF1DD}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
{F41EA96F-A9F7-4E85-B2EE-5757C5FAD00D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F41EA96F-A9F7-4E85-B2EE-5757C5FAD00D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F41EA96F-A9F7-4E85-B2EE-5757C5FAD00D}.Release|Any CPU.Build.0 = Release|Any CPU
@@ -60,26 +59,23 @@ Global
{F41EA96F-A9F7-4E85-B2EE-5757C5FAD00D}.temp|Any CPU.ActiveCfg = Debug|Any CPU
{F41EA96F-A9F7-4E85-B2EE-5757C5FAD00D}.temp|Any CPU.Build.0 = Debug|Any CPU
{F41EA96F-A9F7-4E85-B2EE-5757C5FAD00D}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
- {F41EA96F-A9F7-4E85-B2EE-5757C5FAD00D}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
{1F18E74F-BCC9-481C-8FDF-89D81CBB30BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F18E74F-BCC9-481C-8FDF-89D81CBB30BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F18E74F-BCC9-481C-8FDF-89D81CBB30BE}.Release|Any CPU.Build.0 = Release|Any CPU
{1F18E74F-BCC9-481C-8FDF-89D81CBB30BE}.temp|Any CPU.ActiveCfg = Debug|Any CPU
{1F18E74F-BCC9-481C-8FDF-89D81CBB30BE}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
- {1F18E74F-BCC9-481C-8FDF-89D81CBB30BE}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
+ {1F18E74F-BCC9-481C-8FDF-89D81CBB30BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F05E74F-AEE8-481C-8FDF-456654CC30BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F05E74F-AEE8-481C-8FDF-456654CC30BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F05E74F-AEE8-481C-8FDF-456654CC30BE}.Release|Any CPU.Build.0 = Release|Any CPU
{1F05E74F-AEE8-481C-8FDF-456654CC30BE}.temp|Any CPU.ActiveCfg = Debug|Any CPU
{1F05E74F-AEE8-481C-8FDF-456654CC30BE}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
- {1F05E74F-AEE8-481C-8FDF-456654CC30BE}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
{1603D809-D9C4-4EE5-B921-B053CE22E068}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1603D809-D9C4-4EE5-B921-B053CE22E068}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1603D809-D9C4-4EE5-B921-B053CE22E068}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1603D809-D9C4-4EE5-B921-B053CE22E068}.Release|Any CPU.Build.0 = Release|Any CPU
{1603D809-D9C4-4EE5-B921-B053CE22E068}.temp|Any CPU.ActiveCfg = Debug|Any CPU
{1603D809-D9C4-4EE5-B921-B053CE22E068}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
- {1603D809-D9C4-4EE5-B921-B053CE22E068}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
{9E12DFE6-7DC7-4BF2-8077-42DDC69FD0A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E12DFE6-7DC7-4BF2-8077-42DDC69FD0A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E12DFE6-7DC7-4BF2-8077-42DDC69FD0A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -92,7 +88,7 @@ Global
{001F5D64-871B-47A4-A823-78C7CE3785AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{001F5D64-871B-47A4-A823-78C7CE3785AA}.temp|Any CPU.ActiveCfg = Debug|Any CPU
{001F5D64-871B-47A4-A823-78C7CE3785AA}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
- {001F5D64-871B-47A4-A823-78C7CE3785AA}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
+ {001F5D64-871B-47A4-A823-78C7CE3785AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFF1BEEC-2E93-4963-AD3C-2A8C9BA05C36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BFF1BEEC-2E93-4963-AD3C-2A8C9BA05C36}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFF1BEEC-2E93-4963-AD3C-2A8C9BA05C36}.temp|Any CPU.ActiveCfg = Debug|Any CPU
@@ -101,7 +97,7 @@ Global
{05515E15-D3C3-4A8C-A940-9467D9D77823}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{05515E15-D3C3-4A8C-A940-9467D9D77823}.temp|Any CPU.ActiveCfg = Debug|Any CPU
{05515E15-D3C3-4A8C-A940-9467D9D77823}.DebugCrow|Any CPU.ActiveCfg = Debug|Any CPU
- {05515E15-D3C3-4A8C-A940-9467D9D77823}.DebugCrow|Any CPU.Build.0 = Debug|Any CPU
+ {05515E15-D3C3-4A8C-A940-9467D9D77823}.Debug|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{96A2E0B8-91AE-4EB9-A435-185D01E24067} = {A2A2849A-0032-4AA8-BC0E-82C69D7DE354}
diff --git a/vke/CVKL.csproj b/vke/CVKL.csproj
index af5170d..02be0d8 100644
--- a/vke/CVKL.csproj
+++ b/vke/CVKL.csproj
@@ -4,7 +4,7 @@
<TargetFrameworks>net471;netstandard2.0</TargetFrameworks>
<Copyright></Copyright>
- <AssemblyVersion>0.1.3.1</AssemblyVersion>
+ <AssemblyVersion>0.1.3.2</AssemblyVersion>
<Description>C# vulkan library with IDispose model and references counting</Description>
<Company></Company>
<Product>CVKL</Product>
diff --git a/vke/src/Image.cs b/vke/src/Image.cs
index 96015cb..9b0e5e6 100644
--- a/vke/src/Image.cs
+++ b/vke/src/Image.cs
@@ -36,6 +36,8 @@ namespace CVKL {
/// such imported image will not be disposed with the sampler and the view.
/// </summary>
public class Image : Resource {
+ public static VkFormat DefaultTextureFormat = VkFormat.R8g8b8a8Unorm;
+
internal VkImage handle;
VkImageCreateInfo info = VkImageCreateInfo.New();
@@ -102,16 +104,21 @@ namespace CVKL {
}
#endregion
+ public static uint ComputeMipLevels(uint size) => (uint)Math.Floor (Math.Log (size)) + 1;
+
#region bitmap loading
/// <summary>
/// Load image from data pointed by IntPtr pointer containing full image file (jpg, png,...)
/// </summary>
public static Image Load (Device dev, Queue staggingQ, CommandPool staggingCmdPool,
- IntPtr bitmap, ulong bitmapByteCount, VkFormat format = VkFormat.R8g8b8a8Unorm,
+ IntPtr bitmap, ulong bitmapByteCount, 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) {
+ VkImageUsageFlags usage = VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst) {
+
+ if (format == VkFormat.Undefined)
+ format = DefaultTextureFormat;
int width, height, channels;
IntPtr imgPtr = Stb.Load (bitmap, (int)bitmapByteCount, out width, out height, out channels, 4);
@@ -135,44 +142,10 @@ namespace CVKL {
return img;
}
/// <summary>
- /// Load image from data pointed by IntPtr pointer containing full image file (jpg, png,...)
- /// </summary>
- public static Image Load (Device dev,
- IntPtr bitmap, ulong bitmapByteCount, VkImageUsageFlags usage = VkImageUsageFlags.TransferSrc,
- VkFormat format = VkFormat.R8g8b8a8Unorm,
- VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
- VkImageTiling tiling = VkImageTiling.Linear, bool generateMipmaps = false,
- VkImageType imageType = VkImageType.Image2D) {
-
- int width, height, channels;
- IntPtr imgPtr = Stb.Load (bitmap, (int)bitmapByteCount, out width, out height, out channels, 4);
-
- if (imgPtr == IntPtr.Zero)
- throw new Exception ($"STBI image loading error.");
-
- uint mipLevels = generateMipmaps ? (uint)Math.Floor (Math.Log (Math.Max (width, height))) + 1 : 1;
-
- if (generateMipmaps)
- usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
-
- long size = width * height * 4;
- Image img = new Image (dev, format, usage, memoryProps, (uint)width, (uint)height, imageType, VkSampleCountFlags.SampleCount1, tiling, mipLevels);
-
- img.Map ();
- unsafe {
- System.Buffer.MemoryCopy (imgPtr.ToPointer (), img.MappedData.ToPointer (), size, size);
- }
- img.Unmap ();
-
- Stb.FreeImage (imgPtr);
-
- return img;
- }
- /// <summary>
/// Load image from byte array containing full image file (jpg, png,...)
/// </summary>
public static Image Load (Device dev, Queue staggingQ, CommandPool staggingCmdPool,
- byte[] bitmap, VkFormat format = VkFormat.R8g8b8a8Unorm,
+ byte[] bitmap, VkFormat format = VkFormat.Undefined,
VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.DeviceLocal,
VkImageTiling tiling = VkImageTiling.Optimal, bool generateMipmaps = true,
VkImageType imageType = VkImageType.Image2D,
@@ -181,75 +154,23 @@ namespace CVKL {
Image img = Load (dev, staggingQ, staggingCmdPool, bitmap.Pin (), (ulong)bitmap.Length, format, memoryProps, tiling, generateMipmaps,
imageType, usage);
bitmap.Unpin ();
-
- //int width, height, channels;
- //IntPtr imgPtr = Stb.Load (, bitmap.Length, out width, out height, out channels, 4);
-
- //if (imgPtr == IntPtr.Zero)
- // throw new Exception ($"STBI image loading error.");
-
- //uint mipLevels = generateMipmaps ? (uint)Math.Floor (Math.Log (Math.Max (width, height))) + 1 : 1;
-
- //if (tiling == VkImageTiling.Optimal)
- // usage |= VkImageUsageFlags.TransferDst;
- //if (generateMipmaps)
- // usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
-
- //Image img = new Image (dev, format, usage, memoryProps, (uint)width, (uint)height, imageType, VkSampleCountFlags.SampleCount1, tiling, mipLevels);
-
- //img.load (staggingQ, staggingCmdPool, imgPtr, generateMipmaps);
-
- //Stb.FreeImage (imgPtr);
-
return img;
}
/// <summary>
- /// load bitmap from pointer
- /// </summary>
- void load (Queue staggingQ, CommandPool staggingCmdPool, IntPtr bitmap, bool generateMipmaps = true)
- {
- long size = info.extent.width * info.extent.height * 4 * info.extent.depth;
-
- if (MemoryFlags.HasFlag (VkMemoryPropertyFlags.HostVisible)) {
- Map ();
- unsafe {
- System.Buffer.MemoryCopy (bitmap.ToPointer (), MappedData.ToPointer (), size, size);
- }
- Unmap ();
-
- if (generateMipmaps)
- BuildMipmaps (staggingQ, staggingCmdPool);
- } else {
- using (HostBuffer stagging = new HostBuffer (Dev, VkBufferUsageFlags.TransferSrc, (UInt64)size, bitmap)) {
-
- CommandBuffer cmd = staggingCmdPool.AllocateCommandBuffer ();
-
- cmd.Start (VkCommandBufferUsageFlags.OneTimeSubmit);
-
- stagging.CopyTo (cmd, this);
- if (generateMipmaps)
- BuildMipmaps (cmd);
-
- cmd.End ();
- staggingQ.Submit (cmd);
- staggingQ.WaitIdle ();
- cmd.Free ();
- }
- }
- }
-
- /// <summary>
/// Load bitmap into Image with stagging and mipmap generation if necessary
/// and usage.
/// </summary>
public static Image Load (Device dev, Queue staggingQ, CommandPool staggingCmdPool,
- string path, VkFormat format = VkFormat.R8g8b8a8Unorm,
+ 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) {
+ if (format == VkFormat.Undefined)
+ format = DefaultTextureFormat;
+
int width, height, channels;
IntPtr imgPtr = Stb.Load (path, out width, out height, out channels, 4);
if (imgPtr == IntPtr.Zero)
@@ -272,15 +193,18 @@ namespace CVKL {
}
/// <summary>
- /// create host visible linear image without command
+ /// create host visible linear image without command from path
/// </summary>
public static Image Load (Device dev,
- string path, VkFormat format = VkFormat.R8g8b8a8Unorm, bool reserveSpaceForMipmaps = true,
+ string path, VkFormat format = VkFormat.Undefined, bool reserveSpaceForMipmaps = true,
VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
VkImageTiling tiling = VkImageTiling.Linear,
VkImageType imageType = VkImageType.Image2D,
VkImageUsageFlags usage = VkImageUsageFlags.Sampled) {
+ if (format == VkFormat.Undefined)
+ format = DefaultTextureFormat;
+
int width, height, channels;
IntPtr imgPtr = Stb.Load (path, out width, out height, out channels, 4);
if (imgPtr == IntPtr.Zero)
@@ -301,9 +225,96 @@ namespace CVKL {
return img;
}
-#endregion
+ /// <summary>
+ /// create host visible linear image without command from byte array
+ /// </summary>
+ public static Image Load (Device dev,
+ byte[] bitmap, VkImageUsageFlags usage = VkImageUsageFlags.TransferSrc,
+ VkFormat format = VkFormat.Undefined,
+ VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
+ VkImageTiling tiling = VkImageTiling.Linear, bool generateMipmaps = false,
+ VkImageType imageType = VkImageType.Image2D) {
+
+ Image img = Load (dev, bitmap.Pin (), (ulong)bitmap.Length, usage, format, memoryProps, tiling, generateMipmaps,
+ imageType);
+ bitmap.Unpin ();
+ return img;
+ }
+ /// <summary>
+ /// create host visible linear image without command from data pointed by IntPtr pointer containing full image file (jpg, png,...)
+ /// </summary>
+ public static Image Load (Device dev,
+ IntPtr bitmap, ulong bitmapByteCount, VkImageUsageFlags usage = VkImageUsageFlags.TransferSrc,
+ VkFormat format = VkFormat.Undefined,
+ VkMemoryPropertyFlags memoryProps = VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
+ VkImageTiling tiling = VkImageTiling.Linear, bool generateMipmaps = false,
+ VkImageType imageType = VkImageType.Image2D) {
+
+ if (format == VkFormat.Undefined)
+ format = DefaultTextureFormat;
+
+ int width, height, channels;
+ IntPtr imgPtr = Stb.Load (bitmap, (int)bitmapByteCount, out width, out height, out channels, 4);
+
+ if (imgPtr == IntPtr.Zero)
+ throw new Exception ($"STBI image loading error.");
+
+ uint mipLevels = generateMipmaps ? (uint)Math.Floor (Math.Log (Math.Max (width, height))) + 1 : 1;
+
+ if (generateMipmaps)
+ usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst);
+
+ long size = width * height * 4;
+ Image img = new Image (dev, format, usage, memoryProps, (uint)width, (uint)height, imageType, VkSampleCountFlags.SampleCount1, tiling, mipLevels);
+
+ img.Map ();
+ unsafe {
+ System.Buffer.MemoryCopy (imgPtr.ToPointer (), img.MappedData.ToPointer (), size, size);
+ }
+ img.Unmap ();
+
+ Stb.FreeImage (imgPtr);
+
+ return img;
+ }
+
+ /// <summary>
+ /// load bitmap from pointer
+ /// </summary>
+ void load (Queue staggingQ, CommandPool staggingCmdPool, IntPtr bitmap, bool generateMipmaps = true) {
+ long size = info.extent.width * info.extent.height * 4 * info.extent.depth;
+
+ if (MemoryFlags.HasFlag (VkMemoryPropertyFlags.HostVisible)) {
+ Map ();
+ unsafe {
+ System.Buffer.MemoryCopy (bitmap.ToPointer (), MappedData.ToPointer (), size, size);
+ }
+ Unmap ();
+
+ if (generateMipmaps)
+ BuildMipmaps (staggingQ, staggingCmdPool);
+ } else {
+ using (HostBuffer stagging = new HostBuffer (Dev, VkBufferUsageFlags.TransferSrc, (UInt64)size, bitmap)) {
+
+ CommandBuffer cmd = staggingCmdPool.AllocateCommandBuffer ();
+
+ cmd.Start (VkCommandBufferUsageFlags.OneTimeSubmit);
+
+ stagging.CopyTo (cmd, this);
+ if (generateMipmaps)
+ BuildMipmaps (cmd);
+
+ cmd.End ();
+ staggingQ.Submit (cmd);
+ staggingQ.WaitIdle ();
+ cmd.Free ();
+ }
+ }
+ }
+
+ #endregion
- internal override void updateMemoryRequirements () {
+ internal override void updateMemoryRequirements () {
vkGetImageMemoryRequirements (Dev.VkDev, handle, out memReqs);
}
internal override void bindMemory () {
diff --git a/vke/src/Instance.cs b/vke/src/Instance.cs
index 589b88b..423d3c0 100644
--- a/vke/src/Instance.cs
+++ b/vke/src/Instance.cs
@@ -31,6 +31,10 @@ using static VK.Vk;
namespace CVKL {
public class Instance : IDisposable {
+ public static bool Validation;
+ public static bool DebugUtils;
+ public static bool RenderDocCapture;
+
VkInstance inst;
static class Strings {
@@ -80,15 +84,16 @@ namespace CVKL {
throw new PlatformNotSupportedException ();
}
-#if DEBUG
- instanceExtensions.Add (Strings.VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
- instanceExtensions.Add (Strings.VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
- enabledLayerNames.Add (Strings.LayerMonitor);
- enabledLayerNames.Add (Strings.LayerValidation);
-#if RENDERDOC
- enabledLayerNames.Add (Strings.RenderdocCaptureLayerName);
-#endif
-#endif
+ if (Validation)
+ enabledLayerNames.Add (Strings.LayerValidation);
+ if (RenderDocCapture)
+ enabledLayerNames.Add (Strings.RenderdocCaptureLayerName);
+
+ if (DebugUtils) {
+ instanceExtensions.Add (Strings.VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ instanceExtensions.Add (Strings.VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+ }
+
VkApplicationInfo appInfo = new VkApplicationInfo () {
sType = VkStructureType.ApplicationInfo,
apiVersion = new Vulkan.Version (1, 0, 0),
diff --git a/vke/src/MarshaledObject.cs b/vke/src/MarshaledObject.cs
new file mode 100644
index 0000000..6d3beb7
--- /dev/null
+++ b/vke/src/MarshaledObject.cs
@@ -0,0 +1,64 @@
+//
+// MarshaledObject.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// Copyright (c) 2019 jp
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.InteropServices;
+
+namespace CVKL {
+ public class MarshaledObject<T> : IDisposable where T : struct {
+
+ GCHandle handle;
+
+ public IntPtr Pointer {
+ get {
+ if (!handle.IsAllocated)
+ throw new InvalidOperationException ("Unalocated MarshaledObject");
+ return handle.AddrOfPinnedObject ();
+ }
+ }
+
+ public MarshaledObject (T mobj) {
+ handle = GCHandle.Alloc (mobj, GCHandleType.Pinned);
+ }
+
+ void freeHandle () {
+ if (!disposed)
+ handle.Free ();
+ }
+
+ #region IDisposable Support
+ private bool disposed;
+
+ ~MarshaledObject() {
+ freeHandle ();
+ }
+
+ public void Dispose () {
+ freeHandle ();
+ GC.SuppressFinalize(this);
+ }
+ #endregion
+ }
+}
diff --git a/vke/src/Model.cs b/vke/src/Model.cs
index ed440a9..cc3a3dc 100644
--- a/vke/src/Model.cs
+++ b/vke/src/Model.cs
@@ -24,20 +24,13 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
-using System.Diagnostics;
+using System.Collections.Generic;
using System.Numerics;
-using System.Runtime.InteropServices;
-using glTFLoader;
-using GL = glTFLoader.Schema;
-
using VK;
-using System.Collections.Generic;
-using System.IO;
namespace CVKL {
- using static VK.Utils;
public struct BoundingBox {
public Vector3 min;
public Vector3 max;
@@ -141,18 +134,34 @@ namespace CVKL {
public class Scene {
public string Name;
public Node Root;
- public List<Node> GetNodes () => Root.Children;
+ public List<Node> GetNodes () => Root?.Children;
+ public Node FindNode(string name) => Root == null ? null : Root.FindNode (name);
- public BoundingBox AABB => Root.GetAABB (Matrix4x4.Identity);
+ public BoundingBox AABB => Root.GetAABB (Matrix4x4.Identity);
}
public class Node {
+ public string Name;
public Node Parent;
public List<Node> Children;
public Matrix4x4 localMatrix;
public Mesh Mesh;
- public Matrix4x4 Matrix {
+ public Node FindNode(string name)
+ {
+ if (Name == name)
+ return this;
+ if (Children == null)
+ return null;
+ foreach (Node child in Children) {
+ Node n = child.FindNode(name);
+ if (n != null)
+ return n;
+ }
+ return null;
+ }
+
+ public Matrix4x4 Matrix {
get { return Parent == null ? localMatrix : Parent.Matrix * localMatrix; }
}
@@ -180,8 +189,17 @@ namespace CVKL {
public List<Mesh> Meshes;
public List<Scene> Scenes;
+ public Node FindNode(string name) {
+ foreach (Scene scene in Scenes)
+ {
+ Node n = scene.FindNode(name);
+ if (n != null)
+ return n;
+ }
+ return null;
+ }
- public Dimensions dimensions = new Dimensions (new Vector3 (float.MaxValue), new Vector3 (float.MinValue));
+ public Dimensions dimensions = new Dimensions (new Vector3 (float.MaxValue), new Vector3 (float.MinValue));
//public struct MaterialStruct {
// public UInt32 baseColorTexture;
// public UInt32 metallicRoughnessTexture;
@@ -198,11 +216,11 @@ namespace CVKL {
public enum Workflow { PhysicalyBaseRendering = 1, SpecularGlossinnes };
public string Name;
public Workflow workflow;
- public UInt32 baseColorTexture;
- public UInt32 metallicRoughnessTexture;
- public UInt32 normalTexture;
- public UInt32 occlusionTexture;
- public UInt32 emissiveTexture;
+ public Int32 baseColorTexture;
+ public Int32 metallicRoughnessTexture;
+ public Int32 normalTexture;
+ public Int32 occlusionTexture;
+ public Int32 emissiveTexture;
public Vector4 baseColorFactor;
public Vector4 emissiveFactor;
@@ -224,15 +242,16 @@ namespace CVKL {
//}
//extension;
- public Material (UInt32 _baseColorTexture = 0, UInt32 _metallicRoughnessTexture = 0,
- UInt32 _normalTexture = 0, UInt32 _occlusionTexture = 0)
+ public Material (Int32 _baseColorTexture = -1, Int32 _metallicRoughnessTexture = -1,
+ Int32 _normalTexture = -1, Int32 _occlusionTexture = -1)
{
workflow = Workflow.PhysicalyBaseRendering;
baseColorTexture = _baseColorTexture;
metallicRoughnessTexture = _metallicRoughnessTexture;
normalTexture = _normalTexture;
occlusionTexture = _occlusionTexture;
- emissiveTexture = 0;
+ emissiveTexture = -1;
+
alphaMode = AlphaMode.Opaque;
alphaCutoff = 1f;
metallicFactor = 1f;
diff --git a/vke/src/PbrModel.cs b/vke/src/PbrModel.cs
index bcd5c9c..761001a 100644
--- a/vke/src/PbrModel.cs
+++ b/vke/src/PbrModel.cs
@@ -34,9 +34,8 @@ using System.Collections.Generic;
namespace CVKL {
using static VK.Utils;
-
//TODO:stride in buffer views?
- public class PbrModel : Model {
+ public abstract class PbrModel : Model {
public struct Vertex {
[VertexAttribute (VertexAttributeType.Position, VkFormat.R32g32b32Sfloat)]
public Vector3 pos;
@@ -50,33 +49,11 @@ namespace CVKL {
return pos.ToString () + ";" + normal.ToString () + ";" + uv0.ToString () + ";" + uv1.ToString ();
}
};
- /// <summary>
- /// Pbr data structure suitable for push constant or ubo, containing
- /// availablility of attached textures and the coef of pbr inputs
- /// </summary>
- public struct PbrMaterial {
- public Vector4 baseColorFactor;
- public Vector4 emissiveFactor;
- public Vector4 diffuseFactor;
- public Vector4 specularFactor;
- public float workflow;
- public AttachmentType TexCoord0;
- public AttachmentType TexCoord1;
- public float metallicFactor;
- public float roughnessFactor;
- public float alphaMask;
- public float alphaMaskCutoff;
- int pad0;//see std420
- }
-
- Image[] textures;
- public PbrMaterial[] materials;
- DescriptorSet[] descriptorSets;
- DescriptorPool descriptorPool;
+ protected DescriptorPool descriptorPool;
public GPUBuffer vbo;
public GPUBuffer ibo;
- public HostBuffer<PbrMaterial> materialUBO;
+ public HostBuffer materialUBO;
public PbrModel (Queue transferQ, string path) {
dev = transferQ.Dev;
@@ -101,148 +78,34 @@ namespace CVKL {
}
}
}
- public PbrModel (Queue transferQ, string path, DescriptorSetLayout layout, params AttachmentType[] attachments) {
- dev = transferQ.Dev;
- using (CommandPool cmdPool = new CommandPool (dev, transferQ.index)) {
- using (glTFLoader ctx = new glTFLoader (path, transferQ, cmdPool)) {
- ulong vertexCount, indexCount;
-
- ctx.GetVertexCount (out vertexCount, out indexCount, out IndexBufferType);
- ulong vertSize = vertexCount * (ulong)Marshal.SizeOf<Vertex> ();
- ulong idxSize = indexCount * (IndexBufferType == VkIndexType.Uint16 ? 2ul : 4ul);
- ulong size = vertSize + idxSize;
-
- vbo = new GPUBuffer (dev, VkBufferUsageFlags.VertexBuffer | VkBufferUsageFlags.TransferDst, vertSize);
- ibo = new GPUBuffer (dev, VkBufferUsageFlags.IndexBuffer | VkBufferUsageFlags.TransferDst, idxSize);
-
- vbo.SetName ("vbo gltf");
- ibo.SetName ("ibo gltf");
-
- Meshes = new List<Mesh> (ctx.LoadMeshes<Vertex> (IndexBufferType, vbo, 0, ibo, 0));
- textures = ctx.LoadImages ();
-
- loadMaterials (ctx, layout, attachments);
-
- materialUBO = new HostBuffer<PbrMaterial> (dev, VkBufferUsageFlags.UniformBuffer, materials);
-
- Scenes = new List<Scene> (ctx.LoadScenes (out defaultSceneIndex));
- }
- }
- }
-
- void loadMaterials (glTFLoader ctx, DescriptorSetLayout layout, params AttachmentType[] attachments) {
- Model.Material[] mats = ctx.LoadMaterial ();
- materials = new PbrMaterial[mats.Length];
- descriptorSets = new DescriptorSet[mats.Length];
-
- if (attachments.Length == 0)
- throw new InvalidOperationException ("At least one attachment is required for Model.WriteMaterialDescriptor");
-
- descriptorPool = new DescriptorPool (dev, (uint)materials.Length,
- new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, (uint)(attachments.Length * materials.Length))
- );
- descriptorPool.SetName ("descPool gltfTextures");
-
- for (int i = 0; i < mats.Length; i++) {
- materials[i] = new PbrMaterial {
- workflow = (float)mats[i].workflow,
- baseColorFactor = mats[i].baseColorFactor,
- emissiveFactor = mats[i].emissiveFactor,
- metallicFactor = mats[i].metallicFactor,
- roughnessFactor = mats[i].roughnessFactor,
- TexCoord0 = mats[i].availableAttachments,
- TexCoord1 = mats[i].availableAttachments1,
- alphaMask = 0f,
- alphaMaskCutoff = 0.0f,
- diffuseFactor = new Vector4 (0),
- specularFactor = new Vector4 (0)
- };
-
- //materials[i].metallicFactor = 0.1f;
- //materials[i].roughnessFactor = 0.9f;
- descriptorSets[i] = descriptorPool.Allocate (layout);
- descriptorSets[i].Handle.SetDebugMarkerName (dev, "descSet " + mats[i].Name);
-
- VkDescriptorSetLayoutBinding dslb =
- new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler);
-
- using (DescriptorSetWrites2 uboUpdate = new DescriptorSetWrites2 (dev)) {
- for (uint a = 0; a < attachments.Length; a++) {
- dslb.binding = a;
- switch (attachments[a]) {
- case AttachmentType.None:
- break;
- case AttachmentType.Color:
- if (mats[i].availableAttachments.HasFlag (AttachmentType.Color))
- uboUpdate.AddWriteInfo (descriptorSets[i], dslb, textures[(int)mats[i].baseColorTexture].Descriptor);
- break;
- case AttachmentType.Normal:
- if (mats[i].availableAttachments.HasFlag (AttachmentType.Normal))
- uboUpdate.AddWriteInfo (descriptorSets[i], dslb, textures[(int)mats[i].normalTexture].Descriptor);
- break;
- case AttachmentType.AmbientOcclusion:
- if (mats[i].availableAttachments.HasFlag (AttachmentType.AmbientOcclusion))
- uboUpdate.AddWriteInfo (descriptorSets[i], dslb, textures[(int)mats[i].occlusionTexture].Descriptor);
- break;
- case AttachmentType.PhysicalProps:
- if (mats[i].availableAttachments.HasFlag (AttachmentType.PhysicalProps))
- uboUpdate.AddWriteInfo (descriptorSets[i], dslb, textures[(int)mats[i].metallicRoughnessTexture].Descriptor);
- break;
- case AttachmentType.Metal:
- break;
- case AttachmentType.Roughness:
- break;
- case AttachmentType.Emissive:
- if (mats[i].availableAttachments.HasFlag (AttachmentType.Emissive))
- uboUpdate.AddWriteInfo (descriptorSets[i], dslb, textures[(int)mats[i].emissiveTexture].Descriptor);
- break;
- }
- }
- uboUpdate.Update ();
- }
- }
- }
+ protected PbrModel() { }
/// <summary> bind vertex and index buffers </summary>
- public void Bind (CommandBuffer cmd) {
+ public virtual void Bind (CommandBuffer cmd) {
cmd.BindVertexBuffer (vbo);
cmd.BindIndexBuffer (ibo, IndexBufferType);
}
//TODO:destset for binding must be variable
//TODO: ADD REFAULT MAT IF NO MAT DEFINED
- public void RenderNode (CommandBuffer cmd, PipelineLayout pipelineLayout, Node node, Matrix4x4 currentTransform, bool shadowPass = false) {
- Matrix4x4 localMat = node.localMatrix * currentTransform;
- VkShaderStageFlags matStage = shadowPass ? VkShaderStageFlags.Geometry : VkShaderStageFlags.Vertex;
- cmd.PushConstant (pipelineLayout, matStage, localMat);
-
- if (node.Mesh != null) {
- foreach (Primitive p in node.Mesh.Primitives) {
- if (!shadowPass) {
- cmd.PushConstant (pipelineLayout, VkShaderStageFlags.Fragment, (int)p.material, (uint)Marshal.SizeOf<Matrix4x4> ());
- if (descriptorSets[p.material] != null)
- cmd.BindDescriptorSet (pipelineLayout, descriptorSets[p.material], 1);
- }
- cmd.DrawIndexed (p.indexCount, 1, p.indexBase, p.vertexBase, 0);
- }
- }
- if (node.Children == null)
- return;
- foreach (Node child in node.Children)
- RenderNode (cmd, pipelineLayout, child, localMat, shadowPass);
- }
+ public abstract void RenderNode (CommandBuffer cmd, PipelineLayout pipelineLayout, Node node, Matrix4x4 currentTransform, bool shadowPass = false);
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);
- }
+ foreach (Node node in sc.Root.Children)
+ RenderNode (cmd, pipelineLayout, node, sc.Root.localMatrix, shadowPass);
}
}
+ public void Draw(CommandBuffer cmd, PipelineLayout pipelineLayout, Scene scene, bool shadowPass = false)
+ {
+ if (scene.Root == null)
+ return;
+ RenderNode(cmd, pipelineLayout, scene.Root, Matrix4x4.Identity, shadowPass);
+ }
#region IDisposable Support
- private bool isDisposed = false; // Pour détecter les appels redondants
+ protected bool isDisposed;
protected virtual void Dispose (bool disposing) {
if (!isDisposed) {
@@ -251,9 +114,6 @@ namespace CVKL {
vbo?.Dispose ();
materialUBO?.Dispose ();
descriptorPool?.Dispose ();
- foreach (Image txt in textures) {
- txt.Dispose ();
- }
} else
Debug.WriteLine ("model was not disposed");
isDisposed = true;
diff --git a/vke/src/PbrModelSeparateTextures.cs b/vke/src/PbrModelSeparateTextures.cs
new file mode 100644
index 0000000..387f20a
--- /dev/null
+++ b/vke/src/PbrModelSeparateTextures.cs
@@ -0,0 +1,198 @@
+//
+// PbrModel.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// Copyright (c) 2019 jp
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Diagnostics;
+using System.Numerics;
+using System.Runtime.InteropServices;
+
+using VK;
+using System.Collections.Generic;
+
+namespace CVKL {
+ using static VK.Utils;
+
+ /// <summary>
+ /// Indexed pbr model whith one descriptorSet per material with separate textures attachments
+ /// </summary>
+ public class PbrModelSeparatedTextures : PbrModel {
+ /// <summary>
+ /// Pbr data structure suitable for push constant or ubo, containing
+ /// availablility of attached textures and the coef of pbr inputs
+ /// </summary>
+ public struct Material {
+ public Vector4 baseColorFactor;
+ public Vector4 emissiveFactor;
+ public Vector4 diffuseFactor;
+ public Vector4 specularFactor;
+ public float workflow;
+ public AttachmentType TexCoord0;
+ public AttachmentType TexCoord1;
+ public float metallicFactor;
+ public float roughnessFactor;
+ public float alphaMask;
+ public float alphaMaskCutoff;
+ int pad0;//see std420
+ }
+
+ Image[] textures;
+ public Material[] materials;
+ DescriptorSet[] descriptorSets;
+
+
+ public PbrModelSeparatedTextures (Queue transferQ, string path, DescriptorSetLayout layout, params AttachmentType[] attachments) {
+ dev = transferQ.Dev;
+ using (CommandPool cmdPool = new CommandPool (dev, transferQ.index)) {
+ using (glTFLoader ctx = new glTFLoader (path, transferQ, cmdPool)) {
+ ulong vertexCount, indexCount;
+
+ ctx.GetVertexCount (out vertexCount, out indexCount, out IndexBufferType);
+ ulong vertSize = vertexCount * (ulong)Marshal.SizeOf<Vertex> ();
+ ulong idxSize = indexCount * (IndexBufferType == VkIndexType.Uint16 ? 2ul : 4ul);
+ ulong size = vertSize + idxSize;
+
+ vbo = new GPUBuffer (dev, VkBufferUsageFlags.VertexBuffer | VkBufferUsageFlags.TransferDst, vertSize);
+ ibo = new GPUBuffer (dev, VkBufferUsageFlags.IndexBuffer | VkBufferUsageFlags.TransferDst, idxSize);
+
+ vbo.SetName ("vbo gltf");
+ ibo.SetName ("ibo gltf");
+
+ Meshes = new List<Mesh> (ctx.LoadMeshes<Vertex> (IndexBufferType, vbo, 0, ibo, 0));
+
+ textures = ctx.LoadImages ();
+
+ loadMaterials (ctx, layout, attachments);
+
+ materialUBO = new HostBuffer<Material> (dev, VkBufferUsageFlags.UniformBuffer, materials);
+
+ Scenes = new List<Scene> (ctx.LoadScenes (out defaultSceneIndex));
+ }
+ }
+ }
+
+ void loadMaterials (glTFLoader ctx, DescriptorSetLayout layout, params AttachmentType[] attachments) {
+ Model.Material[] mats = ctx.LoadMaterial ();
+ materials = new Material[mats.Length];
+ descriptorSets = new DescriptorSet[mats.Length];
+
+ if (attachments.Length == 0)
+ throw new InvalidOperationException ("At least one attachment is required for Model.WriteMaterialDescriptor");
+
+ descriptorPool = new DescriptorPool (dev, (uint)materials.Length,
+ new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, (uint)(attachments.Length * materials.Length))
+ );
+ descriptorPool.SetName ("descPool gltfTextures");
+
+ for (int i = 0; i < mats.Length; i++) {
+ materials[i] = new Material {
+ workflow = (float)mats[i].workflow,
+ baseColorFactor = mats[i].baseColorFactor,
+ emissiveFactor = mats[i].emissiveFactor,
+ metallicFactor = mats[i].metallicFactor,
+ roughnessFactor = mats[i].roughnessFactor,
+ TexCoord0 = mats[i].availableAttachments,
+ TexCoord1 = mats[i].availableAttachments1,
+ alphaMask = 0f,
+ alphaMaskCutoff = 0.0f,
+ diffuseFactor = new Vector4 (0),
+ specularFactor = new Vector4 (0)
+ };
+
+ descriptorSets[i] = descriptorPool.Allocate (layout);
+ descriptorSets[i].Handle.SetDebugMarkerName (dev, "descSet " + mats[i].Name);
+
+ VkDescriptorSetLayoutBinding dslb =
+ new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler);
+
+ using (DescriptorSetWrites2 uboUpdate = new DescriptorSetWrites2 (dev)) {
+ for (uint a = 0; a < attachments.Length; a++) {
+ dslb.binding = a;
+ switch (attachments[a]) {
+ case AttachmentType.None:
+ break;
+ case AttachmentType.Color:
+ if (mats[i].availableAttachments.HasFlag (AttachmentType.Color))
+ uboUpdate.AddWriteInfo (descriptorSets[i], dslb, textures[(int)mats[i].baseColorTexture].Descriptor);
+ break;
+ case AttachmentType.Normal:
+ if (mats[i].availableAttachments.HasFlag (AttachmentType.Normal))
+ uboUpdate.AddWriteInfo (descriptorSets[i], dslb, textures[(int)mats[i].normalTexture].Descriptor);
+ break;
+ case AttachmentType.AmbientOcclusion:
+ if (mats[i].availableAttachments.HasFlag (AttachmentType.AmbientOcclusion))
+ uboUpdate.AddWriteInfo (descriptorSets[i], dslb, textures[(int)mats[i].occlusionTexture].Descriptor);
+ break;
+ case AttachmentType.PhysicalProps:
+ if (mats[i].availableAttachments.HasFlag (AttachmentType.PhysicalProps))
+ uboUpdate.AddWriteInfo (descriptorSets[i], dslb, textures[(int)mats[i].metallicRoughnessTexture].Descriptor);
+ break;
+ case AttachmentType.Metal:
+ break;
+ case AttachmentType.Roughness:
+ break;
+ case AttachmentType.Emissive:
+ if (mats[i].availableAttachments.HasFlag (AttachmentType.Emissive))
+ uboUpdate.AddWriteInfo (descriptorSets[i], dslb, textures[(int)mats[i].emissiveTexture].Descriptor);
+ break;
+ }
+ }
+ uboUpdate.Update ();
+ }
+ }
+ }
+
+ public override void RenderNode (CommandBuffer cmd, PipelineLayout pipelineLayout, Node node, Matrix4x4 currentTransform, bool shadowPass = false) {
+ Matrix4x4 localMat = node.localMatrix * currentTransform;
+ VkShaderStageFlags matStage = shadowPass ? VkShaderStageFlags.Geometry : VkShaderStageFlags.Vertex;
+ cmd.PushConstant (pipelineLayout, matStage, localMat);
+
+ if (node.Mesh != null) {
+ foreach (Primitive p in node.Mesh.Primitives) {
+ if (!shadowPass) {
+ cmd.PushConstant (pipelineLayout, VkShaderStageFlags.Fragment, (int)p.material, (uint)Marshal.SizeOf<Matrix4x4> ());
+ if (descriptorSets[p.material] != null)
+ cmd.BindDescriptorSet (pipelineLayout, descriptorSets[p.material], 2);
+ }
+ cmd.DrawIndexed (p.indexCount, 1, p.indexBase, p.vertexBase, 0);
+ }
+ }
+ if (node.Children == null)
+ return;
+ foreach (Node child in node.Children)
+ RenderNode (cmd, pipelineLayout, child, localMat, shadowPass);
+ }
+
+ protected override void Dispose (bool disposing) {
+ if (!isDisposed) {
+ if (disposing) {
+ foreach (Image txt in textures)
+ txt.Dispose ();
+ } else
+ Debug.WriteLine ("model was not disposed");
+ }
+ base.Dispose (disposing);
+ }
+ }
+}
diff --git a/vke/src/PbrModelTexArray.cs b/vke/src/PbrModelTexArray.cs
new file mode 100644
index 0000000..47b6b74
--- /dev/null
+++ b/vke/src/PbrModelTexArray.cs
@@ -0,0 +1,168 @@
+//
+// PbrModel.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// Copyright (c) 2019 jp
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Diagnostics;
+using System.Numerics;
+using System.Runtime.InteropServices;
+
+using VK;
+using System.Collections.Generic;
+
+namespace CVKL {
+ using static VK.Utils;
+
+ /// <summary>
+ /// Indexed pbr model whith one descriptorSet per material with separate textures attachments
+ /// </summary>
+ public class PbrModelTexArray : PbrModel {
+ public static uint TEXTURE_DIM = 512;
+ /// <summary>
+ /// Pbr data structure suitable for push constant or ubo, containing
+ /// availablility of attached textures and the coef of pbr inputs
+ /// </summary>
+ public struct Material {
+ public Vector4 baseColorFactor;
+ public Vector4 emissiveFactor;
+ public Vector4 diffuseFactor;
+ public Vector4 specularFactor;
+
+ public float workflow;
+ public AttachmentType TexCoord0;
+ public AttachmentType TexCoord1;
+ public int baseColorTextureSet;
+
+ public int physicalDescriptorTextureSet;
+ public int normalTextureSet;
+ public int occlusionTextureSet;
+ public int emissiveTextureSet;
+
+ public float metallicFactor;
+ public float roughnessFactor;
+ public float alphaMask;
+ public float alphaMaskCutoff;
+ }
+
+ public Image texArray;
+ public Material[] materials;
+
+ public PbrModelTexArray (Queue transferQ, string path) {
+ dev = transferQ.Dev;
+ using (CommandPool cmdPool = new CommandPool (dev, transferQ.index)) {
+ using (glTFLoader ctx = new glTFLoader (path, transferQ, cmdPool)) {
+ ulong vertexCount, indexCount;
+
+ ctx.GetVertexCount (out vertexCount, out indexCount, out IndexBufferType);
+ ulong vertSize = vertexCount * (ulong)Marshal.SizeOf<Vertex> ();
+ ulong idxSize = indexCount * (IndexBufferType == VkIndexType.Uint16 ? 2ul : 4ul);
+ ulong size = vertSize + idxSize;
+
+ vbo = new GPUBuffer (dev, VkBufferUsageFlags.VertexBuffer | VkBufferUsageFlags.TransferDst, vertSize);
+ ibo = new GPUBuffer (dev, VkBufferUsageFlags.IndexBuffer | VkBufferUsageFlags.TransferDst, idxSize);
+
+ vbo.SetName ("vbo gltf");
+ ibo.SetName ("ibo gltf");
+
+ Meshes = new List<Mesh> (ctx.LoadMeshes<Vertex> (IndexBufferType, vbo, 0, ibo, 0));
+
+ texArray = new Image (dev, Image.DefaultTextureFormat, VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst | VkImageUsageFlags.TransferSrc,
+ VkMemoryPropertyFlags.DeviceLocal, TEXTURE_DIM, TEXTURE_DIM, VkImageType.Image2D,
+ VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal, Image.ComputeMipLevels(TEXTURE_DIM), ctx.ImageCount);
+
+ ctx.BuildTexArray (ref texArray, 0);
+
+ 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);
+
+ Scenes = new List<Scene> (ctx.LoadScenes (out defaultSceneIndex));
+ }
+ }
+ }
+
+ void loadMaterials (glTFLoader ctx) {
+ Model.Material[] mats = ctx.LoadMaterial ();
+ materials = new Material[mats.Length];
+
+ for (int i = 0; i < mats.Length; i++) {
+ materials[i] = new Material {
+ workflow = (float)mats[i].workflow,
+ baseColorFactor = mats[i].baseColorFactor,
+ emissiveFactor = mats[i].emissiveFactor,
+ metallicFactor = mats[i].metallicFactor,
+ roughnessFactor = mats[i].roughnessFactor,
+
+ baseColorTextureSet = mats[i].baseColorTexture,
+ physicalDescriptorTextureSet = mats[i].metallicRoughnessTexture,
+ normalTextureSet = mats[i].normalTexture,
+ occlusionTextureSet = mats[i].occlusionTexture,
+ emissiveTextureSet = mats[i].emissiveTexture,
+
+ TexCoord0 = mats[i].availableAttachments,
+ TexCoord1 = mats[i].availableAttachments1,
+
+ alphaMask = 0f,
+ alphaMaskCutoff = 0.0f,
+ diffuseFactor = new Vector4 (0),
+ specularFactor = new Vector4 (0)
+ };
+ }
+ }
+
+ public override void RenderNode (CommandBuffer cmd, PipelineLayout pipelineLayout, Node node, Matrix4x4 currentTransform, bool shadowPass = false) {
+ Matrix4x4 localMat = node.localMatrix * currentTransform;
+ VkShaderStageFlags matStage = shadowPass ? VkShaderStageFlags.Geometry : VkShaderStageFlags.Vertex;
+ cmd.PushConstant (pipelineLayout, matStage, localMat);
+
+ if (node.Mesh != null) {
+ foreach (Primitive p in node.Mesh.Primitives) {
+ if (!shadowPass) {
+ cmd.PushConstant (pipelineLayout, VkShaderStageFlags.Fragment, (int)p.material, (uint)Marshal.SizeOf<Matrix4x4> ());
+ }
+ cmd.DrawIndexed (p.indexCount, 1, p.indexBase, p.vertexBase, 0);
+ }
+ }
+ if (node.Children == null)
+ return;
+ foreach (Node child in node.Children)
+ RenderNode (cmd, pipelineLayout, child, localMat, shadowPass);
+ }
+
+ protected override void Dispose (bool disposing) {
+ if (!isDisposed) {
+ if (disposing) {
+ texArray?.Dispose ();
+ } else
+ Debug.WriteLine ("model was not disposed");
+ }
+ base.Dispose (disposing);
+ }
+ }
+}
diff --git a/vke/src/SubPass.cs b/vke/src/SubPass.cs
index 016641b..e0998e8 100644
--- a/vke/src/SubPass.cs
+++ b/vke/src/SubPass.cs
@@ -1,5 +1,5 @@
//
-// AttachmentReference.cs
+// SubPass.cs
//
// Author:
// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
@@ -23,91 +23,10 @@
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-using System;
using System.Collections.Generic;
-using System.Runtime.InteropServices;
using VK;
namespace CVKL {
- //public class NativeList2<T> : IDisposable where T : struct {
- // const int sizeStep = 4;
- // int eltSize;
- // int capacity;
- // int count;
- // IntPtr handle;
-
- // public IntPtr Pointer => handle;
-
- // public NativeList2 (T[] array) {
- // eltSize = Marshal.SizeOf<T> ();
- // capacity = count = array.Length;
- // GCHandle hnd = GCHandle.Alloc (array, GCHandleType.Pinned);
- // handle = GCHandle.ToIntPtr (hnd);
- // }
-
- // public void Add (T elem) {
- // if (count == capacity) {
- // }
- // }
-
- // void resize (int newSize) {
-
- // }
-
- // #region IDisposable Support
- // private bool disposedValue;
- // protected virtual void Dispose (bool disposing) {
- // if (!disposedValue) {
- // if (disposing) {
- // }
- // handle.Free ();
- // disposedValue = true;
- // }
- // }
- // public void Dispose () {
- // Dispose (true);
- // GC.SuppressFinalize(this);
- // }
- // ~NativeList2 () { Dispose (false); }
- // #endregion
- //}
-
-
- public class MarshaledObject<T> : IDisposable where T : struct {
-
- GCHandle handle;
-
- public IntPtr Pointer {
- get {
- if (!handle.IsAllocated)
- throw new InvalidOperationException ("Unalocated MarshaledObject");
- return handle.AddrOfPinnedObject ();
- }
- }
-
- public MarshaledObject (T mobj) {
- handle = GCHandle.Alloc (mobj, GCHandleType.Pinned);
- }
-
- void freeHandle () {
- if (!disposed)
- handle.Free ();
- }
-
- #region IDisposable Support
- private bool disposed;
-
- ~MarshaledObject() {
- freeHandle ();
- }
-
- public void Dispose () {
- freeHandle ();
- GC.SuppressFinalize(this);
- }
- #endregion
- }
-
public class SubPass {
List<VkAttachmentReference> colorRefs = new List<VkAttachmentReference>();
List<VkAttachmentReference> inputRefs = new List<VkAttachmentReference>();
@@ -122,7 +41,6 @@ namespace CVKL {
AddColorReference (i, layouts[i]);
}
-
public void AddColorReference (uint attachment, VkImageLayout layout = VkImageLayout.DepthStencilAttachmentOptimal) {
AddColorReference (new VkAttachmentReference { attachment = attachment, layout = layout });
}
diff --git a/vke/src/SwapChain.cs b/vke/src/SwapChain.cs
index ad25abd..5473c93 100644
--- a/vke/src/SwapChain.cs
+++ b/vke/src/SwapChain.cs
@@ -28,32 +28,33 @@ using VK;
using static VK.Vk;
namespace CVKL {
- public class SwapChain {
- Device dev;
- PresentQueue presentQueue;
+ public class SwapChain : Activable {
internal VkSwapchainKHR handle;
- public VkSemaphore presentComplete;
+ internal uint currentImageIndex;
+ VkSwapchainCreateInfoKHR createInfos;
+ PresentQueue presentQueue;
+ public VkSemaphore presentComplete;
public Image[] images;
- internal uint currentImageIndex;
+ protected override VkDebugMarkerObjectNameInfoEXT DebugMarkerInfo
+ => new VkDebugMarkerObjectNameInfoEXT (VkDebugReportObjectTypeEXT.SwapchainKhrEXT, handle.Handle);
- VkSwapchainCreateInfoKHR createInfos;
- public uint ImageCount => (uint)images?.Length;
+ public uint ImageCount => (uint)images?.Length;
public uint Width => createInfos.imageExtent.width;
public uint Height => createInfos.imageExtent.height;
public VkFormat ColorFormat => createInfos.imageFormat;
public VkImageUsageFlags ImageUsage => createInfos.imageUsage;
- public SwapChain (PresentQueue _presentableQueue, uint width = 800, uint height = 600, VkFormat format = VkFormat.B8g8r8a8Unorm, VkPresentModeKHR presentMode = VkPresentModeKHR.FifoKHR) {
- presentQueue = _presentableQueue;
- dev = presentQueue.dev;
+ public SwapChain (PresentQueue _presentableQueue, uint width = 800, uint height = 600, VkFormat format = VkFormat.B8g8r8a8Unorm, VkPresentModeKHR presentMode = VkPresentModeKHR.FifoKHR)
+ : base (_presentableQueue.dev){
+ presentQueue = _presentableQueue;
createInfos = VkSwapchainCreateInfoKHR.New();
- VkSurfaceFormatKHR[] formats = dev.phy.GetSurfaceFormats (presentQueue.Surface);
+ VkSurfaceFormatKHR[] formats = Dev.phy.GetSurfaceFormats (presentQueue.Surface);
for (int i = 0; i < formats.Length; i++) {
if (formats[i].format == format) {
createInfos.imageFormat = format;
@@ -64,7 +65,7 @@ namespace CVKL {
if (createInfos.imageFormat == VkFormat.Undefined)
throw new Exception ("Invalid format for swapchain: " + format);
- VkPresentModeKHR[] presentModes = dev.phy.GetSurfacePresentModes (presentQueue.Surface);
+ VkPresentModeKHR[] presentModes = Dev.phy.GetSurfacePresentModes (presentQueue.Surface);
for (int i = 0; i < presentModes.Length; i++) {
if (presentModes[i] == presentMode) {
createInfos.presentMode = presentMode;
@@ -81,18 +82,23 @@ namespace CVKL {
createInfos.imageSharingMode = VkSharingMode.Exclusive;
createInfos.compositeAlpha = VkCompositeAlphaFlagsKHR.OpaqueKHR;
createInfos.presentMode = presentMode;
- createInfos.clipped = 1;
-
- presentComplete = dev.CreateSemaphore ();
- presentComplete.SetDebugMarkerName (dev, "Semaphore PresentComplete");
-
- Create ();
+ createInfos.clipped = 1;
}
+ public override void Activate () {
+ if (state != ActivableState.Activated) {
+ presentComplete = Dev.CreateSemaphore ();
+ presentComplete.SetDebugMarkerName (Dev, "Semaphore PresentComplete");
+ }
+ base.Activate ();
+ }
- public void Create () {
- dev.WaitIdle ();
+ public void Create () {
+ if (state != ActivableState.Activated)
+ Activate ();
- VkSurfaceCapabilitiesKHR capabilities = dev.phy.GetSurfaceCapabilities (presentQueue.Surface);
+ Dev.WaitIdle ();
+
+ VkSurfaceCapabilitiesKHR capabilities = Dev.phy.GetSurfaceCapabilities (presentQueue.Surface);
createInfos.minImageCount = capabilities.minImageCount;
createInfos.preTransform = capabilities.currentTransform;
@@ -111,23 +117,23 @@ namespace CVKL {
} else
createInfos.imageExtent = capabilities.currentExtent;
- VkSwapchainKHR newSwapChain = dev.CreateSwapChain (createInfos);
+ VkSwapchainKHR newSwapChain = Dev.CreateSwapChain (createInfos);
if (handle.Handle != 0)
_destroy ();
handle = newSwapChain;
- VkImage[] tmp = dev.GetSwapChainImages (handle);
+ VkImage[] tmp = Dev.GetSwapChainImages (handle);
images = new Image[tmp.Length];
for (int i = 0; i < tmp.Length; i++) {
- images[i] = new Image (dev, tmp[i], ColorFormat, ImageUsage, Width, Height);
+ images[i] = new Image (Dev, tmp[i], ColorFormat, ImageUsage, Width, Height);
images[i].CreateView ();
images[i].SetName ("SwapChain Img" + i);
- images[i].Descriptor.imageView.SetDebugMarkerName (dev, "SwapChain Img" + i + " view");
+ images[i].Descriptor.imageView.SetDebugMarkerName (Dev, "SwapChain Img" + i + " view");
}
}
public int GetNextImage () {
- VkResult res = vkAcquireNextImageKHR (dev.VkDev, handle, UInt64.MaxValue, presentComplete, VkFence.Null, out currentImageIndex);
+ VkResult res = vkAcquireNextImageKHR (Dev.VkDev, handle, UInt64.MaxValue, presentComplete, VkFence.Null, out currentImageIndex);
if (res == VkResult.ErrorOutOfDateKHR || res == VkResult.SuboptimalKHR) {
Create ();
return -1;
@@ -140,13 +146,28 @@ namespace CVKL {
for (int i = 0; i < ImageCount; i++)
images[i].Dispose ();
- dev.DestroySwapChain (handle);
+ Dev.DestroySwapChain (handle);
}
- public void Destroy () {
- _destroy ();
+ public override string ToString () {
+ return string.Format ($"{base.ToString ()}[0x{handle.Handle.ToString ("x")}]");
+ }
- dev.DestroySemaphore (presentComplete);
- }
- }
+ #region IDisposable Support
+ protected override void Dispose (bool disposing) {
+ if (state == ActivableState.Activated) {
+ if (disposing) {
+ } else
+ System.Diagnostics.Debug.WriteLine ("VKE Swapchain disposed by finalizer");
+
+ Dev.DestroySemaphore (presentComplete);
+ _destroy ();
+
+ } else if (disposing)
+ System.Diagnostics.Debug.WriteLine ("Calling dispose on unactive Swapchain");
+
+ base.Dispose (disposing);
+ }
+ #endregion
+ }
}
diff --git a/vke/src/VkWindow.cs b/vke/src/VkWindow.cs
index 6928e73..15d4697 100644
--- a/vke/src/VkWindow.cs
+++ b/vke/src/VkWindow.cs
@@ -35,24 +35,20 @@ namespace CVKL {
/// Base class to build vulkan application.
/// Provide default swapchain with its command pool and buffers per image and the main present queue
/// </summary>
- public abstract class VkWindow : IDisposable {
+ public abstract class VkWindow : IDisposable {
static VkWindow currentWindow;
IntPtr hWin;
-#if DEBUG
- DebugReport dbgRepport;
-#endif
-
- protected VkSurfaceKHR hSurf;
- protected Instance instance;
- protected PhysicalDevice phy;
- protected Device dev;
- protected PresentQueue presentQueue;
- protected SwapChain swapChain;
- protected CommandPool cmdPool;
- protected CommandBuffer[] cmds;
- protected VkSemaphore[] drawComplete;
+ protected VkSurfaceKHR hSurf;
+ protected Instance instance;
+ protected PhysicalDevice phy;
+ protected Device dev;
+ protected PresentQueue presentQueue;
+ protected SwapChain swapChain;
+ protected CommandPool cmdPool;
+ protected CommandBuffer[] cmds;
+ protected VkSemaphore[] drawComplete;
protected uint fps;
protected bool updateViewRequested = true, rebuildBuffers = false;
@@ -64,7 +60,7 @@ namespace CVKL {
/// </summary>
protected Camera camera = new Camera (Utils.DegreesToRadians (45f), 1f);
- uint width, height;
+ uint width, height;
bool[] buttons = new bool[10];
public Modifier KeyModifiers = 0;
@@ -76,132 +72,122 @@ namespace CVKL {
/// </summary>
public virtual string[] EnabledExtensions {
get {
- return new string[] {Ext.D.VK_KHR_swapchain};
- }
+ return new string[] { Ext.D.VK_KHR_swapchain };
+ }
}
/// <summary>
/// Frequency in millisecond of the call to the Update method
/// </summary>
public long UpdateFrequency = 200;
- public uint Width => width;
- public uint Height => height;
+ public uint Width => width;
+ public uint Height => height;
- public VkWindow (bool debugMarkers = false, string name = "VkWindow", uint _width = 1024, uint _height=768, bool vSync = false)
- {
- currentWindow = this;
+ public VkWindow (bool debugMarkers = false, string name = "VkWindow", uint _width = 1024, uint _height = 768, bool vSync = false) {
+ currentWindow = this;
- width = _width;
- height = _height;
+ width = _width;
+ height = _height;
- Glfw3.Init ();
+ Glfw3.Init ();
- Glfw3.WindowHint (WindowAttribute.ClientApi, 0);
- Glfw3.WindowHint (WindowAttribute.Resizable, 1);
+ Glfw3.WindowHint (WindowAttribute.ClientApi, 0);
+ Glfw3.WindowHint (WindowAttribute.Resizable, 1);
hWin = Glfw3.CreateWindow ((int)width, (int)height, name, MonitorHandle.Zero, IntPtr.Zero);
- Glfw3.SetKeyCallback (hWin, HandleKeyDelegate);
- Glfw3.SetMouseButtonPosCallback (hWin, HandleMouseButtonDelegate);
- Glfw3.SetCursorPosCallback (hWin, HandleCursorPosDelegate);
- Glfw3.SetWindowSizeCallback (hWin, HandleWindowSizeDelegate);
+ Glfw3.SetKeyCallback (hWin, HandleKeyDelegate);
+ Glfw3.SetMouseButtonPosCallback (hWin, HandleMouseButtonDelegate);
+ Glfw3.SetCursorPosCallback (hWin, HandleCursorPosDelegate);
+ Glfw3.SetWindowSizeCallback (hWin, HandleWindowSizeDelegate);
Glfw3.SetScrollCallback (hWin, HandleScrollDelegate);
Glfw3.SetCharCallback (hWin, HandleCharDelegate);
- initVulkan (vSync, debugMarkers);
+ initVulkan (vSync, debugMarkers);
}
void initVulkan (bool vSync, bool debugMarkers) {
- instance = new Instance ();
-
-#if DEBUG
- dbgRepport = new DebugReport (instance,
- VkDebugReportFlagsEXT.ErrorEXT
- | VkDebugReportFlagsEXT.DebugEXT
- | VkDebugReportFlagsEXT.WarningEXT
- | VkDebugReportFlagsEXT.PerformanceWarningEXT
- //| VkDebugReportFlagsEXT.InformationEXT
- );
-#endif
+ instance = new Instance ();
hSurf = instance.CreateSurface (hWin);
- phy = instance.GetAvailablePhysicalDevice ().Where (p => p.HasSwapChainSupport).FirstOrDefault ();
+ phy = instance.GetAvailablePhysicalDevice ().Where (p => p.HasSwapChainSupport).FirstOrDefault ();
- VkPhysicalDeviceFeatures enabledFeatures = default(VkPhysicalDeviceFeatures);
- configureEnabledFeatures (phy.Features, ref enabledFeatures);
+ VkPhysicalDeviceFeatures enabledFeatures = default (VkPhysicalDeviceFeatures);
+ configureEnabledFeatures (phy.Features, ref enabledFeatures);
if (debugMarkers)
debugMarkers = phy.GetDeviceExtensionSupported (Ext.D.VK_EXT_debug_marker);
//First create the c# device class
dev = new Device (phy, debugMarkers);
- //create queue class
- createQueues ();
+ //create queue class
+ createQueues ();
- //activate the device to have effective queues created accordingly to what's available
- dev.Activate (enabledFeatures, EnabledExtensions);
+ //activate the device to have effective queues created accordingly to what's available
+ dev.Activate (enabledFeatures, EnabledExtensions);
- swapChain = new SwapChain (presentQueue as PresentQueue, width, height, VkFormat.B8g8r8a8Srgb,
- vSync ? VkPresentModeKHR.FifoKHR : VkPresentModeKHR.MailboxKHR );
+ swapChain = new SwapChain (presentQueue as PresentQueue, width, height, VkFormat.B8g8r8a8Srgb,
+ vSync ? VkPresentModeKHR.FifoKHR : VkPresentModeKHR.MailboxKHR);
+ swapChain.Create ();
- cmdPool = new CommandPool(dev, presentQueue.qFamIndex);
+ cmdPool = new CommandPool (dev, presentQueue.qFamIndex);
- cmds = new CommandBuffer[swapChain.ImageCount];
- drawComplete = new VkSemaphore[swapChain.ImageCount];
+ cmds = new CommandBuffer[swapChain.ImageCount];
+ drawComplete = new VkSemaphore[swapChain.ImageCount];
- for (int i = 0; i < swapChain.ImageCount; i++)
- drawComplete[i] = dev.CreateSemaphore ();
+ for (int i = 0; i < swapChain.ImageCount; i++)
+ drawComplete[i] = dev.CreateSemaphore ();
cmdPool.SetName ("main CmdPool");
for (int i = 0; i < swapChain.ImageCount; i++)
drawComplete[i].SetDebugMarkerName (dev, "Semaphore DrawComplete" + i);
- }
+ }
/// <summary>
/// override this method to modify enabled features before device creation
/// </summary>
/// <param name="enabled_features">Features.</param>
protected virtual void configureEnabledFeatures (VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures enabled_features) {
- }
+ }
/// <summary>
/// override this method to create additional queue. Dedicated queue of the requested type will be selected first, created queues may excess
/// available physical queues.
/// </summary>
- protected virtual void createQueues () {
- presentQueue = new PresentQueue (dev, VkQueueFlags.Graphics, hSurf);
- }
+ protected virtual void createQueues () {
+ presentQueue = new PresentQueue (dev, VkQueueFlags.Graphics, hSurf);
+ }
/// <summary>
/// Main render method called each frame. get next swapchain image, process resize if needed, submit and present to the presentQueue.
/// Wait QueueIdle after presenting.
/// </summary>
- protected virtual void render () {
- int idx = swapChain.GetNextImage();
- if (idx < 0) {
- OnResize ();
- return;
- }
+ protected virtual void render () {
+ int idx = swapChain.GetNextImage ();
+ if (idx < 0) {
+ OnResize ();
+ return;
+ }
- presentQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx]);
- presentQueue.Present (swapChain, drawComplete[idx]);
+ presentQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx]);
+ presentQueue.Present (swapChain, drawComplete[idx]);
- presentQueue.WaitIdle ();
- }
+ presentQueue.WaitIdle ();
+ }
- protected virtual void onScroll (double xOffset, double yOffset) {}
- protected virtual void onMouseMove (double xPos, double yPos) {
+ protected virtual void onScroll (double xOffset, double yOffset) { }
+ protected virtual void onMouseMove (double xPos, double yPos) {
double diffX = lastMouseX - xPos;
double diffY = lastMouseY - yPos;
if (MouseButton[0]) {
- camera.Rotate ((float)-diffX,(float)-diffY);
+ camera.Rotate ((float)-diffX, (float)-diffY);
} else if (MouseButton[1]) {
- camera.Move (0,0,(float)diffY);
+ camera.Move (0, 0, (float)diffY);
}
updateViewRequested = true;
- }
- protected virtual void onMouseButtonDown (Glfw.MouseButton button) { }
- protected virtual void onMouseButtonUp (Glfw.MouseButton button) { }
- protected virtual void onKeyDown (Key key, int scanCode, Modifier modifiers) {
+ }
+ protected virtual void onMouseButtonDown (Glfw.MouseButton button) { }
+ protected virtual void onMouseButtonUp (Glfw.MouseButton button) { }
+ protected virtual void onKeyDown (Key key, int scanCode, Modifier modifiers) {
switch (key) {
case Key.F4:
if (modifiers == Modifier.Alt)
@@ -241,21 +227,21 @@ namespace CVKL {
protected virtual void onChar (CodePoint cp) { }
#region events delegates
- static void HandleWindowSizeDelegate (IntPtr window, int width, int height) {}
- static void HandleCursorPosDelegate (IntPtr window, double xPosition, double yPosition) {
- currentWindow.onMouseMove (xPosition, yPosition);
+ static void HandleWindowSizeDelegate (IntPtr window, int width, int height) { }
+ static void HandleCursorPosDelegate (IntPtr window, double xPosition, double yPosition) {
+ currentWindow.onMouseMove (xPosition, yPosition);
currentWindow.lastMouseX = xPosition;
currentWindow.lastMouseY = yPosition;
- }
- static void HandleMouseButtonDelegate (IntPtr window, Glfw.MouseButton button, InputAction action, Modifier mods) {
- if (action == InputAction.Press) {
- currentWindow.buttons[(int)button] = true;
- currentWindow.onMouseButtonDown (button);
- } else {
- currentWindow.buttons[(int)button] = false;
- currentWindow.onMouseButtonUp (button);
- }
- }
+ }
+ static void HandleMouseButtonDelegate (IntPtr window, Glfw.MouseButton button, InputAction action, Modifier mods) {
+ if (action == InputAction.Press) {
+ currentWindow.buttons[(int)button] = true;
+ currentWindow.onMouseButtonDown (button);
+ } else {
+ currentWindow.buttons[(int)button] = false;
+ currentWindow.onMouseButtonUp (button);
+ }
+ }
static void HandleScrollDelegate (IntPtr window, double xOffset, double yOffset) {
currentWindow.onScroll (xOffset, yOffset);
}
@@ -263,10 +249,10 @@ namespace CVKL {
currentWindow.KeyModifiers = modifiers;
if (action == InputAction.Press || action == InputAction.Repeat) {
currentWindow.onKeyDown (key, scanCode, modifiers);
- } else {
+ } else {
currentWindow.onKeyUp (key, scanCode, modifiers);
}
- }
+ }
static void HandleCharDelegate (IntPtr window, CodePoint codepoint) {
currentWindow.onChar (codepoint);
}
@@ -276,46 +262,46 @@ namespace CVKL {
/// main window loop, exits on GLFW3 exit event
/// </summary>
public virtual void Run () {
- OnResize ();
- UpdateView ();
+ OnResize ();
+ UpdateView ();
- frameChrono = Stopwatch.StartNew ();
+ frameChrono = Stopwatch.StartNew ();
long totTime = 0;
- while (!Glfw3.WindowShouldClose (hWin)) {
- render ();
+ while (!Glfw3.WindowShouldClose (hWin)) {
+ render ();
- if(updateViewRequested)
- UpdateView ();
+ if (updateViewRequested)
+ UpdateView ();
- frameCount++;
+ frameCount++;
- if (frameChrono.ElapsedMilliseconds > UpdateFrequency) {
+ if (frameChrono.ElapsedMilliseconds > UpdateFrequency) {
Update ();
frameChrono.Stop ();
totTime += frameChrono.ElapsedMilliseconds;
- fps = (uint)((double)frameCount / (double)totTime * 1000.0);
- //Glfw3.SetWindowTitle (hWin, "FPS: " + fps.ToString ());
+ fps = (uint)((double)frameCount / (double)totTime * 1000.0);
+ Glfw3.SetWindowTitle (hWin, "FPS: " + fps.ToString ());
if (totTime > 2000) {
frameCount = 0;
totTime = 0;
}
frameChrono.Restart ();
- }
- Glfw3.PollEvents ();
- }
- }
- public virtual void UpdateView () {}
+ }
+ Glfw3.PollEvents ();
+ }
+ }
+ public virtual void UpdateView () { }
/// <summary>
/// custom update method called at UpdateFrequency
/// </summary>
- public virtual void Update () {}
+ public virtual void Update () { }
/// <summary>
/// called when swapchain has been resized, override this method to resize your framebuffers coupled to the swapchain
/// </summary>
- protected virtual void OnResize () {}
+ protected virtual void OnResize () { }
#region IDisposable Support
@@ -330,7 +316,7 @@ namespace CVKL {
cmds[i].Free ();
}
- swapChain.Destroy ();
+ swapChain.Dispose ();
vkDestroySurfaceKHR (instance.Handle, hSurf, IntPtr.Zero);
@@ -338,9 +324,6 @@ namespace CVKL {
if (disposing) {
dev.Dispose ();
-#if DEBUG
- dbgRepport.Dispose ();
-#endif
instance.Dispose ();
} else
Debug.WriteLine ("a VkWindow has not been correctly disposed");
diff --git a/vke/src/glTFLoader.cs b/vke/src/glTFLoader.cs
index cf18110..d21ff61 100644
--- a/vke/src/glTFLoader.cs
+++ b/vke/src/glTFLoader.cs
@@ -109,6 +109,9 @@ namespace CVKL {
}
}
+ 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
public Mesh[] LoadMeshes<TVertex> (VkIndexType indexType, Buffer vbo, ulong vboOffset, Buffer ibo, ulong iboOffset) {
@@ -361,7 +364,8 @@ namespace CVKL {
Node node = new Node {
localMatrix = localTransform,
- Parent = parentNode
+ Parent = parentNode,
+ Name = gltfNode.Name
};
parentNode.Children.Add (node);
@@ -380,69 +384,90 @@ namespace CVKL {
///// </summary>
///// <returns>The images.</returns>
///// <param name="textureSize">Texture size.</param>
- //public Image LoadImages (uint textureSize) {
- // Image imgs = new Image (dev, VkFormat.R8g8b8a8Unorm, VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst, VkMemoryPropertyFlags.DeviceLocal, textureSize, textureSize,
- // VkImageType.Image2D, VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal);
+ public void BuildTexArray (ref Image texArray, uint firstImg = 0) {
+ int texDim = (int)texArray.CreateInfo.extent.width;
- // CommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);
+ CommandBuffer cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);
+ texArray.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal,
+ VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.Transfer);
+ cmd.End ();
+ transferQ.Submit (cmd);
+ transferQ.WaitIdle ();
+ cmd.Free ();
- // foreach (GL.Image img in gltf.Images) {
- // Image vkimg = null;
+ VkImageBlit imageBlit = new VkImageBlit {
+ srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0),
+ dstOffsets_1 = new VkOffset3D (texDim, texDim, 1)
+ };
- // string imgName = img.Name;
+ for (int l = 0; l < gltf.Images.Length; l++) {
+ GL.Image img = gltf.Images[l];
+ Image vkimg = null;
- // if (img.BufferView != null) {//load image from gltf buffer view
- // GL.BufferView bv = gltf.BufferViews[(int)img.BufferView];
- // EnsureBufferIsLoaded (bv.Buffer);
- // vkimg = Image.Load (dev, bufferHandles[bv.Buffer].AddrOfPinnedObject () + bv.ByteOffset, (ulong)bv.ByteLength);
- // } else if (img.Uri.StartsWith ("data:", StringComparison.Ordinal)) {//load base64 encoded image
- // Debug.WriteLine ("loading embedded image {0} : {1}", img.Name, img.MimeType);
- // 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));
- // imgName += ";" + img.Uri;
- // }
+ if (img.BufferView != null) {//load image from gltf buffer view
+ GL.BufferView bv = gltf.BufferViews[(int)img.BufferView];
+ EnsureBufferIsLoaded (bv.Buffer);
+ vkimg = Image.Load (dev, bufferHandles[bv.Buffer].AddrOfPinnedObject () + bv.ByteOffset, (ulong)bv.ByteLength);
+ } else if (img.Uri.StartsWith ("data:", StringComparison.Ordinal)) {//load base64 encoded image
+ Debug.WriteLine ("loading embedded image {0} : {1}", img.Name, img.MimeType);
+ vkimg = Image.Load (dev, 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, Path.Combine (baseDirectory, img.Uri));
+ }
+ imageBlit.srcOffsets_1 = new VkOffset3D ((int)vkimg.CreateInfo.extent.width, (int)vkimg.CreateInfo.extent.height, 1);
+ imageBlit.dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, 1, 0, (uint)l + firstImg);
- // VkImageSubresourceRange mipSubRange = new VkImageSubresourceRange (VkImageAspectFlags.Color, 0, 1, 0, info.arrayLayers);
+ cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);
- // SetLayout (cmd, VkImageLayout.Undefined, VkImageLayout.TransferSrcOptimal, mipSubRange,
- // VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);
+ vkimg.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferSrcOptimal,
+ VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);
- // for (int i = 1; i < info.mipLevels; i++) {
- // VkImageBlit imageBlit = new VkImageBlit {
- // srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, info.arrayLayers, (uint)i - 1),
- // srcOffsets_1 = new VkOffset3D ((int)info.extent.width >> (i - 1), (int)info.extent.height >> (i - 1), 1),
- // dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, info.arrayLayers, (uint)i),
- // dstOffsets_1 = new VkOffset3D ((int)info.extent.width >> i, (int)info.extent.height >> i, 1)
- // };
+ Vk.vkCmdBlitImage (cmd.Handle, vkimg.handle, VkImageLayout.TransferSrcOptimal,
+ texArray.handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear);
- // mipSubRange.baseMipLevel = (uint)i;
+ cmd.End ();
+ transferQ.Submit (cmd);
+ transferQ.WaitIdle ();
+ cmd.Free ();
- // SetLayout (cmd, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, mipSubRange,
- // VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);
- // vkCmdBlitImage (cmd.Handle, handle, VkImageLayout.TransferSrcOptimal, handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear);
- // SetLayout (cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.TransferSrcOptimal, mipSubRange,
- // VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);
- // }
- // SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal,
- // VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);
+ vkimg.Dispose ();
+ }
+ uint imgCount = (uint)gltf.Images.Length;
- // vkimg.CreateView ();
- // vkimg.CreateSampler ();
- // vkimg.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal;
+ VkImageSubresourceRange mipSubRange = new VkImageSubresourceRange (VkImageAspectFlags.Color, 0, 1, firstImg, imgCount);
- // vkimg.SetName (imgName);
- // vkimg.Descriptor.imageView.SetDebugMarkerName (dev, "imgView " + imgName);
- // vkimg.Descriptor.sampler.SetDebugMarkerName (dev, "sampler " + imgName);
+ cmd = cmdPool.AllocateAndStart (VkCommandBufferUsageFlags.OneTimeSubmit);
+ texArray.SetLayout (cmd, VkImageLayout.Undefined, VkImageLayout.TransferSrcOptimal, mipSubRange,
+ VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);
+
+ for (int i = 1; i < texArray.CreateInfo.mipLevels; i++) {
+ imageBlit = new VkImageBlit {
+ srcSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, imgCount, (uint)i - 1, firstImg),
+ srcOffsets_1 = new VkOffset3D ((int)texDim >> (i - 1), (int)texDim >> (i - 1), 1),
+ dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, imgCount, (uint)i, firstImg),
+ dstOffsets_1 = new VkOffset3D ((int)texDim >> i, (int)texDim >> i, 1)
+ };
+ mipSubRange.baseMipLevel = (uint)i;
+
+ texArray.SetLayout (cmd, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, mipSubRange,
+ VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);
+ Vk.vkCmdBlitImage (cmd.Handle, texArray.handle, VkImageLayout.TransferSrcOptimal,
+ texArray.handle, VkImageLayout.TransferDstOptimal, 1, ref imageBlit, VkFilter.Linear);
+ texArray.SetLayout (cmd, VkImageLayout.TransferDstOptimal, VkImageLayout.TransferSrcOptimal, mipSubRange,
+ VkPipelineStageFlags.Transfer, VkPipelineStageFlags.Transfer);
+ }
- // textures.Add (vkimg);
- // }
+ texArray.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.TransferSrcOptimal, VkImageLayout.ShaderReadOnlyOptimal,
+ VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader);
- // return imgs;
- //}
+ cmd.End ();
+ transferQ.Submit (cmd);
+ transferQ.WaitIdle ();
+ cmd.Free ();
+ }
public Image[] LoadImages () {
if (gltf.Images == null)
@@ -498,21 +523,21 @@ namespace CVKL {
FromFloatArray (ref pbr.emissiveFactor, mat.EmissiveFactor);
if (mat.EmissiveTexture != null) {
- pbr.emissiveTexture = (uint)mat.EmissiveTexture.Index;
+ pbr.emissiveTexture = mat.EmissiveTexture.Index;
if (mat.EmissiveTexture.TexCoord == 1)
pbr.availableAttachments1 |= AttachmentType.Emissive;
else
pbr.availableAttachments |= AttachmentType.Emissive;
}
if (mat.NormalTexture != null) {
- pbr.normalTexture = (uint)mat.NormalTexture.Index;
+ pbr.normalTexture = mat.NormalTexture.Index;
if (mat.NormalTexture.TexCoord == 1)
pbr.availableAttachments1 |= AttachmentType.Normal;
else
pbr.availableAttachments |= AttachmentType.Normal;
}
if (mat.OcclusionTexture != null) {
- pbr.occlusionTexture = (uint)mat.OcclusionTexture.Index;
+ pbr.occlusionTexture = mat.OcclusionTexture.Index;
if (mat.OcclusionTexture.TexCoord == 1)
pbr.availableAttachments1 |= AttachmentType.AmbientOcclusion;
else
@@ -521,7 +546,7 @@ namespace CVKL {
if (mat.PbrMetallicRoughness != null) {
if (mat.PbrMetallicRoughness.BaseColorTexture != null) {
- pbr.baseColorTexture = (uint)mat.PbrMetallicRoughness.BaseColorTexture.Index;
+ pbr.baseColorTexture = mat.PbrMetallicRoughness.BaseColorTexture.Index;
if (mat.PbrMetallicRoughness.BaseColorTexture.TexCoord == 1)
pbr.availableAttachments1 |= AttachmentType.Color;
else
@@ -531,7 +556,7 @@ namespace CVKL {
FromFloatArray (ref pbr.baseColorFactor, mat.PbrMetallicRoughness.BaseColorFactor);
if (mat.PbrMetallicRoughness.MetallicRoughnessTexture != null) {
- pbr.metallicRoughnessTexture = (uint)mat.PbrMetallicRoughness.MetallicRoughnessTexture.Index;
+ pbr.metallicRoughnessTexture = mat.PbrMetallicRoughness.MetallicRoughnessTexture.Index;
if (mat.PbrMetallicRoughness.MetallicRoughnessTexture.TexCoord == 1)
pbr.availableAttachments1 |= AttachmentType.PhysicalProps;
else