// Copyright (c) 2010-2014 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.Collections.Generic; using System.Runtime.InteropServices; using SharpDX.Direct3D; namespace SharpDX.Direct3D12 { public partial class RootSignatureDescription { //public partial struct RootSignatureDescription { // /// unsigned int NumParameters // public int ParameterCount; // /// D3D12_ROOT_PARAMETER pParameters // public System.IntPtr ParametersPointer; // /// unsigned int Flags // public int Flags; //} /// /// Initializes a new instance of the class. /// public RootSignatureDescription() : this(RootSignatureFlags.None) { } /// /// Initializes a new instance of the class. /// /// The flags. /// The parameters. /// The samplers. public RootSignatureDescription(RootSignatureFlags flags, RootParameter[] parameters = null, StaticSamplerDescription[] samplers = null) { Parameters = parameters; StaticSamplers = samplers; Flags = flags; } public RootSignatureDescription(IntPtr pNativePtr) { Deserialize(pNativePtr); } /// /// The parameters /// public RootParameter[] Parameters { get; set; } /// /// The static samplers. /// public StaticSamplerDescription[] StaticSamplers { get; set; } /// /// The flags /// public RootSignatureFlags Flags { get; set; } /// /// Serializes this description to a blob. /// /// A serialized version of this description. /// If an error occured while serializing the description /// dn859363 /// HRESULT D3D12SerializeRootSignature([In] const void* pRootSignature,[In] D3D_ROOT_SIGNATURE_VERSION Version,[Out] ID3D10Blob** ppBlob,[Out, Optional] ID3D10Blob** ppErrorBlob) /// D3D12SerializeRootSignature public Blob Serialize() { string errorText; Blob blob; var result = Serialize(out blob, out errorText); if(result.Failure) { throw new SharpDXException(result, errorText); } return blob; } /// /// Serializes this description to a blob. /// /// A serialized version of this description. /// dn859363 /// HRESULT D3D12SerializeRootSignature([In] const void* pRootSignature,[In] D3D_ROOT_SIGNATURE_VERSION Version,[Out] ID3D10Blob** ppBlob,[Out, Optional] ID3D10Blob** ppErrorBlob) /// D3D12SerializeRootSignature private unsafe Result Serialize(out Blob result, out string errorText) { Blob error; errorText = null; int length = 0; var rootParameters = (RootParameter.__Native* )0; var pinnedTables = new List(); try { if(Parameters != null) { length = Parameters.Length; rootParameters = (RootParameter.__Native*)Utilities.AllocateMemory(length * Utilities.SizeOf()); for (int i = 0; i < length; i++) { rootParameters[i] = Parameters[i].native; if(rootParameters[i].ParameterType == RootParameterType.DescriptorTable && Parameters[i].DescriptorTable != null) { var handle = GCHandle.Alloc(Parameters[i].DescriptorTable, GCHandleType.Pinned); pinnedTables.Add(handle); rootParameters[i].Union.DescriptorTable.DescriptorRangeCount = Parameters[i].DescriptorTable.Length; rootParameters[i].Union.DescriptorTable.DescriptorRangesPointer = handle.AddrOfPinnedObject(); } } } fixed (void* pSamplers = StaticSamplers) { __Native native; native.ParameterCount = length; native.ParametersPointer = new IntPtr(rootParameters); if(StaticSamplers != null) { native.StaticSamplerCount = StaticSamplers.Length; native.StaticSamplerPointer = new IntPtr(pSamplers); } native.Flags = Flags; var hresult = D3D12.SerializeRootSignature(new IntPtr(&native), RootSignatureVersion.Version1, out result, out error); // TODO: check hresult or just rely on error? if(error != null) { errorText = Utilities.BlobToString(error); } return hresult; } } finally { if(new IntPtr(rootParameters) != IntPtr.Zero) { Utilities.FreeMemory(new IntPtr(rootParameters)); } foreach(var handle in pinnedTables) { handle.Free(); } } } private unsafe void Deserialize(IntPtr pNativePtr) { if(pNativePtr == IntPtr.Zero) { return; } __Native* pNative = (__Native*)pNativePtr; if (pNative->ParameterCount > 0) { Parameters = new RootParameter[pNative->ParameterCount]; RootParameter.__Native* rpn = (RootParameter.__Native * ) pNative->ParametersPointer; for (int i = 0; i < Parameters.Length; ++i) { Parameters[i] = new RootParameter(); if (rpn[i].ParameterType == RootParameterType.DescriptorTable) { // Marshal descriptor table DescriptorRange[] ranges = null; int rangeCount = rpn[i].Union.DescriptorTable.DescriptorRangeCount; if (rangeCount > 0) { ranges = new DescriptorRange[rangeCount]; Utilities.Read(rpn[i].Union.DescriptorTable.DescriptorRangesPointer, ranges, 0, ranges.Length); } Parameters[i] = new RootParameter(rpn[i].ShaderVisibility, ranges); } else { // No need to marshal them when RootParameter don't contain DescriptorTable - simple copy as-is Parameters[i] = new RootParameter {native = *rpn}; } } } if (pNative->StaticSamplerCount > 0) { StaticSamplers = new StaticSamplerDescription[pNative->StaticSamplerCount]; Utilities.Read(pNative->StaticSamplerPointer, StaticSamplers, 0, StaticSamplers.Length); } } internal partial struct __Native { /// unsigned int NumParameters public int ParameterCount; /// D3D12_ROOT_PARAMETER pParameters public System.IntPtr ParametersPointer; public int StaticSamplerCount; public System.IntPtr StaticSamplerPointer; /// unsigned int Flags public RootSignatureFlags Flags; } } }