1
0

VulkanContent.cs 30 KB

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