Commit 863b6236 by Geoff Lang Committed by Commit Bot

Refactor redefineImage and track dirty images properly.

Several issues showed up in testing with WebGL: * Images should only be forcefully re-defined when there is no data to upload. * After an image is marked dirty, a later call to subImage would cause assertion failures because the texture storage would try to verify that the image was not dirty, don't try to copy directly to storage in this case. BUG=angleproject:1635 Change-Id: I9e5d83850d743b7d4d2db938312ee5c35a3a79ee Reviewed-on: https://chromium-review.googlesource.com/527348 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 982f6e01
...@@ -121,6 +121,8 @@ class TextureD3D : public TextureImpl ...@@ -121,6 +121,8 @@ class TextureD3D : public TextureImpl
GLint getBaseLevelDepth() const; GLint getBaseLevelDepth() const;
bool shouldForceReleaseImagesOnSetImage(const uint8_t *pixels) const;
RendererD3D *mRenderer; RendererD3D *mRenderer;
bool mDirtyImages; bool mDirtyImages;
...@@ -394,7 +396,11 @@ class TextureD3D_Cube : public TextureD3D ...@@ -394,7 +396,11 @@ class TextureD3D_Cube : public TextureD3D
virtual bool isImageComplete(const gl::ImageIndex &index) const; virtual bool isImageComplete(const gl::ImageIndex &index) const;
gl::Error updateStorageFaceLevel(int faceIndex, int level); gl::Error updateStorageFaceLevel(int faceIndex, int level);
void redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size); void redefineImage(int faceIndex,
GLint level,
GLenum internalformat,
const gl::Extents &size,
bool forceRelease);
ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
}; };
...@@ -497,7 +503,10 @@ class TextureD3D_3D : public TextureD3D ...@@ -497,7 +503,10 @@ class TextureD3D_3D : public TextureD3D
virtual bool isImageComplete(const gl::ImageIndex &index) const; virtual bool isImageComplete(const gl::ImageIndex &index) const;
gl::Error updateStorageLevel(int level); gl::Error updateStorageLevel(int level);
void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); void redefineImage(GLint level,
GLenum internalformat,
const gl::Extents &size,
bool forceRelease);
ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
}; };
...@@ -599,7 +608,10 @@ class TextureD3D_2DArray : public TextureD3D ...@@ -599,7 +608,10 @@ class TextureD3D_2DArray : public TextureD3D
gl::Error updateStorageLevel(int level); gl::Error updateStorageLevel(int level);
void deleteImages(); void deleteImages();
void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); void redefineImage(GLint level,
GLenum internalformat,
const gl::Extents &size,
bool forceRelease);
// Storing images as an array of single depth textures since D3D11 treats each array level of a // Storing images as an array of single depth textures since D3D11 treats each array level of a
// Texture2D object as a separate subresource. Each layer would have to be looped over // Texture2D object as a separate subresource. Each layer would have to be looped over
......
...@@ -216,8 +216,10 @@ bool Image11::isDirty() const ...@@ -216,8 +216,10 @@ bool Image11::isDirty() const
{ {
// If mDirty is true AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be // If mDirty is true AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be
// recovered from TextureStorage AND the texture doesn't require init data (i.e. a blank new // recovered from TextureStorage AND the texture doesn't require init data (i.e. a blank new
// texture will suffice) then isDirty should still return false. // texture will suffice) AND robust resource initialization is not enabled then isDirty should
if (mDirty && !mStagingTexture.valid() && !mRecoverFromStorage) // still return false.
if (mDirty && !mStagingTexture.valid() && !mRecoverFromStorage &&
!mRenderer->isRobustResourceInitEnabled())
{ {
const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps(); const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps();
const auto &formatInfo = d3d11::Format::Get(mInternalFormat, deviceCaps); const auto &formatInfo = d3d11::Format::Get(mInternalFormat, deviceCaps);
......
...@@ -364,6 +364,43 @@ TEST_P(RobustResourceInitTest, ReuploadingClearsTexture) ...@@ -364,6 +364,43 @@ TEST_P(RobustResourceInitTest, ReuploadingClearsTexture)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// Cover the case where null pixel data is uploaded to a texture and then sub image is used to
// upload partial data
TEST_P(RobustResourceInitTest, TexImageThenSubImage)
{
if (!setup())
{
return;
}
if (IsOpenGL() || IsD3D9())
{
std::cout << "Robust resource init is not yet fully implemented. (" << GetParam() << ")"
<< std::endl;
return;
}
// Put some data into the texture
GLTexture tex;
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
// Force the D3D texture to create a storage
checkNonZeroPixels(&tex, 0, 0, 0, 0, GLColor::transparentBlack);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
std::array<GLColor, kWidth * kHeight> data;
data.fill(GLColor::white);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth / 2, kHeight / 2, GL_RGBA, GL_UNSIGNED_BYTE,
data.data());
checkNonZeroPixels(&tex, 0, 0, kWidth / 2, kHeight / 2, GLColor::white);
EXPECT_GL_NO_ERROR();
}
// Reading an uninitialized texture (texImage2D) should succeed with all bytes set to 0. // Reading an uninitialized texture (texImage2D) should succeed with all bytes set to 0.
TEST_P(RobustResourceInitTest, ReadingUninitialized3DTexture) TEST_P(RobustResourceInitTest, ReadingUninitialized3DTexture)
{ {
......
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