Commit 620cb770 by Shahbaz Youssefi Committed by Commit Bot

Fix texture buffer unbind and size query

- Fixes a crash with glTexBuffer given 0 as buffer. - Fixes query of TEXTURE_BUFFER_SIZE. If glTexBuffer is used to bind a buffer, and the buffer is modified, the result of this query must adapt to the new buffer size. The spec mentions that unlike Desktop GL, ES doesn't have immutable buffers, and so they had no choice but to allow mutable buffers. Bug: angleproject:3573 Test: KHR-GLES31.core.texture_buffer.texture_buffer_parameters Test: dEQP-GLES31.functional.texture.texture_buffer.state_query.texture_buffer_size_integer Change-Id: Iec77c14ccf0e9ee11a171dbe2c7386678304bcc8 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2533494 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com>
parent 63b548b9
...@@ -2099,8 +2099,11 @@ void Context::getRenderbufferParameterivRobust(GLenum target, ...@@ -2099,8 +2099,11 @@ void Context::getRenderbufferParameterivRobust(GLenum target,
void Context::texBuffer(TextureType target, GLenum internalformat, BufferID buffer) void Context::texBuffer(TextureType target, GLenum internalformat, BufferID buffer)
{ {
ASSERT(target == TextureType::Buffer);
Texture *texture = getTextureByType(target);
Buffer *bufferObj = mState.mBufferManager->getBuffer(buffer); Buffer *bufferObj = mState.mBufferManager->getBuffer(buffer);
texBufferRange(target, internalformat, buffer, 0, clampCast<GLintptr>(bufferObj->getSize())); ANGLE_CONTEXT_TRY(texture->setBuffer(this, bufferObj, internalformat));
} }
void Context::texBufferRange(TextureType target, void Context::texBufferRange(TextureType target,
...@@ -2113,7 +2116,7 @@ void Context::texBufferRange(TextureType target, ...@@ -2113,7 +2116,7 @@ void Context::texBufferRange(TextureType target,
Texture *texture = getTextureByType(target); Texture *texture = getTextureByType(target);
Buffer *bufferObj = mState.mBufferManager->getBuffer(buffer); Buffer *bufferObj = mState.mBufferManager->getBuffer(buffer);
ANGLE_CONTEXT_TRY(texture->setBuffer(this, bufferObj, internalformat, offset, size)); ANGLE_CONTEXT_TRY(texture->setBufferRange(this, bufferObj, internalformat, offset, size));
} }
void Context::getTexParameterfv(TextureType target, GLenum pname, GLfloat *params) void Context::getTexParameterfv(TextureType target, GLenum pname, GLfloat *params)
......
...@@ -1896,16 +1896,32 @@ GLenum Texture::getGenerateMipmapHint() const ...@@ -1896,16 +1896,32 @@ GLenum Texture::getGenerateMipmapHint() const
angle::Result Texture::setBuffer(const gl::Context *context, angle::Result Texture::setBuffer(const gl::Context *context,
gl::Buffer *buffer, gl::Buffer *buffer,
GLenum internalFormat, GLenum internalFormat)
GLintptr offset, {
GLsizeiptr size) // Use UINT_MAX to indicate that the size is taken from whatever size the buffer has when the
// texture buffer is used.
return setBufferRange(context, buffer, internalFormat, 0,
std::numeric_limits<GLsizeiptr>::max());
}
angle::Result Texture::setBufferRange(const gl::Context *context,
gl::Buffer *buffer,
GLenum internalFormat,
GLintptr offset,
GLsizeiptr size)
{ {
mState.mImmutableFormat = true; mState.mImmutableFormat = true;
mState.mBuffer.set(context, buffer, offset, size); mState.mBuffer.set(context, buffer, offset, size);
ANGLE_TRY(mTexture->setBuffer(context, internalFormat)); ANGLE_TRY(mTexture->setBuffer(context, internalFormat));
mState.mImmutableLevels = static_cast<GLuint>(1);
mState.clearImageDescs(); mState.clearImageDescs();
if (buffer == nullptr)
{
signalDirtyStorage(InitState::MayNeedInit);
return angle::Result::Continue;
}
mState.mImmutableLevels = static_cast<GLuint>(1);
InternalFormat internalFormatInfo = GetSizedInternalFormatInfo(internalFormat); InternalFormat internalFormatInfo = GetSizedInternalFormatInfo(internalFormat);
Format format(internalFormat); Format format(internalFormat);
Extents extents(static_cast<GLuint>(size / internalFormatInfo.pixelBytes), 1, 1); Extents extents(static_cast<GLuint>(size / internalFormatInfo.pixelBytes), 1, 1);
......
...@@ -329,11 +329,12 @@ class Texture final : public RefCountObject<TextureID>, ...@@ -329,11 +329,12 @@ class Texture final : public RefCountObject<TextureID>,
void setBorderColor(const Context *context, const ColorGeneric &color); void setBorderColor(const Context *context, const ColorGeneric &color);
const ColorGeneric &getBorderColor() const; const ColorGeneric &getBorderColor() const;
angle::Result setBuffer(const Context *context, angle::Result setBuffer(const Context *context, gl::Buffer *buffer, GLenum internalFormat);
gl::Buffer *buffer, angle::Result setBufferRange(const Context *context,
GLenum internalFormat, gl::Buffer *buffer,
GLintptr offset, GLenum internalFormat,
GLsizeiptr size); GLintptr offset,
GLsizeiptr size);
const OffsetBindingPointer<Buffer> &getBuffer() const; const OffsetBindingPointer<Buffer> &getBuffer() const;
const TextureState &getTextureState() const; const TextureState &getTextureState() const;
......
...@@ -226,9 +226,20 @@ void QueryTexLevelParameterBase(const Texture *texture, ...@@ -226,9 +226,20 @@ void QueryTexLevelParameterBase(const Texture *texture,
pname, static_cast<GLint>(texture->getBuffer().getOffset())); pname, static_cast<GLint>(texture->getBuffer().getOffset()));
break; break;
case GL_TEXTURE_BUFFER_SIZE: case GL_TEXTURE_BUFFER_SIZE:
*params = CastFromStateValue<ParamType>( {
pname, static_cast<GLint>(texture->getBuffer().getSize())); const OffsetBindingPointer<Buffer> &bufferBinding = texture->getBuffer();
break; Buffer *buffer = bufferBinding.get();
GLsizeiptr size = bufferBinding.getSize();
const GLintptr offset = bufferBinding.getOffset();
if (buffer != nullptr)
{
size = std::min(size, static_cast<GLsizeiptr>(buffer->getSize()) - offset);
}
*params = CastFromStateValue<ParamType>(pname, static_cast<GLint>(size));
}
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
......
...@@ -1724,11 +1724,25 @@ angle::Result TextureGL::setSwizzle(const gl::Context *context, GLint swizzle[4] ...@@ -1724,11 +1724,25 @@ angle::Result TextureGL::setSwizzle(const gl::Context *context, GLint swizzle[4]
angle::Result TextureGL::setBuffer(const gl::Context *context, GLenum internalFormat) angle::Result TextureGL::setBuffer(const gl::Context *context, GLenum internalFormat)
{ {
const FunctionsGL *functions = GetFunctionsGL(context); const FunctionsGL *functions = GetFunctionsGL(context);
const BufferGL *bufferGL = GetImplAs<BufferGL>(mState.mBuffer.get()); const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding = mState.mBuffer;
ANGLE_GL_TRY(context, functions->texBufferRange( const gl::Buffer *buffer = bufferBinding.get();
GL_TEXTURE_BUFFER, internalFormat, bufferGL->getBufferID(), const GLintptr offset = bufferBinding.getOffset();
mState.mBuffer.getOffset(), mState.mBuffer.getSize())); const GLsizeiptr size = bufferBinding.getSize();
const GLuint bufferID = buffer ? GetImplAs<BufferGL>(buffer)->getBufferID() : 0;
// If buffer is not bound, use texBuffer to unbind it. If size is UINT_MAX, texBuffer was used
// to create this binding, so use the same function. This will allow the implementation to take
// the current size of the buffer on every draw/dispatch call even if the buffer size changes.
if (buffer == nullptr || size == std::numeric_limits<GLsizeiptr>::max())
{
ANGLE_GL_TRY(context, functions->texBuffer(GL_TEXTURE_BUFFER, internalFormat, bufferID));
}
else
{
ANGLE_GL_TRY(context, functions->texBufferRange(GL_TEXTURE_BUFFER, internalFormat, bufferID,
offset, size));
}
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
// 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
//// ////
......
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