Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d / d3d11 / Renderer11.cpp
index c93def8..e5c4d12 100644 (file)
@@ -11,6 +11,7 @@
 #include "libGLESv2/FramebufferAttachment.h"
 #include "libGLESv2/ProgramBinary.h"
 #include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/State.h"
 #include "libGLESv2/renderer/d3d/ProgramD3D.h"
 #include "libGLESv2/renderer/d3d/ShaderD3D.h"
 #include "libGLESv2/renderer/d3d/TextureD3D.h"
@@ -39,6 +40,7 @@
 #include "libEGL/Display.h"
 
 #include "common/utilities.h"
+#include "common/tls.h"
 
 #include <EGL/eglext.h>
 
@@ -58,6 +60,9 @@
 
 namespace rx
 {
+
+namespace
+{
 static const DXGI_FORMAT RenderTargetFormats[] =
     {
         DXGI_FORMAT_B8G8R8A8_UNORM,
@@ -76,6 +81,18 @@ enum
     MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
 };
 
+// Does *not* increment the resource ref count!!
+ID3D11Resource *GetSRVResource(ID3D11ShaderResourceView *srv)
+{
+    ID3D11Resource *resource = NULL;
+    ASSERT(srv);
+    srv->GetResource(&resource);
+    resource->Release();
+    return resource;
+}
+
+}
+
 Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay)
     : Renderer(display),
       mDc(hDc),
@@ -135,6 +152,7 @@ EGLint Renderer11::initialize()
         return EGL_NOT_INITIALIZED;
     }
 
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
     mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
     mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
 
@@ -153,6 +171,7 @@ EGLint Renderer11::initialize()
         ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
         return EGL_NOT_INITIALIZED;
     }
+#endif
 
     D3D_FEATURE_LEVEL featureLevels[] =
     {
@@ -207,6 +226,7 @@ EGLint Renderer11::initialize()
         }
     }
 
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
 #if !ANGLE_SKIP_DXGI_1_2_CHECK
     // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
     // The easiest way to check is to query for a IDXGIDevice2.
@@ -236,6 +256,7 @@ EGLint Renderer11::initialize()
         SafeRelease(dxgiDevice2);
     }
 #endif
+#endif
 
     IDXGIDevice *dxgiDevice = NULL;
     result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
@@ -369,7 +390,7 @@ void Renderer11::deleteConfigs(ConfigDesc *configDescList)
     delete [] (configDescList);
 }
 
-void Renderer11::sync(bool block)
+gl::Error Renderer11::sync(bool block)
 {
     if (block)
     {
@@ -383,6 +404,10 @@ void Renderer11::sync(bool block)
 
             result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
             ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result);
+            }
         }
 
         mDeviceContext->End(mSyncQuery);
@@ -391,13 +416,17 @@ void Renderer11::sync(bool block)
         do
         {
             result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+            }
 
             // Keep polling, but allow other threads to do something useful first
             Sleep(0);
 
             if (testDeviceLost(true))
             {
-                return;
+                return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync.");
             }
         }
         while (result == S_FALSE);
@@ -406,50 +435,64 @@ void Renderer11::sync(bool block)
     {
         mDeviceContext->Flush();
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChain *Renderer11::createSwapChain(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
 {
-    return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
+    return new rx::SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
 }
 
-void Renderer11::generateSwizzle(gl::Texture *texture)
+gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
 {
     if (texture)
     {
-        TextureStorage *texStorage = texture->getNativeTexture();
+        TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+        ASSERT(textureD3D);
+
+        TextureStorage *texStorage = textureD3D->getNativeTexture();
         if (texStorage)
         {
             TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
-
-            storage11->generateSwizzles(texture->getSamplerState().swizzleRed,
-                                        texture->getSamplerState().swizzleGreen,
-                                        texture->getSamplerState().swizzleBlue,
-                                        texture->getSamplerState().swizzleAlpha);
+            gl::Error error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed,
+                                                          texture->getSamplerState().swizzleGreen,
+                                                          texture->getSamplerState().swizzleBlue,
+                                                          texture->getSamplerState().swizzleAlpha);
+            if (error.isError())
+            {
+                return error;
+            }
         }
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
+gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerStateParam)
 {
+    // Make sure to add the level offset for our tiny compressed texture workaround
+    TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+    gl::SamplerState samplerStateInternal = samplerStateParam;
+    samplerStateInternal.baseLevel += textureD3D->getNativeTexture()->getTopLevel();
+
     if (type == gl::SAMPLER_PIXEL)
     {
         ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits);
 
-        if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+        if (mForceSetPixelSamplerStates[index] || memcmp(&samplerStateInternal, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
         {
             ID3D11SamplerState *dxSamplerState = NULL;
-            gl::Error error = mStateCache.getSamplerState(samplerState, &dxSamplerState);
+            gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState);
             if (error.isError())
             {
-                ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
-                    "sampler state for pixel shaders at slot %i.", index);
-                dxSamplerState = NULL;
+                return error;
             }
 
+            ASSERT(dxSamplerState != NULL);
             mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
 
-            mCurPixelSamplerStates[index] = samplerState;
+            mCurPixelSamplerStates[index] = samplerStateInternal;
         }
 
         mForceSetPixelSamplerStates[index] = false;
@@ -458,79 +501,66 @@ void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::Samp
     {
         ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits);
 
-        if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+        if (mForceSetVertexSamplerStates[index] || memcmp(&samplerStateInternal, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
         {
             ID3D11SamplerState *dxSamplerState = NULL;
-            gl::Error error = mStateCache.getSamplerState(samplerState, &dxSamplerState);
+            gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState);
             if (error.isError())
             {
-                ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
-                    "sampler state for vertex shaders at slot %i.", index);
-                dxSamplerState = NULL;
+                return error;
             }
 
+            ASSERT(dxSamplerState != NULL);
             mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
 
-            mCurVertexSamplerStates[index] = samplerState;
+            mCurVertexSamplerStates[index] = samplerStateInternal;
         }
 
         mForceSetVertexSamplerStates[index] = false;
     }
     else UNREACHABLE();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
 {
     ID3D11ShaderResourceView *textureSRV = NULL;
-    bool forceSetTexture = false;
 
     if (texture)
     {
-        TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation());
-
+        TextureD3D *textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation());
         TextureStorage *texStorage = textureImpl->getNativeTexture();
-        if (texStorage)
+        ASSERT(texStorage != NULL);
+
+        TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
+
+        // Make sure to add the level offset for our tiny compressed texture workaround
+        gl::SamplerState samplerState = texture->getSamplerState();
+        samplerState.baseLevel += storage11->getTopLevel();
+
+        gl::Error error = storage11->getSRV(samplerState, &textureSRV);
+        if (error.isError())
         {
-            TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
-            gl::SamplerState samplerState;
-            texture->getSamplerStateWithNativeOffset(&samplerState);
-            textureSRV = storage11->getSRV(samplerState);
+            return error;
         }
 
         // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly
         // missing the shader resource view
         ASSERT(textureSRV != NULL);
 
-        forceSetTexture = textureImpl->hasDirtyImages();
         textureImpl->resetDirty();
     }
 
-    if (type == gl::SAMPLER_PIXEL)
-    {
-        ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits);
-
-        if (forceSetTexture || mCurPixelSRVs[index] != textureSRV)
-        {
-            mDeviceContext->PSSetShaderResources(index, 1, &textureSRV);
-        }
-
-        mCurPixelSRVs[index] = textureSRV;
-    }
-    else if (type == gl::SAMPLER_VERTEX)
-    {
-        ASSERT(static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits);
+    ASSERT((type == gl::SAMPLER_PIXEL && static_cast<unsigned int>(index) < getRendererCaps().maxTextureImageUnits) ||
+           (type == gl::SAMPLER_VERTEX && static_cast<unsigned int>(index) < getRendererCaps().maxVertexTextureImageUnits));
 
-        if (forceSetTexture || mCurVertexSRVs[index] != textureSRV)
-        {
-            mDeviceContext->VSSetShaderResources(index, 1, &textureSRV);
-        }
+    setShaderResource(type, index, textureSRV);
 
-        mCurVertexSRVs[index] = textureSRV;
-    }
-    else UNREACHABLE();
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[])
+gl::Error Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[])
 {
     for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++)
     {
@@ -542,7 +572,7 @@ bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], con
 
             if (!constantBuffer)
             {
-                return false;
+                return gl::Error(GL_OUT_OF_MEMORY);
             }
 
             if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial())
@@ -564,7 +594,7 @@ bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], con
 
             if (!constantBuffer)
             {
-                return false;
+                return gl::Error(GL_OUT_OF_MEMORY);
             }
 
             if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial())
@@ -576,10 +606,10 @@ bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], con
         }
     }
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
+gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
 {
     if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
     {
@@ -587,9 +617,7 @@ void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
         gl::Error error = mStateCache.getRasterizerState(rasterState, mScissorEnabled, &dxRasterState);
         if (error.isError())
         {
-            ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default"
-                "rasterizer state.");
-            dxRasterState = NULL;
+            return error;
         }
 
         mDeviceContext->RSSetState(dxRasterState);
@@ -598,10 +626,12 @@ void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
     }
 
     mForceSetRasterState = false;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
-                               unsigned int sampleMask)
+gl::Error Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
+                                    unsigned int sampleMask)
 {
     if (mForceSetBlendState ||
         memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
@@ -612,11 +642,11 @@ void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendStat
         gl::Error error = mStateCache.getBlendState(framebuffer, blendState, &dxBlendState);
         if (error.isError())
         {
-            ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default "
-                "blend state.");
-            dxBlendState = NULL;
+            return error;
         }
 
+        ASSERT(dxBlendState != NULL);
+
         float blendColors[4] = {0.0f};
         if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
             blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
@@ -642,10 +672,12 @@ void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendStat
     }
 
     mForceSetBlendState = false;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
-                                      int stencilBackRef, bool frontFaceCCW)
+gl::Error Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+                                           int stencilBackRef, bool frontFaceCCW)
 {
     if (mForceSetDepthStencilState ||
         memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
@@ -659,11 +691,11 @@ void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilS
         gl::Error error = mStateCache.getDepthStencilState(depthStencilState, &dxDepthStencilState);
         if (error.isError())
         {
-            ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, "
-                "setting the default depth stencil state.");
-            dxDepthStencilState = NULL;
+            return error;
         }
 
+        ASSERT(dxDepthStencilState);
+
         // Max D3D11 stencil reference value is 0xFF, corresponding to the max 8 bits in a stencil buffer
         // GL specifies we should clamp the ref value to the nearest bit depth when doing stencil ops
         META_ASSERT(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF);
@@ -678,6 +710,8 @@ void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilS
     }
 
     mForceSetDepthStencilState = false;
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
@@ -796,7 +830,22 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
     return count >= minCount;
 }
 
-bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
+void Renderer11::unsetSRVsWithResource(gl::SamplerType samplerType, const ID3D11Resource *resource)
+{
+    auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+    for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
+    {
+        ID3D11ShaderResourceView *srv = currentSRVs[resourceIndex];
+
+        if (srv && GetSRVResource(srv) == resource)
+        {
+            setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL);
+        }
+    }
+}
+
+gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
 {
     // Get the color render buffer and serial
     // Also extract the render target dimensions and view
@@ -822,25 +871,22 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
             // this will not report any gl error but will cause the calling method to return.
             if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
             {
-                return false;
+                return gl::Error(GL_NO_ERROR);
             }
 
             renderTargetSerials[colorAttachment] = GetAttachmentSerial(colorbuffer);
 
             // Extract the render target dimensions and view
-            RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-            if (!renderTarget)
+            RenderTarget11 *renderTarget = NULL;
+            gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
+            if (error.isError())
             {
-                ERR("render target pointer unexpectedly null.");
-                return false;
+                return error;
             }
+            ASSERT(renderTarget);
 
             framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
-            if (!framebufferRTVs[colorAttachment])
-            {
-                ERR("render target view pointer unexpectedly null.");
-                return false;
-            }
+            ASSERT(framebufferRTVs[colorAttachment]);
 
             if (missingColorRenderTarget)
             {
@@ -850,8 +896,12 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
                 missingColorRenderTarget = false;
             }
 
-            // TODO: Detect if this color buffer is already bound as a texture and unbind it first to prevent
-            //       D3D11 warnings.
+#if !defined(NDEBUG)
+            // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
+            ID3D11Resource *renderTargetResource = renderTarget->getTexture();
+            unsetSRVsWithResource(gl::SAMPLER_VERTEX, renderTargetResource);
+            unsetSRVsWithResource(gl::SAMPLER_PIXEL, renderTargetResource);
+#endif
         }
     }
 
@@ -872,21 +922,17 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
     ID3D11DepthStencilView* framebufferDSV = NULL;
     if (depthStencil)
     {
-        RenderTarget11 *depthStencilRenderTarget = d3d11::GetAttachmentRenderTarget(depthStencil);
-        if (!depthStencilRenderTarget)
+        RenderTarget11 *depthStencilRenderTarget = NULL;
+        gl::Error error = d3d11::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget);
+        if (error.isError())
         {
-            ERR("render target pointer unexpectedly null.");
             SafeRelease(framebufferRTVs);
-            return false;
+            return error;
         }
+        ASSERT(depthStencilRenderTarget);
 
         framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
-        if (!framebufferDSV)
-        {
-            ERR("depth stencil view pointer unexpectedly null.");
-            SafeRelease(framebufferRTVs);
-            return false;
-        }
+        ASSERT(framebufferDSV);
 
         // If there is no render buffer, the width, height and format values come from
         // the depth stencil
@@ -930,20 +976,19 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
 
     invalidateFramebufferSwizzles(framebuffer);
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
-gl::Error Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[],
-                                        GLint first, GLsizei count, GLsizei instances)
+gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances)
 {
     TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
-    gl::Error error = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances);
+    gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances);
     if (error.isError())
     {
         return error;
     }
 
-    return mInputLayoutCache.applyVertexBuffers(attributes, programBinary);
+    return mInputLayoutCache.applyVertexBuffers(attributes, state.getCurrentProgramBinary());
 }
 
 gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
@@ -980,28 +1025,25 @@ gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elemen
     return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[])
+void Renderer11::applyTransformFeedbackBuffers(const gl::State& state)
 {
-    ID3D11Buffer* d3dBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
-    UINT d3dOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS];
+    size_t numXFBBindings = state.getTransformFeedbackBufferIndexRange();
+    ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
+
     bool requiresUpdate = false;
-    for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+    for (size_t i = 0; i < numXFBBindings; i++)
     {
-        if (transformFeedbackBuffers[i])
+        gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
+        GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
+        ID3D11Buffer *d3dBuffer = NULL;
+        if (curXFBBuffer)
         {
-            Buffer11 *storage = Buffer11::makeBuffer11(transformFeedbackBuffers[i]->getImplementation());
-            ID3D11Buffer *buffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
-
-            d3dBuffers[i] = buffer;
-            d3dOffsets[i] = (mAppliedTFBuffers[i] != buffer) ? static_cast<UINT>(offsets[i]) : -1;
-        }
-        else
-        {
-            d3dBuffers[i] = NULL;
-            d3dOffsets[i] = 0;
+            Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
+            d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
         }
 
-        if (d3dBuffers[i] != mAppliedTFBuffers[i] || offsets[i] != mAppliedTFOffsets[i])
+        // TODO: mAppliedTFBuffers and friends should also be kept in a vector.
+        if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i])
         {
             requiresUpdate = true;
         }
@@ -1009,16 +1051,33 @@ void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuff
 
     if (requiresUpdate)
     {
-        mDeviceContext->SOSetTargets(ArraySize(d3dBuffers), d3dBuffers, d3dOffsets);
-        for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
+        for (size_t i = 0; i < numXFBBindings; ++i)
         {
-            mAppliedTFBuffers[i] = d3dBuffers[i];
-            mAppliedTFOffsets[i] = offsets[i];
+            gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
+            GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
+
+            if (curXFBBuffer)
+            {
+                Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
+                ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+
+                mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer && mAppliedTFOffsets[i] != curXFBOffset) ?
+                                        static_cast<UINT>(curXFBOffset) : -1;
+                mAppliedTFBuffers[i] = d3dBuffer;
+            }
+            else
+            {
+                mAppliedTFBuffers[i] = NULL;
+                mCurrentD3DOffsets[i] = 0;
+            }
+            mAppliedTFOffsets[i] = curXFBOffset;
         }
+
+        mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets);
     }
 }
 
-void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive)
+gl::Error Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive)
 {
     if (mode == GL_POINTS && transformFeedbackActive)
     {
@@ -1051,57 +1110,70 @@ void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool
         }
 
         mDeviceContext->GSSetShader(mAppliedGeometryShader, NULL, 0);
+
+        return gl::Error(GL_NO_ERROR);
     }
     else if (mode == GL_LINE_LOOP)
     {
-        drawLineLoop(count, GL_NONE, NULL, 0, NULL);
+        return drawLineLoop(count, GL_NONE, NULL, 0, NULL);
     }
     else if (mode == GL_TRIANGLE_FAN)
     {
-        drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
+        return drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
     }
     else if (instances > 0)
     {
         mDeviceContext->DrawInstanced(count, instances, 0, 0);
+        return gl::Error(GL_NO_ERROR);
     }
     else
     {
         mDeviceContext->Draw(count, 0);
+        return gl::Error(GL_NO_ERROR);
     }
 }
 
-void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
-                              gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances)
+gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
+                                   gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances)
 {
     int minIndex = static_cast<int>(indexInfo.indexRange.start);
 
     if (mode == GL_LINE_LOOP)
     {
-        drawLineLoop(count, type, indices, minIndex, elementArrayBuffer);
+        return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer);
     }
     else if (mode == GL_TRIANGLE_FAN)
     {
-        drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances);
+        return drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances);
     }
     else if (instances > 0)
     {
         mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0);
+        return gl::Error(GL_NO_ERROR);
     }
     else
     {
         mDeviceContext->DrawIndexed(count, 0, -minIndex);
+        return gl::Error(GL_NO_ERROR);
     }
 }
 
-void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
 {
     // Get the raw indices for an indexed draw
     if (type != GL_NONE && elementArrayBuffer)
     {
-        gl::Buffer *indexBuffer = elementArrayBuffer;
-        BufferImpl *storage = indexBuffer->getImplementation();
+        BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer);
         intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+
+        const uint8_t *bufferData = NULL;
+        gl::Error error = storage->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        indices = bufferData + offset;
     }
 
     if (!mLineLoopIB)
@@ -1111,9 +1183,7 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
         if (error.isError())
         {
             SafeDelete(mLineLoopIB);
-
-            ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
-            return gl::error(GL_OUT_OF_MEMORY);
+            return error;
         }
     }
 
@@ -1122,16 +1192,14 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
 
     if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
     {
-        ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
-        return gl::error(GL_OUT_OF_MEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
     }
 
     const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
     gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
     if (error.isError())
     {
-        ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
-        return gl::error(GL_OUT_OF_MEMORY);
+        return error;
     }
 
     void* mappedMemory = NULL;
@@ -1139,8 +1207,7 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
     error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
     if (error.isError())
     {
-        ERR("Could not map index buffer for GL_LINE_LOOP.");
-        return gl::error(GL_OUT_OF_MEMORY);
+        return error;
     }
 
     unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
@@ -1182,8 +1249,7 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
     error = mLineLoopIB->unmapBuffer();
     if (error.isError())
     {
-        ERR("Could not unmap index buffer for GL_LINE_LOOP.");
-        return gl::error(GL_OUT_OF_MEMORY);
+        return error;
     }
 
     IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer());
@@ -1199,17 +1265,26 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices,
     }
 
     mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
+gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
 {
     // Get the raw indices for an indexed draw
     if (type != GL_NONE && elementArrayBuffer)
     {
-        gl::Buffer *indexBuffer = elementArrayBuffer;
-        BufferImpl *storage = indexBuffer->getImplementation();
+        BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer);
         intptr_t offset = reinterpret_cast<intptr_t>(indices);
-        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+
+        const uint8_t *bufferData = NULL;
+        gl::Error error = storage->getData(&bufferData);
+        if (error.isError())
+        {
+            return error;
+        }
+
+        indices = bufferData + offset;
     }
 
     if (!mTriangleFanIB)
@@ -1219,9 +1294,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
         if (error.isError())
         {
             SafeDelete(mTriangleFanIB);
-
-            ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN.");
-            return gl::error(GL_OUT_OF_MEMORY);
+            return error;
         }
     }
 
@@ -1232,16 +1305,14 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
 
     if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
     {
-        ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
-        return gl::error(GL_OUT_OF_MEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
     }
 
     const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
     gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
     if (error.isError())
     {
-        ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN.");
-        return gl::error(GL_OUT_OF_MEMORY);
+        return error;
     }
 
     void* mappedMemory = NULL;
@@ -1249,8 +1320,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
     error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset);
     if (error.isError())
     {
-        ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN.");
-        return gl::error(GL_OUT_OF_MEMORY);
+        return error;
     }
 
     unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
@@ -1296,8 +1366,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
     error = mTriangleFanIB->unmapBuffer();
     if (error.isError())
     {
-        ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN.");
-        return gl::error(GL_OUT_OF_MEMORY);
+        return error;
     }
 
     IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer());
@@ -1320,14 +1389,30 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic
     {
         mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex);
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
-                              bool rasterizerDiscard, bool transformFeedbackActive)
+gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+                                   bool rasterizerDiscard, bool transformFeedbackActive)
 {
-    ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout);
-    ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer);
-    ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
+    ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation());
+
+    ShaderExecutable *vertexExe = NULL;
+    gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ShaderExecutable *pixelExe = NULL;
+    error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    ShaderExecutable *geometryExe = programD3D->getGeometryExecutable();
 
     ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL);
 
@@ -1382,14 +1467,14 @@ void Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::Vertex
 
     if (dirtyUniforms)
     {
-        programBinary->dirtyAllUniforms();
+        programD3D->dirtyAllUniforms();
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Renderer11::applyUniforms(const gl::ProgramBinary &programBinary)
+gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray)
 {
-    const std::vector<gl::LinkedUniform*> &uniformArray = programBinary.getUniforms();
-
     unsigned int totalRegisterCountVS = 0;
     unsigned int totalRegisterCountPS = 0;
 
@@ -1413,7 +1498,7 @@ void Renderer11::applyUniforms(const gl::ProgramBinary &programBinary)
         }
     }
 
-    const ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary.getImplementation());
+    const ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(&program);
     const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getVertexUniformStorage());
     const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getFragmentUniformStorage());
     ASSERT(vertexUniformStorage);
@@ -1541,6 +1626,8 @@ void Renderer11::applyUniforms(const gl::ProgramBinary &programBinary)
         mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
         mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
     }
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
@@ -1571,14 +1658,12 @@ void Renderer11::markAllStateDirty()
     for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId)
     {
         mForceSetVertexSamplerStates[vsamplerId] = true;
-        mCurVertexSRVs[vsamplerId] = NULL;
     }
 
     ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelSRVs.size());
     for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId)
     {
         mForceSetPixelSamplerStates[fsamplerId] = true;
-        mCurPixelSRVs[fsamplerId] = NULL;
     }
 
     mForceSetBlendState = true;
@@ -1873,119 +1958,37 @@ int Renderer11::getMaxSwapInterval() const
     return 4;
 }
 
-bool Renderer11::copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source)
-{
-    if (source && dest)
-    {
-        TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source);
-        TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest);
-
-        mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
-
-        dest11->invalidateSwizzleCache();
-
-        return true;
-    }
-
-    return false;
-}
-
-bool Renderer11::copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source)
-{
-    if (source && dest)
-    {
-        TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source);
-        TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest);
-
-        mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
-
-        dest11->invalidateSwizzleCache();
-
-        return true;
-    }
-
-    return false;
-}
-
-bool Renderer11::copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source)
-{
-    if (source && dest)
-    {
-        TextureStorage11_3D *source11 = TextureStorage11_3D::makeTextureStorage11_3D(source);
-        TextureStorage11_3D *dest11 = TextureStorage11_3D::makeTextureStorage11_3D(dest);
-
-        mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
-
-        dest11->invalidateSwizzleCache();
-
-        return true;
-    }
-
-    return false;
-}
-
-bool Renderer11::copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source)
-{
-    if (source && dest)
-    {
-        TextureStorage11_2DArray *source11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(source);
-        TextureStorage11_2DArray *dest11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(dest);
-
-        mDeviceContext->CopyResource(dest11->getResource(), source11->getResource());
-
-        dest11->invalidateSwizzleCache();
-
-        return true;
-    }
-
-    return false;
-}
-
-bool Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                             GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                  GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
 {
     gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
-    if (!colorbuffer)
-    {
-        ERR("Failed to retrieve the color buffer from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(colorbuffer);
 
-    RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-    if (!sourceRenderTarget)
+    RenderTarget11 *sourceRenderTarget = NULL;
+    gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(sourceRenderTarget);
 
     ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target view from the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(source);
 
     TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage);
-    if (!storage11)
-    {
-        ERR("Failed to retrieve the texture storage from the destination.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(storage11);
 
     gl::ImageIndex index = gl::ImageIndex::Make2D(level);
-    RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
-    if (!destRenderTarget)
+    RenderTarget *destRenderTarget = NULL;
+    error = storage11->getRenderTarget(index, &destRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the destination storage.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(destRenderTarget);
 
-    ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
-    if (!dest)
-    {
-        ERR("Failed to retrieve the render target view from the destination render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView();
+    ASSERT(dest);
 
     gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
     gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
@@ -1995,59 +1998,48 @@ bool Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &
 
     // Use nearest filtering because source and destination are the same size for the direct
     // copy
-    bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
-                                  destFormat, GL_NEAREST);
+    mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+    if (error.isError())
+    {
+        return error;
+    }
 
     storage11->invalidateSwizzleCacheLevel(level);
 
-    return ret;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                               GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                    GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
 {
     gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
-    if (!colorbuffer)
-    {
-        ERR("Failed to retrieve the color buffer from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(colorbuffer);
 
-    RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-    if (!sourceRenderTarget)
+    RenderTarget11 *sourceRenderTarget = NULL;
+    gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(sourceRenderTarget);
 
     ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target view from the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(source);
 
     TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage);
-    if (!storage11)
-    {
-        ERR("Failed to retrieve the texture storage from the destination.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(storage11);
 
     gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
-    RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
-    if (!destRenderTarget)
+    RenderTarget *destRenderTarget = NULL;
+    error = storage11->getRenderTarget(index, &destRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the destination storage.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(destRenderTarget);
 
-    ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
-    if (!dest)
-    {
-        ERR("Failed to retrieve the render target view from the destination render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView();
+    ASSERT(dest);
 
     gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
     gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
@@ -2057,59 +2049,48 @@ bool Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle
 
     // Use nearest filtering because source and destination are the same size for the direct
     // copy
-    bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
-                                  destFormat, GL_NEAREST);
+    error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+    if (error.isError())
+    {
+        return error;
+    }
 
     storage11->invalidateSwizzleCacheLevel(level);
 
-    return ret;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                             GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                  GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
 {
     gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
-    if (!colorbuffer)
-    {
-        ERR("Failed to retrieve the color buffer from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(colorbuffer);
 
-    RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-    if (!sourceRenderTarget)
+    RenderTarget11 *sourceRenderTarget = NULL;
+    gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(sourceRenderTarget);
 
     ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target view from the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(source);
 
     TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage);
-    if (!storage11)
-    {
-        ERR("Failed to retrieve the texture storage from the destination.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(storage11);
 
     gl::ImageIndex index = gl::ImageIndex::Make3D(level, zOffset);
-    RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
-    if (!destRenderTarget)
+    RenderTarget *destRenderTarget = NULL;
+    error = storage11->getRenderTarget(index, &destRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the destination storage.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(destRenderTarget);
 
-    ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
-    if (!dest)
-    {
-        ERR("Failed to retrieve the render target view from the destination render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView();
+    ASSERT(dest);
 
     gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
     gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
@@ -2119,61 +2100,48 @@ bool Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &
 
     // Use nearest filtering because source and destination are the same size for the direct
     // copy
-    bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
-                                  destFormat, GL_NEAREST);
+    error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+    if (error.isError())
+    {
+        return error;
+    }
 
     storage11->invalidateSwizzleCacheLevel(level);
 
-    return ret;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
-                                  GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+                                       GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
 {
     gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
-    if (!colorbuffer)
-    {
-        ERR("Failed to retrieve the color buffer from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(colorbuffer);
 
-    RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-    if (!sourceRenderTarget)
+    RenderTarget11 *sourceRenderTarget = NULL;
+    gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget);
+    if (error.isError())
     {
-        ERR("Failed to retrieve the render target from the frame buffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(sourceRenderTarget);
 
     ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
-    if (!source)
-    {
-        ERR("Failed to retrieve the render target view from the render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(source);
 
     TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage);
-    if (!storage11)
-    {
-        SafeRelease(source);
-        ERR("Failed to retrieve the texture storage from the destination.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ASSERT(storage11);
 
     gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zOffset);
-    RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index));
-    if (!destRenderTarget)
+    RenderTarget *destRenderTarget = NULL;
+    error = storage11->getRenderTarget(index, &destRenderTarget);
+    if (error.isError())
     {
-        SafeRelease(source);
-        ERR("Failed to retrieve the render target from the destination storage.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return error;
     }
+    ASSERT(destRenderTarget);
 
-    ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
-    if (!dest)
-    {
-        ERR("Failed to retrieve the render target view from the destination render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
-    }
+    ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView();
+    ASSERT(dest);
 
     gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
     gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
@@ -2183,12 +2151,15 @@ bool Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectan
 
     // Use nearest filtering because source and destination are the same size for the direct
     // copy
-    bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL,
-                                  destFormat, GL_NEAREST);
+    error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST);
+    if (error.isError())
+    {
+        return error;
+    }
 
     storage11->invalidateSwizzleCacheLevel(level);
 
-    return ret;
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Renderer11::unapplyRenderTargets()
@@ -2256,13 +2227,10 @@ void Renderer11::releaseShaderCompiler()
     ShaderD3D::releaseCompiler();
 }
 
-ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type,
-                                             const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                             bool separatedOutputBuffers)
+gl::Error Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type,
+                                     const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                     bool separatedOutputBuffers, ShaderExecutable **outExecutable)
 {
-    ShaderExecutable11 *executable = NULL;
-    HRESULT result;
-
     switch (type)
     {
       case rx::SHADER_VERTEX:
@@ -2270,8 +2238,12 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length
             ID3D11VertexShader *vertexShader = NULL;
             ID3D11GeometryShader *streamOutShader = NULL;
 
-            result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
+            HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader);
             ASSERT(SUCCEEDED(result));
+            if (FAILED(result))
+            {
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result);
+            }
 
             if (transformFeedbackVaryings.size() > 0)
             {
@@ -2297,51 +2269,55 @@ ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length
                 result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(),
                                                                        NULL, 0, 0, NULL, &streamOutShader);
                 ASSERT(SUCCEEDED(result));
+                if (FAILED(result))
+                {
+                    return gl::Error(GL_OUT_OF_MEMORY, "Failed to create steam output shader, result: 0x%X.", result);
+                }
             }
 
-            if (vertexShader)
-            {
-                executable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
-            }
+            *outExecutable = new ShaderExecutable11(function, length, vertexShader, streamOutShader);
         }
         break;
       case rx::SHADER_PIXEL:
         {
             ID3D11PixelShader *pixelShader = NULL;
 
-            result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
+            HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader);
             ASSERT(SUCCEEDED(result));
-
-            if (pixelShader)
+            if (FAILED(result))
             {
-                executable = new ShaderExecutable11(function, length, pixelShader);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader, result: 0x%X.", result);
             }
+
+            *outExecutable = new ShaderExecutable11(function, length, pixelShader);
         }
         break;
       case rx::SHADER_GEOMETRY:
         {
             ID3D11GeometryShader *geometryShader = NULL;
 
-            result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
+            HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader);
             ASSERT(SUCCEEDED(result));
-
-            if (geometryShader)
+            if (FAILED(result))
             {
-                executable = new ShaderExecutable11(function, length, geometryShader);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create geometry shader, result: 0x%X.", result);
             }
+
+            *outExecutable = new ShaderExecutable11(function, length, geometryShader);
         }
         break;
       default:
         UNREACHABLE();
-        break;
+        return gl::Error(GL_INVALID_OPERATION);
     }
 
-    return executable;
+    return gl::Error(GL_NO_ERROR);
 }
 
-ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type,
-                                                  const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
-                                                  bool separatedOutputBuffers, D3DWorkaroundType workaround)
+gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, rx::ShaderType type,
+                                          const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
+                                          bool separatedOutputBuffers, D3DWorkaroundType workaround,
+                                          ShaderExecutable **outExectuable)
 {
     const char *profileType = NULL;
     switch (type)
@@ -2357,30 +2333,33 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch
         break;
       default:
         UNREACHABLE();
-        return NULL;
+        return gl::Error(GL_INVALID_OPERATION);
     }
 
-    const char *profileVersion = NULL;
+    unsigned int profileMajorVersion = 0;
+    unsigned int profileMinorVersion = 0;
     switch (mFeatureLevel)
     {
       case D3D_FEATURE_LEVEL_11_0:
-        profileVersion = "5_0";
+        profileMajorVersion = 5;
+        profileMinorVersion = 0;
         break;
       case D3D_FEATURE_LEVEL_10_1:
-        profileVersion = "4_1";
+        profileMajorVersion = 4;
+        profileMinorVersion = 1;
         break;
       case D3D_FEATURE_LEVEL_10_0:
-        profileVersion = "4_0";
+        profileMajorVersion = 4;
+        profileMinorVersion = 0;
         break;
       default:
         UNREACHABLE();
-        return NULL;
+        return gl::Error(GL_INVALID_OPERATION);
     }
 
-    char profile[32];
-    snprintf(profile, ArraySize(profile), "%s_%s", profileType, profileVersion);
+    std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
 
-    UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0;
+    UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
 
     if (gl::perfActive())
     {
@@ -2389,41 +2368,48 @@ ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const ch
 #endif
 
         flags |= D3DCOMPILE_DEBUG;
-
-        std::string sourcePath = getTempPath();
-        std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL);
-        writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
     }
 
     // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
     // Try the default flags first and if compilation fails, try some alternatives.
-    const UINT extraFlags[] =
-    {
-        flags,
-        flags | D3DCOMPILE_SKIP_VALIDATION,
-        flags | D3DCOMPILE_SKIP_OPTIMIZATION
-    };
+    std::vector<CompileConfig> configs;
+    configs.push_back(CompileConfig(flags,                                "default"          ));
+    configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION,   "skip validation"  ));
+    configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
 
-    const static char *extraFlagNames[] =
-    {
-        "default",
-        "skip validation",
-        "skip optimization"
-    };
+    D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} };
 
-    int attempts = ArraySize(extraFlags);
+    ID3DBlob *binary = NULL;
+    std::string debugInfo;
+    gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary, &debugInfo);
+    if (error.isError())
+    {
+        return error;
+    }
 
-    ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts);
+    // It's possible that binary is NULL if the compiler failed in all configurations.  Set the executable to NULL
+    // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK.
     if (!binary)
     {
-        return NULL;
+        *outExectuable = NULL;
+        return gl::Error(GL_NO_ERROR);
     }
 
-    ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type,
-                                                  transformFeedbackVaryings, separatedOutputBuffers);
+    error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type,
+                           transformFeedbackVaryings, separatedOutputBuffers, outExectuable);
+
     SafeRelease(binary);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!debugInfo.empty())
+    {
+        (*outExectuable)->appendDebugInfo(debugInfo);
+    }
 
-    return executable;
+    return gl::Error(GL_NO_ERROR);
 }
 
 rx::UniformStorage *Renderer11::createUniformStorage(size_t storageSize)
@@ -2456,9 +2442,14 @@ QueryImpl *Renderer11::createQuery(GLenum type)
     return new Query11(this, type);
 }
 
-FenceImpl *Renderer11::createFence()
+FenceNVImpl *Renderer11::createFenceNV()
 {
-    return new Fence11(this);
+    return new FenceNV11(this);
+}
+
+FenceSyncImpl *Renderer11::createFenceSync()
+{
+    return new FenceSync11(this);
 }
 
 TransformFeedbackImpl* Renderer11::createTransformFeedback()
@@ -2501,82 +2492,75 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
     return true;
 }
 
-bool Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
-                                         GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
+gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+                                              GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
 {
     ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
     return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea);
 }
 
-bool Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource)
+gl::Error Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut)
+
 {
-    ASSERT(colorbuffer != NULL);
+    ASSERT(colorbuffer);
 
-    RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer);
-    if (renderTarget)
+    RenderTarget11 *renderTarget = NULL;
+    gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
+    if (error.isError())
     {
-        *subresourceIndex = renderTarget->getSubresourceIndex();
+        return error;
+    }
 
-        ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView();
-        if (colorBufferRTV)
-        {
-            ID3D11Resource *textureResource = NULL;
-            colorBufferRTV->GetResource(&textureResource);
+    ID3D11Resource *renderTargetResource = renderTarget->getTexture();
+    ASSERT(renderTargetResource);
 
-            if (textureResource)
-            {
-                HRESULT result = textureResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)resource);
-                SafeRelease(textureResource);
+    *subresourceIndexOut = renderTarget->getSubresourceIndex();
+    *texture2DOut = d3d11::DynamicCastComObject<ID3D11Texture2D>(renderTargetResource);
 
-                if (SUCCEEDED(result))
-                {
-                    return true;
-                }
-                else
-                {
-                    ERR("Failed to extract the ID3D11Texture2D from the render target resource, "
-                        "HRESULT: 0x%X.", result);
-                }
-            }
-        }
+    if (!(*texture2DOut))
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the ID3D11Texture2D from a RenderTarget");
     }
 
-    return false;
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
-                          const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
+gl::Error Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+                               const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter)
 {
     if (blitRenderTarget)
     {
         gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer();
+        ASSERT(readBuffer);
 
-        if (!readBuffer)
+        RenderTarget *readRenderTarget = NULL;
+        gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
+        if (error.isError())
         {
-            ERR("Failed to retrieve the read buffer from the read framebuffer.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
+            return error;
         }
-
-        RenderTarget *readRenderTarget = GetAttachmentRenderTarget(readBuffer);
+        ASSERT(readRenderTarget);
 
         for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
         {
             if (drawTarget->isEnabledColorAttachment(colorAttachment))
             {
                 gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
+                ASSERT(drawBuffer);
 
-                if (!drawBuffer)
+                RenderTarget *drawRenderTarget = NULL;
+                error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
+                if (error.isError())
                 {
-                    ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
-                    return gl::error(GL_OUT_OF_MEMORY, false);
+                    return error;
                 }
+                ASSERT(drawRenderTarget);
 
-                RenderTarget *drawRenderTarget = GetAttachmentRenderTarget(drawBuffer);
-
-                if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor,
-                                          blitRenderTarget, false, false))
+                error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, blitRenderTarget,
+                                             false, false);
+                if (error.isError())
                 {
-                    return false;
+                    return error;
                 }
             }
         }
@@ -2585,34 +2569,38 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read
     if (blitDepth || blitStencil)
     {
         gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer();
-        gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer();
+        ASSERT(readBuffer);
 
-        if (!readBuffer)
+        RenderTarget *readRenderTarget = NULL;
+        gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
+        if (error.isError())
         {
-            ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
+            return error;
         }
+        ASSERT(readRenderTarget);
+
+        gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer();
+        ASSERT(drawBuffer);
 
-        if (!drawBuffer)
+        RenderTarget *drawRenderTarget = NULL;
+        error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
+        if (error.isError())
         {
-            ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer.");
-            return gl::error(GL_OUT_OF_MEMORY, false);
+            return error;
         }
+        ASSERT(drawRenderTarget);
 
-        RenderTarget *readRenderTarget = GetAttachmentRenderTarget(readBuffer);
-        RenderTarget *drawRenderTarget = GetAttachmentRenderTarget(drawBuffer);
-        ASSERT(readRenderTarget && drawRenderTarget);
-
-        if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor,
-                                  false, blitDepth, blitStencil))
+        error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, false,
+                                     blitDepth, blitStencil);
+        if (error.isError())
         {
-            return false;
+            return error;
         }
     }
 
     invalidateFramebufferSwizzles(drawTarget);
 
-    return true;
+    return gl::Error(GL_NO_ERROR);
 }
 
 gl::Error Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
@@ -2622,41 +2610,47 @@ gl::Error Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y,
     unsigned int subresourceIndex = 0;
 
     gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
+    ASSERT(colorbuffer);
 
-    if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
+    gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture);
+    if (error.isError())
     {
-        gl::Rectangle area;
-        area.x = x;
-        area.y = y;
-        area.width = width;
-        area.height = height;
+        return error;
+    }
 
-        gl::Buffer *packBuffer = pack.pixelBuffer.get();
-        if (packBuffer != NULL)
-        {
-            rx::Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation());
-            PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels));
+    gl::Rectangle area;
+    area.x = x;
+    area.y = y;
+    area.width = width;
+    area.height = height;
 
-            gl::Error error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams);
-            if (error.isError())
-            {
-                return error;
-            }
+    gl::Buffer *packBuffer = pack.pixelBuffer.get();
+    if (packBuffer != NULL)
+    {
+        rx::Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation());
+        PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels));
 
-            packBuffer->getIndexRangeCache()->clear();
-        }
-        else
+        error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams);
+        if (error.isError())
         {
-            gl::Error error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels);
-            if (error.isError())
-            {
-                return error;
-            }
+            SafeRelease(colorBufferTexture);
+            return error;
         }
 
-        SafeRelease(colorBufferTexture);
+        packBuffer->getIndexRangeCache()->clear();
+    }
+    else
+    {
+        error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels);
+        if (error.isError())
+        {
+            SafeRelease(colorBufferTexture);
+            return error;
+        }
     }
 
+    SafeRelease(colorBufferTexture);
+
     return gl::Error(GL_NO_ERROR);
 }
 
@@ -2665,11 +2659,11 @@ Image *Renderer11::createImage()
     return new Image11();
 }
 
-void Renderer11::generateMipmap(Image *dest, Image *src)
+gl::Error Renderer11::generateMipmap(Image *dest, Image *src)
 {
     Image11 *dest11 = Image11::makeImage11(dest);
     Image11 *src11 = Image11::makeImage11(src);
-    Image11::generateMipmap(dest11, src11);
+    return Image11::generateMipmap(dest11, src11);
 }
 
 TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
@@ -2807,22 +2801,25 @@ gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int sub
     SafeRelease(srcTex);
 
     PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0);
-    packPixels(stagingTex, packParams, pixels);
+    gl::Error error = packPixels(stagingTex, packParams, pixels);
 
     SafeRelease(stagingTex);
 
-    return gl::Error(GL_NO_ERROR);
+    return error;
 }
 
-void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams &params, uint8_t *pixelsOut)
+gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams &params, uint8_t *pixelsOut)
 {
     D3D11_TEXTURE2D_DESC textureDesc;
     readTexture->GetDesc(&textureDesc);
 
     D3D11_MAPPED_SUBRESOURCE mapping;
     HRESULT hr = mDeviceContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &mapping);
-    UNUSED_ASSERTION_VARIABLE(hr);
-    ASSERT(SUCCEEDED(hr));
+    if (FAILED(hr))
+    {
+        ASSERT(hr == E_OUTOFMEMORY);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal texture for reading, result: 0x%X.", hr);
+    }
 
     uint8_t *source;
     int inputPitch;
@@ -2893,24 +2890,23 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams
     }
 
     mDeviceContext->Unmap(readTexture, 0);
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
-                                      RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
-                                      bool colorBlit, bool depthBlit, bool stencilBlit)
+gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
+                                           RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
+                                           bool colorBlit, bool depthBlit, bool stencilBlit)
 {
     // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
     // it should never be the case that both color and depth/stencil need to be blitted at
     // at the same time.
     ASSERT(colorBlit != (depthBlit || stencilBlit));
 
-    bool result = true;
-
     RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
     if (!drawRenderTarget)
     {
-        ERR("Failed to retrieve the draw render target from the draw framebuffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal draw render target from the draw framebuffer.");
     }
 
     ID3D11Resource *drawTexture = drawRenderTarget11->getTexture();
@@ -2921,8 +2917,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
     RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget);
     if (!readRenderTarget)
     {
-        ERR("Failed to retrieve the read render target from the read framebuffer.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target from the read framebuffer.");
     }
 
     ID3D11Resource *readTexture = NULL;
@@ -2944,7 +2939,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
             if (FAILED(hresult))
             {
                 SafeRelease(readTexture);
-                return gl::error(GL_OUT_OF_MEMORY, false);
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader resource view to resolve multisampled framebuffer.");
             }
         }
     }
@@ -2961,8 +2956,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
     {
         SafeRelease(readTexture);
         SafeRelease(readSRV);
-        ERR("Failed to retrieve the read render target view from the read render target.");
-        return gl::error(GL_OUT_OF_MEMORY, false);
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target view from the read render target.");
     }
 
     gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
@@ -2988,6 +2982,8 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
     const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getActualFormat());
     bool partialDSBlit = (actualFormatInfo.depthBits > 0 && depthBlit) != (actualFormatInfo.stencilBits > 0 && stencilBlit);
 
+    gl::Error result(GL_NO_ERROR);
+
     if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() &&
         !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
         (!(depthBlit || stencilBlit) || wholeBufferCopy))
@@ -3034,7 +3030,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
 
         mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0,
                                               readTexture, readSubresource, pSrcBox);
-        result = true;
+        result = gl::Error(GL_NO_ERROR);
     }
     else
     {
@@ -3115,7 +3111,8 @@ void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *atta
     ASSERT(attachment->isTexture());
     gl::Texture *texture = attachment->getTexture();
 
-    TextureStorage *texStorage = texture->getNativeTexture();
+    TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+    TextureStorage *texStorage = textureD3D->getNativeTexture();
     if (texStorage)
     {
         TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage);
@@ -3188,4 +3185,30 @@ void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureC
     d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions);
 }
 
+Workarounds Renderer11::generateWorkarounds() const
+{
+    return d3d11::GenerateWorkarounds();
+}
+
+void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv)
+{
+    auto &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+
+    ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
+
+    if (currentSRVs[resourceSlot] != srv)
+    {
+        if (shaderType == gl::SAMPLER_VERTEX)
+        {
+            mDeviceContext->VSSetShaderResources(resourceSlot, 1, &srv);
+        }
+        else
+        {
+            mDeviceContext->PSSetShaderResources(resourceSlot, 1, &srv);
+        }
+
+        currentSRVs[resourceSlot] = srv;
+    }
+}
+
 }