VulkanContent.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Numerics;
  6. using System.Runtime.CompilerServices;
  7. using System.Runtime.InteropServices;
  8. using Avalonia;
  9. using Avalonia.Threading;
  10. using Silk.NET.Vulkan;
  11. using SilkNetDemo;
  12. using Buffer = System.Buffer;
  13. using Image = Silk.NET.Vulkan.Image;
  14. namespace GpuInterop.VulkanDemo;
  15. unsafe class VulkanContent : IDisposable
  16. {
  17. private readonly VulkanContext _context;
  18. private ShaderModule _vertShader;
  19. private ShaderModule _fragShader;
  20. private PipelineLayout _pipelineLayout;
  21. private RenderPass _renderPass;
  22. private Pipeline _pipeline;
  23. private DescriptorSetLayout _descriptorSetLayout;
  24. private Silk.NET.Vulkan.Buffer _vertexBuffer;
  25. private DeviceMemory _vertexBufferMemory;
  26. private Silk.NET.Vulkan.Buffer _indexBuffer;
  27. private DeviceMemory _indexBufferMemory;
  28. private Silk.NET.Vulkan.Buffer _uniformBuffer;
  29. private DeviceMemory _uniformBufferMemory;
  30. private Framebuffer _framebuffer;
  31. private Image _depthImage;
  32. private DeviceMemory _depthImageMemory;
  33. private ImageView _depthImageView;
  34. public VulkanContent(VulkanContext context)
  35. {
  36. _context = context;
  37. var name = typeof(VulkanContent).Assembly.GetManifestResourceNames().First(x => x.Contains("teapot.bin"));
  38. using (var sr = new BinaryReader(typeof(VulkanContent).Assembly.GetManifestResourceStream(name)))
  39. {
  40. var buf = new byte[sr.ReadInt32()];
  41. sr.Read(buf, 0, buf.Length);
  42. var points = new float[buf.Length / 4];
  43. Buffer.BlockCopy(buf, 0, points, 0, buf.Length);
  44. buf = new byte[sr.ReadInt32()];
  45. sr.Read(buf, 0, buf.Length);
  46. _indices = new ushort[buf.Length / 2];
  47. Buffer.BlockCopy(buf, 0, _indices, 0, buf.Length);
  48. _points = new Vertex[points.Length / 3];
  49. for (var primitive = 0; primitive < points.Length / 3; primitive++)
  50. {
  51. var srci = primitive * 3;
  52. _points[primitive] = new Vertex
  53. {
  54. Position = new Vector3(points[srci], points[srci + 1], points[srci + 2])
  55. };
  56. }
  57. for (int i = 0; i < _indices.Length; i += 3)
  58. {
  59. Vector3 a = _points[_indices[i]].Position;
  60. Vector3 b = _points[_indices[i + 1]].Position;
  61. Vector3 c = _points[_indices[i + 2]].Position;
  62. var normal = Vector3.Normalize(Vector3.Cross(c - b, a - b));
  63. _points[_indices[i]].Normal += normal;
  64. _points[_indices[i + 1]].Normal += normal;
  65. _points[_indices[i + 2]].Normal += normal;
  66. }
  67. for (int i = 0; i < _points.Length; i++)
  68. {
  69. _points[i].Normal = Vector3.Normalize(_points[i].Normal);
  70. _maxY = Math.Max(_maxY, _points[i].Position.Y);
  71. _minY = Math.Min(_minY, _points[i].Position.Y);
  72. }
  73. }
  74. var api = _context.Api;
  75. var device = _context.Device;
  76. var vertShaderData = GetShader(false);
  77. var fragShaderData = GetShader(true);
  78. fixed (byte* ptr = vertShaderData)
  79. {
  80. var shaderCreateInfo = new ShaderModuleCreateInfo()
  81. {
  82. SType = StructureType.ShaderModuleCreateInfo,
  83. CodeSize = (nuint)vertShaderData.Length,
  84. PCode = (uint*)ptr,
  85. };
  86. api.CreateShaderModule(device, shaderCreateInfo, null, out _vertShader);
  87. }
  88. fixed (byte* ptr = fragShaderData)
  89. {
  90. var shaderCreateInfo = new ShaderModuleCreateInfo()
  91. {
  92. SType = StructureType.ShaderModuleCreateInfo,
  93. CodeSize = (nuint)fragShaderData.Length,
  94. PCode = (uint*)ptr,
  95. };
  96. api.CreateShaderModule(device, shaderCreateInfo, null, out _fragShader);
  97. }
  98. CreateBuffers();
  99. }
  100. private byte[] GetShader(bool fragment)
  101. {
  102. var name = typeof(VulkanContent).Assembly.GetManifestResourceNames()
  103. .First(x => x.Contains((fragment ? "frag" : "vert") + ".spirv"));
  104. using (var sr = typeof(VulkanContent).Assembly.GetManifestResourceStream(name))
  105. {
  106. using (var mem = new MemoryStream())
  107. {
  108. sr.CopyTo(mem);
  109. return mem.ToArray();
  110. }
  111. }
  112. }
  113. private PixelSize? _previousImageSize = PixelSize.Empty;
  114. public void Render(VulkanImage image,
  115. double yaw, double pitch, double roll, double disco)
  116. {
  117. var api = _context.Api;
  118. if (image.Size != _previousImageSize)
  119. CreateTemporalObjects(image.Size);
  120. _previousImageSize = image.Size;
  121. var model = Matrix4x4.CreateFromYawPitchRoll((float)yaw, (float)pitch, (float)roll);
  122. var view = Matrix4x4.CreateLookAt(new Vector3(25, 25, 25), new Vector3(), new Vector3(0, -1, 0));
  123. var projection =
  124. Matrix4x4.CreatePerspectiveFieldOfView((float)(Math.PI / 4), (float)((float)image.Size.Width / image.Size.Height),
  125. 0.01f, 1000);
  126. var vertexConstant = new VertextPushConstant()
  127. {
  128. Disco = (float)disco,
  129. MinY = _minY,
  130. MaxY = _maxY,
  131. Model = model,
  132. Time = (float)St.Elapsed.TotalSeconds
  133. };
  134. var commandBuffer = _context.Pool.CreateCommandBuffer();
  135. commandBuffer.BeginRecording();
  136. _colorAttachment.TransitionLayout(commandBuffer.InternalHandle,
  137. ImageLayout.Undefined, AccessFlags.None,
  138. ImageLayout.ColorAttachmentOptimal, AccessFlags.ColorAttachmentWriteBit);
  139. var commandBufferHandle = new CommandBuffer(commandBuffer.Handle);
  140. api.CmdSetViewport(commandBufferHandle, 0, 1,
  141. new Viewport()
  142. {
  143. Width = (float)image.Size.Width,
  144. Height = (float)image.Size.Height,
  145. MaxDepth = 1,
  146. MinDepth = 0,
  147. X = 0,
  148. Y = 0
  149. });
  150. var scissor = new Rect2D
  151. {
  152. Extent = new Extent2D((uint?)image.Size.Width, (uint?)image.Size.Height)
  153. };
  154. api.CmdSetScissor(commandBufferHandle, 0, 1, &scissor);
  155. var clearColor = new ClearValue(new ClearColorValue(1, 0, 0, 0.1f), new ClearDepthStencilValue(1, 0));
  156. var clearValues = new[] { clearColor, clearColor };
  157. fixed (ClearValue* clearValue = clearValues)
  158. {
  159. var beginInfo = new RenderPassBeginInfo()
  160. {
  161. SType = StructureType.RenderPassBeginInfo,
  162. RenderPass = _renderPass,
  163. Framebuffer = _framebuffer,
  164. RenderArea = new Rect2D(new Offset2D(0, 0), new Extent2D((uint?)image.Size.Width, (uint?)image.Size.Height)),
  165. ClearValueCount = 2,
  166. PClearValues = clearValue
  167. };
  168. api.CmdBeginRenderPass(commandBufferHandle, beginInfo, SubpassContents.Inline);
  169. }
  170. api.CmdBindPipeline(commandBufferHandle, PipelineBindPoint.Graphics, _pipeline);
  171. var dset = _descriptorSet;
  172. api.CmdBindDescriptorSets(commandBufferHandle, PipelineBindPoint.Graphics,
  173. _pipelineLayout,0,1, &dset, null);
  174. api.CmdPushConstants(commandBufferHandle, _pipelineLayout, ShaderStageFlags.ShaderStageVertexBit | ShaderStageFlags.FragmentBit, 0,
  175. (uint)Marshal.SizeOf<VertextPushConstant>(), &vertexConstant);
  176. api.CmdBindVertexBuffers(commandBufferHandle, 0, 1, _vertexBuffer, 0);
  177. api.CmdBindIndexBuffer(commandBufferHandle, _indexBuffer, 0, IndexType.Uint16);
  178. api.CmdDrawIndexed(commandBufferHandle, (uint)_indices.Length, 1, 0, 0, 0);
  179. api.CmdEndRenderPass(commandBufferHandle);
  180. _colorAttachment.TransitionLayout(commandBuffer.InternalHandle, ImageLayout.TransferSrcOptimal, AccessFlags.TransferReadBit);
  181. image.TransitionLayout(commandBuffer.InternalHandle, ImageLayout.TransferDstOptimal, AccessFlags.TransferWriteBit);
  182. var srcBlitRegion = new ImageBlit
  183. {
  184. SrcOffsets = new ImageBlit.SrcOffsetsBuffer
  185. {
  186. Element0 = new Offset3D(0, 0, 0),
  187. Element1 = new Offset3D(image.Size.Width, image.Size.Height, 1),
  188. },
  189. DstOffsets = new ImageBlit.DstOffsetsBuffer
  190. {
  191. Element0 = new Offset3D(0, 0, 0),
  192. Element1 = new Offset3D(image.Size.Width, image.Size.Height, 1),
  193. },
  194. SrcSubresource =
  195. new ImageSubresourceLayers
  196. {
  197. AspectMask = ImageAspectFlags.ImageAspectColorBit,
  198. BaseArrayLayer = 0,
  199. LayerCount = 1,
  200. MipLevel = 0
  201. },
  202. DstSubresource = new ImageSubresourceLayers
  203. {
  204. AspectMask = ImageAspectFlags.ImageAspectColorBit,
  205. BaseArrayLayer = 0,
  206. LayerCount = 1,
  207. MipLevel = 0
  208. }
  209. };
  210. api.CmdBlitImage(commandBuffer.InternalHandle, _colorAttachment.InternalHandle.Value,
  211. ImageLayout.TransferSrcOptimal,
  212. image.InternalHandle.Value, ImageLayout.TransferDstOptimal, 1, srcBlitRegion, Filter.Linear);
  213. commandBuffer.Submit();
  214. }
  215. public unsafe void Dispose()
  216. {
  217. if (_isInit)
  218. {
  219. var api = _context.Api;
  220. var device = _context.Device;
  221. DestroyTemporalObjects();
  222. api.DestroyShaderModule(device, _vertShader, null);
  223. api.DestroyShaderModule(device, _fragShader, null);
  224. api.DestroyBuffer(device, _vertexBuffer, null);
  225. api.FreeMemory(device, _vertexBufferMemory, null);
  226. api.DestroyBuffer(device, _indexBuffer, null);
  227. api.FreeMemory(device, _indexBufferMemory, null);
  228. }
  229. _isInit = false;
  230. }
  231. public unsafe void DestroyTemporalObjects()
  232. {
  233. if (_isInit)
  234. {
  235. if (_renderPass.Handle != 0)
  236. {
  237. var api = _context.Api;
  238. var device = _context.Device;
  239. api.FreeDescriptorSets(_context.Device, _context.DescriptorPool, new[] { _descriptorSet });
  240. api.DestroyImageView(device, _depthImageView, null);
  241. api.DestroyImage(device, _depthImage, null);
  242. api.FreeMemory(device, _depthImageMemory, null);
  243. api.DestroyFramebuffer(device, _framebuffer, null);
  244. api.DestroyPipeline(device, _pipeline, null);
  245. api.DestroyPipelineLayout(device, _pipelineLayout, null);
  246. api.DestroyRenderPass(device, _renderPass, null);
  247. api.DestroyDescriptorSetLayout(device, _descriptorSetLayout, null);
  248. api.DestroyBuffer(device, _uniformBuffer, null);
  249. api.FreeMemory(device, _uniformBufferMemory, null);
  250. _colorAttachment?.Dispose();
  251. _colorAttachment = null;
  252. _depthImage = default;
  253. _depthImageView = default;
  254. _depthImageView = default;
  255. _framebuffer = default;
  256. _pipeline = default;
  257. _renderPass = default;
  258. _pipelineLayout = default;
  259. _descriptorSetLayout = default;
  260. _uniformBuffer = default;
  261. _uniformBufferMemory = default;
  262. }
  263. }
  264. }
  265. private unsafe void CreateDepthAttachment(PixelSize size)
  266. {
  267. var imageCreateInfo = new ImageCreateInfo
  268. {
  269. SType = StructureType.ImageCreateInfo,
  270. ImageType = ImageType.ImageType2D,
  271. Format = Format.D32Sfloat,
  272. Extent =
  273. new Extent3D((uint?)size.Width,
  274. (uint?)size.Height, 1),
  275. MipLevels = 1,
  276. ArrayLayers = 1,
  277. Samples = SampleCountFlags.SampleCount1Bit,
  278. Tiling = ImageTiling.Optimal,
  279. Usage = ImageUsageFlags.ImageUsageDepthStencilAttachmentBit,
  280. SharingMode = SharingMode.Exclusive,
  281. InitialLayout = ImageLayout.Undefined,
  282. Flags = ImageCreateFlags.ImageCreateMutableFormatBit
  283. };
  284. var api = _context.Api;
  285. var device = _context.Device;
  286. api
  287. .CreateImage(device, imageCreateInfo, null, out _depthImage).ThrowOnError();
  288. api.GetImageMemoryRequirements(device, _depthImage,
  289. out var memoryRequirements);
  290. var memoryAllocateInfo = new MemoryAllocateInfo
  291. {
  292. SType = StructureType.MemoryAllocateInfo,
  293. AllocationSize = memoryRequirements.Size,
  294. MemoryTypeIndex = (uint)FindSuitableMemoryTypeIndex(api,
  295. _context.PhysicalDevice,
  296. memoryRequirements.MemoryTypeBits, MemoryPropertyFlags.MemoryPropertyDeviceLocalBit)
  297. };
  298. api.AllocateMemory(device, memoryAllocateInfo, null,
  299. out _depthImageMemory).ThrowOnError();
  300. api.BindImageMemory(device, _depthImage, _depthImageMemory, 0);
  301. var componentMapping = new ComponentMapping(
  302. ComponentSwizzle.R,
  303. ComponentSwizzle.G,
  304. ComponentSwizzle.B,
  305. ComponentSwizzle.A);
  306. var subresourceRange = new ImageSubresourceRange(ImageAspectFlags.ImageAspectDepthBit,
  307. 0, 1, 0, 1);
  308. var imageViewCreateInfo = new ImageViewCreateInfo
  309. {
  310. SType = StructureType.ImageViewCreateInfo,
  311. Image = _depthImage,
  312. ViewType = ImageViewType.ImageViewType2D,
  313. Format = Format.D32Sfloat,
  314. Components = componentMapping,
  315. SubresourceRange = subresourceRange
  316. };
  317. api
  318. .CreateImageView(device, imageViewCreateInfo, null, out _depthImageView)
  319. .ThrowOnError();
  320. }
  321. private unsafe void CreateTemporalObjects(PixelSize size)
  322. {
  323. DestroyTemporalObjects();
  324. var view = Matrix4x4.CreateLookAt(new Vector3(25, 25, 25), new Vector3(), new Vector3(0, -1, 0));
  325. var projection =
  326. Matrix4x4.CreatePerspectiveFieldOfView((float)(Math.PI / 4), (float)((float)size.Width / size.Height),
  327. 0.01f, 1000);
  328. _colorAttachment = new VulkanImage(_context, (uint)Format.R8G8B8A8Unorm, size, false);
  329. CreateDepthAttachment(size);
  330. var api = _context.Api;
  331. var device = _context.Device;
  332. // create renderpasses
  333. var colorAttachment = new AttachmentDescription()
  334. {
  335. Format = Format.R8G8B8A8Unorm,
  336. Samples = SampleCountFlags.SampleCount1Bit,
  337. LoadOp = AttachmentLoadOp.Clear,
  338. StoreOp = AttachmentStoreOp.Store,
  339. InitialLayout = ImageLayout.Undefined,
  340. FinalLayout = ImageLayout.ColorAttachmentOptimal,
  341. StencilLoadOp = AttachmentLoadOp.DontCare,
  342. StencilStoreOp = AttachmentStoreOp.DontCare
  343. };
  344. var depthAttachment = new AttachmentDescription()
  345. {
  346. Format = Format.D32Sfloat,
  347. Samples = SampleCountFlags.SampleCount1Bit,
  348. LoadOp = AttachmentLoadOp.Clear,
  349. StoreOp = AttachmentStoreOp.DontCare,
  350. InitialLayout = ImageLayout.Undefined,
  351. FinalLayout = ImageLayout.DepthStencilAttachmentOptimal,
  352. StencilLoadOp = AttachmentLoadOp.DontCare,
  353. StencilStoreOp = AttachmentStoreOp.DontCare
  354. };
  355. var subpassDependency = new SubpassDependency()
  356. {
  357. SrcSubpass = Vk.SubpassExternal,
  358. DstSubpass = 0,
  359. SrcStageMask = PipelineStageFlags.PipelineStageColorAttachmentOutputBit,
  360. SrcAccessMask = 0,
  361. DstStageMask = PipelineStageFlags.PipelineStageColorAttachmentOutputBit,
  362. DstAccessMask = AccessFlags.AccessColorAttachmentWriteBit
  363. };
  364. var colorAttachmentReference = new AttachmentReference()
  365. {
  366. Attachment = 0, Layout = ImageLayout.ColorAttachmentOptimal
  367. };
  368. var depthAttachmentReference = new AttachmentReference()
  369. {
  370. Attachment = 1, Layout = ImageLayout.DepthStencilAttachmentOptimal
  371. };
  372. var subpassDescription = new SubpassDescription()
  373. {
  374. PipelineBindPoint = PipelineBindPoint.Graphics,
  375. ColorAttachmentCount = 1,
  376. PColorAttachments = &colorAttachmentReference,
  377. PDepthStencilAttachment = &depthAttachmentReference
  378. };
  379. var attachments = new[] { colorAttachment, depthAttachment };
  380. fixed (AttachmentDescription* atPtr = attachments)
  381. {
  382. var renderPassCreateInfo = new RenderPassCreateInfo()
  383. {
  384. SType = StructureType.RenderPassCreateInfo,
  385. AttachmentCount = (uint)attachments.Length,
  386. PAttachments = atPtr,
  387. SubpassCount = 1,
  388. PSubpasses = &subpassDescription,
  389. DependencyCount = 1,
  390. PDependencies = &subpassDependency
  391. };
  392. api.CreateRenderPass(device, renderPassCreateInfo, null, out _renderPass).ThrowOnError();
  393. // create framebuffer
  394. var frameBufferAttachments = new[] { new ImageView(_colorAttachment.ViewHandle), _depthImageView };
  395. fixed (ImageView* frAtPtr = frameBufferAttachments)
  396. {
  397. var framebufferCreateInfo = new FramebufferCreateInfo()
  398. {
  399. SType = StructureType.FramebufferCreateInfo,
  400. RenderPass = _renderPass,
  401. AttachmentCount = (uint)frameBufferAttachments.Length,
  402. PAttachments = frAtPtr,
  403. Width = (uint)size.Width,
  404. Height = (uint)size.Height,
  405. Layers = 1
  406. };
  407. api.CreateFramebuffer(device, framebufferCreateInfo, null, out _framebuffer).ThrowOnError();
  408. }
  409. }
  410. // Create pipeline
  411. var pname = Marshal.StringToHGlobalAnsi("main");
  412. var vertShaderStageInfo = new PipelineShaderStageCreateInfo()
  413. {
  414. SType = StructureType.PipelineShaderStageCreateInfo,
  415. Stage = ShaderStageFlags.ShaderStageVertexBit,
  416. Module = _vertShader,
  417. PName = (byte*)pname,
  418. };
  419. var fragShaderStageInfo = new PipelineShaderStageCreateInfo()
  420. {
  421. SType = StructureType.PipelineShaderStageCreateInfo,
  422. Stage = ShaderStageFlags.ShaderStageFragmentBit,
  423. Module = _fragShader,
  424. PName = (byte*)pname,
  425. };
  426. var stages = new[] { vertShaderStageInfo, fragShaderStageInfo };
  427. var bindingDescription = Vertex.VertexInputBindingDescription;
  428. var attributeDescription = Vertex.VertexInputAttributeDescription;
  429. fixed (VertexInputAttributeDescription* attrPtr = attributeDescription)
  430. {
  431. var vertextInputInfo = new PipelineVertexInputStateCreateInfo()
  432. {
  433. SType = StructureType.PipelineVertexInputStateCreateInfo,
  434. VertexAttributeDescriptionCount = (uint)attributeDescription.Length,
  435. VertexBindingDescriptionCount = 1,
  436. PVertexAttributeDescriptions = attrPtr,
  437. PVertexBindingDescriptions = &bindingDescription
  438. };
  439. var inputAssembly = new PipelineInputAssemblyStateCreateInfo()
  440. {
  441. SType = StructureType.PipelineInputAssemblyStateCreateInfo,
  442. Topology = PrimitiveTopology.TriangleList,
  443. PrimitiveRestartEnable = false
  444. };
  445. var viewport = new Viewport()
  446. {
  447. X = 0,
  448. Y = 0,
  449. Width = (float)size.Width,
  450. Height = (float)size.Height,
  451. MinDepth = 0,
  452. MaxDepth = 1
  453. };
  454. var scissor = new Rect2D()
  455. {
  456. Offset = new Offset2D(0, 0), Extent = new Extent2D((uint)viewport.Width, (uint)viewport.Height)
  457. };
  458. var pipelineViewPortCreateInfo = new PipelineViewportStateCreateInfo()
  459. {
  460. SType = StructureType.PipelineViewportStateCreateInfo,
  461. ViewportCount = 1,
  462. PViewports = &viewport,
  463. ScissorCount = 1,
  464. PScissors = &scissor
  465. };
  466. var rasterizerStateCreateInfo = new PipelineRasterizationStateCreateInfo()
  467. {
  468. SType = StructureType.PipelineRasterizationStateCreateInfo,
  469. DepthClampEnable = false,
  470. RasterizerDiscardEnable = false,
  471. PolygonMode = PolygonMode.Fill,
  472. LineWidth = 1,
  473. CullMode = CullModeFlags.CullModeNone,
  474. DepthBiasEnable = false
  475. };
  476. var multisampleStateCreateInfo = new PipelineMultisampleStateCreateInfo()
  477. {
  478. SType = StructureType.PipelineMultisampleStateCreateInfo,
  479. SampleShadingEnable = false,
  480. RasterizationSamples = SampleCountFlags.SampleCount1Bit
  481. };
  482. var depthStencilCreateInfo = new PipelineDepthStencilStateCreateInfo()
  483. {
  484. SType = StructureType.PipelineDepthStencilStateCreateInfo,
  485. StencilTestEnable = false,
  486. DepthCompareOp = CompareOp.Less,
  487. DepthTestEnable = true,
  488. DepthWriteEnable = true,
  489. DepthBoundsTestEnable = false,
  490. };
  491. var colorBlendAttachmentState = new PipelineColorBlendAttachmentState()
  492. {
  493. ColorWriteMask = ColorComponentFlags.ColorComponentABit |
  494. ColorComponentFlags.ColorComponentRBit |
  495. ColorComponentFlags.ColorComponentGBit |
  496. ColorComponentFlags.ColorComponentBBit,
  497. BlendEnable = false
  498. };
  499. var colorBlendState = new PipelineColorBlendStateCreateInfo()
  500. {
  501. SType = StructureType.PipelineColorBlendStateCreateInfo,
  502. LogicOpEnable = false,
  503. AttachmentCount = 1,
  504. PAttachments = &colorBlendAttachmentState
  505. };
  506. var dynamicStates = new DynamicState[] { DynamicState.Viewport, DynamicState.Scissor };
  507. fixed (DynamicState* states = dynamicStates)
  508. {
  509. var dynamicStateCreateInfo = new PipelineDynamicStateCreateInfo()
  510. {
  511. SType = StructureType.PipelineDynamicStateCreateInfo,
  512. DynamicStateCount = (uint)dynamicStates.Length,
  513. PDynamicStates = states
  514. };
  515. var vertexPushConstantRange = new PushConstantRange()
  516. {
  517. Offset = 0,
  518. Size = (uint)Marshal.SizeOf<VertextPushConstant>(),
  519. StageFlags = ShaderStageFlags.ShaderStageVertexBit
  520. };
  521. var fragPushConstantRange = new PushConstantRange()
  522. {
  523. //Offset = vertexPushConstantRange.Size,
  524. Size = (uint)Marshal.SizeOf<VertextPushConstant>(),
  525. StageFlags = ShaderStageFlags.ShaderStageFragmentBit
  526. };
  527. var layoutBindingInfo = new DescriptorSetLayoutBinding
  528. {
  529. Binding = 0,
  530. StageFlags = ShaderStageFlags.VertexBit,
  531. DescriptorCount = 1,
  532. DescriptorType = DescriptorType.UniformBuffer,
  533. };
  534. var layoutInfo = new DescriptorSetLayoutCreateInfo
  535. {
  536. SType = StructureType.DescriptorSetLayoutCreateInfo,
  537. BindingCount = 1,
  538. PBindings = &layoutBindingInfo
  539. };
  540. api.CreateDescriptorSetLayout(device, &layoutInfo, null, out _descriptorSetLayout).ThrowOnError();
  541. var projView = view * projection;
  542. VulkanBufferHelper.AllocateBuffer<UniformBuffer>(_context, BufferUsageFlags.UniformBufferBit,
  543. out _uniformBuffer,
  544. out _uniformBufferMemory, new[]
  545. {
  546. new UniformBuffer
  547. {
  548. Projection = projView
  549. }
  550. });
  551. var descriptorSetLayout = _descriptorSetLayout;
  552. var descriptorCreateInfo = new DescriptorSetAllocateInfo
  553. {
  554. SType = StructureType.DescriptorSetAllocateInfo,
  555. DescriptorPool = _context.DescriptorPool,
  556. DescriptorSetCount = 1,
  557. PSetLayouts = &descriptorSetLayout
  558. };
  559. api.AllocateDescriptorSets(device, &descriptorCreateInfo, out _descriptorSet).ThrowOnError();
  560. var descriptorBufferInfo = new DescriptorBufferInfo
  561. {
  562. Buffer = _uniformBuffer,
  563. Range = (ulong)Unsafe.SizeOf<UniformBuffer>(),
  564. };
  565. var descriptorWrite = new WriteDescriptorSet
  566. {
  567. SType = StructureType.WriteDescriptorSet,
  568. DstSet = _descriptorSet,
  569. DescriptorType = DescriptorType.UniformBuffer,
  570. DescriptorCount = 1,
  571. PBufferInfo = &descriptorBufferInfo,
  572. };
  573. api.UpdateDescriptorSets(device, 1, &descriptorWrite, 0, null);
  574. var constants = new[] { vertexPushConstantRange, fragPushConstantRange };
  575. fixed (PushConstantRange* constant = constants)
  576. {
  577. var setLayout = _descriptorSetLayout;
  578. var pipelineLayoutCreateInfo = new PipelineLayoutCreateInfo()
  579. {
  580. SType = StructureType.PipelineLayoutCreateInfo,
  581. PushConstantRangeCount = (uint)constants.Length,
  582. PPushConstantRanges = constant,
  583. SetLayoutCount = 1,
  584. PSetLayouts = &setLayout
  585. };
  586. api.CreatePipelineLayout(device, pipelineLayoutCreateInfo, null, out _pipelineLayout)
  587. .ThrowOnError();
  588. }
  589. fixed (PipelineShaderStageCreateInfo* stPtr = stages)
  590. {
  591. var pipelineCreateInfo = new GraphicsPipelineCreateInfo()
  592. {
  593. SType = StructureType.GraphicsPipelineCreateInfo,
  594. StageCount = 2,
  595. PStages = stPtr,
  596. PVertexInputState = &vertextInputInfo,
  597. PInputAssemblyState = &inputAssembly,
  598. PViewportState = &pipelineViewPortCreateInfo,
  599. PRasterizationState = &rasterizerStateCreateInfo,
  600. PMultisampleState = &multisampleStateCreateInfo,
  601. PDepthStencilState = &depthStencilCreateInfo,
  602. PColorBlendState = &colorBlendState,
  603. PDynamicState = &dynamicStateCreateInfo,
  604. Layout = _pipelineLayout,
  605. RenderPass = _renderPass,
  606. Subpass = 0,
  607. BasePipelineHandle = _pipeline.Handle != 0 ? _pipeline : new Pipeline(),
  608. BasePipelineIndex = _pipeline.Handle != 0 ? 0 : -1
  609. };
  610. api.CreateGraphicsPipelines(device, new PipelineCache(), 1, &pipelineCreateInfo, null,
  611. out _pipeline).ThrowOnError();
  612. }
  613. }
  614. }
  615. Marshal.FreeHGlobal(pname);
  616. _isInit = true;
  617. }
  618. private unsafe void CreateBuffers()
  619. {
  620. VulkanBufferHelper.AllocateBuffer<Vertex>(_context, BufferUsageFlags.VertexBufferBit, out _vertexBuffer,
  621. out _vertexBufferMemory, _points);
  622. VulkanBufferHelper.AllocateBuffer<ushort>(_context, BufferUsageFlags.IndexBufferBit, out _indexBuffer,
  623. out _indexBufferMemory, _indices);
  624. }
  625. private static int FindSuitableMemoryTypeIndex(Vk api, PhysicalDevice physicalDevice, uint memoryTypeBits,
  626. MemoryPropertyFlags flags)
  627. {
  628. api.GetPhysicalDeviceMemoryProperties(physicalDevice, out var properties);
  629. for (var i = 0; i < properties.MemoryTypeCount; i++)
  630. {
  631. var type = properties.MemoryTypes[i];
  632. if ((memoryTypeBits & (1 << i)) != 0 && type.PropertyFlags.HasFlag(flags)) return i;
  633. }
  634. return -1;
  635. }
  636. [StructLayout(LayoutKind.Sequential, Pack = 4)]
  637. private struct Vertex
  638. {
  639. public Vector3 Position;
  640. public Vector3 Normal;
  641. public static unsafe VertexInputBindingDescription VertexInputBindingDescription
  642. {
  643. get
  644. {
  645. return new VertexInputBindingDescription()
  646. {
  647. Binding = 0,
  648. Stride = (uint)Marshal.SizeOf<Vertex>(),
  649. InputRate = VertexInputRate.Vertex
  650. };
  651. }
  652. }
  653. public static unsafe VertexInputAttributeDescription[] VertexInputAttributeDescription
  654. {
  655. get
  656. {
  657. return new VertexInputAttributeDescription[]
  658. {
  659. new VertexInputAttributeDescription
  660. {
  661. Binding = 0,
  662. Location = 0,
  663. Format = Format.R32G32B32Sfloat,
  664. Offset = (uint)Marshal.OffsetOf<Vertex>("Position")
  665. },
  666. new VertexInputAttributeDescription
  667. {
  668. Binding = 0,
  669. Location = 1,
  670. Format = Format.R32G32B32Sfloat,
  671. Offset = (uint)Marshal.OffsetOf<Vertex>("Normal")
  672. }
  673. };
  674. }
  675. }
  676. }
  677. private readonly Vertex[] _points;
  678. private readonly ushort[] _indices;
  679. private readonly float _minY;
  680. private readonly float _maxY;
  681. static Stopwatch St = Stopwatch.StartNew();
  682. private bool _isInit;
  683. private VulkanImage _colorAttachment;
  684. private DescriptorSet _descriptorSet;
  685. [StructLayout(LayoutKind.Sequential, Pack = 4)]
  686. private struct VertextPushConstant
  687. {
  688. public float MaxY;
  689. public float MinY;
  690. public float Time;
  691. public float Disco;
  692. public Matrix4x4 Model;
  693. }
  694. [StructLayout(LayoutKind.Sequential, Pack = 4)]
  695. private struct UniformBuffer
  696. {
  697. public Matrix4x4 Projection;
  698. }
  699. }