Search code examples
visual-c++comdirectx-11

How to save the contents of a COM object to a file Visual C++


I'm working my way through a DirectX11 tutorial and one of the "extra credit" exercises is to compile a shader and save the compiled code to a .shader file.

The program I ended up writing is super simple so I'll just list it here instead of explaining it in English.

The main program:

#include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>

#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    ID3D10Blob *VS, *Errors;
    D3DX11CompileFromFile(L"shaders.shader", 0, 0, "VShader", "vs_4_0", 0, 0, 0, &VS, &Errors, 0);

    if(Errors)
        MessageBox(NULL, L"The vertex shader failed to compile.", L"Error", MB_OK);
    else if(!Errors)
        MessageBox(NULL, L"The vertex shader compiled successfully.", L"Message", MB_OK);

    HANDLE sHandle = CreateFile(L"compiledShader.shader",
                                 GENERIC_WRITE, 
                                 FILE_SHARE_WRITE,
                                 NULL,
                                 CREATE_ALWAYS,
                                 FILE_ATTRIBUTE_NORMAL,
                                 NULL);

    if(WriteFile(sHandle, VS->GetBufferPointer(), VS->GetBufferSize(), NULL, NULL)) // <--- break point
        MessageBox(NULL, L"The compiled shader was saved successfully to 'compiledSahder.shader'", L"Message", MB_OK);
    else
        MessageBox(NULL, L"The vertex shader was not saved successfull.", L"Error", MB_OK);

    return 0;
}

And the shader:

float4 VShader(float4 position : POSITION) : SV_POSITION
{
    return position;
}

Since the contents of the VS Blob is where the compiled code is my first instinct is that I need to save the contents of that Blob to a .shader file. The only file writing I've worked with before is using fstream in basic C++ in linux so I'm unsure how to approach this. I've dug through the MSDN library for various file writing functions but I couldn't find anything that would let me write the content of a COM object to a file.

Let me know if you need any more information, and thanks in advanced for your help.

EDIT: the code has been updated per the suggestions of the current answer. I'm not 100% sure if I'm using these functions properly as I had to intuit how to by reading their descriptions on MSDN, but I think I'm on the right track. It creates the file, but when I try to write to it I'm getting the following error:

First-chance exception at 0x755cdeef in shader compiler.exe: 0xC0000005: Access violation writing location 0x00000000. Unhandled exception at 0x755cdeef in shader compiler.exe: 0xC0000005: Access violation writing location 0x00000000. The program '[5604] shader compiler.exe: Native' has exited with code -1073741819 (0xc0000005).

I feel like it's a simple mistake that is causing this problem. Any ideas?

EDIT #2: Here is what gets written to the file "compiledShader.shader"

Compiled shader code?

Does this look correct? If so I'll close the question as answered and worry about whatever is causing the generic access error on my own.


Solution

  • Look at the ID3D10Blob interface for the content, and check the CreateFile, WriteFile and CloseHandle Win32 functions.