Commit 48d040e8 by Geoff Lang Committed by Commit Bot

D3D11: Fix reads and writes to EGL image textures with mip offsets.

RenderTarget11 knows how to render to a specific mip of a texture but if TextureStorage11 attempts to read or write to the backing resource directly it does not select the correct subresource index. This manifested in calls to glTexSubImage going to the wrong mip of the resource. Fix TextureStorage11::getSubresourceIndex to look up the correct subresource in TextureStorage11_EGLImage. Add a test to cover this case in ImageTest.MipLevels. BUG=angleproject:2668 Change-Id: Id9270ab3bf9f37c7c671639bb8b7ce9578daaed6 Reviewed-on: https://chromium-review.googlesource.com/c/1422058Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 25839802
...@@ -360,7 +360,8 @@ angle::Result Image11::copyFromTexStorage(const gl::Context *context, ...@@ -360,7 +360,8 @@ angle::Result Image11::copyFromTexStorage(const gl::Context *context,
const TextureHelper11 *textureHelper = nullptr; const TextureHelper11 *textureHelper = nullptr;
ANGLE_TRY(storage11->getResource(context, &textureHelper)); ANGLE_TRY(storage11->getResource(context, &textureHelper));
UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex); UINT subresourceIndex = 0;
ANGLE_TRY(storage11->getSubresourceIndex(context, imageIndex, &subresourceIndex));
gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth); gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth);
return copyWithoutConversion(context, gl::Offset(), sourceBox, *textureHelper, return copyWithoutConversion(context, gl::Offset(), sourceBox, *textureHelper,
......
...@@ -2410,10 +2410,15 @@ angle::Result Renderer11::copyTexture(const gl::Context *context, ...@@ -2410,10 +2410,15 @@ angle::Result Renderer11::copyTexture(const gl::Context *context,
if (srcTarget == gl::TextureTarget::_2D || srcTarget == gl::TextureTarget::_3D) if (srcTarget == gl::TextureTarget::_2D || srcTarget == gl::TextureTarget::_3D)
{ {
gl::ImageIndex sourceIndex = gl::ImageIndex::MakeFromTarget(srcTarget, sourceLevel); gl::ImageIndex sourceIndex = gl::ImageIndex::MakeFromTarget(srcTarget, sourceLevel);
UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
UINT sourceSubresource = 0;
ANGLE_TRY(
sourceStorage11->getSubresourceIndex(context, sourceIndex, &sourceSubresource));
gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel); gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel);
UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
UINT destSubresource = 0;
ANGLE_TRY(destStorage11->getSubresourceIndex(context, destIndex, &destSubresource));
D3D11_BOX d3dBox{static_cast<UINT>(sourceBox.x), D3D11_BOX d3dBox{static_cast<UINT>(sourceBox.x),
static_cast<UINT>(sourceBox.y), static_cast<UINT>(sourceBox.y),
...@@ -2439,9 +2444,14 @@ angle::Result Renderer11::copyTexture(const gl::Context *context, ...@@ -2439,9 +2444,14 @@ angle::Result Renderer11::copyTexture(const gl::Context *context,
for (int i = 0; i < sourceBox.depth; i++) for (int i = 0; i < sourceBox.depth; i++)
{ {
gl::ImageIndex srcIndex = gl::ImageIndex::Make2DArray(sourceLevel, i + sourceBox.z); gl::ImageIndex srcIndex = gl::ImageIndex::Make2DArray(sourceLevel, i + sourceBox.z);
UINT sourceSubresource = sourceStorage11->getSubresourceIndex(srcIndex); UINT sourceSubresource = 0;
gl::ImageIndex dIndex = gl::ImageIndex::Make2DArray(destLevel, i + destOffset.z); ANGLE_TRY(
UINT destSubresource = destStorage11->getSubresourceIndex(dIndex); sourceStorage11->getSubresourceIndex(context, srcIndex, &sourceSubresource));
gl::ImageIndex dIndex = gl::ImageIndex::Make2DArray(destLevel, i + destOffset.z);
UINT destSubresource = 0;
ANGLE_TRY(destStorage11->getSubresourceIndex(context, dIndex, &destSubresource));
mDeviceContext->CopySubresourceRegion( mDeviceContext->CopySubresourceRegion(
destResource->get(), destSubresource, destOffset.x, destOffset.y, 0, destResource->get(), destSubresource, destOffset.x, destOffset.y, 0,
sourceResource->get(), sourceSubresource, &d3dBox); sourceResource->get(), sourceSubresource, &d3dBox);
...@@ -2529,7 +2539,8 @@ angle::Result Renderer11::copyCompressedTexture(const gl::Context *context, ...@@ -2529,7 +2539,8 @@ angle::Result Renderer11::copyCompressedTexture(const gl::Context *context,
ANGLE_TRY(destStorage11->getResource(context, &destResource)); ANGLE_TRY(destStorage11->getResource(context, &destResource));
gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel); gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
UINT destSubresource = destStorage11->getSubresourceIndex(destIndex); UINT destSubresource = 0;
ANGLE_TRY(destStorage11->getSubresourceIndex(context, destIndex, &destSubresource));
TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source); TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
ASSERT(sourceD3D); ASSERT(sourceD3D);
...@@ -2544,7 +2555,8 @@ angle::Result Renderer11::copyCompressedTexture(const gl::Context *context, ...@@ -2544,7 +2555,8 @@ angle::Result Renderer11::copyCompressedTexture(const gl::Context *context,
ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource)); ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel); gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex); UINT sourceSubresource = 0;
ANGLE_TRY(sourceStorage11->getSubresourceIndex(context, sourceIndex, &sourceSubresource));
mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0, mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0,
sourceResource->get(), sourceSubresource, nullptr); sourceResource->get(), sourceSubresource, nullptr);
......
...@@ -194,13 +194,16 @@ angle::Result TextureStorage11::getMippedResource(const gl::Context *context, ...@@ -194,13 +194,16 @@ angle::Result TextureStorage11::getMippedResource(const gl::Context *context,
return getResource(context, outResource); return getResource(context, outResource);
} }
UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const angle::Result TextureStorage11::getSubresourceIndex(const gl::Context *context,
const gl::ImageIndex &index,
UINT *outSubresourceIndex) const
{ {
UINT mipSlice = static_cast<UINT>(index.getLevelIndex() + mTopLevel); UINT mipSlice = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.getLayerIndex() : 0); UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.getLayerIndex() : 0);
UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
ASSERT(subresource != std::numeric_limits<UINT>::max()); ASSERT(subresource != std::numeric_limits<UINT>::max());
return subresource; *outSubresourceIndex = subresource;
return angle::Result::Continue;
} }
angle::Result TextureStorage11::getSRVForSampler(const gl::Context *context, angle::Result TextureStorage11::getSRVForSampler(const gl::Context *context,
...@@ -531,7 +534,8 @@ angle::Result TextureStorage11::updateSubresourceLevel(const gl::Context *contex ...@@ -531,7 +534,8 @@ angle::Result TextureStorage11::updateSubresourceLevel(const gl::Context *contex
ANGLE_TRY(getResource(context, &dstTexture)); ANGLE_TRY(getResource(context, &dstTexture));
} }
unsigned int dstSubresource = getSubresourceIndex(index); unsigned int dstSubresource = 0;
ANGLE_TRY(getSubresourceIndex(context, index, &dstSubresource));
ASSERT(dstTexture->valid()); ASSERT(dstTexture->valid());
...@@ -586,7 +590,8 @@ angle::Result TextureStorage11::copySubresourceLevel(const gl::Context *context, ...@@ -586,7 +590,8 @@ angle::Result TextureStorage11::copySubresourceLevel(const gl::Context *context,
ASSERT(srcTexture->valid()); ASSERT(srcTexture->valid());
unsigned int srcSubresource = getSubresourceIndex(index); unsigned int srcSubresource = 0;
ANGLE_TRY(getSubresourceIndex(context, index, &srcSubresource));
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
...@@ -713,7 +718,8 @@ angle::Result TextureStorage11::setData(const gl::Context *context, ...@@ -713,7 +718,8 @@ angle::Result TextureStorage11::setData(const gl::Context *context,
ANGLE_TRY(getResource(context, &resource)); ANGLE_TRY(getResource(context, &resource));
ASSERT(resource && resource->valid()); ASSERT(resource && resource->valid());
UINT destSubresource = getSubresourceIndex(index); UINT destSubresource = 0;
ANGLE_TRY(getSubresourceIndex(context, index, &destSubresource));
const gl::InternalFormat &internalFormatInfo = const gl::InternalFormat &internalFormatInfo =
gl::GetInternalFormatInfo(image->getInternalFormat(), type); gl::GetInternalFormatInfo(image->getInternalFormat(), type);
...@@ -824,7 +830,10 @@ angle::Result TextureStorage11::initDropStencilTexture(const gl::Context *contex ...@@ -824,7 +830,10 @@ angle::Result TextureStorage11::initDropStencilTexture(const gl::Context *contex
gl::Box wholeArea(0, 0, 0, getLevelWidth(index.getLevelIndex()), gl::Box wholeArea(0, 0, 0, getLevelWidth(index.getLevelIndex()),
getLevelHeight(index.getLevelIndex()), 1); getLevelHeight(index.getLevelIndex()), 1);
gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1); gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1);
UINT subresource = getSubresourceIndex(index);
UINT subresource = 0;
ANGLE_TRY(getSubresourceIndex(context, index, &subresource));
ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil( ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(
context, *sourceTexture, subresource, wholeArea, wholeSize, mDropStencilTexture, context, *sourceTexture, subresource, wholeArea, wholeSize, mDropStencilTexture,
subresource, wholeArea, wholeSize, nullptr)); subresource, wholeArea, wholeSize, nullptr));
...@@ -1642,6 +1651,19 @@ TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer, ...@@ -1642,6 +1651,19 @@ TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
TextureStorage11_EGLImage::~TextureStorage11_EGLImage() {} TextureStorage11_EGLImage::~TextureStorage11_EGLImage() {}
angle::Result TextureStorage11_EGLImage::getSubresourceIndex(const gl::Context *context,
const gl::ImageIndex &index,
UINT *outSubresourceIndex) const
{
ASSERT(index.getType() == gl::TextureType::_2D);
ASSERT(index.getLevelIndex() == 0);
RenderTarget11 *renderTarget11 = nullptr;
ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
*outSubresourceIndex = renderTarget11->getSubresourceIndex();
return angle::Result::Continue;
}
angle::Result TextureStorage11_EGLImage::getResource(const gl::Context *context, angle::Result TextureStorage11_EGLImage::getResource(const gl::Context *context,
const TextureHelper11 **outResource) const TextureHelper11 **outResource)
{ {
...@@ -1897,7 +1919,9 @@ angle::Result TextureStorage11_Cube::onDestroy(const gl::Context *context) ...@@ -1897,7 +1919,9 @@ angle::Result TextureStorage11_Cube::onDestroy(const gl::Context *context)
TextureStorage11_Cube::~TextureStorage11_Cube() {} TextureStorage11_Cube::~TextureStorage11_Cube() {}
UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const angle::Result TextureStorage11_Cube::getSubresourceIndex(const gl::Context *context,
const gl::ImageIndex &index,
UINT *outSubresourceIndex) const
{ {
UINT arraySlice = index.cubeMapFaceIndex(); UINT arraySlice = index.cubeMapFaceIndex();
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture &&
...@@ -1905,15 +1929,16 @@ UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) con ...@@ -1905,15 +1929,16 @@ UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) con
{ {
UINT subresource = D3D11CalcSubresource(0, arraySlice, 1); UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
ASSERT(subresource != std::numeric_limits<UINT>::max()); ASSERT(subresource != std::numeric_limits<UINT>::max());
return subresource; *outSubresourceIndex = subresource;
} }
else else
{ {
UINT mipSlice = static_cast<UINT>(index.getLevelIndex() + mTopLevel); UINT mipSlice = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
ASSERT(subresource != std::numeric_limits<UINT>::max()); ASSERT(subresource != std::numeric_limits<UINT>::max());
return subresource; *outSubresourceIndex = subresource;
} }
return angle::Result::Continue;
} }
angle::Result TextureStorage11_Cube::copyToStorage(const gl::Context *context, angle::Result TextureStorage11_Cube::copyToStorage(const gl::Context *context,
......
...@@ -103,7 +103,9 @@ class TextureStorage11 : public TextureStorage ...@@ -103,7 +103,9 @@ class TextureStorage11 : public TextureStorage
angle::Result getUAVForImage(const gl::Context *context, angle::Result getUAVForImage(const gl::Context *context,
const gl::ImageUnit &imageUnit, const gl::ImageUnit &imageUnit,
const d3d11::SharedUAV **outUAV); const d3d11::SharedUAV **outUAV);
virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; virtual angle::Result getSubresourceIndex(const gl::Context *context,
const gl::ImageIndex &index,
UINT *outSubresourceIndex) const;
virtual angle::Result getResource(const gl::Context *context, virtual angle::Result getResource(const gl::Context *context,
const TextureHelper11 **outResource) = 0; const TextureHelper11 **outResource) = 0;
virtual void associateImage(Image11 *image, const gl::ImageIndex &index) = 0; virtual void associateImage(Image11 *image, const gl::ImageIndex &index) = 0;
...@@ -419,6 +421,9 @@ class TextureStorage11_EGLImage final : public TextureStorage11ImmutableBase ...@@ -419,6 +421,9 @@ class TextureStorage11_EGLImage final : public TextureStorage11ImmutableBase
RenderTarget11 *renderTarget11); RenderTarget11 *renderTarget11);
~TextureStorage11_EGLImage() override; ~TextureStorage11_EGLImage() override;
angle::Result getSubresourceIndex(const gl::Context *context,
const gl::ImageIndex &index,
UINT *outSubresourceIndex) const override;
angle::Result getResource(const gl::Context *context, angle::Result getResource(const gl::Context *context,
const TextureHelper11 **outResource) override; const TextureHelper11 **outResource) override;
angle::Result getSRVForSampler(const gl::Context *context, angle::Result getSRVForSampler(const gl::Context *context,
...@@ -478,7 +483,9 @@ class TextureStorage11_Cube : public TextureStorage11 ...@@ -478,7 +483,9 @@ class TextureStorage11_Cube : public TextureStorage11
angle::Result onDestroy(const gl::Context *context) override; angle::Result onDestroy(const gl::Context *context) override;
UINT getSubresourceIndex(const gl::ImageIndex &index) const override; angle::Result getSubresourceIndex(const gl::Context *context,
const gl::ImageIndex &index,
UINT *outSubresourceIndex) const override;
angle::Result getResource(const gl::Context *context, angle::Result getResource(const gl::Context *context,
const TextureHelper11 **outResource) override; const TextureHelper11 **outResource) override;
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
// //
#include "test_utils/ANGLETest.h" #include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include "util/EGLWindow.h" #include "util/EGLWindow.h"
namespace angle namespace angle
...@@ -1624,9 +1625,9 @@ TEST_P(ImageTest, MipLevels) ...@@ -1624,9 +1625,9 @@ TEST_P(ImageTest, MipLevels)
const size_t mipLevels = 3; const size_t mipLevels = 3;
const size_t textureSize = 4; const size_t textureSize = 4;
std::vector<GLuint> mip0Data(textureSize * textureSize, 0xFFFF0000); std::vector<GLColor> mip0Data(textureSize * textureSize, GLColor::red);
std::vector<GLuint> mip1Data(mip0Data.size() << 1, 0xFF00FF00); std::vector<GLColor> mip1Data(mip0Data.size() << 1, GLColor::green);
std::vector<GLuint> mip2Data(mip0Data.size() << 2, 0xFF0000FF); std::vector<GLColor> mip2Data(mip0Data.size() << 2, GLColor::blue);
GLubyte *data[mipLevels] = { GLubyte *data[mipLevels] = {
reinterpret_cast<GLubyte *>(&mip0Data[0]), reinterpret_cast<GLubyte *>(&mip0Data[0]),
reinterpret_cast<GLubyte *>(&mip1Data[0]), reinterpret_cast<GLubyte *>(&mip1Data[0]),
...@@ -1674,6 +1675,36 @@ TEST_P(ImageTest, MipLevels) ...@@ -1674,6 +1675,36 @@ TEST_P(ImageTest, MipLevels)
verifyResults2D(textureTarget, data[level]); verifyResults2D(textureTarget, data[level]);
verifyResultsRenderbuffer(renderbufferTarget, data[level]); verifyResultsRenderbuffer(renderbufferTarget, data[level]);
// Update the data by uploading data to the texture
std::vector<GLuint> textureUpdateData(textureSize * textureSize, level);
glBindTexture(GL_TEXTURE_2D, textureTarget);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, textureSize >> level, textureSize >> level, GL_RGBA,
GL_UNSIGNED_BYTE, textureUpdateData.data());
ASSERT_GL_NO_ERROR();
// Expect that both the texture and renderbuffer see the updated texture data
verifyResults2D(textureTarget, reinterpret_cast<GLubyte *>(textureUpdateData.data()));
verifyResultsRenderbuffer(renderbufferTarget,
reinterpret_cast<GLubyte *>(textureUpdateData.data()));
// Update the renderbuffer by clearing it
GLFramebuffer fbo;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
renderbufferTarget);
GLubyte clearValue = static_cast<GLubyte>(level);
GLubyte renderbufferClearData[4]{clearValue, clearValue, clearValue, clearValue};
glClearColor(renderbufferClearData[0] / 255.0f, renderbufferClearData[1] / 255.0f,
renderbufferClearData[2] / 255.0f, renderbufferClearData[3] / 255.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
ASSERT_GL_NO_ERROR();
// Expect that both the texture and renderbuffer see the cleared renderbuffer data
verifyResults2D(textureTarget, renderbufferClearData);
verifyResultsRenderbuffer(renderbufferTarget, renderbufferClearData);
// Clean up // Clean up
eglDestroyImageKHR(window->getDisplay(), image); eglDestroyImageKHR(window->getDisplay(), image);
glDeleteTextures(1, &textureTarget); glDeleteTextures(1, &textureTarget);
......
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