Commit 5b52afae by Shahbaz Youssefi Committed by Commit Bot

Fix texture buffer width query

If glTexBuffer is used, the width should be calculated based on the buffer size. Since ES doesn't have immutable buffers, EXT_texture_buffer allows mutable buffers to be attached to the texture. This means that updates to the buffer must update the image description. This is done by having the texture observe the attached buffer. Bug: angleproject:3573 Bug: angleproject:5334 Test: dEQP-GLES31.functional.state_query.texture_level.texture_buffer.width_* Test: TextureBufferTestES31.QueryWidthAfterBufferResize Change-Id: I7d9e5344a3d4ea70da7ba525f13b5876481a70a3 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2533495 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 617f8ca6
...@@ -24,6 +24,10 @@ namespace gl ...@@ -24,6 +24,10 @@ namespace gl
namespace namespace
{ {
constexpr angle::SubjectIndex kBufferSubjectIndex = 2;
static_assert(kBufferSubjectIndex != rx::kTextureImageImplObserverMessageIndex, "Index collision");
static_assert(kBufferSubjectIndex != rx::kTextureImageSiblingMessageIndex, "Index collision");
bool IsPointSampled(const SamplerState &samplerState) bool IsPointSampled(const SamplerState &samplerState)
{ {
return (samplerState.getMagFilter() == GL_NEAREST && return (samplerState.getMagFilter() == GL_NEAREST &&
...@@ -713,6 +717,7 @@ Texture::Texture(rx::GLImplFactory *factory, TextureID id, TextureType type) ...@@ -713,6 +717,7 @@ Texture::Texture(rx::GLImplFactory *factory, TextureID id, TextureType type)
mState(type), mState(type),
mTexture(factory->createTexture(mState)), mTexture(factory->createTexture(mState)),
mImplObserver(this, rx::kTextureImageImplObserverMessageIndex), mImplObserver(this, rx::kTextureImageImplObserverMessageIndex),
mBufferObserver(this, kBufferSubjectIndex),
mLabel(), mLabel(),
mBoundSurface(nullptr), mBoundSurface(nullptr),
mBoundStream(nullptr) mBoundStream(nullptr)
...@@ -1917,10 +1922,13 @@ angle::Result Texture::setBufferRange(const gl::Context *context, ...@@ -1917,10 +1922,13 @@ angle::Result Texture::setBufferRange(const gl::Context *context,
mState.clearImageDescs(); mState.clearImageDescs();
if (buffer == nullptr) if (buffer == nullptr)
{ {
mBufferObserver.reset();
signalDirtyStorage(InitState::MayNeedInit); signalDirtyStorage(InitState::MayNeedInit);
return angle::Result::Continue; return angle::Result::Continue;
} }
size = std::min(size, static_cast<GLsizeiptr>(buffer->getSize()));
mState.mImmutableLevels = static_cast<GLuint>(1); mState.mImmutableLevels = static_cast<GLuint>(1);
InternalFormat internalFormatInfo = GetSizedInternalFormatInfo(internalFormat); InternalFormat internalFormatInfo = GetSizedInternalFormatInfo(internalFormat);
Format format(internalFormat); Format format(internalFormat);
...@@ -1930,6 +1938,9 @@ angle::Result Texture::setBufferRange(const gl::Context *context, ...@@ -1930,6 +1938,9 @@ angle::Result Texture::setBufferRange(const gl::Context *context,
signalDirtyStorage(InitState::MayNeedInit); signalDirtyStorage(InitState::MayNeedInit);
// Observe modifications to the buffer, so that extents can be updated.
mBufferObserver.bind(buffer);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -2166,6 +2177,26 @@ void Texture::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMess ...@@ -2166,6 +2177,26 @@ void Texture::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMess
{ {
notifySiblings(message); notifySiblings(message);
} }
else if (index == kBufferSubjectIndex)
{
const gl::Buffer *buffer = mState.mBuffer.get();
ASSERT(buffer != nullptr);
// Update cached image desc based on buffer size.
GLsizeiptr size =
std::min(mState.mBuffer.getSize(), static_cast<GLsizeiptr>(buffer->getSize()));
ImageDesc desc = mState.getImageDesc(TextureTarget::Buffer, 0);
const GLuint pixelBytes = desc.format.info->pixelBytes;
desc.size.width = static_cast<GLuint>(size / pixelBytes);
mState.setImageDesc(TextureTarget::Buffer, 0, desc);
}
break;
case angle::SubjectMessage::SubjectMapped:
case angle::SubjectMessage::SubjectUnmapped:
case angle::SubjectMessage::BindingChanged:
ASSERT(index == kBufferSubjectIndex);
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
......
...@@ -638,6 +638,8 @@ class Texture final : public RefCountObject<TextureID>, ...@@ -638,6 +638,8 @@ class Texture final : public RefCountObject<TextureID>,
DirtyBits mDirtyBits; DirtyBits mDirtyBits;
rx::TextureImpl *mTexture; rx::TextureImpl *mTexture;
angle::ObserverBinding mImplObserver; angle::ObserverBinding mImplObserver;
// For EXT_texture_buffer, observes buffer changes.
angle::ObserverBinding mBufferObserver;
std::string mLabel; std::string mLabel;
......
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
// See README.md for format. // See README.md for format.
3573 : dEQP-GLES31.functional.state_query.texture_level.texture_buffer.width_* = FAIL
//// ////
//// Desktop expectations //// Desktop expectations
//// ////
......
...@@ -8584,6 +8584,44 @@ TEST_P(ETC1CompressedTextureTest, ETC1ShrinkThenGrowMaxLevels) ...@@ -8584,6 +8584,44 @@ TEST_P(ETC1CompressedTextureTest, ETC1ShrinkThenGrowMaxLevels)
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
class TextureBufferTestES31 : public ANGLETest
{
protected:
TextureBufferTestES31() {}
};
// Test that mutating a buffer attached to a texture returns correct results in query.
TEST_P(TextureBufferTestES31, QueryWidthAfterBufferResize)
{
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_buffer"));
constexpr GLint kInitialSize = 128;
constexpr std::array<GLint, 4> kModifiedSizes = {96, 192, 32, 256};
GLTexture texture;
glBindTexture(GL_TEXTURE_BUFFER, texture);
GLBuffer buffer;
glBindBuffer(GL_TEXTURE_BUFFER, buffer);
glBufferData(GL_TEXTURE_BUFFER, kInitialSize, nullptr, GL_STATIC_DRAW);
glTexBufferEXT(GL_TEXTURE_BUFFER, GL_RGBA8, buffer);
ASSERT_GL_NO_ERROR();
GLint queryResult = 0;
glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_WIDTH, &queryResult);
ASSERT_GL_NO_ERROR();
EXPECT_EQ(queryResult, kInitialSize / 4);
for (GLint modifiedSize : kModifiedSizes)
{
glBufferData(GL_TEXTURE_BUFFER, modifiedSize, nullptr, GL_STATIC_DRAW);
glGetTexLevelParameteriv(GL_TEXTURE_BUFFER, 0, GL_TEXTURE_WIDTH, &queryResult);
ASSERT_GL_NO_ERROR();
EXPECT_EQ(queryResult, modifiedSize / 4);
}
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
#define ES2_EMULATE_COPY_TEX_IMAGE() \ #define ES2_EMULATE_COPY_TEX_IMAGE() \
...@@ -8637,5 +8675,6 @@ ANGLE_INSTANTIATE_TEST_ES3(Texture3DIntegerTestES3); ...@@ -8637,5 +8675,6 @@ ANGLE_INSTANTIATE_TEST_ES3(Texture3DIntegerTestES3);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(Texture2DDepthTest); ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(Texture2DDepthTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PBOCompressedTextureTest); ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PBOCompressedTextureTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETC1CompressedTextureTest); ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETC1CompressedTextureTest);
ANGLE_INSTANTIATE_TEST_ES31(TextureBufferTestES31);
} // anonymous namespace } // anonymous namespace
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