D3D11DemoControl.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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 SharpDX;
  9. using SharpDX.Direct3D11;
  10. using SharpDX.DXGI;
  11. using SharpDX.Mathematics.Interop;
  12. using Buffer = SharpDX.Direct3D11.Buffer;
  13. using DxgiFactory1 = SharpDX.DXGI.Factory1;
  14. using Matrix = SharpDX.Matrix;
  15. using D3DDevice = SharpDX.Direct3D11.Device;
  16. using FeatureLevel = SharpDX.Direct3D.FeatureLevel;
  17. using Vector3 = SharpDX.Vector3;
  18. namespace GpuInterop.D3DDemo;
  19. public class D3D11DemoControl : DrawingSurfaceDemoBase
  20. {
  21. private D3DDevice? _device;
  22. private D3D11Swapchain? _swapchain;
  23. private DeviceContext? _context;
  24. private Matrix _view;
  25. private PixelSize _lastSize;
  26. private Texture2D? _depthBuffer;
  27. private DepthStencilView? _depthView;
  28. private Matrix _proj;
  29. private Buffer? _constantBuffer;
  30. private readonly Stopwatch _st = Stopwatch.StartNew();
  31. protected override (bool success, string info) InitializeGraphicsResources(Compositor compositor,
  32. CompositionDrawingSurface surface, ICompositionGpuInterop interop)
  33. {
  34. if (interop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes
  35. .D3D11TextureGlobalSharedHandle) != true)
  36. return (false, "DXGI shared handle import is not supported by the current graphics backend");
  37. var factory = new DxgiFactory1();
  38. using var adapter = factory.GetAdapter1(0);
  39. _device = new D3DDevice(adapter, DeviceCreationFlags.None, new[]
  40. {
  41. FeatureLevel.Level_12_1,
  42. FeatureLevel.Level_12_0,
  43. FeatureLevel.Level_11_1,
  44. FeatureLevel.Level_11_0,
  45. FeatureLevel.Level_10_0,
  46. FeatureLevel.Level_9_3,
  47. FeatureLevel.Level_9_2,
  48. FeatureLevel.Level_9_1,
  49. });
  50. _swapchain = new D3D11Swapchain(_device, interop, surface);
  51. _context = _device.ImmediateContext;
  52. _constantBuffer = D3DContent.CreateMesh(_device);
  53. _view = Matrix.LookAtLH(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY);
  54. return (true, $"D3D11 ({_device.FeatureLevel}) {adapter.Description1.Description}");
  55. }
  56. protected override void FreeGraphicsResources()
  57. {
  58. if (_swapchain is not null)
  59. {
  60. _swapchain.DisposeAsync().GetAwaiter().GetResult();
  61. _swapchain = null;
  62. }
  63. Utilities.Dispose(ref _depthView);
  64. Utilities.Dispose(ref _depthBuffer);
  65. Utilities.Dispose(ref _constantBuffer);
  66. Utilities.Dispose(ref _context);
  67. Utilities.Dispose(ref _device);
  68. }
  69. protected override bool SupportsDisco => true;
  70. protected override void RenderFrame(PixelSize pixelSize)
  71. {
  72. if (pixelSize == default)
  73. return;
  74. if (pixelSize != _lastSize)
  75. {
  76. _lastSize = pixelSize;
  77. Resize(pixelSize);
  78. }
  79. using (_swapchain!.BeginDraw(pixelSize, out var renderView))
  80. {
  81. _device!.ImmediateContext.OutputMerger.SetTargets(_depthView, renderView);
  82. var viewProj = Matrix.Multiply(_view, _proj);
  83. var context = _device.ImmediateContext;
  84. var now = _st.Elapsed.TotalSeconds * 5;
  85. var scaleX = (float)(1f + Disco * (Math.Sin(now) + 1) / 6);
  86. var scaleY = (float)(1f + Disco * (Math.Cos(now) + 1) / 8);
  87. var colorOff =(float) (Math.Sin(now) + 1) / 2 * Disco;
  88. // Clear views
  89. context.ClearDepthStencilView(_depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
  90. context.ClearRenderTargetView(renderView,
  91. new RawColor4(1 - colorOff, colorOff, (float)0.5 + colorOff / 2, 1));
  92. var ypr = Matrix4x4.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
  93. // Update WorldViewProj Matrix
  94. var worldViewProj = Matrix.RotationX(Yaw) * Matrix.RotationY(Pitch)
  95. * Matrix.RotationZ(Roll)
  96. * Matrix.Scaling(new Vector3(scaleX, scaleY, 1))
  97. * viewProj;
  98. worldViewProj.Transpose();
  99. context.UpdateSubresource(ref worldViewProj, _constantBuffer);
  100. // Draw the cube
  101. context.Draw(36, 0);
  102. _context!.Flush();
  103. }
  104. }
  105. private void Resize(PixelSize size)
  106. {
  107. Utilities.Dispose(ref _depthBuffer);
  108. if (_device is null)
  109. return;
  110. _depthBuffer = new Texture2D(_device,
  111. new Texture2DDescription()
  112. {
  113. Format = Format.D32_Float_S8X24_UInt,
  114. ArraySize = 1,
  115. MipLevels = 1,
  116. Width = size.Width,
  117. Height = size.Height,
  118. SampleDescription = new SampleDescription(1, 0),
  119. Usage = ResourceUsage.Default,
  120. BindFlags = BindFlags.DepthStencil,
  121. CpuAccessFlags = CpuAccessFlags.None,
  122. OptionFlags = ResourceOptionFlags.None
  123. });
  124. Utilities.Dispose(ref _depthView);
  125. _depthView = new DepthStencilView(_device, _depthBuffer);
  126. // Setup targets and viewport for rendering
  127. _device.ImmediateContext.Rasterizer.SetViewport(new Viewport(0, 0, size.Width, size.Height, 0.0f, 1.0f));
  128. // Setup new projection matrix with correct aspect ratio
  129. _proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, size.Width / (float) size.Height, 0.1f, 100.0f);
  130. }
  131. }