Edit

kc3-lang/angle/src/libGLESv2/renderer/d3d11/Blit11.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2014-01-29 09:26:48
    Hash : 9eeecfc2
    Message : Split DXGI format info to a GL mapping and info block. The GL mapping depends on context client version (for certain depth textures), but the DXGI base format info is consistent across versions. Also add DXGI component type information to the table, and add a few missing formats related to vertex inputs. Change-Id: I2d1a8ca92b1cb39f4592d94d7d435ae0ada1de65 Reviewed-on: https://chromium-review.googlesource.com/183583 Reviewed-by: Shannon Woods <shannonwoods@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Tested-by: Jamie Madill <jmadill@chromium.org>

  • src/libGLESv2/renderer/d3d11/Blit11.cpp
  • #include "precompiled.h"
    //
    // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // Blit11.cpp: Texture copy utility class.
    
    #include "libGLESv2/main.h"
    #include "libGLESv2/formatutils.h"
    #include "libGLESv2/renderer/d3d11/Blit11.h"
    #include "libGLESv2/renderer/d3d11/Renderer11.h"
    #include "libGLESv2/renderer/d3d11/renderer11_utils.h"
    #include "libGLESv2/renderer/d3d11/formatutils11.h"
    
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough2d11vs.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughdepth2d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2dui11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba2di11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2dui11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb2di11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2dui11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg2di11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2dui11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr2di11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum2d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h"
    
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough3d11vs.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough3d11gs.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3dui11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba3di11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3dui11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb3di11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3dui11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrg3di11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3dui11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughr3di11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum3d11ps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h"
    
    #include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlef2dps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlei2dps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/swizzleui2dps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlef3dps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlei3dps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/swizzleui3dps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlef2darrayps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/swizzlei2darrayps.h"
    #include "libGLESv2/renderer/d3d11/shaders/compiled/swizzleui2darrayps.h"
    
    namespace rx
    {
    
    static DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource)
    {
        ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
        if (!texture)
        {
            return DXGI_FORMAT_UNKNOWN;
        }
    
        D3D11_TEXTURE2D_DESC desc;
        texture->GetDesc(&desc);
    
        SafeRelease(texture);
    
        return desc.Format;
    }
    
    static ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context,
                                                ID3D11Resource *source, unsigned int subresource,
                                                const gl::Extents &size, unsigned int cpuAccessFlags)
    {
        D3D11_TEXTURE2D_DESC stagingDesc;
        stagingDesc.Width = size.width;
        stagingDesc.Height = size.height;
        stagingDesc.MipLevels = 1;
        stagingDesc.ArraySize = 1;
        stagingDesc.Format = GetTextureFormat(source);
        stagingDesc.SampleDesc.Count = 1;
        stagingDesc.SampleDesc.Quality = 0;
        stagingDesc.Usage = D3D11_USAGE_STAGING;
        stagingDesc.CPUAccessFlags = cpuAccessFlags;
        stagingDesc.MiscFlags = 0;
        stagingDesc.BindFlags = 0;
    
        ID3D11Texture2D *stagingTexture = NULL;
        HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture);
        if (FAILED(result))
        {
            ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result);
            return NULL;
        }
    
        context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL);
    
        return stagingTexture;
    }
    
    inline static void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize,
                                            const gl::Box &destArea, const gl::Extents &destSize,
                                            float *x1, float *y1, float *x2, float *y2,
                                            float *u1, float *v1, float *u2, float *v2)
    {
        *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
        *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f;
        *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f;
        *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f;
    
        *u1 = sourceArea.x / float(sourceSize.width);
        *v1 = sourceArea.y / float(sourceSize.height);
        *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width);
        *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height);
    }
    
    static void Write2DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize,
                                const gl::Box &destArea, const gl::Extents &destSize,
                                void *outVertices, unsigned int *outStride, unsigned int *outVertexCount,
                                D3D11_PRIMITIVE_TOPOLOGY *outTopology)
    {
        float x1, y1, x2, y2, u1, v1, u2, v2;
        GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2);
    
        d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(outVertices);
    
        d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
        d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
        d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
        d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
    
        *outStride = sizeof(d3d11::PositionTexCoordVertex);
        *outVertexCount = 4;
        *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
    }
    
    static void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize,
                                const gl::Box &destArea, const gl::Extents &destSize,
                                void *outVertices, unsigned int *outStride, unsigned int *outVertexCount,
                                D3D11_PRIMITIVE_TOPOLOGY *outTopology)
    {
        ASSERT(sourceSize.depth > 0 && destSize.depth > 0);
    
        float x1, y1, x2, y2, u1, v1, u2, v2;
        GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2);
    
        d3d11::PositionLayerTexCoord3DVertex *vertices = static_cast<d3d11::PositionLayerTexCoord3DVertex*>(outVertices);
    
        for (int i = 0; i < destSize.depth; i++)
        {
            float readDepth = (float)i / std::max(destSize.depth - 1, 1);
    
            d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth);
            d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth);
            d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth);
    
            d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth);
            d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth);
            d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth);
        }
    
        *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex);
        *outVertexCount = destSize.depth * 6;
        *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
    }
    
    Blit11::Blit11(rx::Renderer11 *renderer)
        : mRenderer(renderer), mBlitShaderMap(compareBlitParameters), mSwizzleShaderMap(compareSwizzleParameters),
          mVertexBuffer(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL),
          mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL),
          mQuad2DIL(NULL), mQuad2DVS(NULL), mDepthPS(NULL),
          mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL),
          mSwizzleCB(NULL)
    {
        HRESULT result;
        ID3D11Device *device = mRenderer->getDevice();
    
        D3D11_BUFFER_DESC vbDesc;
        vbDesc.ByteWidth = std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) *
                           6 * renderer->getMaxTextureDepth();
        vbDesc.Usage = D3D11_USAGE_DYNAMIC;
        vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
        vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
        vbDesc.MiscFlags = 0;
        vbDesc.StructureByteStride = 0;
    
        result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer");
    
        D3D11_SAMPLER_DESC pointSamplerDesc;
        pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
        pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
        pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
        pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
        pointSamplerDesc.MipLODBias = 0.0f;
        pointSamplerDesc.MaxAnisotropy = 0;
        pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
        pointSamplerDesc.BorderColor[0] = 0.0f;
        pointSamplerDesc.BorderColor[1] = 0.0f;
        pointSamplerDesc.BorderColor[2] = 0.0f;
        pointSamplerDesc.BorderColor[3] = 0.0f;
        pointSamplerDesc.MinLOD = 0.0f;
        pointSamplerDesc.MaxLOD = 0.0f;
    
        result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mPointSampler, "Blit11 point sampler");
    
        D3D11_SAMPLER_DESC linearSamplerDesc;
        linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
        linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
        linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
        linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
        linearSamplerDesc.MipLODBias = 0.0f;
        linearSamplerDesc.MaxAnisotropy = 0;
        linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
        linearSamplerDesc.BorderColor[0] = 0.0f;
        linearSamplerDesc.BorderColor[1] = 0.0f;
        linearSamplerDesc.BorderColor[2] = 0.0f;
        linearSamplerDesc.BorderColor[3] = 0.0f;
        linearSamplerDesc.MinLOD = 0.0f;
        linearSamplerDesc.MaxLOD = 0.0f;
    
        result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler");
    
        // Use a rasterizer state that will not cull so that inverted quads will not be culled
        D3D11_RASTERIZER_DESC rasterDesc;
        rasterDesc.FillMode = D3D11_FILL_SOLID;
        rasterDesc.CullMode = D3D11_CULL_NONE;
        rasterDesc.FrontCounterClockwise = FALSE;
        rasterDesc.DepthBias = 0;
        rasterDesc.SlopeScaledDepthBias = 0.0f;
        rasterDesc.DepthBiasClamp = 0.0f;
        rasterDesc.DepthClipEnable = TRUE;
        rasterDesc.MultisampleEnable = FALSE;
        rasterDesc.AntialiasedLineEnable = FALSE;
    
        rasterDesc.ScissorEnable = TRUE;
        result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state");
    
        rasterDesc.ScissorEnable = FALSE;
        result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state");
    
        D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
        depthStencilDesc.DepthEnable = true;
        depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
        depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
        depthStencilDesc.StencilEnable = FALSE;
        depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
        depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
        depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
        depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
        depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
    
        result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state");
    
        D3D11_INPUT_ELEMENT_DESC quad2DLayout[] =
        {
            { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        };
    
        result = device->CreateInputLayout(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), &mQuad2DIL);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mQuad2DIL, "Blit11 2D input layout");
    
        result = device->CreateVertexShader(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), NULL, &mQuad2DVS);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader");
    
        result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader");
    
        D3D11_INPUT_ELEMENT_DESC quad3DLayout[] =
        {
            { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT,    0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            { "LAYER",    0, DXGI_FORMAT_R32_UINT,        0,  8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
            { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        };
    
        result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout");
    
        result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader");
    
        result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader");
    
        buildShaderMap();
    
        D3D11_BUFFER_DESC swizzleBufferDesc;
        swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4;
        swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
        swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
        swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
        swizzleBufferDesc.MiscFlags = 0;
        swizzleBufferDesc.StructureByteStride = 0;
    
        result = device->CreateBuffer(&swizzleBufferDesc, NULL, &mSwizzleCB);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer");
    }
    
    Blit11::~Blit11()
    {
        SafeRelease(mVertexBuffer);
        SafeRelease(mPointSampler);
        SafeRelease(mLinearSampler);
        SafeRelease(mScissorEnabledRasterizerState);
        SafeRelease(mScissorDisabledRasterizerState);
        SafeRelease(mDepthStencilState);
    
        SafeRelease(mQuad2DIL);
        SafeRelease(mQuad2DVS);
        SafeRelease(mDepthPS);
    
        SafeRelease(mQuad3DIL);
        SafeRelease(mQuad3DVS);
        SafeRelease(mQuad3DGS);
    
        SafeRelease(mSwizzleCB);
    
        clearShaderMap();
    }
    
    static inline unsigned int GetSwizzleIndex(GLenum swizzle)
    {
        unsigned int colorIndex = 0;
    
        switch (swizzle)
        {
          case GL_RED:   colorIndex = 0; break;
          case GL_GREEN: colorIndex = 1; break;
          case GL_BLUE:  colorIndex = 2; break;
          case GL_ALPHA: colorIndex = 3; break;
          case GL_ZERO:  colorIndex = 4; break;
          case GL_ONE:   colorIndex = 5; break;
          default:       UNREACHABLE();  break;
        }
    
        return colorIndex;
    }
    
    bool Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size,
                                GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
    {
        HRESULT result;
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    
        D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
        source->GetDesc(&sourceSRVDesc);
        GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(sourceSRVDesc.Format, mRenderer->getCurrentClientVersion());
    
        GLenum shaderType = GL_NONE;
        switch (gl::GetComponentType(sourceInternalFormat, mRenderer->getCurrentClientVersion()))
        {
          case GL_UNSIGNED_NORMALIZED:
          case GL_SIGNED_NORMALIZED:
          case GL_FLOAT:
            shaderType = GL_FLOAT;
            break;
          case GL_INT:
            shaderType = GL_INT;
            break;
          case GL_UNSIGNED_INT:
            shaderType = GL_UNSIGNED_INT;
            break;
          default:
            UNREACHABLE();
            break;
        }
    
        SwizzleParameters parameters = { 0 };
        parameters.mDestinationType = shaderType;
        parameters.mViewDimension = sourceSRVDesc.ViewDimension;
    
        SwizzleShaderMap::const_iterator i = mSwizzleShaderMap.find(parameters);
        if (i == mSwizzleShaderMap.end())
        {
            UNREACHABLE();
            return false;
        }
    
        const Shader &shader = i->second;
    
        // Set vertices
        D3D11_MAPPED_SUBRESOURCE mappedResource;
        result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
        if (FAILED(result))
        {
            ERR("Failed to map vertex buffer for texture swizzle, HRESULT: 0x%X.", result);
            return false;
        }
    
        UINT stride = 0;
        UINT startIdx = 0;
        UINT drawCount = 0;
        D3D11_PRIMITIVE_TOPOLOGY topology;
    
        gl::Box area(0, 0, 0, size.width, size.height, size.depth);
        shader.mVertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, &topology);
    
        deviceContext->Unmap(mVertexBuffer, 0);
    
        // Set constant buffer
        result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
        if (FAILED(result))
        {
            ERR("Failed to map constant buffer for texture swizzle, HRESULT: 0x%X.", result);
            return false;
        }
    
        unsigned int *swizzleIndices = reinterpret_cast<unsigned int*>(mappedResource.pData);
        swizzleIndices[0] = GetSwizzleIndex(swizzleRed);
        swizzleIndices[1] = GetSwizzleIndex(swizzleGreen);
        swizzleIndices[2] = GetSwizzleIndex(swizzleBlue);
        swizzleIndices[3] = GetSwizzleIndex(swizzleAlpha);
    
        deviceContext->Unmap(mSwizzleCB, 0);
    
        // Apply vertex buffer
        deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
    
        // Apply constant buffer
        deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB);
    
        // Apply state
        deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
        deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
        deviceContext->RSSetState(mScissorDisabledRasterizerState);
    
        // Apply shaders
        deviceContext->IASetInputLayout(shader.mInputLayout);
        deviceContext->IASetPrimitiveTopology(topology);
        deviceContext->VSSetShader(shader.mVertexShader, NULL, 0);
    
        deviceContext->PSSetShader(shader.mPixelShader, NULL, 0);
        deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0);
    
        // Unset the currently bound shader resource to avoid conflicts
        ID3D11ShaderResourceView *const nullSRV = NULL;
        deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    
        // Apply render target
        mRenderer->setOneTimeRenderTarget(dest);
    
        // Set the viewport
        D3D11_VIEWPORT viewport;
        viewport.TopLeftX = 0;
        viewport.TopLeftY = 0;
        viewport.Width = size.width;
        viewport.Height = size.height;
        viewport.MinDepth = 0.0f;
        viewport.MaxDepth = 1.0f;
        deviceContext->RSSetViewports(1, &viewport);
    
        // Apply textures
        deviceContext->PSSetShaderResources(0, 1, &source);
    
        // Apply samplers
        deviceContext->PSSetSamplers(0, 1, &mPointSampler);
    
        // Draw the quad
        deviceContext->Draw(drawCount, 0);
    
        // Unbind textures and render targets and vertex buffer
        deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    
        mRenderer->unapplyRenderTargets();
    
        UINT zero = 0;
        ID3D11Buffer *const nullBuffer = NULL;
        deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
    
        mRenderer->markAllStateDirty();
    
        return true;
    }
    
    bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
                             ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
                             const gl::Rectangle *scissor, GLenum destFormat, GLenum filter)
    {
        HRESULT result;
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    
        // Determine if the source format is a signed integer format, the destFormat will already
        // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned.
        D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
        source->GetDesc(&sourceSRVDesc);
        GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(sourceSRVDesc.Format, mRenderer->getCurrentClientVersion());
    
        BlitParameters parameters = { 0 };
        parameters.mDestinationFormat = destFormat;
        parameters.mSignedInteger = gl::GetComponentType(sourceInternalFormat, mRenderer->getCurrentClientVersion()) == GL_INT;
        parameters.m3DBlit = sourceArea.depth > 1;
    
        BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters);
        if (i == mBlitShaderMap.end())
        {
            UNREACHABLE();
            return false;
        }
    
        const Shader& shader = i->second;
    
        // Set vertices
        D3D11_MAPPED_SUBRESOURCE mappedResource;
        result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
        if (FAILED(result))
        {
            ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
            return false;
        }
    
        UINT stride = 0;
        UINT startIdx = 0;
        UINT drawCount = 0;
        D3D11_PRIMITIVE_TOPOLOGY topology;
    
        shader.mVertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
                                    &stride, &drawCount, &topology);
    
        deviceContext->Unmap(mVertexBuffer, 0);
    
        // Apply vertex buffer
        deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
    
        // Apply state
        deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
        deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
    
        if (scissor)
        {
            D3D11_RECT scissorRect;
            scissorRect.left = scissor->x;
            scissorRect.right = scissor->x + scissor->width;
            scissorRect.top = scissor->y;
            scissorRect.bottom = scissor->y + scissor->height;
    
            deviceContext->RSSetScissorRects(1, &scissorRect);
            deviceContext->RSSetState(mScissorEnabledRasterizerState);
        }
        else
        {
            deviceContext->RSSetState(mScissorDisabledRasterizerState);
        }
    
        // Apply shaders
        deviceContext->IASetInputLayout(shader.mInputLayout);
        deviceContext->IASetPrimitiveTopology(topology);
        deviceContext->VSSetShader(shader.mVertexShader, NULL, 0);
    
        deviceContext->PSSetShader(shader.mPixelShader, NULL, 0);
        deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0);
    
        // Unset the currently bound shader resource to avoid conflicts
        ID3D11ShaderResourceView *const nullSRV = NULL;
        deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    
        // Apply render target
        mRenderer->setOneTimeRenderTarget(dest);
    
        // Set the viewport
        D3D11_VIEWPORT viewport;
        viewport.TopLeftX = 0;
        viewport.TopLeftY = 0;
        viewport.Width = destSize.width;
        viewport.Height = destSize.height;
        viewport.MinDepth = 0.0f;
        viewport.MaxDepth = 1.0f;
        deviceContext->RSSetViewports(1, &viewport);
    
        // Apply textures
        deviceContext->PSSetShaderResources(0, 1, &source);
    
        // Apply samplers
        ID3D11SamplerState *sampler = NULL;
        switch (filter)
        {
          case GL_NEAREST: sampler = mPointSampler;  break;
          case GL_LINEAR:  sampler = mLinearSampler; break;
          default:         UNREACHABLE(); return false;
        }
        deviceContext->PSSetSamplers(0, 1, &sampler);
    
        // Draw the quad
        deviceContext->Draw(drawCount, 0);
    
        // Unbind textures and render targets and vertex buffer
        deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    
        mRenderer->unapplyRenderTargets();
    
        UINT zero = 0;
        ID3D11Buffer *const nullBuffer = NULL;
        deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
    
        mRenderer->markAllStateDirty();
    
        return true;
    }
    
    bool Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
                             ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
                             const gl::Rectangle *scissor)
    {
        return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
                                dest, destSubresource, destArea, destSize,
                                scissor, true);
    }
    
    bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
                           ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
                           const gl::Rectangle *scissor)
    {
        HRESULT result;
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    
        // Set vertices
        D3D11_MAPPED_SUBRESOURCE mappedResource;
        result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
        if (FAILED(result))
        {
            ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
            return false;
        }
    
        UINT stride = 0;
        UINT startIdx = 0;
        UINT drawCount = 0;
        D3D11_PRIMITIVE_TOPOLOGY topology;
    
        Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
                        &stride, &drawCount, &topology);
    
        deviceContext->Unmap(mVertexBuffer, 0);
    
        // Apply vertex buffer
        deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
    
        // Apply state
        deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
        deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF);
    
        if (scissor)
        {
            D3D11_RECT scissorRect;
            scissorRect.left = scissor->x;
            scissorRect.right = scissor->x + scissor->width;
            scissorRect.top = scissor->y;
            scissorRect.bottom = scissor->y + scissor->height;
    
            deviceContext->RSSetScissorRects(1, &scissorRect);
            deviceContext->RSSetState(mScissorEnabledRasterizerState);
        }
        else
        {
            deviceContext->RSSetState(mScissorDisabledRasterizerState);
        }
    
        // Apply shaders
        deviceContext->IASetInputLayout(mQuad2DIL);
        deviceContext->IASetPrimitiveTopology(topology);
        deviceContext->VSSetShader(mQuad2DVS, NULL, 0);
    
        deviceContext->PSSetShader(mDepthPS, NULL, 0);
        deviceContext->GSSetShader(NULL, NULL, 0);
    
        // Unset the currently bound shader resource to avoid conflicts
        ID3D11ShaderResourceView *const nullSRV = NULL;
        deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    
        // Apply render target
        deviceContext->OMSetRenderTargets(0, NULL, dest);
    
        // Set the viewport
        D3D11_VIEWPORT viewport;
        viewport.TopLeftX = 0;
        viewport.TopLeftY = 0;
        viewport.Width = destSize.width;
        viewport.Height = destSize.height;
        viewport.MinDepth = 0.0f;
        viewport.MaxDepth = 1.0f;
        deviceContext->RSSetViewports(1, &viewport);
    
        // Apply textures
        deviceContext->PSSetShaderResources(0, 1, &source);
    
        // Apply samplers
        deviceContext->PSSetSamplers(0, 1, &mPointSampler);
    
        // Draw the quad
        deviceContext->Draw(drawCount, 0);
    
        // Unbind textures and render targets and vertex buffer
        deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    
        mRenderer->unapplyRenderTargets();
    
        UINT zero = 0;
        ID3D11Buffer *const nullBuffer = NULL;
        deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
    
        mRenderer->markAllStateDirty();
    
        return true;
    }
    
    bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
                                  ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
                                  const gl::Rectangle *scissor)
    {
        return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
                                dest, destSubresource, destArea, destSize,
                                scissor, false);
    }
    
    bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
                                  ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
                                  const gl::Rectangle *scissor, bool stencilOnly)
    {
        ID3D11Device *device = mRenderer->getDevice();
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    
        ID3D11Resource *sourceStaging = CreateStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ);
        // HACK: Create the destination staging buffer as a read/write texture so ID3D11DevicContext::UpdateSubresource can be called
        //       using it's mapped data as a source
        ID3D11Resource *destStaging = CreateStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE);
    
        if (!sourceStaging || !destStaging)
        {
            SafeRelease(sourceStaging);
            SafeRelease(destStaging);
            return false;
        }
    
        DXGI_FORMAT format = GetTextureFormat(source);
        ASSERT(format == GetTextureFormat(dest));
    
        unsigned int pixelSize = d3d11::GetFormatPixelBytes(format);
        unsigned int copyOffset = 0;
        unsigned int copySize = pixelSize;
        if (stencilOnly)
        {
            copyOffset = d3d11::GetStencilOffset(format) / 8;
            copySize = d3d11::GetStencilBits(format) / 8;
    
            // It would be expensive to have non-byte sized stencil sizes since it would
            // require reading from the destination, currently there aren't any though.
            ASSERT(d3d11::GetStencilBits(format)   % 8 == 0 &&
                   d3d11::GetStencilOffset(format) % 8 == 0);
        }
    
        D3D11_MAPPED_SUBRESOURCE sourceMapping, destMapping;
        deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping);
        deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping);
    
        if (!sourceMapping.pData || !destMapping.pData)
        {
            if (!sourceMapping.pData)
            {
                deviceContext->Unmap(sourceStaging, 0);
            }
            if (!destMapping.pData)
            {
                deviceContext->Unmap(destStaging, 0);
            }
            SafeRelease(sourceStaging);
            SafeRelease(destStaging);
            return false;
        }
    
        gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
    
        // Clip dest area to the destination size
        gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea);
    
        // Clip dest area to the scissor
        if (scissor)
        {
            gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea);
        }
    
        // Determine if entire rows can be copied at once instead of each individual pixel, requires that there is
        // no out of bounds lookups required, the entire pixel is copied and no stretching
        bool wholeRowCopy = sourceArea.width == clippedDestArea.width &&
                            sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width &&
                            copySize == pixelSize;
    
        for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
        {
            float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1);
    
            // Interpolate using the original source rectangle to determine which row to sample from while clamping to the edges
            unsigned int readRow = gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1);
            unsigned int writeRow = y;
    
            if (wholeRowCopy)
            {
                void *sourceRow = reinterpret_cast<char*>(sourceMapping.pData) +
                                  readRow * sourceMapping.RowPitch +
                                  sourceArea.x * pixelSize;
    
                void *destRow = reinterpret_cast<char*>(destMapping.pData) +
                                writeRow * destMapping.RowPitch +
                                destArea.x * pixelSize;
    
                memcpy(destRow, sourceRow, pixelSize * destArea.width);
            }
            else
            {
                for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++)
                {
                    float xPerc = static_cast<float>(x - destArea.x) / (destArea.width - 1);
    
                    // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges
                    unsigned int readColumn = gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1);
                    unsigned int writeColumn = x;
    
                    void *sourcePixel = reinterpret_cast<char*>(sourceMapping.pData) +
                                        readRow * sourceMapping.RowPitch +
                                        readColumn * pixelSize +
                                        copyOffset;
    
                    void *destPixel = reinterpret_cast<char*>(destMapping.pData) +
                                      writeRow * destMapping.RowPitch +
                                      writeColumn * pixelSize +
                                      copyOffset;
    
                    memcpy(destPixel, sourcePixel, copySize);
                }
            }
        }
    
        // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion
        //       according to MSDN.
        deviceContext->UpdateSubresource(dest, destSubresource, NULL, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch);
    
        deviceContext->Unmap(sourceStaging, 0);
        deviceContext->Unmap(destStaging, 0);
    
        // TODO: Determine why this call to ID3D11DevicContext::CopySubresourceRegion causes a TDR timeout on some
        //       systems when called repeatedly.
        // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, NULL);
    
        SafeRelease(sourceStaging);
        SafeRelease(destStaging);
    
        return true;
    }
    
    bool Blit11::compareBlitParameters(const Blit11::BlitParameters &a, const Blit11::BlitParameters &b)
    {
        return memcmp(&a, &b, sizeof(Blit11::BlitParameters)) < 0;
    }
    
    bool Blit11::compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b)
    {
        return memcmp(&a, &b, sizeof(Blit11::SwizzleParameters)) < 0;
    }
    
    void Blit11::add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps)
    {
        BlitParameters params = { 0 };
        params.mDestinationFormat = destFormat;
        params.mSignedInteger = signedInteger;
        params.m3DBlit = false;
    
        ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end());
        ASSERT(ps);
    
        Shader shader;
        shader.mVertexWriteFunction = Write2DVertices;
        shader.mInputLayout = mQuad2DIL;
        shader.mVertexShader = mQuad2DVS;
        shader.mGeometryShader = NULL;
        shader.mPixelShader = ps;
    
        mBlitShaderMap[params] = shader;
    }
    
    void Blit11::add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps)
    {
        BlitParameters params = { 0 };
        params.mDestinationFormat = destFormat;
        params.mSignedInteger = signedInteger;
        params.m3DBlit = true;
    
        ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end());
        ASSERT(ps);
    
        Shader shader;
        shader.mVertexWriteFunction = Write3DVertices;
        shader.mInputLayout = mQuad3DIL;
        shader.mVertexShader = mQuad3DVS;
        shader.mGeometryShader = mQuad3DGS;
        shader.mPixelShader = ps;
    
        mBlitShaderMap[params] = shader;
    }
    
    void Blit11::addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps)
    {
        SwizzleParameters params = { 0 };
        params.mDestinationType = destType;
        params.mViewDimension = viewDimension;
    
        ASSERT(mSwizzleShaderMap.find(params) == mSwizzleShaderMap.end());
        ASSERT(ps);
    
        Shader shader;
        switch (viewDimension)
        {
          case D3D_SRV_DIMENSION_TEXTURE2D:
            shader.mVertexWriteFunction = Write2DVertices;
            shader.mInputLayout = mQuad2DIL;
            shader.mVertexShader = mQuad2DVS;
            shader.mGeometryShader = NULL;
            break;
    
          case D3D_SRV_DIMENSION_TEXTURE3D:
          case D3D_SRV_DIMENSION_TEXTURE2DARRAY:
          case D3D_SRV_DIMENSION_TEXTURECUBE:
            shader.mVertexWriteFunction = Write3DVertices;
            shader.mInputLayout = mQuad3DIL;
            shader.mVertexShader = mQuad3DVS;
            shader.mGeometryShader = mQuad3DGS;
            break;
    
          default:
            UNREACHABLE();
            break;
        }
        shader.mPixelShader = ps;
    
        mSwizzleShaderMap[params] = shader;
    }
    
    void Blit11::buildShaderMap()
    {
        ID3D11Device *device = mRenderer->getDevice();
    
        add2DBlitShaderToMap(GL_RGBA,            false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D,     "Blit11 2D RGBA pixel shader"           ));
        add2DBlitShaderToMap(GL_RGBA_INTEGER,    false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI,   "Blit11 2D RGBA UI pixel shader"        ));
        add2DBlitShaderToMap(GL_RGBA_INTEGER,    true,  d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI,    "Blit11 2D RGBA I pixel shader"         ));
        add2DBlitShaderToMap(GL_BGRA_EXT,        false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D,     "Blit11 2D BGRA pixel shader"           ));
        add2DBlitShaderToMap(GL_RGB,             false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D,      "Blit11 2D RGB pixel shader"            ));
        add2DBlitShaderToMap(GL_RGB_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI,    "Blit11 2D RGB UI pixel shader"         ));
        add2DBlitShaderToMap(GL_RGB_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughRGB2DI,     "Blit11 2D RGB I pixel shader"          ));
        add2DBlitShaderToMap(GL_RG,              false, d3d11::CompilePS(device, g_PS_PassthroughRG2D,       "Blit11 2D RG pixel shader"             ));
        add2DBlitShaderToMap(GL_RG_INTEGER,      false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI,     "Blit11 2D RG UI pixel shader"          ));
        add2DBlitShaderToMap(GL_RG_INTEGER,      true,  d3d11::CompilePS(device, g_PS_PassthroughRG2DI,      "Blit11 2D RG I pixel shader"           ));
        add2DBlitShaderToMap(GL_RED,             false, d3d11::CompilePS(device, g_PS_PassthroughR2D,        "Blit11 2D R pixel shader"              ));
        add2DBlitShaderToMap(GL_RED_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI,      "Blit11 2D R UI pixel shader"           ));
        add2DBlitShaderToMap(GL_RED_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughR2DI,       "Blit11 2D R I pixel shader"            ));
        add2DBlitShaderToMap(GL_ALPHA,           false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D,     "Blit11 2D alpha pixel shader"          ));
        add2DBlitShaderToMap(GL_LUMINANCE,       false, d3d11::CompilePS(device, g_PS_PassthroughLum2D,      "Blit11 2D lum pixel shader"            ));
        add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader"));
    
        add3DBlitShaderToMap(GL_RGBA,            false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D RGBA pixel shader"           ));
        add3DBlitShaderToMap(GL_RGBA_INTEGER,    false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI,   "Blit11 3D UI RGBA pixel shader"        ));
        add3DBlitShaderToMap(GL_RGBA_INTEGER,    true,  d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI,    "Blit11 3D I RGBA pixel shader"         ));
        add3DBlitShaderToMap(GL_BGRA_EXT,        false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D BGRA pixel shader"           ));
        add3DBlitShaderToMap(GL_RGB,             false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D,      "Blit11 3D RGB pixel shader"            ));
        add3DBlitShaderToMap(GL_RGB_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI,    "Blit11 3D RGB UI pixel shader"         ));
        add3DBlitShaderToMap(GL_RGB_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughRGB3DI,     "Blit11 3D RGB I pixel shader"          ));
        add3DBlitShaderToMap(GL_RG,              false, d3d11::CompilePS(device, g_PS_PassthroughRG3D,       "Blit11 3D RG pixel shader"             ));
        add3DBlitShaderToMap(GL_RG_INTEGER,      false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI,     "Blit11 3D RG UI pixel shader"          ));
        add3DBlitShaderToMap(GL_RG_INTEGER,      true,  d3d11::CompilePS(device, g_PS_PassthroughRG3DI,      "Blit11 3D RG I pixel shader"           ));
        add3DBlitShaderToMap(GL_RED,             false, d3d11::CompilePS(device, g_PS_PassthroughR3D,        "Blit11 3D R pixel shader"              ));
        add3DBlitShaderToMap(GL_RED_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI,      "Blit11 3D R UI pixel shader"           ));
        add3DBlitShaderToMap(GL_RED_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughR3DI,       "Blit11 3D R I pixel shader"            ));
        add3DBlitShaderToMap(GL_ALPHA,           false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D alpha pixel shader"          ));
        add3DBlitShaderToMap(GL_LUMINANCE,       false, d3d11::CompilePS(device, g_PS_PassthroughLum3D,      "Blit11 3D luminance pixel shader"      ));
        add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader"));
    
        addSwizzleShaderToMap(GL_FLOAT,        D3D_SRV_DIMENSION_TEXTURE2D,      d3d11::CompilePS(device, g_PS_SwizzleF2D,       "Blit11 2D F swizzle pixel shader" ));
        addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D,      d3d11::CompilePS(device, g_PS_SwizzleUI2D,      "Blit11 2D UI swizzle pixel shader"));
        addSwizzleShaderToMap(GL_INT,          D3D_SRV_DIMENSION_TEXTURE2D,      d3d11::CompilePS(device, g_PS_SwizzleI2D,       "Blit11 2D I swizzle pixel shader" ));
    
        addSwizzleShaderToMap(GL_FLOAT,        D3D_SRV_DIMENSION_TEXTURECUBE,    d3d11::CompilePS(device, g_PS_SwizzleF2DArray,  "Blit11 2D Cube F swizzle pixel shader" ));
        addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE,    d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader"));
        addSwizzleShaderToMap(GL_INT,          D3D_SRV_DIMENSION_TEXTURECUBE,    d3d11::CompilePS(device, g_PS_SwizzleI2DArray,  "Blit11 2D Cube I swizzle pixel shader" ));
    
        addSwizzleShaderToMap(GL_FLOAT,        D3D_SRV_DIMENSION_TEXTURE3D,      d3d11::CompilePS(device, g_PS_SwizzleF3D,       "Blit11 3D F swizzle pixel shader" ));
        addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D,      d3d11::CompilePS(device, g_PS_SwizzleUI3D,      "Blit11 3D UI swizzle pixel shader"));
        addSwizzleShaderToMap(GL_INT,          D3D_SRV_DIMENSION_TEXTURE3D,      d3d11::CompilePS(device, g_PS_SwizzleI3D,       "Blit11 3D I swizzle pixel shader" ));
    
        addSwizzleShaderToMap(GL_FLOAT,        D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray,  "Blit11 2D Array F swizzle pixel shader" ));
        addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader"));
        addSwizzleShaderToMap(GL_INT,          D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray,  "Blit11 2D Array I swizzle pixel shader" ));
    }
    
    void Blit11::clearShaderMap()
    {
        for (BlitShaderMap::iterator i = mBlitShaderMap.begin(); i != mBlitShaderMap.end(); ++i)
        {
            Shader &shader = i->second;
            SafeRelease(shader.mPixelShader);
        }
        mBlitShaderMap.clear();
    
        for (SwizzleShaderMap::iterator i = mSwizzleShaderMap.begin(); i != mSwizzleShaderMap.end(); ++i)
        {
            Shader &shader = i->second;
            SafeRelease(shader.mPixelShader);
        }
        mSwizzleShaderMap.clear();
    }
    
    }