Home | History | Annotate | Download | only in d3d11
      1 //
      2 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // Blit11.cpp: Texture copy utility class.
      8 
      9 #include "libGLESv2/renderer/d3d/d3d11/Blit11.h"
     10 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
     11 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
     12 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
     13 #include "libGLESv2/main.h"
     14 #include "libGLESv2/formatutils.h"
     15 
     16 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
     17 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h"
     18 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
     19 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h"
     20 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h"
     21 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h"
     22 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h"
     23 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h"
     24 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h"
     25 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h"
     26 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h"
     27 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h"
     28 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h"
     29 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h"
     30 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h"
     31 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h"
     32 
     33 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
     34 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h"
     35 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h"
     36 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h"
     37 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h"
     38 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h"
     39 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h"
     40 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h"
     41 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h"
     42 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h"
     43 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h"
     44 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h"
     45 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h"
     46 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h"
     47 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h"
     48 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h"
     49 
     50 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
     51 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
     52 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
     53 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
     54 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
     55 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
     56 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
     57 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
     58 #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h"
     59 
     60 namespace rx
     61 {
     62 
     63 static DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource)
     64 {
     65     ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
     66     if (!texture)
     67     {
     68         return DXGI_FORMAT_UNKNOWN;
     69     }
     70 
     71     D3D11_TEXTURE2D_DESC desc;
     72     texture->GetDesc(&desc);
     73 
     74     SafeRelease(texture);
     75 
     76     return desc.Format;
     77 }
     78 
     79 static ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context,
     80                                             ID3D11Resource *source, unsigned int subresource,
     81                                             const gl::Extents &size, unsigned int cpuAccessFlags)
     82 {
     83     D3D11_TEXTURE2D_DESC stagingDesc;
     84     stagingDesc.Width = size.width;
     85     stagingDesc.Height = size.height;
     86     stagingDesc.MipLevels = 1;
     87     stagingDesc.ArraySize = 1;
     88     stagingDesc.Format = GetTextureFormat(source);
     89     stagingDesc.SampleDesc.Count = 1;
     90     stagingDesc.SampleDesc.Quality = 0;
     91     stagingDesc.Usage = D3D11_USAGE_STAGING;
     92     stagingDesc.CPUAccessFlags = cpuAccessFlags;
     93     stagingDesc.MiscFlags = 0;
     94     stagingDesc.BindFlags = 0;
     95 
     96     ID3D11Texture2D *stagingTexture = NULL;
     97     HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture);
     98     if (FAILED(result))
     99     {
    100         ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result);
    101         return NULL;
    102     }
    103 
    104     context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL);
    105 
    106     return stagingTexture;
    107 }
    108 
    109 inline static void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize,
    110                                         const gl::Box &destArea, const gl::Extents &destSize,
    111                                         float *x1, float *y1, float *x2, float *y2,
    112                                         float *u1, float *v1, float *u2, float *v2)
    113 {
    114     *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
    115     *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f;
    116     *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f;
    117     *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f;
    118 
    119     *u1 = sourceArea.x / float(sourceSize.width);
    120     *v1 = sourceArea.y / float(sourceSize.height);
    121     *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width);
    122     *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height);
    123 }
    124 
    125 static void Write2DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize,
    126                             const gl::Box &destArea, const gl::Extents &destSize,
    127                             void *outVertices, unsigned int *outStride, unsigned int *outVertexCount,
    128                             D3D11_PRIMITIVE_TOPOLOGY *outTopology)
    129 {
    130     float x1, y1, x2, y2, u1, v1, u2, v2;
    131     GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2);
    132 
    133     d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(outVertices);
    134 
    135     d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
    136     d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
    137     d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
    138     d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
    139 
    140     *outStride = sizeof(d3d11::PositionTexCoordVertex);
    141     *outVertexCount = 4;
    142     *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
    143 }
    144 
    145 static void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize,
    146                             const gl::Box &destArea, const gl::Extents &destSize,
    147                             void *outVertices, unsigned int *outStride, unsigned int *outVertexCount,
    148                             D3D11_PRIMITIVE_TOPOLOGY *outTopology)
    149 {
    150     ASSERT(sourceSize.depth > 0 && destSize.depth > 0);
    151 
    152     float x1, y1, x2, y2, u1, v1, u2, v2;
    153     GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2);
    154 
    155     d3d11::PositionLayerTexCoord3DVertex *vertices = static_cast<d3d11::PositionLayerTexCoord3DVertex*>(outVertices);
    156 
    157     for (int i = 0; i < destSize.depth; i++)
    158     {
    159         float readDepth = (float)i / std::max(destSize.depth - 1, 1);
    160 
    161         d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth);
    162         d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth);
    163         d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth);
    164 
    165         d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth);
    166         d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth);
    167         d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth);
    168     }
    169 
    170     *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex);
    171     *outVertexCount = destSize.depth * 6;
    172     *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
    173 }
    174 
    175 Blit11::Blit11(rx::Renderer11 *renderer)
    176     : mRenderer(renderer), mBlitShaderMap(compareBlitParameters), mSwizzleShaderMap(compareSwizzleParameters),
    177       mVertexBuffer(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL),
    178       mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL),
    179       mQuad2DIL(NULL), mQuad2DVS(NULL), mDepthPS(NULL),
    180       mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL),
    181       mSwizzleCB(NULL)
    182 {
    183     HRESULT result;
    184     ID3D11Device *device = mRenderer->getDevice();
    185 
    186     D3D11_BUFFER_DESC vbDesc;
    187     vbDesc.ByteWidth = std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) *
    188                        6 * renderer->getRendererCaps().max3DTextureSize;
    189     vbDesc.Usage = D3D11_USAGE_DYNAMIC;
    190     vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    191     vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    192     vbDesc.MiscFlags = 0;
    193     vbDesc.StructureByteStride = 0;
    194 
    195     result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer);
    196     ASSERT(SUCCEEDED(result));
    197     d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer");
    198 
    199     D3D11_SAMPLER_DESC pointSamplerDesc;
    200     pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
    201     pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
    202     pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
    203     pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
    204     pointSamplerDesc.MipLODBias = 0.0f;
    205     pointSamplerDesc.MaxAnisotropy = 0;
    206     pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    207     pointSamplerDesc.BorderColor[0] = 0.0f;
    208     pointSamplerDesc.BorderColor[1] = 0.0f;
    209     pointSamplerDesc.BorderColor[2] = 0.0f;
    210     pointSamplerDesc.BorderColor[3] = 0.0f;
    211     pointSamplerDesc.MinLOD = 0.0f;
    212     pointSamplerDesc.MaxLOD = 0.0f;
    213 
    214     result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
    215     ASSERT(SUCCEEDED(result));
    216     d3d11::SetDebugName(mPointSampler, "Blit11 point sampler");
    217 
    218     D3D11_SAMPLER_DESC linearSamplerDesc;
    219     linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    220     linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
    221     linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
    222     linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
    223     linearSamplerDesc.MipLODBias = 0.0f;
    224     linearSamplerDesc.MaxAnisotropy = 0;
    225     linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    226     linearSamplerDesc.BorderColor[0] = 0.0f;
    227     linearSamplerDesc.BorderColor[1] = 0.0f;
    228     linearSamplerDesc.BorderColor[2] = 0.0f;
    229     linearSamplerDesc.BorderColor[3] = 0.0f;
    230     linearSamplerDesc.MinLOD = 0.0f;
    231     linearSamplerDesc.MaxLOD = 0.0f;
    232 
    233     result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
    234     ASSERT(SUCCEEDED(result));
    235     d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler");
    236 
    237     // Use a rasterizer state that will not cull so that inverted quads will not be culled
    238     D3D11_RASTERIZER_DESC rasterDesc;
    239     rasterDesc.FillMode = D3D11_FILL_SOLID;
    240     rasterDesc.CullMode = D3D11_CULL_NONE;
    241     rasterDesc.FrontCounterClockwise = FALSE;
    242     rasterDesc.DepthBias = 0;
    243     rasterDesc.SlopeScaledDepthBias = 0.0f;
    244     rasterDesc.DepthBiasClamp = 0.0f;
    245     rasterDesc.DepthClipEnable = TRUE;
    246     rasterDesc.MultisampleEnable = FALSE;
    247     rasterDesc.AntialiasedLineEnable = FALSE;
    248 
    249     rasterDesc.ScissorEnable = TRUE;
    250     result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState);
    251     ASSERT(SUCCEEDED(result));
    252     d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state");
    253 
    254     rasterDesc.ScissorEnable = FALSE;
    255     result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState);
    256     ASSERT(SUCCEEDED(result));
    257     d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state");
    258 
    259     D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
    260     depthStencilDesc.DepthEnable = true;
    261     depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    262     depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
    263     depthStencilDesc.StencilEnable = FALSE;
    264     depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
    265     depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
    266     depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    267     depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
    268     depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    269     depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
    270     depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
    271     depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
    272     depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
    273     depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
    274 
    275     result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState);
    276     ASSERT(SUCCEEDED(result));
    277     d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state");
    278 
    279     D3D11_INPUT_ELEMENT_DESC quad2DLayout[] =
    280     {
    281         { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    282         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    283     };
    284 
    285     result = device->CreateInputLayout(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), &mQuad2DIL);
    286     ASSERT(SUCCEEDED(result));
    287     d3d11::SetDebugName(mQuad2DIL, "Blit11 2D input layout");
    288 
    289     result = device->CreateVertexShader(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), NULL, &mQuad2DVS);
    290     ASSERT(SUCCEEDED(result));
    291     d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader");
    292 
    293     result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS);
    294     ASSERT(SUCCEEDED(result));
    295     d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader");
    296 
    297     D3D11_INPUT_ELEMENT_DESC quad3DLayout[] =
    298     {
    299         { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT,    0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    300         { "LAYER",    0, DXGI_FORMAT_R32_UINT,        0,  8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    301         { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    302     };
    303 
    304     result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL);
    305     ASSERT(SUCCEEDED(result));
    306     d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout");
    307 
    308     result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS);
    309     ASSERT(SUCCEEDED(result));
    310     d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader");
    311 
    312     result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS);
    313     ASSERT(SUCCEEDED(result));
    314     d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader");
    315 
    316     buildShaderMap();
    317 
    318     D3D11_BUFFER_DESC swizzleBufferDesc;
    319     swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4;
    320     swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
    321     swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    322     swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    323     swizzleBufferDesc.MiscFlags = 0;
    324     swizzleBufferDesc.StructureByteStride = 0;
    325 
    326     result = device->CreateBuffer(&swizzleBufferDesc, NULL, &mSwizzleCB);
    327     ASSERT(SUCCEEDED(result));
    328     d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer");
    329 }
    330 
    331 Blit11::~Blit11()
    332 {
    333     SafeRelease(mVertexBuffer);
    334     SafeRelease(mPointSampler);
    335     SafeRelease(mLinearSampler);
    336     SafeRelease(mScissorEnabledRasterizerState);
    337     SafeRelease(mScissorDisabledRasterizerState);
    338     SafeRelease(mDepthStencilState);
    339 
    340     SafeRelease(mQuad2DIL);
    341     SafeRelease(mQuad2DVS);
    342     SafeRelease(mDepthPS);
    343 
    344     SafeRelease(mQuad3DIL);
    345     SafeRelease(mQuad3DVS);
    346     SafeRelease(mQuad3DGS);
    347 
    348     SafeRelease(mSwizzleCB);
    349 
    350     clearShaderMap();
    351 }
    352 
    353 static inline unsigned int GetSwizzleIndex(GLenum swizzle)
    354 {
    355     unsigned int colorIndex = 0;
    356 
    357     switch (swizzle)
    358     {
    359       case GL_RED:   colorIndex = 0; break;
    360       case GL_GREEN: colorIndex = 1; break;
    361       case GL_BLUE:  colorIndex = 2; break;
    362       case GL_ALPHA: colorIndex = 3; break;
    363       case GL_ZERO:  colorIndex = 4; break;
    364       case GL_ONE:   colorIndex = 5; break;
    365       default:       UNREACHABLE();  break;
    366     }
    367 
    368     return colorIndex;
    369 }
    370 
    371 bool Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size,
    372                             GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
    373 {
    374     HRESULT result;
    375     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    376 
    377     D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
    378     source->GetDesc(&sourceSRVDesc);
    379 
    380     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format);
    381     const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat);
    382 
    383     GLenum shaderType = GL_NONE;
    384     switch (sourceFormatInfo.componentType)
    385     {
    386       case GL_UNSIGNED_NORMALIZED:
    387       case GL_SIGNED_NORMALIZED:
    388       case GL_FLOAT:
    389         shaderType = GL_FLOAT;
    390         break;
    391       case GL_INT:
    392         shaderType = GL_INT;
    393         break;
    394       case GL_UNSIGNED_INT:
    395         shaderType = GL_UNSIGNED_INT;
    396         break;
    397       default:
    398         UNREACHABLE();
    399         break;
    400     }
    401 
    402     SwizzleParameters parameters = { 0 };
    403     parameters.mDestinationType = shaderType;
    404     parameters.mViewDimension = sourceSRVDesc.ViewDimension;
    405 
    406     SwizzleShaderMap::const_iterator i = mSwizzleShaderMap.find(parameters);
    407     if (i == mSwizzleShaderMap.end())
    408     {
    409         UNREACHABLE();
    410         return false;
    411     }
    412 
    413     const Shader &shader = i->second;
    414 
    415     // Set vertices
    416     D3D11_MAPPED_SUBRESOURCE mappedResource;
    417     result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    418     if (FAILED(result))
    419     {
    420         ERR("Failed to map vertex buffer for texture swizzle, HRESULT: 0x%X.", result);
    421         return false;
    422     }
    423 
    424     UINT stride = 0;
    425     UINT startIdx = 0;
    426     UINT drawCount = 0;
    427     D3D11_PRIMITIVE_TOPOLOGY topology;
    428 
    429     gl::Box area(0, 0, 0, size.width, size.height, size.depth);
    430     shader.mVertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, &topology);
    431 
    432     deviceContext->Unmap(mVertexBuffer, 0);
    433 
    434     // Set constant buffer
    435     result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    436     if (FAILED(result))
    437     {
    438         ERR("Failed to map constant buffer for texture swizzle, HRESULT: 0x%X.", result);
    439         return false;
    440     }
    441 
    442     unsigned int *swizzleIndices = reinterpret_cast<unsigned int*>(mappedResource.pData);
    443     swizzleIndices[0] = GetSwizzleIndex(swizzleRed);
    444     swizzleIndices[1] = GetSwizzleIndex(swizzleGreen);
    445     swizzleIndices[2] = GetSwizzleIndex(swizzleBlue);
    446     swizzleIndices[3] = GetSwizzleIndex(swizzleAlpha);
    447 
    448     deviceContext->Unmap(mSwizzleCB, 0);
    449 
    450     // Apply vertex buffer
    451     deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
    452 
    453     // Apply constant buffer
    454     deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB);
    455 
    456     // Apply state
    457     deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
    458     deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
    459     deviceContext->RSSetState(mScissorDisabledRasterizerState);
    460 
    461     // Apply shaders
    462     deviceContext->IASetInputLayout(shader.mInputLayout);
    463     deviceContext->IASetPrimitiveTopology(topology);
    464     deviceContext->VSSetShader(shader.mVertexShader, NULL, 0);
    465 
    466     deviceContext->PSSetShader(shader.mPixelShader, NULL, 0);
    467     deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0);
    468 
    469     // Unset the currently bound shader resource to avoid conflicts
    470     ID3D11ShaderResourceView *const nullSRV = NULL;
    471     deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    472 
    473     // Apply render target
    474     mRenderer->setOneTimeRenderTarget(dest);
    475 
    476     // Set the viewport
    477     D3D11_VIEWPORT viewport;
    478     viewport.TopLeftX = 0;
    479     viewport.TopLeftY = 0;
    480     viewport.Width = size.width;
    481     viewport.Height = size.height;
    482     viewport.MinDepth = 0.0f;
    483     viewport.MaxDepth = 1.0f;
    484     deviceContext->RSSetViewports(1, &viewport);
    485 
    486     // Apply textures
    487     deviceContext->PSSetShaderResources(0, 1, &source);
    488 
    489     // Apply samplers
    490     deviceContext->PSSetSamplers(0, 1, &mPointSampler);
    491 
    492     // Draw the quad
    493     deviceContext->Draw(drawCount, 0);
    494 
    495     // Unbind textures and render targets and vertex buffer
    496     deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    497 
    498     mRenderer->unapplyRenderTargets();
    499 
    500     UINT zero = 0;
    501     ID3D11Buffer *const nullBuffer = NULL;
    502     deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
    503 
    504     mRenderer->markAllStateDirty();
    505 
    506     return true;
    507 }
    508 
    509 bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
    510                          ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize,
    511                          const gl::Rectangle *scissor, GLenum destFormat, GLenum filter)
    512 {
    513     HRESULT result;
    514     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    515 
    516     // Determine if the source format is a signed integer format, the destFormat will already
    517     // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned.
    518     D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
    519     source->GetDesc(&sourceSRVDesc);
    520 
    521     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format);
    522     const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat);
    523 
    524     BlitParameters parameters = { 0 };
    525     parameters.mDestinationFormat = destFormat;
    526     parameters.mSignedInteger = (internalFormatInfo.componentType == GL_INT);
    527     parameters.m3DBlit = sourceArea.depth > 1;
    528 
    529     BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters);
    530     if (i == mBlitShaderMap.end())
    531     {
    532         UNREACHABLE();
    533         return false;
    534     }
    535 
    536     const Shader& shader = i->second;
    537 
    538     // Set vertices
    539     D3D11_MAPPED_SUBRESOURCE mappedResource;
    540     result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    541     if (FAILED(result))
    542     {
    543         ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
    544         return false;
    545     }
    546 
    547     UINT stride = 0;
    548     UINT startIdx = 0;
    549     UINT drawCount = 0;
    550     D3D11_PRIMITIVE_TOPOLOGY topology;
    551 
    552     shader.mVertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
    553                                 &stride, &drawCount, &topology);
    554 
    555     deviceContext->Unmap(mVertexBuffer, 0);
    556 
    557     // Apply vertex buffer
    558     deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
    559 
    560     // Apply state
    561     deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
    562     deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
    563 
    564     if (scissor)
    565     {
    566         D3D11_RECT scissorRect;
    567         scissorRect.left = scissor->x;
    568         scissorRect.right = scissor->x + scissor->width;
    569         scissorRect.top = scissor->y;
    570         scissorRect.bottom = scissor->y + scissor->height;
    571 
    572         deviceContext->RSSetScissorRects(1, &scissorRect);
    573         deviceContext->RSSetState(mScissorEnabledRasterizerState);
    574     }
    575     else
    576     {
    577         deviceContext->RSSetState(mScissorDisabledRasterizerState);
    578     }
    579 
    580     // Apply shaders
    581     deviceContext->IASetInputLayout(shader.mInputLayout);
    582     deviceContext->IASetPrimitiveTopology(topology);
    583     deviceContext->VSSetShader(shader.mVertexShader, NULL, 0);
    584 
    585     deviceContext->PSSetShader(shader.mPixelShader, NULL, 0);
    586     deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0);
    587 
    588     // Unset the currently bound shader resource to avoid conflicts
    589     ID3D11ShaderResourceView *const nullSRV = NULL;
    590     deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    591 
    592     // Apply render target
    593     mRenderer->setOneTimeRenderTarget(dest);
    594 
    595     // Set the viewport
    596     D3D11_VIEWPORT viewport;
    597     viewport.TopLeftX = 0;
    598     viewport.TopLeftY = 0;
    599     viewport.Width = destSize.width;
    600     viewport.Height = destSize.height;
    601     viewport.MinDepth = 0.0f;
    602     viewport.MaxDepth = 1.0f;
    603     deviceContext->RSSetViewports(1, &viewport);
    604 
    605     // Apply textures
    606     deviceContext->PSSetShaderResources(0, 1, &source);
    607 
    608     // Apply samplers
    609     ID3D11SamplerState *sampler = NULL;
    610     switch (filter)
    611     {
    612       case GL_NEAREST: sampler = mPointSampler;  break;
    613       case GL_LINEAR:  sampler = mLinearSampler; break;
    614       default:         UNREACHABLE(); return false;
    615     }
    616     deviceContext->PSSetSamplers(0, 1, &sampler);
    617 
    618     // Draw the quad
    619     deviceContext->Draw(drawCount, 0);
    620 
    621     // Unbind textures and render targets and vertex buffer
    622     deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    623 
    624     mRenderer->unapplyRenderTargets();
    625 
    626     UINT zero = 0;
    627     ID3D11Buffer *const nullBuffer = NULL;
    628     deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
    629 
    630     mRenderer->markAllStateDirty();
    631 
    632     return true;
    633 }
    634 
    635 bool Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
    636                          ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
    637                          const gl::Rectangle *scissor)
    638 {
    639     return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
    640                             dest, destSubresource, destArea, destSize,
    641                             scissor, true);
    642 }
    643 
    644 bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize,
    645                        ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize,
    646                        const gl::Rectangle *scissor)
    647 {
    648     HRESULT result;
    649     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    650 
    651     // Set vertices
    652     D3D11_MAPPED_SUBRESOURCE mappedResource;
    653     result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    654     if (FAILED(result))
    655     {
    656         ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
    657         return false;
    658     }
    659 
    660     UINT stride = 0;
    661     UINT startIdx = 0;
    662     UINT drawCount = 0;
    663     D3D11_PRIMITIVE_TOPOLOGY topology;
    664 
    665     Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
    666                     &stride, &drawCount, &topology);
    667 
    668     deviceContext->Unmap(mVertexBuffer, 0);
    669 
    670     // Apply vertex buffer
    671     deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
    672 
    673     // Apply state
    674     deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
    675     deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF);
    676 
    677     if (scissor)
    678     {
    679         D3D11_RECT scissorRect;
    680         scissorRect.left = scissor->x;
    681         scissorRect.right = scissor->x + scissor->width;
    682         scissorRect.top = scissor->y;
    683         scissorRect.bottom = scissor->y + scissor->height;
    684 
    685         deviceContext->RSSetScissorRects(1, &scissorRect);
    686         deviceContext->RSSetState(mScissorEnabledRasterizerState);
    687     }
    688     else
    689     {
    690         deviceContext->RSSetState(mScissorDisabledRasterizerState);
    691     }
    692 
    693     // Apply shaders
    694     deviceContext->IASetInputLayout(mQuad2DIL);
    695     deviceContext->IASetPrimitiveTopology(topology);
    696     deviceContext->VSSetShader(mQuad2DVS, NULL, 0);
    697 
    698     deviceContext->PSSetShader(mDepthPS, NULL, 0);
    699     deviceContext->GSSetShader(NULL, NULL, 0);
    700 
    701     // Unset the currently bound shader resource to avoid conflicts
    702     ID3D11ShaderResourceView *const nullSRV = NULL;
    703     deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    704 
    705     // Apply render target
    706     deviceContext->OMSetRenderTargets(0, NULL, dest);
    707 
    708     // Set the viewport
    709     D3D11_VIEWPORT viewport;
    710     viewport.TopLeftX = 0;
    711     viewport.TopLeftY = 0;
    712     viewport.Width = destSize.width;
    713     viewport.Height = destSize.height;
    714     viewport.MinDepth = 0.0f;
    715     viewport.MaxDepth = 1.0f;
    716     deviceContext->RSSetViewports(1, &viewport);
    717 
    718     // Apply textures
    719     deviceContext->PSSetShaderResources(0, 1, &source);
    720 
    721     // Apply samplers
    722     deviceContext->PSSetSamplers(0, 1, &mPointSampler);
    723 
    724     // Draw the quad
    725     deviceContext->Draw(drawCount, 0);
    726 
    727     // Unbind textures and render targets and vertex buffer
    728     deviceContext->PSSetShaderResources(0, 1, &nullSRV);
    729 
    730     mRenderer->unapplyRenderTargets();
    731 
    732     UINT zero = 0;
    733     ID3D11Buffer *const nullBuffer = NULL;
    734     deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
    735 
    736     mRenderer->markAllStateDirty();
    737 
    738     return true;
    739 }
    740 
    741 bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
    742                               ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
    743                               const gl::Rectangle *scissor)
    744 {
    745     return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize,
    746                             dest, destSubresource, destArea, destSize,
    747                             scissor, false);
    748 }
    749 
    750 bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize,
    751                               ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize,
    752                               const gl::Rectangle *scissor, bool stencilOnly)
    753 {
    754     ID3D11Device *device = mRenderer->getDevice();
    755     ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
    756 
    757     ID3D11Resource *sourceStaging = CreateStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ);
    758     // HACK: Create the destination staging buffer as a read/write texture so ID3D11DevicContext::UpdateSubresource can be called
    759     //       using it's mapped data as a source
    760     ID3D11Resource *destStaging = CreateStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE);
    761 
    762     if (!sourceStaging || !destStaging)
    763     {
    764         SafeRelease(sourceStaging);
    765         SafeRelease(destStaging);
    766         return false;
    767     }
    768 
    769     DXGI_FORMAT format = GetTextureFormat(source);
    770     ASSERT(format == GetTextureFormat(dest));
    771 
    772     const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format);
    773     unsigned int pixelSize = dxgiFormatInfo.pixelBytes;
    774     unsigned int copyOffset = 0;
    775     unsigned int copySize = pixelSize;
    776     if (stencilOnly)
    777     {
    778         copyOffset = dxgiFormatInfo.depthBits / 8;
    779         copySize = dxgiFormatInfo.stencilBits / 8;
    780 
    781         // It would be expensive to have non-byte sized stencil sizes since it would
    782         // require reading from the destination, currently there aren't any though.
    783         ASSERT(dxgiFormatInfo.stencilBits % 8 == 0 &&
    784                dxgiFormatInfo.depthBits   % 8 == 0);
    785     }
    786 
    787     D3D11_MAPPED_SUBRESOURCE sourceMapping, destMapping;
    788     deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping);
    789     deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping);
    790 
    791     if (!sourceMapping.pData || !destMapping.pData)
    792     {
    793         if (!sourceMapping.pData)
    794         {
    795             deviceContext->Unmap(sourceStaging, 0);
    796         }
    797         if (!destMapping.pData)
    798         {
    799             deviceContext->Unmap(destStaging, 0);
    800         }
    801         SafeRelease(sourceStaging);
    802         SafeRelease(destStaging);
    803         return false;
    804     }
    805 
    806     gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
    807 
    808     // Clip dest area to the destination size
    809     gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea);
    810 
    811     // Clip dest area to the scissor
    812     if (scissor)
    813     {
    814         gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea);
    815     }
    816 
    817     // Determine if entire rows can be copied at once instead of each individual pixel, requires that there is
    818     // no out of bounds lookups required, the entire pixel is copied and no stretching
    819     bool wholeRowCopy = sourceArea.width == clippedDestArea.width &&
    820                         sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width &&
    821                         copySize == pixelSize;
    822 
    823     for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
    824     {
    825         float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1);
    826 
    827         // Interpolate using the original source rectangle to determine which row to sample from while clamping to the edges
    828         unsigned int readRow = gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1);
    829         unsigned int writeRow = y;
    830 
    831         if (wholeRowCopy)
    832         {
    833             void *sourceRow = reinterpret_cast<char*>(sourceMapping.pData) +
    834                               readRow * sourceMapping.RowPitch +
    835                               sourceArea.x * pixelSize;
    836 
    837             void *destRow = reinterpret_cast<char*>(destMapping.pData) +
    838                             writeRow * destMapping.RowPitch +
    839                             destArea.x * pixelSize;
    840 
    841             memcpy(destRow, sourceRow, pixelSize * destArea.width);
    842         }
    843         else
    844         {
    845             for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++)
    846             {
    847                 float xPerc = static_cast<float>(x - destArea.x) / (destArea.width - 1);
    848 
    849                 // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges
    850                 unsigned int readColumn = gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1);
    851                 unsigned int writeColumn = x;
    852 
    853                 void *sourcePixel = reinterpret_cast<char*>(sourceMapping.pData) +
    854                                     readRow * sourceMapping.RowPitch +
    855                                     readColumn * pixelSize +
    856                                     copyOffset;
    857 
    858                 void *destPixel = reinterpret_cast<char*>(destMapping.pData) +
    859                                   writeRow * destMapping.RowPitch +
    860                                   writeColumn * pixelSize +
    861                                   copyOffset;
    862 
    863                 memcpy(destPixel, sourcePixel, copySize);
    864             }
    865         }
    866     }
    867 
    868     // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion
    869     //       according to MSDN.
    870     deviceContext->UpdateSubresource(dest, destSubresource, NULL, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch);
    871 
    872     deviceContext->Unmap(sourceStaging, 0);
    873     deviceContext->Unmap(destStaging, 0);
    874 
    875     // TODO: Determine why this call to ID3D11DevicContext::CopySubresourceRegion causes a TDR timeout on some
    876     //       systems when called repeatedly.
    877     // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, NULL);
    878 
    879     SafeRelease(sourceStaging);
    880     SafeRelease(destStaging);
    881 
    882     return true;
    883 }
    884 
    885 bool Blit11::compareBlitParameters(const Blit11::BlitParameters &a, const Blit11::BlitParameters &b)
    886 {
    887     return memcmp(&a, &b, sizeof(Blit11::BlitParameters)) < 0;
    888 }
    889 
    890 bool Blit11::compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b)
    891 {
    892     return memcmp(&a, &b, sizeof(Blit11::SwizzleParameters)) < 0;
    893 }
    894 
    895 void Blit11::add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps)
    896 {
    897     BlitParameters params = { 0 };
    898     params.mDestinationFormat = destFormat;
    899     params.mSignedInteger = signedInteger;
    900     params.m3DBlit = false;
    901 
    902     ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end());
    903     ASSERT(ps);
    904 
    905     Shader shader;
    906     shader.mVertexWriteFunction = Write2DVertices;
    907     shader.mInputLayout = mQuad2DIL;
    908     shader.mVertexShader = mQuad2DVS;
    909     shader.mGeometryShader = NULL;
    910     shader.mPixelShader = ps;
    911 
    912     mBlitShaderMap[params] = shader;
    913 }
    914 
    915 void Blit11::add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps)
    916 {
    917     BlitParameters params = { 0 };
    918     params.mDestinationFormat = destFormat;
    919     params.mSignedInteger = signedInteger;
    920     params.m3DBlit = true;
    921 
    922     ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end());
    923     ASSERT(ps);
    924 
    925     Shader shader;
    926     shader.mVertexWriteFunction = Write3DVertices;
    927     shader.mInputLayout = mQuad3DIL;
    928     shader.mVertexShader = mQuad3DVS;
    929     shader.mGeometryShader = mQuad3DGS;
    930     shader.mPixelShader = ps;
    931 
    932     mBlitShaderMap[params] = shader;
    933 }
    934 
    935 void Blit11::addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps)
    936 {
    937     SwizzleParameters params = { 0 };
    938     params.mDestinationType = destType;
    939     params.mViewDimension = viewDimension;
    940 
    941     ASSERT(mSwizzleShaderMap.find(params) == mSwizzleShaderMap.end());
    942     ASSERT(ps);
    943 
    944     Shader shader;
    945     switch (viewDimension)
    946     {
    947       case D3D_SRV_DIMENSION_TEXTURE2D:
    948         shader.mVertexWriteFunction = Write2DVertices;
    949         shader.mInputLayout = mQuad2DIL;
    950         shader.mVertexShader = mQuad2DVS;
    951         shader.mGeometryShader = NULL;
    952         break;
    953 
    954       case D3D_SRV_DIMENSION_TEXTURE3D:
    955       case D3D_SRV_DIMENSION_TEXTURE2DARRAY:
    956       case D3D_SRV_DIMENSION_TEXTURECUBE:
    957         shader.mVertexWriteFunction = Write3DVertices;
    958         shader.mInputLayout = mQuad3DIL;
    959         shader.mVertexShader = mQuad3DVS;
    960         shader.mGeometryShader = mQuad3DGS;
    961         break;
    962 
    963       default:
    964         UNREACHABLE();
    965         break;
    966     }
    967     shader.mPixelShader = ps;
    968 
    969     mSwizzleShaderMap[params] = shader;
    970 }
    971 
    972 void Blit11::buildShaderMap()
    973 {
    974     ID3D11Device *device = mRenderer->getDevice();
    975 
    976     add2DBlitShaderToMap(GL_RGBA,            false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D,     "Blit11 2D RGBA pixel shader"           ));
    977     add2DBlitShaderToMap(GL_RGBA_INTEGER,    false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI,   "Blit11 2D RGBA UI pixel shader"        ));
    978     add2DBlitShaderToMap(GL_RGBA_INTEGER,    true,  d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI,    "Blit11 2D RGBA I pixel shader"         ));
    979     add2DBlitShaderToMap(GL_BGRA_EXT,        false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D,     "Blit11 2D BGRA pixel shader"           ));
    980     add2DBlitShaderToMap(GL_RGB,             false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D,      "Blit11 2D RGB pixel shader"            ));
    981     add2DBlitShaderToMap(GL_RGB_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI,    "Blit11 2D RGB UI pixel shader"         ));
    982     add2DBlitShaderToMap(GL_RGB_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughRGB2DI,     "Blit11 2D RGB I pixel shader"          ));
    983     add2DBlitShaderToMap(GL_RG,              false, d3d11::CompilePS(device, g_PS_PassthroughRG2D,       "Blit11 2D RG pixel shader"             ));
    984     add2DBlitShaderToMap(GL_RG_INTEGER,      false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI,     "Blit11 2D RG UI pixel shader"          ));
    985     add2DBlitShaderToMap(GL_RG_INTEGER,      true,  d3d11::CompilePS(device, g_PS_PassthroughRG2DI,      "Blit11 2D RG I pixel shader"           ));
    986     add2DBlitShaderToMap(GL_RED,             false, d3d11::CompilePS(device, g_PS_PassthroughR2D,        "Blit11 2D R pixel shader"              ));
    987     add2DBlitShaderToMap(GL_RED_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI,      "Blit11 2D R UI pixel shader"           ));
    988     add2DBlitShaderToMap(GL_RED_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughR2DI,       "Blit11 2D R I pixel shader"            ));
    989     add2DBlitShaderToMap(GL_ALPHA,           false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D,     "Blit11 2D alpha pixel shader"          ));
    990     add2DBlitShaderToMap(GL_LUMINANCE,       false, d3d11::CompilePS(device, g_PS_PassthroughLum2D,      "Blit11 2D lum pixel shader"            ));
    991     add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader"));
    992 
    993     add3DBlitShaderToMap(GL_RGBA,            false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D RGBA pixel shader"           ));
    994     add3DBlitShaderToMap(GL_RGBA_INTEGER,    false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI,   "Blit11 3D UI RGBA pixel shader"        ));
    995     add3DBlitShaderToMap(GL_RGBA_INTEGER,    true,  d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI,    "Blit11 3D I RGBA pixel shader"         ));
    996     add3DBlitShaderToMap(GL_BGRA_EXT,        false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D BGRA pixel shader"           ));
    997     add3DBlitShaderToMap(GL_RGB,             false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D,      "Blit11 3D RGB pixel shader"            ));
    998     add3DBlitShaderToMap(GL_RGB_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI,    "Blit11 3D RGB UI pixel shader"         ));
    999     add3DBlitShaderToMap(GL_RGB_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughRGB3DI,     "Blit11 3D RGB I pixel shader"          ));
   1000     add3DBlitShaderToMap(GL_RG,              false, d3d11::CompilePS(device, g_PS_PassthroughRG3D,       "Blit11 3D RG pixel shader"             ));
   1001     add3DBlitShaderToMap(GL_RG_INTEGER,      false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI,     "Blit11 3D RG UI pixel shader"          ));
   1002     add3DBlitShaderToMap(GL_RG_INTEGER,      true,  d3d11::CompilePS(device, g_PS_PassthroughRG3DI,      "Blit11 3D RG I pixel shader"           ));
   1003     add3DBlitShaderToMap(GL_RED,             false, d3d11::CompilePS(device, g_PS_PassthroughR3D,        "Blit11 3D R pixel shader"              ));
   1004     add3DBlitShaderToMap(GL_RED_INTEGER,     false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI,      "Blit11 3D R UI pixel shader"           ));
   1005     add3DBlitShaderToMap(GL_RED_INTEGER,     true,  d3d11::CompilePS(device, g_PS_PassthroughR3DI,       "Blit11 3D R I pixel shader"            ));
   1006     add3DBlitShaderToMap(GL_ALPHA,           false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D,     "Blit11 3D alpha pixel shader"          ));
   1007     add3DBlitShaderToMap(GL_LUMINANCE,       false, d3d11::CompilePS(device, g_PS_PassthroughLum3D,      "Blit11 3D luminance pixel shader"      ));
   1008     add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader"));
   1009 
   1010     addSwizzleShaderToMap(GL_FLOAT,        D3D_SRV_DIMENSION_TEXTURE2D,      d3d11::CompilePS(device, g_PS_SwizzleF2D,       "Blit11 2D F swizzle pixel shader" ));
   1011     addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D,      d3d11::CompilePS(device, g_PS_SwizzleUI2D,      "Blit11 2D UI swizzle pixel shader"));
   1012     addSwizzleShaderToMap(GL_INT,          D3D_SRV_DIMENSION_TEXTURE2D,      d3d11::CompilePS(device, g_PS_SwizzleI2D,       "Blit11 2D I swizzle pixel shader" ));
   1013 
   1014     addSwizzleShaderToMap(GL_FLOAT,        D3D_SRV_DIMENSION_TEXTURECUBE,    d3d11::CompilePS(device, g_PS_SwizzleF2DArray,  "Blit11 2D Cube F swizzle pixel shader" ));
   1015     addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE,    d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader"));
   1016     addSwizzleShaderToMap(GL_INT,          D3D_SRV_DIMENSION_TEXTURECUBE,    d3d11::CompilePS(device, g_PS_SwizzleI2DArray,  "Blit11 2D Cube I swizzle pixel shader" ));
   1017 
   1018     addSwizzleShaderToMap(GL_FLOAT,        D3D_SRV_DIMENSION_TEXTURE3D,      d3d11::CompilePS(device, g_PS_SwizzleF3D,       "Blit11 3D F swizzle pixel shader" ));
   1019     addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D,      d3d11::CompilePS(device, g_PS_SwizzleUI3D,      "Blit11 3D UI swizzle pixel shader"));
   1020     addSwizzleShaderToMap(GL_INT,          D3D_SRV_DIMENSION_TEXTURE3D,      d3d11::CompilePS(device, g_PS_SwizzleI3D,       "Blit11 3D I swizzle pixel shader" ));
   1021 
   1022     addSwizzleShaderToMap(GL_FLOAT,        D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray,  "Blit11 2D Array F swizzle pixel shader" ));
   1023     addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader"));
   1024     addSwizzleShaderToMap(GL_INT,          D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray,  "Blit11 2D Array I swizzle pixel shader" ));
   1025 }
   1026 
   1027 void Blit11::clearShaderMap()
   1028 {
   1029     for (BlitShaderMap::iterator i = mBlitShaderMap.begin(); i != mBlitShaderMap.end(); ++i)
   1030     {
   1031         Shader &shader = i->second;
   1032         SafeRelease(shader.mPixelShader);
   1033     }
   1034     mBlitShaderMap.clear();
   1035 
   1036     for (SwizzleShaderMap::iterator i = mSwizzleShaderMap.begin(); i != mSwizzleShaderMap.end(); ++i)
   1037     {
   1038         Shader &shader = i->second;
   1039         SafeRelease(shader.mPixelShader);
   1040     }
   1041     mSwizzleShaderMap.clear();
   1042 }
   1043 
   1044 }
   1045