Commit efbabde2 by Olli Etuaho Committed by Commit Bot

Support multisample array textures on D3D11

This implements complete support for multisample array textures on the D3D11 backend. There's a specialized TextureD3D class as well as a TextureStorage11 class for multisample array textures that have the bulk of the functionality. BUG=angleproject:2775 TEST=angle_end2end_tests, angle_deqp_gles31_tests Change-Id: I68116635c01cef0e48c089fd9da05a844ef2d802 Reviewed-on: https://chromium-review.googlesource.com/1216003Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 85d8ee8c
...@@ -44,6 +44,8 @@ GLint TextureTargetToLayer(TextureTarget target) ...@@ -44,6 +44,8 @@ GLint TextureTargetToLayer(TextureTarget target)
return ImageIndex::kEntireLevel; return ImageIndex::kEntireLevel;
case TextureTarget::_2DMultisample: case TextureTarget::_2DMultisample:
return ImageIndex::kEntireLevel; return ImageIndex::kEntireLevel;
case TextureTarget::_2DMultisampleArray:
return ImageIndex::kEntireLevel;
case TextureTarget::_3D: case TextureTarget::_3D:
return ImageIndex::kEntireLevel; return ImageIndex::kEntireLevel;
default: default:
...@@ -183,6 +185,11 @@ ImageIndex ImageIndex::Make2DMultisample() ...@@ -183,6 +185,11 @@ ImageIndex ImageIndex::Make2DMultisample()
return ImageIndex(TextureType::_2DMultisample, 0, kEntireLevel, 1); return ImageIndex(TextureType::_2DMultisample, 0, kEntireLevel, 1);
} }
ImageIndex ImageIndex::Make2DMultisampleArray(GLint layerIndex)
{
return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, 1);
}
bool ImageIndex::operator<(const ImageIndex &b) const bool ImageIndex::operator<(const ImageIndex &b) const
{ {
return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) < return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) <
...@@ -254,6 +261,13 @@ ImageIndexIterator ImageIndexIterator::Make2DMultisample() ...@@ -254,6 +261,13 @@ ImageIndexIterator ImageIndexIterator::Make2DMultisample()
nullptr); nullptr);
} }
ImageIndexIterator ImageIndexIterator::Make2DMultisampleArray(const GLsizei *layerCounts)
{
return ImageIndexIterator(TextureType::_2DMultisampleArray, Range<GLint>(0, 0),
Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
layerCounts);
}
ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type, ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type,
GLint minMip, GLint minMip,
GLint maxMip, GLint maxMip,
......
...@@ -55,6 +55,7 @@ class ImageIndex ...@@ -55,6 +55,7 @@ class ImageIndex
GLint layerIndex = kEntireLevel, GLint layerIndex = kEntireLevel,
GLint layerCount = 1); GLint layerCount = 1);
static ImageIndex Make2DMultisample(); static ImageIndex Make2DMultisample();
static ImageIndex Make2DMultisampleArray(GLint layerIndex = kEntireLevel);
static constexpr GLint kEntireLevel = static_cast<GLint>(-1); static constexpr GLint kEntireLevel = static_cast<GLint>(-1);
...@@ -94,6 +95,7 @@ class ImageIndexIterator ...@@ -94,6 +95,7 @@ class ImageIndexIterator
static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer); static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer);
static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts); static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts);
static ImageIndexIterator Make2DMultisample(); static ImageIndexIterator Make2DMultisample();
static ImageIndexIterator Make2DMultisampleArray(const GLsizei *layerCounts);
static ImageIndexIterator MakeGeneric(TextureType type, static ImageIndexIterator MakeGeneric(TextureType type,
GLint minMip, GLint minMip,
GLint maxMip, GLint maxMip,
......
...@@ -330,6 +330,13 @@ class RendererD3D : public BufferFactoryD3D ...@@ -330,6 +330,13 @@ class RendererD3D : public BufferFactoryD3D
int levels, int levels,
int samples, int samples,
bool fixedSampleLocations) = 0; bool fixedSampleLocations) = 0;
virtual TextureStorage *createTextureStorage2DMultisampleArray(GLenum internalformat,
GLsizei width,
GLsizei height,
GLsizei depth,
int levels,
int samples,
bool fixedSampleLocations) = 0;
// Buffer-to-texture and Texture-to-buffer copies // Buffer-to-texture and Texture-to-buffer copies
virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0;
......
...@@ -3790,4 +3790,125 @@ bool TextureD3D_2DMultisample::isImageComplete(const gl::ImageIndex &index) cons ...@@ -3790,4 +3790,125 @@ bool TextureD3D_2DMultisample::isImageComplete(const gl::ImageIndex &index) cons
return true; return true;
} }
TextureD3D_2DMultisampleArray::TextureD3D_2DMultisampleArray(const gl::TextureState &state,
RendererD3D *renderer)
: TextureD3DImmutableBase(state, renderer)
{
}
TextureD3D_2DMultisampleArray::~TextureD3D_2DMultisampleArray()
{
}
gl::Error TextureD3D_2DMultisampleArray::setStorageMultisample(const gl::Context *context,
gl::TextureType type,
GLsizei samples,
GLint internalFormat,
const gl::Extents &size,
bool fixedSampleLocations)
{
ASSERT(type == gl::TextureType::_2DMultisampleArray);
mLayerCount = size.depth;
TexStoragePointer storage(context);
storage.reset(mRenderer->createTextureStorage2DMultisampleArray(
internalFormat, size.width, size.height, size.depth, static_cast<int>(0), samples,
fixedSampleLocations));
ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
storage.release();
mImmutable = true;
return gl::NoError();
}
gl::Error TextureD3D_2DMultisampleArray::setEGLImageTarget(const gl::Context *context,
gl::TextureType type,
egl::Image *image)
{
UNREACHABLE();
return gl::InternalError();
}
gl::Error TextureD3D_2DMultisampleArray::getRenderTarget(const gl::Context *context,
const gl::ImageIndex &index,
RenderTargetD3D **outRT)
{
// ensure the underlying texture is created
ANGLE_TRY(ensureRenderTarget(context));
return mTexStorage->getRenderTarget(context, index, outRT);
}
gl::ImageIndexIterator TextureD3D_2DMultisampleArray::imageIterator() const
{
return gl::ImageIndexIterator::Make2DMultisampleArray(&mLayerCount);
}
gl::ImageIndex TextureD3D_2DMultisampleArray::getImageIndex(GLint mip, GLint layer) const
{
return gl::ImageIndex::Make2DMultisampleArray(layer);
}
bool TextureD3D_2DMultisampleArray::isValidIndex(const gl::ImageIndex &index) const
{
return (mTexStorage && index.getType() == gl::TextureType::_2DMultisampleArray &&
index.getLevelIndex() == 0);
}
GLsizei TextureD3D_2DMultisampleArray::getLayerCount(int level) const
{
return mLayerCount;
}
void TextureD3D_2DMultisampleArray::markAllImagesDirty()
{
}
angle::Result TextureD3D_2DMultisampleArray::initializeStorage(const gl::Context *context,
bool renderTarget)
{
// initializeStorage should only be called in a situation where the texture already has storage
// associated with it (storage is created in setStorageMultisample).
ASSERT(mTexStorage);
return angle::Result::Continue();
}
angle::Result TextureD3D_2DMultisampleArray::createCompleteStorage(
bool renderTarget,
TexStoragePointer *outStorage) const
{
UNREACHABLE();
outStorage->reset(mTexStorage);
return angle::Result::Continue();
}
angle::Result TextureD3D_2DMultisampleArray::setCompleteTexStorage(
const gl::Context *context,
TextureStorage *newCompleteTexStorage)
{
// These textures are immutable, so this should only be ever called once.
ASSERT(!mTexStorage);
mTexStorage = newCompleteTexStorage;
return angle::Result::Continue();
}
angle::Result TextureD3D_2DMultisampleArray::updateStorage(const gl::Context *context)
{
return angle::Result::Continue();
}
angle::Result TextureD3D_2DMultisampleArray::initMipmapImages(const gl::Context *context)
{
UNIMPLEMENTED();
return angle::Result::Continue();
}
bool TextureD3D_2DMultisampleArray::isImageComplete(const gl::ImageIndex &index) const
{
return true;
}
} // namespace rx } // namespace rx
...@@ -794,17 +794,64 @@ class TextureD3D_2DMultisample : public TextureD3DImmutableBase ...@@ -794,17 +794,64 @@ class TextureD3D_2DMultisample : public TextureD3DImmutableBase
protected: protected:
void markAllImagesDirty() override; void markAllImagesDirty() override;
angle::Result setCompleteTexStorage(const gl::Context *context,
TextureStorage *newCompleteTexStorage) override;
angle::Result updateStorage(const gl::Context *context) override;
private: private:
angle::Result initializeStorage(const gl::Context *context, bool renderTarget) override; angle::Result initializeStorage(const gl::Context *context, bool renderTarget) override;
angle::Result createCompleteStorage(bool renderTarget, angle::Result createCompleteStorage(bool renderTarget,
TexStoragePointer *outTexStorage) const override; TexStoragePointer *outTexStorage) const override;
angle::Result initMipmapImages(const gl::Context *context) override;
bool isImageComplete(const gl::ImageIndex &index) const override;
};
class TextureD3D_2DMultisampleArray : public TextureD3DImmutableBase
{
public:
TextureD3D_2DMultisampleArray(const gl::TextureState &data, RendererD3D *renderer);
~TextureD3D_2DMultisampleArray() override;
gl::Error setStorageMultisample(const gl::Context *context,
gl::TextureType type,
GLsizei samples,
GLint internalFormat,
const gl::Extents &size,
bool fixedSampleLocations) override;
gl::Error setEGLImageTarget(const gl::Context *context,
gl::TextureType type,
egl::Image *image) override;
gl::Error getRenderTarget(const gl::Context *context,
const gl::ImageIndex &index,
RenderTargetD3D **outRT) override;
gl::ImageIndexIterator imageIterator() const override;
gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
bool isValidIndex(const gl::ImageIndex &index) const override;
GLsizei getLayerCount(int level) const override;
protected:
void markAllImagesDirty() override;
angle::Result setCompleteTexStorage(const gl::Context *context, angle::Result setCompleteTexStorage(const gl::Context *context,
TextureStorage *newCompleteTexStorage) override; TextureStorage *newCompleteTexStorage) override;
angle::Result updateStorage(const gl::Context *context) override; angle::Result updateStorage(const gl::Context *context) override;
private:
angle::Result initializeStorage(const gl::Context *context, bool renderTarget) override;
angle::Result createCompleteStorage(bool renderTarget,
TexStoragePointer *outTexStorage) const override;
angle::Result initMipmapImages(const gl::Context *context) override; angle::Result initMipmapImages(const gl::Context *context) override;
bool isImageComplete(const gl::ImageIndex &index) const override; bool isImageComplete(const gl::ImageIndex &index) const override;
GLsizei mLayerCount;
}; };
} }
......
...@@ -170,10 +170,7 @@ TextureImpl *Context11::createTexture(const gl::TextureState &state) ...@@ -170,10 +170,7 @@ TextureImpl *Context11::createTexture(const gl::TextureState &state)
case gl::TextureType::_2DMultisample: case gl::TextureType::_2DMultisample:
return new TextureD3D_2DMultisample(state, mRenderer); return new TextureD3D_2DMultisample(state, mRenderer);
case gl::TextureType::_2DMultisampleArray: case gl::TextureType::_2DMultisampleArray:
// TODO(http://anglebug.com/2775): Proper implementation of D3D multisample array return new TextureD3D_2DMultisampleArray(state, mRenderer);
// textures. Right now multisample array textures are not supported but we need to
// create some object so we don't end up with asserts when using the zero texture array.
return new TextureD3D_2DMultisample(state, mRenderer);
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -3003,6 +3003,18 @@ TextureStorage *Renderer11::createTextureStorage2DMultisample(GLenum internalfor ...@@ -3003,6 +3003,18 @@ TextureStorage *Renderer11::createTextureStorage2DMultisample(GLenum internalfor
fixedSampleLocations); fixedSampleLocations);
} }
TextureStorage *Renderer11::createTextureStorage2DMultisampleArray(GLenum internalformat,
GLsizei width,
GLsizei height,
GLsizei depth,
int levels,
int samples,
bool fixedSampleLocations)
{
return new TextureStorage11_2DMultisampleArray(this, internalformat, width, height, depth,
levels, samples, fixedSampleLocations);
}
angle::Result Renderer11::readFromAttachment(const gl::Context *context, angle::Result Renderer11::readFromAttachment(const gl::Context *context,
const gl::FramebufferAttachment &srcAttachment, const gl::FramebufferAttachment &srcAttachment,
const gl::Rectangle &sourceArea, const gl::Rectangle &sourceArea,
...@@ -3495,7 +3507,8 @@ angle::Result Renderer11::resolveMultisampledTexture(const gl::Context *context, ...@@ -3495,7 +3507,8 @@ angle::Result Renderer11::resolveMultisampledTexture(const gl::Context *context,
const d3d11::SharedSRV &sourceSRV = renderTarget->getShaderResourceView(context); const d3d11::SharedSRV &sourceSRV = renderTarget->getShaderResourceView(context);
D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
sourceSRV.get()->GetDesc(&sourceSRVDesc); sourceSRV.get()->GetDesc(&sourceSRVDesc);
ASSERT(sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMS); ASSERT(sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMS ||
sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMSARRAY);
if (!mCachedResolveTexture.valid() || if (!mCachedResolveTexture.valid() ||
mCachedResolveTexture.getExtents().width != renderTarget->getWidth() || mCachedResolveTexture.getExtents().width != renderTarget->getWidth() ||
......
...@@ -297,6 +297,13 @@ class Renderer11 : public RendererD3D ...@@ -297,6 +297,13 @@ class Renderer11 : public RendererD3D
int levels, int levels,
int samples, int samples,
bool fixedSampleLocations) override; bool fixedSampleLocations) override;
TextureStorage *createTextureStorage2DMultisampleArray(GLenum internalformat,
GLsizei width,
GLsizei height,
GLsizei depth,
int levels,
int samples,
bool fixedSampleLocations) override;
VertexBuffer *createVertexBuffer() override; VertexBuffer *createVertexBuffer() override;
IndexBuffer *createIndexBuffer() override; IndexBuffer *createIndexBuffer() override;
......
...@@ -643,17 +643,6 @@ class TextureStorage11_2DArray : public TextureStorage11 ...@@ -643,17 +643,6 @@ class TextureStorage11_2DArray : public TextureStorage11
const gl::ImageIndex &index, const gl::ImageIndex &index,
Image11 *incomingImage) override; Image11 *incomingImage) override;
protected:
angle::Result getSwizzleTexture(const gl::Context *context,
const TextureHelper11 **outTexture) override;
angle::Result getSwizzleRenderTarget(const gl::Context *context,
int mipLevel,
const d3d11::RenderTargetView **outRTV) override;
angle::Result ensureDropStencilTexture(const gl::Context *context,
DropStencil *dropStencilOut) override;
private:
struct LevelLayerRangeKey struct LevelLayerRangeKey
{ {
LevelLayerRangeKey(int mipLevelIn, int layerIn, int numLayersIn) LevelLayerRangeKey(int mipLevelIn, int layerIn, int numLayersIn)
...@@ -677,6 +666,16 @@ class TextureStorage11_2DArray : public TextureStorage11 ...@@ -677,6 +666,16 @@ class TextureStorage11_2DArray : public TextureStorage11
int numLayers; int numLayers;
}; };
protected:
angle::Result getSwizzleTexture(const gl::Context *context,
const TextureHelper11 **outTexture) override;
angle::Result getSwizzleRenderTarget(const gl::Context *context,
int mipLevel,
const d3d11::RenderTargetView **outRTV) override;
angle::Result ensureDropStencilTexture(const gl::Context *context,
DropStencil *dropStencilOut) override;
private: private:
angle::Result createSRVForSampler(const gl::Context *context, angle::Result createSRVForSampler(const gl::Context *context,
int baseLevel, int baseLevel,
...@@ -759,6 +758,63 @@ class TextureStorage11_2DMultisample final : public TextureStorage11ImmutableBas ...@@ -759,6 +758,63 @@ class TextureStorage11_2DMultisample final : public TextureStorage11ImmutableBas
unsigned int mSamples; unsigned int mSamples;
GLboolean mFixedSampleLocations; GLboolean mFixedSampleLocations;
}; };
class TextureStorage11_2DMultisampleArray final : public TextureStorage11ImmutableBase
{
public:
TextureStorage11_2DMultisampleArray(Renderer11 *renderer,
GLenum internalformat,
GLsizei width,
GLsizei height,
GLsizei depth,
int levels,
int samples,
bool fixedSampleLocations);
~TextureStorage11_2DMultisampleArray() override;
angle::Result onDestroy(const gl::Context *context) override;
angle::Result getResource(const gl::Context *context,
const TextureHelper11 **outResource) override;
angle::Result getRenderTarget(const gl::Context *context,
const gl::ImageIndex &index,
RenderTargetD3D **outRT) override;
angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
protected:
angle::Result getSwizzleTexture(const gl::Context *context,
const TextureHelper11 **outTexture) override;
angle::Result getSwizzleRenderTarget(const gl::Context *context,
int mipLevel,
const d3d11::RenderTargetView **outRTV) override;
angle::Result ensureDropStencilTexture(const gl::Context *context,
DropStencil *dropStencilOut) override;
angle::Result ensureTextureExists(const gl::Context *context, int mipLevels);
private:
angle::Result createRenderTargetSRV(const gl::Context *context,
const TextureHelper11 &texture,
const gl::ImageIndex &index,
DXGI_FORMAT resourceFormat,
d3d11::SharedSRV *srv) const;
angle::Result createSRVForSampler(const gl::Context *context,
int baseLevel,
int mipLevels,
DXGI_FORMAT format,
const TextureHelper11 &texture,
d3d11::SharedSRV *outSRV) override;
TextureHelper11 mTexture;
std::map<TextureStorage11_2DArray::LevelLayerRangeKey, std::unique_ptr<RenderTarget11>>
mRenderTargets;
unsigned int mSamples;
GLboolean mFixedSampleLocations;
};
} }
#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ #endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
...@@ -1562,6 +1562,7 @@ void GenerateCaps(ID3D11Device *device, ...@@ -1562,6 +1562,7 @@ void GenerateCaps(ID3D11Device *device,
extensions->syncQuery = GetEventQuerySupport(featureLevel); extensions->syncQuery = GetEventQuerySupport(featureLevel);
extensions->copyTexture = true; extensions->copyTexture = true;
extensions->copyCompressedTexture = true; extensions->copyCompressedTexture = true;
extensions->textureStorageMultisample2DArray = true;
// D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing. // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
// D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing. // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing.
......
...@@ -2864,6 +2864,20 @@ TextureStorage *Renderer9::createTextureStorage2DMultisample(GLenum internalform ...@@ -2864,6 +2864,20 @@ TextureStorage *Renderer9::createTextureStorage2DMultisample(GLenum internalform
return nullptr; return nullptr;
} }
TextureStorage *Renderer9::createTextureStorage2DMultisampleArray(GLenum internalformat,
GLsizei width,
GLsizei height,
GLsizei depth,
int levels,
int samples,
bool fixedSampleLocations)
{
// 2D multisampled textures are not supported by the D3D9 backend.
UNREACHABLE();
return nullptr;
}
bool Renderer9::getLUID(LUID *adapterLuid) const bool Renderer9::getLUID(LUID *adapterLuid) const
{ {
adapterLuid->HighPart = 0; adapterLuid->HighPart = 0;
......
...@@ -323,6 +323,13 @@ class Renderer9 : public RendererD3D ...@@ -323,6 +323,13 @@ class Renderer9 : public RendererD3D
int levels, int levels,
int samples, int samples,
bool fixedSampleLocations) override; bool fixedSampleLocations) override;
TextureStorage *createTextureStorage2DMultisampleArray(GLenum internalformat,
GLsizei width,
GLsizei height,
GLsizei depth,
int levels,
int samples,
bool fixedSampleLocations) override;
// Buffer creation // Buffer creation
VertexBuffer *createVertexBuffer() override; VertexBuffer *createVertexBuffer() 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