diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2019-05-02 02:49:54 +0200 |
|---|---|---|
| committer | j-p <jp_bruyere@hotmail.com> | 2019-05-02 03:07:11 +0200 |
| commit | 28019686e4c06aa7b3e1b3a5e33ce7eec0bfeb0a (patch) | |
| tree | 734bf444afb0897018be0041a7802955956c418a | |
| parent | d54a090d4a6665e7e8fbb6986da11051b243736a (diff) | |
Crow tests
27 files changed, 1377 insertions, 688 deletions
diff --git a/crow b/crow -Subproject c160c5b518d91cbd9b664df9c9d23b60dfee4bc +Subproject 152bc103da8a40d737ecf4e9a824ab5d5dde97c diff --git a/samples/Triangle/Triangle.csproj b/samples/Triangle/Triangle.csproj index 5039c7e..eeba0b2 100644 --- a/samples/Triangle/Triangle.csproj +++ b/samples/Triangle/Triangle.csproj @@ -27,7 +27,7 @@ <Reference Include="System.Numerics" /> <Reference Include="System" /> <Reference Include="Newtonsoft.Json"> - <HintPath>..\..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> + <HintPath>..\..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath> </Reference> <Reference Include="glTFLoader"> <HintPath>..\..\packages\glTF2Loader.1.1.3-alpha\lib\net35\glTFLoader.dll</HintPath> diff --git a/samples/Triangle/main.cs b/samples/Triangle/main.cs index da03b46..55ce742 100644 --- a/samples/Triangle/main.cs +++ b/samples/Triangle/main.cs @@ -56,9 +56,7 @@ namespace Triangle { descriptorPool = new DescriptorPool (dev, 1, new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer)); dsLayout = new DescriptorSetLayout (dev, - new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex|VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer)); - - descriptorSet = descriptorPool.Allocate (dsLayout); + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex|VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer)); GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1); @@ -76,6 +74,7 @@ namespace Triangle { pipeline = new GraphicPipeline (cfg); + descriptorSet = descriptorPool.Allocate (dsLayout); DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descriptorSet, dsLayout); uboUpdate.Write (dev, uboMats.Descriptor); diff --git a/samples/Triangle/packages.config b/samples/Triangle/packages.config index 69e495e..1af220a 100644 --- a/samples/Triangle/packages.config +++ b/samples/Triangle/packages.config @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="glTF2Loader" version="1.1.3-alpha" targetFramework="net471" /> - <package id="Newtonsoft.Json" version="12.0.1" targetFramework="net471" /> + <package id="Newtonsoft.Json" version="12.0.2" targetFramework="net471" /> <package id="System.Numerics.Vectors" version="4.6.0-preview4.19212.13" targetFramework="net471" /> <package id="System.Runtime.CompilerServices.Unsafe" version="4.6.0-preview4.19212.13" targetFramework="net471" /> <package id="Vulkan" version="0.1.2.6" targetFramework="net471" /> diff --git a/samples/VkvgCrowTest/EnvironmentPipeline.cs b/samples/VkvgCrowTest/EnvironmentPipeline.cs index 968a3e5..03b70c7 100644 --- a/samples/VkvgCrowTest/EnvironmentPipeline.cs +++ b/samples/VkvgCrowTest/EnvironmentPipeline.cs @@ -6,49 +6,40 @@ using VK; namespace CVKL { class EnvironmentCube : GraphicPipeline { - DescriptorPool descriptorPool; - DescriptorSetLayout descLayoutMain; - public DescriptorSet dsSkybox; GPUBuffer vboSkybox; public Image cubemap { get; private set; } public Image lutBrdf { get; private set; } public Image irradianceCube { get; private set; } - public Image prefilterCube { get; private set; } + public Image prefilterCube { get; set; } - public EnvironmentCube (Queue staggingQ, RenderPass renderPass) - : base (renderPass, "EnvCube pipeline") { - descriptorPool = new DescriptorPool (dev, 1, - new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer, 1), - new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 1) - ); + public Image debugImg; + public int debugMip = -1; + public int debugFace = 0; - descLayoutMain = new DescriptorSetLayout (dev, - new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex, VkDescriptorType.UniformBuffer), - new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)); - - dsSkybox = descriptorPool.Allocate (descLayoutMain); + public EnvironmentCube (DescriptorSet dsSkybox, PipelineLayout plLayout, Queue staggingQ, RenderPass renderPass, PipelineCache pipelineCache = null) + : base (renderPass, pipelineCache, "EnvCube pipeline") { using (CommandPool cmdPool = new CommandPool (staggingQ.Dev, staggingQ.index)) { vboSkybox = new GPUBuffer<float> (staggingQ, cmdPool, VkBufferUsageFlags.VertexBuffer, box_vertices); - cubemap = KTX.KTX.Load (staggingQ, cmdPool, cubemapPathes[4], + cubemap = KTX.KTX.Load (staggingQ, cmdPool, cubemapPathes[2], VkImageUsageFlags.Sampled, VkMemoryPropertyFlags.DeviceLocal, true); - cubemap.CreateView (VkImageViewType.Cube, VkImageAspectFlags.Color, 6); - cubemap.CreateSampler (); + cubemap.CreateView (VkImageViewType.Cube, VkImageAspectFlags.Color, 6, 0, cubemap.CreateInfo.mipLevels); + cubemap.CreateSampler (VkSamplerAddressMode.ClampToEdge); cubemap.SetName ("skybox Texture"); + cubemap.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; - GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, renderPass.Samples); + GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, renderPass.Samples, false); cfg.RenderPass = renderPass; - cfg.Layout = new PipelineLayout (dev, descLayoutMain); - cfg.AddVertexBinding (0, 5 * sizeof (float)); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat); + cfg.Layout = plLayout; + cfg.AddVertexBinding (0, 3 * sizeof (float)); + cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/skybox.vert.spv"); cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/skybox.frag.spv"); - cfg.depthStencilState.depthTestEnable = false; - cfg.depthStencilState.depthWriteEnable = false; + cfg.multisampleState.rasterizationSamples = Samples; layout = cfg.Layout; @@ -57,23 +48,22 @@ namespace CVKL { generateBRDFLUT (staggingQ, cmdPool); generateCubemaps (staggingQ, cmdPool); } - - } - public void WriteDesc (VkDescriptorBufferInfo matrixDesc) { - DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descLayoutMain); - uboUpdate.Write (dev, dsSkybox, matrixDesc, cubemap.Descriptor); } + //public void WriteDesc (VkDescriptorBufferInfo matrixDesc) { + // DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descLayoutMain); + // uboUpdate.Write (Dev, dsSkybox, matrixDesc, cubemap.Descriptor); + //} + public void RecordDraw (CommandBuffer cmd) { - Bind (cmd); - cmd.BindDescriptorSet (Layout, dsSkybox); + Bind (cmd); cmd.BindVertexBuffer (vboSkybox); cmd.Draw (36); } #region skybox - public List<string> cubemapPathes = new List<string>() { + public List<string> cubemapPathes = new List<string> () { "../data/textures/papermill.ktx", "../data/textures/cubemap_yokohama_bc3_unorm.ktx", "../data/textures/gcanyon_cube.ktx", @@ -81,47 +71,48 @@ namespace CVKL { "../data/textures/uffizi_cube.ktx", }; static float[] box_vertices = { - -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, // -X side - -1.0f,-1.0f, 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, - -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, - -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, - -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, + 1.0f, 1.0f,-1.0f, // +X side + 1.0f, 1.0f, 1.0f, + 1.0f,-1.0f, 1.0f, + 1.0f,-1.0f, 1.0f, + 1.0f,-1.0f,-1.0f, + 1.0f, 1.0f,-1.0f, + + -1.0f,-1.0f,-1.0f, // +X side + -1.0f,-1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f,-1.0f, + -1.0f,-1.0f,-1.0f, - 1.0f, 1.0f,-1.0f, 1.0f, 0.0f, // +X side - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, - 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, - 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, - 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, - 1.0f, 1.0f,-1.0f, 1.0f, 0.0f, + -1.0f, 1.0f,-1.0f, // +Y side + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f,-1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f,-1.0f, - -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, // -Y side - 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, - 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, - -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, - 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, - -1.0f,-1.0f, 1.0f, 0.0f, 0.0f, + -1.0f,-1.0f,-1.0f, // -Y side + 1.0f,-1.0f,-1.0f, + 1.0f,-1.0f, 1.0f, + -1.0f,-1.0f,-1.0f, + 1.0f,-1.0f, 1.0f, + -1.0f,-1.0f, 1.0f, - -1.0f, 1.0f,-1.0f, 1.0f, 0.0f, // +Y side - -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, - -1.0f, 1.0f,-1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, // +Z side + -1.0f,-1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f,-1.0f, 1.0f, + 1.0f,-1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, - -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, // -Z side - 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, - 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, - -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, - -1.0f, 1.0f,-1.0f, 1.0f, 0.0f, - 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, + -1.0f,-1.0f,-1.0f, // -Z side + 1.0f, 1.0f,-1.0f, + 1.0f,-1.0f,-1.0f, + -1.0f,-1.0f,-1.0f, + -1.0f, 1.0f,-1.0f, + 1.0f, 1.0f,-1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // +Z side - -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, - -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, - 1.0f,-1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, }; #endregion @@ -129,7 +120,7 @@ namespace CVKL { const VkFormat format = VkFormat.R16g16Sfloat; const int dim = 512; - lutBrdf = new Image (dev, format, VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.Sampled, + lutBrdf = new Image (Dev, format, VkImageUsageFlags.ColorAttachment | VkImageUsageFlags.Sampled, VkMemoryPropertyFlags.DeviceLocal, dim, dim); lutBrdf.SetName ("lutBrdf"); @@ -138,8 +129,8 @@ namespace CVKL { GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false); - cfg.Layout = new PipelineLayout (dev, new DescriptorSetLayout (dev)); - cfg.RenderPass = new RenderPass (dev); + cfg.Layout = new PipelineLayout (Dev, new DescriptorSetLayout (Dev)); + cfg.RenderPass = new RenderPass (Dev); cfg.RenderPass.AddAttachment (format, VkImageLayout.ShaderReadOnlyOptimal); cfg.RenderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0, 0, 0) }); cfg.RenderPass.AddSubpass (new SubPass (VkImageLayout.ColorAttachmentOptimal)); @@ -167,9 +158,9 @@ namespace CVKL { lutBrdf.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; } - enum CBTarget { IRRADIANCE = 0, PREFILTEREDENV = 1 }; + public enum CBTarget { IRRADIANCE = 0, PREFILTEREDENV = 1 }; - Image generateCubeMap (Queue staggingQ, CommandPool cmdPool, CBTarget target) { + public Image generateCubeMap (Queue staggingQ, CommandPool cmdPool, CBTarget target) { const float deltaPhi = (2.0f * (float)Math.PI) / 180.0f; const float deltaTheta = (0.5f * (float)Math.PI) / 64.0f; @@ -181,16 +172,16 @@ namespace CVKL { dim = 512; } - uint numMips = (uint)Math.Floor (Math.Log (dim)) + 1; + uint numMips = (uint)Math.Floor (Math.Log (dim, 2)) + 1; - Image imgFbOffscreen = new Image (dev, format, VkImageUsageFlags.TransferSrc | VkImageUsageFlags.ColorAttachment, + Image imgFbOffscreen = new Image (Dev, format, VkImageUsageFlags.TransferSrc | VkImageUsageFlags.ColorAttachment, VkMemoryPropertyFlags.DeviceLocal, dim, dim); imgFbOffscreen.SetName ("offscreenfb"); imgFbOffscreen.CreateView (); - Image cmap = new Image (dev, format, VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled, + Image cmap = new Image (Dev, format, VkImageUsageFlags.TransferDst | VkImageUsageFlags.Sampled, VkMemoryPropertyFlags.DeviceLocal, dim, dim, VkImageType.Image2D, VkSampleCountFlags.SampleCount1, VkImageTiling.Optimal, - numMips, 6, 1, VkImageCreateFlags.CubeCompatible); + numMips, 6, 1, VkImageCreateFlags.CubeCompatible); if (target == CBTarget.PREFILTEREDENV) cmap.SetName ("prefilterenvmap"); else @@ -198,28 +189,24 @@ namespace CVKL { cmap.CreateView (VkImageViewType.Cube, VkImageAspectFlags.Color, 6, 0, numMips); cmap.CreateSampler (VkSamplerAddressMode.ClampToEdge); - DescriptorPool dsPool = new DescriptorPool (dev, 2, new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler)); + DescriptorPool dsPool = new DescriptorPool (Dev, 2, new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler)); - DescriptorSetLayout dsLayout = new DescriptorSetLayout (dev, - new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)); - - DescriptorSet dset = dsPool.Allocate (dsLayout); + DescriptorSetLayout dsLayout = new DescriptorSetLayout (Dev, + new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)); GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, VkSampleCountFlags.SampleCount1, false); - DescriptorSetWrites dsUpdate = new DescriptorSetWrites (dsLayout); - dsUpdate.Write (dev, dset, cubemap.Descriptor); - cfg.Layout = new PipelineLayout (dev, dsLayout); + cfg.Layout = new PipelineLayout (Dev, dsLayout); cfg.Layout.AddPushConstants ( new VkPushConstantRange (VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, (uint)Marshal.SizeOf<Matrix4x4> () + 8)); - cfg.RenderPass = new RenderPass (dev); + cfg.RenderPass = new RenderPass (Dev); cfg.RenderPass.AddAttachment (format, VkImageLayout.ColorAttachmentOptimal); cfg.RenderPass.ClearValues.Add (new VkClearValue { color = new VkClearColorValue (0, 0, 0) }); cfg.RenderPass.AddSubpass (new SubPass (VkImageLayout.ColorAttachmentOptimal)); - cfg.AddVertexBinding (0, 5 * sizeof (float)); + cfg.AddVertexBinding (0, 3 * sizeof (float)); cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat); cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/filtercube.vert.spv"); @@ -246,33 +233,33 @@ namespace CVKL { VkImageSubresourceRange subRes = new VkImageSubresourceRange (VkImageAspectFlags.Color, 0, numMips, 0, 6); using (GraphicPipeline pl = new GraphicPipeline (cfg)) { + DescriptorSet dset = dsPool.Allocate (dsLayout); + DescriptorSetWrites dsUpdate = new DescriptorSetWrites (dsLayout); + dsUpdate.Write (Dev, dset, cubemap.Descriptor); + using (Framebuffer fb = new Framebuffer (pl.RenderPass, dim, dim, imgFbOffscreen)) { CommandBuffer cmd = cmdPool.AllocateCommandBuffer (); cmd.Start (VkCommandBufferUsageFlags.OneTimeSubmit); cmap.SetLayout (cmd, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, subRes); - + float roughness = 0; cmd.SetScissor (dim, dim); cmd.SetViewport ((float)(dim), (float)dim); for (int m = 0; m < numMips; m++) { - roughness = (float)m / (numMips - 1); - for (int f = 0; f < 6; f++) { - + roughness = (float)m / ((float)numMips - 1f); + for (int f = 0; f < 6; f++) { pl.RenderPass.Begin (cmd, fb); pl.Bind (cmd); float viewPortSize = (float)Math.Pow (0.5, m) * dim; cmd.SetViewport (viewPortSize, viewPortSize); - - cmd.PushConstant (pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, - matrices[f] * - Matrix4x4.CreatePerspectiveFieldOfView (Utils.DegreesToRadians (90), 1f, 0.1f, 512f)) ; + matrices[f] * Matrix4x4.CreatePerspectiveFieldOfView (Utils.DegreesToRadians (90), 1f, 0.1f, 512f)); if (target == CBTarget.IRRADIANCE) { cmd.PushConstant (pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, deltaPhi, (uint)Marshal.SizeOf<Matrix4x4> ()); cmd.PushConstant (pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, deltaTheta, (uint)Marshal.SizeOf<Matrix4x4> () + 4); @@ -280,6 +267,7 @@ namespace CVKL { cmd.PushConstant (pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, roughness, (uint)Marshal.SizeOf<Matrix4x4> ()); cmd.PushConstant (pl.Layout, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, 32u, (uint)Marshal.SizeOf<Matrix4x4> () + 4); } + cmd.BindDescriptorSet (pl.Layout, dset); cmd.BindVertexBuffer (vboSkybox); cmd.Draw (36); @@ -300,6 +288,26 @@ namespace CVKL { 1, region.Pin ()); region.Unpin (); + //debug img + if (target == CBTarget.PREFILTEREDENV && m == debugMip && f == debugFace) { + debugImg?.Dispose (); + debugImg = new Image (Dev, VkFormat.R16g16b16a16Sfloat, VkImageUsageFlags.Sampled | VkImageUsageFlags.TransferDst, VkMemoryPropertyFlags.DeviceLocal, + (uint)viewPortSize, (uint)viewPortSize); + debugImg.CreateView (); + debugImg.CreateSampler (); + region.dstSubresource.baseArrayLayer = 0; + region.dstSubresource.mipLevel = 0; + debugImg.SetLayout (cmd, VkImageAspectFlags.Color, + VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal); + Vk.vkCmdCopyImage (cmd.Handle, + imgFbOffscreen.Handle, VkImageLayout.TransferSrcOptimal, + debugImg.Handle, VkImageLayout.TransferDstOptimal, + 1, region.Pin ()); + debugImg.SetLayout (cmd, VkImageAspectFlags.Color, + VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal); + region.Unpin (); + } + imgFbOffscreen.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.TransferSrcOptimal, VkImageLayout.ColorAttachmentOptimal); @@ -337,8 +345,7 @@ namespace CVKL { irradianceCube.Dispose (); prefilterCube.Dispose (); - descLayoutMain.Dispose (); - descriptorPool.Dispose (); + debugImg?.Dispose (); base.Dispose (disposing); } diff --git a/samples/VkvgCrowTest/PbrPipeline.cs b/samples/VkvgCrowTest/PbrPipeline.cs index f285f8a..ea93163 100644 --- a/samples/VkvgCrowTest/PbrPipeline.cs +++ b/samples/VkvgCrowTest/PbrPipeline.cs @@ -2,49 +2,295 @@ using System.Numerics; using System.Runtime.InteropServices; using VK; +using System.Diagnostics; +using System.Collections.Generic; namespace CVKL { - class PBRPipeline : GraphicPipeline { + using static VK.Utils; + + + //TODO:stride in buffer views? + public class PbrModel2 : Model { + public struct Vertex { + [VertexAttribute (VertexAttributeType.Position, VkFormat.R32g32b32Sfloat)] + public Vector3 pos; + [VertexAttribute (VertexAttributeType.Normal, VkFormat.R32g32b32Sfloat)] + public Vector3 normal; + [VertexAttribute (VertexAttributeType.UVs, VkFormat.R32g32Sfloat)] + public Vector2 uv0; + [VertexAttribute (VertexAttributeType.UVs, VkFormat.R32g32Sfloat)] + public Vector2 uv1; + public override string ToString () { + 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; + PbrMaterial[] materials; + DescriptorSet[] descriptorSets; + + DescriptorPool descriptorPool; + public GPUBuffer vbo; + public GPUBuffer ibo; + public GPUBuffer<PbrMaterial> materialUBO; + + public PbrModel2 (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)); + Scenes = new List<Scene> (ctx.LoadScenes (out defaultSceneIndex)); + } + } + } + public PbrModel2 (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 GPUBuffer<PbrMaterial> (transferQ, cmdPool, 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) + }; + + 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 (); + } + } + } + + + /// <summary> bind vertex and index buffers </summary> + public 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) { + Matrix4x4 localMat = node.localMatrix * currentTransform; + + cmd.PushConstant (pipelineLayout, VkShaderStageFlags.Vertex, localMat); + + if (node.Mesh != null) { + foreach (Primitive p in node.Mesh.Primitives) { + 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); + } + + public void DrawAll (CommandBuffer cmd, PipelineLayout pipelineLayout) { + foreach (Scene sc in Scenes) { + foreach (Node node in sc.Root.Children) { + RenderNode (cmd, pipelineLayout, node, sc.Root.localMatrix); + } + } + } + + #region IDisposable Support + private bool isDisposed = false; // Pour détecter les appels redondants + + protected virtual void Dispose (bool disposing) { + if (!isDisposed) { + if (disposing) { + ibo?.Dispose (); + vbo?.Dispose (); + materialUBO?.Dispose (); + descriptorPool?.Dispose (); + foreach (Image txt in textures) { + txt.Dispose (); + } + } else + Debug.WriteLine ("model was not disposed"); + isDisposed = true; + } + } + public void Dispose () { + Dispose (true); + } + #endregion + } +} + +namespace CVKL { + + class PBRPipeline : GraphicPipeline { + public struct Matrices { public Matrix4x4 projection; - public Matrix4x4 view; public Matrix4x4 model; - public Vector4 lightPos; - public float gamma; + public Matrix4x4 view; + public Vector4 camPos; + public Vector4 lightDir; public float exposure; + public float gamma; + public float prefilteredCubeMipLevels; + public float scaleIBLAmbient; + public float debugViewInputs; + public float debugViewEquation; } public Matrices matrices = new Matrices { - lightPos = new Vector4 (1.0f, 0.0f, 0.0f, 1.0f), - gamma = 1.0f, - exposure = 2.0f, + lightDir = Vector4.Normalize (new Vector4 (0.7f, 0.6f, 0.2f, 0.0f)), + gamma = 2.2f, + exposure = 4.5f, + scaleIBLAmbient = 1f, + debugViewInputs = 0, + debugViewEquation = 0 }; public HostBuffer uboMats; DescriptorPool descriptorPool; + DescriptorSetLayout descLayoutMain; DescriptorSetLayout descLayoutTextures; - DescriptorSet dsMain; + public DescriptorSet dsMain; - Model model; - EnvironmentCube envCube; + public PbrModel2 model; + public EnvironmentCube envCube; - public PBRPipeline (Queue staggingQ, RenderPass renderPass) : - base (renderPass, "pbr pipeline") { + public PBRPipeline (Queue staggingQ, RenderPass renderPass, Image uiImage, PipelineCache pipelineCache = null) : + base (renderPass, pipelineCache, "pbr pipeline") { - descriptorPool = new DescriptorPool (dev, 2, + descriptorPool = new DescriptorPool (Dev, 2, new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer, 2), - new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 8) + new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 9) ); - descLayoutMain = new DescriptorSetLayout (dev, + descLayoutMain = new DescriptorSetLayout (Dev, new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer), new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), - new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)); + new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), + new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer), + new VkDescriptorSetLayoutBinding (5, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler));//ui image - descLayoutTextures = new DescriptorSetLayout (dev, + 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), @@ -52,90 +298,80 @@ namespace CVKL { new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) ); - dsMain = descriptorPool.Allocate (descLayoutMain); GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, renderPass.Samples); - - cfg.Layout = new PipelineLayout (dev, descLayoutMain, descLayoutTextures); + cfg.Layout = new PipelineLayout (Dev, descLayoutMain, descLayoutTextures); cfg.Layout.AddPushConstants ( new VkPushConstantRange (VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf<Matrix4x4> ()), - new VkPushConstantRange (VkShaderStageFlags.Fragment, (uint)Marshal.SizeOf<Model.PbrMaterial> (), 64) + new VkPushConstantRange (VkShaderStageFlags.Fragment, sizeof (int), 64) ); cfg.RenderPass = renderPass; - cfg.AddVertexBinding<Model.Vertex> (0); - cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat); + cfg.AddVertexBinding<PbrModel2.Vertex> (0); + cfg.SetVertexAttributes (0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat, VkFormat.R32g32Sfloat); - cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/pbrtest.vert.spv"); - cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/pbrtest.frag.spv"); + cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/pbr.vert.spv"); + cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/pbr_khr.frag.spv"); layout = cfg.Layout; init (cfg); - envCube = new EnvironmentCube (staggingQ, RenderPass); + dsMain = descriptorPool.Allocate (descLayoutMain); + + envCube = new EnvironmentCube (dsMain, layout, staggingQ, RenderPass); - uboMats = new HostBuffer (dev, VkBufferUsageFlags.UniformBuffer, (ulong)Marshal.SizeOf<Matrices> () * 2); - uboMats.Map ();//permanent map + matrices.prefilteredCubeMipLevels = envCube.prefilterCube.CreateInfo.mipLevels; + uboMats = new HostBuffer (Dev, VkBufferUsageFlags.UniformBuffer, matrices, true); + string[] modelPathes = { + "../data/models/DamagedHelmet/glTF/DamagedHelmet.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Avocado/glTF/Avocado.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/BarramundiFish/glTF/BarramundiFish.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/BoomBoxWithAxes/glTF/BoomBoxWithAxes.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Box/glTF/Box.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/EnvironmentTest/glTF/EnvironmentTest.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/MetalRoughSpheres/glTF/MetalRoughSpheres.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/OrientationTest/glTF/OrientationTest.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Buggy/glTF/Buggy.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/2CylinderEngine/glTF-Embedded/2CylinderEngine.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/FlightHelmet/glTF/FlightHelmet.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/GearboxAssy/glTF/GearboxAssy.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Lantern/glTF/Lantern.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/SciFiHelmet/glTF/SciFiHelmet.gltf", + "/mnt/devel/vulkan/glTF-Sample-Models-master/2.0/Sponza/glTF/Sponza.gltf", + "/mnt/devel/vkChess/data/chess.gltf" + }; + + + model = new PbrModel2 (staggingQ, modelPathes[0], descLayoutTextures, + AttachmentType.Color, + AttachmentType.PhysicalProps, + AttachmentType.Normal, + AttachmentType.AmbientOcclusion, + AttachmentType.Emissive); + //model = new Model (Dev, presentQueue, "../data/models/icosphere.gltf"); + //model = new Model (Dev, presentQueue, cmdPool, "../data/models/cube.gltf"); DescriptorSetWrites uboUpdate = new DescriptorSetWrites (descLayoutMain); - uboUpdate.Write (dev, dsMain, uboMats.Descriptor, - envCube.lutBrdf.Descriptor, + uboUpdate.Write (Dev, dsMain, + uboMats.Descriptor, envCube.irradianceCube.Descriptor, - envCube.prefilterCube.Descriptor); - uboMats.Descriptor.offset = (ulong)Marshal.SizeOf<Matrices> (); - envCube.WriteDesc (uboMats.Descriptor); + envCube.prefilterCube.Descriptor, + envCube.lutBrdf.Descriptor, + model.materialUBO.Descriptor, + uiImage.Descriptor); - model = new Model (staggingQ, "../data/models/DamagedHelmet/glTF/DamagedHelmet.gltf"); - //model = new Model (dev, presentQueue, "../data/models/icosphere.gltf"); - //model = new Model (dev, presentQueue, cmdPool, "../data/models/cube.gltf"); - model.WriteMaterialsDescriptorSets (descLayoutTextures, - VK.AttachmentType.Color, - VK.AttachmentType.Normal, - VK.AttachmentType.AmbientOcclusion, - VK.AttachmentType.PhysicalProps, - VK.AttachmentType.Emissive); } - public void RecordDraw (CommandBuffer cmd) { + public void RecordDraw (CommandBuffer cmd) { + cmd.BindDescriptorSet (Layout, dsMain); envCube.RecordDraw (cmd); drawModel (cmd); } void drawModel (CommandBuffer cmd) { Bind (cmd); - cmd.BindDescriptorSet (Layout, dsMain); - model.Bind (cmd); - model.DrawAll (cmd, Layout); - } - void drawShadedModelArray (CommandBuffer cmd) { - Bind (cmd); - cmd.BindDescriptorSet (Layout, dsMain); model.Bind (cmd); model.DrawAll (cmd, Layout); - - Matrix4x4 modelMat = Matrix4x4.Identity; - Model.PbrMaterial material = new Model.PbrMaterial (1, 0, Model.AlphaMode.Opaque, 0.5f, VK.AttachmentType.None); - Model.Primitive p = model.Scenes[0].Root.Children[0].Mesh.Primitives[0]; - - for (int metalFact = 0; metalFact < 10; metalFact++) { - - material.metallicFactor = (float)metalFact / 10; - - for (int roughFact = 0; roughFact < 10; roughFact++) { - - material.roughnessFactor = (float)roughFact / 10; - - modelMat = Matrix4x4.CreateTranslation (-roughFact, metalFact, 0); - - - cmd.PushConstant (Layout, VkShaderStageFlags.Vertex, modelMat); - cmd.PushConstant (Layout, VkShaderStageFlags.Fragment, material, (uint)Marshal.SizeOf<Matrix4x4> ()); - - cmd.DrawIndexed (p.indexCount, 1, p.indexBase, p.vertexBase, 0); - } - } - - } protected override void Dispose (bool disposing) { diff --git a/samples/VkvgCrowTest/VkvgCrowTest.csproj b/samples/VkvgCrowTest/VkvgCrowTest.csproj index 0c3ed96..b60384e 100644 --- a/samples/VkvgCrowTest/VkvgCrowTest.csproj +++ b/samples/VkvgCrowTest/VkvgCrowTest.csproj @@ -38,7 +38,7 @@ </Reference> <Reference Include="mscorlib" /> <Reference Include="Newtonsoft.Json"> - <HintPath>..\..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> + <HintPath>..\..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath> </Reference> <Reference Include="glTFLoader"> <HintPath>..\..\packages\glTF2Loader.1.1.3-alpha\lib\net35\glTFLoader.dll</HintPath> @@ -53,21 +53,21 @@ <HintPath>..\..\packages\System.Memory.4.5.2\lib\netstandard2.0\System.Memory.dll</HintPath> </Reference> <Reference Include="VK"> - <HintPath>..\..\packages\Vulkan.0.1.2.5-alpha\lib\netstandard2.0\VK.dll</HintPath> + <HintPath>..\..\packages\Vulkan.0.1.2.6\lib\netstandard2.0\VK.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> <None Include="packages.config" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\..\vke\VKE.csproj"> - <Project>{32B7E80D-BEA7-4811-B82D-CC2533069F0A}</Project> - <Name>CVKL</Name> - </ProjectReference> <ProjectReference Include="..\..\crow\Crow\Crow.csproj"> <Project>{C2980F9B-4798-4C05-99E2-E174810F7C7B}</Project> <Name>Crow</Name> </ProjectReference> + <ProjectReference Include="..\..\vke\CVKL.csproj"> + <Project>{32B7E80D-BEA7-4811-B82D-CC2533069F0A}</Project> + <Name>CVKL</Name> + </ProjectReference> </ItemGroup> <ItemGroup> <Folder Include="ui\" /> @@ -75,7 +75,16 @@ <ItemGroup> <EmbeddedResource Include="ui\fps.crow"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <LogicalName>vkvgCrowTest.fps.crow</LogicalName> </EmbeddedResource> + <EmbeddedResource Include="ui\perfMsr.crow"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <LogicalName>vkvgCrowTest.perfMsr.crow</LogicalName> + </EmbeddedResource> + <EmbeddedResource Include="ui\perfMeasures.crow"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <LogicalName>vkvgCrowTest.perfMeasures.crow</LogicalName> + </EmbeddedResource> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(SolutionDir)spirv.targets" /> diff --git a/samples/VkvgCrowTest/main.cs b/samples/VkvgCrowTest/main.cs index 81ea779..46a8903 100644 --- a/samples/VkvgCrowTest/main.cs +++ b/samples/VkvgCrowTest/main.cs @@ -4,22 +4,59 @@ using System.Runtime.InteropServices; using Glfw; using VK; using CVKL; +using System.Threading; -namespace PbrSample { - class Program : VkWindow, Crow.IValueChange { +namespace pbrSachaWillem { + class Program : VkWindow, Crow.IValueChange { static void Main (string[] args) { using (Program vke = new Program ()) { vke.Run (); } } + bool isRunning; - VkSampleCountFlags samples = VkSampleCountFlags.SampleCount4; + protected override void render () { + int idx = swapChain.GetNextImage (); - Framebuffer[] frameBuffers; - PBRPipeline pbrPipeline; + lock (crow.RenderMutex) { + if (idx < 0) { + OnResize (); + return; + } + + presentQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx]); + presentQueue.Present (swapChain, drawComplete[idx]); + presentQueue.WaitIdle (); + } + } #region crow + void crow_thread_func () { + vkvgDev = new vkvg.Device (instance.Handle, phy.Handle, dev.VkDev.Handle, presentQueue.qFamIndex, + vkvg.SampleCount.Sample_4, presentQueue.index); + + crow = new Crow.Interface (vkvgDev, 800, 600); + + isRunning = true; + //int frameCount = 0; + + while (isRunning) { + crow.Update (); + + /*if (frameCount++ > 100) { + for (int i = 0; i < crow.PerfMeasures.Count; i++) + crow.PerfMeasures[i].NotifyChanges (); + frameCount = 0; + }*/ + + Thread.Sleep (2); + } + dev.WaitIdle (); + crow.Dispose (); + vkvgDev.Dispose (); + } + #region IValueChange implementation public event EventHandler<Crow.ValueChangeEventArgs> ValueChanged; public virtual void NotifyValueChanged(string MemberName, object _value) @@ -50,77 +87,151 @@ namespace PbrSample { } } Crow.Interface crow; - GraphicPipeline uiPipeline; - Image uiImage; - vkvg.Device vkvgDev; - - void initCrow () { - vkvgDev = new vkvg.Device (instance.Handle, phy.Handle, dev.VkDev.Handle, presentQueue.qFamIndex, - vkvg.SampleCount.Sample_1, presentQueue.index); + #endregion - crow = new Crow.Interface(vkvgDev, 800,600); + protected override void configureEnabledFeatures (VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures features) { + base.configureEnabledFeatures (available_features, ref features); +#if PIPELINE_STATS + features.pipelineStatisticsQuery = true; +#endif + features.samplerAnisotropy = true; } - void createUIImage () { - uiImage?.Dispose (); - uiImage = new Image (dev, new VkImage ((ulong)crow.surf.VkImage.ToInt64 ()), VkFormat.B8g8r8a8Unorm, - VkImageUsageFlags.Sampled, swapChain.Width, swapChain.Height); - uiImage.SetName ("uiImage"); - uiImage.CreateView (); - uiImage.CreateSampler (); - uiImage.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + + VkSampleCountFlags samples = VkSampleCountFlags.SampleCount4; + + Framebuffer[] frameBuffers; + PBRPipeline pbrPipeline; + + enum DebugView { + none, + color, + normal, + occlusion, + emissive, + metallic, + roughness } - #endregion - Program () { - //UpdateFrequency = 20; - camera.Model = Matrix4x4.CreateRotationX (Utils.DegreesToRadians (-90)) * Matrix4x4.CreateRotationY (Utils.DegreesToRadians (180)); - camera.SetRotation (-0.1f,-0.4f); - camera.SetPosition (0, 0, -3); + DebugView currentDebugView = DebugView.none; - initCrow (); +#if PIPELINE_STATS + PipelineStatisticsQueryPool statPool; + TimestampQueryPool timestampQPool; + ulong[] results; +#endif - init (); - crow.Load ("ui/fps.crow").DataSource = this; - } + bool queryUpdatePrefilCube, showDebugImg, showUI = true; - DescriptorPool descriptorPool; - DescriptorSetLayout descLayoutMain; - DescriptorSet dsMain; - void init() { + Image uiImage; + + #region ui + //DescriptorSet dsDebugImg; + //void initDebugImg () { + // dsDebugImg = descriptorPool.Allocate (descLayoutMain); + // pbrPipeline.envCube.debugImg.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + // DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsDebugImg, descLayoutMain); + // uboUpdate.Write (dev, pbrPipeline.envCube.debugImg.Descriptor); + //} - pbrPipeline = new PBRPipeline(presentQueue, - new RenderPass (dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat (), samples)); + vkvg.Device vkvgDev; - descriptorPool = new DescriptorPool (dev, 1, new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler)); - descLayoutMain = new DescriptorSetLayout (dev, - new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)); - dsMain = descriptorPool.Allocate (descLayoutMain); + Pipeline uiPipeline; - GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, samples); + void initUIPipeline () { + GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, samples, false); cfg.RenderPass = pbrPipeline.RenderPass; - cfg.Layout = new PipelineLayout (dev, descLayoutMain); - + cfg.Layout = pbrPipeline.Layout; cfg.AddShader (VkShaderStageFlags.Vertex, "shaders/FullScreenQuad.vert.spv"); cfg.AddShader (VkShaderStageFlags.Fragment, "shaders/simpletexture.frag.spv"); cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState (true); uiPipeline = new GraphicPipeline (cfg); - createUIImage (); } + void initUISurface () { + lock (crow.UpdateMutex) { + uiImage?.Dispose (); + uiImage = new CVKL.Image (dev, new VkImage ((ulong)crow.surf.VkImage.ToInt64 ()), VkFormat.B8g8r8a8Unorm, + VkImageUsageFlags.Sampled, swapChain.Width, swapChain.Height); + uiImage.SetName ("uiImage"); + uiImage.CreateView (VkImageViewType.ImageView2D, VkImageAspectFlags.Color); + uiImage.CreateSampler (VkFilter.Nearest, VkFilter.Nearest, VkSamplerMipmapMode.Nearest, VkSamplerAddressMode.ClampToBorder); + uiImage.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + } + } + + + void recordDrawOverlay (CommandBuffer cmd) { + uiPipeline.Bind (cmd); + + uiImage.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.ColorAttachmentOptimal, VkImageLayout.ShaderReadOnlyOptimal, + VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.FragmentShader); + + cmd.Draw (3, 1, 0, 0); + uiImage.SetLayout (cmd, VkImageAspectFlags.Color, VkImageLayout.ShaderReadOnlyOptimal, VkImageLayout.ColorAttachmentOptimal, + VkPipelineStageFlags.FragmentShader, VkPipelineStageFlags.BottomOfPipe); + //if (!showDebugImg) + // return; + //const uint debugImgSize = 256; + //const uint debugImgMargin = 10; + + //cmd.BindDescriptorSet (uiPipeline.Layout, dsDebugImg); + + //cmd.SetViewport (debugImgSize, debugImgSize, debugImgMargin, swapChain.Height - debugImgSize - debugImgMargin); + //cmd.SetScissor (debugImgSize, debugImgSize, (int)debugImgMargin, (int)(swapChain.Height - debugImgSize - debugImgMargin)); + + //cmd.Draw (3, 1, 0, 0); + } + #endregion + + + Vector4 lightPos = new Vector4 (1, 0, 0, 0); + BoundingBox modelAABB; + + Program () { + camera.SetPosition (0, 0, 5); + + Thread crowThread = new Thread (crow_thread_func); + crowThread.IsBackground = true; + crowThread.Start (); + + while (crow == null) + Thread.Sleep (5); + + initUISurface (); + + pbrPipeline = new PBRPipeline (presentQueue, + new RenderPass (dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat (), samples), uiImage); + + initUIPipeline (); + + modelAABB = pbrPipeline.model.DefaultScene.AABB; + + crow.Load ("ui/fps.crow").DataSource = this; + //crow.Load ("#vkvgCrowTest.perfMeasures.crow").DataSource = crow; + + //crow.LoadIMLFragment ("<Window Height='200' Width='200' CornerRadius='5'/>").DataSource=this; + //crow.LoadIMLFragment ("<Window Height='200' Width='200'/>").DataSource = this; + crow.LoadIMLFragment (@"<Image Margin='1' Path='/mnt/devel/gts/vk.net/crow/Images/crow.png' Width='100' Height='100' Background='White' MouseEnter='{Background=Blue}' MouseLeave='{Background=White}'/>"); + //crow.LoadIMLFragment ("<Window Height='200' Width='200'/>").DataSource = this; + UpdateFrequency = 20; + } - #region command buffers void buildCommandBuffers () { for (int i = 0; i < swapChain.ImageCount; ++i) { cmds[i]?.Free (); - cmds[i] = cmdPool.AllocateCommandBuffer (); - cmds[i].Start (); - + cmds[i] = cmdPool.AllocateAndStart (); +#if PIPELINE_STATS + statPool.Begin (cmds[i]); recordDraw (cmds[i], frameBuffers[i]); + statPool.End (cmds[i]); +#else + recordDraw (cmds[i], frameBuffers[i]); +#endif cmds[i].End (); } @@ -133,47 +244,68 @@ namespace PbrSample { pbrPipeline.RecordDraw (cmd); - uiPipeline.Bind (cmd); - cmd.BindDescriptorSet (uiPipeline.Layout, dsMain); - cmd.Draw (3, 1, 0, 0); + if (showUI) + recordDrawOverlay (cmd); pbrPipeline.RenderPass.End (cmd); } - #endregion #region update - void updateMatrices () { + public override void UpdateView () { camera.AspectRatio = (float)swapChain.Width / swapChain.Height; + pbrPipeline.matrices.lightDir = lightPos; pbrPipeline.matrices.projection = camera.Projection; pbrPipeline.matrices.view = camera.View; pbrPipeline.matrices.model = camera.Model; + + + pbrPipeline.matrices.camPos = new Vector4 ( + -camera.Position.Z * (float)Math.Sin (camera.Rotation.Y) * (float)Math.Cos (camera.Rotation.X), + camera.Position.Z * (float)Math.Sin (camera.Rotation.X), + camera.Position.Z * (float)Math.Cos (camera.Rotation.Y) * (float)Math.Cos (camera.Rotation.X), + 0 + ); + pbrPipeline.matrices.debugViewInputs = (float)currentDebugView; + pbrPipeline.uboMats.Update (pbrPipeline.matrices, (uint)Marshal.SizeOf<PBRPipeline.Matrices> ()); - pbrPipeline.matrices.view *= Matrix4x4.CreateTranslation (-pbrPipeline.matrices.view.Translation); - pbrPipeline.matrices.model = Matrix4x4.Identity; - pbrPipeline.uboMats.Update (pbrPipeline.matrices, (uint)Marshal.SizeOf<PBRPipeline.Matrices> (), (uint)Marshal.SizeOf<PBRPipeline.Matrices> ()); - } - public override void UpdateView () { - updateMatrices (); updateViewRequested = false; } + + int frameCount = 0; + public override void Update () { - NotifyValueChanged ("fps", fps); - crow.Update (); +#if PIPELINE_STATS + results = statPool.GetResults (); +#endif + camera.Model *= Matrix4x4.CreateRotationY(0.05f); + updateViewRequested = true; + + if (rebuildBuffers) { + buildCommandBuffers (); + rebuildBuffers = false; + } + + if (++frameCount > 20) { + NotifyValueChanged ("fps", fps); + frameCount = 0; + } } #endregion + protected override void OnResize () { crow.ProcessResize (new Crow.Rectangle (0,0,(int)swapChain.Width, (int)swapChain.Height)); - createUIImage (); + initUISurface (); - DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsMain, descLayoutMain.Bindings[0]); + uiImage.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; + DescriptorSetWrites uboUpdate = new DescriptorSetWrites (pbrPipeline.dsMain, pbrPipeline.Layout.DescriptorSetLayouts[0].Bindings[5]); uboUpdate.Write (dev, uiImage.Descriptor); - updateMatrices (); + UpdateView (); if (frameBuffers != null) for (int i = 0; i < swapChain.ImageCount; ++i) @@ -196,7 +328,6 @@ namespace PbrSample { buildCommandBuffers (); } - #region Mouse and keyboard protected override void onMouseMove (double xPos, double yPos) { if (crow.ProcessMouseMove ((int)xPos, (int)yPos)) @@ -207,17 +338,18 @@ namespace PbrSample { if (MouseButton[0]) { camera.Rotate ((float)-diffX, (float)-diffY); } else if (MouseButton[1]) { - camera.Zoom ((float)diffY); - } + camera.SetZoom ((float)diffY); + } else + return; updateViewRequested = true; } - protected override void onMouseButtonDown (MouseButton button) { + protected override void onMouseButtonDown (Glfw.MouseButton button) { if (crow.ProcessMouseButtonDown ((Crow.MouseButton)button)) return; base.onMouseButtonDown (button); } - protected override void onMouseButtonUp (MouseButton button) { + protected override void onMouseButtonUp (Glfw.MouseButton button) { if (crow.ProcessMouseButtonUp ((Crow.MouseButton)button)) return; base.onMouseButtonUp (button); @@ -225,55 +357,108 @@ namespace PbrSample { protected override void onKeyDown (Key key, int scanCode, Modifier modifiers) { switch (key) { + case Key.F: + if (modifiers.HasFlag (Modifier.Shift)) { + pbrPipeline.envCube.debugFace--; + if (pbrPipeline.envCube.debugFace < 0) + pbrPipeline.envCube.debugFace = 5; + } else { + pbrPipeline.envCube.debugFace++; + if (pbrPipeline.envCube.debugFace > 5) + pbrPipeline.envCube.debugFace = 0; + } + queryUpdatePrefilCube = updateViewRequested = true; + break; + case Key.M: + if (modifiers.HasFlag (Modifier.Shift)) { + pbrPipeline.envCube.debugMip--; + if (pbrPipeline.envCube.debugMip < 0) + pbrPipeline.envCube.debugMip = (int)pbrPipeline.envCube.prefilterCube.CreateInfo.mipLevels - 1; + } else { + pbrPipeline.envCube.debugMip++; + if (pbrPipeline.envCube.debugMip > pbrPipeline.envCube.prefilterCube.CreateInfo.mipLevels) + pbrPipeline.envCube.debugMip = 0; + } + queryUpdatePrefilCube = updateViewRequested = true; + break; + case Key.P: + showDebugImg = !showDebugImg; + queryUpdatePrefilCube = updateViewRequested = true; + break; + case Key.Keypad0: + currentDebugView = DebugView.none; + break; + case Key.Keypad1: + currentDebugView = DebugView.color; + break; + case Key.Keypad2: + currentDebugView = DebugView.normal; + break; + case Key.Keypad3: + currentDebugView = DebugView.occlusion; + break; + case Key.Keypad4: + currentDebugView = DebugView.emissive; + break; + case Key.Keypad5: + currentDebugView = DebugView.metallic; + break; + case Key.Keypad6: + currentDebugView = DebugView.roughness; + break; case Key.Up: if (modifiers.HasFlag (Modifier.Shift)) - pbrPipeline.matrices.lightPos += new Vector4 (0, 0, 1, 0); + lightPos -= Vector4.UnitZ; else camera.Move (0, 0, 1); break; case Key.Down: if (modifiers.HasFlag (Modifier.Shift)) - pbrPipeline.matrices.lightPos += new Vector4 (0, 0, -1, 0); + lightPos += Vector4.UnitZ; else camera.Move (0, 0, -1); break; case Key.Left: if (modifiers.HasFlag (Modifier.Shift)) - pbrPipeline.matrices.lightPos += new Vector4 (1, 0, 0, 0); + lightPos -= Vector4.UnitX; else camera.Move (1, 0, 0); break; case Key.Right: if (modifiers.HasFlag (Modifier.Shift)) - pbrPipeline.matrices.lightPos += new Vector4 (-1, 0, 0, 0); + lightPos += Vector4.UnitX; else camera.Move (-1, 0, 0); break; case Key.PageUp: if (modifiers.HasFlag (Modifier.Shift)) - pbrPipeline.matrices.lightPos += new Vector4 (0, 1, 0, 0); + lightPos += Vector4.UnitY; else camera.Move (0, 1, 0); break; case Key.PageDown: if (modifiers.HasFlag (Modifier.Shift)) - pbrPipeline.matrices.lightPos += new Vector4 (0, -1, 0, 0); + lightPos -= Vector4.UnitY; else camera.Move (0, -1, 0); break; case Key.F1: + showUI = !showUI; + rebuildBuffers = true; + break; + case Key.F2: if (modifiers.HasFlag (Modifier.Shift)) pbrPipeline.matrices.exposure -= 0.3f; else pbrPipeline.matrices.exposure += 0.3f; break; - case Key.F2: + case Key.F3: if (modifiers.HasFlag (Modifier.Shift)) pbrPipeline.matrices.gamma -= 0.1f; else pbrPipeline.matrices.gamma += 0.1f; break; - case Key.F3: + case Key.F4: if (camera.Type == Camera.CamType.FirstPerson) camera.Type = Camera.CamType.LookAt; else @@ -288,32 +473,92 @@ namespace PbrSample { } #endregion + #region dispose protected override void Dispose (bool disposing) { if (disposing) { if (!isDisposed) { dev.WaitIdle (); + + isRunning = false; + for (int i = 0; i < swapChain.ImageCount; ++i) frameBuffers[i]?.Dispose (); pbrPipeline.Dispose (); uiPipeline.Dispose (); - descLayoutMain.Dispose (); - descriptorPool.Dispose (); - - uiImage.Dispose (); - - crow.Dispose (); - - vkvgDev.Dispose (); - + uiImage?.Dispose (); } } base.Dispose (disposing); } - - + #endregion } } + + + + + + + +// protected override void onKeyDown (Glfw.Key key, int scanCode, Modifier modifiers) { +// switch (key) { +// case Glfw.Key.F1: +// if (modifiers.HasFlag (Modifier.Shift)) +// pbrPipeline.matrices.exposure -= 0.3f; +// else +// pbrPipeline.matrices.exposure += 0.3f; +// break; +// case Glfw.Key.F2: +// if (modifiers.HasFlag (Modifier.Shift)) +// pbrPipeline.matrices.gamma -= 0.1f; +// else +// pbrPipeline.matrices.gamma += 0.1f; +// break; +// case Glfw.Key.F3: +// if (camera.Type == Camera.CamType.FirstPerson) +// camera.Type = Camera.CamType.LookAt; +// else +// camera.Type = Camera.CamType.FirstPerson; +// Console.WriteLine ($"camera type = {camera.Type}"); +// break; +// default: +// base.onKeyDown (key, scanCode, modifiers); +// return; +// } +// updateViewRequested = true; +// } +// #endregion + +// protected override void Dispose (bool disposing) { +// if (disposing) { +// if (!isDisposed) { +// dev.WaitIdle (); +// for (int i = 0; i < swapChain.ImageCount; ++i) +// frameBuffers[i]?.Dispose (); + +// pbrPipeline.Dispose (); + +// uiPipeline.Dispose (); +// descLayoutMain.Dispose (); +// descriptorPool.Dispose (); + +// uiImage.Dispose (); + +// crow.Dispose (); + +// vkvgDev.Dispose (); + + +// } +// } + +// base.Dispose (disposing); +// } + + +// } +//} diff --git a/samples/VkvgCrowTest/packages.config b/samples/VkvgCrowTest/packages.config index 5f9100e..0e162ba 100644 --- a/samples/VkvgCrowTest/packages.config +++ b/samples/VkvgCrowTest/packages.config @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="glTF2Loader" version="1.1.3-alpha" targetFramework="net471" /> - <package id="Newtonsoft.Json" version="12.0.1" targetFramework="net471" /> + <package id="Newtonsoft.Json" version="12.0.2" targetFramework="net471" /> <package id="System.Buffers" version="4.5.0" targetFramework="net471" /> <package id="System.Memory" version="4.5.2" targetFramework="net471" /> <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net471" /> <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net471" /> - <package id="Vulkan" version="0.1.2.5-alpha" targetFramework="net471" /> + <package id="Vulkan" version="0.1.2.6" targetFramework="net471" /> </packages>
\ No newline at end of file diff --git a/samples/VkvgCrowTest/shaders/filtercube.vert b/samples/VkvgCrowTest/shaders/filtercube.vert index 1226e28..34adf73 100644 --- a/samples/VkvgCrowTest/shaders/filtercube.vert +++ b/samples/VkvgCrowTest/shaders/filtercube.vert @@ -15,5 +15,6 @@ out gl_PerVertex { void main() { outUVW = inPos; - gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0); + //outUVW.y = -outUVW.y; + gl_Position = pushConsts.mvp * vec4(inPos.xyz, 1.0); } diff --git a/samples/VkvgCrowTest/shaders/pbr.vert b/samples/VkvgCrowTest/shaders/pbr.vert index 03d24da..76ee24b 100644 --- a/samples/VkvgCrowTest/shaders/pbr.vert +++ b/samples/VkvgCrowTest/shaders/pbr.vert @@ -4,24 +4,22 @@ layout (location = 0) in vec3 inPos; layout (location = 1) in vec3 inNormal; layout (location = 2) in vec2 inUV0; layout (location = 3) in vec2 inUV1; -layout (location = 4) in vec4 inJoint0; -layout (location = 5) in vec4 inWeight0; -layout (set = 0, binding = 0) uniform UBO -{ - mat4 projection; - mat4 model; - mat4 view; - vec3 camPos; +layout (set = 0, binding = 0) uniform UBO { + mat4 projection; + mat4 model; + mat4 view; + vec4 camPos; + vec4 lightDir; + float exposure; + float gamma; + float prefilteredCubeMipLevels; + float scaleIBLAmbient; } ubo; -#define MAX_NUM_JOINTS 128 - -layout (set = 2, binding = 0) uniform UBONode { - mat4 matrix; - mat4 jointMatrix[MAX_NUM_JOINTS]; - float jointCount; -} node; +layout(push_constant) uniform PushConsts { + mat4 model; +} pc; layout (location = 0) out vec3 outWorldPos; layout (location = 1) out vec3 outNormal; @@ -30,29 +28,17 @@ layout (location = 3) out vec2 outUV1; out gl_PerVertex { - vec4 gl_Position; + vec4 gl_Position; }; void main() -{ - vec4 locPos; - if (node.jointCount > 0.0) { - // Mesh is skinned - mat4 skinMat = - inWeight0.x * node.jointMatrix[int(inJoint0.x)] + - inWeight0.y * node.jointMatrix[int(inJoint0.y)] + - inWeight0.z * node.jointMatrix[int(inJoint0.z)] + - inWeight0.w * node.jointMatrix[int(inJoint0.w)]; +{ + vec4 locPos = ubo.model * pc.model * vec4(inPos, 1.0); + outNormal = normalize(transpose(inverse(mat3(ubo.model * pc.model))) * inNormal); - locPos = ubo.model * node.matrix * skinMat * vec4(inPos, 1.0); - outNormal = normalize(transpose(inverse(mat3(ubo.model * node.matrix * skinMat))) * inNormal); - } else { - locPos = ubo.model * node.matrix * vec4(inPos, 1.0); - outNormal = normalize(transpose(inverse(mat3(ubo.model * node.matrix))) * inNormal); - } - locPos.y = -locPos.y; - outWorldPos = locPos.xyz / locPos.w; - outUV0 = inUV0; - outUV1 = inUV1; - gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0); + //locPos.y = -locPos.y; + outWorldPos = locPos.xyz;// / locPos.w; + outUV0 = inUV0; + outUV1 = inUV1; + gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0); } diff --git a/samples/VkvgCrowTest/shaders/pbr_khr.frag b/samples/VkvgCrowTest/shaders/pbr_khr.frag index bdf9fce..9564e00 100644 --- a/samples/VkvgCrowTest/shaders/pbr_khr.frag +++ b/samples/VkvgCrowTest/shaders/pbr_khr.frag @@ -3,34 +3,63 @@ // Supports both metallic roughness and specular glossiness inputs #version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +#define MANUAL_SRGB 0 +#define DEBUG 0 + +struct Material { + vec4 baseColorFactor; + vec4 emissiveFactor; + vec4 diffuseFactor; + vec4 specularFactor; + float workflow; + uint tex0; + uint tex1; + float metallicFactor; + float roughnessFactor; + float alphaMask; + float alphaMaskCutoff; + int pad0; +}; + +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; -// Scene bindings - layout (set = 0, binding = 0) uniform UBO { - mat4 projection; - mat4 model; - mat4 view; - vec3 camPos; + mat4 projection; + mat4 model; + mat4 view; + vec4 camPos; + vec4 lightDir; + float exposure; + float gamma; + float prefilteredCubeMipLevels; + float scaleIBLAmbient; +#if DEBUG + float debugViewInputs; + float debugViewEquation; +#endif } ubo; -layout (set = 0, binding = 1) uniform UBOParams { - vec4 lightDir; - float exposure; - float gamma; - float prefilteredCubeMipLevels; - float scaleIBLAmbient; - float debugViewInputs; - float debugViewEquation; -} uboParams; +layout (set = 0, binding = 4) uniform UBOMaterials { + Material materials[16]; +}; -layout (set = 0, binding = 2) uniform samplerCube samplerIrradiance; -layout (set = 0, binding = 3) uniform samplerCube prefilteredMap; -layout (set = 0, binding = 4) uniform sampler2D samplerBRDFLUT; +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 @@ -40,22 +69,11 @@ 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 (push_constant) uniform Material { - vec4 baseColorFactor; - vec4 emissiveFactor; - vec4 diffuseFactor; - vec4 specularFactor; - float workflow; - int baseColorTextureSet; - int physicalDescriptorTextureSet; - int normalTextureSet; - int occlusionTextureSet; - int emissiveTextureSet; - float metallicFactor; - float roughnessFactor; - float alphaMask; - float alphaMaskCutoff; -} material; + +layout (push_constant) uniform PushCsts { + layout(offset = 64) + int materialIdx; +}; layout (location = 0) out vec4 outColor; @@ -64,80 +82,84 @@ layout (location = 0) out vec4 outColor; // of the shading terms, outlined in the Readme.MD Appendix. struct PBRInfo { - float NdotL; // cos angle between normal and light direction - float NdotV; // cos angle between normal and view direction - float NdotH; // cos angle between normal and half vector - float LdotH; // cos angle between light direction and half vector - float VdotH; // cos angle between view direction and half vector - float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) - float metalness; // metallic value at the surface - vec3 reflectance0; // full reflectance color (normal incidence angle) - vec3 reflectance90; // reflectance color at grazing angle - float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) - vec3 diffuseColor; // color contribution from diffuse lighting - vec3 specularColor; // color contribution from specular lighting + float NdotL; // cos angle between normal and light direction + float NdotV; // cos angle between normal and view direction + float NdotH; // cos angle between normal and half vector + float LdotH; // cos angle between light direction and half vector + float VdotH; // cos angle between view direction and half vector + float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) + float metalness; // metallic value at the surface + vec3 reflectance0; // full reflectance color (normal incidence angle) + vec3 reflectance90; // reflectance color at grazing angle + float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) + vec3 diffuseColor; // color contribution from diffuse lighting + vec3 specularColor; // color contribution from specular lighting }; const float M_PI = 3.141592653589793; const float c_MinRoughness = 0.04; -const float PBR_WORKFLOW_METALLIC_ROUGHNESS = 0.0; -const float PBR_WORKFLOW_SPECULAR_GLOSINESS = 1.0f; - -#define MANUAL_SRGB 1 +const float PBR_WORKFLOW_METALLIC_ROUGHNESS = 1.0; +const float PBR_WORKFLOW_SPECULAR_GLOSINESS = 2.0f; vec3 Uncharted2Tonemap(vec3 color) { - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - float W = 11.2; - return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; + float A = 0.15; + float B = 0.50; + float C = 0.10; + float D = 0.20; + float E = 0.02; + float F = 0.30; + float W = 11.2; + return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; } vec4 tonemap(vec4 color) { - vec3 outcol = Uncharted2Tonemap(color.rgb * uboParams.exposure); - outcol = outcol * (1.0f / Uncharted2Tonemap(vec3(11.2f))); - return vec4(pow(outcol, vec3(1.0f / uboParams.gamma)), color.a); + vec3 outcol = Uncharted2Tonemap(color.rgb * ubo.exposure); + outcol = outcol * (1.0f / Uncharted2Tonemap(vec3(11.2f))); + return vec4(pow(outcol, vec3(1.0f / ubo.gamma)), color.a); } 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 + #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() { - // Perturb normal, see http://www.thetenthplanet.de/archives/1180 - vec3 tangentNormal = texture(normalMap, material.normalTextureSet == 0 ? inUV0 : inUV1).xyz * 2.0 - 1.0; - - vec3 q1 = dFdx(inWorldPos); - vec3 q2 = dFdy(inWorldPos); - vec2 st1 = dFdx(inUV0); - vec2 st2 = dFdy(inUV0); + vec3 tangentNormal; + // Perturb normal, see http://www.thetenthplanet.de/archives/1180 + if ((materials[materialIdx].tex0 & MAP_NORMAL) == MAP_NORMAL) + tangentNormal = texture(normalMap, inUV0).xyz * 2.0 - 1.0; + else if ((materials[materialIdx].tex1 & MAP_NORMAL) == MAP_NORMAL) + tangentNormal = texture(normalMap, inUV1).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); + 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); + return normalize(TBN * tangentNormal); } // Calculation of the lighting contribution from an optional Image Based Light source. @@ -145,22 +167,22 @@ vec3 getNormal() // See our README.md on Environment Maps [3] for additional discussion. vec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection) { - float lod = (pbrInputs.perceptualRoughness * uboParams.prefilteredCubeMipLevels); - // retrieve a scale and bias to F0. See [1], Figure 3 - vec3 brdf = (texture(samplerBRDFLUT, vec2(pbrInputs.NdotV, 1.0 - pbrInputs.perceptualRoughness))).rgb; - vec3 diffuseLight = SRGBtoLINEAR(tonemap(texture(samplerIrradiance, n))).rgb; + float lod = (pbrInputs.perceptualRoughness * ubo.prefilteredCubeMipLevels); + // retrieve a scale and bias to F0. See [1], Figure 3 + vec3 brdf = (texture(samplerBRDFLUT, vec2(pbrInputs.NdotV, 1.0 - pbrInputs.perceptualRoughness))).rgb; + vec3 diffuseLight = SRGBtoLINEAR(tonemap(texture(samplerIrradiance, n))).rgb; - vec3 specularLight = SRGBtoLINEAR(tonemap(textureLod(prefilteredMap, reflection, lod))).rgb; + vec3 specularLight = SRGBtoLINEAR(tonemap(textureLod(prefilteredMap, reflection, lod))).rgb; - vec3 diffuse = diffuseLight * pbrInputs.diffuseColor; - vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y); + vec3 diffuse = diffuseLight * pbrInputs.diffuseColor; + vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y); - // For presentation, this allows us to disable IBL terms - // For presentation, this allows us to disable IBL terms - diffuse *= uboParams.scaleIBLAmbient; - specular *= uboParams.scaleIBLAmbient; + // For presentation, this allows us to disable IBL terms + // For presentation, this allows us to disable IBL terms + diffuse *= ubo.scaleIBLAmbient; + specular *= ubo.scaleIBLAmbient; - return diffuse + specular; + return diffuse + specular; } // Basic Lambertian diffuse @@ -168,14 +190,14 @@ vec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection) // See also [1], Equation 1 vec3 diffuse(PBRInfo pbrInputs) { - return pbrInputs.diffuseColor / M_PI; + return pbrInputs.diffuseColor / M_PI; } // The following equation models the Fresnel reflectance term of the spec equation (aka F()) // Implementation of fresnel from [4], Equation 15 vec3 specularReflection(PBRInfo pbrInputs) { - return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); + return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); } // This calculates the specular geometric attenuation (aka G()), @@ -184,13 +206,13 @@ vec3 specularReflection(PBRInfo pbrInputs) // alphaRoughness as input as originally proposed in [2]. float geometricOcclusion(PBRInfo pbrInputs) { - float NdotL = pbrInputs.NdotL; - float NdotV = pbrInputs.NdotV; - float r = pbrInputs.alphaRoughness; + float NdotL = pbrInputs.NdotL; + float NdotV = pbrInputs.NdotV; + float r = pbrInputs.alphaRoughness; - float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); - float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); - return attenuationL * attenuationV; + float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); + float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); + return attenuationL * attenuationV; } // The following equation(s) model the distribution of microfacet normals across the area being drawn (aka D()) @@ -198,218 +220,241 @@ float geometricOcclusion(PBRInfo pbrInputs) // Follows the distribution function recommended in the SIGGRAPH 2013 course notes from EPIC Games [1], Equation 3. float microfacetDistribution(PBRInfo pbrInputs) { - float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness; - float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0; - return roughnessSq / (M_PI * f * f); + float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness; + float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0; + return roughnessSq / (M_PI * f * f); } // 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 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); } void main() { - float perceptualRoughness; - float metallic; - vec3 diffuseColor; - vec4 baseColor; - - vec3 f0 = vec3(0.04); - - if (material.alphaMask == 1.0f) { - if (material.baseColorTextureSet > -1) { - baseColor = SRGBtoLINEAR(texture(colorMap, material.baseColorTextureSet == 0 ? inUV0 : inUV1)) * material.baseColorFactor; - } else { - baseColor = material.baseColorFactor; - } - if (baseColor.a < material.alphaMaskCutoff) { - discard; - } - } - - if (material.workflow == PBR_WORKFLOW_METALLIC_ROUGHNESS) { - // Metallic and Roughness material properties are packed together - // In glTF, these factors can be specified by fixed scalar values - // or from a metallic-roughness map - perceptualRoughness = material.roughnessFactor; - metallic = material.metallicFactor; - if (material.physicalDescriptorTextureSet > -1) { - // 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 - vec4 mrSample = texture(physicalDescriptorMap, material.physicalDescriptorTextureSet == 0 ? inUV0 : inUV1); - perceptualRoughness = mrSample.g * perceptualRoughness; - metallic = mrSample.b * metallic; - } else { - perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0); - metallic = clamp(metallic, 0.0, 1.0); - } - // Roughness is authored as perceptual roughness; as is convention, - // convert to material roughness by squaring the perceptual roughness [2]. - - // The albedo may be defined from a base texture or a flat color - if (material.baseColorTextureSet > -1) { - baseColor = SRGBtoLINEAR(texture(colorMap, material.baseColorTextureSet == 0 ? inUV0 : inUV1)) * material.baseColorFactor; - } else { - baseColor = material.baseColorFactor; - } - } - - if (material.workflow == PBR_WORKFLOW_SPECULAR_GLOSINESS) { - // Values from specular glossiness workflow are converted to metallic roughness - if (material.physicalDescriptorTextureSet > -1) { - perceptualRoughness = 1.0 - texture(physicalDescriptorMap, material.physicalDescriptorTextureSet == 0 ? inUV0 : inUV1).a; - } else { - perceptualRoughness = 0.0; - } + float perceptualRoughness; + float metallic; + vec3 diffuseColor; + vec4 baseColor; - const float epsilon = 1e-6; + vec3 f0 = vec3(0.04); + + 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(physicalDescriptorMap, inUV0).g; + metallic *= texture(physicalDescriptorMap, inUV0).b; + }else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){ + perceptualRoughness *= texture(physicalDescriptorMap, inUV1).g; + metallic *= texture(physicalDescriptorMap, inUV1).b; + } + perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0); + metallic = clamp(metallic, 0.0, 1.0); - vec4 diffuse = SRGBtoLINEAR(texture(colorMap, inUV0)); - vec3 specular = SRGBtoLINEAR(texture(physicalDescriptorMap, inUV0)).rgb; + // The albedo may be defined from a base texture or a flat color + if ((materials[materialIdx].tex0 & MAP_COLOR) == MAP_COLOR) + baseColor *= SRGBtoLINEAR(texture(colorMap, inUV0)); + else if ((materials[materialIdx].tex1 & MAP_COLOR) == MAP_COLOR) + baseColor *= SRGBtoLINEAR(texture(colorMap, inUV1)); + } + + if (materials[materialIdx].alphaMask == 1.0f) { + if (baseColor.a < materials[materialIdx].alphaMaskCutoff) + discard; + } - float maxSpecular = max(max(specular.r, specular.g), specular.b); + 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(physicalDescriptorMap, inUV0).a; + else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS) + perceptualRoughness = 1.0 - texture(physicalDescriptorMap, inUV1).a; + else + perceptualRoughness = 0.0; - // Convert metallic value from specular glossiness inputs - metallic = convertMetallic(diffuse.rgb, specular, maxSpecular); + const float epsilon = 1e-6; - vec3 baseColorDiffusePart = diffuse.rgb * ((1.0 - maxSpecular) / (1 - c_MinRoughness) / max(1 - metallic, epsilon)) * material.diffuseFactor.rgb; - vec3 baseColorSpecularPart = specular - (vec3(c_MinRoughness) * (1 - metallic) * (1 / max(metallic, epsilon))) * material.specularFactor.rgb; - baseColor = vec4(mix(baseColorDiffusePart, baseColorSpecularPart, metallic * metallic), diffuse.a); + vec4 diffuse = SRGBtoLINEAR(texture(colorMap, inUV0)); + vec3 specular = SRGBtoLINEAR(texture(physicalDescriptorMap, inUV0)).rgb; - } + float maxSpecular = max(max(specular.r, specular.g), specular.b); - diffuseColor = baseColor.rgb * (vec3(1.0) - f0); - diffuseColor *= 1.0 - metallic; - - float alphaRoughness = perceptualRoughness * perceptualRoughness; + // Convert metallic value from specular glossiness inputs + metallic = convertMetallic(diffuse.rgb, specular, maxSpecular); - vec3 specularColor = mix(f0, baseColor.rgb, metallic); + 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); - // Compute reflectance. - float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); + } - // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect. - // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%. - float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); - vec3 specularEnvironmentR0 = specularColor.rgb; - vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90; + diffuseColor = baseColor.rgb * (vec3(1.0) - f0); + diffuseColor *= 1.0 - metallic; + + float alphaRoughness = perceptualRoughness * perceptualRoughness; - vec3 n = (material.normalTextureSet > -1) ? getNormal() : normalize(inNormal); - vec3 v = normalize(ubo.camPos - inWorldPos); // Vector from surface point to camera - vec3 l = normalize(uboParams.lightDir.xyz); // Vector from surface point to light - vec3 h = normalize(l+v); // Half vector between both l and v - vec3 reflection = -normalize(reflect(v, n)); - reflection.y *= -1.0f; + vec3 specularColor = mix(f0, baseColor.rgb, metallic); - float NdotL = clamp(dot(n, l), 0.001, 1.0); - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - float NdotH = clamp(dot(n, h), 0.0, 1.0); - float LdotH = clamp(dot(l, h), 0.0, 1.0); - float VdotH = clamp(dot(v, h), 0.0, 1.0); + // Compute reflectance. + float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); - PBRInfo pbrInputs = PBRInfo( - NdotL, - NdotV, - NdotH, - LdotH, - VdotH, - perceptualRoughness, - metallic, - specularEnvironmentR0, - specularEnvironmentR90, - alphaRoughness, - diffuseColor, - specularColor - ); + // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect. + // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%. + float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); + vec3 specularEnvironmentR0 = specularColor.rgb; + vec3 specularEnvironmentR90 = vec3(1.0) * reflectance90; - // Calculate the shading terms for the microfacet specular shading model - vec3 F = specularReflection(pbrInputs); - float G = geometricOcclusion(pbrInputs); - float D = microfacetDistribution(pbrInputs); + vec3 n = getNormal(); + vec3 v = normalize(ubo.camPos.xyz - inWorldPos); // Vector from surface point to camera + vec3 l = normalize(ubo.lightDir.xyz); // Vector from surface point to light + vec3 h = normalize(l+v); // Half vector between both l and v + vec3 reflection = -normalize(reflect(v, n)); + reflection.y *= -1.0f; - const vec3 u_LightColor = vec3(1.0); + float NdotL = clamp(dot(n, l), 0.001, 1.0); + float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); + float NdotH = clamp(dot(n, h), 0.0, 1.0); + float LdotH = clamp(dot(l, h), 0.0, 1.0); + float VdotH = clamp(dot(v, h), 0.0, 1.0); - // Calculation of analytical lighting contribution - vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); - vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV); - // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law) - vec3 color = NdotL * u_LightColor * (diffuseContrib + specContrib); + PBRInfo pbrInputs = PBRInfo( + NdotL, + NdotV, + NdotH, + LdotH, + VdotH, + perceptualRoughness, + metallic, + specularEnvironmentR0, + specularEnvironmentR90, + alphaRoughness, + diffuseColor, + specularColor + ); - // Calculate lighting contribution from image based lighting source (IBL) - color += getIBLContribution(pbrInputs, n, reflection); + // Calculate the shading terms for the microfacet specular shading model + vec3 F = specularReflection(pbrInputs); + float G = geometricOcclusion(pbrInputs); + float D = microfacetDistribution(pbrInputs); - const float u_OcclusionStrength = 1.0f; - // Apply optional PBR terms for additional (optional) shading - if (material.occlusionTextureSet > -1) { - float ao = texture(aoMap, (material.occlusionTextureSet == 0 ? inUV0 : inUV1)).r; - color = mix(color, color * ao, u_OcclusionStrength); - } + const vec3 u_LightColor = vec3(1.0); - const float u_EmissiveFactor = 1.0f; - if (material.emissiveTextureSet > -1) { - vec3 emissive = SRGBtoLINEAR(texture(emissiveMap, material.emissiveTextureSet == 0 ? inUV0 : inUV1)).rgb * u_EmissiveFactor; - color += emissive; - } - - outColor = vec4(color, baseColor.a); + // Calculation of analytical lighting contribution + vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); + vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV); + // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law) + vec3 color = NdotL * u_LightColor * (diffuseContrib + specContrib); - // Shader inputs debug visualization - if (uboParams.debugViewInputs > 0.0) { - int index = int(uboParams.debugViewInputs); - switch (index) { - case 1: - outColor.rgba = material.baseColorTextureSet > -1 ? texture(colorMap, material.baseColorTextureSet == 0 ? inUV0 : inUV1) : vec4(1.0f); - break; - case 2: - outColor.rgb = (material.normalTextureSet > -1) ? texture(normalMap, material.normalTextureSet == 0 ? inUV0 : inUV1).rgb : normalize(inNormal); - break; - case 3: - outColor.rgb = (material.occlusionTextureSet > -1) ? texture(aoMap, material.occlusionTextureSet == 0 ? inUV0 : inUV1).rrr : vec3(0.0f); - break; - case 4: - outColor.rgb = (material.emissiveTextureSet > -1) ? texture(emissiveMap, material.emissiveTextureSet == 0 ? inUV0 : inUV1).rgb : vec3(0.0f); - break; - case 5: - outColor.rgb = texture(physicalDescriptorMap, inUV0).bbb; - break; - case 6: - outColor.rgb = texture(physicalDescriptorMap, inUV0).ggg; - break; - } - outColor = SRGBtoLINEAR(outColor); - } + // Calculate lighting contribution from image based lighting source (IBL) + color += getIBLContribution(pbrInputs, n, reflection); - // PBR equation debug visualization - // "none", "Diff (l,n)", "F (l,h)", "G (l,v,h)", "D (h)", "Specular" - if (uboParams.debugViewEquation > 0.0) { - int index = int(uboParams.debugViewEquation); - switch (index) { - case 1: - outColor.rgb = diffuseContrib; - break; - case 2: - outColor.rgb = F; - break; - case 3: - outColor.rgb = vec3(G); - break; - case 4: - outColor.rgb = vec3(D); - break; - case 5: - outColor.rgb = specContrib; - break; - } - } + const float u_OcclusionStrength = 1.0f; + const float u_EmissiveFactor = 1.0f; + + // Apply optional PBR terms for additional (optional) shading + if ((materials[materialIdx].tex0 & MAP_AO) == MAP_AO) + color = mix(color, color * texture(aoMap, inUV0).r, u_OcclusionStrength); + else if ((materials[materialIdx].tex1 & MAP_AO) == MAP_AO) + color = mix(color, color * texture(aoMap, inUV1).r, u_OcclusionStrength); + + if ((materials[materialIdx].tex0 & MAP_EMISSIVE) == MAP_EMISSIVE) + color += SRGBtoLINEAR(texture(emissiveMap, inUV0)).rgb * u_EmissiveFactor; + else if ((materials[materialIdx].tex1 & MAP_EMISSIVE) == MAP_EMISSIVE) + color += SRGBtoLINEAR(texture(emissiveMap, inUV1)).rgb * u_EmissiveFactor; + + outColor = vec4(color, baseColor.a); +#if DEBUG + // Shader inputs debug visualization + if (ubo.debugViewInputs > 0.0) { + int index = int(ubo.debugViewInputs); + switch (index) { + case 1: + if ((materials[materialIdx].tex0 & MAP_COLOR) == MAP_COLOR) + outColor.rgba = texture(colorMap, inUV0); + else if ((materials[materialIdx].tex1 & MAP_COLOR) == MAP_COLOR) + outColor.rgba = texture(colorMap, inUV1); + else + outColor.rgba = vec4(1.0f); + break; + case 2: + if ((materials[materialIdx].tex0 & MAP_NORMAL) == MAP_NORMAL) + outColor.rgb = texture(normalMap, inUV0).rgb; + else if ((materials[materialIdx].tex1 & MAP_NORMAL) == MAP_NORMAL) + outColor.rgb = texture(normalMap, inUV1).rgb; + else + outColor.rgb = normalize(inNormal); + break; + case 3: + if ((materials[materialIdx].tex0 & MAP_AO) == MAP_AO) + outColor.rgb = texture(aoMap, inUV0).rrr; + else if ((materials[materialIdx].tex1 & MAP_AO) == MAP_AO) + outColor.rgb = texture(aoMap, inUV1).rrr; + else + outColor.rgb = vec3(0); + break; + case 4: + if ((materials[materialIdx].tex0 & MAP_EMISSIVE) == MAP_EMISSIVE) + outColor.rgb = texture(emissiveMap, inUV0).rgb; + else if ((materials[materialIdx].tex1 & MAP_EMISSIVE) == MAP_EMISSIVE) + outColor.rgb = texture(emissiveMap, inUV1).rgb; + else + outColor.rgb = vec3(0); + break; + case 5: + if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS) + outColor.rgb = texture(physicalDescriptorMap, inUV0).bbb; + else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS) + outColor.rgb = texture(physicalDescriptorMap, inUV1).bbb; + else + outColor.rgb = vec3(0); + break; + case 6: + if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS) + outColor.rgb = texture(physicalDescriptorMap, inUV0).ggg; + else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS) + outColor.rgb = texture(physicalDescriptorMap, inUV1).ggg; + else + outColor.rgb = vec3(0); + break; + } + outColor = SRGBtoLINEAR(outColor); + } + // PBR equation debug visualization + // "none", "Diff (l,n)", "F (l,h)", "G (l,v,h)", "D (h)", "Specular" + if (ubo.debugViewEquation > 0.0) { + int index = int(ubo.debugViewEquation); + switch (index) { + case 1: + outColor.rgb = diffuseContrib; + break; + case 2: + outColor.rgb = F; + break; + case 3: + outColor.rgb = vec3(G); + break; + case 4: + outColor.rgb = vec3(D); + break; + case 5: + outColor.rgb = specContrib; + break; + } + } +#endif } diff --git a/samples/VkvgCrowTest/shaders/simpletexture.frag b/samples/VkvgCrowTest/shaders/simpletexture.frag index a081876..d5bcf79 100644 --- a/samples/VkvgCrowTest/shaders/simpletexture.frag +++ b/samples/VkvgCrowTest/shaders/simpletexture.frag @@ -3,7 +3,7 @@ #extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_shading_language_420pack : enable -layout (set = 0, binding = 0) uniform sampler2D samplerColor; +layout (set = 0, binding = 5) uniform sampler2D samplerColor; layout (location = 0) in vec2 inUV; diff --git a/samples/VkvgCrowTest/shaders/skybox.frag b/samples/VkvgCrowTest/shaders/skybox.frag index fa10f82..57a7dbe 100644 --- a/samples/VkvgCrowTest/shaders/skybox.frag +++ b/samples/VkvgCrowTest/shaders/skybox.frag @@ -1,15 +1,60 @@ #version 450 -#extension GL_ARB_separate_shader_objects : enable -#extension GL_ARB_shading_language_420pack : enable +layout (binding = 2) uniform samplerCube samplerEnv; -layout (binding = 1) uniform samplerCube skybox; +layout (set = 0, location = 0) in vec3 inUVW; -layout (location = 0) in vec3 TexCoords; +layout (set = 0, location = 0) out vec4 outColor; -layout (location = 0) out vec4 outFragColor; +layout (set = 0, binding = 0) uniform UBO { + mat4 projection; + mat4 model; + mat4 view; + vec3 camPos; + vec4 lightDir; + float exposure; + float gamma; +} ubo; -void main() +// From http://filmicworlds.com/blog/filmic-tonemapping-operators/ +vec3 Uncharted2Tonemap(vec3 color) +{ + float A = 0.15; + float B = 0.50; + float C = 0.10; + float D = 0.20; + float E = 0.02; + float F = 0.30; + float W = 11.2; + return ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; +} + +vec4 tonemap(vec4 color) { - outFragColor = texture(skybox, TexCoords); + vec3 outcol = Uncharted2Tonemap(color.rgb * ubo.exposure); + outcol = outcol * (1.0f / Uncharted2Tonemap(vec3(11.2f))); + return vec4(pow(outcol, vec3(1.0f / ubo.gamma)), color.a); } + +#define MANUAL_SRGB 1 + +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 +} + +void main() +{ + vec3 color = SRGBtoLINEAR(tonemap(textureLod(samplerEnv, inUVW, 1.5))).rgb; + outColor = vec4(color * 1.0, 1.0); +}
\ No newline at end of file diff --git a/samples/VkvgCrowTest/shaders/skybox.vert b/samples/VkvgCrowTest/shaders/skybox.vert index 1925ec9..22e285e 100644 --- a/samples/VkvgCrowTest/shaders/skybox.vert +++ b/samples/VkvgCrowTest/shaders/skybox.vert @@ -4,27 +4,24 @@ #extension GL_ARB_shading_language_420pack : enable layout (location = 0) in vec3 inPos; -layout (location = 1) in vec2 inUV; - -layout (location = 0) out vec3 outUVW; layout (binding = 0) uniform UBO { mat4 projection; - mat4 view; mat4 model; - vec4 lightPos; - float gamma; - float exposure; + mat4 view; } ubo; +layout (location = 0) out vec3 outUVW; + out gl_PerVertex { - vec4 gl_Position; + vec4 gl_Position; }; -void main() +void main() { outUVW = inPos; - gl_Position = ubo.projection * ubo.view * vec4(inPos, 1.0); + outUVW.y = -outUVW.y; + gl_Position = ubo.projection * mat4(mat3(ubo.view)) * vec4(inPos, 1.0); } diff --git a/samples/VkvgCrowTest/ui/fps.crow b/samples/VkvgCrowTest/ui/fps.crow index 8b6b1f0..bf73460 100755 --- a/samples/VkvgCrowTest/ui/fps.crow +++ b/samples/VkvgCrowTest/ui/fps.crow @@ -1,21 +1,31 @@ <?xml version="1.0"?> -<VerticalStack Left="10" Top="100" Width="30%" Height="Fit" Spacing="2" Background="0.8,0.3,0.3,0.5" Margin="20"> - <HorizontalStack Height="Fit"> - <Label Text="Fps:" Width="80" Background="SteelBlue"/> - <Label Text="{fps}" Background="0.8,0.3,0.3,0.5" Margin="20"/> - </HorizontalStack> - <HorizontalStack Height="Fit"> - <Label Text="Gamma:" Width="80" Background="SteelBlue"/> - <Slider Height="20" Value="{²Gamma}" Maximum="10.0" SmallIncrement="0.1" LargeIncrement="1.0"/> - <Label Text="{Gamma}" Width="40" TextAlignment="Right"/> - </HorizontalStack> - <HorizontalStack Height="Fit"> - <Label Text="Exposure:" Width="80" Background="SteelBlue"/> - <Slider Height="20" Value="{²Exposure}" Maximum="10.0" SmallIncrement="0.1" LargeIncrement="1.0"/> - <Label Text="{Exposure}" Width="40" TextAlignment="Right"/> - </HorizontalStack> -</VerticalStack> -<!--<Window Caption="Showcase" Height="30%" Width="20%" Top="10" Left="10">--> -<!--</Window>--> -<!--<Label Text="{fps}" Background="SteelBlue" Margin="0" Font="mono,20"/>--> +<Window Left="10" Top="100" Width="40%" Height="80%" CornerRadius="10"> + <VerticalStack Spacing="1" Margin="10" CacheEnabled="true"> + <HorizontalStack Height="Fit"> + <Label Text="Fps:" Width="80"/> + <Label Text="{fps}" Width="Stretched" TextAlignment="Center"/> + </HorizontalStack> + <HorizontalStack Height="Fit" > + <Label Text="Exposure:" Width="80"/> + <Slider Height="10" Value="{²Exposure}" Maximum="10.0" SmallIncrement="0.1" LargeIncrement="1.0"/> + <Label Text="{Exposure}" Width="40" TextAlignment="Right" /> + </HorizontalStack> + <HorizontalStack Height="Fit"> + <Label Text="Gamma:" Width="80" /> + <Slider Height="10" Value="{²Gamma}" Maximum="10.0" SmallIncrement="0.1" LargeIncrement="1.0"/> + <Label Text="{Gamma}" Width="40" TextAlignment="Right" /> + </HorizontalStack> + <Spinner Value="{²Gamma}" Maximum="10.0" SmallIncrement="0.1" LargeIncrement="1.0" Width="60"/> + <Image Margin="1" Path="/mnt/devel/gts/vk.net/crow/Images/crow0.svg" Width="100" Height="100" Background="White" MouseEnter="{Background=Blue}" MouseLeave="{Background=White}"/> + <Image Margin="1" Path="/mnt/devel/gts/vk.net/crow/Images/crow.png" Width="128" Height="128" Background="White" MouseEnter="{Background=Blue}" MouseLeave="{Background=White}"/> + <Image Margin="1" Path="/mnt/devel/gts/vk.net/crow/Images/crow.png" Width="200" Height="200" Background="White" MouseEnter="{Background=Blue}" MouseLeave="{Background=White}"/> + <Expandable> + <Widget Height="100" Width="100" MouseEnter="{Background=Red}" MouseLeave="{Background=Transparent}"/> + </Expandable> + <Popper> + <Image Margin="1" Path="/mnt/devel/gts/vk.net/crow/Images/crow.png" Width="64" Height="64" MouseEnter="{Background=Red}" MouseLeave="{Background=Transparent}"/> + </Popper> +<!-- <ColorPicker Width="300" Height="300"/>--> + </VerticalStack> +</Window> diff --git a/samples/VkvgCrowTest/ui/perfMeasures.crow b/samples/VkvgCrowTest/ui/perfMeasures.crow new file mode 100644 index 0000000..14295f0 --- /dev/null +++ b/samples/VkvgCrowTest/ui/perfMeasures.crow @@ -0,0 +1,5 @@ +<?xml version="1.0"?> +<Window Focusable="true" Caption="Measures" Width="30%" Height="300" MinimumSize="100,100"> + <ListBox Data="{PerfMeasures}" + ItemTemplate="#vkvgCrowTest.perfMsr.crow"/> +</Window> diff --git a/samples/VkvgCrowTest/ui/perfMsr.crow b/samples/VkvgCrowTest/ui/perfMsr.crow new file mode 100755 index 0000000..c579c4e --- /dev/null +++ b/samples/VkvgCrowTest/ui/perfMsr.crow @@ -0,0 +1,36 @@ +<?xml version="1.0"?> + + <VerticalStack Spacing="1" Height="Fit" Width="Stretched"> + <HorizontalStack Background="DarkSlateGrey"> + <Label Text="{Name}" Width="Stretched" Font="doid bold, 10" Margin="2"/> + <Button Caption="Reset" MouseClick="onResetClick" Height="Fit"/> + </HorizontalStack> + <HorizontalStack> + <Label Text="Current:" Style="FpsLabel"/> + <Label Text="{current}" Style="FpsDisp"/> + </HorizontalStack> + <HorizontalStack> + <Label Text="Minimum:" Style="FpsLabel"/> + <Label Text="{minimum}" Style="FpsDisp"/> + </HorizontalStack> + <HorizontalStack> + <Label Text="Mean:" Style="FpsLabel"/> + <Label Text="{mean}" Style="FpsDisp"/> + </HorizontalStack> + <HorizontalStack> + <Label Text="Maximum:" Style="FpsLabel"/> + <Label Text="{maximum}" Style="FpsDisp"/> + </HorizontalStack> +<!-- <Border Foreground="White" Width="Stretched" Height="60"> + <Trend Background="Black" NewValue="{current}" Minimum="0" Maximum="10"/> + </Border> + <HorizontalStack> + <Label Text="Total:" Style="FpsLabel"/> + <Label Text="{total}" Style="FpsDisp"/> + </HorizontalStack> + <HorizontalStack> + <Label Text="Cpt:" Style="FpsLabel"/> + <Label Text="{cptMeasures}" Style="FpsDisp"/> + </HorizontalStack>--> + </VerticalStack> + diff --git a/samples/data/models/shadow.gltf b/samples/data/models/shadow.gltf new file mode 100644 index 0000000..62b6133 --- /dev/null +++ b/samples/data/models/shadow.gltf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a516145efb32792dbf6422ef2f6e5cd0907765584ee083a1f47cf6a94c503fb6 +size 13832 diff --git a/samples/deferred/deferred.csproj b/samples/deferred/deferred.csproj index 0a3b19a..1515582 100644 --- a/samples/deferred/deferred.csproj +++ b/samples/deferred/deferred.csproj @@ -54,7 +54,7 @@ <HintPath>..\..\packages\System.Memory.4.5.2\lib\netstandard2.0\System.Memory.dll</HintPath> </Reference> <Reference Include="vkvg.net"> - <HintPath>..\..\packages\vkvg.net.0.2.1-beta\lib\netstandard2.0\vkvg.net.dll</HintPath> + <HintPath>..\..\packages\vkvg.net.0.2.1.1-beta\lib\netstandard2.0\vkvg.net.dll</HintPath> </Reference> <Reference Include="VK"> <HintPath>..\..\packages\Vulkan.0.1.2.6\lib\netstandard2.0\VK.dll</HintPath> diff --git a/samples/deferred/packages.config b/samples/deferred/packages.config index 3b083ad..cb60b70 100644 --- a/samples/deferred/packages.config +++ b/samples/deferred/packages.config @@ -6,6 +6,6 @@ <package id="System.Memory" version="4.5.2" targetFramework="net471" /> <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net471" /> <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net471" /> - <package id="vkvg.net" version="0.2.1-beta" targetFramework="net471" /> + <package id="vkvg.net" version="0.2.1.1-beta" targetFramework="net471" /> <package id="Vulkan" version="0.1.2.6" targetFramework="net471" /> </packages>
\ No newline at end of file diff --git a/samples/pbrSashaWillem/main.cs b/samples/pbrSashaWillem/main.cs index 98fb5dc..95e945b 100644 --- a/samples/pbrSashaWillem/main.cs +++ b/samples/pbrSashaWillem/main.cs @@ -12,9 +12,8 @@ namespace pbrSachaWillem { vke.Run (); } } - - protected override void configureEnabledFeatures (ref VkPhysicalDeviceFeatures features) { - base.configureEnabledFeatures (ref features); + protected override void configureEnabledFeatures (VkPhysicalDeviceFeatures available_features, ref VkPhysicalDeviceFeatures features) { + base.configureEnabledFeatures (available_features, ref features); #if PIPELINE_STATS features.pipelineStatisticsQuery = true; #endif diff --git a/samples/vkvg_tests/main.cs b/samples/vkvg_tests/main.cs index 7544a4b..99f0398 100644 --- a/samples/vkvg_tests/main.cs +++ b/samples/vkvg_tests/main.cs @@ -1,4 +1,5 @@ -using CVKL; +using System.Threading; +using CVKL; using VK; namespace vkvg_test { @@ -27,41 +28,110 @@ namespace vkvg_test { ctx.Fill (); ctx.Operator = vkvg.Operator.Over; } - void vkvgDraw () { - using (vkvg.Context ctx = new vkvg.Context (vkvgSurf)) { - ctx.ResetClip (); - ctx.Rectangle (50, 50, 200, 200); - ctx.Rectangle (50, 50, 250, 250); - clearAndClip (ctx); - //ctx.Rectangle (60, 60, 200, 200); + using (vkvg.Context ctx = new vkvg.Context (vkvgSurf)) { + //ctx.SetSource (1.0, 0.1, 0.1, 0.2); + //ctx.Paint (); + + //ctx.Rectangle (50, 50, 200, 200); + //ctx.Rectangle (50, 50, 250, 250); //clearAndClip (ctx); + ////ctx.Rectangle (60, 60, 200, 200); + ////clearAndClip (ctx); - ctx.LineWidth = 1; - ctx.SetSource (1.0, 0.1, 0.1, 0.2); - ctx.Rectangle (5.5, 5.5, 400, 250); - ctx.FillPreserve (); - ctx.Flush (); + //ctx.LineWidth = 1; + //ctx.SetSource (1.0, 0.1, 0.1, 0.2); + //ctx.Rectangle (5.5, 5.5, 400, 250); + //ctx.FillPreserve (); + //ctx.Flush (); ctx.SetSource (0.8, 0.8, 0.8); - ctx.Stroke (); + //ctx.Stroke (); ctx.FontFace = "mono"; - ctx.FontSize = 20; - int x = 60; - int y = 80, dy = 16; - ctx.MoveTo (x, y); - ctx.ShowText (string.Format ($"fps: {fps,5} ")); + ctx.FontSize = 8; + int x = 10; + int y = 10, dy = 14; + for (int j = 0; j < 10; j++) { + + for (int i = 0; i < 50; i++) { + ctx.Save (); + string text = string.Format ($"fps: {fps,5}"); + vkvg.TextExtents te = ctx.TextExtents (text); + vkvg.FontExtents fe = ctx.FontExtents; + + ctx.Rectangle (x, y, te.XAdvance + 1.0f, fe.Height); + clearAndClip (ctx); + ctx.SetSource (0.1, 0.2, 0.8); + ctx.Fill (); + ctx.SetSource (0.8, 0.8, 0.8); + ctx.MoveTo (x, (float)y+fe.Ascent); + ctx.ShowText (text); + y += dy; + ctx.Restore (); + } + ctx.Flush (); + x += 100; + y = 10; + + } + } } #endregion - Program () : base () { + bool recreateSurfaceStatus = true; + + void recreateSurface () { + vkvgImage?.Dispose (); + vkvgSurf?.Dispose (); + vkvgSurf = new vkvg.Surface (vkvgDev, (int)swapChain.Width, (int)swapChain.Height); + vkvgSurf.Clear (); + vkvgImage = new Image (dev, new VkImage ((ulong)vkvgSurf.VkImage.ToInt64 ()), VkFormat.B8g8r8a8Unorm, + VkImageUsageFlags.ColorAttachment, (uint)vkvgSurf.Width, (uint)vkvgSurf.Height); + vkvgImage.CreateView (VkImageViewType.ImageView2D, VkImageAspectFlags.Color); + vkvgImage.CreateSampler (VkFilter.Nearest, VkFilter.Nearest, VkSamplerMipmapMode.Nearest, VkSamplerAddressMode.ClampToBorder); + recreateSurfaceStatus = false; + } + + void uiThreadFunc () { vkvgDev = new vkvg.Device (instance.Handle, phy.Handle, dev.VkDev.Handle, presentQueue.qFamIndex, - vkvg.SampleCount.Sample_4, presentQueue.index); + vkvg.SampleCount.Sample_1, presentQueue.index); + + while (true) { + if (recreateSurfaceStatus == true) + recreateSurface (); + lock (Qmutex) { + vkvgDraw (); + } + Thread.Sleep (10); + } + } + + Program () : base () { + Thread uiThread = new Thread (uiThreadFunc); + uiThread.IsBackground = true; + uiThread.Start (); init (); + UpdateFrequency = 5; + } + object Qmutex = new object (); + + protected override void render () { + int idx = swapChain.GetNextImage (); + if (idx < 0) { + OnResize (); + return; + } + + lock (Qmutex) { + presentQueue.Submit (cmds[idx], swapChain.presentComplete, drawComplete[idx]); + presentQueue.Present (swapChain, drawComplete[idx]); + + presentQueue.WaitIdle (); + } } void init (VkSampleCountFlags samples = VkSampleCountFlags.SampleCount4) { @@ -71,9 +141,7 @@ namespace vkvg_test { descLayout = new DescriptorSetLayout (dev, new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) - ); - - dsVkvg = descriptorPool.Allocate (descLayout); + ); GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, samples); @@ -87,6 +155,8 @@ namespace vkvg_test { cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState (true); uiPipeline = new GraphicPipeline (cfg); + + dsVkvg = descriptorPool.Allocate (descLayout); } void buildCommandBuffers () { @@ -123,18 +193,13 @@ namespace vkvg_test { } public override void Update () { - vkvgDraw (); - dev.WaitIdle (); + } protected override void OnResize () { - - vkvgImage?.Dispose (); - vkvgSurf?.Dispose (); - vkvgSurf = new vkvg.Surface (vkvgDev, (int)swapChain.Width, (int)swapChain.Height); - vkvgImage = new Image (dev, new VkImage ((ulong)vkvgSurf.VkImage.ToInt64 ()), VkFormat.B8g8r8a8Unorm, - VkImageUsageFlags.ColorAttachment, (uint)vkvgSurf.Width, (uint)vkvgSurf.Height); - vkvgImage.CreateView (VkImageViewType.ImageView2D, VkImageAspectFlags.Color); - vkvgImage.CreateSampler (VkFilter.Nearest,VkFilter.Nearest, VkSamplerMipmapMode.Nearest, VkSamplerAddressMode.ClampToBorder); + dev.WaitIdle (); + recreateSurfaceStatus = true; + while (recreateSurfaceStatus) + Thread.Sleep (1); vkvgImage.Descriptor.imageLayout = VkImageLayout.ShaderReadOnlyOptimal; DescriptorSetWrites uboUpdate = new DescriptorSetWrites (dsVkvg, descLayout); diff --git a/samples/vkvg_tests/packages.config b/samples/vkvg_tests/packages.config index 773c14e..cb60b70 100644 --- a/samples/vkvg_tests/packages.config +++ b/samples/vkvg_tests/packages.config @@ -1,11 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="glTF2Loader" version="1.1.3-alpha" targetFramework="net471" /> - <package id="Newtonsoft.Json" version="12.0.1" targetFramework="net471" /> + <package id="Newtonsoft.Json" version="12.0.2" targetFramework="net471" /> <package id="System.Buffers" version="4.5.0" targetFramework="net471" /> <package id="System.Memory" version="4.5.2" targetFramework="net471" /> <package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net471" /> <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net471" /> - <package id="vkvg.net" version="0.2.1-beta" targetFramework="net471" /> + <package id="vkvg.net" version="0.2.1.1-beta" targetFramework="net471" /> <package id="Vulkan" version="0.1.2.6" targetFramework="net471" /> </packages>
\ No newline at end of file diff --git a/samples/vkvg_tests/vkvg_tests.csproj b/samples/vkvg_tests/vkvg_tests.csproj index 4581ca2..4ef1c82 100644 --- a/samples/vkvg_tests/vkvg_tests.csproj +++ b/samples/vkvg_tests/vkvg_tests.csproj @@ -39,7 +39,7 @@ </Reference> <Reference Include="mscorlib" /> <Reference Include="Newtonsoft.Json"> - <HintPath>..\..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> + <HintPath>..\..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath> </Reference> <Reference Include="glTFLoader"> <HintPath>..\..\packages\glTF2Loader.1.1.3-alpha\lib\net35\glTFLoader.dll</HintPath> @@ -57,7 +57,7 @@ <HintPath>..\..\packages\Vulkan.0.1.2.6\lib\netstandard2.0\VK.dll</HintPath> </Reference> <Reference Include="vkvg.net"> - <HintPath>..\..\packages\vkvg.net.0.2.1-beta\lib\netstandard2.0\vkvg.net.dll</HintPath> + <HintPath>..\..\packages\vkvg.net.0.2.1.1-beta\lib\netstandard2.0\vkvg.net.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> diff --git a/vke/src/Camera.cs b/vke/src/Camera.cs index c49717c..5021c84 100644 --- a/vke/src/Camera.cs +++ b/vke/src/Camera.cs @@ -59,7 +59,7 @@ namespace CVKL { public void Rotate (float x, float y, float z = 0) { rotation.Y += rotSpeed * x; rotation.X += rotSpeed * y; - Update (); + //Update (); } public float Zoom { get { return zoom; } diff --git a/vke/src/VkWindow.cs b/vke/src/VkWindow.cs index b304e75..a04b9ce 100644 --- a/vke/src/VkWindow.cs +++ b/vke/src/VkWindow.cs @@ -267,6 +267,7 @@ namespace CVKL { UpdateView (); frameChrono = Stopwatch.StartNew (); + long totTime = 0; while (!Glfw3.WindowShouldClose (hWin)) { render (); @@ -277,17 +278,17 @@ namespace CVKL { frameCount++; if (frameChrono.ElapsedMilliseconds > UpdateFrequency) { - frameChrono.Stop (); - - fps = (uint)(1000.0 * frameCount / frameChrono.ElapsedMilliseconds); - - Glfw3.SetWindowTitle (hWin, "FPS: " + fps.ToString ()); - Update (); - frameCount = 0; - frameChrono.Restart (); - + frameChrono.Stop (); + totTime += frameChrono.ElapsedMilliseconds; + 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 (); } |