diff options
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp | 682 |
1 files changed, 530 insertions, 152 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp index 00b81b7c92..91e7147da6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -9,17 +8,18 @@ // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. #include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" - -#include "libGLESv2/renderer/d3d/TextureD3D.h" #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" #include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/renderer/d3d/d3d11/Blit11.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/main.h" +#include "libGLESv2/ImageIndex.h" #include "common/utilities.h" -#include "libGLESv2/main.h" namespace rx { @@ -126,15 +126,16 @@ DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTa { UINT bindFlags = 0; - if (gl_d3d11::GetSRVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); + if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) { bindFlags |= D3D11_BIND_SHADER_RESOURCE; } - if (gl_d3d11::GetDSVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) { bindFlags |= D3D11_BIND_DEPTH_STENCIL; } - if (gl_d3d11::GetRTVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN && renderTarget) + if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget) { bindFlags |= D3D11_BIND_RENDER_TARGET; } @@ -195,7 +196,7 @@ UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget) const ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState) { bool swizzleRequired = samplerState.swizzleRequired(); - bool mipmapping = IsMipmapFiltered(samplerState); + bool mipmapping = gl::IsMipmapFiltered(samplerState); unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel) : 1; // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0) @@ -239,7 +240,7 @@ ID3D11ShaderResourceView *TextureStorage11::getSRVLevel(int mipLevel) } } -void TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) { SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); for (int level = 0; level < getLevelCount(); level++) @@ -255,16 +256,17 @@ void TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, Blit11 *blitter = mRenderer->getBlitter(); - if (blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha)) + gl::Error error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); + if (error.isError()) { - mSwizzleCache[level] = swizzleTarget; - } - else - { - ERR("Failed to swizzle texture."); + return error; } + + mSwizzleCache[level] = swizzleTarget; } } + + return gl::Error(GL_NO_ERROR); } void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel) @@ -308,7 +310,8 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign ASSERT(dstTexture); - if (!fullCopy && (d3d11::GetDepthBits(mTextureFormat) > 0 || d3d11::GetStencilBits(mTextureFormat) > 0)) + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0)) { // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead Blit11 *blitter = mRenderer->getBlitter(); @@ -319,11 +322,13 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign } else { + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + D3D11_BOX srcBox; srcBox.left = copyArea.x; srcBox.top = copyArea.y; - srcBox.right = copyArea.x + roundUp((unsigned int)width, d3d11::GetBlockWidth(mTextureFormat)); - srcBox.bottom = copyArea.y + roundUp((unsigned int)height, d3d11::GetBlockHeight(mTextureFormat)); + srcBox.right = copyArea.x + roundUp((unsigned int)width, dxgiFormatInfo.blockWidth); + srcBox.bottom = copyArea.y + roundUp((unsigned int)height, dxgiFormatInfo.blockHeight); srcBox.front = copyArea.z; srcBox.back = copyArea.z + copyArea.depth; @@ -338,6 +343,27 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign return false; } +bool TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, + int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth) +{ + if (dstTexture) + { + ID3D11Resource *srcTexture = getResource(); + unsigned int srcSubresource = getSubresourceIndex(level + mTopLevel, layerTarget); + + ASSERT(srcTexture); + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + context->CopySubresourceRegion(dstTexture, dstSubresource, xoffset, yoffset, zoffset, + srcTexture, srcSubresource, NULL); + return true; + } + + return false; +} + void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) { if (source && dest) @@ -356,7 +382,7 @@ void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget1 Blit11 *blitter = mRenderer->getBlitter(); blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, - gl::GetFormat(source->getInternalFormat()), GL_LINEAR); + gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR); } } } @@ -371,14 +397,15 @@ void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGree } TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) - : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) + : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), + mTexture(swapchain->getOffscreenTexture()), + mSwizzleTexture(NULL) { - mTexture = swapchain->getOffscreenTexture(); mTexture->AddRef(); - mSwizzleTexture = NULL; for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { + mAssociatedImages[i] = NULL; mRenderTarget[i] = NULL; mSwizzleRenderTargets[i] = NULL; } @@ -401,33 +428,37 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch offscreenRTV->GetDesc(&rtvDesc); mRenderTargetFormat = rtvDesc.Format; - GLenum internalFormat = d3d11_gl::GetInternalFormat(mTextureFormat); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalFormat); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalFormat); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalFormat); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat); + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; + + initializeSerials(1, 1); } TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)), + mTexture(NULL), + mSwizzleTexture(NULL) { - mTexture = NULL; - mSwizzleTexture = NULL; - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { + mAssociatedImages[i] = NULL; mRenderTarget[i] = NULL; mSwizzleRenderTargets[i] = NULL; } - mTextureFormat = gl_d3d11::GetTexFormat(internalformat); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; // if the width or height is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation @@ -441,7 +472,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform D3D11_TEXTURE2D_DESC desc; desc.Width = width; // Compressed texture size constraints? desc.Height = height; - desc.MipLevels = mRenderer->isLevel9() ? 1 : ((levels > 0) ? (mTopLevel + levels) : 0); + desc.MipLevels = desc.MipLevels = mRenderer->isLevel9() ? 1 : ((levels > 0) ? (mTopLevel + levels) : 0); desc.ArraySize = 1; desc.Format = mTextureFormat; desc.SampleDesc.Count = 1; @@ -474,10 +505,27 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform mTextureDepth = 1; } } + + initializeSerials(getLevelCount(), 1); } TextureStorage11_2D::~TextureStorage11_2D() { + for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if (mAssociatedImages[i] != NULL) + { + bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + mAssociatedImages[i]->recoverFromAssociatedStorage(); + } + } + } + SafeRelease(mTexture); SafeRelease(mSwizzleTexture); @@ -494,13 +542,80 @@ TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage return static_cast<TextureStorage11_2D*>(storage); } +void TextureStorage11_2D::associateImage(Image11* image, int level, int layerTarget) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + mAssociatedImages[level] = image; + } +} + +bool TextureStorage11_2D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +{ + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages[level] == expectedImage); + ASSERT(retValue); + return retValue; + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_2D::disassociateImage(int level, int layerTarget, Image11* expectedImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + ASSERT(mAssociatedImages[level] == expectedImage); + + if (mAssociatedImages[level] == expectedImage) + { + mAssociatedImages[level] = NULL; + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +void TextureStorage11_2D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + mAssociatedImages[level]->recoverFromAssociatedStorage(); + } + } + } +} + ID3D11Resource *TextureStorage11_2D::getResource() const { return mTexture; } -RenderTarget *TextureStorage11_2D::getRenderTarget(int level) +RenderTarget *TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index) { + ASSERT(!index.hasLayer()); + + int level = index.mipIndex; + if (level >= 0 && level < getLevelCount()) { if (!mRenderTarget[level]) @@ -595,14 +710,22 @@ ID3D11ShaderResourceView *TextureStorage11_2D::createSRV(int baseLevel, int mipL return SRV; } -void TextureStorage11_2D::generateMipmap(int level) +void TextureStorage11_2D::generateMipmaps() { - invalidateSwizzleCacheLevel(level); + // Base level must already be defined + + for (int level = 1; level < getLevelCount(); level++) + { + invalidateSwizzleCacheLevel(level); + + gl::ImageIndex srcIndex = gl::ImageIndex::Make2D(level - 1); + gl::ImageIndex destIndex = gl::ImageIndex::Make2D(level); - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); - generateMipmapLayer(source, dest); + generateMipmapLayer(source, dest); + } } ID3D11Resource *TextureStorage11_2D::getSwizzleTexture() @@ -671,11 +794,6 @@ ID3D11RenderTargetView *TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel } } -unsigned int TextureStorage11_2D::getTextureLevelDepth(int mipLevel) const -{ - return 1; -} - TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) { @@ -687,17 +805,19 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal mSwizzleRenderTargets[level] = NULL; for (unsigned int face = 0; face < 6; face++) { + mAssociatedImages[face][level] = NULL; mRenderTarget[face][level] = NULL; } } - mTextureFormat = gl_d3d11::GetTexFormat(internalformat); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; // if the size is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation @@ -739,10 +859,31 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal mTextureDepth = 1; } } + + initializeSerials(getLevelCount() * 6, 6); } + TextureStorage11_Cube::~TextureStorage11_Cube() { + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (unsigned int face = 0; face < 6; face++) + { + if (mAssociatedImages[face][level] != NULL) + { + bool imageAssociationCorrect = mAssociatedImages[face][level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + mAssociatedImages[face][level]->recoverFromAssociatedStorage(); + } + } + } + } + SafeRelease(mTexture); SafeRelease(mSwizzleTexture); @@ -762,16 +903,96 @@ TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureS return static_cast<TextureStorage11_Cube*>(storage); } +void TextureStorage11_Cube::associateImage(Image11* image, int level, int layerTarget) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < 6); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < 6) + { + mAssociatedImages[layerTarget][level] = image; + } + } +} + +bool TextureStorage11_Cube::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +{ + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < 6) + { + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage); + ASSERT(retValue); + return retValue; + } + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_Cube::disassociateImage(int level, int layerTarget, Image11* expectedImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < 6); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < 6) + { + ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); + + if (mAssociatedImages[layerTarget][level] == expectedImage) + { + mAssociatedImages[layerTarget][level] = NULL; + } + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +void TextureStorage11_Cube::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < 6); + + if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) + { + if (0 <= layerTarget && layerTarget < 6) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[layerTarget][level] != NULL && mAssociatedImages[layerTarget][level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[layerTarget][level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(); + } + } + } + } +} + ID3D11Resource *TextureStorage11_Cube::getResource() const { return mTexture; } -RenderTarget *TextureStorage11_Cube::getRenderTargetFace(GLenum faceTarget, int level) +RenderTarget *TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index) { + int faceIndex = index.layerIndex; + int level = index.mipIndex; + if (level >= 0 && level < getLevelCount()) { - int faceIndex = TextureD3D_Cube::targetToIndex(faceTarget); if (!mRenderTarget[faceIndex][level]) { ID3D11Device *device = mRenderer->getDevice(); @@ -865,10 +1086,8 @@ ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mi srvDesc.Format = format; // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures - bool unnormalizedInteger = (d3d11::GetComponentType(mTextureFormat) == GL_INT || - d3d11::GetComponentType(mTextureFormat) == GL_UNSIGNED_INT); - - if(unnormalizedInteger) + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); + if (dxgiFormatInfo.componentType == GL_INT || dxgiFormatInfo.componentType == GL_UNSIGNED_INT) { srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; @@ -897,14 +1116,25 @@ ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mi return SRV; } -void TextureStorage11_Cube::generateMipmap(int faceIndex, int level) +void TextureStorage11_Cube::generateMipmaps() { - invalidateSwizzleCacheLevel(level); + // Base level must already be defined - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level)); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < getLevelCount(); level++) + { + invalidateSwizzleCacheLevel(level); + + gl::ImageIndex srcIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1); + gl::ImageIndex destIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level); - generateMipmapLayer(source, dest); + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); + + generateMipmapLayer(source, dest); + } + } } ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture() @@ -976,11 +1206,6 @@ ID3D11RenderTargetView *TextureStorage11_Cube::getSwizzleRenderTarget(int mipLev } } -unsigned int TextureStorage11_Cube::getTextureLevelDepth(int mipLevel) const -{ - return 6; -} - TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) @@ -990,17 +1215,19 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { + mAssociatedImages[i] = NULL; mLevelRenderTargets[i] = NULL; mSwizzleRenderTargets[i] = NULL; } - mTextureFormat = gl_d3d11::GetTexFormat(internalformat); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; // If the width, height or depth are not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation @@ -1045,10 +1272,27 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform mTextureDepth = desc.Depth; } } + + initializeSerials(getLevelCount() * depth, depth); } TextureStorage11_3D::~TextureStorage11_3D() { + for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + if (mAssociatedImages[i] != NULL) + { + bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + mAssociatedImages[i]->recoverFromAssociatedStorage(); + } + } + } + SafeRelease(mTexture); SafeRelease(mSwizzleTexture); @@ -1071,6 +1315,69 @@ TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage return static_cast<TextureStorage11_3D*>(storage); } +void TextureStorage11_3D::associateImage(Image11* image, int level, int layerTarget) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + mAssociatedImages[level] = image; + } +} + +bool TextureStorage11_3D::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +{ + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages[level] == expectedImage); + ASSERT(retValue); + return retValue; + } + + return false; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_3D::disassociateImage(int level, int layerTarget, Image11* expectedImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + ASSERT(mAssociatedImages[level] == expectedImage); + + if (mAssociatedImages[level] == expectedImage) + { + mAssociatedImages[level] = NULL; + } + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +void TextureStorage11_3D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + // No need to let the old Image recover its data, if it is also the incoming Image. + if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + mAssociatedImages[level]->recoverFromAssociatedStorage(); + } + } + } +} + ID3D11Resource *TextureStorage11_3D::getResource() const { return mTexture; @@ -1098,20 +1405,24 @@ ID3D11ShaderResourceView *TextureStorage11_3D::createSRV(int baseLevel, int mipL return SRV; } -RenderTarget *TextureStorage11_3D::getRenderTarget(int mipLevel) +RenderTarget *TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index) { + int mipLevel = index.mipIndex; + if (mipLevel >= 0 && mipLevel < getLevelCount()) { - if (!mLevelRenderTargets[mipLevel]) + ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN); + + if (!index.hasLayer()) { - ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel); - if (!srv) + if (!mLevelRenderTargets[mipLevel]) { - return NULL; - } + ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel); + if (!srv) + { + return NULL; + } - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { ID3D11Device *device = mRenderer->getDevice(); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; @@ -1136,35 +1447,22 @@ RenderTarget *TextureStorage11_3D::getRenderTarget(int mipLevel) // RenderTarget will take ownership of these resources SafeRelease(rtv); } - else - { - UNREACHABLE(); - } - } - return mLevelRenderTargets[mipLevel]; - } - else - { - return NULL; - } -} - -RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer) -{ - if (mipLevel >= 0 && mipLevel < getLevelCount()) - { - LevelLayerKey key(mipLevel, layer); - if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) + return mLevelRenderTargets[mipLevel]; + } + else { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; + int layer = index.layerIndex; - // TODO, what kind of SRV is expected here? - ID3D11ShaderResourceView *srv = NULL; - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + LevelLayerKey key(mipLevel, layer); + if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + // TODO, what kind of SRV is expected here? + ID3D11ShaderResourceView *srv = NULL; + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; rtvDesc.Format = mRenderTargetFormat; rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; @@ -1188,28 +1486,30 @@ RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer) SafeRelease(rtv); SafeRelease(srv); } - else - { - UNREACHABLE(); - } - } - return mLevelLayerRenderTargets[key]; - } - else - { - return NULL; + return mLevelLayerRenderTargets[key]; + } } + + return NULL; } -void TextureStorage11_3D::generateMipmap(int level) +void TextureStorage11_3D::generateMipmaps() { - invalidateSwizzleCacheLevel(level); + // Base level must already be defined + + for (int level = 1; level < getLevelCount(); level++) + { + invalidateSwizzleCacheLevel(level); + + gl::ImageIndex srcIndex = gl::ImageIndex::Make3D(level - 1); + gl::ImageIndex destIndex = gl::ImageIndex::Make3D(level); - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); - generateMipmapLayer(source, dest); + generateMipmapLayer(source, dest); + } } ID3D11Resource *TextureStorage11_3D::getSwizzleTexture() @@ -1279,12 +1579,6 @@ ID3D11RenderTargetView *TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel } } -unsigned int TextureStorage11_3D::getTextureLevelDepth(int mipLevel) const -{ - return std::max(mTextureDepth >> mipLevel, 1U); -} - - TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) @@ -1297,13 +1591,14 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in mSwizzleRenderTargets[level] = NULL; } - mTextureFormat = gl_d3d11::GetTexFormat(internalformat); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalformat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat); + mTextureFormat = formatInfo.texFormat; + mShaderResourceFormat = formatInfo.srvFormat; + mDepthStencilFormat = formatInfo.dsvFormat; + mRenderTargetFormat = formatInfo.rtvFormat; + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; // if the width, height or depth is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation @@ -1350,10 +1645,25 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in mTextureDepth = desc.ArraySize; } } + + initializeSerials(getLevelCount() * depth, depth); } TextureStorage11_2DArray::~TextureStorage11_2DArray() { + for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++) + { + bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // We must let the Images recover their data before we delete it from the TextureStorage. + i->second->recoverFromAssociatedStorage(); + } + } + mAssociatedImages.clear(); + SafeRelease(mTexture); SafeRelease(mSwizzleTexture); @@ -1375,6 +1685,66 @@ TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray return static_cast<TextureStorage11_2DArray*>(storage); } +void TextureStorage11_2DArray::associateImage(Image11* image, int level, int layerTarget) +{ + ASSERT(0 <= level && level < getLevelCount()); + + if (0 <= level && level < getLevelCount()) + { + LevelLayerKey key(level, layerTarget); + mAssociatedImages[key] = image; + } +} + +bool TextureStorage11_2DArray::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +{ + LevelLayerKey key(level, layerTarget); + + // This validation check should never return false. It means the Image/TextureStorage association is broken. + bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); + ASSERT(retValue); + return retValue; +} + +// disassociateImage allows an Image to end its association with a Storage. +void TextureStorage11_2DArray::disassociateImage(int level, int layerTarget, Image11* expectedImage) +{ + LevelLayerKey key(level, layerTarget); + + bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + mAssociatedImages[key] = NULL; + } +} + +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. +void TextureStorage11_2DArray::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + LevelLayerKey key(level, layerTarget); + + ASSERT(mAssociatedImages.find(key) != mAssociatedImages.end()); + + if (mAssociatedImages.find(key) != mAssociatedImages.end()) + { + if (mAssociatedImages[key] != NULL && mAssociatedImages[key] != incomingImage) + { + // Ensure that the Image is still associated with this TextureStorage. This should be true. + bool imageAssociationCorrect = mAssociatedImages[key]->isAssociatedStorageValid(this); + ASSERT(imageAssociationCorrect); + + if (imageAssociationCorrect) + { + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to NULL too. + mAssociatedImages[key]->recoverFromAssociatedStorage(); + } + } + } +} + ID3D11Resource *TextureStorage11_2DArray::getResource() const { return mTexture; @@ -1404,8 +1774,13 @@ ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int return SRV; } -RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int layer) +RenderTarget *TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index) { + ASSERT(index.hasLayer()); + + int mipLevel = index.mipIndex; + int layer = index.layerIndex; + if (mipLevel >= 0 && mipLevel < getLevelCount()) { LevelLayerKey key(mipLevel, layer); @@ -1470,15 +1845,23 @@ RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int l } } -void TextureStorage11_2DArray::generateMipmap(int level) +void TextureStorage11_2DArray::generateMipmaps() { - invalidateSwizzleCacheLevel(level); - for (unsigned int layer = 0; layer < mTextureDepth; layer++) + // Base level must already be defined + + for (int level = 0; level < getLevelCount(); level++) { - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level - 1, layer)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level, layer)); + invalidateSwizzleCacheLevel(level); + for (unsigned int layer = 0; layer < mTextureDepth; layer++) + { + gl::ImageIndex sourceIndex = gl::ImageIndex::Make2DArray(level - 1, layer); + gl::ImageIndex destIndex = gl::ImageIndex::Make2DArray(level, layer); - generateMipmapLayer(source, dest); + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(sourceIndex)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); + + generateMipmapLayer(source, dest); + } } } @@ -1551,9 +1934,4 @@ ID3D11RenderTargetView *TextureStorage11_2DArray::getSwizzleRenderTarget(int mip } } -unsigned int TextureStorage11_2DArray::getTextureLevelDepth(int mipLevel) const -{ - return mTextureDepth; -} - } |