Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

My shader creation code looks like this.

std::shared_ptr<IRenderUtility::IVertexShader> D3D11RenderUtility::CreateVertexShader(IShader::INIT_DESC & desc) const
{
    HRESULT result;
    ID3D10Blob * errorMessage;
    ID3D10Blob * vertexShaderBuffer;
    ID3D11VertexShader * vertShader;
    D3D11VertexShader::INIT_DESC vertShaderDesc;
    char errorMsg[255];

    result = D3DX11CompileFromFileA(desc.fileName.c_str(), NULL, NULL, desc.entryPoint.c_str(), "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, &vertexShaderBuffer, &errorMessage, NULL);
    if(FAILED(result))
    {
        if(errorMessage)
        {
            OutputErrorBlob(errorMessage, desc.fileName.c_str());
        }

        sprintf_s(errorMsg, "D3D11_Renderer | D3D11RenderUtility::CreateVertexShader \n\tfailed to compile shader file %s %i", desc.fileName, __LINE__);
        throw std::exception(errorMsg);
    }

    result = m_Device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &vertShader);
    if(FAILED(result))
    {
        sprintf_s(errorMsg, "D3D11_Renderer | D3D11RenderUtility::CreateVertexShader \n\tfailed to create the vertex shader %i", __LINE__);
        throw std::exception(errorMsg);
    }

    vertexShaderBuffer->Release();
    vertexShaderBuffer = 0;

    vertShaderDesc.shader = vertShader;

    return std::shared_ptr<IVertexShader>(new D3D11VertexShader(vertShaderDesc));
}

IRenderUtility, D3D11RenderUtility, IVertexShader, D3D11VertexShader, and IShader are my stuff. My question only pertains to the Shader creation code. At a later point, after the shader is made, i would like to create an input layout, but without the blob to get a pointer to the compiled shader, i cannot. Is there any way to obtain a pointer to the compiled shader from ID3D11VertexShader after it is created, or should i keep the blob around, storing it in my VertexShader object? How big is it?

share|improve this question
    
"How big is it?" You can answer that question yourself by calling GetBufferSize(). I wouldn't expect the shader bytecode to be more than a few KB - maybe into the tens of KB for a big, complex shader - so keeping the bytecode around shouldn't be an issue. –  Nathan Reed Apr 25 '13 at 18:25
add comment

2 Answers

You can use (ID3D10Blob*)->GetBufferPointer() to get what you need and dispose of the Vertex Buffer once you have finished

bool LightSpecularShader::createInputLayout(ID3D11Device* device, ID3D10Blob* vertexShaderBuffer)
{
    D3D11_INPUT_ELEMENT_DESC polygonLayout[3];
    unsigned int numElements;

    //Setup shader desc here...

    // Create the vertex input layout.
    HRESULT result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), 
                                       &_layout);
    if(FAILED(result))        
        return false;

    return true;
}

bool LightSpecularShader::initialiseShader()
{
    HRESULT result;

    ID3D10Blob* vertexShaderBuffer(nullptr);
    ID3D10Blob* pixelShaderBuffer(nullptr); 


    if(!compileVSShader(vertexShaderBuffer,vsFilename,hwnd))
            return false;

    if(!compilePSShader(pixelShaderBuffer,psFilename, hwnd))
            return false;

    result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &_vertexShader);
    if(FAILED(result))
            return false;

    result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &_pixelShader);
    if(FAILED(result))
            return false;

    if(!createInputLayout(device,vertexShaderBuffer))
            return false;

    // Release the vertex shader buffer and pixel shader buffer since they are no longer needed.
    vertexShaderBuffer->Release();
    vertexShaderBuffer = nullptr;

    pixelShaderBuffer->Release();
    pixelShaderBuffer = nullptr;

    //Rest of initialisation code

    return true;
}
share|improve this answer
add comment

In general, and because vertex shaders and input layouts are so tightly coupled, I prefer to create both at the same time, i.e. something like this (not the exact code, just for illustration):

HRESULT CreateVertexShaderAndInputLayout (ID3D11VertexShader **vs, ID3D11InputLayout **il, otherParams...)

This ensures that your layout is valid for the shader and that you have no blobs left hanging around that you may forget to Release. It comes at the expense of potentially having multiple duplicate input layouts, of course, but I don't consider it that big a deal.

Another option is to use shader reflection to get at the vertex shader input, but that of course won't get you the per-instance attributes of the layout, if you use them, so I don't consider it viable.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.