// 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. // ----------------------------------------------------------------------------- // Original code from SlimDX project, ported from C++/CLI. // 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 System.IO; using System.Runtime.InteropServices; using System.Text; using SharpDX.Direct3D; namespace SharpDX.Direct3D9 { /// /// Represents the compiled bytecode of a shader or effect. /// /// Blob public class ShaderBytecode : DisposeBase { private bool isOwner; private Blob blob; private ConstantTable constantTable; /// /// Initializes a new instance of the class. /// /// A containing the compiled bytecode. public ShaderBytecode(DataStream data) { CreateFromPointer(data.PositionPointer, (int)(data.Length - data.Position)); } /// /// Initializes a new instance of the class. /// /// A containing the compiled bytecode. public ShaderBytecode(Stream data) { int size = (int)(data.Length - data.Position); byte[] localBuffer = new byte[size]; data.Read(localBuffer, 0, size); CreateFromBuffer(localBuffer); } /// /// Initializes a new instance of the class. /// /// The buffer. public ShaderBytecode(byte[] buffer) { CreateFromBuffer(buffer); } /// /// Initializes a new instance of the class. /// /// a pointer to a compiler bytecode /// size of the bytecode public ShaderBytecode(IntPtr buffer, int sizeInBytes) { BufferPointer = buffer; BufferSize = sizeInBytes; } /// /// Initializes a new instance of the class. /// /// The BLOB. protected internal ShaderBytecode(Blob blob) { this.blob = blob; BufferPointer = blob.BufferPointer; BufferSize = blob.BufferSize; } /// /// Gets the buffer pointer. /// public System.IntPtr BufferPointer { get; private set; } /// /// Gets or sets the size of the buffer. /// /// /// The size of the buffer. /// public SharpDX.PointerSize BufferSize { get; set; } /// /// Gets the shader constant table. /// /// HRESULT D3DXGetShaderConstantTable([In] const void* pFunction,[In] ID3DXConstantTable** ppConstantTable) public ConstantTable ConstantTable { get { if (constantTable != null) return constantTable; return constantTable = D3DX9.GetShaderConstantTable(BufferPointer); } } /// /// Gets the version of the shader. /// /// unsigned int D3DXGetShaderVersion([In] const void* pFunction) public int Version { get { return D3DX9.GetShaderVersion(BufferPointer); } } /// /// Gets the size of the shader from a function pointer. /// /// The shader function pointer. /// Size of the shader public static int GetShaderSize(IntPtr shaderFunctionPtr) { return D3DX9.GetShaderSize(shaderFunctionPtr); } /// /// Assembles a shader from the given source data. /// /// The source shader data. /// Compilation options. /// A object representing the raw shader stream. /// HRESULT D3DXAssembleShader([In] const void* pSrcData,[In] unsigned int SrcDataLen,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs) public static CompilationResult Assemble(byte[] sourceData, ShaderFlags flags) { return Assemble(sourceData, null, null, flags); } /// /// Assembles a shader from the given source data. /// /// The source shader data. /// Compilation options. /// A object representing the raw shader stream. /// HRESULT D3DXAssembleShader([In] const void* pSrcData,[In] unsigned int SrcDataLen,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs) public static CompilationResult Assemble(string sourceData, ShaderFlags flags) { return Assemble(sourceData, null, null, flags); } /// /// Assembles a shader from the given source data. /// /// The source shader data. /// Macro definitions. /// An interface to use for handling #include directives. /// Compilation options. /// A object representing the raw shader stream. /// HRESULT D3DXAssembleShader([In] const void* pSrcData,[In] unsigned int SrcDataLen,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs) public static CompilationResult Assemble(string sourceData, Macro[] defines, Include includeFile, ShaderFlags flags) { return Assemble(Encoding.ASCII.GetBytes(sourceData), defines, includeFile, flags); } /// /// Assembles a shader from the given source data. /// /// The source shader data. /// Macro definitions. /// An interface to use for handling #include directives. /// Compilation options. /// A object representing the raw shader stream. /// HRESULT D3DXAssembleShader([In] const void* pSrcData,[In] unsigned int SrcDataLen,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs) public static CompilationResult Assemble(byte[] sourceData, Macro[] defines, Include includeFile, ShaderFlags flags) { unsafe { var resultCode = Result.Ok; Blob blobForCode = null; Blob blobForErrors = null; try { fixed (void* pData = sourceData) D3DX9.AssembleShader( (IntPtr)pData, sourceData.Length, PrepareMacros(defines), IncludeShadow.ToIntPtr(includeFile), (int)flags, out blobForCode, out blobForErrors); } catch (SharpDXException ex) { if (blobForErrors != null) { resultCode = ex.ResultCode; if (Configuration.ThrowOnShaderCompileError) throw new CompilationException(ex.ResultCode, Utilities.BlobToString(blobForErrors)); } else { throw; } } return new CompilationResult(blobForCode != null ? new ShaderBytecode(blobForCode) : null, resultCode, Utilities.BlobToString(blobForErrors)); } } /// /// Assembles a shader from file. /// /// Name of the shader file. /// Compilation options. /// A object representing the raw shader stream. public static CompilationResult AssembleFromFile(string fileName, ShaderFlags flags) { return AssembleFromFile(fileName, null, null, flags); } /// /// Assembles a shader from file. /// /// Name of the shader file. /// Macro definitions. /// An interface to use for handling #include directives. /// Compilation options. /// /// A object representing the raw shader stream. /// public static CompilationResult AssembleFromFile(string fileName, Macro[] defines, Include includeFile, ShaderFlags flags) { return Assemble(File.ReadAllText(fileName), defines, includeFile, flags); } /// /// Compiles the provided shader or effect source. /// /// A string containing the source of the shader or effect to compile. /// The shader target or set of shader features to compile against. /// Shader compilation options. /// /// The compiled shader bytecode, or null if the method fails. /// /// HRESULT D3DXCompileShader([In] const char* pSrcData,[In] unsigned int SrcDataLen,[In] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] const char* pFunctionName,[In] const char* pProfile,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs,[In] ID3DXConstantTable** ppConstantTable) public static CompilationResult Compile(string shaderSource, string profile, ShaderFlags shaderFlags) { if (string.IsNullOrEmpty(shaderSource)) { throw new ArgumentNullException("shaderSource"); } return Compile(Encoding.ASCII.GetBytes(shaderSource), null, profile, shaderFlags, null, null); } /// /// Compiles the provided shader or effect source. /// /// An array of bytes containing the raw source of the shader or effect to compile. /// The shader target or set of shader features to compile against. /// Shader compilation options. /// /// The compiled shader bytecode, or null if the method fails. /// /// HRESULT D3DXCompileShader([In] const char* pSrcData,[In] unsigned int SrcDataLen,[In] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] const char* pFunctionName,[In] const char* pProfile,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs,[In] ID3DXConstantTable** ppConstantTable) public static CompilationResult Compile(byte[] shaderSource, string profile, ShaderFlags shaderFlags) { return Compile(shaderSource, null, profile, shaderFlags, null, null); } /// /// Compiles the provided shader or effect source. /// /// A string containing the source of the shader or effect to compile. /// The name of the shader entry-point function, or null for an effect file. /// The shader target or set of shader features to compile against. /// Shader compilation options. /// /// The compiled shader bytecode, or null if the method fails. /// /// HRESULT D3DXCompileShader([In] const char* pSrcData,[In] unsigned int SrcDataLen,[In] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] const char* pFunctionName,[In] const char* pProfile,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs,[In] ID3DXConstantTable** ppConstantTable) public static CompilationResult Compile(string shaderSource, string entryPoint, string profile, ShaderFlags shaderFlags) { if (string.IsNullOrEmpty(shaderSource)) { throw new ArgumentNullException("shaderSource"); } return Compile(Encoding.ASCII.GetBytes(shaderSource), entryPoint, profile, shaderFlags, null, null); } /// /// Compiles the provided shader or effect source. /// /// An array of bytes containing the raw source of the shader or effect to compile. /// The name of the shader entry-point function, or null for an effect file. /// The shader target or set of shader features to compile against. /// Shader compilation options. /// /// The compiled shader bytecode, or null if the method fails. /// /// HRESULT D3DXCompileShader([In] const char* pSrcData,[In] unsigned int SrcDataLen,[In] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] const char* pFunctionName,[In] const char* pProfile,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs,[In] ID3DXConstantTable** ppConstantTable) public static CompilationResult Compile(byte[] shaderSource, string entryPoint, string profile, ShaderFlags shaderFlags) { return Compile(shaderSource, entryPoint, profile, shaderFlags, null, null); } /// /// Compiles the provided shader or effect source. /// /// A string containing the source of the shader or effect to compile. /// The shader target or set of shader features to compile against. /// Shader compilation options. /// A set of macros to define during compilation. /// An interface for handling include files. /// /// The compiled shader bytecode, or null if the method fails. /// /// HRESULT D3DXCompileShader([In] const char* pSrcData,[In] unsigned int SrcDataLen,[In] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] const char* pFunctionName,[In] const char* pProfile,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs,[In] ID3DXConstantTable** ppConstantTable) public static CompilationResult Compile(string shaderSource, string profile, ShaderFlags shaderFlags, Macro[] defines, Include include) { if (string.IsNullOrEmpty(shaderSource)) { throw new ArgumentNullException("shaderSource"); } return Compile(Encoding.ASCII.GetBytes(shaderSource), null, profile, shaderFlags, defines, include); } /// /// Compiles the provided shader or effect source. /// /// An array of bytes containing the raw source of the shader or effect to compile. /// The shader target or set of shader features to compile against. /// Shader compilation options. /// A set of macros to define during compilation. /// An interface for handling include files. /// /// The compiled shader bytecode, or null if the method fails. /// /// HRESULT D3DXCompileShader([In] const char* pSrcData,[In] unsigned int SrcDataLen,[In] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] const char* pFunctionName,[In] const char* pProfile,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs,[In] ID3DXConstantTable** ppConstantTable) public static CompilationResult Compile(byte[] shaderSource, string profile, ShaderFlags shaderFlags, Macro[] defines, Include include) { return Compile(shaderSource, null, profile, shaderFlags, defines, include); } /// /// Compiles the provided shader or effect source. /// /// A string containing the source of the shader or effect to compile. /// The name of the shader entry-point function, or null for an effect file. /// The shader target or set of shader features to compile against. /// Shader compilation options. /// A set of macros to define during compilation. /// An interface for handling include files. /// /// The compiled shader bytecode, or null if the method fails. /// /// HRESULT D3DXCompileShader([In] const char* pSrcData,[In] unsigned int SrcDataLen,[In] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] const char* pFunctionName,[In] const char* pProfile,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs,[In] ID3DXConstantTable** ppConstantTable) public static CompilationResult Compile(string shaderSource, string entryPoint, string profile, ShaderFlags shaderFlags, Macro[] defines, Include include) { if (string.IsNullOrEmpty(shaderSource)) { throw new ArgumentNullException("shaderSource"); } return Compile(Encoding.ASCII.GetBytes(shaderSource), entryPoint, profile, shaderFlags, defines, include); } /// /// Compiles a shader or effect from a file on disk. /// /// The name of the source file to compile. /// The shader target or set of shader features to compile against. /// Shader compilation options. /// A set of macros to define during compilation. /// An interface for handling include files. /// /// The compiled shader bytecode, or null if the method fails. /// /// HRESULT D3DXCompileShader([In] const char* pSrcData,[In] unsigned int SrcDataLen,[In] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] const char* pFunctionName,[In] const char* pProfile,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs,[In] ID3DXConstantTable** ppConstantTable) public static CompilationResult CompileFromFile(string fileName, string profile, ShaderFlags shaderFlags = ShaderFlags.None, Macro[] defines = null, Include include = null) { return CompileFromFile(fileName, null, profile, shaderFlags, defines, include); } /// /// Compiles a shader or effect from a file on disk. /// /// The name of the source file to compile. /// The name of the shader entry-point function, or null for an effect file. /// The shader target or set of shader features to compile against. /// Shader compilation options. /// A set of macros to define during compilation. /// An interface for handling include files. /// /// The compiled shader bytecode, or null if the method fails. /// /// HRESULT D3DXCompileShader([In] const char* pSrcData,[In] unsigned int SrcDataLen,[In] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] const char* pFunctionName,[In] const char* pProfile,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs,[In] ID3DXConstantTable** ppConstantTable) public static CompilationResult CompileFromFile(string fileName, string entryPoint, string profile, ShaderFlags shaderFlags = ShaderFlags.None, Macro[] defines = null, Include include = null) { if (fileName == null) { throw new ArgumentNullException("fileName"); } if (profile == null) { throw new ArgumentNullException("profile"); } if (!File.Exists(fileName)) { throw new FileNotFoundException("Could not open the shader or effect file.", fileName); } return Compile(File.ReadAllText(fileName), entryPoint, profile, shaderFlags, PrepareMacros(defines), include); } /// /// Compiles the provided shader or effect source. /// /// An array of bytes containing the raw source of the shader or effect to compile. /// The name of the shader entry-point function, or null for an effect file. /// The shader target or set of shader features to compile against. /// Shader compilation options. /// A set of macros to define during compilation. /// An interface for handling include files. /// /// The compiled shader bytecode, or null if the method fails. /// /// HRESULT D3DXCompileShader([In] const char* pSrcData,[In] unsigned int SrcDataLen,[In] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] const char* pFunctionName,[In] const char* pProfile,[In] unsigned int Flags,[In] ID3DXBuffer** ppShader,[In] ID3DXBuffer** ppErrorMsgs,[In] ID3DXConstantTable** ppConstantTable) public static CompilationResult Compile(byte[] shaderSource, string entryPoint, string profile, ShaderFlags shaderFlags, Macro[] defines, Include include) { unsafe { var resultCode = Result.Ok; Blob blobForCode = null; Blob blobForErrors = null; ConstantTable constantTable = null; try { fixed (void* pData = &shaderSource[0]) D3DX9.CompileShader( (IntPtr)pData, shaderSource.Length, PrepareMacros(defines), IncludeShadow.ToIntPtr(include), entryPoint, profile, (int)shaderFlags, out blobForCode, out blobForErrors, out constantTable); } catch (SharpDXException ex) { if (blobForErrors != null) { resultCode = ex.ResultCode; if (Configuration.ThrowOnShaderCompileError) throw new CompilationException(ex.ResultCode, Utilities.BlobToString(blobForErrors)); } else { throw; } } finally { if (constantTable != null) constantTable.Dispose(); } return new CompilationResult(blobForCode != null ? new ShaderBytecode(blobForCode) : null, resultCode, Utilities.BlobToString(blobForErrors)); } } /// /// Disassembles compiled HLSL code back into textual source. /// /// The textual source of the shader or effect. /// HRESULT D3DXDisassembleShader([In] const void* pShader,[In] BOOL EnableColorCode,[In] const char* pComments,[In] ID3DXBuffer** ppDisassembly) public string Disassemble() { return this.Disassemble(false, null); } /// /// Disassembles compiled HLSL code back into textual source. /// /// if set to true [enable color code]. /// /// The textual source of the shader or effect. /// /// HRESULT D3DXDisassembleShader([In] const void* pShader,[In] BOOL EnableColorCode,[In] const char* pComments,[In] ID3DXBuffer** ppDisassembly) public string Disassemble(bool enableColorCode) { return this.Disassemble(enableColorCode, null); } /// /// Disassembles compiled HLSL code back into textual source. /// /// if set to true [enable color code]. /// Commenting information to embed in the disassembly. /// /// The textual source of the shader or effect. /// /// HRESULT D3DXDisassembleShader([In] const void* pShader,[In] BOOL EnableColorCode,[In] const char* pComments,[In] ID3DXBuffer** ppDisassembly) public string Disassemble(bool enableColorCode, string comments) { Blob output; D3DX9.DisassembleShader(BufferPointer, enableColorCode, comments, out output); return Utilities.BlobToString(output); } /// /// Searches through the shader for the specified comment. /// /// A FOURCC code used to identify the comment. /// The comment data. /// HRESULT D3DXFindShaderComment([In] const void* pFunction,[In] unsigned int FourCC,[Out] const void** ppData,[Out] unsigned int* pSizeInBytes) public DataStream FindComment(Format fourCC) { IntPtr buffer; int size; D3DX9.FindShaderComment(BufferPointer, (int)fourCC, out buffer, out size); return new DataStream(buffer, size, true, true); } /// /// Gets the set of semantics for shader inputs. /// /// The set of semantics for shader inputs. /// HRESULT D3DXGetShaderInputSemantics([In] const void* pFunction,[In, Out, Buffer] D3DXSEMANTIC* pSemantics,[InOut] unsigned int* pCount) public ShaderSemantic[] GetInputSemantics() { int count = 0; D3DX9.GetShaderInputSemantics(BufferPointer, null, ref count); if (count == 0) return null; var buffer = new ShaderSemantic[count]; D3DX9.GetShaderInputSemantics(BufferPointer, buffer, ref count); return buffer; } /// /// Gets the set of semantics for shader outputs. /// /// The set of semantics for shader outputs. /// HRESULT D3DXGetShaderOutputSemantics([In] const void* pFunction,[In, Out, Buffer] D3DXSEMANTIC* pSemantics,[InOut] unsigned int* pCount) public ShaderSemantic[] GetOutputSemantics() { int count = 0; D3DX9.GetShaderOutputSemantics(BufferPointer, null, ref count); if (count == 0) return null; var buffer = new ShaderSemantic[count]; D3DX9.GetShaderOutputSemantics(BufferPointer, buffer, ref count); return buffer; } /// /// Gets the sampler names references in the shader. /// /// The set of referenced sampler names. /// HRESULT D3DXGetShaderSamplers([In] const void* pFunction,[In] const char** pSamplers,[In] unsigned int* pCount) public string[] GetSamplers() { unsafe { int count = 0; D3DX9.GetShaderSamplers(BufferPointer, IntPtr.Zero, ref count); if (count == 0) return null; var result = new string[count]; if (count < 1024) { var pointers = stackalloc IntPtr[count]; D3DX9.GetShaderSamplers(BufferPointer, (IntPtr)pointers, ref count); for (int i = 0; i < count; i++) result[i] = Marshal.PtrToStringAnsi(pointers[i]); } else { var pointers = new IntPtr[count]; fixed (void* pPointers = pointers) D3DX9.GetShaderSamplers(BufferPointer, (IntPtr)pPointers, ref count); for (int i = 0; i < count; i++) result[i] = Marshal.PtrToStringAnsi(pointers[i]); } return result; } } /// /// Extracts the major version component of a shader version number. /// /// The shader version number. /// The major version component. public static int MajorVersion(int version) { return ((version >> 8) & 0xff); } /// /// Extracts the minor version component of a shader version number. /// /// The shader version number. /// The minor version component. public static int MinorVersion(int version) { return (version & 0xff); } /// /// Converts a shader version number into a managed object. /// /// The shader version number. /// The parsed shader version information. public static Version ParseVersion(int version) { return new Version((version >> 8) & 0xff, version & 0xff); } /// /// Loads from the specified stream. /// /// The stream. /// A shader bytecode public static ShaderBytecode Load(Stream stream) { var buffer = Utilities.ReadStream(stream); return new ShaderBytecode(buffer); } /// /// Saves to the specified file name. /// /// Name of the file. public void Save(string fileName) { using (var stream = new FileStream(fileName, FileMode.Create, FileAccess.Write)) Save(stream); } /// /// Saves this bytecode to the specified stream. /// /// The stream. public void Save(Stream stream) { if (BufferSize == 0) return; var buffer = new byte[BufferSize]; Utilities.Read(BufferPointer, buffer, 0, buffer.Length); stream.Write(buffer, 0, buffer.Length); } /// /// Create a ShaderBytecode from a pointer. /// /// The pointer. /// public static ShaderBytecode FromPointer(IntPtr pointer) { // TODO: check that pointer is a blob? return new ShaderBytecode(new Blob(pointer)); } /// /// Preprocesses the provided shader or effect source. /// /// A string containing the source of the shader or effect to preprocess. /// A set of macros to define during preprocessing. /// An interface for handling include files. /// The preprocessed shader source. /// HRESULT D3DXPreprocessShader([In] const void* pSrcData,[In] unsigned int SrcDataSize,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] ID3DXBuffer** ppShaderText,[In] ID3DXBuffer** ppErrorMsgs) public static string Preprocess(string shaderSource, Macro[] defines = null, Include include = null) { string errors = null; if (string.IsNullOrEmpty(shaderSource)) { throw new ArgumentNullException("shaderSource"); } var shaderSourcePtr = Marshal.StringToHGlobalAnsi(shaderSource); try { return Preprocess(shaderSourcePtr, shaderSource.Length, defines, include, out errors); } finally { if (shaderSourcePtr != IntPtr.Zero) Marshal.FreeHGlobal(shaderSourcePtr); } } /// /// Preprocesses the provided shader or effect source. /// /// An array of bytes containing the raw source of the shader or effect to preprocess. /// A set of macros to define during preprocessing. /// An interface for handling include files. /// The preprocessed shader source. /// HRESULT D3DXPreprocessShader([In] const void* pSrcData,[In] unsigned int SrcDataSize,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] ID3DXBuffer** ppShaderText,[In] ID3DXBuffer** ppErrorMsgs) public static string Preprocess(byte[] shaderSource, Macro[] defines = null, Include include = null) { string errors = null; return Preprocess(shaderSource, defines, include, out errors); } /// /// Preprocesses the provided shader or effect source. /// /// An array of bytes containing the raw source of the shader or effect to preprocess. /// A set of macros to define during preprocessing. /// An interface for handling include files. /// When the method completes, contains a string of compilation errors, or an empty string if preprocessing succeeded. /// The preprocessed shader source. /// HRESULT D3DXPreprocessShader([In] const void* pSrcData,[In] unsigned int SrcDataSize,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] ID3DXBuffer** ppShaderText,[In] ID3DXBuffer** ppErrorMsgs) public static string Preprocess(byte[] shaderSource, Macro[] defines, Include include, out string compilationErrors) { unsafe { fixed (void* pData = &shaderSource[0]) return Preprocess((IntPtr)pData, shaderSource.Length, defines, include, out compilationErrors); } } /// /// Preprocesses the provided shader or effect source. /// /// The shader source PTR. /// Length of the shader source. /// A set of macros to define during preprocessing. /// An interface for handling include files. /// When the method completes, contains a string of compilation errors, or an empty string if preprocessing succeeded. /// /// The preprocessed shader source. /// /// HRESULT D3DXPreprocessShader([In] const void* pSrcData,[In] unsigned int SrcDataSize,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] ID3DXBuffer** ppShaderText,[In] ID3DXBuffer** ppErrorMsgs) public static string Preprocess(IntPtr shaderSourcePtr, int shaderSourceLength, Macro[] defines, Include include, out string compilationErrors) { unsafe { Blob blobForText = null; Blob blobForErrors = null; compilationErrors = null; try { D3DX9.PreprocessShader(shaderSourcePtr, shaderSourceLength, PrepareMacros(defines), IncludeShadow.ToIntPtr(include), out blobForText, out blobForErrors); } catch (SharpDXException ex) { if (blobForErrors != null) { compilationErrors = Utilities.BlobToString(blobForErrors); throw new CompilationException(ex.ResultCode, compilationErrors); } throw; } return Utilities.BlobToString(blobForText); } } /// /// Preprocesses the provided shader or effect source. /// /// A string containing the source of the shader or effect to preprocess. /// A set of macros to define during preprocessing. /// An interface for handling include files. /// When the method completes, contains a string of compilation errors, or an empty string if preprocessing succeeded. /// The preprocessed shader source. /// HRESULT D3DXPreprocessShader([In] const void* pSrcData,[In] unsigned int SrcDataSize,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] ID3DXBuffer** ppShaderText,[In] ID3DXBuffer** ppErrorMsgs) public static string Preprocess(string shaderSource, Macro[] defines, Include include, out string compilationErrors) { if (string.IsNullOrEmpty(shaderSource)) { throw new ArgumentNullException("shaderSource"); } var shaderSourcePtr = Marshal.StringToHGlobalAnsi(shaderSource); try { return Preprocess(shaderSourcePtr, shaderSource.Length, defines, include, out compilationErrors); } finally { if (shaderSourcePtr != IntPtr.Zero) Marshal.FreeHGlobal(shaderSourcePtr); } } /// /// Preprocesses a shader or effect from a file on disk. /// /// The name of the source file to compile. /// The preprocessed shader source. /// HRESULT D3DXPreprocessShader([In] const void* pSrcData,[In] unsigned int SrcDataSize,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] ID3DXBuffer** ppShaderText,[In] ID3DXBuffer** ppErrorMsgs) public static string PreprocessFromFile(string fileName) { string errors = null; if (fileName == null) { throw new ArgumentNullException("fileName"); } if (!File.Exists(fileName)) { throw new FileNotFoundException("Could not open the shader or effect file.", fileName); } string str = File.ReadAllText(fileName); if (string.IsNullOrEmpty(str)) { throw new ArgumentNullException("fileName"); } return Preprocess(Encoding.ASCII.GetBytes(str), null, null, out errors); } /// /// Preprocesses a shader or effect from a file on disk. /// /// The name of the source file to compile. /// A set of macros to define during preprocessing. /// An interface for handling include files. /// The preprocessed shader source. /// HRESULT D3DXPreprocessShader([In] const void* pSrcData,[In] unsigned int SrcDataSize,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] ID3DXBuffer** ppShaderText,[In] ID3DXBuffer** ppErrorMsgs) public static string PreprocessFromFile(string fileName, Macro[] defines, Include include) { string errors = null; return PreprocessFromFile(fileName, defines, include, out errors); } /// /// Preprocesses a shader or effect from a file on disk. /// /// The name of the source file to compile. /// A set of macros to define during preprocessing. /// An interface for handling include files. /// When the method completes, contains a string of compilation errors, or an empty string if preprocessing succeeded. /// The preprocessed shader source. /// HRESULT D3DXPreprocessShader([In] const void* pSrcData,[In] unsigned int SrcDataSize,[In, Buffer] const D3DXMACRO* pDefines,[In] ID3DXInclude* pInclude,[In] ID3DXBuffer** ppShaderText,[In] ID3DXBuffer** ppErrorMsgs) public static string PreprocessFromFile(string fileName, Macro[] defines, Include include, out string compilationErrors) { if (fileName == null) { throw new ArgumentNullException("fileName"); } if (!File.Exists(fileName)) { throw new FileNotFoundException("Could not open the shader or effect file.", fileName); } return Preprocess(File.ReadAllText(fileName), defines, include, out compilationErrors); } /// /// Gets the raw data of the compiled bytecode. /// public DataStream Data { get { return new DataStream(BufferPointer, BufferSize, true, true); } } /// /// Read a compiled shader bytecode from a Stream and return a ShaderBytecode /// /// /// public static ShaderBytecode FromStream(Stream stream) { return new ShaderBytecode(stream); } /// /// Read a compiled shader bytecode from a Stream and return a ShaderBytecode /// /// /// public static ShaderBytecode FromFile(string fileName) { return new ShaderBytecode(File.ReadAllBytes(fileName)); } internal static Macro[] PrepareMacros(Macro[] macros) { if (macros == null) return null; if (macros.Length == 0) return null; if (macros[macros.Length - 1].Name == null && macros[macros.Length - 1].Definition == null) return macros; var macroArray = new Macro[macros.Length + 1]; Array.Copy(macros, macroArray, macros.Length); macroArray[macros.Length] = new Macro(null, null); return macroArray; } protected override void Dispose(bool disposing) { if (disposing) { if (blob != null) { blob.Dispose(); blob = null; } if (constantTable != null) { constantTable.Dispose(); constantTable = null; } } if (isOwner && BufferPointer != IntPtr.Zero) { Marshal.FreeHGlobal(BufferPointer); BufferPointer = IntPtr.Zero; BufferSize = 0; } } private void CreateFromBuffer(byte[] buffer) { unsafe { fixed (void* pBuffer = &buffer[0]) CreateFromPointer((IntPtr)pBuffer, buffer.Length); } } private void CreateFromPointer(IntPtr buffer, int sizeInBytes) { // D3DCommon.CreateBlob(sizeInBytes, this); BufferPointer = Marshal.AllocHGlobal(sizeInBytes); BufferSize = sizeInBytes; isOwner = true; Utilities.CopyMemory(BufferPointer, buffer, sizeInBytes); } } }