Home | History | Annotate | Download | only in renderer
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
      9 // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
     10 
     11 #include "libGLESv2/renderer/TextureStorage11.h"
     12 
     13 #include "libGLESv2/renderer/Renderer11.h"
     14 #include "libGLESv2/renderer/RenderTarget11.h"
     15 #include "libGLESv2/renderer/SwapChain11.h"
     16 #include "libGLESv2/renderer/renderer11_utils.h"
     17 
     18 #include "libGLESv2/utilities.h"
     19 #include "libGLESv2/main.h"
     20 
     21 namespace rx
     22 {
     23 
     24 TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
     25     : mBindFlags(bindFlags),
     26       mLodOffset(0),
     27       mMipLevels(0),
     28       mTexture(NULL),
     29       mTextureFormat(DXGI_FORMAT_UNKNOWN),
     30       mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
     31       mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
     32       mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
     33       mSRV(NULL),
     34       mTextureWidth(0),
     35       mTextureHeight(0)
     36 {
     37     mRenderer = Renderer11::makeRenderer11(renderer);
     38 }
     39 
     40 TextureStorage11::~TextureStorage11()
     41 {
     42 }
     43 
     44 TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
     45 {
     46     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
     47     return static_cast<TextureStorage11*>(storage);
     48 }
     49 
     50 DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
     51 {
     52     UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
     53 
     54     if (d3d11::IsDepthStencilFormat(format))
     55     {
     56         bindFlags |= D3D11_BIND_DEPTH_STENCIL;
     57     }
     58     else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
     59     {
     60         bindFlags |= D3D11_BIND_RENDER_TARGET;
     61     }
     62     return bindFlags;
     63 }
     64 
     65 bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
     66 {
     67     switch(format)
     68     {
     69       case DXGI_FORMAT_R8G8B8A8_UNORM:
     70       case DXGI_FORMAT_A8_UNORM:
     71       case DXGI_FORMAT_R32G32B32A32_FLOAT:
     72       case DXGI_FORMAT_R16G16B16A16_FLOAT:
     73       case DXGI_FORMAT_B8G8R8A8_UNORM:
     74       case DXGI_FORMAT_R8_UNORM:
     75       case DXGI_FORMAT_R8G8_UNORM:
     76       case DXGI_FORMAT_R16_FLOAT:
     77       case DXGI_FORMAT_R16G16_FLOAT:
     78         return true;
     79       case DXGI_FORMAT_BC1_UNORM:
     80       case DXGI_FORMAT_BC2_UNORM:
     81       case DXGI_FORMAT_BC3_UNORM:
     82       case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices
     83         return false;
     84       default:
     85         UNREACHABLE();
     86         return false;
     87     }
     88 }
     89 
     90 UINT TextureStorage11::getBindFlags() const
     91 {
     92     return mBindFlags;
     93 }
     94 
     95 ID3D11Texture2D *TextureStorage11::getBaseTexture() const
     96 {
     97     return mTexture;
     98 }
     99 
    100 int TextureStorage11::getLodOffset() const
    101 {
    102     return mLodOffset;
    103 }
    104 
    105 bool TextureStorage11::isRenderTarget() const
    106 {
    107     return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
    108 }
    109 
    110 bool TextureStorage11::isManaged() const
    111 {
    112     return false;
    113 }
    114 
    115 int TextureStorage11::levelCount()
    116 {
    117     int levels = 0;
    118     if (getBaseTexture())
    119     {
    120         levels = mMipLevels - getLodOffset();
    121     }
    122     return levels;
    123 }
    124 
    125 UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex)
    126 {
    127     UINT index = 0;
    128     if (getBaseTexture())
    129     {
    130         index = D3D11CalcSubresource(level, faceIndex, mMipLevels);
    131     }
    132     return index;
    133 }
    134 
    135 bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource,
    136                                               int level, int face, GLint xoffset, GLint yoffset,
    137                                               GLsizei width, GLsizei height)
    138 {
    139     if (srcTexture)
    140     {
    141         // Round up the width and height to the nearest multiple of dimension alignment
    142         unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat);
    143         width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment;
    144         height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment;
    145 
    146         D3D11_BOX srcBox;
    147         srcBox.left = xoffset;
    148         srcBox.top = yoffset;
    149         srcBox.right = xoffset + width;
    150         srcBox.bottom = yoffset + height;
    151         srcBox.front = 0;
    152         srcBox.back = 1;
    153 
    154         ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    155 
    156         ASSERT(getBaseTexture());
    157         context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face),
    158                                        xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox);
    159         return true;
    160     }
    161 
    162     return false;
    163 }
    164 
    165 void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
    166 {
    167     if (source && dest)
    168     {
    169         ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
    170         ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
    171 
    172         if (sourceSRV && destRTV)
    173         {
    174             gl::Rectangle sourceArea;
    175             sourceArea.x = 0;
    176             sourceArea.y = 0;
    177             sourceArea.width = source->getWidth();
    178             sourceArea.height = source->getHeight();
    179 
    180             gl::Rectangle destArea;
    181             destArea.x = 0;
    182             destArea.y = 0;
    183             destArea.width = dest->getWidth();
    184             destArea.height = dest->getHeight();
    185 
    186             mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(),
    187                                    destRTV, destArea, dest->getWidth(), dest->getHeight(),
    188                                    GL_RGBA);
    189         }
    190     }
    191 }
    192 
    193 TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
    194     : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
    195 {
    196     mTexture = swapchain->getOffscreenTexture();
    197     mSRV = swapchain->getRenderTargetShaderResource();
    198 
    199     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    200     {
    201         mRenderTarget[i] = NULL;
    202     }
    203 
    204     D3D11_TEXTURE2D_DESC texDesc;
    205     mTexture->GetDesc(&texDesc);
    206     mMipLevels = texDesc.MipLevels;
    207     mTextureFormat = texDesc.Format;
    208     mTextureWidth = texDesc.Width;
    209     mTextureHeight = texDesc.Height;
    210 
    211     D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    212     mSRV->GetDesc(&srvDesc);
    213     mShaderResourceFormat = srvDesc.Format;
    214 
    215     ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
    216     D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
    217     offscreenRTV->GetDesc(&rtvDesc);
    218     mRenderTargetFormat = rtvDesc.Format;
    219     offscreenRTV->Release();
    220 
    221     mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
    222 }
    223 
    224 TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
    225     : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
    226 {
    227     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    228     {
    229         mRenderTarget[i] = NULL;
    230     }
    231 
    232     DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
    233     if (d3d11::IsDepthStencilFormat(convertedFormat))
    234     {
    235         mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
    236         mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
    237         mDepthStencilFormat = convertedFormat;
    238         mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
    239     }
    240     else
    241     {
    242         mTextureFormat = convertedFormat;
    243         mShaderResourceFormat = convertedFormat;
    244         mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
    245         mRenderTargetFormat = convertedFormat;
    246     }
    247 
    248     // if the width or height is not positive this should be treated as an incomplete texture
    249     // we handle that here by skipping the d3d texture creation
    250     if (width > 0 && height > 0)
    251     {
    252         // adjust size if needed for compressed textures
    253         gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
    254 
    255         ID3D11Device *device = mRenderer->getDevice();
    256 
    257         D3D11_TEXTURE2D_DESC desc;
    258         desc.Width = width;      // Compressed texture size constraints?
    259         desc.Height = height;
    260         desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
    261         desc.ArraySize = 1;
    262         desc.Format = mTextureFormat;
    263         desc.SampleDesc.Count = 1;
    264         desc.SampleDesc.Quality = 0;
    265         desc.Usage = D3D11_USAGE_DEFAULT;
    266         desc.BindFlags = getBindFlags();
    267         desc.CPUAccessFlags = 0;
    268         desc.MiscFlags = 0;
    269 
    270         HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
    271 
    272         // this can happen from windows TDR
    273         if (d3d11::isDeviceLostError(result))
    274         {
    275             mRenderer->notifyDeviceLost();
    276             gl::error(GL_OUT_OF_MEMORY);
    277         }
    278         else if (FAILED(result))
    279         {
    280             ASSERT(result == E_OUTOFMEMORY);
    281             ERR("Creating image failed.");
    282             gl::error(GL_OUT_OF_MEMORY);
    283         }
    284         else
    285         {
    286             mTexture->GetDesc(&desc);
    287             mMipLevels = desc.MipLevels;
    288             mTextureWidth = desc.Width;
    289             mTextureHeight = desc.Height;
    290         }
    291     }
    292 }
    293 
    294 TextureStorage11_2D::~TextureStorage11_2D()
    295 {
    296     if (mTexture)
    297     {
    298         mTexture->Release();
    299         mTexture = NULL;
    300     }
    301 
    302     if (mSRV)
    303     {
    304         mSRV->Release();
    305         mSRV = NULL;
    306     }
    307 
    308     for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
    309     {
    310         delete mRenderTarget[i];
    311         mRenderTarget[i] = NULL;
    312     }
    313 }
    314 
    315 TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
    316 {
    317     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
    318     return static_cast<TextureStorage11_2D*>(storage);
    319 }
    320 
    321 RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
    322 {
    323     if (level >= 0 && level < static_cast<int>(mMipLevels))
    324     {
    325         if (!mRenderTarget[level])
    326         {
    327             ID3D11Device *device = mRenderer->getDevice();
    328             HRESULT result;
    329 
    330             D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    331             srvDesc.Format = mShaderResourceFormat;
    332             srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    333             srvDesc.Texture2D.MostDetailedMip = level;
    334             srvDesc.Texture2D.MipLevels = 1;
    335 
    336             ID3D11ShaderResourceView *srv;
    337             result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
    338 
    339             if (result == E_OUTOFMEMORY)
    340             {
    341                 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
    342             }
    343             ASSERT(SUCCEEDED(result));
    344 
    345             if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
    346             {
    347                 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
    348                 rtvDesc.Format = mRenderTargetFormat;
    349                 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
    350                 rtvDesc.Texture2D.MipSlice = level;
    351 
    352                 ID3D11RenderTargetView *rtv;
    353                 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
    354 
    355                 if (result == E_OUTOFMEMORY)
    356                 {
    357                     srv->Release();
    358                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
    359                 }
    360                 ASSERT(SUCCEEDED(result));
    361 
    362                 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
    363                 // also needs to keep a reference to the texture.
    364                 mTexture->AddRef();
    365 
    366                 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
    367                                                           std::max(mTextureWidth >> level, 1U),
    368                                                           std::max(mTextureHeight >> level, 1U));
    369             }
    370             else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
    371             {
    372                 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
    373                 dsvDesc.Format = mDepthStencilFormat;
    374                 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
    375                 dsvDesc.Texture2D.MipSlice = level;
    376                 dsvDesc.Flags = 0;
    377 
    378                 ID3D11DepthStencilView *dsv;
    379                 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
    380 
    381                 if (result == E_OUTOFMEMORY)
    382                 {
    383                     srv->Release();
    384                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
    385                 }
    386                 ASSERT(SUCCEEDED(result));
    387 
    388                 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
    389                 // also needs to keep a reference to the texture.
    390                 mTexture->AddRef();
    391 
    392                 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
    393                                                           std::max(mTextureWidth >> level, 1U),
    394                                                           std::max(mTextureHeight >> level, 1U));
    395             }
    396             else
    397             {
    398                 UNREACHABLE();
    399             }
    400         }
    401 
    402         return mRenderTarget[level];
    403     }
    404     else
    405     {
    406         return NULL;
    407     }
    408 }
    409 
    410 ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
    411 {
    412     if (!mSRV)
    413     {
    414         ID3D11Device *device = mRenderer->getDevice();
    415 
    416         D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    417         srvDesc.Format = mShaderResourceFormat;
    418         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    419         srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
    420         srvDesc.Texture2D.MostDetailedMip = 0;
    421 
    422         HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
    423 
    424         if (result == E_OUTOFMEMORY)
    425         {
    426             return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
    427         }
    428         ASSERT(SUCCEEDED(result));
    429     }
    430 
    431     return mSRV;
    432 }
    433 
    434 void TextureStorage11_2D::generateMipmap(int level)
    435 {
    436     RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
    437     RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
    438 
    439     generateMipmapLayer(source, dest);
    440 }
    441 
    442 TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
    443     : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
    444 {
    445     for (unsigned int i = 0; i < 6; i++)
    446     {
    447         for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
    448         {
    449             mRenderTarget[i][j] = NULL;
    450         }
    451     }
    452 
    453     DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
    454     if (d3d11::IsDepthStencilFormat(convertedFormat))
    455     {
    456         mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
    457         mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
    458         mDepthStencilFormat = convertedFormat;
    459         mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
    460     }
    461     else
    462     {
    463         mTextureFormat = convertedFormat;
    464         mShaderResourceFormat = convertedFormat;
    465         mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
    466         mRenderTargetFormat = convertedFormat;
    467     }
    468 
    469     // if the size is not positive this should be treated as an incomplete texture
    470     // we handle that here by skipping the d3d texture creation
    471     if (size > 0)
    472     {
    473         // adjust size if needed for compressed textures
    474         int height = size;
    475         gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
    476 
    477         ID3D11Device *device = mRenderer->getDevice();
    478 
    479         D3D11_TEXTURE2D_DESC desc;
    480         desc.Width = size;
    481         desc.Height = size;
    482         desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
    483         desc.ArraySize = 6;
    484         desc.Format = mTextureFormat;
    485         desc.SampleDesc.Count = 1;
    486         desc.SampleDesc.Quality = 0;
    487         desc.Usage = D3D11_USAGE_DEFAULT;
    488         desc.BindFlags = getBindFlags();
    489         desc.CPUAccessFlags = 0;
    490         desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
    491 
    492         HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
    493 
    494         if (FAILED(result))
    495         {
    496             ASSERT(result == E_OUTOFMEMORY);
    497             ERR("Creating image failed.");
    498             gl::error(GL_OUT_OF_MEMORY);
    499         }
    500         else
    501         {
    502             mTexture->GetDesc(&desc);
    503             mMipLevels = desc.MipLevels;
    504             mTextureWidth = desc.Width;
    505             mTextureHeight = desc.Height;
    506         }
    507     }
    508 }
    509 
    510 TextureStorage11_Cube::~TextureStorage11_Cube()
    511 {
    512     if (mTexture)
    513     {
    514         mTexture->Release();
    515         mTexture = NULL;
    516     }
    517 
    518     if (mSRV)
    519     {
    520         mSRV->Release();
    521         mSRV = NULL;
    522     }
    523 
    524     for (unsigned int i = 0; i < 6; i++)
    525     {
    526         for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
    527         {
    528             delete mRenderTarget[i][j];
    529             mRenderTarget[i][j] = NULL;
    530         }
    531     }
    532 }
    533 
    534 TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
    535 {
    536     ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
    537     return static_cast<TextureStorage11_Cube*>(storage);
    538 }
    539 
    540 RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
    541 {
    542     unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
    543     if (level >= 0 && level < static_cast<int>(mMipLevels))
    544     {
    545         if (!mRenderTarget[faceIdx][level])
    546         {
    547             ID3D11Device *device = mRenderer->getDevice();
    548             HRESULT result;
    549 
    550             D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    551             srvDesc.Format = mShaderResourceFormat;
    552             srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
    553             srvDesc.Texture2DArray.MostDetailedMip = level;
    554             srvDesc.Texture2DArray.MipLevels = 1;
    555             srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
    556             srvDesc.Texture2DArray.ArraySize = 1;
    557 
    558             ID3D11ShaderResourceView *srv;
    559             result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
    560 
    561             if (result == E_OUTOFMEMORY)
    562             {
    563                 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
    564             }
    565             ASSERT(SUCCEEDED(result));
    566 
    567             if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
    568             {
    569                 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
    570                 rtvDesc.Format = mRenderTargetFormat;
    571                 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
    572                 rtvDesc.Texture2DArray.MipSlice = level;
    573                 rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
    574                 rtvDesc.Texture2DArray.ArraySize = 1;
    575 
    576                 ID3D11RenderTargetView *rtv;
    577                 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
    578 
    579                 if (result == E_OUTOFMEMORY)
    580                 {
    581                     srv->Release();
    582                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
    583                 }
    584                 ASSERT(SUCCEEDED(result));
    585 
    586                 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
    587                 // also needs to keep a reference to the texture.
    588                 mTexture->AddRef();
    589 
    590                 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
    591                                                                    std::max(mTextureWidth >> level, 1U),
    592                                                                    std::max(mTextureHeight >> level, 1U));
    593             }
    594             else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
    595             {
    596                 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
    597                 dsvDesc.Format = mRenderTargetFormat;
    598                 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
    599                 dsvDesc.Texture2DArray.MipSlice = level;
    600                 dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
    601                 dsvDesc.Texture2DArray.ArraySize = 1;
    602 
    603                 ID3D11DepthStencilView *dsv;
    604                 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
    605 
    606                 if (result == E_OUTOFMEMORY)
    607                 {
    608                     srv->Release();
    609                     return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
    610                 }
    611                 ASSERT(SUCCEEDED(result));
    612 
    613                 // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
    614                 // also needs to keep a reference to the texture.
    615                 mTexture->AddRef();
    616 
    617                 mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
    618                                                                    std::max(mTextureWidth >> level, 1U),
    619                                                                    std::max(mTextureHeight >> level, 1U));
    620             }
    621             else
    622             {
    623                 UNREACHABLE();
    624             }
    625         }
    626 
    627         return mRenderTarget[faceIdx][level];
    628     }
    629     else
    630     {
    631         return NULL;
    632     }
    633 }
    634 
    635 ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
    636 {
    637     if (!mSRV)
    638     {
    639         ID3D11Device *device = mRenderer->getDevice();
    640 
    641         D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
    642         srvDesc.Format = mShaderResourceFormat;
    643         srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
    644         srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
    645         srvDesc.TextureCube.MostDetailedMip = 0;
    646 
    647         HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
    648 
    649         if (result == E_OUTOFMEMORY)
    650         {
    651             return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
    652         }
    653         ASSERT(SUCCEEDED(result));
    654     }
    655 
    656     return mSRV;
    657 }
    658 
    659 void TextureStorage11_Cube::generateMipmap(int face, int level)
    660 {
    661     RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
    662     RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
    663 
    664     generateMipmapLayer(source, dest);
    665 }
    666 
    667 }
    668