blob: 006b427848fcefeb5b076ba2a89c2225299d06e4 [file] [log] [blame]
//
// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived
// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
#include "libANGLE/Error.h"
#include "libANGLE/Texture.h"
#include "libANGLE/renderer/d3d/TextureStorage.h"
#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
#include <array>
#include <map>
namespace gl
{
struct ImageIndex;
}
namespace rx
{
class EGLImageD3D;
class RenderTargetD3D;
class RenderTarget11;
class Renderer11;
class SwapChain11;
class Image11;
struct Renderer11DeviceCaps;
class TextureStorage11 : public TextureStorage
{
public:
~TextureStorage11() override;
static DWORD GetTextureBindFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget);
static DWORD GetTextureMiscFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget, int levels);
UINT getBindFlags() const;
UINT getMiscFlags() const;
const d3d11::Format &getFormatSet() const;
gl::Error getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV);
gl::Error generateSwizzles(const gl::SwizzleState &swizzleTarget);
void markLevelDirty(int mipLevel);
void markDirty();
gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource,
const gl::ImageIndex &index, const gl::Box &copyArea);
gl::Error copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource,
const gl::ImageIndex &index, const gl::Box &region);
// TextureStorage virtual functions
int getTopLevel() const override;
bool isRenderTarget() const override;
bool isManaged() const override;
bool supportsNativeMipmapFunction() const override;
int getLevelCount() const override;
gl::Error generateMipmap(const gl::ImageIndex &sourceIndex,
const gl::ImageIndex &destIndex) override;
gl::Error copyToStorage(TextureStorage *destStorage) override;
gl::Error setData(const gl::ImageIndex &index,
ImageD3D *image,
const gl::Box *destBox,
GLenum type,
const gl::PixelUnpackState &unpack,
const uint8_t *pixelData) override;
virtual gl::Error getSRV(const gl::TextureState &textureState,
ID3D11ShaderResourceView **outSRV);
virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
virtual gl::Error getResource(ID3D11Resource **outResource) = 0;
virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0;
virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0;
virtual void verifyAssociatedImageValid(const gl::ImageIndex &index,
Image11 *expectedImage) = 0;
virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0;
protected:
TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags, GLenum internalFormat);
int getLevelWidth(int mipLevel) const;
int getLevelHeight(int mipLevel) const;
int getLevelDepth(int mipLevel) const;
// Some classes (e.g. TextureStorage11_2D) will override getMippedResource.
virtual gl::Error getMippedResource(ID3D11Resource **outResource) { return getResource(outResource); }
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0;
virtual gl::Error getSwizzleRenderTarget(int mipLevel,
const d3d11::RenderTargetView **outRTV) = 0;
gl::Error getSRVLevel(int mipLevel, bool blitSRV, ID3D11ShaderResourceView **outSRV);
// Get a version of a depth texture with only depth information, not stencil.
enum DropStencil
{
CREATED,
ALREADY_EXISTS
};
virtual gl::ErrorOrResult<DropStencil> ensureDropStencilTexture();
gl::Error initDropStencilTexture(const gl::ImageIndexIterator &it);
// The baseLevel parameter should *not* have mTopLevel applied.
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const = 0;
void verifySwizzleExists(const gl::SwizzleState &swizzleState);
// Clear all cached non-swizzle SRVs and invalidate the swizzle cache.
void clearSRVCache();
Renderer11 *mRenderer;
int mTopLevel;
unsigned int mMipLevels;
const d3d11::Format &mFormatInfo;
unsigned int mTextureWidth;
unsigned int mTextureHeight;
unsigned int mTextureDepth;
gl::SwizzleState mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
ID3D11Texture2D *mDropStencilTexture;
private:
const UINT mBindFlags;
const UINT mMiscFlags;
struct SRVKey
{
SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil);
bool operator<(const SRVKey &rhs) const;
int baseLevel = 0; // Without mTopLevel applied.
int mipLevels = 0;
bool swizzle = false;
bool dropStencil = false;
};
typedef std::map<SRVKey, ID3D11ShaderResourceView *> SRVCache;
gl::Error getCachedOrCreateSRV(const SRVKey &key, ID3D11ShaderResourceView **outSRV);
SRVCache mSrvCache;
std::array<ID3D11ShaderResourceView *, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> mLevelSRVs;
std::array<ID3D11ShaderResourceView *, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> mLevelBlitSRVs;
};
class TextureStorage11_2D : public TextureStorage11
{
public:
TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain);
TextureStorage11_2D(Renderer11 *renderer,
IUnknown *texture,
bool bindChroma,
unsigned int arrayIndex);
TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false);
~TextureStorage11_2D() override;
gl::Error getResource(ID3D11Resource **outResource) override;
gl::Error getMippedResource(ID3D11Resource **outResource) override;
gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
gl::Error copyToStorage(TextureStorage *destStorage) override;
void associateImage(Image11 *image, const gl::ImageIndex &index) override;
void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
protected:
gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
gl::ErrorOrResult<DropStencil> ensureDropStencilTexture() override;
gl::Error ensureTextureExists(int mipLevels);
private:
gl::Error createSRV(int baseLevel,
int mipLevels,
DXGI_FORMAT format,
ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const override;
ID3D11Texture2D *mTexture;
RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
bool mHasKeyedMutex;
// These are members related to the zero max-LOD workaround.
// D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero).
// These members are used to work around this limitation.
// Usually only mTexture XOR mLevelZeroTexture will exist.
// For example, if an app creates a texture with only one level, then 9_3 will only create mLevelZeroTexture.
// However, in some scenarios, both textures have to be created. This incurs additional memory overhead.
// One example of this is an application that creates a texture, calls glGenerateMipmap, and then disables mipmaps on the texture.
// A more likely example is an app that creates an empty texture, renders to it, and then calls glGenerateMipmap
// TODO: In this rendering scenario, release the mLevelZeroTexture after mTexture has been created to save memory.
ID3D11Texture2D *mLevelZeroTexture;
RenderTarget11 *mLevelZeroRenderTarget;
bool mUseLevelZeroTexture;
// Swizzle-related variables
ID3D11Texture2D *mSwizzleTexture;
d3d11::RenderTargetView mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
bool mBindChroma;
UINT mArrayIndex;
};
class TextureStorage11_External : public TextureStorage11
{
public:
TextureStorage11_External(Renderer11 *renderer,
egl::Stream *stream,
const egl::Stream::GLTextureDescription &glDesc);
~TextureStorage11_External() override;
gl::Error getResource(ID3D11Resource **outResource) override;
gl::Error getMippedResource(ID3D11Resource **outResource) override;
gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
gl::Error copyToStorage(TextureStorage *destStorage) override;
void associateImage(Image11 *image, const gl::ImageIndex &index) override;
void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
protected:
gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
private:
gl::Error createSRV(int baseLevel,
int mipLevels,
DXGI_FORMAT format,
ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const override;
ID3D11Texture2D *mTexture;
int mSubresourceIndex;
bool mHasKeyedMutex;
Image11 *mAssociatedImage;
};
class TextureStorage11_EGLImage final : public TextureStorage11
{
public:
TextureStorage11_EGLImage(Renderer11 *renderer,
EGLImageD3D *eglImage,
RenderTarget11 *renderTarget11);
~TextureStorage11_EGLImage() override;
gl::Error getResource(ID3D11Resource **outResource) override;
gl::Error getSRV(const gl::TextureState &textureState,
ID3D11ShaderResourceView **outSRV) override;
gl::Error getMippedResource(ID3D11Resource **outResource) override;
gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
gl::Error copyToStorage(TextureStorage *destStorage) override;
void associateImage(Image11 *image, const gl::ImageIndex &index) override;
void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
protected:
gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
private:
// Check if the EGL image's render target has been updated due to orphaning and delete
// any SRVs and other resources based on the image's old render target.
gl::Error checkForUpdatedRenderTarget();
gl::Error createSRV(int baseLevel,
int mipLevels,
DXGI_FORMAT format,
ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const override;
gl::Error getImageRenderTarget(RenderTarget11 **outRT) const;
EGLImageD3D *mImage;
uintptr_t mCurrentRenderTarget;
// Swizzle-related variables
ID3D11Texture2D *mSwizzleTexture;
std::vector<d3d11::RenderTargetView> mSwizzleRenderTargets;
};
class TextureStorage11_Cube : public TextureStorage11
{
public:
TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
~TextureStorage11_Cube() override;
UINT getSubresourceIndex(const gl::ImageIndex &index) const override;
gl::Error getResource(ID3D11Resource **outResource) override;
gl::Error getMippedResource(ID3D11Resource **outResource) override;
gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
gl::Error copyToStorage(TextureStorage *destStorage) override;
void associateImage(Image11 *image, const gl::ImageIndex &index) override;
void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override;
protected:
gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
gl::ErrorOrResult<DropStencil> ensureDropStencilTexture() override;
gl::Error ensureTextureExists(int mipLevels);
private:
gl::Error createSRV(int baseLevel,
int mipLevels,
DXGI_FORMAT format,
ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const override;
gl::Error createRenderTargetSRV(ID3D11Resource *texture,
const gl::ImageIndex &index,
DXGI_FORMAT resourceFormat,
ID3D11ShaderResourceView **srv) const;
static const size_t CUBE_FACE_COUNT = 6;
ID3D11Texture2D *mTexture;
RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
// Level-zero workaround members. See TextureStorage11_2D's workaround members for a description.
ID3D11Texture2D *mLevelZeroTexture;
RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT];
bool mUseLevelZeroTexture;
ID3D11Texture2D *mSwizzleTexture;
d3d11::RenderTargetView mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
};
class TextureStorage11_3D : public TextureStorage11
{
public:
TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
GLsizei width, GLsizei height, GLsizei depth, int levels);
~TextureStorage11_3D() override;
gl::Error getResource(ID3D11Resource **outResource) override;
// Handles both layer and non-layer RTs
gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
void associateImage(Image11 *image, const gl::ImageIndex &index) override;
void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
protected:
gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
private:
gl::Error createSRV(int baseLevel,
int mipLevels,
DXGI_FORMAT format,
ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const override;
typedef std::pair<int, int> LevelLayerKey;
typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap;
RenderTargetMap mLevelLayerRenderTargets;
RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
ID3D11Texture3D *mTexture;
ID3D11Texture3D *mSwizzleTexture;
d3d11::RenderTargetView mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
};
class TextureStorage11_2DArray : public TextureStorage11
{
public:
TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
GLsizei width, GLsizei height, GLsizei depth, int levels);
~TextureStorage11_2DArray() override;
gl::Error getResource(ID3D11Resource **outResource) override;
gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override;
void associateImage(Image11 *image, const gl::ImageIndex &index) override;
void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override;
protected:
gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override;
gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override;
gl::ErrorOrResult<DropStencil> ensureDropStencilTexture() override;
private:
gl::Error createSRV(int baseLevel,
int mipLevels,
DXGI_FORMAT format,
ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const override;
gl::Error createRenderTargetSRV(ID3D11Resource *texture,
const gl::ImageIndex &index,
DXGI_FORMAT resourceFormat,
ID3D11ShaderResourceView **srv) const;
typedef std::pair<int, int> LevelLayerKey;
typedef std::map<LevelLayerKey, RenderTarget11*> RenderTargetMap;
RenderTargetMap mRenderTargets;
ID3D11Texture2D *mTexture;
ID3D11Texture2D *mSwizzleTexture;
d3d11::RenderTargetView mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
typedef std::map<LevelLayerKey, Image11*> ImageMap;
ImageMap mAssociatedImages;
};
}
#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_