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
...@@ -147,6 +147,11 @@ GLint TextureD3D::getBaseLevelDepth() const ...@@ -147,6 +147,11 @@ GLint TextureD3D::getBaseLevelDepth() const
return (baseImage ? baseImage->getDepth() : 0); return (baseImage ? baseImage->getDepth() : 0);
} }
bool TextureD3D::shouldForceReleaseImagesOnSetImage(const uint8_t *pixels) const
{
return mRenderer->isRobustResourceInitEnabled() && pixels == nullptr;
}
// Note: "base level image" is loosely defined to be any image from the base level, // Note: "base level image" is loosely defined to be any image from the base level,
// where in the base of 2D array textures and cube maps there are several. Don't use // where in the base of 2D array textures and cube maps there are several. Don't use
// the base level image for anything except querying texture format and size. // the base level image for anything except querying texture format and size.
...@@ -174,6 +179,11 @@ bool TextureD3D::shouldUseSetData(const ImageD3D *image) const ...@@ -174,6 +179,11 @@ bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
return false; return false;
} }
if (image->isDirty())
{
return false;
}
gl::InternalFormat internalFormat = gl::GetSizedInternalFormatInfo(image->getInternalFormat()); gl::InternalFormat internalFormat = gl::GetSizedInternalFormatInfo(image->getInternalFormat());
// We can only handle full updates for depth-stencil textures, so to avoid complications // We can only handle full updates for depth-stencil textures, so to avoid complications
...@@ -873,7 +883,7 @@ gl::Error TextureD3D_2D::setImage(const gl::Context *context, ...@@ -873,7 +883,7 @@ gl::Error TextureD3D_2D::setImage(const gl::Context *context,
GLint level = static_cast<GLint>(imageLevel); GLint level = static_cast<GLint>(imageLevel);
redefineImage(level, internalFormatInfo.sizedInternalFormat, size, redefineImage(level, internalFormatInfo.sizedInternalFormat, size,
mRenderer->isRobustResourceInitEnabled()); shouldForceReleaseImagesOnSetImage(pixels));
gl::ImageIndex index = gl::ImageIndex::Make2D(level); gl::ImageIndex index = gl::ImageIndex::Make2D(level);
...@@ -943,7 +953,7 @@ gl::Error TextureD3D_2D::setCompressedImage(const gl::Context *context, ...@@ -943,7 +953,7 @@ gl::Error TextureD3D_2D::setCompressedImage(const gl::Context *context,
GLint level = static_cast<GLint>(imageLevel); GLint level = static_cast<GLint>(imageLevel);
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
redefineImage(level, internalFormat, size, mRenderer->isRobustResourceInitEnabled()); redefineImage(level, internalFormat, size, shouldForceReleaseImagesOnSetImage(pixels));
return setCompressedImageImpl(gl::ImageIndex::Make2D(level), unpack, pixels, 0); return setCompressedImageImpl(gl::ImageIndex::Make2D(level), unpack, pixels, 0);
} }
...@@ -1469,6 +1479,7 @@ void TextureD3D_2D::redefineImage(size_t level, ...@@ -1469,6 +1479,7 @@ void TextureD3D_2D::redefineImage(size_t level,
const GLenum storageFormat = getBaseLevelInternalFormat(); const GLenum storageFormat = getBaseLevelInternalFormat();
mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, forceRelease); mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, forceRelease);
mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();
if (mTexStorage) if (mTexStorage)
{ {
...@@ -1615,7 +1626,8 @@ gl::Error TextureD3D_Cube::setImage(const gl::Context *context, ...@@ -1615,7 +1626,8 @@ gl::Error TextureD3D_Cube::setImage(const gl::Context *context,
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level)); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
redefineImage(index.layerIndex, static_cast<GLint>(level), redefineImage(index.layerIndex, static_cast<GLint>(level),
internalFormatInfo.sizedInternalFormat, size); internalFormatInfo.sizedInternalFormat, size,
shouldForceReleaseImagesOnSetImage(pixels));
return setImageImpl(index, type, unpack, pixels, 0); return setImageImpl(index, type, unpack, pixels, 0);
} }
...@@ -1649,7 +1661,8 @@ gl::Error TextureD3D_Cube::setCompressedImage(const gl::Context *context, ...@@ -1649,7 +1661,8 @@ gl::Error TextureD3D_Cube::setCompressedImage(const gl::Context *context,
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target);
redefineImage(static_cast<int>(faceIndex), static_cast<GLint>(level), internalFormat, size); redefineImage(static_cast<int>(faceIndex), static_cast<GLint>(level), internalFormat, size,
shouldForceReleaseImagesOnSetImage(pixels));
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level)); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast<GLint>(level));
return setCompressedImageImpl(index, unpack, pixels, 0); return setCompressedImageImpl(index, unpack, pixels, 0);
...@@ -1686,7 +1699,8 @@ gl::Error TextureD3D_Cube::copyImage(const gl::Context *context, ...@@ -1686,7 +1699,8 @@ gl::Error TextureD3D_Cube::copyImage(const gl::Context *context,
GLint level = static_cast<GLint>(imageLevel); GLint level = static_cast<GLint>(imageLevel);
gl::Extents size(sourceArea.width, sourceArea.height, 1); gl::Extents size(sourceArea.width, sourceArea.height, 1);
redefineImage(static_cast<int>(faceIndex), level, internalFormatInfo.sizedInternalFormat, size); redefineImage(static_cast<int>(faceIndex), level, internalFormatInfo.sizedInternalFormat, size,
mRenderer->isRobustResourceInitEnabled());
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
gl::Offset destOffset(0, 0, 0); gl::Offset destOffset(0, 0, 0);
...@@ -1777,7 +1791,7 @@ gl::Error TextureD3D_Cube::copyTexture(const gl::Context *context, ...@@ -1777,7 +1791,7 @@ gl::Error TextureD3D_Cube::copyTexture(const gl::Context *context,
const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type); const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)), gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1); static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
redefineImage(faceIndex, destLevel, internalFormatInfo.sizedInternalFormat, size); redefineImage(faceIndex, destLevel, internalFormatInfo.sizedInternalFormat, size, false);
gl::Rectangle sourceRect(0, 0, size.width, size.height); gl::Rectangle sourceRect(0, 0, size.width, size.height);
gl::Offset destOffset(0, 0, 0); gl::Offset destOffset(0, 0, 0);
...@@ -1954,7 +1968,7 @@ void TextureD3D_Cube::initMipmapImages() ...@@ -1954,7 +1968,7 @@ void TextureD3D_Cube::initMipmapImages()
int faceLevelSize = int faceLevelSize =
(std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1)); (std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1));
redefineImage(faceIndex, level, mImageArray[faceIndex][baseLevel]->getInternalFormat(), redefineImage(faceIndex, level, mImageArray[faceIndex][baseLevel]->getInternalFormat(),
gl::Extents(faceLevelSize, faceLevelSize, 1)); gl::Extents(faceLevelSize, faceLevelSize, 1), false);
} }
} }
} }
...@@ -2145,16 +2159,20 @@ gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) ...@@ -2145,16 +2159,20 @@ gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
return gl::NoError(); return gl::NoError();
} }
void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size) void TextureD3D_Cube::redefineImage(int faceIndex,
GLint level,
GLenum internalformat,
const gl::Extents &size,
bool forceRelease)
{ {
// If there currently is a corresponding storage texture image, it has these parameters // If there currently is a corresponding storage texture image, it has these parameters
const int storageWidth = std::max(1, getLevelZeroWidth() >> level); const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
const int storageHeight = std::max(1, getLevelZeroHeight() >> level); const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat(); const GLenum storageFormat = getBaseLevelInternalFormat();
bool forceRelease = mRenderer->isRobustResourceInitEnabled();
mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size, mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size,
forceRelease); forceRelease);
mDirtyImages = mDirtyImages || mImageArray[faceIndex][level]->isDirty();
if (mTexStorage) if (mTexStorage)
{ {
...@@ -2299,7 +2317,8 @@ gl::Error TextureD3D_3D::setImage(const gl::Context *context, ...@@ -2299,7 +2317,8 @@ gl::Error TextureD3D_3D::setImage(const gl::Context *context,
const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type); const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
GLint level = static_cast<GLint>(imageLevel); GLint level = static_cast<GLint>(imageLevel);
redefineImage(level, internalFormatInfo.sizedInternalFormat, size); redefineImage(level, internalFormatInfo.sizedInternalFormat, size,
shouldForceReleaseImagesOnSetImage(pixels));
bool fastUnpacked = false; bool fastUnpacked = false;
...@@ -2374,7 +2393,7 @@ gl::Error TextureD3D_3D::setCompressedImage(const gl::Context *context, ...@@ -2374,7 +2393,7 @@ gl::Error TextureD3D_3D::setCompressedImage(const gl::Context *context,
GLint level = static_cast<GLint>(imageLevel); GLint level = static_cast<GLint>(imageLevel);
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
redefineImage(level, internalFormat, size); redefineImage(level, internalFormat, size, shouldForceReleaseImagesOnSetImage(pixels));
gl::ImageIndex index = gl::ImageIndex::Make3D(level); gl::ImageIndex index = gl::ImageIndex::Make3D(level);
return setCompressedImageImpl(index, unpack, pixels, 0); return setCompressedImageImpl(index, unpack, pixels, 0);
...@@ -2506,7 +2525,7 @@ void TextureD3D_3D::initMipmapImages() ...@@ -2506,7 +2525,7 @@ void TextureD3D_3D::initMipmapImages()
gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1), gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
std::max(getLevelZeroHeight() >> level, 1), std::max(getLevelZeroHeight() >> level, 1),
std::max(getLevelZeroDepth() >> level, 1)); std::max(getLevelZeroDepth() >> level, 1));
redefineImage(level, getBaseLevelInternalFormat(), levelSize); redefineImage(level, getBaseLevelInternalFormat(), levelSize, false);
} }
} }
...@@ -2679,7 +2698,10 @@ gl::Error TextureD3D_3D::updateStorageLevel(int level) ...@@ -2679,7 +2698,10 @@ gl::Error TextureD3D_3D::updateStorageLevel(int level)
return gl::NoError(); return gl::NoError();
} }
void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) void TextureD3D_3D::redefineImage(GLint level,
GLenum internalformat,
const gl::Extents &size,
bool forceRelease)
{ {
// If there currently is a corresponding storage texture image, it has these parameters // If there currently is a corresponding storage texture image, it has these parameters
const int storageWidth = std::max(1, getLevelZeroWidth() >> level); const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
...@@ -2687,8 +2709,8 @@ void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl:: ...@@ -2687,8 +2709,8 @@ void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::
const int storageDepth = std::max(1, getLevelZeroDepth() >> level); const int storageDepth = std::max(1, getLevelZeroDepth() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat(); const GLenum storageFormat = getBaseLevelInternalFormat();
bool forceRelease = mRenderer->isRobustResourceInitEnabled();
mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, forceRelease); mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, forceRelease);
mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();
if (mTexStorage) if (mTexStorage)
{ {
...@@ -2820,7 +2842,8 @@ gl::Error TextureD3D_2DArray::setImage(const gl::Context *context, ...@@ -2820,7 +2842,8 @@ gl::Error TextureD3D_2DArray::setImage(const gl::Context *context,
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
GLint level = static_cast<GLint>(imageLevel); GLint level = static_cast<GLint>(imageLevel);
redefineImage(level, formatInfo.sizedInternalFormat, size); redefineImage(level, formatInfo.sizedInternalFormat, size,
shouldForceReleaseImagesOnSetImage(pixels));
GLsizei inputDepthPitch = 0; GLsizei inputDepthPitch = 0;
ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment, ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment,
...@@ -2883,7 +2906,7 @@ gl::Error TextureD3D_2DArray::setCompressedImage(const gl::Context *context, ...@@ -2883,7 +2906,7 @@ gl::Error TextureD3D_2DArray::setCompressedImage(const gl::Context *context,
GLint level = static_cast<GLint>(imageLevel); GLint level = static_cast<GLint>(imageLevel);
// compressed formats don't have separate sized internal formats-- we can just use the compressed format directly // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
redefineImage(level, internalFormat, size); redefineImage(level, internalFormat, size, shouldForceReleaseImagesOnSetImage(pixels));
const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat); const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
GLsizei inputDepthPitch = 0; GLsizei inputDepthPitch = 0;
...@@ -3058,7 +3081,7 @@ void TextureD3D_2DArray::initMipmapImages() ...@@ -3058,7 +3081,7 @@ void TextureD3D_2DArray::initMipmapImages()
gl::Extents levelLayerSize(std::max(baseWidth >> level, 1), gl::Extents levelLayerSize(std::max(baseWidth >> level, 1),
std::max(baseHeight >> level, 1), std::max(baseHeight >> level, 1),
baseDepth); baseDepth);
redefineImage(level, baseFormat, levelLayerSize); redefineImage(level, baseFormat, levelLayerSize, false);
} }
} }
...@@ -3246,7 +3269,10 @@ void TextureD3D_2DArray::deleteImages() ...@@ -3246,7 +3269,10 @@ void TextureD3D_2DArray::deleteImages()
} }
} }
void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) void TextureD3D_2DArray::redefineImage(GLint level,
GLenum internalformat,
const gl::Extents &size,
bool forceRelease)
{ {
// If there currently is a corresponding storage texture image, it has these parameters // If there currently is a corresponding storage texture image, it has these parameters
const int storageWidth = std::max(1, getLevelZeroWidth() >> level); const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
...@@ -3278,8 +3304,6 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const ...@@ -3278,8 +3304,6 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const
} }
} }
bool forceRelease = mRenderer->isRobustResourceInitEnabled();
if (size.depth > 0) if (size.depth > 0)
{ {
for (int layer = 0; layer < mLayerCounts[level]; layer++) for (int layer = 0; layer < mLayerCounts[level]; layer++)
...@@ -3287,6 +3311,7 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const ...@@ -3287,6 +3311,7 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const
mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalformat, mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalformat,
gl::Extents(size.width, size.height, 1), gl::Extents(size.width, size.height, 1),
forceRelease); forceRelease);
mDirtyImages = mDirtyImages || mImageArray[level][layer]->isDirty();
} }
} }
......
...@@ -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