From 650317246c39210bebe79bb24d876261a2f0080b Mon Sep 17 00:00:00 2001 From: AndrewSt Date: Fri, 17 Jun 2016 09:46:17 +0300 Subject: [PATCH] [Direct3D10] return samples for Direct3D10 --- Desktop/Common/Direct3D10DemoApp.cs | 118 ++++++++ Desktop/Common/SharpDX.Samples.csproj | 4 + .../DisplayFontApp/DisplayFontApp.csproj | 87 ++++++ Desktop/Direct3D10/DisplayFontApp/Program.cs | 100 +++++++ .../DisplayFontApp/Properties/AssemblyInfo.cs | 36 +++ Desktop/Direct3D10/DisplayFontApp/app.config | 3 + .../Direct3D10/DisplayFontApp/screenshot.png | Bin 0 -> 34656 bytes .../DisplayFontApp/screenshot_small.png | Bin 0 -> 3655 bytes Desktop/Direct3D10/MiniCube/MiniCube.csproj | 108 +++++++ Desktop/Direct3D10/MiniCube/MiniCube.fx | 47 ++++ Desktop/Direct3D10/MiniCube/Program.cs | 211 ++++++++++++++ .../MiniCube/Properties/AssemblyInfo.cs | 55 ++++ Desktop/Direct3D10/MiniCube/app.config | 3 + Desktop/Direct3D10/MiniTri/MiniTri.csproj | 82 ++++++ Desktop/Direct3D10/MiniTri/MiniTri.fx | 62 ++++ Desktop/Direct3D10/MiniTri/Program.cs | 155 ++++++++++ .../Direct3D10/MiniTri/ProgramWithNoEffect.cs | 129 +++++++++ .../MiniTri/Properties/AssemblyInfo.cs | 56 ++++ Desktop/Direct3D10/MiniTri/app.config | 3 + Desktop/Direct3D10/MiniTri/screenshot.png | Bin 0 -> 44270 bytes .../Direct3D10/MiniTri/screenshot_small.png | Bin 0 -> 4047 bytes Desktop/Direct3D10/WPFHost/App.xaml | 8 + Desktop/Direct3D10/WPFHost/App.xaml.cs | 16 ++ Desktop/Direct3D10/WPFHost/DPFCanvas.cs | 266 ++++++++++++++++++ Desktop/Direct3D10/WPFHost/DX10ImageSource.cs | 178 ++++++++++++ Desktop/Direct3D10/WPFHost/Disposer.cs | 52 ++++ Desktop/Direct3D10/WPFHost/IScene.cs | 37 +++ Desktop/Direct3D10/WPFHost/MainWindow.xaml | 11 + Desktop/Direct3D10/WPFHost/MainWindow.xaml.cs | 17 ++ .../WPFHost/Properties/AssemblyInfo.cs | 55 ++++ .../WPFHost/Properties/Resources.Designer.cs | 63 +++++ .../WPFHost/Properties/Resources.resx | 117 ++++++++ .../WPFHost/Properties/Settings.Designer.cs | 26 ++ .../WPFHost/Properties/Settings.settings | 7 + Desktop/Direct3D10/WPFHost/Scene.cs | 142 ++++++++++ Desktop/Direct3D10/WPFHost/Simple.fx | 82 ++++++ Desktop/Direct3D10/WPFHost/WPFHost.csproj | 163 +++++++++++ Desktop/Direct3D10/WPFHost/app.config | 3 + SharpDXSamples-Desktop.sln | 48 +++- 39 files changed, 2549 insertions(+), 1 deletion(-) create mode 100644 Desktop/Common/Direct3D10DemoApp.cs create mode 100644 Desktop/Direct3D10/DisplayFontApp/DisplayFontApp.csproj create mode 100644 Desktop/Direct3D10/DisplayFontApp/Program.cs create mode 100644 Desktop/Direct3D10/DisplayFontApp/Properties/AssemblyInfo.cs create mode 100644 Desktop/Direct3D10/DisplayFontApp/app.config create mode 100644 Desktop/Direct3D10/DisplayFontApp/screenshot.png create mode 100644 Desktop/Direct3D10/DisplayFontApp/screenshot_small.png create mode 100644 Desktop/Direct3D10/MiniCube/MiniCube.csproj create mode 100644 Desktop/Direct3D10/MiniCube/MiniCube.fx create mode 100644 Desktop/Direct3D10/MiniCube/Program.cs create mode 100644 Desktop/Direct3D10/MiniCube/Properties/AssemblyInfo.cs create mode 100644 Desktop/Direct3D10/MiniCube/app.config create mode 100644 Desktop/Direct3D10/MiniTri/MiniTri.csproj create mode 100644 Desktop/Direct3D10/MiniTri/MiniTri.fx create mode 100644 Desktop/Direct3D10/MiniTri/Program.cs create mode 100644 Desktop/Direct3D10/MiniTri/ProgramWithNoEffect.cs create mode 100644 Desktop/Direct3D10/MiniTri/Properties/AssemblyInfo.cs create mode 100644 Desktop/Direct3D10/MiniTri/app.config create mode 100644 Desktop/Direct3D10/MiniTri/screenshot.png create mode 100644 Desktop/Direct3D10/MiniTri/screenshot_small.png create mode 100644 Desktop/Direct3D10/WPFHost/App.xaml create mode 100644 Desktop/Direct3D10/WPFHost/App.xaml.cs create mode 100644 Desktop/Direct3D10/WPFHost/DPFCanvas.cs create mode 100644 Desktop/Direct3D10/WPFHost/DX10ImageSource.cs create mode 100644 Desktop/Direct3D10/WPFHost/Disposer.cs create mode 100644 Desktop/Direct3D10/WPFHost/IScene.cs create mode 100644 Desktop/Direct3D10/WPFHost/MainWindow.xaml create mode 100644 Desktop/Direct3D10/WPFHost/MainWindow.xaml.cs create mode 100644 Desktop/Direct3D10/WPFHost/Properties/AssemblyInfo.cs create mode 100644 Desktop/Direct3D10/WPFHost/Properties/Resources.Designer.cs create mode 100644 Desktop/Direct3D10/WPFHost/Properties/Resources.resx create mode 100644 Desktop/Direct3D10/WPFHost/Properties/Settings.Designer.cs create mode 100644 Desktop/Direct3D10/WPFHost/Properties/Settings.settings create mode 100644 Desktop/Direct3D10/WPFHost/Scene.cs create mode 100644 Desktop/Direct3D10/WPFHost/Simple.fx create mode 100644 Desktop/Direct3D10/WPFHost/WPFHost.csproj create mode 100644 Desktop/Direct3D10/WPFHost/app.config diff --git a/Desktop/Common/Direct3D10DemoApp.cs b/Desktop/Common/Direct3D10DemoApp.cs new file mode 100644 index 00000000..ca051233 --- /dev/null +++ b/Desktop/Common/Direct3D10DemoApp.cs @@ -0,0 +1,118 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using SharpDX.Direct3D; +using SharpDX.Direct3D10; +using SharpDX.DXGI; +using Device = SharpDX.Direct3D10.Device; +using Device1 = SharpDX.Direct3D10.Device1; +using DriverType = SharpDX.Direct3D10.DriverType; +using FeatureLevel = SharpDX.Direct3D10.FeatureLevel; + + +namespace SharpDX.Samples +{ + /// + /// Root class for Direct3D10(.1) Demo App + /// + public class Direct3D10DemoApp : DemoApp + { + Device1 _device; + SwapChain _swapChain; + Texture2D _backBuffer; + RenderTargetView _backBufferView; + + /// + /// Returns the device + /// + public Device1 Device + { + get + { + return _device; + } + } + + /// + /// Returns the backbuffer used by the SwapChain + /// + public Texture2D BackBuffer + { + get + { + return _backBuffer; + } + } + + /// + /// Returns the render target view on the backbuffer used by the SwapChain. + /// + public RenderTargetView BackBufferView + { + get + { + return _backBufferView; + } + } + + protected override void Initialize(DemoConfiguration demoConfiguration) + { + // SwapChain description + var desc = new SwapChainDescription() + { + BufferCount = 1, + ModeDescription = + new ModeDescription(demoConfiguration.Width, demoConfiguration.Height, + new Rational(60, 1), Format.R8G8B8A8_UNorm), + IsWindowed = true, + OutputHandle = DisplayHandle, + SampleDescription = new SampleDescription(1, 0), + SwapEffect = SwapEffect.Discard, + Usage = Usage.RenderTargetOutput + }; + + // Create Device and SwapChain + Device1.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.BgraSupport, desc, FeatureLevel.Level_10_0, out _device, out _swapChain); + + // Ignore all windows events + Factory factory = _swapChain.GetParent(); + factory.MakeWindowAssociation(DisplayHandle, WindowAssociationFlags.IgnoreAll); + + // New RenderTargetView from the backbuffer + _backBuffer = Texture2D.FromSwapChain(_swapChain, 0); + + _backBufferView = new RenderTargetView(_device, _backBuffer); + + + } + + protected override void BeginDraw() + { + base.BeginDraw(); + Device.Rasterizer.SetViewports(new Viewport(0, 0, Config.Width, Config.Height)); + Device.OutputMerger.SetTargets(_backBufferView); + } + + + protected override void EndDraw() + { + _swapChain.Present(Config.WaitVerticalBlanking?1:0, PresentFlags.None); + } + } +} \ No newline at end of file diff --git a/Desktop/Common/SharpDX.Samples.csproj b/Desktop/Common/SharpDX.Samples.csproj index bc8e0ca8..96be8a8d 100644 --- a/Desktop/Common/SharpDX.Samples.csproj +++ b/Desktop/Common/SharpDX.Samples.csproj @@ -46,6 +46,9 @@ ..\..\..\Bin\Desktop\SharpDX.Direct2D1.dll + + ..\..\..\Bin\Desktop\SharpDX.Direct3D10.dll + ..\..\..\Bin\Desktop\SharpDX.Direct3D11.dll @@ -67,6 +70,7 @@ + diff --git a/Desktop/Direct3D10/DisplayFontApp/DisplayFontApp.csproj b/Desktop/Direct3D10/DisplayFontApp/DisplayFontApp.csproj new file mode 100644 index 00000000..5852f974 --- /dev/null +++ b/Desktop/Direct3D10/DisplayFontApp/DisplayFontApp.csproj @@ -0,0 +1,87 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {A0A13A2D-9D57-4057-AA8C-A46D18B99354} + WinExe + Properties + DisplayFontApp + DisplayFontApp + v4.5.1 + + + 512 + 10cd9ae8 + ..\..\ + + + true + bin\Debug\ + DEBUG;TRACE + full + AnyCPU + prompt + false + + + bin\Release\ + TRACE + true + pdbonly + AnyCPU + prompt + false + + + + + + + ..\..\..\..\Bin\Desktop\SharpDX.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.D3DCompiler.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.Desktop.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.Direct3D10.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.DXGI.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.Mathematics.dll + + + + + + + + + + + + + + {93716298-9FA4-4002-AE0B-4C9F4705CCEA} + SharpDX.Samples + + + + + + + + \ No newline at end of file diff --git a/Desktop/Direct3D10/DisplayFontApp/Program.cs b/Desktop/Direct3D10/DisplayFontApp/Program.cs new file mode 100644 index 00000000..968aca91 --- /dev/null +++ b/Desktop/Direct3D10/DisplayFontApp/Program.cs @@ -0,0 +1,100 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using SharpDX; +using SharpDX.Direct3D10; +using SharpDX.Samples; + + +namespace DisplayFontApp +{ + /// + /// SharpDX Demo using D3D10 Font rendering. + /// Animates and draws a text, boucing on the screen limits. + /// + public class Program : Direct3D10DemoApp + { + private Font font; + private Rectangle fontDimension; + private float xDir, yDir; + private const string DisplayText = "SharpDX D3D10 Font"; + + protected override void Initialize(DemoConfiguration demoConfiguration) + { + base.Initialize(demoConfiguration); + + // Initialize the Font + FontDescription fontDescription = new FontDescription() + { + Height = 72, + Italic = false, + CharacterSet = FontCharacterSet.Ansi, + FaceName = "Arial", + MipLevels = 0, + OutputPrecision = FontPrecision.TrueType, + PitchAndFamily = FontPitchAndFamily.Default, + Quality = FontQuality.ClearType, + Weight = FontWeight.Bold + }; + + + font = new Font(Device, fontDescription); + + // Measure the text to display + fontDimension = font.MeasureText(null, DisplayText, new Rectangle(0, 0, 800, 600), FontDrawFlags.Center | FontDrawFlags.VerticalCenter); + + xDir = 1; + yDir = 1; + } + + protected override void Draw(DemoTime time) + { + base.Draw(time); + + Device.ClearRenderTargetView(BackBufferView, Color.White); + + // Make the text boucing on the screen limits + if ((fontDimension.Right + xDir) > Config.Width) + xDir = -1; + else if ((fontDimension.Left + xDir) <= 0) + xDir = 1; + + if ((fontDimension.Bottom + yDir) > Config.Height) + yDir = -1; + else if ((fontDimension.Top + yDir) <= 0) + yDir = 1; + + fontDimension.Left += (int)xDir; + fontDimension.Top += (int)yDir; + fontDimension.Bottom += (int)yDir; + fontDimension.Right += (int)xDir; + + // Draw the text + font.DrawText(null, DisplayText, fontDimension, FontDrawFlags.Center | FontDrawFlags.VerticalCenter, Color.Black); + } + + [STAThread] + static void Main(string[] args) + { + Program program = new Program(); + program.Run(new DemoConfiguration("SharpDX D3D10 Font Rendering Demo") { WaitVerticalBlanking = true }); + } + } +} \ No newline at end of file diff --git a/Desktop/Direct3D10/DisplayFontApp/Properties/AssemblyInfo.cs b/Desktop/Direct3D10/DisplayFontApp/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..cb087533 --- /dev/null +++ b/Desktop/Direct3D10/DisplayFontApp/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DisplayFontApp")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("DisplayFontApp")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2f297cfc-8862-458a-97dd-a8bafdb6eb94")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Desktop/Direct3D10/DisplayFontApp/app.config b/Desktop/Direct3D10/DisplayFontApp/app.config new file mode 100644 index 00000000..884f9844 --- /dev/null +++ b/Desktop/Direct3D10/DisplayFontApp/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Desktop/Direct3D10/DisplayFontApp/screenshot.png b/Desktop/Direct3D10/DisplayFontApp/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..20afaffdff5cd7a28ff3914b45e1f1551f406ae2 GIT binary patch literal 34656 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 + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {3177A431-E344-4395-A5E7-F54DE5A1D397} + WinExe + Properties + MiniCube + MiniCube + v4.5.1 + + + 512 + 155db97a + ..\..\ + + + true + bin\Debug\ + DEBUG;TRACE + true + full + AnyCPU + prompt + false + + + bin\Release\ + TRACE + true + pdbonly + AnyCPU + prompt + false + + + true + bin\Win8Debug\ + DEBUG;TRACE + true + full + AnyCPU + prompt + false + false + false + false + + + bin\Win8Release\ + TRACE + true + pdbonly + AnyCPU + prompt + false + false + false + false + + + + ..\..\..\..\Bin\Desktop\SharpDX.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.D3DCompiler.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.Desktop.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.Direct3D10.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.DXGI.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.Mathematics.dll + + + + + + + + + + + + + PreserveNewest + + + + + + + + \ No newline at end of file diff --git a/Desktop/Direct3D10/MiniCube/MiniCube.fx b/Desktop/Direct3D10/MiniCube/MiniCube.fx new file mode 100644 index 00000000..c6064ea5 --- /dev/null +++ b/Desktop/Direct3D10/MiniCube/MiniCube.fx @@ -0,0 +1,47 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +struct VS_IN +{ + float4 pos : POSITION; + float4 col : COLOR; +}; + +struct PS_IN +{ + float4 pos : SV_POSITION; + float4 col : COLOR; +}; + +float4x4 worldViewProj; + +PS_IN VS( VS_IN input ) +{ + PS_IN output = (PS_IN)0; + + output.pos = mul(input.pos, worldViewProj); + output.col = input.col; + + return output; +} + +float4 PS( PS_IN input ) : SV_Target +{ + return input.col; +} diff --git a/Desktop/Direct3D10/MiniCube/Program.cs b/Desktop/Direct3D10/MiniCube/Program.cs new file mode 100644 index 00000000..402b54e0 --- /dev/null +++ b/Desktop/Direct3D10/MiniCube/Program.cs @@ -0,0 +1,211 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Diagnostics; + +using SharpDX; +using SharpDX.D3DCompiler; +using SharpDX.Direct3D; +using SharpDX.Direct3D10; +using SharpDX.DXGI; +using SharpDX.Windows; +using Buffer = SharpDX.Direct3D10.Buffer; +using Device = SharpDX.Direct3D10.Device; +using DriverType = SharpDX.Direct3D10.DriverType; + +namespace MiniCube +{ + /// + /// SharpDX MiniCube Direct3D 10 Sample + /// + internal static class Program + { + [STAThread] + private static void Main() + { + var form = new RenderForm("SharpDX - MiniCube Direct3D 10 Sample"); + + // SwapChain description + var desc = new SwapChainDescription() + { + BufferCount = 1, + ModeDescription= + new ModeDescription(form.ClientSize.Width, form.ClientSize.Height, + new Rational(60, 1), Format.R8G8B8A8_UNorm), + IsWindowed = true, + OutputHandle = form.Handle, + SampleDescription = new SampleDescription(1, 0), + SwapEffect = SwapEffect.Discard, + Usage = Usage.RenderTargetOutput + }; + + // Create Device and SwapChain + Device device; + SwapChain swapChain; + Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, desc, out device, out swapChain); + var context = device; + + // Ignore all windows events + var factory = swapChain.GetParent(); + factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll); + + // New RenderTargetView from the backbuffer + var backBuffer = Texture2D.FromSwapChain(swapChain, 0); + var renderView = new RenderTargetView(device, backBuffer); + + // Compile Vertex and Pixel shaders + var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.fx", "VS", "vs_4_0"); + var vertexShader = new VertexShader(device, vertexShaderByteCode); + + var pixelShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.fx", "PS", "ps_4_0"); + var pixelShader = new PixelShader(device, pixelShaderByteCode); + + // Layout from VertexShader input signature + var layout = new InputLayout(device, ShaderSignature.GetInputSignature(vertexShaderByteCode), new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0) + }); + + // Instantiate Vertex buiffer from vertex data + var vertices = Buffer.Create(device, BindFlags.VertexBuffer, new[] + { + new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front + new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + + new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + + new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top + new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), + new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), + new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), + + new Vector4(-1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom + new Vector4( 1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + new Vector4(-1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + new Vector4(-1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + new Vector4( 1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + new Vector4( 1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), + + new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left + new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), + new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), + new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), + new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), + new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), + + new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), + new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), + new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), + new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), + new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), + }); + + // Create Constant Buffer + var contantBuffer = new Buffer(device, Utilities.SizeOf(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None); + + // Create Depth Buffer & View + var depthBuffer = new Texture2D(device, new Texture2DDescription() + { + Format = Format.D32_Float_S8X24_UInt, + ArraySize = 1, + MipLevels = 1, + Width = form.ClientSize.Width, + Height = form.ClientSize.Height, + SampleDescription = new SampleDescription(1, 0), + Usage = ResourceUsage.Default, + BindFlags = BindFlags.DepthStencil, + CpuAccessFlags = CpuAccessFlags.None, + OptionFlags = ResourceOptionFlags.None + }); + + var depthView = new DepthStencilView(device, depthBuffer); + + // Prepare All the stages + context.InputAssembler.InputLayout = layout; + context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, Utilities.SizeOf() * 2, 0)); + context.VertexShader.SetConstantBuffer(0, contantBuffer); + context.VertexShader.Set(vertexShader); + context.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f)); + context.PixelShader.Set(pixelShader); + + // Prepare matrices + var view = Matrix.LookAtLH(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY); + var proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, form.ClientSize.Width / (float)form.ClientSize.Height, 0.1f, 100.0f); + var viewProj = Matrix.Multiply(view, proj); + + // Use clock + var clock = new Stopwatch(); + clock.Start(); + + // Main loop + RenderLoop.Run(form, () => + { + var time = clock.ElapsedMilliseconds / 1000.0f; + + // Clear views + context.OutputMerger.SetTargets(depthView, renderView); + + context.ClearDepthStencilView(depthView, DepthStencilClearFlags.Depth, 1.0f, 0); + context.ClearRenderTargetView(renderView, Color.Black); + + // Update WorldViewProj Matrix + var worldViewProj = Matrix.RotationX(time) * Matrix.RotationY(time * 2) * Matrix.RotationZ(time * .7f) * viewProj; + worldViewProj.Transpose(); + context.UpdateSubresource(ref worldViewProj, contantBuffer); + + // Draw the cube + context.Draw(36, 0); + + // Present! + swapChain.Present(0, PresentFlags.None); + }); + + // Release all resources + vertexShaderByteCode.Dispose(); + vertexShader.Dispose(); + pixelShaderByteCode.Dispose(); + pixelShader.Dispose(); + vertices.Dispose(); + layout.Dispose(); + renderView.Dispose(); + backBuffer.Dispose(); + context.ClearState(); + context.Flush(); + device.Dispose(); + context.Dispose(); + swapChain.Dispose(); + factory.Dispose(); + } + } +} \ No newline at end of file diff --git a/Desktop/Direct3D10/MiniCube/Properties/AssemblyInfo.cs b/Desktop/Direct3D10/MiniCube/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..de42f5a1 --- /dev/null +++ b/Desktop/Direct3D10/MiniCube/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MiniCube")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyProduct("MiniCube")] +[assembly: AssemblyCompany("Alexandre Mutel")] +[assembly: AssemblyCopyright("Copyright © 2010-2011 Alexandre Mutel")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3e6b3234-906e-4119-a237-9d4634545d63")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Desktop/Direct3D10/MiniCube/app.config b/Desktop/Direct3D10/MiniCube/app.config new file mode 100644 index 00000000..884f9844 --- /dev/null +++ b/Desktop/Direct3D10/MiniCube/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Desktop/Direct3D10/MiniTri/MiniTri.csproj b/Desktop/Direct3D10/MiniTri/MiniTri.csproj new file mode 100644 index 00000000..70628aec --- /dev/null +++ b/Desktop/Direct3D10/MiniTri/MiniTri.csproj @@ -0,0 +1,82 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {F54F5361-F0E1-4D8E-8AB9-56A6EBFF1DBB} + WinExe + Properties + MiniTri + MiniTri + v4.5.1 + + + 512 + 67081415 + ..\..\ + + + true + bin\Debug\ + DEBUG;TRACE + false + full + AnyCPU + prompt + false + + + bin\Release\ + TRACE + true + pdbonly + AnyCPU + prompt + false + + + + ..\..\..\..\Bin\Desktop\SharpDX.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.D3DCompiler.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.Desktop.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.Direct3D10.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.DXGI.dll + + + ..\..\..\..\Bin\Desktop\SharpDX.Mathematics.dll + + + + + + + + + + + + PreserveNewest + + + + + + + + \ No newline at end of file diff --git a/Desktop/Direct3D10/MiniTri/MiniTri.fx b/Desktop/Direct3D10/MiniTri/MiniTri.fx new file mode 100644 index 00000000..be84e533 --- /dev/null +++ b/Desktop/Direct3D10/MiniTri/MiniTri.fx @@ -0,0 +1,62 @@ +// ----------------------------------------------------------------------------- +// Original code from SlimDX project. +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ + +struct VS_IN +{ + float4 pos : POSITION; + float4 col : COLOR; +}; + +struct PS_IN +{ + float4 pos : SV_POSITION; + float4 col : COLOR; +}; + +PS_IN VS( VS_IN input ) +{ + PS_IN output = (PS_IN)0; + + output.pos = input.pos; + output.col = input.col; + + return output; +} + +float4 PS( PS_IN input ) : SV_Target +{ + return input.col; +} + +technique10 Render +{ + pass P0 + { + SetGeometryShader( 0 ); + SetVertexShader( CompileShader( vs_4_0, VS() ) ); + SetPixelShader( CompileShader( ps_4_0, PS() ) ); + } +} \ No newline at end of file diff --git a/Desktop/Direct3D10/MiniTri/Program.cs b/Desktop/Direct3D10/MiniTri/Program.cs new file mode 100644 index 00000000..2eb91c9e --- /dev/null +++ b/Desktop/Direct3D10/MiniTri/Program.cs @@ -0,0 +1,155 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimDX project. +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +using System; +using SharpDX; +using SharpDX.D3DCompiler; +using SharpDX.Diagnostics; +using SharpDX.Direct3D; +using SharpDX.Direct3D10; +using SharpDX.DXGI; +using SharpDX.Windows; + +using Buffer = SharpDX.Direct3D10.Buffer; +using Device = SharpDX.Direct3D10.Device; +using DriverType = SharpDX.Direct3D10.DriverType; + +namespace MiniTri +{ + /// + /// SharpDX port of SlimDX-MiniTri Direct3D 10 Sample + /// + internal static class Program + { + [STAThread] + private static void Main() + { + var form = new RenderForm("SharpDX - MiniTri Direct3D 10 Sample"); + + Configuration.EnableObjectTracking = true; + + // SwapChain description + var desc = new SwapChainDescription() + { + BufferCount = 1, + ModeDescription = + new ModeDescription(form.ClientSize.Width, form.ClientSize.Height, + new Rational(60, 1), Format.R8G8B8A8_UNorm), + IsWindowed = true, + OutputHandle = form.Handle, + SampleDescription = new SampleDescription(1, 0), + SwapEffect = SwapEffect.Discard, + Usage = Usage.RenderTargetOutput + }; + + // Create Device and SwapChain + Device device; + SwapChain swapChain; + Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, desc, out device, out swapChain); + + // Ignore all windows events + var factory = swapChain.GetParent(); + factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll); + + // New RenderTargetView from the backbuffer + var backBuffer = Texture2D.FromSwapChain(swapChain, 0); + var renderView = new RenderTargetView(device, backBuffer); + + // Compile Vertex and Pixel shaders + var effectByteCode = ShaderBytecode.CompileFromFile("MiniTri.fx", "fx_4_0", ShaderFlags.None, EffectFlags.None); + var effect = new Effect(device, effectByteCode); + var technique = effect.GetTechniqueByIndex(0); + var pass = technique.GetPassByIndex(0); + + // Layout from VertexShader input signature + var passSignature = pass.Description.Signature; + var layout = new InputLayout(device, passSignature, new[] + { + new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), + new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0) + }); + + // Instantiate Vertex buiffer from vertex data + var vertices = Buffer.Create(device, BindFlags.VertexBuffer, new[] + { + new Vector4(0.0f, 0.5f, 0.5f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + new Vector4(0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f) + }); + + // Prepare All the stages + device.InputAssembler.InputLayout = layout; + device.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + device.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, 32, 0)); + device.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f)); + device.OutputMerger.SetTargets(renderView); + + // Main loop + RenderLoop.Run(form, () => + { + device.ClearRenderTargetView(renderView, Color.Black); + for (int i = 0; i < technique.Description.PassCount; ++i) + { + pass.Apply(); + device.Draw(3, 0); + } + swapChain.Present(0, PresentFlags.None); + }); + + // Release all resources + passSignature.Dispose(); + effect.Dispose(); + effectByteCode.Dispose(); + vertices.Dispose(); + layout.Dispose(); + renderView.Dispose(); + backBuffer.Dispose(); + device.ClearState(); + device.Flush(); + device.Dispose(); + swapChain.Dispose(); + factory.Dispose(); + } + } +} \ No newline at end of file diff --git a/Desktop/Direct3D10/MiniTri/ProgramWithNoEffect.cs b/Desktop/Direct3D10/MiniTri/ProgramWithNoEffect.cs new file mode 100644 index 00000000..51f55ec5 --- /dev/null +++ b/Desktop/Direct3D10/MiniTri/ProgramWithNoEffect.cs @@ -0,0 +1,129 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using SharpDX; +using SharpDX.D3DCompiler; +using SharpDX.Direct3D; +using SharpDX.Direct3D10; +using SharpDX.DXGI; +using SharpDX.Windows; + +using Buffer = SharpDX.Direct3D10.Buffer; +using Device = SharpDX.Direct3D10.Device; +using DriverType = SharpDX.Direct3D10.DriverType; + +namespace MiniTri +{ + /// + /// SharpDX port of SlimDX-MiniTri Direct3D 10 Sample + /// + internal static class ProgramWithNoEffect + { + [STAThread] + private static void Main2() + { + var form = new RenderForm("SharpDX - MiniTri Direct3D 10 Sample"); + + // SwapChain description + var desc = new SwapChainDescription() + { + BufferCount = 1, + ModeDescription = + new ModeDescription(form.ClientSize.Width, form.ClientSize.Height, + new Rational(60, 1), Format.R8G8B8A8_UNorm), + IsWindowed = true, + OutputHandle = form.Handle, + SampleDescription = new SampleDescription(1, 0), + SwapEffect = SwapEffect.Discard, + Usage = Usage.RenderTargetOutput + }; + + // Create Device and SwapChain + Device device; + SwapChain swapChain; + Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, desc, out device, out swapChain); + + + // Ignore all windows events + Factory factory = swapChain.GetParent(); + factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll); + + // New RenderTargetView from the backbuffer + Texture2D backBuffer = Texture2D.FromSwapChain(swapChain, 0); + var renderView = new RenderTargetView(device, backBuffer); + + // Compile Vertex and Pixel shaders + var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniTri.fx", "VS", "vs_4_0", ShaderFlags.None, + EffectFlags.None); + var vertexShader = new VertexShader(device, vertexShaderByteCode); + + var pixelShaderByteCode = ShaderBytecode.CompileFromFile("MiniTri.fx", "PS", "ps_4_0", ShaderFlags.None, + EffectFlags.None); + var pixelShader = new PixelShader(device, pixelShaderByteCode); + + // Layout from VertexShader input signature + var layout = new InputLayout(device, ShaderSignature.GetInputSignature(vertexShaderByteCode), new[] { + new InputElement("POSITION",0,Format.R32G32B32A32_Float,0,0), + new InputElement("COLOR",0,Format.R32G32B32A32_Float,16,0) + }); + + // Instantiate Vertex buiffer from vertex data + var vertices = Buffer.Create(device, BindFlags.VertexBuffer, new[] + { + new Vector4(0.0f, 0.5f, 0.5f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), + new Vector4(0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), + new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f) + }); + + // Prepare All the stages + device.InputAssembler.InputLayout = layout; + device.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; + device.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, 32, 0)); + device.VertexShader.Set(vertexShader); + device.Rasterizer.SetViewports(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f)); + device.PixelShader.Set(pixelShader); + device.OutputMerger.SetTargets(renderView); + + // Main loop + RenderLoop.Run(form, () => + { + device.ClearRenderTargetView(renderView, Color.Black); + device.Draw(3, 0); + swapChain.Present(0, PresentFlags.None); + }); + + // Release all resources + vertexShaderByteCode.Dispose(); + vertexShader.Dispose(); + pixelShaderByteCode.Dispose(); + pixelShader.Dispose(); + vertices.Dispose(); + layout.Dispose(); + renderView.Dispose(); + backBuffer.Dispose(); + device.ClearState(); + device.Flush(); + device.Dispose(); + device.Dispose(); + swapChain.Dispose(); + factory.Dispose(); + } + } +} \ No newline at end of file diff --git a/Desktop/Direct3D10/MiniTri/Properties/AssemblyInfo.cs b/Desktop/Direct3D10/MiniTri/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..0e11d20f --- /dev/null +++ b/Desktop/Direct3D10/MiniTri/Properties/AssemblyInfo.cs @@ -0,0 +1,56 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MiniTri")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyProduct("MiniTri")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: Obfuscation(Feature = "string encryption", Exclude = true)] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3e6b3234-906e-4119-a237-9d4634545d63")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Desktop/Direct3D10/MiniTri/app.config b/Desktop/Direct3D10/MiniTri/app.config new file mode 100644 index 00000000..884f9844 --- /dev/null +++ b/Desktop/Direct3D10/MiniTri/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Desktop/Direct3D10/MiniTri/screenshot.png b/Desktop/Direct3D10/MiniTri/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..066fdd2d486f319b42ba45a82de7380c4c858325 GIT binary patch literal 44270 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 LnhMY5EQ0?Jyf!@m literal 0 HcmV?d00001 diff --git a/Desktop/Direct3D10/MiniTri/screenshot_small.png b/Desktop/Direct3D10/MiniTri/screenshot_small.png new file mode 100644 index 0000000000000000000000000000000000000000..8bb5c4c90bed8c07feaa2e7c8f9cf1ccc58fa02d GIT binary patch literal 4047 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 literal 0 HcmV?d00001 diff --git a/Desktop/Direct3D10/WPFHost/App.xaml b/Desktop/Direct3D10/WPFHost/App.xaml new file mode 100644 index 00000000..2f9661f5 --- /dev/null +++ b/Desktop/Direct3D10/WPFHost/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Desktop/Direct3D10/WPFHost/App.xaml.cs b/Desktop/Direct3D10/WPFHost/App.xaml.cs new file mode 100644 index 00000000..b41bdba2 --- /dev/null +++ b/Desktop/Direct3D10/WPFHost/App.xaml.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; + +namespace WPFHost +{ + ///

+ /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/Desktop/Direct3D10/WPFHost/DPFCanvas.cs b/Desktop/Direct3D10/WPFHost/DPFCanvas.cs new file mode 100644 index 00000000..82118aa8 --- /dev/null +++ b/Desktop/Direct3D10/WPFHost/DPFCanvas.cs @@ -0,0 +1,266 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +namespace WPFHost +{ + using System; + using System.ComponentModel; + using System.Diagnostics; + using System.Windows; + using System.Windows.Controls; + using System.Windows.Media; + using SharpDX; + using SharpDX.Direct3D10; + using SharpDX.DXGI; + using Device = SharpDX.Direct3D10.Device1; + + public partial class DPFCanvas : Image, ISceneHost + { + private Device Device; + private Texture2D RenderTarget; + private Texture2D DepthStencil; + private RenderTargetView RenderTargetView; + private DepthStencilView DepthStencilView; + private DX10ImageSource D3DSurface; + private Stopwatch RenderTimer; + private IScene RenderScene; + private bool SceneAttached; + + public Color4 ClearColor = SharpDX.Color.Black; + + public DPFCanvas() + { + this.RenderTimer = new Stopwatch(); + this.Loaded += this.Window_Loaded; + this.Unloaded += this.Window_Closing; + } + + private void Window_Loaded(object sender, RoutedEventArgs e) + { + if (DPFCanvas.IsInDesignMode) + return; + + this.StartD3D(); + this.StartRendering(); + } + + private void Window_Closing(object sender, RoutedEventArgs e) + { + if (DPFCanvas.IsInDesignMode) + return; + + this.StopRendering(); + this.EndD3D(); + } + + private void StartD3D() + { + this.Device = new Device(DriverType.Hardware, DeviceCreationFlags.BgraSupport, FeatureLevel.Level_10_0); + + this.D3DSurface = new DX10ImageSource(); + this.D3DSurface.IsFrontBufferAvailableChanged += OnIsFrontBufferAvailableChanged; + + this.CreateAndBindTargets(); + + this.Source = this.D3DSurface; + } + + private void EndD3D() + { + if (this.RenderScene != null) + { + this.RenderScene.Detach(); + this.SceneAttached = false; + } + + this.D3DSurface.IsFrontBufferAvailableChanged -= OnIsFrontBufferAvailableChanged; + this.Source = null; + + Disposer.RemoveAndDispose(ref this.D3DSurface); + Disposer.RemoveAndDispose(ref this.RenderTargetView); + Disposer.RemoveAndDispose(ref this.DepthStencilView); + Disposer.RemoveAndDispose(ref this.RenderTarget); + Disposer.RemoveAndDispose(ref this.DepthStencil); + Disposer.RemoveAndDispose(ref this.Device); + } + + private void CreateAndBindTargets() + { + this.D3DSurface.SetRenderTargetDX10(null); + + Disposer.RemoveAndDispose(ref this.RenderTargetView); + Disposer.RemoveAndDispose(ref this.DepthStencilView); + Disposer.RemoveAndDispose(ref this.RenderTarget); + Disposer.RemoveAndDispose(ref this.DepthStencil); + + int width = Math.Max((int)base.ActualWidth, 100); + int height = Math.Max((int)base.ActualHeight, 100); + + Texture2DDescription colordesc = new Texture2DDescription + { + BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource, + Format = Format.B8G8R8A8_UNorm, + Width = width, + Height = height, + MipLevels = 1, + SampleDescription = new SampleDescription(1, 0), + Usage = ResourceUsage.Default, + OptionFlags = ResourceOptionFlags.Shared, + CpuAccessFlags = CpuAccessFlags.None, + ArraySize = 1 + }; + + Texture2DDescription depthdesc = new Texture2DDescription + { + BindFlags = BindFlags.DepthStencil, + Format = Format.D32_Float_S8X24_UInt, + Width = width, + Height = height, + MipLevels = 1, + SampleDescription = new SampleDescription(1, 0), + Usage = ResourceUsage.Default, + OptionFlags = ResourceOptionFlags.None, + CpuAccessFlags = CpuAccessFlags.None, + ArraySize = 1, + }; + + this.RenderTarget = new Texture2D(this.Device, colordesc); + this.DepthStencil = new Texture2D(this.Device, depthdesc); + this.RenderTargetView = new RenderTargetView(this.Device, this.RenderTarget); + this.DepthStencilView = new DepthStencilView(this.Device, this.DepthStencil); + + this.D3DSurface.SetRenderTargetDX10(this.RenderTarget); + } + + private void StartRendering() + { + if (this.RenderTimer.IsRunning) + return; + + CompositionTarget.Rendering += OnRendering; + this.RenderTimer.Start(); + } + + private void StopRendering() + { + if (!this.RenderTimer.IsRunning) + return; + + CompositionTarget.Rendering -= OnRendering; + this.RenderTimer.Stop(); + } + + private void OnRendering(object sender, EventArgs e) + { + if (!this.RenderTimer.IsRunning) + return; + + this.Render(this.RenderTimer.Elapsed); + this.D3DSurface.InvalidateD3DImage(); + } + + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) + { + this.CreateAndBindTargets(); + base.OnRenderSizeChanged(sizeInfo); + } + + void Render(TimeSpan sceneTime) + { + SharpDX.Direct3D10.Device device = this.Device; + if (device == null) + return; + + Texture2D renderTarget = this.RenderTarget; + if (renderTarget == null) + return; + + int targetWidth = renderTarget.Description.Width; + int targetHeight = renderTarget.Description.Height; + + device.OutputMerger.SetTargets(this.DepthStencilView, this.RenderTargetView); + device.Rasterizer.SetViewports(new Viewport(0, 0, targetWidth, targetHeight, 0.0f, 1.0f)); + + device.ClearRenderTargetView(this.RenderTargetView, this.ClearColor); + device.ClearDepthStencilView(this.DepthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0); + + if (this.Scene != null) + { + if (!this.SceneAttached) + { + this.SceneAttached = true; + this.RenderScene.Attach(this); + } + + this.Scene.Update(this.RenderTimer.Elapsed); + this.Scene.Render(); + } + + device.Flush(); + } + + private void OnIsFrontBufferAvailableChanged(object sender, DependencyPropertyChangedEventArgs e) + { + // this fires when the screensaver kicks in, the machine goes into sleep or hibernate + // and any other catastrophic losses of the d3d device from WPF's point of view + if(this.D3DSurface.IsFrontBufferAvailable) + { + CreateAndBindTargets(); + this.StartRendering(); + } + else + this.StopRendering(); + } + + /// + /// Gets a value indicating whether the control is in design mode + /// (running in Blend or Visual Studio). + /// + public static bool IsInDesignMode + { + get + { + DependencyProperty prop = DesignerProperties.IsInDesignModeProperty; + bool isDesignMode = (bool)DependencyPropertyDescriptor.FromProperty(prop, typeof(FrameworkElement)).Metadata.DefaultValue; + return isDesignMode; + } + } + + public IScene Scene + { + get { return this.RenderScene; } + set + { + if (ReferenceEquals(this.RenderScene, value)) + return; + + if (this.RenderScene != null) + this.RenderScene.Detach(); + + this.SceneAttached = false; + this.RenderScene = value; + } + } + + SharpDX.Direct3D10.Device ISceneHost.Device + { + get { return this.Device; } + } + } +} diff --git a/Desktop/Direct3D10/WPFHost/DX10ImageSource.cs b/Desktop/Direct3D10/WPFHost/DX10ImageSource.cs new file mode 100644 index 00000000..a9867507 --- /dev/null +++ b/Desktop/Direct3D10/WPFHost/DX10ImageSource.cs @@ -0,0 +1,178 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// ----------------------------------------------------------------------------- +// Original code from SlimMath project. http://code.google.com/p/slimmath/ +// Greetings to SlimDX Group. Original code published with the following license: +// ----------------------------------------------------------------------------- +/* +* Copyright (c) 2007-2011 SlimDX Group +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +*/ +namespace WPFHost +{ + using System; + using System.Runtime.InteropServices; + using System.Windows; + using System.Windows.Interop; + using SharpDX.Direct3D9; + + class DX10ImageSource : D3DImage, IDisposable + { + [DllImport("user32.dll", SetLastError = false)] + private static extern IntPtr GetDesktopWindow(); + private static int ActiveClients; + private static Direct3DEx D3DContext; + private static DeviceEx D3DDevice; + private Texture RenderTarget; + + public DX10ImageSource() + { + this.StartD3D(); + DX10ImageSource.ActiveClients++; + } + + public void Dispose() + { + this.SetRenderTargetDX10(null); + Disposer.RemoveAndDispose(ref this.RenderTarget); + + DX10ImageSource.ActiveClients--; + this.EndD3D(); + } + + public void InvalidateD3DImage() + { + if (this.RenderTarget != null) + { + base.Lock(); + base.AddDirtyRect(new Int32Rect(0, 0, base.PixelWidth, base.PixelHeight)); + base.Unlock(); + } + } + + public void SetRenderTargetDX10(SharpDX.Direct3D10.Texture2D renderTarget) + { + if (this.RenderTarget != null) + { + this.RenderTarget = null; + + base.Lock(); + base.SetBackBuffer(D3DResourceType.IDirect3DSurface9, IntPtr.Zero); + base.Unlock(); + } + + if (renderTarget == null) + return; + + if (!IsShareable(renderTarget)) + throw new ArgumentException("Texture must be created with ResourceOptionFlags.Shared"); + + Format format = DX10ImageSource.TranslateFormat(renderTarget); + if (format == Format.Unknown) + throw new ArgumentException("Texture format is not compatible with OpenSharedResource"); + + IntPtr handle = GetSharedHandle(renderTarget); + if (handle == IntPtr.Zero) + throw new ArgumentNullException("Handle"); + + this.RenderTarget = new Texture(DX10ImageSource.D3DDevice, renderTarget.Description.Width, renderTarget.Description.Height, 1, Usage.RenderTarget, format, Pool.Default, ref handle); + using (Surface surface = this.RenderTarget.GetSurfaceLevel(0)) + { + base.Lock(); + base.SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface.NativePointer); + base.Unlock(); + } + } + + private void StartD3D() + { + if (DX10ImageSource.ActiveClients != 0) + return; + + D3DContext = new Direct3DEx(); + + PresentParameters presentparams = new PresentParameters(); + presentparams.Windowed = true; + presentparams.SwapEffect = SwapEffect.Discard; + presentparams.DeviceWindowHandle = GetDesktopWindow(); + presentparams.PresentationInterval = PresentInterval.Default; + + DX10ImageSource.D3DDevice = new DeviceEx(D3DContext, 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.HardwareVertexProcessing | CreateFlags.Multithreaded | CreateFlags.FpuPreserve, presentparams); + } + + private void EndD3D() + { + if (DX10ImageSource.ActiveClients != 0) + return; + + Disposer.RemoveAndDispose(ref this.RenderTarget); + Disposer.RemoveAndDispose(ref DX10ImageSource.D3DDevice); + Disposer.RemoveAndDispose(ref DX10ImageSource.D3DContext); + } + + private IntPtr GetSharedHandle(SharpDX.Direct3D10.Texture2D Texture) + { + SharpDX.DXGI.Resource resource = Texture.QueryInterface(); + IntPtr result = resource.SharedHandle; + resource.Dispose(); + return result; + } + + private static Format TranslateFormat(SharpDX.Direct3D10.Texture2D Texture) + { + switch (Texture.Description.Format) + { + case SharpDX.DXGI.Format.R10G10B10A2_UNorm: + return SharpDX.Direct3D9.Format.A2B10G10R10; + + case SharpDX.DXGI.Format.R16G16B16A16_Float: + return SharpDX.Direct3D9.Format.A16B16G16R16F; + + case SharpDX.DXGI.Format.B8G8R8A8_UNorm: + return SharpDX.Direct3D9.Format.A8R8G8B8; + + default: + return SharpDX.Direct3D9.Format.Unknown; + } + } + + private static bool IsShareable(SharpDX.Direct3D10.Texture2D Texture) + { + return (Texture.Description.OptionFlags & SharpDX.Direct3D10.ResourceOptionFlags.Shared) != 0; + } + } +} diff --git a/Desktop/Direct3D10/WPFHost/Disposer.cs b/Desktop/Direct3D10/WPFHost/Disposer.cs new file mode 100644 index 00000000..1f8d5337 --- /dev/null +++ b/Desktop/Direct3D10/WPFHost/Disposer.cs @@ -0,0 +1,52 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace WPFHost +{ + public static class Disposer + { + /// + /// Dispose an object instance and set the reference to null + /// + /// The type of object to dispose + /// A reference to the instance for disposal + /// This method hides any thrown exceptions that might occur during disposal of the object (by design) + public static void RemoveAndDispose(ref TypeName resource) where TypeName : class + { + if (resource == null) + return; + + IDisposable disposer = resource as IDisposable; + if (disposer != null) + { + try + { + disposer.Dispose(); + } + catch + { + } + } + + resource = null; + } + } +} diff --git a/Desktop/Direct3D10/WPFHost/IScene.cs b/Desktop/Direct3D10/WPFHost/IScene.cs new file mode 100644 index 00000000..c7c6d273 --- /dev/null +++ b/Desktop/Direct3D10/WPFHost/IScene.cs @@ -0,0 +1,37 @@ +// Copyright (c) 2010-2013 SharpDX - Alexandre Mutel +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +namespace WPFHost +{ + using System; + using SharpDX.Direct3D10; + + public interface ISceneHost + { + Device Device { get; } + } + + public interface IScene + { + void Attach(ISceneHost host); + void Detach(); + void Update(TimeSpan timeSpan); + void Render(); + } +} diff --git a/Desktop/Direct3D10/WPFHost/MainWindow.xaml b/Desktop/Direct3D10/WPFHost/MainWindow.xaml new file mode 100644 index 00000000..f5154428 --- /dev/null +++ b/Desktop/Direct3D10/WPFHost/MainWindow.xaml @@ -0,0 +1,11 @@ + + + +