0

I have taken parts of the code from Shazzam Shader Editor (http://shazzam.codeplex.com/) and modified the code to use the Compile From file instead of memory (https://msdn.microsoft.com/en-us/library/windows/desktop/hh446872(v=vs.85).aspx)

 <Guid("8BA5FB08-5195-40e2-AC58-0D989C3A0102"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
    Private Interface ID3DBlob
        <PreserveSig> _
        Function GetBufferPointer() As IntPtr
        <PreserveSig> _
        Function GetBufferSize() As Integer
    End Interface

    <PreserveSig> _
    <DllImport("d3dcompiler_47.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.Cdecl)> _
    Private Function D3DCompileFromFile(<MarshalAs(UnmanagedType.LPTStr)> pFilename As String,
                                                          pDefines As IntPtr,
                                                          pInclude As IntPtr,
                                                          <MarshalAs(UnmanagedType.LPTStr)> pEntrypoint As String,
                                                          <MarshalAs(UnmanagedType.LPTStr)> pTarget As String,
                                                          flags1 As Integer,
                                                          flags2 As Integer,
                                                          ByRef ppCode As ID3DBlob,
                                                          ByRef ppErrorMsgs As ID3DBlob) As Integer
    End Function

    Public Sub Compile(ByVal File As HLSLFileHelperClass)
        Dim pFilename As String = File.GetSourceFileFullName ' C:\MyPSFiles\GaussianFilter.fx
        Dim pDefines As IntPtr = IntPtr.Zero
        Dim pInclude As IntPtr = IntPtr.Zero

        Dim pEntrypoint As String = File.HLSLEntryPoint ' main
        Dim pTarget As String = File.ShaderCompilerVersion.ToString ' ps_3_0

        Dim flags1 As Integer = 0
        Dim flags2 As Integer = 0
        Dim ppCode As ID3DBlob
        Dim ppErrorMsgs As ID3DBlob

        Dim CompileResult As Integer = 0

        CompileResult = D3DCompileFromFile(pFilename,
                                           pDefines,
                                           pInclude,
                                           pEntrypoint,
                                           pTarget,
                                           flags1,
                                           flags2,
                                           ppCode,
                                           ppErrorMsgs)

        If CompileResult <> 0 Then

            Dim errors As IntPtr = ppErrorMsgs.GetBufferPointer()

            Dim size As Integer = ppErrorMsgs.GetBufferSize()

            ErrorText = Marshal.PtrToStringAnsi(errors)
            IsCompiled = False
        Else
            ErrorText = ""
            IsCompiled = True
            Dim psPath = File.GetCompiledFileFullName
            Dim pCompiledPs As IntPtr = ppCode.GetBufferPointer()
            Dim compiledPsSize As Integer = ppCode.GetBufferSize()

            Dim compiledPs = New Byte(compiledPsSize - 1) {}
            Marshal.Copy(pCompiledPs, compiledPs, 0, compiledPs.Length)
            Using psFile = IO.File.Open(psPath, FileMode.Create, FileAccess.Write)
                psFile.Write(compiledPs, 0, compiledPs.Length)
            End Using
        End If

        If ppCode IsNot Nothing Then
            Marshal.ReleaseComObject(ppCode)
        End If
        ppCode = Nothing

        If ppErrorMsgs IsNot Nothing Then
            Marshal.ReleaseComObject(ppErrorMsgs)
        End If
        ppErrorMsgs = Nothing


    End Sub

The code as it is now gives me the error:

A call to PInvoke function '::D3DCompileFromFile' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

If I remove the line:

CallingConvention:=CallingConvention.Cdecl

The compiler seems to run, but now I get the error message:

X3506 unrecognized compiler target 'p'

It seems to just read the first char in the string? So, what am I doing wrong here?

1 Answers1

0

Got it working and I did two things:

First I moved it all into a Module:

Module Extend
    <Guid("8BA5FB08-5195-40e2-AC58-0D989C3A0102"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
    Public Interface ID3DBlob
        <PreserveSig> _
        Function GetBufferPointer() As IntPtr
        <PreserveSig> _
        Function GetBufferSize() As Integer
    End Interface

    <PreserveSig> _
    <DllImport("d3dcompiler_47.dll", CharSet:=CharSet.Auto)> _
    Public Function D3DCompileFromFile(<MarshalAs(UnmanagedType.LPTStr)> pFilename As String,
                                                          pDefines As IntPtr,
                                                          pInclude As IntPtr,
                                                          <MarshalAs(UnmanagedType.LPStr)> pEntrypoint As String,
                                                          <MarshalAs(UnmanagedType.LPStr)> pTarget As String,
                                                          flags1 As Integer,
                                                          flags2 As Integer,
                                                          ByRef ppCode As ID3DBlob,
                                                          ByRef ppErrorMsgs As ID3DBlob) As Integer
    End Function
End Module

Secondly I changed the:

<MarshalAs(UnmanagedType.LPTStr)>

to

<MarshalAs(UnmanagedType.LPStr)>

Seems I got a bit frustrated and changed things that worked too :S