1 #include "precompiled.h"
3 // Copyright (c) 2012-2014 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.
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.
11 #include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
13 #include "libGLESv2/renderer/d3d/TextureD3D.h"
14 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
15 #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
16 #include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
17 #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
18 #include "libGLESv2/renderer/d3d/d3d11/Blit11.h"
19 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
21 #include "common/utilities.h"
22 #include "libGLESv2/main.h"
27 TextureStorage11::SwizzleCacheValue::SwizzleCacheValue()
28 : swizzleRed(GL_NONE), swizzleGreen(GL_NONE), swizzleBlue(GL_NONE), swizzleAlpha(GL_NONE)
32 TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha)
33 : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha)
37 bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const
39 return swizzleRed == other.swizzleRed &&
40 swizzleGreen == other.swizzleGreen &&
41 swizzleBlue == other.swizzleBlue &&
42 swizzleAlpha == other.swizzleAlpha;
45 bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const
47 return !(*this == other);
50 TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle)
51 : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle)
55 bool TextureStorage11::SRVKey::operator==(const SRVKey &rhs) const
57 return baseLevel == rhs.baseLevel &&
58 mipLevels == rhs.mipLevels &&
59 swizzle == rhs.swizzle;
62 TextureStorage11::SRVCache::~SRVCache()
64 for (size_t i = 0; i < cache.size(); i++)
66 SafeRelease(cache[i].srv);
70 ID3D11ShaderResourceView *TextureStorage11::SRVCache::find(const SRVKey &key) const
72 for (size_t i = 0; i < cache.size(); i++)
74 if (cache[i].key == key)
83 ID3D11ShaderResourceView *TextureStorage11::SRVCache::add(const SRVKey &key, ID3D11ShaderResourceView *srv)
85 SRVPair pair = {key, srv};
86 cache.push_back(pair);
91 TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
92 : mBindFlags(bindFlags),
95 mTextureFormat(DXGI_FORMAT_UNKNOWN),
96 mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
97 mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
98 mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
103 mRenderer = Renderer11::makeRenderer11(renderer);
105 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
107 mLevelSRVs[i] = NULL;
111 TextureStorage11::~TextureStorage11()
113 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
115 SafeRelease(mLevelSRVs[level]);
119 TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
121 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
122 return static_cast<TextureStorage11*>(storage);
125 DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTarget)
129 const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat);
130 if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
132 bindFlags |= D3D11_BIND_SHADER_RESOURCE;
134 if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
136 bindFlags |= D3D11_BIND_DEPTH_STENCIL;
138 if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget)
140 bindFlags |= D3D11_BIND_RENDER_TARGET;
146 UINT TextureStorage11::getBindFlags() const
151 int TextureStorage11::getTopLevel() const
156 bool TextureStorage11::isRenderTarget() const
158 return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
161 bool TextureStorage11::isManaged() const
166 int TextureStorage11::getLevelCount() const
168 return mMipLevels - mTopLevel;
171 int TextureStorage11::getLevelWidth(int mipLevel) const
173 return std::max(static_cast<int>(mTextureWidth) >> mipLevel, 1);
176 int TextureStorage11::getLevelHeight(int mipLevel) const
178 return std::max(static_cast<int>(mTextureHeight) >> mipLevel, 1);
181 int TextureStorage11::getLevelDepth(int mipLevel) const
183 return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1);
186 UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget) const
191 index = D3D11CalcSubresource(mipLevel, layerTarget, mMipLevels);
196 ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState)
198 bool swizzleRequired = samplerState.swizzleRequired();
199 bool mipmapping = IsMipmapFiltered(samplerState);
200 unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel) : 1;
202 // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0)
203 mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - samplerState.baseLevel);
207 verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha);
210 SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired);
211 ID3D11ShaderResourceView *srv = srvCache.find(key);
218 DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat);
219 ID3D11Resource *texture = swizzleRequired ? getSwizzleTexture() : getResource();
221 srv = createSRV(samplerState.baseLevel, mipLevels, format, texture);
223 return srvCache.add(key, srv);
226 ID3D11ShaderResourceView *TextureStorage11::getSRVLevel(int mipLevel)
228 if (mipLevel >= 0 && mipLevel < getLevelCount())
230 if (!mLevelSRVs[mipLevel])
232 mLevelSRVs[mipLevel] = createSRV(mipLevel, 1, mShaderResourceFormat, getResource());
235 return mLevelSRVs[mipLevel];
243 void TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
245 SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
246 for (int level = 0; level < getLevelCount(); level++)
248 // Check if the swizzle for this level is out of date
249 if (mSwizzleCache[level] != swizzleTarget)
251 // Need to re-render the swizzle for this level
252 ID3D11ShaderResourceView *sourceSRV = getSRVLevel(level);
253 ID3D11RenderTargetView *destRTV = getSwizzleRenderTarget(level);
255 gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
257 Blit11 *blitter = mRenderer->getBlitter();
259 if (blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha))
261 mSwizzleCache[level] = swizzleTarget;
265 ERR("Failed to swizzle texture.");
271 void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel)
273 if (mipLevel >= 0 && static_cast<unsigned int>(mipLevel) < ArraySize(mSwizzleCache))
275 // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a
276 // valid swizzle combination
277 mSwizzleCache[mipLevel] = SwizzleCacheValue();
281 void TextureStorage11::invalidateSwizzleCache()
283 for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++)
285 invalidateSwizzleCacheLevel(mipLevel);
289 bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource,
290 int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset,
291 GLsizei width, GLsizei height, GLsizei depth)
295 invalidateSwizzleCacheLevel(level);
297 gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
298 gl::Box copyArea(xoffset, yoffset, zoffset, width, height, depth);
300 bool fullCopy = copyArea.x == 0 &&
303 copyArea.width == texSize.width &&
304 copyArea.height == texSize.height &&
305 copyArea.depth == texSize.depth;
307 ID3D11Resource *dstTexture = getResource();
308 unsigned int dstSubresource = getSubresourceIndex(level + mTopLevel, layerTarget);
312 const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
313 if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0))
315 // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead
316 Blit11 *blitter = mRenderer->getBlitter();
318 return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize,
319 dstTexture, dstSubresource, copyArea, texSize,
324 const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
327 srcBox.left = copyArea.x;
328 srcBox.top = copyArea.y;
329 srcBox.right = copyArea.x + roundUp((unsigned int)width, dxgiFormatInfo.blockWidth);
330 srcBox.bottom = copyArea.y + roundUp((unsigned int)height, dxgiFormatInfo.blockHeight);
331 srcBox.front = copyArea.z;
332 srcBox.back = copyArea.z + copyArea.depth;
334 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
336 context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z,
337 srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox);
345 void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
349 ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
350 ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
352 if (sourceSRV && destRTV)
354 gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth());
355 gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth());
357 gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth());
358 gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
360 Blit11 *blitter = mRenderer->getBlitter();
362 blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL,
363 gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR);
368 void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
370 SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
371 for (unsigned int level = 0; level < mMipLevels; level++)
373 ASSERT(mSwizzleCache[level] == swizzleTarget);
377 TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
378 : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
380 mTexture = swapchain->getOffscreenTexture();
382 mSwizzleTexture = NULL;
384 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
386 mRenderTarget[i] = NULL;
387 mSwizzleRenderTargets[i] = NULL;
390 D3D11_TEXTURE2D_DESC texDesc;
391 mTexture->GetDesc(&texDesc);
392 mMipLevels = texDesc.MipLevels;
393 mTextureFormat = texDesc.Format;
394 mTextureWidth = texDesc.Width;
395 mTextureHeight = texDesc.Height;
398 ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource();
399 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
400 srv->GetDesc(&srvDesc);
401 mShaderResourceFormat = srvDesc.Format;
403 ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
404 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
405 offscreenRTV->GetDesc(&rtvDesc);
406 mRenderTargetFormat = rtvDesc.Format;
408 const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
409 const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat);
410 mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
411 mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
412 mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
414 mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
417 TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
418 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
421 mSwizzleTexture = NULL;
423 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
425 mRenderTarget[i] = NULL;
426 mSwizzleRenderTargets[i] = NULL;
429 const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
430 mTextureFormat = formatInfo.texFormat;
431 mShaderResourceFormat = formatInfo.srvFormat;
432 mDepthStencilFormat = formatInfo.dsvFormat;
433 mRenderTargetFormat = formatInfo.rtvFormat;
434 mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
435 mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
436 mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
438 // if the width or height is not positive this should be treated as an incomplete texture
439 // we handle that here by skipping the d3d texture creation
440 if (width > 0 && height > 0)
442 // adjust size if needed for compressed textures
443 d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
445 ID3D11Device *device = mRenderer->getDevice();
447 D3D11_TEXTURE2D_DESC desc;
448 desc.Width = width; // Compressed texture size constraints?
449 desc.Height = height;
450 desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
452 desc.Format = mTextureFormat;
453 desc.SampleDesc.Count = 1;
454 desc.SampleDesc.Quality = 0;
455 desc.Usage = D3D11_USAGE_DEFAULT;
456 desc.BindFlags = getBindFlags();
457 desc.CPUAccessFlags = 0;
460 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
462 // this can happen from windows TDR
463 if (d3d11::isDeviceLostError(result))
465 mRenderer->notifyDeviceLost();
466 gl::error(GL_OUT_OF_MEMORY);
468 else if (FAILED(result))
470 ASSERT(result == E_OUTOFMEMORY);
471 ERR("Creating image failed.");
472 gl::error(GL_OUT_OF_MEMORY);
476 mTexture->GetDesc(&desc);
477 mMipLevels = desc.MipLevels;
478 mTextureWidth = desc.Width;
479 mTextureHeight = desc.Height;
485 TextureStorage11_2D::~TextureStorage11_2D()
487 SafeRelease(mTexture);
488 SafeRelease(mSwizzleTexture);
490 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
492 SafeDelete(mRenderTarget[i]);
493 SafeRelease(mSwizzleRenderTargets[i]);
497 TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
499 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
500 return static_cast<TextureStorage11_2D*>(storage);
503 ID3D11Resource *TextureStorage11_2D::getResource() const
508 RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
510 if (level >= 0 && level < getLevelCount())
512 if (!mRenderTarget[level])
514 ID3D11ShaderResourceView *srv = getSRVLevel(level);
520 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
522 ID3D11Device *device = mRenderer->getDevice();
524 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
525 rtvDesc.Format = mRenderTargetFormat;
526 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
527 rtvDesc.Texture2D.MipSlice = mTopLevel + level;
529 ID3D11RenderTargetView *rtv;
530 HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
532 if (result == E_OUTOFMEMORY)
534 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
536 ASSERT(SUCCEEDED(result));
538 mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
540 // RenderTarget will take ownership of these resources
543 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
545 ID3D11Device *device = mRenderer->getDevice();
547 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
548 dsvDesc.Format = mDepthStencilFormat;
549 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
550 dsvDesc.Texture2D.MipSlice = mTopLevel + level;
553 ID3D11DepthStencilView *dsv;
554 HRESULT result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
556 if (result == E_OUTOFMEMORY)
559 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
561 ASSERT(SUCCEEDED(result));
563 mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
565 // RenderTarget will take ownership of these resources
574 return mRenderTarget[level];
582 ID3D11ShaderResourceView *TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
584 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
585 srvDesc.Format = format;
586 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
587 srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
588 srvDesc.Texture2D.MipLevels = mipLevels;
590 ID3D11ShaderResourceView *SRV = NULL;
592 ID3D11Device *device = mRenderer->getDevice();
593 HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
595 if (result == E_OUTOFMEMORY)
597 gl::error(GL_OUT_OF_MEMORY);
599 ASSERT(SUCCEEDED(result));
604 void TextureStorage11_2D::generateMipmap(int level)
606 invalidateSwizzleCacheLevel(level);
608 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
609 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
611 generateMipmapLayer(source, dest);
614 ID3D11Resource *TextureStorage11_2D::getSwizzleTexture()
616 if (!mSwizzleTexture)
618 ID3D11Device *device = mRenderer->getDevice();
620 D3D11_TEXTURE2D_DESC desc;
621 desc.Width = mTextureWidth;
622 desc.Height = mTextureHeight;
623 desc.MipLevels = mMipLevels;
625 desc.Format = mSwizzleTextureFormat;
626 desc.SampleDesc.Count = 1;
627 desc.SampleDesc.Quality = 0;
628 desc.Usage = D3D11_USAGE_DEFAULT;
629 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
630 desc.CPUAccessFlags = 0;
633 HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
635 if (result == E_OUTOFMEMORY)
637 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
639 ASSERT(SUCCEEDED(result));
642 return mSwizzleTexture;
645 ID3D11RenderTargetView *TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel)
647 if (mipLevel >= 0 && mipLevel < getLevelCount())
649 if (!mSwizzleRenderTargets[mipLevel])
651 ID3D11Resource *swizzleTexture = getSwizzleTexture();
657 ID3D11Device *device = mRenderer->getDevice();
659 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
660 rtvDesc.Format = mSwizzleRenderTargetFormat;
661 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
662 rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
664 HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
665 if (result == E_OUTOFMEMORY)
667 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
669 ASSERT(SUCCEEDED(result));
672 return mSwizzleRenderTargets[mipLevel];
680 unsigned int TextureStorage11_2D::getTextureLevelDepth(int mipLevel) const
685 TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
686 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
689 mSwizzleTexture = NULL;
691 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
693 mSwizzleRenderTargets[level] = NULL;
694 for (unsigned int face = 0; face < 6; face++)
696 mRenderTarget[face][level] = NULL;
700 const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
701 mTextureFormat = formatInfo.texFormat;
702 mShaderResourceFormat = formatInfo.srvFormat;
703 mDepthStencilFormat = formatInfo.dsvFormat;
704 mRenderTargetFormat = formatInfo.rtvFormat;
705 mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
706 mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
707 mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
709 // if the size is not positive this should be treated as an incomplete texture
710 // we handle that here by skipping the d3d texture creation
713 // adjust size if needed for compressed textures
715 d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel);
717 ID3D11Device *device = mRenderer->getDevice();
719 D3D11_TEXTURE2D_DESC desc;
722 desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
724 desc.Format = mTextureFormat;
725 desc.SampleDesc.Count = 1;
726 desc.SampleDesc.Quality = 0;
727 desc.Usage = D3D11_USAGE_DEFAULT;
728 desc.BindFlags = getBindFlags();
729 desc.CPUAccessFlags = 0;
730 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
732 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
736 ASSERT(result == E_OUTOFMEMORY);
737 ERR("Creating image failed.");
738 gl::error(GL_OUT_OF_MEMORY);
742 mTexture->GetDesc(&desc);
743 mMipLevels = desc.MipLevels;
744 mTextureWidth = desc.Width;
745 mTextureHeight = desc.Height;
751 TextureStorage11_Cube::~TextureStorage11_Cube()
753 SafeRelease(mTexture);
754 SafeRelease(mSwizzleTexture);
756 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
758 SafeRelease(mSwizzleRenderTargets[level]);
759 for (unsigned int face = 0; face < 6; face++)
761 SafeDelete(mRenderTarget[face][level]);
766 TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
768 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
769 return static_cast<TextureStorage11_Cube*>(storage);
772 ID3D11Resource *TextureStorage11_Cube::getResource() const
777 RenderTarget *TextureStorage11_Cube::getRenderTargetFace(GLenum faceTarget, int level)
779 if (level >= 0 && level < getLevelCount())
781 int faceIndex = gl::TextureCubeMap::targetToLayerIndex(faceTarget);
782 if (!mRenderTarget[faceIndex][level])
784 ID3D11Device *device = mRenderer->getDevice();
787 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
788 srvDesc.Format = mShaderResourceFormat;
789 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
790 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
791 srvDesc.Texture2DArray.MipLevels = 1;
792 srvDesc.Texture2DArray.FirstArraySlice = faceIndex;
793 srvDesc.Texture2DArray.ArraySize = 1;
795 ID3D11ShaderResourceView *srv;
796 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
798 if (result == E_OUTOFMEMORY)
800 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
802 ASSERT(SUCCEEDED(result));
804 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
806 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
807 rtvDesc.Format = mRenderTargetFormat;
808 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
809 rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
810 rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
811 rtvDesc.Texture2DArray.ArraySize = 1;
813 ID3D11RenderTargetView *rtv;
814 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
816 if (result == E_OUTOFMEMORY)
819 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
821 ASSERT(SUCCEEDED(result));
823 mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
825 // RenderTarget will take ownership of these resources
829 else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
831 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
832 dsvDesc.Format = mDepthStencilFormat;
833 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
835 dsvDesc.Texture2DArray.MipSlice = mTopLevel + level;
836 dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
837 dsvDesc.Texture2DArray.ArraySize = 1;
839 ID3D11DepthStencilView *dsv;
840 result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
842 if (result == E_OUTOFMEMORY)
845 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
847 ASSERT(SUCCEEDED(result));
849 mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1);
851 // RenderTarget will take ownership of these resources
861 return mRenderTarget[faceIndex][level];
869 ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
871 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
872 srvDesc.Format = format;
874 // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures
875 const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format);
876 if (dxgiFormatInfo.componentType == GL_INT || dxgiFormatInfo.componentType == GL_UNSIGNED_INT)
878 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
879 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
880 srvDesc.Texture2DArray.MipLevels = 1;
881 srvDesc.Texture2DArray.FirstArraySlice = 0;
882 srvDesc.Texture2DArray.ArraySize = 6;
886 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
887 srvDesc.TextureCube.MipLevels = mipLevels;
888 srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
891 ID3D11ShaderResourceView *SRV = NULL;
893 ID3D11Device *device = mRenderer->getDevice();
894 HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
896 if (result == E_OUTOFMEMORY)
898 gl::error(GL_OUT_OF_MEMORY);
900 ASSERT(SUCCEEDED(result));
905 void TextureStorage11_Cube::generateMipmap(int faceIndex, int level)
907 invalidateSwizzleCacheLevel(level);
909 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1));
910 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level));
912 generateMipmapLayer(source, dest);
915 ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture()
917 if (!mSwizzleTexture)
919 ID3D11Device *device = mRenderer->getDevice();
921 D3D11_TEXTURE2D_DESC desc;
922 desc.Width = mTextureWidth;
923 desc.Height = mTextureHeight;
924 desc.MipLevels = mMipLevels;
926 desc.Format = mSwizzleTextureFormat;
927 desc.SampleDesc.Count = 1;
928 desc.SampleDesc.Quality = 0;
929 desc.Usage = D3D11_USAGE_DEFAULT;
930 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
931 desc.CPUAccessFlags = 0;
932 desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
934 HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
936 if (result == E_OUTOFMEMORY)
938 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
940 ASSERT(SUCCEEDED(result));
943 return mSwizzleTexture;
946 ID3D11RenderTargetView *TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel)
948 if (mipLevel >= 0 && mipLevel < getLevelCount())
950 if (!mSwizzleRenderTargets[mipLevel])
952 ID3D11Resource *swizzleTexture = getSwizzleTexture();
958 ID3D11Device *device = mRenderer->getDevice();
960 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
961 rtvDesc.Format = mSwizzleRenderTargetFormat;
962 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
963 rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
964 rtvDesc.Texture2DArray.FirstArraySlice = 0;
965 rtvDesc.Texture2DArray.ArraySize = 6;
967 HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
969 if (result == E_OUTOFMEMORY)
971 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
973 ASSERT(SUCCEEDED(result));
976 return mSwizzleRenderTargets[mipLevel];
984 unsigned int TextureStorage11_Cube::getTextureLevelDepth(int mipLevel) const
989 TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget,
990 GLsizei width, GLsizei height, GLsizei depth, int levels)
991 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
994 mSwizzleTexture = NULL;
996 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
998 mLevelRenderTargets[i] = NULL;
999 mSwizzleRenderTargets[i] = NULL;
1002 const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
1003 mTextureFormat = formatInfo.texFormat;
1004 mShaderResourceFormat = formatInfo.srvFormat;
1005 mDepthStencilFormat = formatInfo.dsvFormat;
1006 mRenderTargetFormat = formatInfo.rtvFormat;
1007 mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
1008 mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
1009 mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
1011 // If the width, height or depth are not positive this should be treated as an incomplete texture
1012 // we handle that here by skipping the d3d texture creation
1013 if (width > 0 && height > 0 && depth > 0)
1015 // adjust size if needed for compressed textures
1016 d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
1018 ID3D11Device *device = mRenderer->getDevice();
1020 D3D11_TEXTURE3D_DESC desc;
1022 desc.Height = height;
1024 desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
1025 desc.Format = mTextureFormat;
1026 desc.Usage = D3D11_USAGE_DEFAULT;
1027 desc.BindFlags = getBindFlags();
1028 desc.CPUAccessFlags = 0;
1031 HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
1033 // this can happen from windows TDR
1034 if (d3d11::isDeviceLostError(result))
1036 mRenderer->notifyDeviceLost();
1037 gl::error(GL_OUT_OF_MEMORY);
1039 else if (FAILED(result))
1041 ASSERT(result == E_OUTOFMEMORY);
1042 ERR("Creating image failed.");
1043 gl::error(GL_OUT_OF_MEMORY);
1047 mTexture->GetDesc(&desc);
1048 mMipLevels = desc.MipLevels;
1049 mTextureWidth = desc.Width;
1050 mTextureHeight = desc.Height;
1051 mTextureDepth = desc.Depth;
1056 TextureStorage11_3D::~TextureStorage11_3D()
1058 SafeRelease(mTexture);
1059 SafeRelease(mSwizzleTexture);
1061 for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++)
1063 SafeDelete(i->second);
1065 mLevelLayerRenderTargets.clear();
1067 for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
1069 SafeDelete(mLevelRenderTargets[i]);
1070 SafeRelease(mSwizzleRenderTargets[i]);
1074 TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage)
1076 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage));
1077 return static_cast<TextureStorage11_3D*>(storage);
1080 ID3D11Resource *TextureStorage11_3D::getResource() const
1085 ID3D11ShaderResourceView *TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
1087 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1088 srvDesc.Format = format;
1089 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
1090 srvDesc.Texture3D.MostDetailedMip = baseLevel;
1091 srvDesc.Texture3D.MipLevels = mipLevels;
1093 ID3D11ShaderResourceView *SRV = NULL;
1095 ID3D11Device *device = mRenderer->getDevice();
1096 HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
1098 if (result == E_OUTOFMEMORY)
1100 gl::error(GL_OUT_OF_MEMORY);
1102 ASSERT(SUCCEEDED(result));
1107 RenderTarget *TextureStorage11_3D::getRenderTarget(int mipLevel)
1109 if (mipLevel >= 0 && mipLevel < getLevelCount())
1111 if (!mLevelRenderTargets[mipLevel])
1113 ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel);
1119 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
1121 ID3D11Device *device = mRenderer->getDevice();
1123 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1124 rtvDesc.Format = mRenderTargetFormat;
1125 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
1126 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
1127 rtvDesc.Texture3D.FirstWSlice = 0;
1128 rtvDesc.Texture3D.WSize = -1;
1130 ID3D11RenderTargetView *rtv;
1131 HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
1133 if (result == E_OUTOFMEMORY)
1136 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1138 ASSERT(SUCCEEDED(result));
1140 mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel));
1142 // RenderTarget will take ownership of these resources
1151 return mLevelRenderTargets[mipLevel];
1159 RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer)
1161 if (mipLevel >= 0 && mipLevel < getLevelCount())
1163 LevelLayerKey key(mipLevel, layer);
1164 if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
1166 ID3D11Device *device = mRenderer->getDevice();
1169 // TODO, what kind of SRV is expected here?
1170 ID3D11ShaderResourceView *srv = NULL;
1172 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
1174 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1175 rtvDesc.Format = mRenderTargetFormat;
1176 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
1177 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
1178 rtvDesc.Texture3D.FirstWSlice = layer;
1179 rtvDesc.Texture3D.WSize = 1;
1181 ID3D11RenderTargetView *rtv;
1182 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
1184 if (result == E_OUTOFMEMORY)
1187 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1189 ASSERT(SUCCEEDED(result));
1191 mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1);
1193 // RenderTarget will take ownership of these resources
1203 return mLevelLayerRenderTargets[key];
1211 void TextureStorage11_3D::generateMipmap(int level)
1213 invalidateSwizzleCacheLevel(level);
1215 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
1216 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
1218 generateMipmapLayer(source, dest);
1221 ID3D11Resource *TextureStorage11_3D::getSwizzleTexture()
1223 if (!mSwizzleTexture)
1225 ID3D11Device *device = mRenderer->getDevice();
1227 D3D11_TEXTURE3D_DESC desc;
1228 desc.Width = mTextureWidth;
1229 desc.Height = mTextureHeight;
1230 desc.Depth = mTextureDepth;
1231 desc.MipLevels = mMipLevels;
1232 desc.Format = mSwizzleTextureFormat;
1233 desc.Usage = D3D11_USAGE_DEFAULT;
1234 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
1235 desc.CPUAccessFlags = 0;
1238 HRESULT result = device->CreateTexture3D(&desc, NULL, &mSwizzleTexture);
1240 if (result == E_OUTOFMEMORY)
1242 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture3D*>(NULL));
1244 ASSERT(SUCCEEDED(result));
1247 return mSwizzleTexture;
1250 ID3D11RenderTargetView *TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel)
1252 if (mipLevel >= 0 && mipLevel < getLevelCount())
1254 if (!mSwizzleRenderTargets[mipLevel])
1256 ID3D11Resource *swizzleTexture = getSwizzleTexture();
1257 if (!swizzleTexture)
1262 ID3D11Device *device = mRenderer->getDevice();
1264 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1265 rtvDesc.Format = mSwizzleRenderTargetFormat;
1266 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
1267 rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
1268 rtvDesc.Texture3D.FirstWSlice = 0;
1269 rtvDesc.Texture3D.WSize = -1;
1271 HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
1273 if (result == E_OUTOFMEMORY)
1275 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
1277 ASSERT(SUCCEEDED(result));
1280 return mSwizzleRenderTargets[mipLevel];
1288 unsigned int TextureStorage11_3D::getTextureLevelDepth(int mipLevel) const
1290 return std::max(mTextureDepth >> mipLevel, 1U);
1294 TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget,
1295 GLsizei width, GLsizei height, GLsizei depth, int levels)
1296 : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
1299 mSwizzleTexture = NULL;
1301 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
1303 mSwizzleRenderTargets[level] = NULL;
1306 const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
1307 mTextureFormat = formatInfo.texFormat;
1308 mShaderResourceFormat = formatInfo.srvFormat;
1309 mDepthStencilFormat = formatInfo.dsvFormat;
1310 mRenderTargetFormat = formatInfo.rtvFormat;
1311 mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
1312 mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
1313 mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
1315 // if the width, height or depth is not positive this should be treated as an incomplete texture
1316 // we handle that here by skipping the d3d texture creation
1317 if (width > 0 && height > 0 && depth > 0)
1319 // adjust size if needed for compressed textures
1320 d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel);
1322 ID3D11Device *device = mRenderer->getDevice();
1324 D3D11_TEXTURE2D_DESC desc;
1326 desc.Height = height;
1327 desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0);
1328 desc.ArraySize = depth;
1329 desc.Format = mTextureFormat;
1330 desc.SampleDesc.Count = 1;
1331 desc.SampleDesc.Quality = 0;
1332 desc.Usage = D3D11_USAGE_DEFAULT;
1333 desc.BindFlags = getBindFlags();
1334 desc.CPUAccessFlags = 0;
1337 HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
1339 // this can happen from windows TDR
1340 if (d3d11::isDeviceLostError(result))
1342 mRenderer->notifyDeviceLost();
1343 gl::error(GL_OUT_OF_MEMORY);
1345 else if (FAILED(result))
1347 ASSERT(result == E_OUTOFMEMORY);
1348 ERR("Creating image failed.");
1349 gl::error(GL_OUT_OF_MEMORY);
1353 mTexture->GetDesc(&desc);
1354 mMipLevels = desc.MipLevels;
1355 mTextureWidth = desc.Width;
1356 mTextureHeight = desc.Height;
1357 mTextureDepth = desc.ArraySize;
1362 TextureStorage11_2DArray::~TextureStorage11_2DArray()
1364 SafeRelease(mTexture);
1365 SafeRelease(mSwizzleTexture);
1367 for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
1369 SafeRelease(mSwizzleRenderTargets[level]);
1372 for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++)
1374 SafeDelete(i->second);
1376 mRenderTargets.clear();
1379 TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage)
1381 ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage));
1382 return static_cast<TextureStorage11_2DArray*>(storage);
1385 ID3D11Resource *TextureStorage11_2DArray::getResource() const
1390 ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture)
1392 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1393 srvDesc.Format = format;
1394 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1395 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
1396 srvDesc.Texture2DArray.MipLevels = mipLevels;
1397 srvDesc.Texture2DArray.FirstArraySlice = 0;
1398 srvDesc.Texture2DArray.ArraySize = mTextureDepth;
1400 ID3D11ShaderResourceView *SRV = NULL;
1402 ID3D11Device *device = mRenderer->getDevice();
1403 HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV);
1405 if (result == E_OUTOFMEMORY)
1407 gl::error(GL_OUT_OF_MEMORY);
1409 ASSERT(SUCCEEDED(result));
1414 RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int layer)
1416 if (mipLevel >= 0 && mipLevel < getLevelCount())
1418 LevelLayerKey key(mipLevel, layer);
1419 if (mRenderTargets.find(key) == mRenderTargets.end())
1421 ID3D11Device *device = mRenderer->getDevice();
1424 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
1425 srvDesc.Format = mShaderResourceFormat;
1426 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
1427 srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel;
1428 srvDesc.Texture2DArray.MipLevels = 1;
1429 srvDesc.Texture2DArray.FirstArraySlice = layer;
1430 srvDesc.Texture2DArray.ArraySize = 1;
1432 ID3D11ShaderResourceView *srv;
1433 result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
1435 if (result == E_OUTOFMEMORY)
1437 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1439 ASSERT(SUCCEEDED(result));
1441 if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
1443 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1444 rtvDesc.Format = mRenderTargetFormat;
1445 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1446 rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
1447 rtvDesc.Texture2DArray.FirstArraySlice = layer;
1448 rtvDesc.Texture2DArray.ArraySize = 1;
1450 ID3D11RenderTargetView *rtv;
1451 result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
1453 if (result == E_OUTOFMEMORY)
1456 return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
1458 ASSERT(SUCCEEDED(result));
1460 mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1);
1462 // RenderTarget will take ownership of these resources
1472 return mRenderTargets[key];
1480 void TextureStorage11_2DArray::generateMipmap(int level)
1482 invalidateSwizzleCacheLevel(level);
1483 for (unsigned int layer = 0; layer < mTextureDepth; layer++)
1485 RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level - 1, layer));
1486 RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level, layer));
1488 generateMipmapLayer(source, dest);
1492 ID3D11Resource *TextureStorage11_2DArray::getSwizzleTexture()
1494 if (!mSwizzleTexture)
1496 ID3D11Device *device = mRenderer->getDevice();
1498 D3D11_TEXTURE2D_DESC desc;
1499 desc.Width = mTextureWidth;
1500 desc.Height = mTextureHeight;
1501 desc.MipLevels = mMipLevels;
1502 desc.ArraySize = mTextureDepth;
1503 desc.Format = mSwizzleTextureFormat;
1504 desc.SampleDesc.Count = 1;
1505 desc.SampleDesc.Quality = 0;
1506 desc.Usage = D3D11_USAGE_DEFAULT;
1507 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
1508 desc.CPUAccessFlags = 0;
1511 HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture);
1513 if (result == E_OUTOFMEMORY)
1515 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11Texture2D*>(NULL));
1517 ASSERT(SUCCEEDED(result));
1520 return mSwizzleTexture;
1523 ID3D11RenderTargetView *TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel)
1525 if (mipLevel >= 0 && mipLevel < getLevelCount())
1527 if (!mSwizzleRenderTargets[mipLevel])
1529 ID3D11Resource *swizzleTexture = getSwizzleTexture();
1530 if (!swizzleTexture)
1535 ID3D11Device *device = mRenderer->getDevice();
1537 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
1538 rtvDesc.Format = mSwizzleRenderTargetFormat;
1539 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
1540 rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
1541 rtvDesc.Texture2DArray.FirstArraySlice = 0;
1542 rtvDesc.Texture2DArray.ArraySize = mTextureDepth;
1544 HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
1546 if (result == E_OUTOFMEMORY)
1548 return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11RenderTargetView*>(NULL));
1550 ASSERT(SUCCEEDED(result));
1553 return mSwizzleRenderTargets[mipLevel];
1561 unsigned int TextureStorage11_2DArray::getTextureLevelDepth(int mipLevel) const
1563 return mTextureDepth;