summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
diff options
context:
space:
mode:
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.cpp682
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;
-}
-
}