Ejemplo n.º 1
0
GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout)
{
    ASSERT(mFence->isSet());

    bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);

    if (mFence->test(flushCommandBuffer))
    {
        return GL_ALREADY_SIGNALED;
    }

    if (mFence->hasError())
    {
        return GL_WAIT_FAILED;
    }

    if (timeout == 0)
    {
        return GL_TIMEOUT_EXPIRED;
    }

    LARGE_INTEGER currentCounter = { 0 };
    BOOL success = QueryPerformanceCounter(&currentCounter);
    UNUSED_ASSERTION_VARIABLE(success);
    ASSERT(success);

    LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout) * static_cast<LONGLONG>(1000000ll);
    LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;

    while (currentCounter.QuadPart < endCounter && !mFence->test(flushCommandBuffer))
    {
        Sleep(0);
        BOOL success = QueryPerformanceCounter(&currentCounter);
        UNUSED_ASSERTION_VARIABLE(success);
        ASSERT(success);
    }

    if (mFence->hasError())
    {
        return GL_WAIT_FAILED;
    }

    if (currentCounter.QuadPart >= endCounter)
    {
        return GL_TIMEOUT_EXPIRED;
    }

    return GL_CONDITION_SATISFIED;
}
Ejemplo n.º 2
0
// Increments refcount on surface.
// caller must Release() the returned surface
gl::Error TextureStorage9_2D::getSurfaceLevel(GLenum target,
                                              int level,
                                              bool dirty,
                                              IDirect3DSurface9 **outSurface)
{
    ASSERT(target == GL_TEXTURE_2D);
    UNUSED_ASSERTION_VARIABLE(target);

    IDirect3DBaseTexture9 *baseTexture = NULL;
    gl::Error error = getBaseTexture(&baseTexture);
    if (error.isError())
    {
        return error;
    }

    IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9*>(baseTexture);

    HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface);

    ASSERT(SUCCEEDED(result));
    if (FAILED(result))
    {
        return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the surface from a texture, result: 0x%X.", result);
    }

    // With managed textures the driver needs to be informed of updates to the lower mipmap levels
    if (level + mTopLevel != 0 && isManaged() && dirty)
    {
        texture->AddDirtyRect(NULL);
    }

    return gl::Error(GL_NO_ERROR);
}
Ejemplo n.º 3
0
TCache::TypeKey::TypeKey(TBasicType basicType,
                         TPrecision precision,
                         TQualifier qualifier,
                         unsigned char primarySize,
                         unsigned char secondarySize)
{
    static_assert(sizeof(components) <= sizeof(value),
                  "TypeKey::value is too small");

    const size_t MaxEnumValue = std::numeric_limits<EnumComponentType>::max();
    UNUSED_ASSERTION_VARIABLE(MaxEnumValue);

    // TODO: change to static_assert() once we deprecate MSVC 2013 support
    ASSERT(MaxEnumValue >= EbtLast &&
           MaxEnumValue >= EbpLast &&
           MaxEnumValue >= EvqLast &&
           "TypeKey::EnumComponentType is too small");

    value = 0;
    components.basicType = static_cast<EnumComponentType>(basicType);
    components.precision = static_cast<EnumComponentType>(precision);
    components.qualifier = static_cast<EnumComponentType>(qualifier);
    components.primarySize = primarySize;
    components.secondarySize = secondarySize;
}
Ejemplo n.º 4
0
void SurfaceD3D::unsubclassWindow()
{
    if (!mWindowSubclassed)
    {
        return;
    }

#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
    HWND window = mNativeWindow.getNativeWindow();
    if (!window)
    {
        return;
    }

    // un-subclass
    LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc));

    // Check the windowproc is still SurfaceWindowProc.
    // If this assert fails, then it is likely the application has subclassed the
    // hwnd as well and did not unsubclass before destroying its EGL context. The
    // application should be modified to either subclass before initializing the
    // EGL context, or to unsubclass before destroying the EGL context.
    if(parentWndFunc)
    {
        LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
        UNUSED_ASSERTION_VARIABLE(prevWndFunc);
        ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
    }

    RemoveProp(window, kSurfaceProperty);
    RemoveProp(window, kParentWndProc);
#endif
    mWindowSubclassed = false;
}
Ejemplo n.º 5
0
// Returns true if it recreates the direct buffer
bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset,
                                               size_t size, size_t destOffset)
{
    ID3D11DeviceContext *context = mRenderer->getDeviceContext();

    size_t requiredSize = sourceOffset + size;
    bool createBuffer = !mNativeStorage || mBufferSize < requiredSize;

    // (Re)initialize D3D buffer if needed
    if (createBuffer)
    {
        bool preserveData = (destOffset > 0);
        resize(source->getSize(), preserveData);
    }

    if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
        source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
    {
        ASSERT(source->isMappable());

        uint8_t *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT);

        D3D11_MAPPED_SUBRESOURCE mappedResource;
        HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource);
        UNUSED_ASSERTION_VARIABLE(hr);
        ASSERT(SUCCEEDED(hr));

        uint8_t *destPointer = static_cast<uint8_t *>(mappedResource.pData) + destOffset;

        // Offset bounds are validated at the API layer
        ASSERT(sourceOffset + size <= destOffset + mBufferSize);
        memcpy(destPointer, sourcePointer, size);

        context->Unmap(mNativeStorage, 0);
        source->unmap();
    }
    else
    {
        ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source));

        D3D11_BOX srcBox;
        srcBox.left = sourceOffset;
        srcBox.right = sourceOffset + size;
        srcBox.top = 0;
        srcBox.bottom = 1;
        srcBox.front = 0;
        srcBox.back = 1;

        ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source));
        ID3D11Buffer *sourceBuffer = static_cast<NativeStorage*>(source)->getNativeStorage();

        context->CopySubresourceRegion(mNativeStorage, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox);
    }

    return createBuffer;
}
Ejemplo n.º 6
0
void Query9::end()
{
    ASSERT(mQuery);

    HRESULT result = mQuery->Issue(D3DISSUE_END);
    UNUSED_ASSERTION_VARIABLE(result);
    ASSERT(SUCCEEDED(result));

    mStatus = GL_FALSE;
    mResult = GL_FALSE;
}
Ejemplo n.º 7
0
FenceSync::FenceSync(rx::Renderer *renderer, GLuint id)
    : RefCountObject(id)
{
    mFence = renderer->createFence();

    LARGE_INTEGER counterFreqency = { 0 };
    BOOL success = QueryPerformanceFrequency(&counterFreqency);
    UNUSED_ASSERTION_VARIABLE(success);
    ASSERT(success);

    mCounterFrequency = counterFreqency.QuadPart;
}
Ejemplo n.º 8
0
void Query9::begin()
{
    if (mQuery == NULL)
    {
        if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery)))
        {
            return gl::error(GL_OUT_OF_MEMORY);
        }
    }

    HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
    UNUSED_ASSERTION_VARIABLE(result);
    ASSERT(SUCCEEDED(result));
}
Ejemplo n.º 9
0
void *BufferStorage11::NativeBuffer11::map(GLbitfield access)
{
    ASSERT(mUsage == BUFFER_USAGE_STAGING);

    D3D11_MAPPED_SUBRESOURCE mappedResource;
    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access);
    UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);

    HRESULT result = context->Map(mNativeBuffer, 0, d3dMapType, d3dMapFlag, &mappedResource);
    UNUSED_ASSERTION_VARIABLE(result);
    ASSERT(SUCCEEDED(result));

    return mappedResource.pData;
}
Ejemplo n.º 10
0
ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat)
{
    BufferStorage *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK);

    if (!storage)
    {
        // Storage out-of-memory
        return NULL;
    }

    ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, storage));
    ID3D11Buffer *buffer = static_cast<NativeStorage*>(storage)->getNativeStorage();

    auto bufferSRVIt = mBufferResourceViews.find(srvFormat);

    if (bufferSRVIt != mBufferResourceViews.end())
    {
        if (bufferSRVIt->second.first == buffer)
        {
            return bufferSRVIt->second.second;
        }
        else
        {
            // The underlying buffer has changed since the SRV was created: recreate the SRV.
            SafeRelease(bufferSRVIt->second.second);
        }
    }

    ID3D11Device *device = mRenderer->getDevice();
    ID3D11ShaderResourceView *bufferSRV = NULL;

    const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(srvFormat);

    D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
    bufferSRVDesc.Buffer.ElementOffset = 0;
    bufferSRVDesc.Buffer.ElementWidth = mSize / dxgiFormatInfo.pixelBytes;
    bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
    bufferSRVDesc.Format = srvFormat;

    HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV);
    UNUSED_ASSERTION_VARIABLE(result);
    ASSERT(SUCCEEDED(result));

    mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV);

    return bufferSRV;
}
Ejemplo n.º 11
0
bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
{
    // TODO(jmadill): We shouldn't need to cache this.
    mCompilerOutputType = compiler->getShaderOutputType();

    const std::string &translatedSource = mData.getTranslatedSource();

    mUsesMultipleRenderTargets = translatedSource.find("GL_USES_MRT") != std::string::npos;
    mUsesFragColor             = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
    mUsesFragData              = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
    mUsesFragCoord             = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
    mUsesFrontFacing           = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
    mUsesPointSize             = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
    mUsesPointCoord            = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
    mUsesDepthRange            = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
    mUsesFragDepth = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
    mUsesDiscardRewriting =
        translatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
    mUsesNestedBreak  = translatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
    mRequiresIEEEStrictCompiling =
        translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos;

    ShHandle compilerHandle = compiler->getCompilerHandle(mData.getShaderType());

    mUniformRegisterMap = GetUniformRegisterMap(ShGetUniformRegisterMap(compilerHandle));

    for (const sh::InterfaceBlock &interfaceBlock : mData.getInterfaceBlocks())
    {
        if (interfaceBlock.staticUse)
        {
            unsigned int index = static_cast<unsigned int>(-1);
            bool blockRegisterResult =
                ShGetInterfaceBlockRegister(compilerHandle, interfaceBlock.name, &index);
            UNUSED_ASSERTION_VARIABLE(blockRegisterResult);
            ASSERT(blockRegisterResult);

            mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
        }
    }

    mDebugInfo +=
        std::string("// ") + GetShaderTypeString(mData.getShaderType()) + " SHADER BEGIN\n";
    mDebugInfo += "\n// GLSL BEGIN\n\n" + mData.getSource() + "\n\n// GLSL END\n\n\n";
    mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n";
    // Successive steps will append more info
    return true;
}
Ejemplo n.º 12
0
size_t CallDAG::findIndex(const TIntermAggregate *function) const
{
    TOperator op = function->getOp();
    ASSERT(op == EOpPrototype || op == EOpFunction || op == EOpFunctionCall);
    UNUSED_ASSERTION_VARIABLE(op);

    auto it = mFunctionIdToIndex.find(function->getFunctionId());

    if (it == mFunctionIdToIndex.end())
    {
        return InvalidIndex;
    }
    else
    {
        return it->second;
    }
}
Ejemplo n.º 13
0
// Increments refcount on surface.
// caller must Release() the returned surface
IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty)
{
    IDirect3DSurface9 *surface = NULL;

    if (mTexture)
    {
        HRESULT result = mTexture->GetSurfaceLevel(level + mTopLevel, &surface);
        UNUSED_ASSERTION_VARIABLE(result);
        ASSERT(SUCCEEDED(result));

        // With managed textures the driver needs to be informed of updates to the lower mipmap levels
        if (level + mTopLevel != 0 && isManaged() && dirty)
        {
            mTexture->AddDirtyRect(NULL);
        }
    }

    return surface;
}
Ejemplo n.º 14
0
gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib,
                                                   GLsizei count,
                                                   GLsizei instances) const
{
    const gl::VertexAttribute &attrib = *translatedAttrib.attribute;
    ASSERT(!DirectStoragePossible(attrib));

    gl::Buffer *buffer   = attrib.buffer.get();
    BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
    ASSERT(!bufferD3D || bufferD3D->getStaticVertexBuffer(attrib) == nullptr);
    UNUSED_ASSERTION_VARIABLE(bufferD3D);

    size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
    ASSERT(!bufferD3D ||
           ElementsInBuffer(attrib, static_cast<unsigned int>(bufferD3D->getSize())) >=
               static_cast<int>(totalCount));

    return mStreamingBuffer->reserveVertexSpace(attrib, static_cast<GLsizei>(totalCount),
                                                instances);
}
Ejemplo n.º 15
0
// Increments refcount on surface.
// caller must Release() the returned surface
IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty)
{
    IDirect3DSurface9 *surface = NULL;

    if (mTexture)
    {
        D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
        HRESULT result = mTexture->GetCubeMapSurface(face, level + mTopLevel, &surface);
        UNUSED_ASSERTION_VARIABLE(result);
        ASSERT(SUCCEEDED(result));

        // With managed textures the driver needs to be informed of updates to the lower mipmap levels
        if (level != 0 && isManaged() && dirty)
        {
            mTexture->AddDirtyRect(face, NULL);
        }
    }

    return surface;
}
Ejemplo n.º 16
0
void VertexDataManager::prepareStaticBufferForAttribute(const gl::VertexAttribute &attrib,
                                                        const gl::VertexAttribCurrentValueData &currentValue) const
{
    gl::Buffer *buffer = attrib.buffer.get();

    if (buffer)
    {
        BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer);

        // This will create the static buffer in the right circumstances
        StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBufferForAttribute(attrib);
        UNUSED_ASSERTION_VARIABLE(staticBuffer);

        // This check validates that a valid static vertex buffer was returned above
        ASSERT(!(staticBuffer &&
                 staticBuffer->getBufferSize() > 0 &&
                 !staticBuffer->lookupAttribute(attrib, NULL) &&
                 !staticBuffer->directStoragePossible(attrib, currentValue)));
    }
}
Ejemplo n.º 17
0
UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize)
    : UniformStorage(initialSize),
      mConstantBuffer(NULL)
{
    ID3D11Device *d3d11Device = renderer->getDevice();

    if (initialSize > 0)
    {
        D3D11_BUFFER_DESC constantBufferDescription = {0};
        constantBufferDescription.ByteWidth = initialSize;
        constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC;
        constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
        constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
        constantBufferDescription.MiscFlags = 0;
        constantBufferDescription.StructureByteStride = 0;

        HRESULT result = d3d11Device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer);
        UNUSED_ASSERTION_VARIABLE(result);
        ASSERT(SUCCEEDED(result));
    }
}
Ejemplo n.º 18
0
void Display::destroySurface(Surface *surface)
{
    if (surface->getType() == EGL_WINDOW_BIT)
    {
        WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
        ASSERT(windowSurfaces);

        bool surfaceRemoved = false;
        for (WindowSurfaceMap::iterator iter = windowSurfaces->begin(); iter != windowSurfaces->end(); iter++)
        {
            if (iter->second == surface)
            {
                windowSurfaces->erase(iter);
                surfaceRemoved = true;
                break;
            }
        }

        ASSERT(surfaceRemoved);
        UNUSED_ASSERTION_VARIABLE(surfaceRemoved);
    }

    mImplementation->destroySurface(surface);
}
Ejemplo n.º 19
0
void ShaderD3D::compileToHLSL(void *compiler, const std::string &source)
{
    // ensure the compiler is loaded
    initializeCompiler();

    int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES);
    std::string sourcePath;

#if !defined (ANGLE_ENABLE_WINDOWS_STORE)
    if (gl::perfActive())
    {
        sourcePath = getTempPath();
        writeFile(sourcePath.c_str(), source.c_str(), source.length());
        compileOptions |= SH_LINE_DIRECTIVES;
    }
#endif

    int result;
    if (sourcePath.empty())
    {
        const char* sourceStrings[] =
        {
            source.c_str(),
        };

        result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions);
    }
    else
    {
        const char* sourceStrings[] =
        {
            sourcePath.c_str(),
            source.c_str(),
        };

        result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH);
    }

    mShaderVersion = ShGetShaderVersion(compiler);

    if (mShaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3)
    {
        mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
        TRACE("\n%s", mInfoLog.c_str());
    }
    else if (result)
    {
        mHlsl = ShGetObjectCode(compiler);

#ifdef _DEBUG
        // Prefix hlsl shader with commented out glsl shader
        // Useful in diagnostics tools like pix which capture the hlsl shaders
        std::ostringstream hlslStream;
        hlslStream << "// GLSL\n";
        hlslStream << "//\n";

        size_t curPos = 0;
        while (curPos != std::string::npos)
        {
            size_t nextLine = source.find("\n", curPos);
            size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);

            hlslStream << "// " << source.substr(curPos, len);

            curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
        }
        hlslStream << "\n\n";
        hlslStream << mHlsl;
        mHlsl = hlslStream.str();
#endif

        mUniforms = *GetShaderVariables(ShGetUniforms(compiler));

        for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
        {
            const sh::Uniform &uniform = mUniforms[uniformIndex];

            if (uniform.staticUse)
            {
                unsigned int index = -1;
                bool result = ShGetUniformRegister(compiler, uniform.name, &index);
                UNUSED_ASSERTION_VARIABLE(result);
                ASSERT(result);

                mUniformRegisterMap[uniform.name] = index;
            }
        }

        mInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler));

        for (size_t blockIndex = 0; blockIndex < mInterfaceBlocks.size(); blockIndex++)
        {
            const sh::InterfaceBlock &interfaceBlock = mInterfaceBlocks[blockIndex];

            if (interfaceBlock.staticUse)
            {
                unsigned int index = -1;
                bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index);
                UNUSED_ASSERTION_VARIABLE(result);
                ASSERT(result);

                mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
            }
        }
    }
    else
    {
        mInfoLog = ShGetInfoLog(compiler);

        TRACE("\n%s", mInfoLog.c_str());
    }
}
Ejemplo n.º 20
0
void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source)
{
    int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES);

    // D3D11 Feature Level 9_3 and below do not support non-constant loop indexers in fragment
    // shaders.
    // Shader compilation will fail. To provide a better error message we can instruct the
    // compiler to pre-validate.
    if (mRenderer->getRendererLimitations().shadersRequireIndexedLoopValidation)
    {
        compileOptions |= SH_VALIDATE_LOOP_INDEXING;
    }

    std::string sourcePath;

#if !defined (ANGLE_ENABLE_WINDOWS_STORE)
    if (gl::DebugAnnotationsActive())
    {
        sourcePath = getTempPath();
        writeFile(sourcePath.c_str(), source.c_str(), source.length());
        compileOptions |= SH_LINE_DIRECTIVES;
    }
#endif

    int result;
    if (sourcePath.empty())
    {
        const char* sourceStrings[] =
        {
            source.c_str(),
        };

        result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions);
    }
    else
    {
        const char* sourceStrings[] =
        {
            sourcePath.c_str(),
            source.c_str(),
        };

        result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH);
    }

    mShaderVersion = ShGetShaderVersion(compiler);

    if (result)
    {
        mTranslatedSource = ShGetObjectCode(compiler);

#ifdef _DEBUG
        // Prefix hlsl shader with commented out glsl shader
        // Useful in diagnostics tools like pix which capture the hlsl shaders
        std::ostringstream hlslStream;
        hlslStream << "// GLSL\n";
        hlslStream << "//\n";

        size_t curPos = 0;
        while (curPos != std::string::npos)
        {
            size_t nextLine = source.find("\n", curPos);
            size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);

            hlslStream << "// " << source.substr(curPos, len);

            curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
        }
        hlslStream << "\n\n";
        hlslStream << mTranslatedSource;
        mTranslatedSource = hlslStream.str();
#endif

        mUniforms = *GetShaderVariables(ShGetUniforms(compiler));

        for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
        {
            const sh::Uniform &uniform = mUniforms[uniformIndex];

            if (uniform.staticUse && !uniform.isBuiltIn())
            {
                unsigned int index = static_cast<unsigned int>(-1);
                bool getUniformRegisterResult = ShGetUniformRegister(compiler, uniform.name, &index);
                UNUSED_ASSERTION_VARIABLE(getUniformRegisterResult);
                ASSERT(getUniformRegisterResult);

                mUniformRegisterMap[uniform.name] = index;
            }
        }

        mInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler));

        for (size_t blockIndex = 0; blockIndex < mInterfaceBlocks.size(); blockIndex++)
        {
            const sh::InterfaceBlock &interfaceBlock = mInterfaceBlocks[blockIndex];

            if (interfaceBlock.staticUse)
            {
                unsigned int index = static_cast<unsigned int>(-1);
                bool blockRegisterResult = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index);
                UNUSED_ASSERTION_VARIABLE(blockRegisterResult);
                ASSERT(blockRegisterResult);

                mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
            }
        }
    }
    else
    {
        mInfoLog = ShGetInfoLog(compiler);

        TRACE("\n%s", mInfoLog.c_str());
    }
}