D3D11DemoControl.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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 SharpDX.Direct3D11.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 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. _swapchain.DisposeAsync();
  59. _swapchain = null!;
  60. Utilities.Dispose(ref _depthView);
  61. Utilities.Dispose(ref _depthBuffer);
  62. Utilities.Dispose(ref _constantBuffer);
  63. Utilities.Dispose(ref _context);
  64. Utilities.Dispose(ref _device);
  65. }
  66. protected override bool SupportsDisco => true;
  67. protected override void RenderFrame(PixelSize pixelSize)
  68. {
  69. if (pixelSize == default)
  70. return;
  71. if (pixelSize != _lastSize)
  72. {
  73. _lastSize = pixelSize;
  74. Resize(pixelSize);
  75. }
  76. using (_swapchain.BeginDraw(pixelSize, out var renderView))
  77. {
  78. _device.ImmediateContext.OutputMerger.SetTargets(_depthView, renderView);
  79. var viewProj = Matrix.Multiply(_view, _proj);
  80. var context = _device.ImmediateContext;
  81. var now = _st.Elapsed.TotalSeconds * 5;
  82. var scaleX = (float)(1f + Disco * (Math.Sin(now) + 1) / 6);
  83. var scaleY = (float)(1f + Disco * (Math.Cos(now) + 1) / 8);
  84. var colorOff =(float) (Math.Sin(now) + 1) / 2 * Disco;
  85. // Clear views
  86. context.ClearDepthStencilView(_depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
  87. context.ClearRenderTargetView(renderView,
  88. new RawColor4(1 - colorOff, colorOff, (float)0.5 + colorOff / 2, 1));
  89. var ypr = Matrix4x4.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
  90. // Update WorldViewProj Matrix
  91. var worldViewProj = Matrix.RotationX((float)Yaw) * Matrix.RotationY((float)Pitch)
  92. * Matrix.RotationZ((float)Roll)
  93. * Matrix.Scaling(new Vector3(scaleX, scaleY, 1))
  94. * viewProj;
  95. worldViewProj.Transpose();
  96. context.UpdateSubresource(ref worldViewProj, _constantBuffer);
  97. // Draw the cube
  98. context.Draw(36, 0);
  99. _context.Flush();
  100. }
  101. }
  102. private void Resize(PixelSize size)
  103. {
  104. Utilities.Dispose(ref _depthBuffer);
  105. _depthBuffer = new Texture2D(_device,
  106. new Texture2DDescription()
  107. {
  108. Format = Format.D32_Float_S8X24_UInt,
  109. ArraySize = 1,
  110. MipLevels = 1,
  111. Width = (int)size.Width,
  112. Height = (int)size.Height,
  113. SampleDescription = new SampleDescription(1, 0),
  114. Usage = ResourceUsage.Default,
  115. BindFlags = BindFlags.DepthStencil,
  116. CpuAccessFlags = CpuAccessFlags.None,
  117. OptionFlags = ResourceOptionFlags.None
  118. });
  119. Utilities.Dispose(ref _depthView);
  120. _depthView = new DepthStencilView(_device, _depthBuffer);
  121. // Setup targets and viewport for rendering
  122. _device.ImmediateContext.Rasterizer.SetViewport(new Viewport(0, 0, (int)size.Width, (int)size.Height, 0.0f, 1.0f));
  123. // Setup new projection matrix with correct aspect ratio
  124. _proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, (float)(size.Width / size.Height), 0.1f, 100.0f);
  125. }
  126. }