michael@0: #include "precompiled.h" michael@0: // michael@0: // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: michael@0: // TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived michael@0: // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. michael@0: michael@0: #include "libGLESv2/renderer/TextureStorage11.h" michael@0: michael@0: #include "libGLESv2/renderer/Renderer11.h" michael@0: #include "libGLESv2/renderer/RenderTarget11.h" michael@0: #include "libGLESv2/renderer/SwapChain11.h" michael@0: #include "libGLESv2/renderer/renderer11_utils.h" michael@0: michael@0: #include "libGLESv2/utilities.h" michael@0: #include "libGLESv2/main.h" michael@0: michael@0: namespace rx michael@0: { michael@0: michael@0: TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) michael@0: : mBindFlags(bindFlags), michael@0: mLodOffset(0), michael@0: mMipLevels(0), michael@0: mTexture(NULL), michael@0: mTextureFormat(DXGI_FORMAT_UNKNOWN), michael@0: mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), michael@0: mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), michael@0: mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), michael@0: mSRV(NULL), michael@0: mTextureWidth(0), michael@0: mTextureHeight(0) michael@0: { michael@0: mRenderer = Renderer11::makeRenderer11(renderer); michael@0: } michael@0: michael@0: TextureStorage11::~TextureStorage11() michael@0: { michael@0: } michael@0: michael@0: TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) michael@0: { michael@0: ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); michael@0: return static_cast(storage); michael@0: } michael@0: michael@0: DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable) michael@0: { michael@0: UINT bindFlags = D3D11_BIND_SHADER_RESOURCE; michael@0: michael@0: if (d3d11::IsDepthStencilFormat(format)) michael@0: { michael@0: bindFlags |= D3D11_BIND_DEPTH_STENCIL; michael@0: } michael@0: else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) michael@0: { michael@0: bindFlags |= D3D11_BIND_RENDER_TARGET; michael@0: } michael@0: return bindFlags; michael@0: } michael@0: michael@0: bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format) michael@0: { michael@0: switch(format) michael@0: { michael@0: case DXGI_FORMAT_R8G8B8A8_UNORM: michael@0: case DXGI_FORMAT_A8_UNORM: michael@0: case DXGI_FORMAT_R32G32B32A32_FLOAT: michael@0: case DXGI_FORMAT_R16G16B16A16_FLOAT: michael@0: case DXGI_FORMAT_B8G8R8A8_UNORM: michael@0: case DXGI_FORMAT_R8_UNORM: michael@0: case DXGI_FORMAT_R8G8_UNORM: michael@0: case DXGI_FORMAT_R16_FLOAT: michael@0: case DXGI_FORMAT_R16G16_FLOAT: michael@0: return true; michael@0: case DXGI_FORMAT_BC1_UNORM: michael@0: case DXGI_FORMAT_BC2_UNORM: michael@0: case DXGI_FORMAT_BC3_UNORM: michael@0: case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices michael@0: return false; michael@0: default: michael@0: UNREACHABLE(); michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: UINT TextureStorage11::getBindFlags() const michael@0: { michael@0: return mBindFlags; michael@0: } michael@0: michael@0: ID3D11Texture2D *TextureStorage11::getBaseTexture() const michael@0: { michael@0: return mTexture; michael@0: } michael@0: michael@0: int TextureStorage11::getLodOffset() const michael@0: { michael@0: return mLodOffset; michael@0: } michael@0: michael@0: bool TextureStorage11::isRenderTarget() const michael@0: { michael@0: return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; michael@0: } michael@0: michael@0: bool TextureStorage11::isManaged() const michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: int TextureStorage11::levelCount() michael@0: { michael@0: int levels = 0; michael@0: if (getBaseTexture()) michael@0: { michael@0: levels = mMipLevels - getLodOffset(); michael@0: } michael@0: return levels; michael@0: } michael@0: michael@0: UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex) michael@0: { michael@0: UINT index = 0; michael@0: if (getBaseTexture()) michael@0: { michael@0: index = D3D11CalcSubresource(level, faceIndex, mMipLevels); michael@0: } michael@0: return index; michael@0: } michael@0: michael@0: bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource, michael@0: int level, int face, GLint xoffset, GLint yoffset, michael@0: GLsizei width, GLsizei height) michael@0: { michael@0: if (srcTexture) michael@0: { michael@0: // Round up the width and height to the nearest multiple of dimension alignment michael@0: unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat); michael@0: width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment; michael@0: height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment; michael@0: michael@0: D3D11_BOX srcBox; michael@0: srcBox.left = xoffset; michael@0: srcBox.top = yoffset; michael@0: srcBox.right = xoffset + width; michael@0: srcBox.bottom = yoffset + height; michael@0: srcBox.front = 0; michael@0: srcBox.back = 1; michael@0: michael@0: ID3D11DeviceContext *context = mRenderer->getDeviceContext(); michael@0: michael@0: ASSERT(getBaseTexture()); michael@0: context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face), michael@0: xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox); michael@0: return true; michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) michael@0: { michael@0: if (source && dest) michael@0: { michael@0: ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); michael@0: ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); michael@0: michael@0: if (sourceSRV && destRTV) michael@0: { michael@0: gl::Rectangle sourceArea; michael@0: sourceArea.x = 0; michael@0: sourceArea.y = 0; michael@0: sourceArea.width = source->getWidth(); michael@0: sourceArea.height = source->getHeight(); michael@0: michael@0: gl::Rectangle destArea; michael@0: destArea.x = 0; michael@0: destArea.y = 0; michael@0: destArea.width = dest->getWidth(); michael@0: destArea.height = dest->getHeight(); michael@0: michael@0: mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(), michael@0: destRTV, destArea, dest->getWidth(), dest->getHeight(), michael@0: GL_RGBA); michael@0: } michael@0: } michael@0: } michael@0: michael@0: TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) michael@0: : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) michael@0: { michael@0: mTexture = swapchain->getOffscreenTexture(); michael@0: mSRV = swapchain->getRenderTargetShaderResource(); michael@0: michael@0: for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) michael@0: { michael@0: mRenderTarget[i] = NULL; michael@0: } michael@0: michael@0: D3D11_TEXTURE2D_DESC texDesc; michael@0: mTexture->GetDesc(&texDesc); michael@0: mMipLevels = texDesc.MipLevels; michael@0: mTextureFormat = texDesc.Format; michael@0: mTextureWidth = texDesc.Width; michael@0: mTextureHeight = texDesc.Height; michael@0: michael@0: D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; michael@0: mSRV->GetDesc(&srvDesc); michael@0: mShaderResourceFormat = srvDesc.Format; michael@0: michael@0: ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); michael@0: D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; michael@0: offscreenRTV->GetDesc(&rtvDesc); michael@0: mRenderTargetFormat = rtvDesc.Format; michael@0: offscreenRTV->Release(); michael@0: michael@0: mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; michael@0: } michael@0: michael@0: TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) michael@0: : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable)) michael@0: { michael@0: for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) michael@0: { michael@0: mRenderTarget[i] = NULL; michael@0: } michael@0: michael@0: DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); michael@0: if (d3d11::IsDepthStencilFormat(convertedFormat)) michael@0: { michael@0: mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); michael@0: mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); michael@0: mDepthStencilFormat = convertedFormat; michael@0: mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; michael@0: } michael@0: else michael@0: { michael@0: mTextureFormat = convertedFormat; michael@0: mShaderResourceFormat = convertedFormat; michael@0: mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; michael@0: mRenderTargetFormat = convertedFormat; michael@0: } michael@0: michael@0: // if the width or height is not positive this should be treated as an incomplete texture michael@0: // we handle that here by skipping the d3d texture creation michael@0: if (width > 0 && height > 0) michael@0: { michael@0: // adjust size if needed for compressed textures michael@0: gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); michael@0: michael@0: ID3D11Device *device = mRenderer->getDevice(); michael@0: michael@0: D3D11_TEXTURE2D_DESC desc; michael@0: desc.Width = width; // Compressed texture size constraints? michael@0: desc.Height = height; michael@0: desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; michael@0: desc.ArraySize = 1; michael@0: desc.Format = mTextureFormat; michael@0: desc.SampleDesc.Count = 1; michael@0: desc.SampleDesc.Quality = 0; michael@0: desc.Usage = D3D11_USAGE_DEFAULT; michael@0: desc.BindFlags = getBindFlags(); michael@0: desc.CPUAccessFlags = 0; michael@0: desc.MiscFlags = 0; michael@0: michael@0: HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); michael@0: michael@0: // this can happen from windows TDR michael@0: if (d3d11::isDeviceLostError(result)) michael@0: { michael@0: mRenderer->notifyDeviceLost(); michael@0: gl::error(GL_OUT_OF_MEMORY); michael@0: } michael@0: else if (FAILED(result)) michael@0: { michael@0: ASSERT(result == E_OUTOFMEMORY); michael@0: ERR("Creating image failed."); michael@0: gl::error(GL_OUT_OF_MEMORY); michael@0: } michael@0: else michael@0: { michael@0: mTexture->GetDesc(&desc); michael@0: mMipLevels = desc.MipLevels; michael@0: mTextureWidth = desc.Width; michael@0: mTextureHeight = desc.Height; michael@0: } michael@0: } michael@0: } michael@0: michael@0: TextureStorage11_2D::~TextureStorage11_2D() michael@0: { michael@0: if (mTexture) michael@0: { michael@0: mTexture->Release(); michael@0: mTexture = NULL; michael@0: } michael@0: michael@0: if (mSRV) michael@0: { michael@0: mSRV->Release(); michael@0: mSRV = NULL; michael@0: } michael@0: michael@0: for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) michael@0: { michael@0: delete mRenderTarget[i]; michael@0: mRenderTarget[i] = NULL; michael@0: } michael@0: } michael@0: michael@0: TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) michael@0: { michael@0: ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); michael@0: return static_cast(storage); michael@0: } michael@0: michael@0: RenderTarget *TextureStorage11_2D::getRenderTarget(int level) michael@0: { michael@0: if (level >= 0 && level < static_cast(mMipLevels)) michael@0: { michael@0: if (!mRenderTarget[level]) michael@0: { michael@0: ID3D11Device *device = mRenderer->getDevice(); michael@0: HRESULT result; michael@0: michael@0: D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; michael@0: srvDesc.Format = mShaderResourceFormat; michael@0: srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; michael@0: srvDesc.Texture2D.MostDetailedMip = level; michael@0: srvDesc.Texture2D.MipLevels = 1; michael@0: michael@0: ID3D11ShaderResourceView *srv; michael@0: result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: michael@0: if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) michael@0: { michael@0: D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; michael@0: rtvDesc.Format = mRenderTargetFormat; michael@0: rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; michael@0: rtvDesc.Texture2D.MipSlice = level; michael@0: michael@0: ID3D11RenderTargetView *rtv; michael@0: result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: srv->Release(); michael@0: return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: michael@0: // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 michael@0: // also needs to keep a reference to the texture. michael@0: mTexture->AddRef(); michael@0: michael@0: mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, michael@0: std::max(mTextureWidth >> level, 1U), michael@0: std::max(mTextureHeight >> level, 1U)); michael@0: } michael@0: else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) michael@0: { michael@0: D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; michael@0: dsvDesc.Format = mDepthStencilFormat; michael@0: dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; michael@0: dsvDesc.Texture2D.MipSlice = level; michael@0: dsvDesc.Flags = 0; michael@0: michael@0: ID3D11DepthStencilView *dsv; michael@0: result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: srv->Release(); michael@0: return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: michael@0: // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 michael@0: // also needs to keep a reference to the texture. michael@0: mTexture->AddRef(); michael@0: michael@0: mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, michael@0: std::max(mTextureWidth >> level, 1U), michael@0: std::max(mTextureHeight >> level, 1U)); michael@0: } michael@0: else michael@0: { michael@0: UNREACHABLE(); michael@0: } michael@0: } michael@0: michael@0: return mRenderTarget[level]; michael@0: } michael@0: else michael@0: { michael@0: return NULL; michael@0: } michael@0: } michael@0: michael@0: ID3D11ShaderResourceView *TextureStorage11_2D::getSRV() michael@0: { michael@0: if (!mSRV) michael@0: { michael@0: ID3D11Device *device = mRenderer->getDevice(); michael@0: michael@0: D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; michael@0: srvDesc.Format = mShaderResourceFormat; michael@0: srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; michael@0: srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); michael@0: srvDesc.Texture2D.MostDetailedMip = 0; michael@0: michael@0: HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: } michael@0: michael@0: return mSRV; michael@0: } michael@0: michael@0: void TextureStorage11_2D::generateMipmap(int level) michael@0: { michael@0: RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); michael@0: RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); michael@0: michael@0: generateMipmapLayer(source, dest); michael@0: } michael@0: michael@0: TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) michael@0: : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable)) michael@0: { michael@0: for (unsigned int i = 0; i < 6; i++) michael@0: { michael@0: for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) michael@0: { michael@0: mRenderTarget[i][j] = NULL; michael@0: } michael@0: } michael@0: michael@0: DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat); michael@0: if (d3d11::IsDepthStencilFormat(convertedFormat)) michael@0: { michael@0: mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); michael@0: mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); michael@0: mDepthStencilFormat = convertedFormat; michael@0: mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; michael@0: } michael@0: else michael@0: { michael@0: mTextureFormat = convertedFormat; michael@0: mShaderResourceFormat = convertedFormat; michael@0: mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; michael@0: mRenderTargetFormat = convertedFormat; michael@0: } michael@0: michael@0: // if the size is not positive this should be treated as an incomplete texture michael@0: // we handle that here by skipping the d3d texture creation michael@0: if (size > 0) michael@0: { michael@0: // adjust size if needed for compressed textures michael@0: int height = size; michael@0: gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); michael@0: michael@0: ID3D11Device *device = mRenderer->getDevice(); michael@0: michael@0: D3D11_TEXTURE2D_DESC desc; michael@0: desc.Width = size; michael@0: desc.Height = size; michael@0: desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; michael@0: desc.ArraySize = 6; michael@0: desc.Format = mTextureFormat; michael@0: desc.SampleDesc.Count = 1; michael@0: desc.SampleDesc.Quality = 0; michael@0: desc.Usage = D3D11_USAGE_DEFAULT; michael@0: desc.BindFlags = getBindFlags(); michael@0: desc.CPUAccessFlags = 0; michael@0: desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; michael@0: michael@0: HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); michael@0: michael@0: if (FAILED(result)) michael@0: { michael@0: ASSERT(result == E_OUTOFMEMORY); michael@0: ERR("Creating image failed."); michael@0: gl::error(GL_OUT_OF_MEMORY); michael@0: } michael@0: else michael@0: { michael@0: mTexture->GetDesc(&desc); michael@0: mMipLevels = desc.MipLevels; michael@0: mTextureWidth = desc.Width; michael@0: mTextureHeight = desc.Height; michael@0: } michael@0: } michael@0: } michael@0: michael@0: TextureStorage11_Cube::~TextureStorage11_Cube() michael@0: { michael@0: if (mTexture) michael@0: { michael@0: mTexture->Release(); michael@0: mTexture = NULL; michael@0: } michael@0: michael@0: if (mSRV) michael@0: { michael@0: mSRV->Release(); michael@0: mSRV = NULL; michael@0: } michael@0: michael@0: for (unsigned int i = 0; i < 6; i++) michael@0: { michael@0: for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) michael@0: { michael@0: delete mRenderTarget[i][j]; michael@0: mRenderTarget[i][j] = NULL; michael@0: } michael@0: } michael@0: } michael@0: michael@0: TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) michael@0: { michael@0: ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); michael@0: return static_cast(storage); michael@0: } michael@0: michael@0: RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level) michael@0: { michael@0: unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget); michael@0: if (level >= 0 && level < static_cast(mMipLevels)) michael@0: { michael@0: if (!mRenderTarget[faceIdx][level]) michael@0: { michael@0: ID3D11Device *device = mRenderer->getDevice(); michael@0: HRESULT result; michael@0: michael@0: D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; michael@0: srvDesc.Format = mShaderResourceFormat; michael@0: srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; michael@0: srvDesc.Texture2DArray.MostDetailedMip = level; michael@0: srvDesc.Texture2DArray.MipLevels = 1; michael@0: srvDesc.Texture2DArray.FirstArraySlice = faceIdx; michael@0: srvDesc.Texture2DArray.ArraySize = 1; michael@0: michael@0: ID3D11ShaderResourceView *srv; michael@0: result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: michael@0: if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) michael@0: { michael@0: D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; michael@0: rtvDesc.Format = mRenderTargetFormat; michael@0: rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; michael@0: rtvDesc.Texture2DArray.MipSlice = level; michael@0: rtvDesc.Texture2DArray.FirstArraySlice = faceIdx; michael@0: rtvDesc.Texture2DArray.ArraySize = 1; michael@0: michael@0: ID3D11RenderTargetView *rtv; michael@0: result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: srv->Release(); michael@0: return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: michael@0: // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 michael@0: // also needs to keep a reference to the texture. michael@0: mTexture->AddRef(); michael@0: michael@0: mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, michael@0: std::max(mTextureWidth >> level, 1U), michael@0: std::max(mTextureHeight >> level, 1U)); michael@0: } michael@0: else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) michael@0: { michael@0: D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; michael@0: dsvDesc.Format = mRenderTargetFormat; michael@0: dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; michael@0: dsvDesc.Texture2DArray.MipSlice = level; michael@0: dsvDesc.Texture2DArray.FirstArraySlice = faceIdx; michael@0: dsvDesc.Texture2DArray.ArraySize = 1; michael@0: michael@0: ID3D11DepthStencilView *dsv; michael@0: result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: srv->Release(); michael@0: return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: michael@0: // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 michael@0: // also needs to keep a reference to the texture. michael@0: mTexture->AddRef(); michael@0: michael@0: mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, michael@0: std::max(mTextureWidth >> level, 1U), michael@0: std::max(mTextureHeight >> level, 1U)); michael@0: } michael@0: else michael@0: { michael@0: UNREACHABLE(); michael@0: } michael@0: } michael@0: michael@0: return mRenderTarget[faceIdx][level]; michael@0: } michael@0: else michael@0: { michael@0: return NULL; michael@0: } michael@0: } michael@0: michael@0: ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV() michael@0: { michael@0: if (!mSRV) michael@0: { michael@0: ID3D11Device *device = mRenderer->getDevice(); michael@0: michael@0: D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; michael@0: srvDesc.Format = mShaderResourceFormat; michael@0: srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; michael@0: srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); michael@0: srvDesc.TextureCube.MostDetailedMip = 0; michael@0: michael@0: HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); michael@0: michael@0: if (result == E_OUTOFMEMORY) michael@0: { michael@0: return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); michael@0: } michael@0: ASSERT(SUCCEEDED(result)); michael@0: } michael@0: michael@0: return mSRV; michael@0: } michael@0: michael@0: void TextureStorage11_Cube::generateMipmap(int face, int level) michael@0: { michael@0: RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1)); michael@0: RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level)); michael@0: michael@0: generateMipmapLayer(source, dest); michael@0: } michael@0: michael@0: }