D3D11DemoControl.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Diagnostics;
  3. using System.Linq;
  4. using System.Numerics;
  5. using Avalonia;
  6. using Avalonia.Platform;
  7. using Avalonia.Rendering.Composition;
  8. using Silk.NET.Core.Native;
  9. using Silk.NET.Direct3D11;
  10. using Silk.NET.DXGI;
  11. using static Silk.NET.Core.Native.SilkMarshal;
  12. namespace GpuInterop.D3DDemo;
  13. public class D3D11DemoControl : DrawingSurfaceDemoBase
  14. {
  15. private ComPtr<ID3D11Device> _device;
  16. private D3D11Swapchain? _swapchain;
  17. private ComPtr<ID3D11DeviceContext> _context;
  18. private Matrix4x4 _view;
  19. private PixelSize _lastSize;
  20. private ComPtr<ID3D11Texture2D> _depthBuffer;
  21. private ComPtr<ID3D11DepthStencilView> _depthView;
  22. private Matrix4x4 _proj;
  23. private ComPtr<ID3D11Buffer> _constantBuffer;
  24. private readonly Stopwatch _st = Stopwatch.StartNew();
  25. protected override unsafe (bool success, string info) InitializeGraphicsResources(Compositor compositor,
  26. CompositionDrawingSurface surface, ICompositionGpuInterop interop)
  27. {
  28. if (interop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes
  29. .D3D11TextureGlobalSharedHandle) != true)
  30. return (false, "DXGI shared handle import is not supported by the current graphics backend");
  31. using var dxgi = new DXGI(DXGI.CreateDefaultContext(["DXGI.dll"]));
  32. using var d3d11 = new D3D11(D3D11.CreateDefaultContext(["d3d11.dll"]));
  33. using var factory = dxgi.CreateDXGIFactory1<IDXGIFactory1>();
  34. using ComPtr<IDXGIAdapter> adapter = default;
  35. ThrowHResult(factory.EnumAdapters(0, adapter.GetAddressOf()));
  36. const int featureLevelCount = 8;
  37. var featureLevels = stackalloc D3DFeatureLevel[featureLevelCount]
  38. {
  39. D3DFeatureLevel.Level121,
  40. D3DFeatureLevel.Level120,
  41. D3DFeatureLevel.Level111,
  42. D3DFeatureLevel.Level110,
  43. D3DFeatureLevel.Level100,
  44. D3DFeatureLevel.Level93,
  45. D3DFeatureLevel.Level92,
  46. D3DFeatureLevel.Level91
  47. };
  48. ComPtr<ID3D11Device> device = default;
  49. ComPtr<ID3D11DeviceContext> context = default;
  50. D3DFeatureLevel actualFeatureLevel;
  51. ThrowHResult(d3d11.CreateDevice(
  52. adapter,
  53. D3DDriverType.Unknown,
  54. IntPtr.Zero,
  55. 0u,
  56. featureLevels,
  57. featureLevelCount,
  58. D3D11.SdkVersion,
  59. device.GetAddressOf(),
  60. &actualFeatureLevel,
  61. context.GetAddressOf()));
  62. _device = device;
  63. _swapchain = new D3D11Swapchain(device, interop, surface);
  64. _context = context;
  65. _constantBuffer = D3DContent.CreateMesh(_device);
  66. _view = Matrix4x4.CreateLookAtLeftHanded(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY);
  67. AdapterDesc adapterDesc;
  68. ThrowHResult(adapter.GetDesc(&adapterDesc));
  69. var description = PtrToString((IntPtr)adapterDesc.Description, NativeStringEncoding.LPWStr);
  70. return (true, $"D3D11 ({actualFeatureLevel}) {description}");
  71. }
  72. protected override void FreeGraphicsResources()
  73. {
  74. if (_swapchain is not null)
  75. {
  76. _swapchain.DisposeAsync().GetAwaiter().GetResult();
  77. _swapchain = null;
  78. }
  79. _depthView.Dispose();
  80. _depthBuffer.Dispose();
  81. _constantBuffer.Dispose();
  82. _context.Dispose();
  83. _device.Dispose();
  84. }
  85. protected override bool SupportsDisco => true;
  86. protected override unsafe void RenderFrame(PixelSize pixelSize)
  87. {
  88. if (pixelSize == default)
  89. return;
  90. if (pixelSize != _lastSize)
  91. {
  92. _lastSize = pixelSize;
  93. Resize(pixelSize);
  94. }
  95. using (_swapchain!.BeginDraw(pixelSize, out var renderView))
  96. {
  97. var renderViewHandle = renderView.Handle;
  98. _context.OMSetRenderTargets(1, &renderViewHandle, _depthView);
  99. var viewProj = _view * _proj;
  100. var now = _st.Elapsed.TotalSeconds * 5;
  101. var scaleX = (float)(1f + Disco * (Math.Sin(now) + 1) / 6);
  102. var scaleY = (float)(1f + Disco * (Math.Cos(now) + 1) / 8);
  103. var colorOff =(float) (Math.Sin(now) + 1) / 2 * Disco;
  104. // Clear views
  105. _context.ClearDepthStencilView(_depthView, (uint)ClearFlag.Depth, 1.0f, 0);
  106. var color = new Vector4(1f - colorOff, colorOff, 0.5f + colorOff * 0.5f, 1.0f);
  107. _context.ClearRenderTargetView(renderView, (float*)&color);
  108. // Update WorldViewProj Matrix
  109. var ypr = Matrix4x4.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
  110. var worldViewProj = ypr * Matrix4x4.CreateScale(new Vector3(scaleX, scaleY, 1)) * viewProj;
  111. worldViewProj = Matrix4x4.Transpose(worldViewProj);
  112. _context.UpdateSubresource(_constantBuffer, 0, null, &worldViewProj, 0, 0);
  113. // Draw the cube
  114. _context.Draw(36, 0);
  115. _context.Flush();
  116. }
  117. }
  118. private unsafe void Resize(PixelSize size)
  119. {
  120. _depthBuffer.Dispose();
  121. if (_device.Handle == null)
  122. return;
  123. ComPtr<ID3D11Texture2D> depthBuffer = default;
  124. var textureDesc = new Texture2DDesc
  125. {
  126. Format = Format.FormatD32FloatS8X24Uint,
  127. ArraySize = 1,
  128. MipLevels = 1,
  129. Width = (uint)size.Width,
  130. Height = (uint)size.Height,
  131. SampleDesc = new SampleDesc(1, 0),
  132. Usage = Usage.Default,
  133. BindFlags = (uint)BindFlag.DepthStencil,
  134. CPUAccessFlags = (uint)CpuAccessFlag.None,
  135. MiscFlags = (uint)ResourceMiscFlag.None
  136. };
  137. ThrowHResult(_device.CreateTexture2D(
  138. &textureDesc,
  139. (SubresourceData*)null,
  140. depthBuffer.GetAddressOf()));
  141. _depthBuffer = depthBuffer;
  142. _depthView.Dispose();
  143. ThrowHResult(_device.CreateDepthStencilView(_depthBuffer, null, ref _depthView));
  144. // Setup targets and viewport for rendering
  145. var viewport = new Viewport(0, 0, size.Width, size.Height, 0.0f, 1.0f);
  146. _context.RSSetViewports(1, &viewport);
  147. // Setup new projection matrix with correct aspect ratio
  148. _proj = Matrix4x4.CreatePerspectiveFieldOfViewLeftHanded((float)Math.PI / 4.0f, size.Width / (float) size.Height, 0.1f, 100.0f);
  149. }
  150. }