Commit 752ce192 by Gregoire Payen de La Garanderie Committed by Jamie Madill

D3D11: Use DX generateMips to generate mipmaps whenever possible.

BUG=angleproject:974 Change-Id: I95937fe7a0833de77c52f838ebb3ecba55dfbf8a Reviewed-on: https://chromium-review.googlesource.com/265640Tested-by: 's avatarGregoire Payen de La Garanderie <Gregory.Payen@imgtec.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 28eb65e3
......@@ -277,7 +277,7 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c
Error Texture::generateMipmaps()
{
Error error = mTexture->generateMipmaps();
Error error = mTexture->generateMipmaps(getSamplerState());
if (error.isError())
{
return error;
......
......@@ -60,7 +60,7 @@ class TextureImpl : angle::NonCopyable
virtual gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) = 0;
virtual gl::Error generateMipmaps() = 0;
virtual gl::Error generateMipmaps(const gl::SamplerState &samplerState) = 0;
virtual void bindTexImage(egl::Surface *surface) = 0;
virtual void releaseTexImage() = 0;
......
......@@ -163,6 +163,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
// Image operations
virtual ImageD3D *createImage() = 0;
virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0;
virtual gl::Error generateMipmapsUsingD3D(TextureStorage *storage, const gl::SamplerState &samplerState) = 0;
virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0;
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) = 0;
virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) = 0;
......
......@@ -376,7 +376,7 @@ ImageD3D *TextureD3D::getBaseLevelImage() const
return getImage(getImageIndex(0, 0));
}
gl::Error TextureD3D::generateMipmaps()
gl::Error TextureD3D::generateMipmaps(const gl::SamplerState &samplerState)
{
GLint mipCount = mipLevels();
......@@ -405,6 +405,38 @@ gl::Error TextureD3D::generateMipmaps()
// Set up proper mipmap chain in our Image array.
initMipmapsImages();
if (mTexStorage && mTexStorage->supportsNativeMipmapFunction())
{
gl::Error error = updateStorage();
if (error.isError())
{
return error;
}
// Generate the mipmap chain using the ad-hoc DirectX function.
error = mRenderer->generateMipmapsUsingD3D(mTexStorage, samplerState);
if (error.isError())
{
return error;
}
}
else
{
// Generate the mipmap chain, one level at a time.
gl::Error error = generateMipmapsUsingImages();
if (error.isError())
{
return error;
}
}
return gl::Error(GL_NO_ERROR);
}
gl::Error TextureD3D::generateMipmapsUsingImages()
{
GLint mipCount = mipLevels();
// We know that all layers have the same dimension, for the texture to be complete
GLint layerCount = static_cast<GLint>(getLayerCount(0));
......
......@@ -60,7 +60,7 @@ class TextureD3D : public TextureImpl
virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0;
virtual bool isValidIndex(const gl::ImageIndex &index) const = 0;
virtual gl::Error generateMipmaps();
virtual gl::Error generateMipmaps(const gl::SamplerState &samplerState);
TextureStorage *getStorage();
ImageD3D *getBaseLevelImage() const;
......@@ -106,6 +106,8 @@ class TextureD3D : public TextureImpl
virtual gl::Error updateStorage() = 0;
bool shouldUseSetData(const ImageD3D *image) const;
gl::Error generateMipmapsUsingImages();
};
class TextureD3D_2D : public TextureD3D
......
......@@ -39,6 +39,7 @@ class TextureStorage : angle::NonCopyable
virtual int getTopLevel() const = 0;
virtual bool isRenderTarget() const = 0;
virtual bool isManaged() const = 0;
virtual bool supportsNativeMipmapFunction() const = 0;
virtual int getLevelCount() const = 0;
virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
......
......@@ -3070,6 +3070,25 @@ gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src)
return Image11::generateMipmap(dest11, src11);
}
gl::Error Renderer11::generateMipmapsUsingD3D(TextureStorage *storage, const gl::SamplerState &samplerState)
{
TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
ASSERT(storage11->isRenderTarget());
ASSERT(storage11->supportsNativeMipmapFunction());
ID3D11ShaderResourceView *srv;
gl::Error error = storage11->getSRVLevels(samplerState.baseLevel, samplerState.maxLevel, &srv);
if (error.isError())
{
return error;
}
mDeviceContext->GenerateMips(srv);
return gl::Error(GL_NO_ERROR);
}
TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
{
SwapChain11 *swapChain11 = GetAs<SwapChain11>(swapChain);
......
......@@ -185,6 +185,7 @@ class Renderer11 : public RendererD3D
// Image operations
virtual ImageD3D *createImage();
gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
gl::Error generateMipmapsUsingD3D(TextureStorage *storage, const gl::SamplerState &samplerState) override;
virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain);
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly);
virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
......
......@@ -60,9 +60,10 @@ bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const
return std::tie(baseLevel, mipLevels, swizzle) < std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle);
}
TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags)
TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags)
: mRenderer(renderer),
mBindFlags(bindFlags),
mMiscFlags(miscFlags),
mTopLevel(0),
mMipLevels(0),
mInternalFormat(GL_NONE),
......@@ -115,11 +116,34 @@ DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_L
return bindFlags;
}
DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget, int levels)
{
UINT miscFlags = 0;
const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, featureLevel);
if (renderTarget && levels > 1)
{
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.srvFormat);
if (dxgiFormatInfo.nativeMipmapSupport(featureLevel))
{
miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
}
}
return miscFlags;
}
UINT TextureStorage11::getBindFlags() const
{
return mBindFlags;
}
UINT TextureStorage11::getMiscFlags() const
{
return mMiscFlags;
}
int TextureStorage11::getTopLevel() const
{
return mTopLevel;
......@@ -135,6 +159,11 @@ bool TextureStorage11::isManaged() const
return false;
}
bool TextureStorage11::supportsNativeMipmapFunction() const
{
return (mMiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) != 0;
}
int TextureStorage11::getLevelCount() const
{
return mMipLevels - mTopLevel;
......@@ -195,14 +224,14 @@ gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11S
}
SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired);
SRVCache::const_iterator iter = mSrvCache.find(key);
auto iter = mSrvCache.find(key);
if (iter != mSrvCache.end())
{
*outSRV = iter->second;
return gl::Error(GL_NO_ERROR);
}
else
{
ID3D11Resource *texture = NULL;
ID3D11Resource *texture = nullptr;
if (swizzleRequired)
{
gl::Error error = getSwizzleTexture(&texture);
......@@ -220,7 +249,7 @@ gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11S
}
}
ID3D11ShaderResourceView *srv = NULL;
ID3D11ShaderResourceView *srv = nullptr;
DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat);
gl::Error error = createSRV(samplerState.baseLevel, mipLevels, format, texture, &srv);
if (error.isError())
......@@ -230,7 +259,6 @@ gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11S
mSrvCache.insert(std::make_pair(key, srv));
*outSRV = srv;
}
return gl::Error(GL_NO_ERROR);
}
......@@ -260,6 +288,56 @@ gl::Error TextureStorage11::getSRVLevel(int mipLevel, ID3D11ShaderResourceView *
return gl::Error(GL_NO_ERROR);
}
gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV)
{
unsigned int mipLevels = maxLevel - baseLevel + 1;
// Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0)
mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - baseLevel);
if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3)
{
ASSERT(mipLevels == 1 || mipLevels == mMipLevels);
}
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
// We must ensure that the level zero texture is in sync with mipped texture.
gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1);
if (error.isError())
{
return error;
}
}
SRVKey key(baseLevel, mipLevels, false);
auto iter = mSrvCache.find(key);
if (iter != mSrvCache.end())
{
*outSRV = iter->second;
return gl::Error(GL_NO_ERROR);
}
ID3D11Resource *texture = nullptr;
gl::Error error = getResource(&texture);
if (error.isError())
{
return error;
}
ID3D11ShaderResourceView *srv = nullptr;
error = createSRV(baseLevel, mipLevels, mShaderResourceFormat, texture, &srv);
if (error.isError())
{
return error;
}
mSrvCache[key] = srv;
*outSRV = srv;
return gl::Error(GL_NO_ERROR);
}
gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha)
{
SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha);
......@@ -596,7 +674,7 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image
}
TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
: TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE),
: TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0),
mTexture(swapchain->getOffscreenTexture()),
mSwizzleTexture(NULL),
mLevelZeroTexture(NULL),
......@@ -644,7 +722,9 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swap
}
TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly)
: TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)),
: TextureStorage11(renderer,
GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget),
GetTextureMiscFlags(internalformat, renderer->getFeatureLevel(), renderTarget, levels)),
mTexture(NULL),
mSwizzleTexture(NULL),
mLevelZeroTexture(NULL),
......@@ -976,7 +1056,7 @@ gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels)
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = getBindFlags();
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.MiscFlags = getMiscFlags();
HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture);
......@@ -1229,7 +1309,9 @@ gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11Render
}
TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
: TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget))
: TextureStorage11(renderer,
GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget),
GetTextureMiscFlags(internalformat, renderer->getFeatureLevel(), renderTarget, levels))
{
mTexture = NULL;
mSwizzleTexture = NULL;
......@@ -1624,7 +1706,7 @@ gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels)
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = getBindFlags();
desc.CPUAccessFlags = 0;
desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags();
HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture);
......@@ -1913,7 +1995,9 @@ gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11Rend
TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
GLsizei width, GLsizei height, GLsizei depth, int levels)
: TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget))
: TextureStorage11(renderer,
GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget),
GetTextureMiscFlags(internalformat, renderer->getFeatureLevel(), renderTarget, levels))
{
mTexture = NULL;
mSwizzleTexture = NULL;
......@@ -2076,7 +2160,7 @@ gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource)
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = getBindFlags();
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.MiscFlags = getMiscFlags();
HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture);
......@@ -2293,7 +2377,9 @@ gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11Render
TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
GLsizei width, GLsizei height, GLsizei depth, int levels)
: TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget))
: TextureStorage11(renderer,
GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget),
GetTextureMiscFlags(internalformat, renderer->getFeatureLevel(), renderTarget, levels))
{
mTexture = NULL;
mSwizzleTexture = NULL;
......@@ -2455,7 +2541,7 @@ gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource)
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = getBindFlags();
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.MiscFlags = getMiscFlags();
HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
......
......@@ -35,8 +35,10 @@ class TextureStorage11 : public TextureStorage
virtual ~TextureStorage11();
static DWORD GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget);
static DWORD GetTextureMiscFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget, int levels);
UINT getBindFlags() const;
UINT getMiscFlags() const;
virtual gl::Error getResource(ID3D11Resource **outResource) = 0;
virtual gl::Error getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV);
......@@ -47,6 +49,7 @@ class TextureStorage11 : public TextureStorage
virtual int getTopLevel() const;
virtual bool isRenderTarget() const;
virtual bool isManaged() const;
bool supportsNativeMipmapFunction() const override;
virtual int getLevelCount() const;
virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
......@@ -69,8 +72,10 @@ class TextureStorage11 : public TextureStorage
virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
gl::Error getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV);
protected:
TextureStorage11(Renderer11 *renderer, UINT bindFlags);
TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags);
int getLevelWidth(int mipLevel) const;
int getLevelHeight(int mipLevel) const;
int getLevelDepth(int mipLevel) const;
......@@ -120,6 +125,7 @@ class TextureStorage11 : public TextureStorage
private:
const UINT mBindFlags;
const UINT mMiscFlags;
struct SRVKey
{
......
......@@ -24,6 +24,7 @@ namespace d3d11
{
typedef std::map<std::pair<GLenum, GLenum>, ColorCopyFunction> FastCopyFunctionMap;
typedef bool (*NativeMipmapGenerationSupportFunction)(D3D_FEATURE_LEVEL);
struct DXGIFormat
{
......@@ -51,6 +52,9 @@ struct DXGIFormat
ColorReadFunction colorReadFunction;
FastCopyFunctionMap fastCopyFunctions;
NativeMipmapGenerationSupportFunction nativeMipmapSupport;
ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const;
};
const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format);
......
......@@ -2846,6 +2846,12 @@ gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src)
return Image9::generateMipmap(dst9, src9);
}
gl::Error Renderer9::generateMipmapsUsingD3D(TextureStorage *storage, const gl::SamplerState &samplerState)
{
UNREACHABLE();
return gl::Error(GL_NO_ERROR);
}
TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain)
{
SwapChain9 *swapChain9 = GetAs<SwapChain9>(swapChain);
......
......@@ -183,6 +183,7 @@ class Renderer9 : public RendererD3D
// Image operations
virtual ImageD3D *createImage();
gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
gl::Error generateMipmapsUsingD3D(TextureStorage *storage, const gl::SamplerState &samplerState) override;
virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain);
virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly);
virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
......
......@@ -66,6 +66,11 @@ bool TextureStorage9::isManaged() const
return (mD3DPool == D3DPOOL_MANAGED);
}
bool TextureStorage9::supportsNativeMipmapFunction() const
{
return false;
}
D3DPOOL TextureStorage9::getPool() const
{
return mD3DPool;
......
......@@ -37,6 +37,7 @@ class TextureStorage9 : public TextureStorage
virtual int getTopLevel() const;
virtual bool isRenderTarget() const;
virtual bool isManaged() const;
bool supportsNativeMipmapFunction() const override;
virtual int getLevelCount() const;
virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
......
......@@ -333,7 +333,7 @@ gl::Error TextureGL::setStorage(GLenum target, size_t levels, GLenum internalFor
return gl::Error(GL_NO_ERROR);
}
gl::Error TextureGL::generateMipmaps()
gl::Error TextureGL::generateMipmaps(const gl::SamplerState &samplerState)
{
mStateManager->bindTexture(mTextureType, mTextureID);
mFunctions->generateMipmap(mTextureType);
......
......@@ -43,7 +43,7 @@ class TextureGL : public TextureImpl
gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
gl::Error generateMipmaps() override;
gl::Error generateMipmaps(const gl::SamplerState &samplerState) override;
void bindTexImage(egl::Surface *surface) override;
void releaseTexImage() override;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment